Commit fba0e0ffc742dfd2c78a379dcdc7097c3cef12a2

Authored by Mumfrey
1 parent 0ec79e75

adding AccessorTransformer and replacing MinecraftOverlay with accessor injection

debug/obfuscation.properties
1 field_71424_I=mcProfiler 1 field_71424_I=mcProfiler
2 -field_78729_o=entityRenderMap field_110546_b=reloadListeners 2 +field_78729_o=entityRenderMap
  3 +field_110546_b=reloadListeners
3 field_147393_d=networkManager 4 field_147393_d=networkManager
4 -field_82596_a=registryObjects field_148759_a=underlyingIntegerMap field_148749_a=identityMap  
5 -field_148748_b=objectList field_147559_m=mapSpecialRenderers 5 +field_82596_a=registryObjects
  6 +field_148759_a=underlyingIntegerMap
  7 +field_148749_a=identityMap
  8 +field_148748_b=objectList
  9 +field_147559_m=mapSpecialRenderers
6 field_145855_i=nameToClassMap 10 field_145855_i=nameToClassMap
7 -field_145853_j=classToNameMap func_148833_a=processPacket func_71411_J=runGameLoop func_71407_l=runTick func_78480_b=updateCameraAndRender  
8 -func_78471_a=renderWorld func_175180_a=renderGameOverlay func_76320_a=startSection 11 +field_145853_j=classToNameMap
  12 +field_71428_T=timer
  13 +field_71424_I=mcProfiler
  14 +field_71425_J=running
  15 +field_110449_ao=defaultResourcePacks
  16 +field_71475_ae=serverName
  17 +field_71477_af=serverPort
  18 +func_148833_a=processPacket
  19 +func_71411_J=runGameLoop
  20 +func_71407_l=runTick
  21 +func_78480_b=updateCameraAndRender
  22 +func_78471_a=renderWorld
  23 +func_175180_a=renderGameOverlay
  24 +func_76320_a=startSection
9 func_76319_b=endSection 25 func_76319_b=endSection
10 func_76318_c=endStartSection 26 func_76318_c=endStartSection
11 func_148545_a=createPlayerForUser 27 func_148545_a=createPlayerForUser
@@ -28,4 +44,5 @@ func_148256_e=getProfile @@ -28,4 +44,5 @@ func_148256_e=getProfile
28 func_148260_a=saveScreenshot 44 func_148260_a=saveScreenshot
29 func_148822_b=isFramebufferEnabled 45 func_148822_b=isFramebufferEnabled
30 func_147939_a=doRenderEntity 46 func_147939_a=doRenderEntity
31 -func_76986_a=doRender  
32 \ No newline at end of file 47 \ No newline at end of file
  48 +func_76986_a=doRender
  49 +func_71370_a=resize
33 \ No newline at end of file 50 \ No newline at end of file
java/client/com/mumfrey/liteloader/client/api/LiteLoaderCoreAPIClient.java
@@ -35,7 +35,7 @@ public class LiteLoaderCoreAPIClient extends LiteLoaderCoreAPI @@ -35,7 +35,7 @@ public class LiteLoaderCoreAPIClient extends LiteLoaderCoreAPI
35 private static final String[] requiredDownstreamTransformers = { 35 private static final String[] requiredDownstreamTransformers = {
36 LiteLoaderCoreAPI.PKG_LITELOADER_COMMON + ".transformers.LiteLoaderPacketTransformer", 36 LiteLoaderCoreAPI.PKG_LITELOADER_COMMON + ".transformers.LiteLoaderPacketTransformer",
37 LiteLoaderCoreAPIClient.PKG_LITELOADER_CLIENT + ".transformers.LiteLoaderEventInjectionTransformer", 37 LiteLoaderCoreAPIClient.PKG_LITELOADER_CLIENT + ".transformers.LiteLoaderEventInjectionTransformer",
38 - LiteLoaderCoreAPIClient.PKG_LITELOADER_CLIENT + ".transformers.MinecraftOverlayTransformer", 38 + LiteLoaderCoreAPIClient.PKG_LITELOADER_CLIENT + ".transformers.MinecraftTransformer",
39 LiteLoaderCoreAPI.PKG_LITELOADER + ".transformers.event.json.ModEventInjectionTransformer" 39 LiteLoaderCoreAPI.PKG_LITELOADER + ".transformers.event.json.ModEventInjectionTransformer"
40 }; 40 };
41 41
java/client/com/mumfrey/liteloader/client/overlays/IMinecraft.java
@@ -5,43 +5,56 @@ import java.util.List; @@ -5,43 +5,56 @@ import java.util.List;
5 import net.minecraft.client.resources.IResourcePack; 5 import net.minecraft.client.resources.IResourcePack;
6 import net.minecraft.util.Timer; 6 import net.minecraft.util.Timer;
7 7
  8 +import com.mumfrey.liteloader.core.runtime.Obf;
  9 +import com.mumfrey.liteloader.transformers.access.Accessor;
  10 +import com.mumfrey.liteloader.transformers.access.Invoker;
  11 +import com.mumfrey.liteloader.transformers.access.ObfTableClass;
  12 +
8 /** 13 /**
9 - * Interface containing injected accessors which are provided by MinecraftOverlay 14 + * Interface containing injected accessors for Minecraft
10 * 15 *
11 * @author Adam Mummery-Smith 16 * @author Adam Mummery-Smith
12 */ 17 */
  18 +@ObfTableClass(Obf.class)
  19 +@Accessor("Minecraft")
13 public interface IMinecraft 20 public interface IMinecraft
14 { 21 {
15 /** 22 /**
16 * Get the timer instance 23 * Get the timer instance
17 */ 24 */
  25 + @Accessor("timer")
18 public abstract Timer getTimer(); 26 public abstract Timer getTimer();
19 27
20 /** 28 /**
21 * Get the "running" flag 29 * Get the "running" flag
22 */ 30 */
  31 + @Accessor("running")
23 public abstract boolean isRunning(); 32 public abstract boolean isRunning();
24 33
25 /** 34 /**
26 * Get the default resource packs set 35 * Get the default resource packs set
27 */ 36 */
  37 + @Accessor("defaultResourcePacks")
28 public abstract List<IResourcePack> getDefaultResourcePacks(); 38 public abstract List<IResourcePack> getDefaultResourcePacks();
29 -  
30 - /**  
31 - * Resize the window  
32 - *  
33 - * @param width  
34 - * @param height  
35 - */  
36 - public abstract void setSize(int width, int height);  
37 39
38 /** 40 /**
39 * Get the current server address (from connection) 41 * Get the current server address (from connection)
40 */ 42 */
  43 + @Accessor("serverName")
41 public abstract String getServerName(); 44 public abstract String getServerName();
42 45
43 /** 46 /**
44 * Get the current server port (from connection) 47 * Get the current server port (from connection)
45 */ 48 */
  49 + @Accessor("serverPort")
46 public abstract int getServerPort(); 50 public abstract int getServerPort();
  51 +
  52 + /**
  53 + * Notify the client that the window was resized
  54 + *
  55 + * @param width
  56 + * @param height
  57 + */
  58 + @Invoker("resize")
  59 + public abstract void onResizeWindow(int width, int height);
47 } 60 }
java/client/com/mumfrey/liteloader/client/overlays/MinecraftOverlay.java deleted 100644 โ†’ 0
1 -package com.mumfrey.liteloader.client.overlays;  
2 -  
3 -import java.util.List;  
4 -  
5 -import org.lwjgl.LWJGLException;  
6 -import org.lwjgl.opengl.Display;  
7 -import org.lwjgl.opengl.DisplayMode;  
8 -  
9 -import net.minecraft.client.Minecraft;  
10 -import net.minecraft.client.resources.IResourcePack;  
11 -import net.minecraft.profiler.Profiler;  
12 -import net.minecraft.util.Timer;  
13 -  
14 -import com.google.common.collect.Lists;  
15 -import com.mumfrey.liteloader.transformers.Obfuscated;  
16 -import com.mumfrey.liteloader.transformers.Stub;  
17 -  
18 -/**  
19 - * Overlay to inject accessors into Minecraft main class  
20 - *  
21 - * @author Adam Mummery-Smith  
22 - */  
23 -public abstract class MinecraftOverlay implements IMinecraft  
24 -{  
25 - @SuppressWarnings("unused")  
26 - private static Minecraft __TARGET;  
27 -  
28 - // TODO Obfuscation 1.8  
29 - // Fields  
30 - @Obfuscated({"field_71428_T", "U"}) private Timer timer;  
31 - @Obfuscated({"field_71424_I", "y"}) private Profiler mcProfiler;  
32 - @Obfuscated({"field_71425_J", "z"}) private boolean running;  
33 - @Obfuscated({"field_110449_ao", "aw"}) private List<?> defaultResourcePacks = Lists.newArrayList();  
34 - @Obfuscated({"field_71475_ae", "am"}) private String serverName;  
35 - @Obfuscated({"field_71477_af", "an"}) private int serverPort;  
36 -  
37 - // Methods  
38 - @Obfuscated({"func_71370_a", "a"}) @Stub abstract void resize(int width, int height);  
39 -  
40 - /* (non-Javadoc)  
41 - * @see com.mumfrey.liteloader.client.overlays.IMinecraft#getTimer()  
42 - */  
43 - @Override  
44 - public Timer getTimer()  
45 - {  
46 - return this.timer;  
47 - }  
48 -  
49 - /* (non-Javadoc)  
50 - * @see com.mumfrey.liteloader.client.overlays.IMinecraft#isRunning()  
51 - */  
52 - @Override  
53 - public boolean isRunning()  
54 - {  
55 - return this.running;  
56 - }  
57 -  
58 - /* (non-Javadoc)  
59 - * @see com.mumfrey.liteloader.client.overlays.IMinecraft#getDefaultResourcePacks()  
60 - */  
61 - @Override  
62 - @SuppressWarnings("unchecked")  
63 - public List<IResourcePack> getDefaultResourcePacks()  
64 - {  
65 - return (List<IResourcePack>)this.defaultResourcePacks;  
66 - }  
67 -  
68 - /* (non-Javadoc)  
69 - * @see com.mumfrey.liteloader.client.overlays.IMinecraft#setSize(int, int)  
70 - */  
71 - @Override  
72 - public void setSize(int width, int height)  
73 - {  
74 - try  
75 - {  
76 - Display.setDisplayMode(new DisplayMode(width, height));  
77 - this.resize(width, height);  
78 - Display.setVSyncEnabled(Minecraft.getMinecraft().gameSettings.enableVsync);  
79 - }  
80 - catch (LWJGLException ex)  
81 - {  
82 - ex.printStackTrace();  
83 - }  
84 - }  
85 -  
86 - /* (non-Javadoc)  
87 - * @see com.mumfrey.liteloader.client.overlays.IMinecraft#getServerName()  
88 - */  
89 - @Override  
90 - public String getServerName()  
91 - {  
92 - return this.serverName;  
93 - }  
94 -  
95 - /* (non-Javadoc)  
96 - * @see com.mumfrey.liteloader.client.overlays.IMinecraft#getServerPort()  
97 - */  
98 - @Override  
99 - public int getServerPort()  
100 - {  
101 - return this.serverPort;  
102 - }  
103 -}  
java/client/com/mumfrey/liteloader/client/transformers/MinecraftOverlayTransformer.java renamed to java/client/com/mumfrey/liteloader/client/transformers/MinecraftTransformer.java
@@ -13,30 +13,25 @@ import org.objectweb.asm.tree.TypeInsnNode; @@ -13,30 +13,25 @@ import org.objectweb.asm.tree.TypeInsnNode;
13 13
14 import com.mumfrey.liteloader.core.runtime.Obf; 14 import com.mumfrey.liteloader.core.runtime.Obf;
15 import com.mumfrey.liteloader.launch.LiteLoaderTweaker; 15 import com.mumfrey.liteloader.launch.LiteLoaderTweaker;
16 -import com.mumfrey.liteloader.transformers.ClassOverlayTransformer; 16 +import com.mumfrey.liteloader.transformers.access.AccessorTransformer;
17 import com.mumfrey.liteloader.util.log.LiteLoaderLogger; 17 import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
18 18
19 -public class MinecraftOverlayTransformer extends ClassOverlayTransformer 19 +public class MinecraftTransformer extends AccessorTransformer
20 { 20 {
21 - private static final String overlayClassName = "com.mumfrey.liteloader.client.overlays.MinecraftOverlay"; 21 + private static final String TWEAKCLASS = LiteLoaderTweaker.class.getName().replace('.', '/');
22 22
23 - private static final String LITELOADER_TWEAKER_CLASS = LiteLoaderTweaker.class.getName().replace('.', '/');  
24 -  
25 - private static final String METHOD_INIT = "init";  
26 - private static final String METHOD_POSTINIT = "postInit";  
27 -  
28 - public MinecraftOverlayTransformer() 23 + @Override
  24 + protected void addAccessors()
29 { 25 {
30 - super(MinecraftOverlayTransformer.overlayClassName);  
31 - this.setSourceFile = false; 26 + this.addAccessor(Obf.IMinecraft.name);
32 } 27 }
33 28
34 @Override 29 @Override
35 - protected void postOverlayTransform(String transformedName, ClassNode targetClass, ClassNode overlayClass) 30 + protected void postTransform(String name, String transformedName, ClassNode classNode)
36 { 31 {
37 if ((Obf.Minecraft.name.equals(transformedName) || Obf.Minecraft.obf.equals(transformedName))) 32 if ((Obf.Minecraft.name.equals(transformedName) || Obf.Minecraft.obf.equals(transformedName)))
38 { 33 {
39 - for (MethodNode method : targetClass.methods) 34 + for (MethodNode method : classNode.methods)
40 { 35 {
41 if (Obf.startGame.obf.equals(method.name) || Obf.startGame.srg.equals(method.name) || Obf.startGame.name.equals(method.name)) 36 if (Obf.startGame.obf.equals(method.name) || Obf.startGame.srg.equals(method.name) || Obf.startGame.name.equals(method.name))
42 { 37 {
@@ -63,11 +58,11 @@ public class MinecraftOverlayTransformer extends ClassOverlayTransformer @@ -63,11 +58,11 @@ public class MinecraftOverlayTransformer extends ClassOverlayTransformer
63 TypeInsnNode typeNode = (TypeInsnNode)insn; 58 TypeInsnNode typeNode = (TypeInsnNode)insn;
64 if (!found && (Obf.EntityRenderer.obf.equals(typeNode.desc) || Obf.EntityRenderer.ref.equals(typeNode.desc))) 59 if (!found && (Obf.EntityRenderer.obf.equals(typeNode.desc) || Obf.EntityRenderer.ref.equals(typeNode.desc)))
65 { 60 {
66 - LiteLoaderLogger.info("MinecraftOverlayTransformer found INIT injection point, this is good."); 61 + LiteLoaderLogger.info("MinecraftTransformer found INIT injection point, this is good.");
67 found = true; 62 found = true;
68 63
69 - insns.add(new MethodInsnNode(Opcodes.INVOKESTATIC, MinecraftOverlayTransformer.LITELOADER_TWEAKER_CLASS, MinecraftOverlayTransformer.METHOD_INIT, "()V", false));  
70 - insns.add(new MethodInsnNode(Opcodes.INVOKESTATIC, MinecraftOverlayTransformer.LITELOADER_TWEAKER_CLASS, MinecraftOverlayTransformer.METHOD_POSTINIT, "()V", false)); 64 + insns.add(new MethodInsnNode(Opcodes.INVOKESTATIC, MinecraftTransformer.TWEAKCLASS, Obf.init.name, "()V", false));
  65 + insns.add(new MethodInsnNode(Opcodes.INVOKESTATIC, MinecraftTransformer.TWEAKCLASS, Obf.postInit.name, "()V", false));
71 } 66 }
72 } 67 }
73 68
@@ -88,6 +83,6 @@ public class MinecraftOverlayTransformer extends ClassOverlayTransformer @@ -88,6 +83,6 @@ public class MinecraftOverlayTransformer extends ClassOverlayTransformer
88 83
89 method.instructions = insns; 84 method.instructions = insns;
90 85
91 - if (!found) LiteLoaderLogger.severe("MinecraftOverlayTransformer failed to find the INIT injection point, the game will probably crash pretty soon."); 86 + if (!found) LiteLoaderLogger.severe("MinecraftTransformer failed to find the INIT injection point, the game will probably crash pretty soon.");
92 } 87 }
93 } 88 }
java/client/com/mumfrey/liteloader/util/ModUtilities.java
@@ -6,6 +6,10 @@ import java.util.IdentityHashMap; @@ -6,6 +6,10 @@ import java.util.IdentityHashMap;
6 import java.util.List; 6 import java.util.List;
7 import java.util.Map; 7 import java.util.Map;
8 8
  9 +import org.lwjgl.LWJGLException;
  10 +import org.lwjgl.opengl.Display;
  11 +import org.lwjgl.opengl.DisplayMode;
  12 +
9 import net.minecraft.block.Block; 13 import net.minecraft.block.Block;
10 import net.minecraft.client.Minecraft; 14 import net.minecraft.client.Minecraft;
11 import net.minecraft.client.renderer.Tessellator; 15 import net.minecraft.client.renderer.Tessellator;
@@ -25,6 +29,7 @@ import net.minecraft.util.RegistryNamespaced; @@ -25,6 +29,7 @@ import net.minecraft.util.RegistryNamespaced;
25 import net.minecraft.util.RegistrySimple; 29 import net.minecraft.util.RegistrySimple;
26 import net.minecraft.util.ResourceLocation; 30 import net.minecraft.util.ResourceLocation;
27 31
  32 +import com.mumfrey.liteloader.client.overlays.IMinecraft;
28 import com.mumfrey.liteloader.client.util.PrivateFields; 33 import com.mumfrey.liteloader.client.util.PrivateFields;
29 import com.mumfrey.liteloader.core.runtime.Obf; 34 import com.mumfrey.liteloader.core.runtime.Obf;
30 import com.mumfrey.liteloader.util.log.LiteLoaderLogger; 35 import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
@@ -74,6 +79,21 @@ public abstract class ModUtilities @@ -74,6 +79,21 @@ public abstract class ModUtilities
74 return false; 79 return false;
75 } 80 }
76 81
  82 + public static void setWindowSize(int width, int height)
  83 + {
  84 + try
  85 + {
  86 + Minecraft mc = Minecraft.getMinecraft();
  87 + Display.setDisplayMode(new DisplayMode(width, height));
  88 + ((IMinecraft)mc).onResizeWindow(width, height);
  89 + Display.setVSyncEnabled(mc.gameSettings.enableVsync);
  90 + }
  91 + catch (LWJGLException ex)
  92 + {
  93 + ex.printStackTrace();
  94 + }
  95 + }
  96 +
77 /** 97 /**
78 * Add a renderer map entry for the specified entity class 98 * Add a renderer map entry for the specified entity class
79 * 99 *
java/common/com/mumfrey/liteloader/core/runtime/Obf.java
@@ -25,11 +25,14 @@ public class Obf @@ -25,11 +25,14 @@ public class Obf
25 public static final Obf PacketEvents = new Obf("com.mumfrey.liteloader.core.PacketEvents" ); 25 public static final Obf PacketEvents = new Obf("com.mumfrey.liteloader.core.PacketEvents" );
26 public static final Obf PacketEventsClient = new Obf("com.mumfrey.liteloader.client.PacketEventsClient" ); 26 public static final Obf PacketEventsClient = new Obf("com.mumfrey.liteloader.client.PacketEventsClient" );
27 public static final Obf LoadingBar = new Obf("com.mumfrey.liteloader.client.gui.startup.LoadingBar" ); 27 public static final Obf LoadingBar = new Obf("com.mumfrey.liteloader.client.gui.startup.LoadingBar" );
  28 + public static final Obf IMinecraft = new Obf("com.mumfrey.liteloader.client.overlays.IMinecraft" );
28 public static final Obf GameProfile = new Obf("com.mojang.authlib.GameProfile" ); 29 public static final Obf GameProfile = new Obf("com.mojang.authlib.GameProfile" );
29 public static final Obf MinecraftMain = new Obf("net.minecraft.client.main.Main" ); 30 public static final Obf MinecraftMain = new Obf("net.minecraft.client.main.Main" );
30 public static final Obf MinecraftServer = new Obf("net.minecraft.server.MinecraftServer" ); 31 public static final Obf MinecraftServer = new Obf("net.minecraft.server.MinecraftServer" );
31 public static final Obf GL11 = new Obf("org.lwjgl.opengl.GL11" ); 32 public static final Obf GL11 = new Obf("org.lwjgl.opengl.GL11" );
32 public static final Obf RealmsMainScreen = new Obf("com.mojang.realmsclient.RealmsMainScreen" ); 33 public static final Obf RealmsMainScreen = new Obf("com.mojang.realmsclient.RealmsMainScreen" );
  34 + public static final Obf init = new Obf("init" );
  35 + public static final Obf postInit = new Obf("postInit" );
33 public static final Obf constructor = new Obf("<init>" ); 36 public static final Obf constructor = new Obf("<init>" );
34 37
35 // Classes 38 // Classes
@@ -73,6 +76,12 @@ public class Obf @@ -73,6 +76,12 @@ public class Obf
73 public static final Obf mapSpecialRenderers = new Obf("field_147559_m", "m" ); 76 public static final Obf mapSpecialRenderers = new Obf("field_147559_m", "m" );
74 public static final Obf tileEntityNameToClassMap = new Obf("field_145855_i", "f" ); 77 public static final Obf tileEntityNameToClassMap = new Obf("field_145855_i", "f" );
75 public static final Obf tileEntityClassToNameMap = new Obf("field_145853_j", "g" ); 78 public static final Obf tileEntityClassToNameMap = new Obf("field_145853_j", "g" );
  79 + public static final Obf timer = new Obf("field_71428_T", "U" );
  80 + public static final Obf mcProfiler = new Obf("field_71424_I", "y" );
  81 + public static final Obf running = new Obf("field_71425_J", "z" );
  82 + public static final Obf defaultResourcePacks = new Obf("field_110449_ao", "aw" );
  83 + public static final Obf serverName = new Obf("field_71475_ae", "am" );
  84 + public static final Obf serverPort = new Obf("field_71477_af", "an" );
76 85
77 // Methods 86 // Methods
78 // ----------------------------------------------------------------------------------------- 87 // -----------------------------------------------------------------------------------------
@@ -107,6 +116,7 @@ public class Obf @@ -107,6 +116,7 @@ public class Obf
107 public static final Obf doRenderEntity = new Obf("func_147939_a", "a" ); 116 public static final Obf doRenderEntity = new Obf("func_147939_a", "a" );
108 public static final Obf doRender = new Obf("func_76986_a", "a" ); 117 public static final Obf doRender = new Obf("func_76986_a", "a" );
109 public static final Obf doRenderShadowAndFire = new Obf("func_76979_b", "b" ); 118 public static final Obf doRenderShadowAndFire = new Obf("func_76979_b", "b" );
  119 + public static final Obf resize = new Obf("func_71370_a", "a" );
110 120
111 public static final int MCP = 0; 121 public static final int MCP = 0;
112 public static final int SRG = 1; 122 public static final int SRG = 1;
@@ -239,4 +249,24 @@ public class Obf @@ -239,4 +249,24 @@ public class Obf
239 { 249 {
240 return Obf.obfs.get(name); 250 return Obf.obfs.get(name);
241 } 251 }
  252 +
  253 + public static Obf getByName(Class<? extends Obf> obf, String name)
  254 + {
  255 + try
  256 + {
  257 + for (Field fd : obf.getFields())
  258 + {
  259 + if (fd.getType().equals(Obf.class))
  260 + {
  261 + String fieldName = fd.getName();
  262 + Obf entry = (Obf)fd.get(null);
  263 + if (name.equals(fieldName) || name.equals(entry.name))
  264 + return entry;
  265 + }
  266 + }
  267 + }
  268 + catch (Exception ex) {}
  269 +
  270 + return Obf.getByName(name);
  271 + }
242 } 272 }
java/common/com/mumfrey/liteloader/transformers/ByteCodeUtilities.java
1 package com.mumfrey.liteloader.transformers; 1 package com.mumfrey.liteloader.transformers;
2 2
  3 +import java.io.IOException;
3 import java.lang.annotation.Annotation; 4 import java.lang.annotation.Annotation;
4 import java.util.ArrayList; 5 import java.util.ArrayList;
5 import java.util.HashMap; 6 import java.util.HashMap;
@@ -7,6 +8,10 @@ import java.util.Iterator; @@ -7,6 +8,10 @@ import java.util.Iterator;
7 import java.util.List; 8 import java.util.List;
8 import java.util.Map; 9 import java.util.Map;
9 10
  11 +import net.minecraft.launchwrapper.IClassTransformer;
  12 +import net.minecraft.launchwrapper.Launch;
  13 +
  14 +import org.objectweb.asm.ClassReader;
10 import org.objectweb.asm.Opcodes; 15 import org.objectweb.asm.Opcodes;
11 import org.objectweb.asm.Type; 16 import org.objectweb.asm.Type;
12 import org.objectweb.asm.tree.*; 17 import org.objectweb.asm.tree.*;
@@ -476,7 +481,7 @@ public abstract class ByteCodeUtilities @@ -476,7 +481,7 @@ public abstract class ByteCodeUtilities
476 return target; 481 return target;
477 } 482 }
478 483
479 - AnnotationNode obfuscatedAnnotation = ByteCodeUtilities.getAnnotation(searchFor, Obfuscated.class); 484 + AnnotationNode obfuscatedAnnotation = ByteCodeUtilities.getVisibleAnnotation(searchFor, Obfuscated.class);
480 if (obfuscatedAnnotation != null) 485 if (obfuscatedAnnotation != null)
481 { 486 {
482 for (String obfuscatedName : ByteCodeUtilities.<List<String>>getAnnotationValue(obfuscatedAnnotation)) 487 for (String obfuscatedName : ByteCodeUtilities.<List<String>>getAnnotationValue(obfuscatedAnnotation))
@@ -506,7 +511,7 @@ public abstract class ByteCodeUtilities @@ -506,7 +511,7 @@ public abstract class ByteCodeUtilities
506 return target; 511 return target;
507 } 512 }
508 513
509 - AnnotationNode obfuscatedAnnotation = ByteCodeUtilities.getAnnotation(searchFor, Obfuscated.class); 514 + AnnotationNode obfuscatedAnnotation = ByteCodeUtilities.getVisibleAnnotation(searchFor, Obfuscated.class);
510 if (obfuscatedAnnotation != null) 515 if (obfuscatedAnnotation != null)
511 { 516 {
512 for (String obfuscatedName : ByteCodeUtilities.<List<String>>getAnnotationValue(obfuscatedAnnotation)) 517 for (String obfuscatedName : ByteCodeUtilities.<List<String>>getAnnotationValue(obfuscatedAnnotation))
@@ -521,24 +526,111 @@ public abstract class ByteCodeUtilities @@ -521,24 +526,111 @@ public abstract class ByteCodeUtilities
521 526
522 return null; 527 return null;
523 } 528 }
  529 +
  530 + public static ClassNode loadClass(String className) throws IOException
  531 + {
  532 + return ByteCodeUtilities.loadClass(className, true, null);
  533 + }
  534 +
  535 + public static ClassNode loadClass(String className, boolean runTransformers) throws IOException
  536 + {
  537 + return ByteCodeUtilities.loadClass(className, runTransformers, null);
  538 + }
  539 +
  540 + public static ClassNode loadClass(String className, IClassTransformer source) throws IOException
  541 + {
  542 + return ByteCodeUtilities.loadClass(className, source != null, source);
  543 + }
  544 +
  545 + public static ClassNode loadClass(String className, boolean runTransformers, IClassTransformer source) throws IOException
  546 + {
  547 + byte[] bytes = Launch.classLoader.getClassBytes(className);
  548 +
  549 + if (runTransformers)
  550 + {
  551 + bytes = ByteCodeUtilities.applyTransformers(className, bytes, source);
  552 + }
  553 +
  554 + return ByteCodeUtilities.readClass(bytes);
  555 + }
  556 +
  557 + public static ClassNode readClass(byte[] basicClass)
  558 + {
  559 + ClassReader classReader = new ClassReader(basicClass);
  560 + ClassNode classNode = new ClassNode();
  561 + classReader.accept(classNode, ClassReader.EXPAND_FRAMES);
  562 + return classNode;
  563 + }
  564 +
  565 + public static byte[] applyTransformers(String className, byte[] basicClass)
  566 + {
  567 + return ByteCodeUtilities.applyTransformers(className, basicClass, null);
  568 + }
  569 +
  570 + public static byte[] applyTransformers(String className, byte[] basicClass, IClassTransformer source)
  571 + {
  572 + final List<IClassTransformer> transformers = Launch.classLoader.getTransformers();
  573 +
  574 + for (final IClassTransformer transformer : transformers)
  575 + {
  576 + if (transformer != source)
  577 + {
  578 + basicClass = transformer.transform(className, className, basicClass);
  579 + }
  580 + }
  581 +
  582 + return basicClass;
  583 + }
524 584
525 /** 585 /**
526 * Get an annotation of the specified class from the supplied field node 586 * Get an annotation of the specified class from the supplied field node
527 */ 587 */
528 - public static AnnotationNode getAnnotation(FieldNode field, Class<? extends Annotation> annotationClass) 588 + public static AnnotationNode getVisibleAnnotation(FieldNode field, Class<? extends Annotation> annotationClass)
529 { 589 {
530 return ByteCodeUtilities.getAnnotation(field.visibleAnnotations, Type.getDescriptor(annotationClass)); 590 return ByteCodeUtilities.getAnnotation(field.visibleAnnotations, Type.getDescriptor(annotationClass));
531 } 591 }
  592 +
  593 + /**
  594 + * Get an annotation of the specified class from the supplied field node
  595 + */
  596 + public static AnnotationNode getInvisibleAnnotation(FieldNode field, Class<? extends Annotation> annotationClass)
  597 + {
  598 + return ByteCodeUtilities.getAnnotation(field.invisibleAnnotations, Type.getDescriptor(annotationClass));
  599 + }
532 600
533 /** 601 /**
534 * Get an annotation of the specified class from the supplied method node 602 * Get an annotation of the specified class from the supplied method node
535 */ 603 */
536 - public static AnnotationNode getAnnotation(MethodNode method, Class<? extends Annotation> annotationClass) 604 + public static AnnotationNode getVisibleAnnotation(MethodNode method, Class<? extends Annotation> annotationClass)
537 { 605 {
538 return ByteCodeUtilities.getAnnotation(method.visibleAnnotations, Type.getDescriptor(annotationClass)); 606 return ByteCodeUtilities.getAnnotation(method.visibleAnnotations, Type.getDescriptor(annotationClass));
539 } 607 }
  608 +
  609 + /**
  610 + * Get an annotation of the specified class from the supplied method node
  611 + */
  612 + public static AnnotationNode getInvisibleAnnotation(MethodNode method, Class<? extends Annotation> annotationClass)
  613 + {
  614 + return ByteCodeUtilities.getAnnotation(method.invisibleAnnotations, Type.getDescriptor(annotationClass));
  615 + }
540 616
541 /** 617 /**
  618 + * Get an annotation of the specified class from the supplied class node
  619 + */
  620 + public static AnnotationNode getVisibleAnnotation(ClassNode classNode, Class<? extends Annotation> annotationClass)
  621 + {
  622 + return ByteCodeUtilities.getAnnotation(classNode.visibleAnnotations, Type.getDescriptor(annotationClass));
  623 + }
  624 +
  625 + /**
  626 + * Get an annotation of the specified class from the supplied class node
  627 + */
  628 + public static AnnotationNode getInvisibleAnnotation(ClassNode classNode, Class<? extends Annotation> annotationClass)
  629 + {
  630 + return ByteCodeUtilities.getAnnotation(classNode.invisibleAnnotations, Type.getDescriptor(annotationClass));
  631 + }
  632 +
  633 + /**
542 * Get an annotation of the specified class from the supplied list of annotations, returns null if no matching annotation was found 634 * Get an annotation of the specified class from the supplied list of annotations, returns null if no matching annotation was found
543 */ 635 */
544 public static AnnotationNode getAnnotation(List<AnnotationNode> annotations, String annotationType) 636 public static AnnotationNode getAnnotation(List<AnnotationNode> annotations, String annotationType)
@@ -574,6 +666,9 @@ public abstract class ByteCodeUtilities @@ -574,6 +666,9 @@ public abstract class ByteCodeUtilities
574 @SuppressWarnings("unchecked") 666 @SuppressWarnings("unchecked")
575 public static <T> T getAnnotationValue(AnnotationNode annotation, String key) 667 public static <T> T getAnnotationValue(AnnotationNode annotation, String key)
576 { 668 {
  669 + if (annotation == null || annotation.values == null)
  670 + return null;
  671 +
577 boolean getNextValue = false; 672 boolean getNextValue = false;
578 for (Object value : annotation.values) 673 for (Object value : annotation.values)
579 { 674 {
java/common/com/mumfrey/liteloader/transformers/ClassOverlayTransformer.java
@@ -8,7 +8,6 @@ import java.util.List; @@ -8,7 +8,6 @@ import java.util.List;
8 import java.util.Map; 8 import java.util.Map;
9 import java.util.Set; 9 import java.util.Set;
10 10
11 -import net.minecraft.launchwrapper.IClassTransformer;  
12 import net.minecraft.launchwrapper.Launch; 11 import net.minecraft.launchwrapper.Launch;
13 12
14 import org.objectweb.asm.ClassReader; 13 import org.objectweb.asm.ClassReader;
@@ -314,7 +313,7 @@ public abstract class ClassOverlayTransformer extends ClassTransformer @@ -314,7 +313,7 @@ public abstract class ClassOverlayTransformer extends ClassTransformer
314 { 313 {
315 for (MethodNode overlayMethod : overlayClass.methods) 314 for (MethodNode overlayMethod : overlayClass.methods)
316 { 315 {
317 - if (ByteCodeUtilities.getAnnotation(overlayMethod, Stub.class) != null || (ByteCodeUtilities.getAnnotation(overlayMethod, AppendInsns.class) == null && !overlayMethod.name.startsWith("<"))) 316 + if (ByteCodeUtilities.getVisibleAnnotation(overlayMethod, Stub.class) != null || (ByteCodeUtilities.getVisibleAnnotation(overlayMethod, AppendInsns.class) == null && !overlayMethod.name.startsWith("<")))
318 { 317 {
319 this.checkRenameMethod(targetClass, overlayMethod); 318 this.checkRenameMethod(targetClass, overlayMethod);
320 } 319 }
@@ -333,8 +332,8 @@ public abstract class ClassOverlayTransformer extends ClassTransformer @@ -333,8 +332,8 @@ public abstract class ClassOverlayTransformer extends ClassTransformer
333 { 332 {
334 this.transformMethod(overlayMethod, overlayClass.name, targetClass.name); 333 this.transformMethod(overlayMethod, overlayClass.name, targetClass.name);
335 334
336 - AnnotationNode appendAnnotation = ByteCodeUtilities.getAnnotation(overlayMethod, AppendInsns.class);  
337 - AnnotationNode stubAnnotation = ByteCodeUtilities.getAnnotation(overlayMethod, Stub.class); 335 + AnnotationNode appendAnnotation = ByteCodeUtilities.getVisibleAnnotation(overlayMethod, AppendInsns.class);
  336 + AnnotationNode stubAnnotation = ByteCodeUtilities.getVisibleAnnotation(overlayMethod, Stub.class);
338 337
339 if (stubAnnotation != null) 338 if (stubAnnotation != null)
340 { 339 {
@@ -428,7 +427,7 @@ public abstract class ClassOverlayTransformer extends ClassTransformer @@ -428,7 +427,7 @@ public abstract class ClassOverlayTransformer extends ClassTransformer
428 if (targetMethodName == null || targetMethodName.length() == 0) targetMethodName = sourceMethod.name; 427 if (targetMethodName == null || targetMethodName.length() == 0) targetMethodName = sourceMethod.name;
429 428
430 Set<String> obfuscatedNames = new HashSet<String>(); 429 Set<String> obfuscatedNames = new HashSet<String>();
431 - AnnotationNode obfuscatedAnnotation = ByteCodeUtilities.getAnnotation(sourceMethod, Obfuscated.class); 430 + AnnotationNode obfuscatedAnnotation = ByteCodeUtilities.getVisibleAnnotation(sourceMethod, Obfuscated.class);
432 if (obfuscatedAnnotation != null) 431 if (obfuscatedAnnotation != null)
433 { 432 {
434 obfuscatedNames.addAll(ByteCodeUtilities.<List<String>>getAnnotationValue(obfuscatedAnnotation)); 433 obfuscatedNames.addAll(ByteCodeUtilities.<List<String>>getAnnotationValue(obfuscatedAnnotation));
@@ -495,7 +494,7 @@ public abstract class ClassOverlayTransformer extends ClassTransformer @@ -495,7 +494,7 @@ public abstract class ClassOverlayTransformer extends ClassTransformer
495 494
496 if (runTransformers) 495 if (runTransformers)
497 { 496 {
498 - overlayBytes = this.applyTransformers(this.overlayClassName, overlayBytes); 497 + overlayBytes = ByteCodeUtilities.applyTransformers(this.overlayClassName, overlayBytes, this);
499 } 498 }
500 } 499 }
501 catch (IOException ex) 500 catch (IOException ex)
@@ -506,25 +505,4 @@ public abstract class ClassOverlayTransformer extends ClassTransformer @@ -506,25 +505,4 @@ public abstract class ClassOverlayTransformer extends ClassTransformer
506 505
507 return this.readClass(overlayBytes, false); 506 return this.readClass(overlayBytes, false);
508 } 507 }
509 -  
510 - /**  
511 - * Since we obtain the overlay class bytes with getClassBytes(), we need to apply the transformers ourself  
512 - *  
513 - * @param name  
514 - * @param basicClass  
515 - */  
516 - private byte[] applyTransformers(String name, byte[] basicClass)  
517 - {  
518 - final List<IClassTransformer> transformers = Launch.classLoader.getTransformers();  
519 -  
520 - for (final IClassTransformer transformer : transformers)  
521 - {  
522 - if (transformer != this)  
523 - {  
524 - basicClass = transformer.transform(name, name, basicClass);  
525 - }  
526 - }  
527 -  
528 - return basicClass;  
529 - }  
530 } 508 }
java/common/com/mumfrey/liteloader/transformers/access/Accessor.java 0 โ†’ 100644
  1 +package com.mumfrey.liteloader.transformers.access;
  2 +
  3 +import java.lang.annotation.ElementType;
  4 +import java.lang.annotation.Retention;
  5 +import java.lang.annotation.RetentionPolicy;
  6 +import java.lang.annotation.Target;
  7 +
  8 +/**
  9 + * Defines an accessor method within an accessor injection interface, or an accessor interface itself
  10 + *
  11 + * @author Adam Mummery-Smith
  12 + */
  13 +@Target({ElementType.METHOD, ElementType.TYPE})
  14 +@Retention(RetentionPolicy.CLASS)
  15 +public @interface Accessor
  16 +{
  17 + public String value();
  18 +}
java/common/com/mumfrey/liteloader/transformers/access/AccessorTransformer.java 0 โ†’ 100644
  1 +package com.mumfrey.liteloader.transformers.access;
  2 +
  3 +import java.io.IOException;
  4 +import java.util.ArrayList;
  5 +import java.util.Iterator;
  6 +import java.util.List;
  7 +
  8 +import net.minecraft.launchwrapper.Launch;
  9 +
  10 +import org.objectweb.asm.ClassReader;
  11 +import org.objectweb.asm.Opcodes;
  12 +import org.objectweb.asm.Type;
  13 +import org.objectweb.asm.tree.AnnotationNode;
  14 +import org.objectweb.asm.tree.ClassNode;
  15 +import org.objectweb.asm.tree.FieldInsnNode;
  16 +import org.objectweb.asm.tree.FieldNode;
  17 +import org.objectweb.asm.tree.InsnNode;
  18 +import org.objectweb.asm.tree.MethodInsnNode;
  19 +import org.objectweb.asm.tree.MethodNode;
  20 +import org.objectweb.asm.tree.VarInsnNode;
  21 +
  22 +import com.mumfrey.liteloader.core.runtime.Obf;
  23 +import com.mumfrey.liteloader.transformers.ByteCodeUtilities;
  24 +import com.mumfrey.liteloader.transformers.ClassTransformer;
  25 +import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
  26 +
  27 +/**
  28 + * Transformer which can inject accessor methods into a target class
  29 + *
  30 + * @author Adam Mummery-Smith
  31 + */
  32 +public abstract class AccessorTransformer extends ClassTransformer
  33 +{
  34 + /**
  35 + * An injection record
  36 + *
  37 + * @author Adam Mummery-Smith
  38 + */
  39 + class AccessorInjection
  40 + {
  41 + /**
  42 + * Full name of the interface to inject
  43 + */
  44 + private final String iface;
  45 +
  46 + /**
  47 + * Obfuscation table class specified by the interface
  48 + */
  49 + private final Class<? extends Obf> table;
  50 +
  51 + /**
  52 + * Target class to inject into
  53 + */
  54 + private final Obf target;
  55 +
  56 + protected AccessorInjection(String iface) throws IOException
  57 + {
  58 + ClassNode ifaceNode = this.loadClass(iface);
  59 + this.table = this.setupTable(ifaceNode);
  60 + this.target = this.setupTarget(ifaceNode);
  61 + this.iface = iface;
  62 + }
  63 +
  64 + private ClassNode loadClass(String iface) throws IOException
  65 + {
  66 + byte[] bytes = this.getClassBytes(iface);
  67 + ClassReader classReader = new ClassReader(bytes);
  68 + ClassNode classNode = new ClassNode();
  69 + classReader.accept(classNode, 0);
  70 + return classNode;
  71 + }
  72 +
  73 + private byte[] getClassBytes(String iface) throws IOException
  74 + {
  75 + return Launch.classLoader.getClassBytes(iface);
  76 + }
  77 +
  78 + private Obf getObf(String name)
  79 + {
  80 + return Obf.getByName(this.table, name);
  81 + }
  82 +
  83 + protected Obf getTarget()
  84 + {
  85 + return this.target;
  86 + }
  87 +
  88 + @SuppressWarnings("unchecked")
  89 + private Class<? extends Obf> setupTable(ClassNode ifaceNode)
  90 + {
  91 + AnnotationNode annotation = ByteCodeUtilities.getInvisibleAnnotation(ifaceNode, ObfTableClass.class);
  92 + if (annotation != null)
  93 + {
  94 + try
  95 + {
  96 + Type obfTableType = ByteCodeUtilities.getAnnotationValue(annotation);
  97 + return (Class<? extends Obf>)Class.forName(obfTableType.getClassName(), true, Launch.classLoader);
  98 + }
  99 + catch (ClassNotFoundException ex)
  100 + {
  101 + ex.printStackTrace();
  102 + }
  103 + }
  104 +
  105 + return Obf.class;
  106 + }
  107 +
  108 + private Obf setupTarget(ClassNode ifaceNode)
  109 + {
  110 + AnnotationNode annotation = ByteCodeUtilities.getInvisibleAnnotation(ifaceNode, Accessor.class);
  111 + return this.getObf(ByteCodeUtilities.<String>getAnnotationValue(annotation));
  112 + }
  113 +
  114 + protected void apply(ClassNode classNode)
  115 + {
  116 + String ifaceRef = this.iface.replace('.', '/');
  117 +
  118 + if (classNode.interfaces.contains(ifaceRef))
  119 + {
  120 + LiteLoaderLogger.debug("[AccessorTransformer] Skipping %s because %s was already applied", classNode.name, this.iface);
  121 + return;
  122 + }
  123 +
  124 + classNode.interfaces.add(ifaceRef);
  125 +
  126 + try
  127 + {
  128 + LiteLoaderLogger.debug("[AccessorTransformer] Loading %s", this.iface);
  129 + ClassNode ifaceNode = ByteCodeUtilities.loadClass(this.iface, AccessorTransformer.this);
  130 +
  131 + for (MethodNode method : ifaceNode.methods)
  132 + {
  133 + this.addMethod(classNode, method);
  134 + }
  135 + }
  136 + catch (Exception ex)
  137 + {
  138 + ex.printStackTrace();
  139 + }
  140 + }
  141 +
  142 + private void addMethod(ClassNode classNode, MethodNode method)
  143 + {
  144 + if (!this.addMethodToClass(classNode, method))
  145 + {
  146 + LiteLoaderLogger.debug("[AccessorTransformer] Method %s already exists in %s", method.name, classNode.name);
  147 + return;
  148 + }
  149 +
  150 + LiteLoaderLogger.debug("[AccessorTransformer] Attempting to add %s to %s", method.name, classNode.name);
  151 +
  152 + AnnotationNode accessor = ByteCodeUtilities.getInvisibleAnnotation(method, Accessor.class);
  153 + AnnotationNode invoker = ByteCodeUtilities.getInvisibleAnnotation(method, Invoker.class);
  154 + if (accessor != null)
  155 + {
  156 + Obf targetName = this.getObf(ByteCodeUtilities.<String>getAnnotationValue(accessor));
  157 + if (this.injectAccessor(classNode, method, targetName)) return;
  158 + }
  159 + else if (invoker != null)
  160 + {
  161 + Obf targetName = this.getObf(ByteCodeUtilities.<String>getAnnotationValue(invoker));
  162 + if (this.injectInvoker(classNode, method, targetName)) return;
  163 + }
  164 + else
  165 + {
  166 + LiteLoaderLogger.severe("[AccessorTransformer] Method %s for %s has no @Accessor or @Invoker annotation, the method will be ABSTRACT!", method.name, this.iface);
  167 + }
  168 +
  169 + LiteLoaderLogger.severe("[AccessorTransformer] Method %s for %s could not locate target member, the method will be ABSTRACT!", method.name, this.iface);
  170 + }
  171 +
  172 + private boolean injectAccessor(ClassNode classNode, MethodNode method, Obf targetName)
  173 + {
  174 + FieldNode targetField = this.findField(classNode, targetName);
  175 + if (targetField != null)
  176 + {
  177 + LiteLoaderLogger.debug("[AccessorTransformer] Found field %s for %s", targetField.name, method.name);
  178 + if (Type.getReturnType(method.desc) != Type.VOID_TYPE)
  179 + {
  180 + this.populateGetter(classNode, method, targetField);
  181 + }
  182 + else
  183 + {
  184 + this.populateSetter(classNode, method, targetField);
  185 + }
  186 +
  187 + return true;
  188 + }
  189 +
  190 + return false;
  191 + }
  192 +
  193 + private boolean injectInvoker(ClassNode classNode, MethodNode method, Obf targetName)
  194 + {
  195 + MethodNode targetMethod = this.findMethod(classNode, targetName, method.desc);
  196 + if (targetMethod != null)
  197 + {
  198 + LiteLoaderLogger.debug("[AccessorTransformer] Found method %s for %s", targetMethod.name, method.name);
  199 + this.populateInvoker(classNode, method, targetMethod);
  200 + return true;
  201 + }
  202 +
  203 + return false;
  204 + }
  205 +
  206 + private void populateGetter(ClassNode classNode, MethodNode method, FieldNode field)
  207 + {
  208 + Type returnType = Type.getReturnType(method.desc);
  209 + Type fieldType = Type.getType(field.desc);
  210 + if (!returnType.equals(fieldType))
  211 + {
  212 + throw new RuntimeException("Incompatible types! Field type: " + fieldType + " Method type: " + returnType);
  213 + }
  214 +
  215 + method.instructions.clear();
  216 + method.maxLocals = ByteCodeUtilities.getFirstNonArgLocalIndex(method);
  217 + method.maxStack = fieldType.getSize();
  218 +
  219 + if ((field.access & Opcodes.ACC_STATIC) == 0)
  220 + {
  221 + method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
  222 + method.instructions.add(new FieldInsnNode(Opcodes.GETFIELD, classNode.name, field.name, field.desc));
  223 + }
  224 + else
  225 + {
  226 + method.instructions.add(new FieldInsnNode(Opcodes.GETSTATIC, classNode.name, field.name, field.desc));
  227 + }
  228 +
  229 + method.instructions.add(new InsnNode(returnType.getOpcode(Opcodes.IRETURN)));
  230 + }
  231 +
  232 + private void populateSetter(ClassNode classNode, MethodNode method, FieldNode field)
  233 + {
  234 + Type[] argTypes = Type.getArgumentTypes(method.desc);
  235 + if (argTypes.length != 1)
  236 + {
  237 + throw new RuntimeException("Invalid setter! " + method.name + " must take exactly one argument");
  238 + }
  239 + Type argType = argTypes[0];
  240 + Type fieldType = Type.getType(field.desc);
  241 + if (!argType.equals(fieldType))
  242 + {
  243 + throw new RuntimeException("Incompatible types! Field type: " + fieldType + " Method type: " + argType);
  244 + }
  245 +
  246 + method.instructions.clear();
  247 + method.maxLocals = ByteCodeUtilities.getFirstNonArgLocalIndex(method);
  248 + method.maxStack = fieldType.getSize();
  249 +
  250 + if ((field.access & Opcodes.ACC_STATIC) == 0)
  251 + {
  252 + method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
  253 + method.instructions.add(new VarInsnNode(argType.getOpcode(Opcodes.ILOAD), 1));
  254 + method.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, classNode.name, field.name, field.desc));
  255 + }
  256 + else
  257 + {
  258 + method.instructions.add(new VarInsnNode(argType.getOpcode(Opcodes.ILOAD), 0));
  259 + method.instructions.add(new FieldInsnNode(Opcodes.PUTSTATIC, classNode.name, field.name, field.desc));
  260 + }
  261 +
  262 + method.instructions.add(new InsnNode(Opcodes.RETURN));
  263 + }
  264 +
  265 + private void populateInvoker(ClassNode classNode, MethodNode method, MethodNode targetMethod)
  266 + {
  267 + Type[] args = Type.getArgumentTypes(targetMethod.desc);
  268 + Type returnType = Type.getReturnType(targetMethod.desc);
  269 + boolean isStatic = (targetMethod.access & Opcodes.ACC_STATIC) != 0;
  270 +
  271 + method.instructions.clear();
  272 + method.maxStack = (method.maxLocals = ByteCodeUtilities.getFirstNonArgLocalIndex(method)) + 1;
  273 +
  274 + if (isStatic)
  275 + {
  276 + ByteCodeUtilities.loadArgs(args, method.instructions, 0);
  277 + method.instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, classNode.name, targetMethod.name, targetMethod.desc, false));
  278 + }
  279 + else
  280 + {
  281 + method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
  282 + ByteCodeUtilities.loadArgs(args, method.instructions, 1);
  283 + method.instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, classNode.name, targetMethod.name, targetMethod.desc, false));
  284 + }
  285 +
  286 + method.instructions.add(new InsnNode(returnType.getOpcode(Opcodes.IRETURN)));
  287 + }
  288 +
  289 + private FieldNode findField(ClassNode classNode, Obf fieldName)
  290 + {
  291 + for (FieldNode field : classNode.fields)
  292 + {
  293 + if (fieldName.obf.equals(field.name) || fieldName.srg.equals(field.name)|| fieldName.name.equals(field.name))
  294 + return field;
  295 + }
  296 +
  297 + return null;
  298 + }
  299 +
  300 + private MethodNode findMethod(ClassNode classNode, Obf methodName, String desc)
  301 + {
  302 + for (MethodNode method : classNode.methods)
  303 + {
  304 + if ((methodName.obf.equals(method.name) || methodName.srg.equals(method.name)|| methodName.name.equals(method.name)) && method.desc.equals(desc))
  305 + return method;
  306 + }
  307 +
  308 + return null;
  309 + }
  310 +
  311 + private boolean addMethodToClass(ClassNode classNode, MethodNode method)
  312 + {
  313 + MethodNode existingMethod = ByteCodeUtilities.findTargetMethod(classNode, method);
  314 + if (existingMethod != null) return false;
  315 + classNode.methods.add(method);
  316 + method.access = method.access & ~Opcodes.ACC_ABSTRACT;
  317 + return true;
  318 + }
  319 + }
  320 +
  321 + private List<AccessorInjection> accessors = new ArrayList<AccessorInjection>();
  322 +
  323 + public AccessorTransformer()
  324 + {
  325 + this.addAccessors();
  326 + }
  327 +
  328 + public void addAccessor(String interfaceName)
  329 + {
  330 + try
  331 + {
  332 + this.accessors.add(new AccessorInjection(interfaceName));
  333 + }
  334 + catch (Exception ex)
  335 + {
  336 + LiteLoaderLogger.debug(ex);
  337 + }
  338 + }
  339 +
  340 + @Override
  341 + public byte[] transform(String name, String transformedName, byte[] basicClass)
  342 + {
  343 + ClassNode classNode = null;
  344 +
  345 + classNode = this.apply(name, transformedName, basicClass, classNode);
  346 +
  347 + if (classNode != null)
  348 + {
  349 + this.postTransform(name, transformedName, classNode);
  350 + return this.writeClass(classNode);
  351 + }
  352 +
  353 + return basicClass;
  354 + }
  355 +
  356 + public ClassNode apply(String name, String transformedName, byte[] basicClass, ClassNode classNode)
  357 + {
  358 + for (Iterator<AccessorInjection> iter = this.accessors.iterator(); iter.hasNext(); )
  359 + {
  360 + AccessorInjection accessor = iter.next();
  361 + Obf target = accessor.getTarget();
  362 + if (target.obf.equals(transformedName) || target.name.equals(transformedName))
  363 + {
  364 + LiteLoaderLogger.debug("[AccessorTransformer] Processing access injections in %s", transformedName);
  365 + if (classNode == null) classNode = this.readClass(basicClass, true);
  366 + accessor.apply(classNode);
  367 + iter.remove();
  368 + }
  369 + }
  370 +
  371 + return classNode;
  372 + }
  373 +
  374 + protected void addAccessors()
  375 + {
  376 + }
  377 +
  378 + protected void postTransform(String name, String transformedName, ClassNode classNode)
  379 + {
  380 + }
  381 +}
java/common/com/mumfrey/liteloader/transformers/access/Invoker.java 0 โ†’ 100644
  1 +package com.mumfrey.liteloader.transformers.access;
  2 +
  3 +import java.lang.annotation.ElementType;
  4 +import java.lang.annotation.Retention;
  5 +import java.lang.annotation.RetentionPolicy;
  6 +import java.lang.annotation.Target;
  7 +
  8 +/**
  9 + * Defines an invoker method within an accessor injection interface
  10 + *
  11 + * @author Adam Mummery-Smith
  12 + */
  13 +@Target({ElementType.METHOD, ElementType.TYPE})
  14 +@Retention(RetentionPolicy.CLASS)
  15 +public @interface Invoker
  16 +{
  17 + public String value();
  18 +}
java/common/com/mumfrey/liteloader/transformers/access/ObfTableClass.java 0 โ†’ 100644
  1 +package com.mumfrey.liteloader.transformers.access;
  2 +
  3 +import java.lang.annotation.ElementType;
  4 +import java.lang.annotation.Retention;
  5 +import java.lang.annotation.RetentionPolicy;
  6 +import java.lang.annotation.Target;
  7 +
  8 +import com.mumfrey.liteloader.core.runtime.Obf;
  9 +
  10 +/**
  11 + * Defines the obfuscation table class to use for an accessor injection interface
  12 + *
  13 + * @author Adam Mummery-Smith
  14 + */
  15 +@Target(ElementType.TYPE)
  16 +@Retention(RetentionPolicy.CLASS)
  17 +public @interface ObfTableClass
  18 +{
  19 + public Class<? extends Obf> value();
  20 +}
java/common/com/mumfrey/liteloader/transformers/event/EventInjectionTransformer.java
@@ -75,4 +75,14 @@ public abstract class EventInjectionTransformer implements IClassTransformer @@ -75,4 +75,14 @@ public abstract class EventInjectionTransformer implements IClassTransformer
75 75
76 return event; 76 return event;
77 } 77 }
  78 +
  79 + /**
  80 + * Register an access injection interface
  81 + *
  82 + * @param interfaceName
  83 + */
  84 + protected final void addAccessor(String interfaceName)
  85 + {
  86 + EventTransformer.addAccessor(interfaceName);
  87 + }
78 } 88 }
java/common/com/mumfrey/liteloader/transformers/event/EventTransformer.java
@@ -19,6 +19,7 @@ import org.objectweb.asm.util.CheckClassAdapter; @@ -19,6 +19,7 @@ import org.objectweb.asm.util.CheckClassAdapter;
19 19
20 import com.mumfrey.liteloader.transformers.ByteCodeUtilities; 20 import com.mumfrey.liteloader.transformers.ByteCodeUtilities;
21 import com.mumfrey.liteloader.transformers.ClassTransformer; 21 import com.mumfrey.liteloader.transformers.ClassTransformer;
  22 +import com.mumfrey.liteloader.transformers.access.AccessorTransformer;
22 import com.mumfrey.liteloader.util.log.LiteLoaderLogger; 23 import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
23 24
24 /** 25 /**
@@ -55,12 +56,14 @@ public final class EventTransformer extends ClassTransformer @@ -55,12 +56,14 @@ public final class EventTransformer extends ClassTransformer
55 */ 56 */
56 private static Map<String, Map<String, Map<Event, InjectionPoint>>> eventMappings = new HashMap<String, Map<String, Map<Event, InjectionPoint>>>(); 57 private static Map<String, Map<String, Map<Event, InjectionPoint>>> eventMappings = new HashMap<String, Map<String, Map<Event, InjectionPoint>>>();
57 58
  59 + private static AccessorTransformer accessorTransformer;
  60 +
58 /** 61 /**
59 * Runs the validator on the generated classes, only for debugging purposes 62 * Runs the validator on the generated classes, only for debugging purposes
60 */ 63 */
61 private final boolean runValidator = false; 64 private final boolean runValidator = false;
62 65
63 - private int globalEventID = 0; 66 + private int globalEventID = 0;
64 67
65 static class Injection 68 static class Injection
66 { 69 {
@@ -186,18 +189,37 @@ public final class EventTransformer extends ClassTransformer @@ -186,18 +189,37 @@ public final class EventTransformer extends ClassTransformer
186 events.put(event, injectionPoint); 189 events.put(event, injectionPoint);
187 } 190 }
188 191
  192 + static void addAccessor(String interfaceName)
  193 + {
  194 + if (EventTransformer.accessorTransformer == null)
  195 + {
  196 + EventTransformer.accessorTransformer = new AccessorTransformer()
  197 + {
  198 + @Override
  199 + protected void addAccessors() {}
  200 + };
  201 + }
  202 +
  203 + EventTransformer.accessorTransformer.addAccessor(interfaceName);
  204 + }
  205 +
189 @Override 206 @Override
190 public final byte[] transform(String name, String transformedName, byte[] basicClass) 207 public final byte[] transform(String name, String transformedName, byte[] basicClass)
191 { 208 {
192 if (basicClass != null && EventTransformer.eventMappings.containsKey(transformedName)) 209 if (basicClass != null && EventTransformer.eventMappings.containsKey(transformedName))
193 { 210 {
194 - return this.injectEvents(basicClass, EventTransformer.eventMappings.get(transformedName)); 211 + return this.injectEvents(name, transformedName, basicClass, EventTransformer.eventMappings.get(transformedName));
  212 + }
  213 +
  214 + if (EventTransformer.accessorTransformer != null)
  215 + {
  216 + return EventTransformer.accessorTransformer.transform(name, transformedName, basicClass);
195 } 217 }
196 218
197 return basicClass; 219 return basicClass;
198 } 220 }
199 221
200 - private byte[] injectEvents(byte[] basicClass, Map<String, Map<Event, InjectionPoint>> mappings) 222 + private byte[] injectEvents(String name, String transformedName, byte[] basicClass, Map<String, Map<Event, InjectionPoint>> mappings)
201 { 223 {
202 if (mappings == null) return basicClass; 224 if (mappings == null) return basicClass;
203 225
@@ -213,6 +235,11 @@ public final class EventTransformer extends ClassTransformer @@ -213,6 +235,11 @@ public final class EventTransformer extends ClassTransformer
213 } 235 }
214 } 236 }
215 237
  238 + if (EventTransformer.accessorTransformer != null)
  239 + {
  240 + EventTransformer.accessorTransformer.apply(name, transformedName, basicClass, classNode);
  241 + }
  242 +
216 if (this.runValidator) 243 if (this.runValidator)
217 { 244 {
218 ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); 245 ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
java/common/com/mumfrey/liteloader/transformers/event/json/JsonEvents.java
1 package com.mumfrey.liteloader.transformers.event.json; 1 package com.mumfrey.liteloader.transformers.event.json;
2 2
3 import java.io.Serializable; 3 import java.io.Serializable;
  4 +import java.util.ArrayList;
4 import java.util.List; 5 import java.util.List;
5 import java.util.regex.Matcher; 6 import java.util.regex.Matcher;
6 import java.util.regex.Pattern; 7 import java.util.regex.Pattern;
@@ -8,6 +9,7 @@ import java.util.regex.Pattern; @@ -8,6 +9,7 @@ import java.util.regex.Pattern;
8 import com.google.gson.Gson; 9 import com.google.gson.Gson;
9 import com.google.gson.GsonBuilder; 10 import com.google.gson.GsonBuilder;
10 import com.google.gson.annotations.SerializedName; 11 import com.google.gson.annotations.SerializedName;
  12 +import com.mumfrey.liteloader.core.runtime.Obf;
11 13
12 /** 14 /**
13 * Serialisable class which represents a set of event injection definitions. Instances of this class are 15 * Serialisable class which represents a set of event injection definitions. Instances of this class are
@@ -49,11 +51,22 @@ public class JsonEvents implements Serializable @@ -49,11 +51,22 @@ public class JsonEvents implements Serializable
49 private List<JsonEvent> events; 51 private List<JsonEvent> events;
50 52
51 /** 53 /**
  54 + * List of accessor interfaces
  55 + */
  56 + @SerializedName("accessors")
  57 + private List<String> accessors;
  58 +
  59 + /**
52 * Parsed method descriptors 60 * Parsed method descriptors
53 */ 61 */
54 private transient JsonMethods methods; 62 private transient JsonMethods methods;
55 63
56 /** 64 /**
  65 + * Parsed accessors
  66 + */
  67 + private transient List<String> accessorInterfaces = new ArrayList<String>();
  68 +
  69 + /**
57 * Attempts to parse the information in this object 70 * Attempts to parse the information in this object
58 */ 71 */
59 private void parse() 72 private void parse()
@@ -76,6 +89,18 @@ public class JsonEvents implements Serializable @@ -76,6 +89,18 @@ public class JsonEvents implements Serializable
76 { 89 {
77 event.parse(this.methods); 90 event.parse(this.methods);
78 } 91 }
  92 +
  93 + if (this.accessors != null)
  94 + {
  95 + for (String accessor : this.accessors)
  96 + {
  97 + if (accessor != null)
  98 + {
  99 + Obf accessorName = this.obfuscation.parseClass(accessor);
  100 + this.accessorInterfaces.add(accessorName.name);
  101 + }
  102 + }
  103 + }
79 } 104 }
80 catch (InvalidEventJsonException ex) 105 catch (InvalidEventJsonException ex)
81 { 106 {
@@ -116,6 +141,11 @@ public class JsonEvents implements Serializable @@ -116,6 +141,11 @@ public class JsonEvents implements Serializable
116 { 141 {
117 event.register(transformer); 142 event.register(transformer);
118 } 143 }
  144 +
  145 + for (String interfaceName : this.accessorInterfaces)
  146 + {
  147 + transformer.registerAccessor(interfaceName);
  148 + }
119 } 149 }
120 150
121 // public String toJson() 151 // public String toJson()
java/common/com/mumfrey/liteloader/transformers/event/json/ModEventInjectionTransformer.java
@@ -74,4 +74,9 @@ public class ModEventInjectionTransformer extends EventInjectionTransformer @@ -74,4 +74,9 @@ public class ModEventInjectionTransformer extends EventInjectionTransformer
74 { 74 {
75 return super.addEvent(event, targetMethod, injectionPoint); 75 return super.addEvent(event, targetMethod, injectionPoint);
76 } 76 }
  77 +
  78 + protected void registerAccessor(String interfaceName)
  79 + {
  80 + super.addAccessor(interfaceName);
  81 + }
77 } 82 }