Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#Folders
.gradle/*
.settings/*
.idea/*
bin/*
build/*
eclipse/*
Expand Down
138 changes: 28 additions & 110 deletions src/main/java/com/charles445/rltweaker/asm/ASMConfig.java
Original file line number Diff line number Diff line change
@@ -1,143 +1,61 @@
package com.charles445.rltweaker.asm;

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.nio.file.Path;
import java.nio.file.Paths;

//FoamFix loads these three classes... Seems to work fine?
import net.minecraftforge.common.config.ConfigCategory;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property;

public class ASMConfig
{
private static boolean setup = false;

@Nullable
private static Configuration config = null;

@Nonnull
public static Map<String, Property> configMap = new ConcurrentHashMap<>();

//Example map strings

//general.server.roguelike dungeons.ENABLED
//general.server.battle towers.Change Tower Explosion Owner

public static boolean getBoolean(String id, boolean _default)
{
if(hasConfig())
{
Property prop = getProperty(id);
if(prop == null)
{
//Warn
System.out.println("WARNING: unknown config request: "+id);
return _default;
}

return prop.getBoolean(_default);

}

return _default;
}
private final Configuration config;

@Nullable
public static Property getProperty(String s)
{
return configMap.get(s);
}

public static boolean hasConfig()
{
return configMap.size() > 0;
}

public static void setup()
{
//Run once
if(setup)
return;

setup = true;

public ASMConfig(String modName) {
System.out.println("ConfigSetup is running.");

//Look for the RLTweaker config
Path path = getConfig("rltweaker");
Path path = getConfig(modName);

//TODO the boolean here is "Case Sensitive Categories"
//Which one is appropriate?
config = new Configuration(path.toFile(), true);

processConfiguration();
}

private static void processConfiguration()
//Example map strings

//general.server.roguelike dungeons.ENABLED
//general.server.battle towers.Change Tower Explosion Owner

public boolean getBoolean(String id, boolean _default)
{
if(config != null)
Property prop = getProperty(id);
if(prop == null)
{
//System.out.println("Processing configuration");

/*
System.out.println("CATEGORIES");
for(String s : config.getCategoryNames())
{
System.out.println(s);
}
*/

//System.out.println("Populating configMap");

for(String s : config.getCategoryNames())
{
loadCategory(config.getCategory(s), s);
}

/*
System.out.println("Dumping configuration keys");

for(String s : configMap.keySet())
{
System.out.println(s);
}
*/

//Categories are all loaded
}
else
{
System.out.println("Config does not exist, patcher will assume defaults");
//Warn
// TODO: shhhh, let's not be so harsh and just assume default
System.out.println("WARNING: unknown config request: "+id);
return _default;
}

return prop.getBoolean(_default);
}

private static void loadCategory(ConfigCategory category, String header)
@Nullable
public <T> Property getProperty(String s)
{
for(Map.Entry<String, Property> entry : category.getValues().entrySet())
{
String key = header + "." + entry.getKey();
if(configMap.containsKey(key))
{
System.out.println("WARNING: Duplicate key for: "+key);
}

configMap.put(key, entry.getValue());
int i = s.lastIndexOf(Configuration.CATEGORY_SPLITTER);
if (i < 0) {
System.out.println("WARNING: malformed config key: " + s);
}

//No need to run through child categories, "getCategoryNames" already does this
//Optionally could do it manually by skipping anything with a dot in it but I really do not care at all
return this.config.getCategory(s.substring(0, i)).get(s.substring(i + 1));
}


private static Path getConfig(String modName)
{
//TODO is File.separator appropriate here?
return Paths.get("config"+File.separator+modName+".cfg").toAbsolutePath();
return Paths.get("config").resolve(modName + ".cfg").toAbsolutePath();
}
}
1 change: 0 additions & 1 deletion src/main/java/com/charles445/rltweaker/asm/CoreLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ public class CoreLoader implements IFMLLoadingPlugin
@Override
public String[] getASMTransformerClass()
{
ASMConfig.setup();
return new String[] { "com.charles445.rltweaker.asm.RLTweakerASM" };
}

Expand Down
17 changes: 17 additions & 0 deletions src/main/java/com/charles445/rltweaker/asm/Patch.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.charles445.rltweaker.asm;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Patch {

/** The path of the target class that this patch will be applied to. */
String target();

/** A short description of what this patch does (optional). */
String desc() default "";
}
69 changes: 69 additions & 0 deletions src/main/java/com/charles445/rltweaker/asm/PatchResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.charles445.rltweaker.asm;

import org.objectweb.asm.ClassWriter;

public class PatchResult {

public static PatchResult NO_MUTATION = new PatchResult(-1);
public static PatchResult NO_FLAGS = new PatchResult(0);
public static PatchResult MAXS = new PatchResult(ClassWriter.COMPUTE_MAXS);
public static PatchResult MAXS_FRAMES = new PatchResult(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
public static PatchResult FRAMES = new PatchResult(ClassWriter.COMPUTE_FRAMES);

/**
* {@link org.objectweb.asm.ClassWriter} flags
* no-mutation if negative
*/
private final int flags;

public PatchResult(int flags) {
this.flags = flags;
}

/**
* @return the {@link org.objectweb.asm.ClassWriter} flags that should be used
*/
public int getFlags() {
return Math.max(this.flags, 0);
}

/**
* @return True if the {@link org.objectweb.asm.tree.ClassNode} has been mutated
*/
public boolean isMutated() {
return this.flags >= 0;
}

public PatchResult add(PatchResult other) {
// if there is no mutation use -1, else bitwise-or the flags
return new PatchResult(this.isMutated() || other.isMutated() ?
this.getFlags() | other.getFlags() : -1);
}

@Override
public boolean equals(Object other) {
return other instanceof PatchResult &&
Math.max(-1, ((PatchResult) other).flags) == Math.max(-1, this.flags);
}

@Override
public int hashCode() {
return Integer.hashCode(Math.max(-1, this.flags));
}

@Override
public String toString() {
switch (this.getFlags()) {
case 0:
return "None";
case 1:
return "MAXS";
case 2:
return "FRAMES";
case 3:
return "MAXS | FRAMES";
default:
return "(unknown " + this.getFlags() + ")";
}
}
}
14 changes: 14 additions & 0 deletions src/main/java/com/charles445/rltweaker/asm/Patcher.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.charles445.rltweaker.asm;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Patcher {

/** The name of this set of patches (defaults to the class name). */
String name() default "";
}
Loading