Added ASM Method and Field stripper, more work on own power net
This commit is contained in:
parent
4fae706242
commit
5b06a20351
6 changed files with 327 additions and 5 deletions
|
@ -137,6 +137,10 @@ task deobfJar(type: Jar) {
|
||||||
}
|
}
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
|
manifest {
|
||||||
|
attributes 'FMLCorePlugin': 'techreborn.asm.LoadingPlugin'
|
||||||
|
attributes 'FMLCorePluginContainsFMLMod': 'true'
|
||||||
|
}
|
||||||
exclude "**/*.psd"
|
exclude "**/*.psd"
|
||||||
appendix = 'universal'
|
appendix = 'universal'
|
||||||
classifier = 'universal'
|
classifier = 'universal'
|
||||||
|
|
179
src/main/java/techreborn/asm/ClassTransformation.java
Normal file
179
src/main/java/techreborn/asm/ClassTransformation.java
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
package techreborn.asm;
|
||||||
|
|
||||||
|
import cpw.mods.fml.common.Loader;
|
||||||
|
import cpw.mods.fml.common.ModAPIManager;
|
||||||
|
import cpw.mods.fml.common.ModContainer;
|
||||||
|
import cpw.mods.fml.common.discovery.ASMDataTable;
|
||||||
|
import cpw.mods.fml.common.versioning.InvalidVersionSpecificationException;
|
||||||
|
import cpw.mods.fml.common.versioning.VersionRange;
|
||||||
|
import net.minecraft.launchwrapper.IClassTransformer;
|
||||||
|
import org.objectweb.asm.ClassReader;
|
||||||
|
import org.objectweb.asm.ClassWriter;
|
||||||
|
import org.objectweb.asm.Type;
|
||||||
|
import org.objectweb.asm.tree.AnnotationNode;
|
||||||
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
|
import org.objectweb.asm.tree.FieldNode;
|
||||||
|
import org.objectweb.asm.tree.MethodNode;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class ClassTransformation implements IClassTransformer {
|
||||||
|
|
||||||
|
private static boolean scrappedData = false;
|
||||||
|
static String strippableDesc;
|
||||||
|
private static final String[] emptyList = {};
|
||||||
|
|
||||||
|
public ClassTransformation() {
|
||||||
|
strippableDesc = Type.getDescriptor(Strippable.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] transform(String name, String transformedName, byte[] bytes) {
|
||||||
|
|
||||||
|
if (bytes == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassReader cr = new ClassReader(bytes);
|
||||||
|
ClassNode cn = new ClassNode();
|
||||||
|
cr.accept(cn, 0);
|
||||||
|
if (strip(cn)) {
|
||||||
|
ClassWriter cw = new ClassWriter(0);
|
||||||
|
cn.accept(cw);
|
||||||
|
bytes = cw.toByteArray();
|
||||||
|
System.out.println("Striped " + name);
|
||||||
|
} else {
|
||||||
|
//LogHelper.trace("Nothing stripped from " + transformedName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean strip(ClassNode cn) {
|
||||||
|
boolean altered = false;
|
||||||
|
if (cn.visibleAnnotations != null) {
|
||||||
|
for (AnnotationNode n : cn.visibleAnnotations) {
|
||||||
|
AnnotationInfo node = parseAnnotation(n, strippableDesc);
|
||||||
|
if(node != null){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cn.methods != null) {
|
||||||
|
Iterator<MethodNode> iter = cn.methods.iterator();
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
MethodNode mn = iter.next();
|
||||||
|
if (mn.visibleAnnotations != null) {
|
||||||
|
for (AnnotationNode node : mn.visibleAnnotations) {
|
||||||
|
if (checkRemove(parseAnnotation(node, strippableDesc), iter)) {
|
||||||
|
altered = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cn.fields != null) {
|
||||||
|
Iterator<FieldNode> iter = cn.fields.iterator();
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
FieldNode fn = iter.next();
|
||||||
|
if (fn.visibleAnnotations != null) {
|
||||||
|
for (AnnotationNode node : fn.visibleAnnotations) {
|
||||||
|
if (checkRemove(parseAnnotation(node, strippableDesc), iter)) {
|
||||||
|
altered = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return altered;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static AnnotationInfo parseAnnotation(AnnotationNode node, String desc) {
|
||||||
|
|
||||||
|
AnnotationInfo info = null;
|
||||||
|
if (node.desc.equals(desc)) {
|
||||||
|
info = new AnnotationInfo();
|
||||||
|
if (node.values != null) {
|
||||||
|
List<Object> values = node.values;
|
||||||
|
for (int i = 0, e = values.size(); i < e; ) {
|
||||||
|
Object k = values.get(i++);
|
||||||
|
Object v = values.get(i++);
|
||||||
|
if ("value".equals(k)) {
|
||||||
|
if (!(v instanceof List && ((List<?>) v).size() > 0 && ((List<?>) v).get(0) instanceof String)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
info.values = ((List<?>) v).toArray(emptyList);
|
||||||
|
} else if ("side".equals(k) && v instanceof String[]) {
|
||||||
|
String t = ((String[]) v)[1];
|
||||||
|
if (t != null) {
|
||||||
|
info.side = t.toUpperCase().intern();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean checkRemove(AnnotationInfo node, Iterator<? extends Object> iter) {
|
||||||
|
|
||||||
|
if (node != null) {
|
||||||
|
boolean needsRemoved = true;
|
||||||
|
if (!needsRemoved) {
|
||||||
|
String[] value = node.values;
|
||||||
|
for (int j = 0, l = value.length; j < l; ++j) {
|
||||||
|
String clazz = value[j];
|
||||||
|
String mod = clazz.substring(4);
|
||||||
|
if (clazz.startsWith("mod:")) {
|
||||||
|
int i = mod.indexOf('@');
|
||||||
|
if (i > 0) {
|
||||||
|
clazz = mod.substring(i + 1);
|
||||||
|
mod = mod.substring(0, i);
|
||||||
|
}
|
||||||
|
needsRemoved = !Loader.isModLoaded(mod);
|
||||||
|
if (!needsRemoved && i > 0) {
|
||||||
|
ModContainer modc = getLoadedMods().get(mod);
|
||||||
|
try {
|
||||||
|
needsRemoved = !VersionRange.createFromVersionSpec(clazz).containsVersion(modc.getProcessedVersion());
|
||||||
|
} catch (InvalidVersionSpecificationException e) {
|
||||||
|
needsRemoved = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (needsRemoved) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (needsRemoved) {
|
||||||
|
iter.remove();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class AnnotationInfo {
|
||||||
|
|
||||||
|
public String side = "NONE";
|
||||||
|
public String[] values = emptyList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, ModContainer> mods;
|
||||||
|
static Map<String, ModContainer> getLoadedMods() {
|
||||||
|
|
||||||
|
if (mods == null) {
|
||||||
|
mods = new HashMap<String, ModContainer>();
|
||||||
|
for (ModContainer m : Loader.instance().getModList()) {
|
||||||
|
mods.put(m.getModId(), m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mods;
|
||||||
|
}
|
||||||
|
}
|
82
src/main/java/techreborn/asm/LoadingPlugin.java
Normal file
82
src/main/java/techreborn/asm/LoadingPlugin.java
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
package techreborn.asm;
|
||||||
|
|
||||||
|
import com.google.common.eventbus.EventBus;
|
||||||
|
import com.google.common.eventbus.Subscribe;
|
||||||
|
import cpw.mods.fml.common.DummyModContainer;
|
||||||
|
import cpw.mods.fml.common.LoadController;
|
||||||
|
import cpw.mods.fml.common.ModMetadata;
|
||||||
|
import cpw.mods.fml.common.discovery.ASMDataTable;
|
||||||
|
import cpw.mods.fml.common.event.FMLConstructionEvent;
|
||||||
|
import cpw.mods.fml.relauncher.IFMLCallHook;
|
||||||
|
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
|
||||||
|
import techreborn.lib.ModInfo;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@IFMLLoadingPlugin.MCVersion( "1.7.10" )
|
||||||
|
public class LoadingPlugin implements IFMLLoadingPlugin {
|
||||||
|
|
||||||
|
public static ASMDataTable ASM_DATA = null;
|
||||||
|
public static boolean runtimeDeobfEnabled = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getASMTransformerClass() {
|
||||||
|
return new String[]{"techreborn.asm.ClassTransformation"};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getModContainerClass() {
|
||||||
|
return DummyMod.class.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSetupClass() {
|
||||||
|
return DummyMod.class.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void injectData(Map<String, Object> data) {
|
||||||
|
runtimeDeobfEnabled = (Boolean) data.get("runtimeDeobfuscationEnabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAccessTransformerClass() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DummyMod extends DummyModContainer implements IFMLCallHook {
|
||||||
|
|
||||||
|
public DummyMod() {
|
||||||
|
|
||||||
|
super(new ModMetadata());
|
||||||
|
ModMetadata md = getMetadata();
|
||||||
|
md.autogenerated = true;
|
||||||
|
md.modId = ModInfo.MOD_ID + "asm";
|
||||||
|
md.name = md.description = "Techreborn-Stripper";
|
||||||
|
md.parent = ModInfo.MOD_ID;
|
||||||
|
md.version = "000";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean registerBus(EventBus bus, LoadController controller) {
|
||||||
|
|
||||||
|
bus.register(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void construction(FMLConstructionEvent evt) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void call() throws Exception {
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void injectData(Map<String, Object> data) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
src/main/java/techreborn/asm/Strippable.java
Normal file
23
src/main/java/techreborn/asm/Strippable.java
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
package techreborn.asm;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When used on a class, methods from referenced interfaces will not be removed <br>
|
||||||
|
* When using this annotation on methods, ensure you do not switch on an enum inside that method. JavaC implementation details means this will cause crashes.
|
||||||
|
* <p/>
|
||||||
|
* Can also strip on modid using "mod:CoFHCore" as a value <br>
|
||||||
|
* Can also strip on API using "api:CoFHAPI|energy" as a value
|
||||||
|
*/
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.TYPE})
|
||||||
|
public @interface Strippable {
|
||||||
|
|
||||||
|
public String[] value();
|
||||||
|
|
||||||
|
}
|
|
@ -2,17 +2,50 @@ package techreborn.powerSystem;
|
||||||
|
|
||||||
import cofh.api.energy.IEnergyReceiver;
|
import cofh.api.energy.IEnergyReceiver;
|
||||||
import cpw.mods.fml.common.Optional;
|
import cpw.mods.fml.common.Optional;
|
||||||
|
import ic2.api.energy.prefab.BasicSink;
|
||||||
|
import ic2.api.energy.tile.IEnergySink;
|
||||||
import ic2.api.energy.tile.IEnergyTile;
|
import ic2.api.energy.tile.IEnergyTile;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import techreborn.api.power.IEnergyInterfaceTile;
|
import techreborn.api.power.IEnergyInterfaceTile;
|
||||||
|
import techreborn.asm.Strippable;
|
||||||
|
import techreborn.tiles.TileMachineBase;
|
||||||
|
|
||||||
|
|
||||||
@Optional.Interface(iface="ic2.api.energy.tile.IEnergyTile", modid="IC2", striprefs=true)
|
@Optional.InterfaceList(value={
|
||||||
public abstract class TilePowerAcceptor implements IEnergyReceiver, IEnergyInterfaceTile, IEnergyTile {
|
@Optional.Interface(iface="ic2.api.energy.tile.IEnergyTile", modid="IC2", striprefs=true),
|
||||||
|
@Optional.Interface(iface="ic2.api.energy.tile.IEnergySink", modid="IC2", striprefs=true)
|
||||||
|
})
|
||||||
|
public abstract class TilePowerAcceptor extends TileMachineBase implements
|
||||||
|
IEnergyReceiver, //Techreborn
|
||||||
|
IEnergyInterfaceTile,//Cofh
|
||||||
|
IEnergyTile, IEnergySink //Ic2
|
||||||
|
{
|
||||||
|
|
||||||
|
@Strippable("mod:ic2")
|
||||||
|
BasicSink sink;
|
||||||
|
|
||||||
|
@Strippable("mod:ic2")
|
||||||
|
@Override
|
||||||
|
public void updateEntity()
|
||||||
|
{
|
||||||
|
super.updateEntity();
|
||||||
|
sink.updateEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Strippable("mod:ic2")
|
||||||
|
@Override
|
||||||
|
public void invalidate()
|
||||||
|
{
|
||||||
|
sink.invalidate();
|
||||||
|
super.invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Strippable("mod:ic2")
|
||||||
|
@Override
|
||||||
|
public void onChunkUnload()
|
||||||
|
{
|
||||||
|
sink.onChunkUnload();
|
||||||
|
super.onChunkUnload();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
import net.minecraftforge.common.util.ForgeDirection;
|
import net.minecraftforge.common.util.ForgeDirection;
|
||||||
import techreborn.api.recipe.RecipeCrafter;
|
import techreborn.api.recipe.RecipeCrafter;
|
||||||
|
import techreborn.asm.Strippable;
|
||||||
import techreborn.init.ModBlocks;
|
import techreborn.init.ModBlocks;
|
||||||
import techreborn.util.Inventory;
|
import techreborn.util.Inventory;
|
||||||
|
|
||||||
|
@ -33,7 +34,7 @@ public class TileLathe extends TileMachineBase implements IWrenchable, IEnergyTi
|
||||||
outputs[0] = 1;
|
outputs[0] = 1;
|
||||||
crafter = new RecipeCrafter("latheRecipe", this, energy, 1, 1, inventory, inputs, outputs);
|
crafter = new RecipeCrafter("latheRecipe", this, energy, 1, 1, inventory, inputs, outputs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateEntity()
|
public void updateEntity()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue