Created
June 3, 2019 08:54
-
-
Save RareScrap/d032aab61d010117743994df1976453c to your computer and use it in GitHub Desktop.
Коллекция идиотских (но местами интересных) способ отслеживания изменения инвентарей в Minecraft 1.7.10
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ru.rarescrap.simpleweightsystem; | |
import cpw.mods.fml.common.eventhandler.SubscribeEvent; | |
import net.minecraft.entity.Entity; | |
import net.minecraft.entity.item.EntityItem; | |
import net.minecraft.entity.player.EntityPlayer; | |
import net.minecraft.entity.player.EntityPlayerMP; | |
import net.minecraft.inventory.*; | |
import net.minecraft.item.Item; | |
import net.minecraft.world.World; | |
import net.minecraftforge.common.ForgeHooks; | |
import net.minecraftforge.event.entity.EntityJoinWorldEvent; | |
import net.minecraftforge.event.entity.player.EntityInteractEvent; | |
import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent; | |
import ru.rarescrap.gloomyfolken.hooklib.asm.Hook; | |
import ru.rarescrap.gloomyfolken.hooklib.asm.ReturnCondition; | |
import ru.rarescrap.gloomyfolken.hooklib.minecraft.HookLoader; | |
import ru.rarescrap.gloomyfolken.hooklib.minecraft.PrimaryClassTransformer; | |
import net.minecraft.entity.player.InventoryPlayer; | |
import net.minecraft.item.ItemStack; | |
import net.minecraftforge.common.MinecraftForge; | |
import ru.rarescrap.weightapi.IWeightProvider; | |
import ru.rarescrap.weightapi.WeightRegistry; | |
import ru.rarescrap.weightapi.event.CalculateInventoryWeightEvent; | |
import ru.rarescrap.weightapi.event.WeightChangedEvent; | |
import java.util.List; | |
public class ASMHookLoader extends HookLoader { | |
// включает саму HookLib'у. Делать это можно только в одном из ASMHookLoader'ов. | |
// При желании, можно включить ru.rarescrap.gloomyfolken.hooklib.minecraft.HookLibPlugin и не указывать здесь это вовсе. | |
// TODO: Как включить плагин? | |
@Override | |
public String[] getASMTransformerClass() { | |
return new String[]{PrimaryClassTransformer.class.getName()}; | |
} | |
@Override | |
public void registerHooks() { | |
//регистрируем класс, где есть методы с аннотацией @Hook | |
//registerHookContainer(PlayerWeightTrackerHooks.class.getName()); | |
//registerHookContainer(PlayerInventoryHooks.class.getName()); | |
//registerHookContainer(ICraftingHooks.class.getName()); | |
} | |
public static class PlayerWeightTrackerHooks { | |
private static double prevWeight; | |
private static void updatePrevWeight(InventoryPlayer inventoryPlayer, Entity owner) { | |
prevWeight = WeightRegistry.getWeightProvider().getWeight(inventoryPlayer, owner); | |
} | |
// UI: Вычисляем вес до изменения инвентаря | |
@Hook | |
public static void putStack(Slot slot, ItemStack p_75215_1_) { | |
IWeightProvider weightProvider = WeightRegistry.getWeightProvider(); | |
// На случай, если WeightProvider должен приходить с сервера. Т.к. контент | |
// игрока может высылаться на клиент раньше, чем придет WeightProvider | |
if (slot.inventory instanceof InventoryPlayer && weightProvider != null) { | |
InventoryPlayer inventoryPlayer = (InventoryPlayer) slot.inventory; | |
updatePrevWeight(inventoryPlayer, inventoryPlayer.player); | |
} | |
} | |
// UI: Шлем евент изменения веса | |
@Hook | |
public static void onSlotChanged(Slot slot) { | |
IWeightProvider weightProvider = WeightRegistry.getWeightProvider(); | |
if (slot.inventory instanceof InventoryPlayer && weightProvider != null) { | |
InventoryPlayer inventoryPlayer = (InventoryPlayer) slot.inventory; | |
MinecraftForge.EVENT_BUS.post(new WeightChangedEvent(inventoryPlayer, | |
prevWeight, | |
weightProvider.getWeight(inventoryPlayer, inventoryPlayer.player), | |
weightProvider.isOverloaded(inventoryPlayer, inventoryPlayer.player), | |
inventoryPlayer.player)); | |
} | |
} | |
// Drop Item: Вычисляем вес до изменения инвентаря | |
@Hook(injectOnExit = true, returnCondition = ReturnCondition.ON_TRUE) | |
public static boolean onDroppedByPlayer(Item item, ItemStack itemStack, EntityPlayer player) { | |
updatePrevWeight(player.inventory, player); | |
return true; | |
} | |
// Drop Item: Шлем евент изменения веса | |
// Выбрасывание итемов изменяет инвентарь не через слоты, а напрямую. Отлавливаем это. | |
// TODO: Вот такой вот самопальный "static @SubscribeEvent". Как его заменить кошерными средствами на 1.7.10? | |
@Hook(injectOnExit = true, returnCondition = ReturnCondition.ON_NOT_NULL) | |
public static EntityItem onPlayerTossEvent(ForgeHooks hooks, EntityPlayer player, ItemStack item, boolean includeName, @Hook.ReturnValue EntityItem returnValue) { | |
Slot slot = player.inventoryContainer.getSlotFromInventory(player.inventory, player.inventory.currentItem); | |
onSlotChanged(slot); // Думаю, это лучше чем вызывать ванильный slot.onSlotChanged(); | |
return returnValue; | |
} | |
// Item Use: Шлем евент изменения веса | |
// TODO: А вот тут я не могу заюзать подход выше, т.к. PlayerDestroyItemEvent может выброситься миновав вызов ForgeEventFactory#onPlayerDestroyItem() | |
@SubscribeEvent | |
public void onPlayerDestroyItem(PlayerDestroyItemEvent event) { | |
Slot slot = event.entityPlayer.inventoryContainer.getSlotFromInventory(event.entityPlayer.inventory, event.entityPlayer.inventory.currentItem); // TODO: Предмет в руке? | |
onSlotChanged(slot); // Думаю, это лучше чем вызывать ванильный slot.onSlotChanged(); | |
} | |
@Hook | |
public static void tryPlaceItemIntoWorld(ItemStack itemStack, EntityPlayer p_77943_1_, World p_77943_2_, int p_77943_3_, int p_77943_4_, int p_77943_5_, int p_77943_6_, float p_77943_7_, float p_77943_8_, float p_77943_9_) { | |
updatePrevWeight(p_77943_1_.inventory, p_77943_1_); | |
} | |
@SubscribeEvent | |
public void onInteract(EntityInteractEvent event) { | |
updatePrevWeight(event.entityPlayer.inventory, event.entityPlayer); | |
} | |
@Hook(injectOnExit = true) | |
public static void interactWith(EntityPlayer player, Entity p_70998_1_) { | |
Slot slot = player.inventoryContainer.getSlotFromInventory(player.inventory, player.inventory.currentItem); // TODO: Предмет в руке? | |
onSlotChanged(slot); // Думаю, это лучше чем вызывать ванильный slot.onSlotChanged(); | |
} | |
} | |
public static class PlayerInventoryHooks { | |
private static double prevWeight; | |
@Hook(targetMethod = "setInventorySlotContents") | |
public static void setInventorySlotContents_before(InventoryPlayer inventoryPlayer, int p_70299_1_, ItemStack p_70299_2_) { | |
prevWeight = WeightRegistry.getWeightProvider().getWeight(inventoryPlayer, inventoryPlayer.player); | |
} | |
@Hook(targetMethod = "setInventorySlotContents", injectOnExit = true) | |
public static void setInventorySlotContents_after(InventoryPlayer inventoryPlayer, int p_70299_1_, ItemStack p_70299_2_) { | |
IWeightProvider weightProvider = WeightRegistry.getWeightProvider(); | |
if (weightProvider != null) { | |
MinecraftForge.EVENT_BUS.post(new WeightChangedEvent(inventoryPlayer, | |
prevWeight, | |
weightProvider.getWeight(inventoryPlayer, inventoryPlayer.player), | |
weightProvider.isOverloaded(inventoryPlayer, inventoryPlayer.player), | |
inventoryPlayer.player)); | |
} | |
} | |
@Hook(targetMethod = "decrStackSize") | |
public static void decrStackSize_before(InventoryPlayer inventoryPlayer, int p_70298_1_, int p_70298_2_) { | |
prevWeight = WeightRegistry.getWeightProvider().getWeight(inventoryPlayer, inventoryPlayer.player); | |
} | |
@Hook(targetMethod = "decrStackSize", injectOnExit = true) | |
public static void decrStackSize_after(InventoryPlayer inventoryPlayer, int p_70298_1_, int p_70298_2_) { | |
IWeightProvider weightProvider = WeightRegistry.getWeightProvider(); | |
if (weightProvider != null) { | |
MinecraftForge.EVENT_BUS.post(new WeightChangedEvent(inventoryPlayer, | |
prevWeight, | |
weightProvider.getWeight(inventoryPlayer, inventoryPlayer.player), | |
weightProvider.isOverloaded(inventoryPlayer, inventoryPlayer.player), | |
inventoryPlayer.player)); | |
} | |
} | |
} | |
public static class ICraftingHooks { | |
// private static boolean isInDetectAndSendChanges; | |
// private static Container container; | |
// private static Entity owner; | |
// | |
// private static double prevWeight; | |
// | |
// @Hook(targetMethod = "detectAndSendChanges") | |
// public static void enableFlag(Container container) { | |
// isInDetectAndSendChanges = true; | |
// ICraftingHooks.container = container; | |
// } | |
// | |
// @Hook(targetMethod = "detectAndSendChanges", injectOnExit = true) | |
// public static void disableFlag(Container container) { | |
// isInDetectAndSendChanges = false; | |
// } | |
// | |
// @Hook(targetMethod = "areItemStacksEqual", injectOnExit = true) | |
// public static void injectWeightPrecalculating(ItemStack itemStack, ItemStack p_77989_0_, ItemStack p_77989_1_, @Hook.ReturnValue boolean returnValue) { | |
// if (container instanceof ContainerPlayer) | |
// prevWeight = WeightRegistry.getWeightProvider().getWeight( | |
// ((ContainerPlayer) container).thePlayer.inventory, | |
// ((ContainerPlayer) container).thePlayer | |
// ); | |
// } | |
// @Hook(returnCondition = ReturnCondition.ALWAYS) | |
// public static void detectAndSendChanges(Container container) | |
// { | |
// for (int i = 0; i < container.inventorySlots.size(); ++i) | |
// { | |
// ItemStack itemstack = ((Slot)container.inventorySlots.get(i)).getStack(); | |
// ItemStack itemstack1 = (ItemStack)container.inventoryItemStacks.get(i); | |
// | |
// if (!ItemStack.areItemStacksEqual(itemstack1, itemstack)) | |
// { | |
// prevWeight = WeightRegistry.getWeightProvider().getWeight(((Slot) container.inventorySlots.get(i)).inventory, ) | |
// itemstack1 = itemstack == null ? null : itemstack.copy(); | |
// container.inventoryItemStacks.set(i, itemstack1); | |
// | |
// for (int j = 0; j < container.crafters.size(); ++j) | |
// { | |
// ((ICrafting)container.crafters.get(j)).sendSlotContents(container, i, itemstack1); | |
// } | |
// } | |
// } | |
// } | |
// // Для начала попробуем прсто вставлять в начало метода | |
// @Hook | |
// public static void sendSlotContents(EntityPlayerMP entityPlayerMP, Container p_71111_1_, int p_71111_2_, ItemStack p_71111_3_) { | |
// //WeightChangedEvent event = new WeightChangedEvent(entityPlayerMP.inventory, ) | |
// } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://forum.mcmodding.ru/threads/Лучший-способ-отслеживания-изменения-инвентаря-игрока.24160/