Skip to content

Commit

Permalink
Refactored the ASM patch system
Browse files Browse the repository at this point in the history
Cleaned up ASMConfig
  • Loading branch information
xcube16 committed Jun 22, 2021
1 parent 0804c05 commit 2e14d86
Show file tree
Hide file tree
Showing 16 changed files with 505 additions and 614 deletions.
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

0 comments on commit 2e14d86

Please sign in to comment.