From d31b692f9432b67028475551bdbccf0d1ec305df Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Sat, 1 Oct 2022 19:43:22 +0700 Subject: [PATCH] Hook directly into Inventory#add using coremod Fixes #43 --- .editorconfig | 13 + .gitattributes | 2 + .../mc/otm/OverdriveThatMatters.java | 1 - .../otm/capability/MatteryPlayerCapability.kt | 55 +- src/main/resources/META-INF/coremods.json | 3 + src/main/resources/coremods/code_injector.js | 598 ++++++++++++++++++ 6 files changed, 646 insertions(+), 26 deletions(-) create mode 100644 src/main/resources/META-INF/coremods.json create mode 100644 src/main/resources/coremods/code_injector.js diff --git a/.editorconfig b/.editorconfig index e88aff724..da3a86110 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,6 +7,12 @@ charset = utf-8 indent_style = tab end_of_line = crlf +[*.js] +insert_final_newline = true +charset = utf-8 +indent_style = tab +end_of_line = crlf + [*.java] insert_final_newline = true charset = utf-8 @@ -18,3 +24,10 @@ insert_final_newline = false charset = utf-8 indent_style = space indent_size = 2 + +[*.toml] +insert_final_newline = false +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf diff --git a/.gitattributes b/.gitattributes index a651d5292..a90be2361 100644 --- a/.gitattributes +++ b/.gitattributes @@ -6,3 +6,5 @@ src/generated/**/*.json text eol=lf *.kt text eol=crlf *.json text eol=crlf +*.js text eol=crlf +*.toml text eol=lf diff --git a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java index 1b0c33ab3..bb320418c 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java +++ b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java @@ -124,7 +124,6 @@ public final class OverdriveThatMatters { EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onPlayerChangeDimensionEvent); EVENT_BUS.addListener(EventPriority.LOWEST, MatteryPlayerCapability.Companion::onPlayerDeath); EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onPlayerCloneEvent); - EVENT_BUS.addListener(EventPriority.LOW, MatteryPlayerCapability.Companion::onPickupEvent); EVENT_BUS.addListener(EventPriority.HIGHEST, MatteryPlayerCapability.Companion::onLivingDrops); EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::canEntitySpawn); diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt index ed6dcb209..834bf79d5 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt @@ -1,6 +1,5 @@ package ru.dbotthepony.mc.otm.capability -import it.unimi.dsi.fastutil.objects.Object2IntAVLTreeMap import net.minecraft.ChatFormatting import net.minecraft.core.Direction import net.minecraft.nbt.CompoundTag @@ -16,6 +15,7 @@ import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.MobSpawnType import net.minecraft.world.entity.item.ItemEntity import net.minecraft.world.entity.monster.Phantom +import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player import net.minecraft.world.item.ItemStack import net.minecraft.world.item.enchantment.EnchantmentHelper.hasVanishingCurse @@ -57,6 +57,35 @@ import kotlin.collections.ArrayDeque import kotlin.collections.ArrayList import kotlin.collections.HashMap +/** + * this method is hooked through coremod transformer + */ +fun inventoryAddItemHook(inventory: Inventory, item: ItemStack) { + if (item.isEmpty) { + return + } + + val it = inventory.player.matteryPlayer ?: return + + if (!it.hasExoSuit) { + return + } + + val leftover = it.exoSuitContainer.addItem(item, false) + item.count = leftover.count +} + +/** + * this method is hooked through coremod transformer + */ +fun inventoryAddDamagedItemHook(determinedSlot: Int, inventory: Inventory, item: ItemStack) { + if (determinedSlot > 0) { + return + } + + inventoryAddItemHook(inventory, item) +} + @Suppress("unused") class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerializable { private inner class PlayerMatteryContainer(size: Int) : MatteryContainer(size) { @@ -820,32 +849,8 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial const val SLEEP_TICKS_LIMIT = 80 - private val itemPickupTicks = WeakHashMap>() - private val LOGGER = LogManager.getLogger() - fun onPickupEvent(event: EntityItemPickupEvent) { - if (event.item.owner != null && event.item.owner != event.entity.uuid && event.item.age < 200 || event.item.item.isEmpty) { - return - } - - val it = event.entity.matteryPlayer ?: return - - if (!it.hasExoSuit) { - return - } - - val ticks = itemPickupTicks.computeIfAbsent(event.entity) { WeakHashMap() }.computeIfAbsent(event.item) { MutableInt() } - ticks.increment() - - if (ticks.value < 10) { - return - } - - val leftover = it.exoSuitContainer.addItem(event.item.item, false) - event.item.item.count = leftover.count - } - fun canEntitySpawn(event: LivingSpawnEvent.CheckSpawn) { if (event.spawnReason == MobSpawnType.NATURAL && event.entity is Phantom) { for (ply in event.entity.level.players()) { diff --git a/src/main/resources/META-INF/coremods.json b/src/main/resources/META-INF/coremods.json new file mode 100644 index 000000000..0f2a0791b --- /dev/null +++ b/src/main/resources/META-INF/coremods.json @@ -0,0 +1,3 @@ +{ + "code_injector": "coremods/code_injector.js" +} \ No newline at end of file diff --git a/src/main/resources/coremods/code_injector.js b/src/main/resources/coremods/code_injector.js new file mode 100644 index 000000000..45562a52d --- /dev/null +++ b/src/main/resources/coremods/code_injector.js @@ -0,0 +1,598 @@ + +var ASMAPI = Java.type('net.minecraftforge.coremod.api.ASMAPI') +var AbstractInsnNode = Java.type('org.objectweb.asm.tree.AbstractInsnNode') +var Opcodes = Java.type('org.objectweb.asm.Opcodes') +var VarInsnNode = Java.type('org.objectweb.asm.tree.VarInsnNode') +var MethodInsnNode = Java.type('org.objectweb.asm.tree.MethodInsnNode') + +var opcodesRemapped = { + 'aaload': 50, + 'aastore': 83, + 'aconst_null': 1, + 'aload': 25, + 'aload_0': 42, + 'aload_1': 43, + 'aload_2': 44, + 'aload_3': 45, + 'anewarray': 189, + 'areturn': 176, + 'arraylength': 190, + 'astore': 58, + 'astore_0': 75, + 'astore_1': 76, + 'astore_2': 77, + 'astore_3': 78, + 'athrow': 191, + 'baload': 51, + 'bastore': 84, + 'bipush': 16, + 'breakpoint': 202, + 'caload': 52, + 'castore': 85, + 'checkcast': 192, + 'd2f': 144, + 'd2i': 142, + 'd2l': 143, + 'dadd': 99, + 'daload': 49, + 'dastore': 82, + 'dcmpg': 152, + 'dcmpl': 151, + 'dconst_0': 14, + 'dconst_1': 15, + 'ddiv': 111, + 'dload': 24, + 'dload_0': 38, + 'dload_1': 39, + 'dload_2': 40, + 'dload_3': 41, + 'dmul': 107, + 'dneg': 119, + 'drem': 115, + 'dreturn': 175, + 'dstore': 57, + 'dstore_0': 71, + 'dstore_1': 72, + 'dstore_2': 73, + 'dstore_3': 74, + 'dsub': 103, + 'dup': 89, + 'dup_x1': 90, + 'dup_x2': 91, + 'dup2': 92, + 'dup2_x1': 93, + 'dup2_x2': 94, + 'f2d': 141, + 'f2i': 139, + 'f2l': 140, + 'fadd': 98, + 'faload': 48, + 'fastore': 81, + 'fcmpg': 150, + 'fcmpl': 149, + 'fconst_0': 11, + 'fconst_1': 12, + 'fconst_2': 13, + 'fdiv': 110, + 'fload': 23, + 'fload_0': 34, + 'fload_1': 35, + 'fload_2': 36, + 'fload_3': 37, + 'fmul': 106, + 'fneg': 118, + 'frem': 114, + 'freturn': 174, + 'fstore': 56, + 'fstore_0': 67, + 'fstore_1': 68, + 'fstore_2': 69, + 'fstore_3': 70, + 'fsub': 102, + 'getfield': 180, + 'getstatic': 178, + 'goto': 167, + 'goto_w': 200, + 'i2b': 145, + 'i2c': 146, + 'i2d': 135, + 'i2f': 134, + 'i2l': 133, + 'i2s': 147, + 'iadd': 96, + 'iaload': 46, + 'iand': 126, + 'iastore': 79, + 'iconst_0': 3, + 'iconst_1': 4, + 'iconst_2': 5, + 'iconst_3': 6, + 'iconst_4': 7, + 'iconst_5': 8, + 'iconst_m1': 2, + 'idiv': 108, + 'if_acmpeq': 165, + 'if_acmpne': 166, + 'if_icmpeq': 159, + 'if_icmpge': 162, + 'if_icmpgt': 163, + 'if_icmple': 164, + 'if_icmplt': 161, + 'if_icmpne': 160, + 'ifeq': 153, + 'ifge': 156, + 'ifgt': 157, + 'ifle': 158, + 'iflt': 155, + 'ifne': 154, + 'ifnonnull': 199, + 'ifnull': 198, + 'iinc': 132, + 'iload': 21, + 'iload_0': 26, + 'iload_1': 27, + 'iload_2': 28, + 'iload_3': 29, + 'impdep1': 254, + 'impdep2': 255, + 'imul': 104, + 'ineg': 116, + 'instanceof': 193, + 'invokedynamic': 186, + 'invokeinterface': 185, + 'invokespecial': 183, + 'invokestatic': 184, + 'invokevirtual': 182, + 'ior': 128, + 'irem': 112, + 'ireturn': 172, + 'ishl': 120, + 'ishr': 122, + 'istore': 54, + 'istore_0': 59, + 'istore_1': 60, + 'istore_2': 61, + 'istore_3': 62, + 'isub': 100, + 'iushr': 124, + 'ixor': 130, + 'jsr': 168, + 'jsr_w': 201, + 'l2d': 138, + 'l2f': 137, + 'l2i': 136, + 'ladd': 97, + 'laload': 47, + 'land': 127, + 'lastore': 80, + 'lcmp': 148, + 'lconst_0': 9, + 'lconst_1': 10, + 'ldc': 18, + 'ldc_w': 19, + 'ldc2_w': 20, + 'ldiv': 109, + 'lload': 22, + 'lload_0': 30, + 'lload_1': 31, + 'lload_2': 32, + 'lload_3': 33, + 'lmul': 105, + 'lneg': 117, + 'lookupswitch': 171, + 'lor': 129, + 'lrem': 113, + 'lreturn': 173, + 'lshl': 121, + 'lshr': 123, + 'lstore': 55, + 'lstore_0': 63, + 'lstore_1': 64, + 'lstore_2': 65, + 'lstore_3': 66, + 'lsub': 101, + 'lushr': 125, + 'lxor': 131, + 'monitorenter': 194, + 'monitorexit': 195, + 'multianewarray': 197, + 'new': 187, + 'newarray': 188, + 'nop': 0, + 'pop': 87, + 'pop2': 88, + 'putfield': 181, + 'putstatic': 179, + 'ret': 169, + 'return': 177, + 'saload': 53, + 'sastore': 86, + 'sipush': 17, + 'swap': 95, + 'tableswitch': 170, + 'wide': 196 +} + +var opcodes = [] +opcodes[opcodesRemapped.aaload] = 'aaload' +opcodes[opcodesRemapped.aastore] = 'aastore' +opcodes[opcodesRemapped.aconst_null] = 'aconst_null' +opcodes[opcodesRemapped.aload] = 'aload' +opcodes[opcodesRemapped.aload_0] = 'aload_0' +opcodes[opcodesRemapped.aload_1] = 'aload_1' +opcodes[opcodesRemapped.aload_2] = 'aload_2' +opcodes[opcodesRemapped.aload_3] = 'aload_3' +opcodes[opcodesRemapped.anewarray] = 'anewarray' +opcodes[opcodesRemapped.areturn] = 'areturn' +opcodes[opcodesRemapped.arraylength] = 'arraylength' +opcodes[opcodesRemapped.astore] = 'astore' +opcodes[opcodesRemapped.astore_0] = 'astore_0' +opcodes[opcodesRemapped.astore_1] = 'astore_1' +opcodes[opcodesRemapped.astore_2] = 'astore_2' +opcodes[opcodesRemapped.astore_3] = 'astore_3' +opcodes[opcodesRemapped.athrow] = 'athrow' +opcodes[opcodesRemapped.baload] = 'baload' +opcodes[opcodesRemapped.bastore] = 'bastore' +opcodes[opcodesRemapped.bipush] = 'bipush' +opcodes[opcodesRemapped.breakpoint] = 'breakpoint' +opcodes[opcodesRemapped.caload] = 'caload' +opcodes[opcodesRemapped.castore] = 'castore' +opcodes[opcodesRemapped.checkcast] = 'checkcast' +opcodes[opcodesRemapped.d2f] = 'd2f' +opcodes[opcodesRemapped.d2i] = 'd2i' +opcodes[opcodesRemapped.d2l] = 'd2l' +opcodes[opcodesRemapped.dadd] = 'dadd' +opcodes[opcodesRemapped.daload] = 'daload' +opcodes[opcodesRemapped.dastore] = 'dastore' +opcodes[opcodesRemapped.dcmpg] = 'dcmpg' +opcodes[opcodesRemapped.dcmpl] = 'dcmpl' +opcodes[opcodesRemapped.dconst_0] = 'dconst_0' +opcodes[opcodesRemapped.dconst_1] = 'dconst_1' +opcodes[opcodesRemapped.ddiv] = 'ddiv' +opcodes[opcodesRemapped.dload] = 'dload' +opcodes[opcodesRemapped.dload_0] = 'dload_0' +opcodes[opcodesRemapped.dload_1] = 'dload_1' +opcodes[opcodesRemapped.dload_2] = 'dload_2' +opcodes[opcodesRemapped.dload_3] = 'dload_3' +opcodes[opcodesRemapped.dmul] = 'dmul' +opcodes[opcodesRemapped.dneg] = 'dneg' +opcodes[opcodesRemapped.drem] = 'drem' +opcodes[opcodesRemapped.dreturn] = 'dreturn' +opcodes[opcodesRemapped.dstore] = 'dstore' +opcodes[opcodesRemapped.dstore_0] = 'dstore_0' +opcodes[opcodesRemapped.dstore_1] = 'dstore_1' +opcodes[opcodesRemapped.dstore_2] = 'dstore_2' +opcodes[opcodesRemapped.dstore_3] = 'dstore_3' +opcodes[opcodesRemapped.dsub] = 'dsub' +opcodes[opcodesRemapped.dup] = 'dup' +opcodes[opcodesRemapped.dup_x1] = 'dup_x1' +opcodes[opcodesRemapped.dup_x2] = 'dup_x2' +opcodes[opcodesRemapped.dup2] = 'dup2' +opcodes[opcodesRemapped.dup2_x1] = 'dup2_x1' +opcodes[opcodesRemapped.dup2_x2] = 'dup2_x2' +opcodes[opcodesRemapped.f2d] = 'f2d' +opcodes[opcodesRemapped.f2i] = 'f2i' +opcodes[opcodesRemapped.f2l] = 'f2l' +opcodes[opcodesRemapped.fadd] = 'fadd' +opcodes[opcodesRemapped.faload] = 'faload' +opcodes[opcodesRemapped.fastore] = 'fastore' +opcodes[opcodesRemapped.fcmpg] = 'fcmpg' +opcodes[opcodesRemapped.fcmpl] = 'fcmpl' +opcodes[opcodesRemapped.fconst_0] = 'fconst_0' +opcodes[opcodesRemapped.fconst_1] = 'fconst_1' +opcodes[opcodesRemapped.fconst_2] = 'fconst_2' +opcodes[opcodesRemapped.fdiv] = 'fdiv' +opcodes[opcodesRemapped.fload] = 'fload' +opcodes[opcodesRemapped.fload_0] = 'fload_0' +opcodes[opcodesRemapped.fload_1] = 'fload_1' +opcodes[opcodesRemapped.fload_2] = 'fload_2' +opcodes[opcodesRemapped.fload_3] = 'fload_3' +opcodes[opcodesRemapped.fmul] = 'fmul' +opcodes[opcodesRemapped.fneg] = 'fneg' +opcodes[opcodesRemapped.frem] = 'frem' +opcodes[opcodesRemapped.freturn] = 'freturn' +opcodes[opcodesRemapped.fstore] = 'fstore' +opcodes[opcodesRemapped.fstore_0] = 'fstore_0' +opcodes[opcodesRemapped.fstore_1] = 'fstore_1' +opcodes[opcodesRemapped.fstore_2] = 'fstore_2' +opcodes[opcodesRemapped.fstore_3] = 'fstore_3' +opcodes[opcodesRemapped.fsub] = 'fsub' +opcodes[opcodesRemapped.getfield] = 'getfield' +opcodes[opcodesRemapped.getstatic] = 'getstatic' +opcodes[opcodesRemapped.goto] = 'goto' +opcodes[opcodesRemapped.goto_w] = 'goto_w' +opcodes[opcodesRemapped.i2b] = 'i2b' +opcodes[opcodesRemapped.i2c] = 'i2c' +opcodes[opcodesRemapped.i2d] = 'i2d' +opcodes[opcodesRemapped.i2f] = 'i2f' +opcodes[opcodesRemapped.i2l] = 'i2l' +opcodes[opcodesRemapped.i2s] = 'i2s' +opcodes[opcodesRemapped.iadd] = 'iadd' +opcodes[opcodesRemapped.iaload] = 'iaload' +opcodes[opcodesRemapped.iand] = 'iand' +opcodes[opcodesRemapped.iastore] = 'iastore' +opcodes[opcodesRemapped.iconst_0] = 'iconst_0' +opcodes[opcodesRemapped.iconst_1] = 'iconst_1' +opcodes[opcodesRemapped.iconst_2] = 'iconst_2' +opcodes[opcodesRemapped.iconst_3] = 'iconst_3' +opcodes[opcodesRemapped.iconst_4] = 'iconst_4' +opcodes[opcodesRemapped.iconst_5] = 'iconst_5' +opcodes[opcodesRemapped.iconst_m1] = 'iconst_m1' +opcodes[opcodesRemapped.idiv] = 'idiv' +opcodes[opcodesRemapped.if_acmpeq] = 'if_acmpeq' +opcodes[opcodesRemapped.if_acmpne] = 'if_acmpne' +opcodes[opcodesRemapped.if_icmpeq] = 'if_icmpeq' +opcodes[opcodesRemapped.if_icmpge] = 'if_icmpge' +opcodes[opcodesRemapped.if_icmpgt] = 'if_icmpgt' +opcodes[opcodesRemapped.if_icmple] = 'if_icmple' +opcodes[opcodesRemapped.if_icmplt] = 'if_icmplt' +opcodes[opcodesRemapped.if_icmpne] = 'if_icmpne' +opcodes[opcodesRemapped.ifeq] = 'ifeq' +opcodes[opcodesRemapped.ifge] = 'ifge' +opcodes[opcodesRemapped.ifgt] = 'ifgt' +opcodes[opcodesRemapped.ifle] = 'ifle' +opcodes[opcodesRemapped.iflt] = 'iflt' +opcodes[opcodesRemapped.ifne] = 'ifne' +opcodes[opcodesRemapped.ifnonnull] = 'ifnonnull' +opcodes[opcodesRemapped.ifnull] = 'ifnull' +opcodes[opcodesRemapped.iinc] = 'iinc' +opcodes[opcodesRemapped.iload] = 'iload' +opcodes[opcodesRemapped.iload_0] = 'iload_0' +opcodes[opcodesRemapped.iload_1] = 'iload_1' +opcodes[opcodesRemapped.iload_2] = 'iload_2' +opcodes[opcodesRemapped.iload_3] = 'iload_3' +opcodes[opcodesRemapped.impdep1] = 'impdep1' +opcodes[opcodesRemapped.impdep2] = 'impdep2' +opcodes[opcodesRemapped.imul] = 'imul' +opcodes[opcodesRemapped.ineg] = 'ineg' +opcodes[opcodesRemapped.instanceof] = 'instanceof' +opcodes[opcodesRemapped.invokedynamic] = 'invokedynamic' +opcodes[opcodesRemapped.invokeinterface] = 'invokeinterface' +opcodes[opcodesRemapped.invokespecial] = 'invokespecial' +opcodes[opcodesRemapped.invokestatic] = 'invokestatic' +opcodes[opcodesRemapped.invokevirtual] = 'invokevirtual' +opcodes[opcodesRemapped.ior] = 'ior' +opcodes[opcodesRemapped.irem] = 'irem' +opcodes[opcodesRemapped.ireturn] = 'ireturn' +opcodes[opcodesRemapped.ishl] = 'ishl' +opcodes[opcodesRemapped.ishr] = 'ishr' +opcodes[opcodesRemapped.istore] = 'istore' +opcodes[opcodesRemapped.istore_0] = 'istore_0' +opcodes[opcodesRemapped.istore_1] = 'istore_1' +opcodes[opcodesRemapped.istore_2] = 'istore_2' +opcodes[opcodesRemapped.istore_3] = 'istore_3' +opcodes[opcodesRemapped.isub] = 'isub' +opcodes[opcodesRemapped.iushr] = 'iushr' +opcodes[opcodesRemapped.ixor] = 'ixor' +opcodes[opcodesRemapped.jsr] = 'jsr' +opcodes[opcodesRemapped.jsr_w] = 'jsr_w' +opcodes[opcodesRemapped.l2d] = 'l2d' +opcodes[opcodesRemapped.l2f] = 'l2f' +opcodes[opcodesRemapped.l2i] = 'l2i' +opcodes[opcodesRemapped.ladd] = 'ladd' +opcodes[opcodesRemapped.laload] = 'laload' +opcodes[opcodesRemapped.land] = 'land' +opcodes[opcodesRemapped.lastore] = 'lastore' +opcodes[opcodesRemapped.lcmp] = 'lcmp' +opcodes[opcodesRemapped.lconst_0] = 'lconst_0' +opcodes[opcodesRemapped.lconst_1] = 'lconst_1' +opcodes[opcodesRemapped.ldc] = 'ldc' +opcodes[opcodesRemapped.ldc_w] = 'ldc_w' +opcodes[opcodesRemapped.ldc2_w] = 'ldc2_w' +opcodes[opcodesRemapped.ldiv] = 'ldiv' +opcodes[opcodesRemapped.lload] = 'lload' +opcodes[opcodesRemapped.lload_0] = 'lload_0' +opcodes[opcodesRemapped.lload_1] = 'lload_1' +opcodes[opcodesRemapped.lload_2] = 'lload_2' +opcodes[opcodesRemapped.lload_3] = 'lload_3' +opcodes[opcodesRemapped.lmul] = 'lmul' +opcodes[opcodesRemapped.lneg] = 'lneg' +opcodes[opcodesRemapped.lookupswitch] = 'lookupswitch' +opcodes[opcodesRemapped.lor] = 'lor' +opcodes[opcodesRemapped.lrem] = 'lrem' +opcodes[opcodesRemapped.lreturn] = 'lreturn' +opcodes[opcodesRemapped.lshl] = 'lshl' +opcodes[opcodesRemapped.lshr] = 'lshr' +opcodes[opcodesRemapped.lstore] = 'lstore' +opcodes[opcodesRemapped.lstore_0] = 'lstore_0' +opcodes[opcodesRemapped.lstore_1] = 'lstore_1' +opcodes[opcodesRemapped.lstore_2] = 'lstore_2' +opcodes[opcodesRemapped.lstore_3] = 'lstore_3' +opcodes[opcodesRemapped.lsub] = 'lsub' +opcodes[opcodesRemapped.lushr] = 'lushr' +opcodes[opcodesRemapped.lxor] = 'lxor' +opcodes[opcodesRemapped.monitorenter] = 'monitorenter' +opcodes[opcodesRemapped.monitorexit] = 'monitorexit' +opcodes[opcodesRemapped.multianewarray] = 'multianewarray' +opcodes[opcodesRemapped.new] = 'new' +opcodes[opcodesRemapped.newarray] = 'newarray' +opcodes[opcodesRemapped.nop] = 'nop' +opcodes[opcodesRemapped.pop] = 'pop' +opcodes[opcodesRemapped.pop2] = 'pop2' +opcodes[opcodesRemapped.putfield] = 'putfield' +opcodes[opcodesRemapped.putstatic] = 'putstatic' +opcodes[opcodesRemapped.ret] = 'ret' +opcodes[opcodesRemapped.return] = 'return' +opcodes[opcodesRemapped.saload] = 'saload' +opcodes[opcodesRemapped.sastore] = 'sastore' +opcodes[opcodesRemapped.sipush] = 'sipush' +opcodes[opcodesRemapped.swap] = 'swap' +opcodes[opcodesRemapped.tableswitch] = 'tableswitch' +opcodes[opcodesRemapped.wide] = 'wide' + +function includes(array, value) { + var i + + for (i = 0; i < array.length; i++) { + if (array[i] == value) { + return true + } + } + + return false +} + +function test(instructionList, instructions, offset) { + var i + var offset = offset + + for (i = 0; i < instructionList.length && instructions.size() > offset; i++) { + var instruction = instructions.get(offset) + + // no opcode + if (instruction.getOpcode() == -1) { + i-- + offset++ + continue + } + + if (instructionList[i] == instruction.getOpcode()) { + offset++ + } else { + // print("Not matched at " + i + " offset " + offset + " because it has op code of " + opcodes[instruction.getOpcode()] + " when expected " + opcodes[instructionList[i]]) + return -1 + } + } + + // print("exiting with " + i + " when expecting " + instructionList.length) + return i == instructionList.length ? offset : -1 +} + +function injectInventoryInsertHook( + instructions, + determinedOffset, + hookName, + hookDesc, + pre +) { + var last = instructions.get(determinedOffset) + + // print('Patching Inventory#add at instruction ' + determinedOffset + ' to add ' + hookName + hookDesc) + + // loading this (Inventory) to stack + + if (pre != undefined) { + instructions.insert(last, pre) + last = pre + } + + var next = new VarInsnNode(opcodesRemapped.aload, 0) + instructions.insert(last, next) + + last = next + // loading itemstack to stack + next = new VarInsnNode(opcodesRemapped.aload, 2) + + instructions.insert(last, next) + + last = next + // dispatching hook method + next = new MethodInsnNode( + opcodesRemapped.invokestatic, + 'ru/dbotthepony/mc/otm/capability/MatteryPlayerCapabilityKt', + hookName, + hookDesc, + false + ) + + instructions.insert(last, next) +} + +function initializeCoreMod() { + return { + 'Inventory#add patch': { + 'target': { + 'type': 'METHOD', + 'class': 'net.minecraft.world.entity.player.Inventory', + 'methodName': ASMAPI.mapMethod('m_36040_'), // add + 'methodDesc': '(ILnet/minecraft/world/item/ItemStack;)Z' + }, + + 'transformer': function(node) { + // If item is not "damaged": + // 113: invokevirtual #144 // Method addResource:(ILnet/minecraft/world/item/ItemStack;)I + // 116: invokevirtual #158 // Method net/minecraft/world/item/ItemStack.setCount:(I)V + // 119: aload_2 + // 120: invokevirtual #57 // Method net/minecraft/world/item/ItemStack.isEmpty:()Z + // 123: ifne 134 + // 126: aload_2 + // 127: invokevirtual #68 // Method net/minecraft/world/item/ItemStack.getCount:()I + // 130: iload_3 + // 131: if_icmplt 87 + // <-- our target + // 134: aload_2 + // 135: invokevirtual #68 // Method net/minecraft/world/item/ItemStack.getCount:()I + // 138: iload_3 + // 139: if_icmpne 162 + // 142: aload_0 + + // If item returned that it is damaged: + // 10: invokevirtual #97 // Method net/minecraft/world/item/ItemStack.isDamaged:()Z + // 13: ifeq 87 + // 16: iload_1 + // 17: iconst_m1 + // 18: if_icmpne 26 + // 21: aload_0 + // 22: invokevirtual #86 // Method getFreeSlot:()I + // 25: istore_1 + // <-- our target + // 26: iload_1 + // 27: iflt 65 + // 30: aload_0 + // 31: getfield #19 // Field items:Lnet/minecraft/core/NonNullList; + // 34: iload_1 + // 35: aload_2 + + var i + + // patch "not damaged" + for (i = 0; i < node.instructions.size(); i++) { + var determinedOffset = test([ + opcodesRemapped.invokevirtual, + opcodesRemapped.invokevirtual, + opcodesRemapped.aload, + opcodesRemapped.invokevirtual, + opcodesRemapped.ifne, + opcodesRemapped.aload, + opcodesRemapped.invokevirtual, + opcodesRemapped.iload, + opcodesRemapped.if_icmplt, + ], node.instructions, i) + + if (determinedOffset != -1) { + injectInventoryInsertHook(node.instructions, determinedOffset, + 'inventoryAddItemHook', + '(Lnet/minecraft/world/entity/player/Inventory;Lnet/minecraft/world/item/ItemStack;)V') + + break + } + } + + // patch "damaged" + for (i = 0; i < node.instructions.size(); i++) { + var determinedOffset = test([ + opcodesRemapped.invokevirtual, + opcodesRemapped.ifeq, + opcodesRemapped.iload, + opcodesRemapped.iconst_m1, + opcodesRemapped.if_icmpne, + opcodesRemapped.aload, + opcodesRemapped.invokevirtual, + opcodesRemapped.istore, + ], node.instructions, i) + + if (determinedOffset != -1) { + injectInventoryInsertHook(node.instructions, determinedOffset, + 'inventoryAddDamagedItemHook', + '(ILnet/minecraft/world/entity/player/Inventory;Lnet/minecraft/world/item/ItemStack;)V', + new VarInsnNode(opcodesRemapped.iload, 1)) + + break + } + } + + return node + } + } + } +}