Commit fba0e0ffc742dfd2c78a379dcdc7097c3cef12a2
1 parent
0ec79e75
adding AccessorTransformer and replacing MinecraftOverlay with accessor injection
Showing
17 changed files
with
724 additions
and
170 deletions
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 | } |