aboutsummaryrefslogtreecommitdiff
path: root/src/featureClass/forgeEvents.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/featureClass/forgeEvents.js')
-rw-r--r--src/featureClass/forgeEvents.js99
1 files changed, 99 insertions, 0 deletions
diff --git a/src/featureClass/forgeEvents.js b/src/featureClass/forgeEvents.js
new file mode 100644
index 0000000..fb723b1
--- /dev/null
+++ b/src/featureClass/forgeEvents.js
@@ -0,0 +1,99 @@
+importClass(net.minecraftforge.common.MinecraftForge) //i would have used the ct module but it is broken (line 78) (this is fixed verison)
+importPackage(net.minecraftforge.fml.common.eventhandler)
+importPackage(org.objectweb.asm)
+importClass(java.lang.ClassLoader)
+importClass(org.apache.commons.lang3.RandomStringUtils)
+importClass(java.util.function.Consumer)
+importClass(net.minecraftforge.fml.common.eventhandler.EventPriority)
+
+const L = s => `L${s};`
+const LoadedInsts = []
+
+function defineClassBytes(name, bytes) {//should support multymc? ty dawjaw https://canary.discord.com/channels/119493402902528000/688773480954855537/979959207124168744
+ const classLoader = Packages.com.chattriggers.ctjs.CTJS.class.getClassLoader()
+
+ let defClass;
+ ClassLoader.class.getDeclaredMethods().forEach(m => {
+ if (m.toString() === "protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int) throws java.lang.ClassFormatError") {
+ defClass = m;
+ }
+ })
+
+ defClass.setAccessible(true)
+
+ const n = new java.lang.String(name)
+ const o = new java.lang.Integer(0)
+ const s = new java.lang.Integer(bytes.length)
+ return defClass.invoke(classLoader, n, bytes, o, s)
+}
+
+const registerForge = (e, priority = EventPriority.NORMAL, cb) => {
+ const cw = new ClassWriter(0)
+
+ const event = Type.getType(e.class).internalName
+ const name = RandomStringUtils.randomAlphabetic(7)
+
+ const consumer = Type.getType(Consumer.class).internalName
+ const mcForge = Type.getType(MinecraftForge.class).internalName
+ const eventBus = Type.getType(EventBus.class).internalName
+ const subscribeEvent = Type.getType(SubscribeEvent.class).internalName
+ const obj = Type.getType(java.lang.Object.class).internalName
+
+ cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, name, null, obj, null)
+ //cw.visitInnerClass("net/minecraftforge/event/entity/player/PlayerEvent$BreakSpeed","net/minecraftforge/event/entity/player/PlayerEvent","BreakSpeed",ACC_PUBLIC+ACC_STATIC);
+ {
+ cw.visitField(Opcodes.ACC_PRIVATE + Opcodes.ACC_FINAL, "callback", L(consumer), L(consumer + "<" + L(event) + ">"), null).visitEnd()
+ }
+ {
+ const con = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "(" + L(consumer) + ")V", "(" + L(consumer + "<" + L(event) + ">") + ")V", null)
+ con.visitCode()
+ con.visitVarInsn(Opcodes.ALOAD, 0)
+ con.visitMethodInsn(Opcodes.INVOKESPECIAL, obj, "<init>", "()V", false)
+
+ con.visitVarInsn(Opcodes.ALOAD, 0)
+ con.visitVarInsn(Opcodes.ALOAD, 1)
+ con.visitFieldInsn(Opcodes.PUTFIELD, name, "callback", L(consumer))
+ con.visitFieldInsn(Opcodes.GETSTATIC, mcForge, "EVENT_BUS", L(eventBus))
+ con.visitVarInsn(Opcodes.ALOAD, 0)
+ con.visitMethodInsn(Opcodes.INVOKEVIRTUAL, eventBus, "register", "(" + L(obj) + ")V", false)
+ con.visitInsn(Opcodes.RETURN)
+ con.visitMaxs(2, 2)
+ con.visitEnd()
+ }
+ {
+ const mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "on", "(" + L(event) + ")V", null, null)
+ {
+ const av = mv.visitAnnotation(L(subscribeEvent), true)
+ av.visitEnum("priority", "Lnet/minecraftforge/fml/common/eventhandler/EventPriority;", priority.name());
+ av.visitEnd()
+ }
+ mv.visitCode()
+ mv.visitVarInsn(Opcodes.ALOAD, 0)
+ mv.visitFieldInsn(Opcodes.GETFIELD, name, "callback", L(consumer))
+ mv.visitVarInsn(Opcodes.ALOAD, 1)
+ mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, consumer, "accept", "(" + L(obj) + ")V", true)
+ mv.visitInsn(Opcodes.RETURN)
+ mv.visitMaxs(2, 2)
+ mv.visitEnd()
+ }
+ cw.visitEnd()
+
+ const inst = defineClassBytes(name, cw.toByteArray())
+ .getDeclaredConstructor(Consumer.class)
+ .newInstance(new java.util.function.Consumer({
+ accept: function (t) { cb(t) }
+ }))
+ LoadedInsts.push(inst)
+ return inst;
+}
+
+const unregisterForge = inst => {
+ MinecraftForge.EVENT_BUS.unregister(inst)
+}
+
+register("gameUnload", () => {
+ LoadedInsts.forEach(unregisterForge)
+ LoadedInsts.length = 0
+})
+
+export { registerForge, unregisterForge } \ No newline at end of file