diff --git a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java index 83b9209de..ad72a3868 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java +++ b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java @@ -129,7 +129,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.HIGHEST, MatteryPlayerCapability.Companion::onLivingDrops); EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::canEntitySpawn); EVENT_BUS.addListener(EventPriority.LOW, MatterDataKt::serverStartData); 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 5e55e0048..64a7990b2 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt @@ -129,26 +129,6 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial field = value } - fun dropExoSuitInventory(): List { - val result = ArrayList() - val oldCaptureDrops = ply.captureDrops(result) as MutableCollection? - - val iterator = exoSuitContainer.iterator().nonEmpty() - - for (item in iterator) { - if (!hasVanishingCurse(item)) { - ply.drop(item, true, false) - } - - iterator.remove() - } - - ply.captureDrops(oldCaptureDrops) - oldCaptureDrops?.addAll(result) - - return result - } - var isExoSuitCraftingUpgraded by synchronizer.bool(setter = setter@{ value, access, _ -> if (value != access.read()) { access.write(value) @@ -768,23 +748,6 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial .ifPresentK { it.invalidateNetworkState() } } - private val waitingToDie = ArrayList>() - - fun onLivingDrops(event: LivingDropsEvent) { - val indexOf = waitingToDie.indexOfFirst { event.entity == it.first } - - if (indexOf == -1) - return - - val drops = waitingToDie[indexOf].second.dropExoSuitInventory() - - if (event.entity.captureDrops() == null) { - event.drops.addAll(drops) - } - - waitingToDie.removeAt(indexOf) - } - fun onPlayerDeath(event: LivingDeathEvent) { val ply = event.entity as? Player ?: return val mattery = ply.matteryPlayer ?: return @@ -795,21 +758,6 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial return } - if (mattery.hasExoSuit && !ply.level.gameRules.getBoolean(GameRules.RULE_KEEPINVENTORY)) { - waitingToDie.add(ply to mattery) - - onceServer { - val index = waitingToDie.indexOfFirst { it.first == ply } - - if (index != -1) { - waitingToDie.removeAt(index) - mattery.dropExoSuitInventory().forEach { ply.level.addFreshEntity(it) } - LOGGER.warn("Unable to 'properly' drop $ply's ExoSuit inventory contents") - LOGGER.warn("I blame Forge.") - } - } - } - if (!mattery.isAndroid) { return } @@ -901,7 +849,26 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial return } - val leftover = it.exoSuitContainer.addItem(item, false) + val leftover = it.exoSuitContainer.addItem(item, false, popTime = 5) + item.count = leftover.count + } + + /** + * this method is hooked through coremod transformer + */ + @JvmStatic + fun inventoryAddItemHookPre(inventory: Inventory, item: ItemStack) { + if (item.isEmpty) { + return + } + + val it = inventory.player.matteryPlayer ?: return + + if (!it.hasExoSuit) { + return + } + + val leftover = it.exoSuitContainer.addItem(item, simulate = false, onlyIntoExisting = true, popTime = 5) item.count = leftover.count } @@ -916,5 +883,42 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial inventoryAddItemHook(inventory, item) } + + @JvmStatic + fun inventoryDropAll(inventory: Inventory) { + if (inventory.player.matteryPlayer?.hasExoSuit == false) { + return + } + + val iterator = inventory.player.matteryPlayer?.exoSuitContainer?.iterator()?.nonEmpty() ?: return + + for (item in iterator) { + inventory.player.drop(item, true, false) + } + } + + @JvmStatic + fun inventoryClearContent(inventory: Inventory) { + if (inventory.player.matteryPlayer?.hasExoSuit == false) { + return + } + + inventory.player.matteryPlayer?.exoSuitContainer?.clearContent() + } + + @JvmStatic + fun playerDestroyVanishingCursedItems(player: Player) { + if (player.matteryPlayer?.hasExoSuit == false) { + return + } + + val iterator = player.matteryPlayer?.exoSuitContainer?.iterator()?.nonEmpty() ?: return + + for (item in iterator) { + if (hasVanishingCurse(item)) { + iterator.remove() + } + } + } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/MatteryContainer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/MatteryContainer.kt index 0aa3974a0..24d1d97be 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/MatteryContainer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/MatteryContainer.kt @@ -147,7 +147,7 @@ open class MatteryContainer(val watcher: Runnable, private val size: Int) : Cont } @JvmOverloads - fun addItem(stack: ItemStack, range: IntRange, simulate: Boolean = false): ItemStack { + fun addItem(stack: ItemStack, range: IntRange, simulate: Boolean = false, onlyIntoExisting: Boolean = false, popTime: Int? = null): ItemStack { if (range.last >= size || range.first < 0) throw IllegalArgumentException("Invalid range: $range") @@ -171,6 +171,10 @@ open class MatteryContainer(val watcher: Runnable, private val size: Int) : Cont slotStack.count = newCount trackedSlots[slot] = slotStack.copy() setChanged(slot, slotStack, old) + + if (popTime != null) { + slotStack.popTime = popTime + } } copy.shrink(diff) @@ -182,21 +186,27 @@ open class MatteryContainer(val watcher: Runnable, private val size: Int) : Cont } } - // двигаем в пустые слоты - for (slot in range) { - if (slots[slot].isEmpty) { - val diff = copy.count.coerceAtMost(getMaxStackSize(slot).coerceAtMost(copy.maxStackSize)) + if (!onlyIntoExisting) { + // двигаем в пустые слоты + for (slot in range) { + if (slots[slot].isEmpty) { + val diff = copy.count.coerceAtMost(getMaxStackSize(slot).coerceAtMost(copy.maxStackSize)) - if (!simulate) { - val copyToPut = copy.copy() - copyToPut.count = diff - this[slot] = copyToPut - } + if (!simulate) { + val copyToPut = copy.copy() + copyToPut.count = diff + this[slot] = copyToPut - copy.shrink(diff) + if (popTime != null) { + copyToPut.popTime = popTime + } + } - if (copy.isEmpty) { - return copy + copy.shrink(diff) + + if (copy.isEmpty) { + return copy + } } } } @@ -204,8 +214,8 @@ open class MatteryContainer(val watcher: Runnable, private val size: Int) : Cont return copy } - fun addItem(stack: ItemStack, simulate: Boolean): ItemStack { - return addItem(stack, 0 until size, simulate) + fun addItem(stack: ItemStack, simulate: Boolean, onlyIntoExisting: Boolean = false, popTime: Int? = null): ItemStack { + return addItem(stack, 0 until size, simulate, onlyIntoExisting = onlyIntoExisting, popTime = popTime) } @JvmOverloads diff --git a/src/main/resources/coremods/code_injector.js b/src/main/resources/coremods/code_injector.js index c16b73327..08cf490fd 100644 --- a/src/main/resources/coremods/code_injector.js +++ b/src/main/resources/coremods/code_injector.js @@ -462,6 +462,92 @@ function test(instructionList, instructions, offset) { return i == instructionList.length ? offset : -1 } +function method(path, transform) { + var split = path.split('.') + var methodName = split.pop() + var indexOf = methodName.indexOf('(') + var classname = split.join('.') + + return { + 'target': { + 'type': 'METHOD', + 'class': classname, + 'methodName': ASMAPI.mapMethod(methodName.substring(0, indexOf)), + 'methodDesc': methodName.substring(indexOf) + }, + + 'transformer': transform + } +} + +function injectAtHead(path, instructions) { + return method(path, function(node) { + var last = undefined + var next + + for (var i = 0; i < instructions.length; i++) { + next = instructions[i] + + if (last === undefined) { + node.instructions.insert(next) + } else { + node.instructions.insert(last, next) + } + + last = next + } + + return node + }) +} + +var returnCodes = [ + opcodesRemapped.return, + opcodesRemapped.areturn, + opcodesRemapped.freturn, + opcodesRemapped.ireturn, + opcodesRemapped.dreturn, + opcodesRemapped.lreturn, +] + +function injectAtTail(path, instructions) { + return method(path, function(node) { + for (var instr = node.instructions.size() - 1; instr >= 0; instr--) { + if (includes(returnCodes, node.instructions.get(instr).getOpcode())) { + var last = node.instructions.get(instr > 0 ? --instr : instr) + var next + + for (var i = 0; i < instructions.length; i++) { + next = instructions[i] + node.instructions.insert(last, next) + last = next + } + + return node + } + } + + print('[Overdrive That Matters Coremod] Unable to find tail of ' + path + ', injecting at beginning!') + + var last = undefined + var next + + for (var i = 0; i < instructions.length; i++) { + next = instructions[i] + + if (last === undefined) { + node.instructions.insert(next) + } else { + node.instructions.insert(last, next) + } + + last = next + } + + return node + }) +} + function injectInventoryInsertHook( instructions, determinedOffset, @@ -530,6 +616,30 @@ function patchBlendFunc(node) { function initializeCoreMod() { return { + 'Inventory#dropAll': injectAtTail( + 'net.minecraft.world.entity.player.Inventory.m_36071_()V', + [ + new VarInsnNode(opcodesRemapped.aload, 0), + new MethodInsnNode(opcodesRemapped.invokestatic, 'ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability', 'inventoryDropAll', '(Lnet/minecraft/world/entity/player/Inventory;)V', false) + ] + ), + + 'Inventory#clearContent': injectAtTail( + 'net.minecraft.world.entity.player.Inventory.m_6211_()V', + [ + new VarInsnNode(opcodesRemapped.aload, 0), + new MethodInsnNode(opcodesRemapped.invokestatic, 'ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability', 'inventoryClearContent', '(Lnet/minecraft/world/entity/player/Inventory;)V', false) + ] + ), + + 'Player#destroyVanishingCursedItems': injectAtTail( + 'net.minecraft.world.entity.player.Player.m_36345_()V', + [ + new VarInsnNode(opcodesRemapped.aload, 0), + new MethodInsnNode(opcodesRemapped.invokestatic, 'ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability', 'playerDestroyVanishingCursedItems', '(Lnet/minecraft/world/entity/player/Player;)V', false) + ] + ), + 'blend func lock 1': { 'target': { 'type': 'METHOD', @@ -635,7 +745,34 @@ function initializeCoreMod() { var i - // patch "not damaged" + // 83: iconst_1 + // 84: ireturn + // 85: iconst_0 + // 86: ireturn + // 87: aload_2 + // 88: invokevirtual #68 // Method net/minecraft/world/item/ItemStack.getCount:()I + + // patch "not damaged" before loop + for (i = 0; i < node.instructions.size(); i++) { + var determinedOffset = test([ + opcodesRemapped.iconst_1, + opcodesRemapped.ireturn, + opcodesRemapped.iconst_0, + opcodesRemapped.ireturn, + opcodesRemapped.aload, + opcodesRemapped.invokevirtual, + ], node.instructions, i) + + if (determinedOffset != -1) { + injectInventoryInsertHook(node.instructions, determinedOffset - 1, + 'inventoryAddItemHookPre', + '(Lnet/minecraft/world/entity/player/Inventory;Lnet/minecraft/world/item/ItemStack;)V') + + break + } + } + + // patch "not damaged" after loop for (i = 0; i < node.instructions.size(); i++) { var determinedOffset = test([ opcodesRemapped.invokevirtual,