From e43a132ccbdfe8a2fc87fc40456023397621d96c Mon Sep 17 00:00:00 2001 From: Lyfts <127234178+Lyfts@users.noreply.github.com> Date: Tue, 30 Jul 2024 18:45:44 +0200 Subject: [PATCH 01/16] Fix inventory not updating when offhand is active + a few other things --- src/main/java/xonin/backhand/Backhand.java | 11 ++- src/main/java/xonin/backhand/CommonProxy.java | 27 ++--- .../xonin/backhand/HookContainerClass.java | 3 + .../xonin/backhand/ServerEventsHandler.java | 68 ++++++------- .../xonin/backhand/ServerTickHandler.java | 99 +++++++++---------- .../backhand/api/core/BackhandUtils.java | 38 ++----- .../api/core/OffhandExtendedProperty.java | 4 + .../client/BackhandClientTickHandler.java | 11 +-- .../backhand/client/ClientEventHandler.java | 7 +- .../xonin/backhand/client/ClientProxy.java | 6 -- .../backhand/client/ClientTickHandler.java | 9 +- .../client/renderer/RenderOffhandPlayer.java | 14 +-- .../client/utils/BackhandClientUtils.java | 32 +++++- .../client/world/ClientFakePlayer.java | 68 +++++++++++++ .../client/world/DummyChunkProvider.java | 97 ++++++++++++++++++ .../client/world/DummySaveHandler.java | 99 +++++++++++++++++++ .../backhand/client/world/DummyWorld.java | 68 +++++++++++++ .../coremod/BackhandLoadingPlugin.java | 1 + .../mixins/early/MixinEntityItem.java | 27 +++++ .../mixins/early/MixinItemRenderer.java | 1 - .../early/MixinNetHandlerPlayClient.java | 17 ---- .../early/MixinNetHandlerPlayServer.java | 48 ++++++--- .../mixins/early/MixinPlayerControllerMP.java | 27 ----- .../packet/BackhandPacketHandler.java | 1 - .../packet/OffhandWorldHotswapPacket.java | 34 ------- src/main/resources/META-INF/backhand_at.cfg | 4 + 26 files changed, 547 insertions(+), 274 deletions(-) create mode 100644 src/main/java/xonin/backhand/client/world/ClientFakePlayer.java create mode 100644 src/main/java/xonin/backhand/client/world/DummyChunkProvider.java create mode 100644 src/main/java/xonin/backhand/client/world/DummySaveHandler.java create mode 100644 src/main/java/xonin/backhand/client/world/DummyWorld.java create mode 100644 src/main/java/xonin/backhand/mixins/early/MixinEntityItem.java delete mode 100644 src/main/java/xonin/backhand/packet/OffhandWorldHotswapPacket.java diff --git a/src/main/java/xonin/backhand/Backhand.java b/src/main/java/xonin/backhand/Backhand.java index 1acd10c..b6f56ba 100644 --- a/src/main/java/xonin/backhand/Backhand.java +++ b/src/main/java/xonin/backhand/Backhand.java @@ -14,7 +14,7 @@ import cpw.mods.fml.common.SidedProxy; import cpw.mods.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.event.FMLPreInitializationEvent; -import cpw.mods.fml.common.network.NetworkRegistry; +import cpw.mods.fml.common.event.FMLServerStoppingEvent; import xonin.backhand.packet.BackhandPacketHandler; import xonin.backhand.utils.BackhandConfig; @@ -55,7 +55,6 @@ public void load(FMLPreInitializationEvent event) { BackhandConfig.getConfig(new Configuration(event.getSuggestedConfigurationFile())); proxy.load(); - NetworkRegistry.INSTANCE.registerGuiHandler(this, proxy); MinecraftForge.EVENT_BUS.register(new ServerEventsHandler()); FMLCommonHandler.instance() @@ -74,8 +73,14 @@ public void init(FMLInitializationEvent event) { packetHandler.register(); } + @Mod.EventHandler + public void onServerStopping(FMLServerStoppingEvent event) { + proxy.onServerStopping(event); + } + public static MinecraftServer getServer() { - return MinecraftServer.getServer(); + return FMLCommonHandler.instance() + .getMinecraftServerInstance(); } public static boolean isOffhandBlacklisted(ItemStack stack) { diff --git a/src/main/java/xonin/backhand/CommonProxy.java b/src/main/java/xonin/backhand/CommonProxy.java index 24576e7..bce93b1 100644 --- a/src/main/java/xonin/backhand/CommonProxy.java +++ b/src/main/java/xonin/backhand/CommonProxy.java @@ -2,12 +2,12 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; -import net.minecraft.world.World; -import cpw.mods.fml.common.network.IGuiHandler; +import cpw.mods.fml.common.event.FMLServerStoppingEvent; +import xonin.backhand.api.core.BackhandUtils; import xonin.backhand.utils.EnumAnimations; -public class CommonProxy implements IGuiHandler { +public class CommonProxy { public static ItemStack offhandItemUsed; @@ -15,20 +15,13 @@ public void load() { } - @Override - public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { - /* - * if(ID > EnumGuiType.values().length) - * return null; - * EnumGuiType gui = EnumGuiType.values()[ID]; - * return getContainer(gui, player, x, y, z, npc); - */ - return null; - } - - @Override - public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { - return null; + public void onServerStopping(FMLServerStoppingEvent event) { + for (EntityPlayer player : Backhand.getServer() + .getConfigurationManager().playerEntityList) { + if (BackhandUtils.getOffhandItem(player) != null) { + ServerTickHandler.resetTickingHotswap(player); + } + } } public EntityPlayer getClientPlayer() { diff --git a/src/main/java/xonin/backhand/HookContainerClass.java b/src/main/java/xonin/backhand/HookContainerClass.java index 694c9b1..5bd89f4 100644 --- a/src/main/java/xonin/backhand/HookContainerClass.java +++ b/src/main/java/xonin/backhand/HookContainerClass.java @@ -67,6 +67,9 @@ public void onEntityJoin(EntityJoinWorldEvent event) { Backhand.packetHandler.sendPacketToPlayer( new OffhandConfigSyncPacket(player).generatePacket(), (EntityPlayerMP) event.entity); + Backhand.packetHandler.sendPacketToPlayer( + new OffhandSyncItemPacket(player).generatePacket(), + (EntityPlayerMP) event.entity); } ItemStack offhandItem = BackhandUtils.getOffhandItem(player); if (Backhand.isOffhandBlacklisted(offhandItem)) { diff --git a/src/main/java/xonin/backhand/ServerEventsHandler.java b/src/main/java/xonin/backhand/ServerEventsHandler.java index 3d7bc2d..d66a2ae 100644 --- a/src/main/java/xonin/backhand/ServerEventsHandler.java +++ b/src/main/java/xonin/backhand/ServerEventsHandler.java @@ -1,10 +1,12 @@ package xonin.backhand; +import net.minecraft.block.BlockDispenser; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Items; import net.minecraft.item.Item; import net.minecraft.item.ItemBow; import net.minecraft.item.ItemStack; +import net.minecraft.util.RegistrySimple; import net.minecraftforge.event.entity.living.LivingDeathEvent; import net.minecraftforge.event.entity.living.LivingHurtEvent; import net.minecraftforge.event.entity.player.ArrowNockEvent; @@ -16,13 +18,11 @@ import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.relauncher.Side; import ganymedes01.etfuturum.ModItems; -import ganymedes01.etfuturum.items.ItemArrowTipped; import xonin.backhand.api.core.BackhandUtils; +import xonin.backhand.api.core.OffhandExtendedProperty; public class ServerEventsHandler { - public static boolean arrowHotSwapped = false; - public static boolean regularHotSwap = false; public static int fireworkHotSwapped = -1; @SubscribeEvent @@ -31,7 +31,9 @@ public void onPlayerInteractNonVanilla(PlayerInteractEvent event) { EntityPlayer player = event.entityPlayer; ItemStack mainhandItem = player.getHeldItem(); ItemStack offhandItem = BackhandUtils.getOffhandItem(player); - if ((mainhandItem == null || mainhandItem.getItem() != Items.fireworks) && offhandItem != null + if ((mainhandItem == null + || mainhandItem.getItem() != Items.fireworks && !BackhandUtils.usagePriorAttack(mainhandItem)) + && offhandItem != null && offhandItem.getItem() == Items.fireworks) { fireworkHotSwapped = 1; } @@ -56,6 +58,7 @@ public void onLivingHurt(LivingHurtEvent event) { ItemStack offhandItem = BackhandUtils.getOffhandItem(player); ItemStack mainhandItem = player.getCurrentEquippedItem(); + OffhandExtendedProperty offhandProp = BackhandUtils.getOffhandEP(player); if (offhandItem == null) { return; @@ -66,7 +69,7 @@ public void onLivingHurt(LivingHurtEvent event) { if (offhandItem.getItem() == totem && (mainhandItem == null || mainhandItem.getItem() != totem)) { BackhandUtils.swapOffhandItem(player); - regularHotSwap = true; + offhandProp.regularHotSwap = true; } } } @@ -76,8 +79,6 @@ public void onItemUseStart(PlayerUseItemEvent.Start event) { EntityPlayer player = event.entityPlayer; ItemStack offhandItem = BackhandUtils.getOffhandItem(player); ItemStack mainhandItem = player.getCurrentEquippedItem(); - - // boolean offHandUse = BattlegearUtils.checkForRightClickFunction(offhandItem); boolean mainhandUse = BackhandUtils.checkForRightClickFunction(mainhandItem); if (offhandItem != null && !mainhandUse) { @@ -90,25 +91,18 @@ public void onArrowNock(ArrowNockEvent event) { if (!Backhand.UseOffhandArrows) { return; } - - boolean overrideWithOffhand = false; - ItemStack offhandItem = BackhandUtils.getOffhandItem(event.entityPlayer); + EntityPlayer player = event.entityPlayer; + ItemStack offhandItem = BackhandUtils.getOffhandItem(player); if (offhandItem != null) { - if (Backhand.isEFRLoaded && offhandItem.getItem() instanceof ItemArrowTipped) { - overrideWithOffhand = true; - } - - if (Items.arrow == offhandItem.getItem()) { - overrideWithOffhand = true; + if (!((RegistrySimple) BlockDispenser.dispenseBehaviorRegistry).containsKey(offhandItem.getItem())) { + return; } - if (overrideWithOffhand) { - event.setCanceled(true); - event.entityPlayer.setItemInUse( - event.result, - event.result.getItem() - .getMaxItemUseDuration(event.result)); - } + event.setCanceled(true); + player.setItemInUse( + event.result, + event.result.getItem() + .getMaxItemUseDuration(event.result)); } } @@ -117,14 +111,15 @@ public void onItemFinish(PlayerUseItemEvent.Finish event) { EntityPlayer player = event.entityPlayer; ItemStack offhandItem = BackhandUtils.getOffhandItem(player); ItemStack mainhandItem = player.getCurrentEquippedItem(); + OffhandExtendedProperty offhandProp = BackhandUtils.getOffhandEP(player); boolean mainhandUse = BackhandUtils.checkForRightClickFunction(mainhandItem); - if (offhandItem == null || mainhandUse) { + if (offhandItem == null || mainhandUse || offhandProp == null) { return; } if (FMLCommonHandler.instance() .getEffectiveSide() == Side.SERVER && !ServerTickHandler.tickStartItems.containsKey(player.getUniqueID())) { BackhandUtils.swapOffhandItem(player); - regularHotSwap = true; + offhandProp.regularHotSwap = true; } } @@ -132,34 +127,29 @@ public void onItemFinish(PlayerUseItemEvent.Finish event) { public void onItemStop(PlayerUseItemEvent.Stop event) { EntityPlayer player = event.entityPlayer; ItemStack mainhandItem = player.getCurrentEquippedItem(); + OffhandExtendedProperty offhandProp = BackhandUtils.getOffhandEP(player); boolean skip = BackhandUtils.checkForRightClickFunction(mainhandItem) || BackhandUtils.getOffhandItem(player) == null; - if (!skip && !ServerTickHandler.tickStartItems.containsKey(player.getUniqueID()) && !regularHotSwap) { + if (!skip && !ServerTickHandler.tickStartItems.containsKey(player.getUniqueID()) + && !offhandProp.regularHotSwap) { BackhandUtils.swapOffhandItem(player); - regularHotSwap = true; + offhandProp.regularHotSwap = true; } if (!Backhand.UseOffhandArrows || !(event.item.getItem() instanceof ItemBow)) { return; } - boolean overrideWithOffhand = false; ItemStack offhandItem = BackhandUtils.getOffhandItem(player); if (offhandItem != null) { - if (Backhand.isEFRLoaded && offhandItem.getItem() instanceof ItemArrowTipped) { - overrideWithOffhand = true; + if (!((RegistrySimple) BlockDispenser.dispenseBehaviorRegistry).containsKey(offhandItem.getItem())) { + return; } - if (Items.arrow == offhandItem.getItem()) { - overrideWithOffhand = true; - } - - if (overrideWithOffhand) { - arrowHotSwapped = true; - if (offhandItem.getItem() != Items.arrow) { - BackhandUtils.swapOffhandItem(event.entityPlayer); - } + offhandProp.arrowHotSwapped = true; + if (offhandItem.getItem() != Items.arrow) { + BackhandUtils.swapOffhandItem(player); } } } diff --git a/src/main/java/xonin/backhand/ServerTickHandler.java b/src/main/java/xonin/backhand/ServerTickHandler.java index cf6dfda..4e48fae 100644 --- a/src/main/java/xonin/backhand/ServerTickHandler.java +++ b/src/main/java/xonin/backhand/ServerTickHandler.java @@ -18,81 +18,76 @@ import cpw.mods.fml.common.gameevent.TickEvent; import cpw.mods.fml.relauncher.Side; import xonin.backhand.api.core.BackhandUtils; +import xonin.backhand.api.core.OffhandExtendedProperty; import xonin.backhand.packet.OffhandSyncItemPacket; -import xonin.backhand.packet.OffhandWorldHotswapPacket; public class ServerTickHandler { public ItemStack prevStackInSlot; public int blacklistDelay = -1; - public static HashMap> tickStartItems = new HashMap<>(); + public static final HashMap> tickStartItems = new HashMap<>(); + + public static void resetTickingHotswap(EntityPlayer player) { + List tickedItems = tickStartItems.get(player.getUniqueID()); + if (tickedItems != null) { + BackhandUtils.getOffhandEP(player).ignoreSetSlot = false; + player.setCurrentItemOrArmor(0, tickedItems.get(0)); + BackhandUtils.setPlayerOffhandItem(player, tickedItems.get(1)); + tickStartItems.remove(player.getUniqueID()); + } + } + + public static void tickHotswap(EntityPlayerMP player) { + ItemStack mainhand = player.getCurrentEquippedItem() == null ? null + : player.getCurrentEquippedItem() + .copy(); + ItemStack offhand = BackhandUtils.getOffhandItem(player); + if (offhand == null || player.currentWindowId != 0) return; + UUID key = player.getUniqueID(); + if (!BackhandUtils.checkForRightClickFunction(mainhand)) { + if (!tickStartItems.containsKey(key)) { + BackhandUtils.getOffhandEP(player).ignoreSetSlot = true; + } + tickStartItems.put(key, Arrays.asList(mainhand, offhand)); + player.setCurrentItemOrArmor( + 0, + tickStartItems.get(key) + .get(1)); + BackhandUtils.getOffhandEP(player).activeSlot = player.inventory.currentItem + + player.inventory.mainInventory.length; + } + } @SubscribeEvent - @SuppressWarnings("unchecked") public void onUpdateWorld(TickEvent.WorldTickEvent event) { if (FMLCommonHandler.instance() .getEffectiveSide() != Side.SERVER) { return; } - if (Backhand.OffhandTickHotswap) { - List players = event.world.playerEntities; - for (EntityPlayer player : players) { - ItemStack mainhand = player.getCurrentEquippedItem() == null ? null - : player.getCurrentEquippedItem() - .copy(); - ItemStack offhand = BackhandUtils.getOffhandItem(player) == null ? null - : BackhandUtils.getOffhandItem(player) - .copy(); - if (offhand == null) { - continue; - } + for (EntityPlayer player : event.world.playerEntities) { + if (!(player instanceof EntityPlayerMP playerMP)) continue; if (event.phase == TickEvent.Phase.START && !player.isUsingItem()) { - if (!BackhandUtils.checkForRightClickFunction(mainhand)) { - if (!tickStartItems.containsKey(player.getUniqueID())) { - Backhand.packetHandler.sendPacketToPlayer( - new OffhandWorldHotswapPacket(true).generatePacket(), - (EntityPlayerMP) player); - } - tickStartItems.put(player.getUniqueID(), Arrays.asList(mainhand, offhand)); - player.setCurrentItemOrArmor( - 0, - tickStartItems.get(player.getUniqueID()) - .get(1)); - } + tickHotswap(playerMP); } else { - ServerTickHandler.resetTickingHotswap(player); + resetTickingHotswap(playerMP); } } } } - public static void resetTickingHotswap(EntityPlayer player) { - if (tickStartItems.containsKey(player.getUniqueID())) { - player.setCurrentItemOrArmor( - 0, - tickStartItems.get(player.getUniqueID()) - .get(0)); - BackhandUtils.setPlayerOffhandItem( - player, - tickStartItems.get(player.getUniqueID()) - .get(1)); - tickStartItems.remove(player.getUniqueID()); - Backhand.packetHandler - .sendPacketToPlayer(new OffhandWorldHotswapPacket(false).generatePacket(), (EntityPlayerMP) player); - } - } - @SubscribeEvent(priority = EventPriority.HIGHEST) public void onUpdatePlayer(TickEvent.PlayerTickEvent event) { EntityPlayer player = event.player; + OffhandExtendedProperty offhandProp = BackhandUtils.getOffhandEP(player); + if (FMLCommonHandler.instance() .getEffectiveSide() != Side.SERVER) { - if (ServerEventsHandler.regularHotSwap) { + if (offhandProp.regularHotSwap) { BackhandUtils.swapOffhandItem(player); - ServerEventsHandler.regularHotSwap = false; + offhandProp.regularHotSwap = false; } return; } @@ -127,22 +122,22 @@ public void onUpdatePlayer(TickEvent.PlayerTickEvent event) { prevStackInSlot = offhand; } - if (BackhandUtils.getOffhandEP(player).syncOffhand) { + if (offhandProp.syncOffhand) { if (!tickStartItems.containsKey(player.getUniqueID())) { Backhand.packetHandler.sendPacketToAll(new OffhandSyncItemPacket(player).generatePacket()); } - BackhandUtils.getOffhandEP(player).syncOffhand = false; + offhandProp.syncOffhand = false; } - if (ServerEventsHandler.arrowHotSwapped) { + if (offhandProp.arrowHotSwapped) { if (offhand != null && offhand.getItem() != Items.arrow) { BackhandUtils.swapOffhandItem(player); } - ServerEventsHandler.arrowHotSwapped = false; + offhandProp.arrowHotSwapped = false; } - if (ServerEventsHandler.regularHotSwap) { + if (offhandProp.regularHotSwap) { BackhandUtils.swapOffhandItem(player); - ServerEventsHandler.regularHotSwap = false; + offhandProp.regularHotSwap = false; } if (ServerEventsHandler.fireworkHotSwapped > 0) { diff --git a/src/main/java/xonin/backhand/api/core/BackhandUtils.java b/src/main/java/xonin/backhand/api/core/BackhandUtils.java index 8eb0037..76e11ee 100644 --- a/src/main/java/xonin/backhand/api/core/BackhandUtils.java +++ b/src/main/java/xonin/backhand/api/core/BackhandUtils.java @@ -5,13 +5,11 @@ import javax.annotation.Nullable; -import net.minecraft.block.Block; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.ai.attributes.BaseAttributeMap; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.Blocks; import net.minecraft.item.EnumAction; import net.minecraft.item.Item; import net.minecraft.item.ItemBed; @@ -38,6 +36,7 @@ import net.minecraft.nbt.NBTSizeTracker; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; +import net.minecraftforge.common.IExtendedEntityProperties; import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.event.ForgeEventFactory; import net.minecraftforge.event.entity.player.AttackEntityEvent; @@ -110,7 +109,13 @@ public static void setPlayerOffhandItem(EntityPlayer player, ItemStack stack) { } public static OffhandExtendedProperty getOffhandEP(EntityPlayer player) { - return ((OffhandExtendedProperty) player.getExtendedProperties("OffhandStorage")); + IExtendedEntityProperties prop = player.getExtendedProperties("OffhandStorage"); + + if (prop instanceof OffhandExtendedProperty offhandProp) { + return offhandProp; + } + // Probably a fake player, return a dummy property + return new OffhandExtendedProperty(player); } /** @@ -240,33 +245,6 @@ public static boolean isItemBlock(Item item) { || item instanceof ItemSkull; } - public static boolean blockHasUse(Block block) { - if (block == null || block == Blocks.air) { - return false; - } - try { - String mappedName = BackhandTranslator.getMapedMethodName("Block", "func_149727_a", "onBlockActivated"); - Class[] classParams = new Class[] { World.class, int.class, int.class, int.class, EntityPlayer.class, - int.class, float.class, float.class, float.class }; - - Class c = block.getClass(); - while (!(c.equals(Block.class))) { - try { - try { - c.getDeclaredMethod(mappedName, classParams); - return true; - } catch (NoSuchMethodException ignored) {} - } catch (NoClassDefFoundError ignored) {} - - c = c.getSuperclass(); - } - - return false; - } catch (NullPointerException e) { - return true; - } - } - @SuppressWarnings("unchecked") public static boolean hasEntityInteraction(ItemStack stack) { if (stack == null) { diff --git a/src/main/java/xonin/backhand/api/core/OffhandExtendedProperty.java b/src/main/java/xonin/backhand/api/core/OffhandExtendedProperty.java index 3e20e20..c4ca623 100644 --- a/src/main/java/xonin/backhand/api/core/OffhandExtendedProperty.java +++ b/src/main/java/xonin/backhand/api/core/OffhandExtendedProperty.java @@ -12,6 +12,10 @@ public class OffhandExtendedProperty implements IExtendedEntityProperties { public EntityPlayer player; public boolean syncOffhand = true; private ItemStack offhandItem; + public boolean ignoreSetSlot = false; + public int activeSlot = -1; + public boolean arrowHotSwapped = false; + public boolean regularHotSwap = false; public OffhandExtendedProperty(EntityPlayer player) { this.player = player; diff --git a/src/main/java/xonin/backhand/client/BackhandClientTickHandler.java b/src/main/java/xonin/backhand/client/BackhandClientTickHandler.java index 1e2b33b..5bc8523 100644 --- a/src/main/java/xonin/backhand/client/BackhandClientTickHandler.java +++ b/src/main/java/xonin/backhand/client/BackhandClientTickHandler.java @@ -121,8 +121,7 @@ public boolean tryCheckUseItem(ItemStack offhandItem, EntityPlayer player) { } if (mouseOver != null && mouseOver.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) { - if (BackhandUtils - .blockHasUse(player.worldObj.getBlock(mouseOver.blockX, mouseOver.blockY, mouseOver.blockZ)) + if (BackhandClientUtils.canBlockBeInteractedWith(mouseOver.blockX, mouseOver.blockY, mouseOver.blockZ) && !BackhandUtils.getOffhandItem(player) .getItem() .doesSneakBypassUse(player.worldObj, mouseOver.blockX, mouseOver.blockY, mouseOver.blockZ, player) @@ -302,13 +301,7 @@ public static void tryBreakBlockOffhand(MovingObjectPosition objectMouseOver, It && (offhandItem == null || !(offhandItem.getItem() instanceof ItemSword))) { PlayerControllerMP .clickBlockCreative(mcInstance, mcInstance.playerController, i, j, k, objectMouseOver.sideHit); - HookContainerClass.sendOffSwingEventNoCheck(event.player, mainHandItem, offhandItem); // force - // offhand - // swing - // anyway - // because we - // broke a - // block + HookContainerClass.sendOffSwingEventNoCheck(event.player, mainHandItem, offhandItem); mcInstance.getNetHandler() .addToSendQueue(new C07PacketPlayerDigging(2, i, j, k, objectMouseOver.sideHit)); } diff --git a/src/main/java/xonin/backhand/client/ClientEventHandler.java b/src/main/java/xonin/backhand/client/ClientEventHandler.java index 1167d25..e39eda9 100644 --- a/src/main/java/xonin/backhand/client/ClientEventHandler.java +++ b/src/main/java/xonin/backhand/client/ClientEventHandler.java @@ -28,7 +28,6 @@ public class ClientEventHandler { public static RenderOffhandPlayer renderOffhandPlayer = new RenderOffhandPlayer(); public static EntityPlayer renderingPlayer; - public static boolean cancelone = false; @SubscribeEvent public void renderHotbarOverlay(RenderGameOverlayEvent event) { @@ -113,12 +112,10 @@ public void onRenderHand(RenderHandEvent event) { */ @SubscribeEvent(priority = EventPriority.LOW) public void renderPlayerLeftItemUsage(RenderLivingEvent.Pre event) { - if (event.entity instanceof EntityPlayer) { - EntityPlayer entityPlayer = (EntityPlayer) event.entity; + if (event.entity instanceof EntityPlayer entityPlayer) { renderingPlayer = entityPlayer; ItemStack offhand = BackhandUtils.getOffhandItem(entityPlayer); - if (offhand != null && event.renderer instanceof RenderPlayer) { - RenderPlayer renderer = ((RenderPlayer) event.renderer); + if (offhand != null && event.renderer instanceof RenderPlayer renderer) { renderer.modelArmorChestplate.heldItemLeft = renderer.modelArmor.heldItemLeft = renderer.modelBipedMain.heldItemLeft = 1; if (entityPlayer.getItemInUseCount() > 0 && entityPlayer.getItemInUse() == offhand) { EnumAction enumaction = offhand.getItemUseAction(); diff --git a/src/main/java/xonin/backhand/client/ClientProxy.java b/src/main/java/xonin/backhand/client/ClientProxy.java index 66f77c8..5fb7545 100644 --- a/src/main/java/xonin/backhand/client/ClientProxy.java +++ b/src/main/java/xonin/backhand/client/ClientProxy.java @@ -4,7 +4,6 @@ import net.minecraft.client.entity.EntityClientPlayerMP; import net.minecraft.client.settings.KeyBinding; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; import org.lwjgl.input.Keyboard; @@ -35,11 +34,6 @@ public void load() { ClientRegistry.registerKeyBinding(swapOffhand); } - @Override - public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { - return null; - } - @Override public EntityPlayer getClientPlayer() { return Minecraft.getMinecraft().thePlayer; diff --git a/src/main/java/xonin/backhand/client/ClientTickHandler.java b/src/main/java/xonin/backhand/client/ClientTickHandler.java index 84b63b4..a9e6e26 100644 --- a/src/main/java/xonin/backhand/client/ClientTickHandler.java +++ b/src/main/java/xonin/backhand/client/ClientTickHandler.java @@ -17,6 +17,7 @@ import xonin.backhand.Backhand; import xonin.backhand.HookContainerClass; import xonin.backhand.api.core.BackhandUtils; +import xonin.backhand.client.utils.BackhandClientUtils; import xonin.backhand.packet.OffhandSwapPacket; public class ClientTickHandler { @@ -122,10 +123,7 @@ public void clientHelper(TickEvent.PlayerTickEvent event) { && mc.objectMouseOver.typeOfHit != MovingObjectPosition.MovingObjectType.ENTITY) { if (event.player.capabilities.allowEdit) { if (Backhand.proxy.isRightClickHeld() - && !(mainHandItem != null && BackhandUtils.isItemBlock(mainHandItem.getItem()))) { // if it's a - // block and we - // should try - // break it + && !(mainHandItem != null && BackhandUtils.isItemBlock(mainHandItem.getItem()))) { MovingObjectPosition mop = HookContainerClass.getRaytraceBlock(event.player); if (offhandItem != null && HookContainerClass.isItemBlock(offhandItem.getItem())) { if (!BackhandUtils.usagePriorAttack(offhandItem) && mop != null) { @@ -136,8 +134,7 @@ public void clientHelper(TickEvent.PlayerTickEvent event) { } } else { if (mop != null && !BackhandUtils.usagePriorAttack(offhandItem) - && !HookContainerClass - .canBlockBeInteractedWith(mc.theWorld, mop.blockX, mop.blockY, mop.blockZ)) { + && !BackhandClientUtils.canBlockBeInteractedWith(mop.blockX, mop.blockY, mop.blockZ)) { BackhandClientTickHandler.tryBreakBlockOffhand(mop, offhandItem, mainHandItem, event); Backhand.proxy.setLeftClickCounter(10); } else { diff --git a/src/main/java/xonin/backhand/client/renderer/RenderOffhandPlayer.java b/src/main/java/xonin/backhand/client/renderer/RenderOffhandPlayer.java index 7699e27..3a0fc45 100644 --- a/src/main/java/xonin/backhand/client/renderer/RenderOffhandPlayer.java +++ b/src/main/java/xonin/backhand/client/renderer/RenderOffhandPlayer.java @@ -54,8 +54,7 @@ protected void func_96449_a(AbstractClientPlayer p_96449_1_, double p_96449_2_, public void updateFovModifierHand() { Minecraft mc = Minecraft.getMinecraft(); - if (mc.renderViewEntity instanceof EntityPlayerSP) { - EntityPlayerSP entityplayersp = (EntityPlayerSP) mc.renderViewEntity; + if (mc.renderViewEntity instanceof EntityPlayerSP entityplayersp) { this.fovMultiplierTemp = entityplayersp.getFOVMultiplier(); } else { this.fovMultiplierTemp = mc.thePlayer.getFOVMultiplier(); @@ -87,13 +86,10 @@ public void renderOffhandItem(ItemRenderer otherItemRenderer, float frame) { otherItemRenderer.equippedProgress = itemRenderer.equippedProgress; otherItemRenderer.prevEquippedProgress = itemRenderer.prevEquippedProgress; - EntityClientPlayerMP entityclientplayermp = mc.thePlayer; - float f3 = entityclientplayermp.prevRenderArmPitch - + (entityclientplayermp.renderArmPitch - entityclientplayermp.prevRenderArmPitch) * frame; - float f4 = entityclientplayermp.prevRenderArmYaw - + (entityclientplayermp.renderArmYaw - entityclientplayermp.prevRenderArmYaw) * frame; - GL11.glRotatef((entityclientplayermp.rotationPitch - f3) * -0.1F, 1.0F, 0.0F, 0.0F); - GL11.glRotatef((entityclientplayermp.rotationYaw - f4) * -0.1F, 0.0F, 1.0F, 0.0F); + float f3 = player.prevRenderArmPitch + (player.renderArmPitch - player.prevRenderArmPitch) * frame; + float f4 = player.prevRenderArmYaw + (player.renderArmYaw - player.prevRenderArmYaw) * frame; + GL11.glRotatef((player.rotationPitch - f3) * -0.1F, 1.0F, 0.0F, 0.0F); + GL11.glRotatef((player.rotationYaw - f4) * -0.1F, 0.0F, 1.0F, 0.0F); otherItemRenderer.renderItemInFirstPerson(frame); diff --git a/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java b/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java index 84e3f43..3197da1 100644 --- a/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java +++ b/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java @@ -1,23 +1,24 @@ package xonin.backhand.client.utils; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityOtherPlayerMP; +import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; +import net.minecraft.util.MovingObjectPosition; import xonin.backhand.api.core.BackhandUtils; +import xonin.backhand.client.world.ClientFakePlayer; +import xonin.backhand.client.world.DummyWorld; public final class BackhandClientUtils { public static boolean disableMainhandAnimation = false; public static int countToCancel = 0; - public static float onGround2; public static float firstPersonFrame; public static boolean offhandFPRender; - public static boolean ignoreSetSlot = false; public static boolean receivedConfigs = false; - /** If we have hotswapped the breaking item with the one in offhand and should hotswap it back when called next */ - public static boolean hotSwapped = false; - /** * Patch over EntityOtherPlayerMP#onUpdate() to update isItemInUse field * @@ -39,4 +40,25 @@ public static boolean entityOtherPlayerIsItemInUseHook(EntityOtherPlayerMP playe return isItemInUse; } } + + public static boolean canBlockBeInteractedWith(int x, int y, int z) { + Minecraft mc = Minecraft.getMinecraft(); + MovingObjectPosition mop = mc.objectMouseOver; + + if (mop == null) return false; + + float subX = (float) mc.objectMouseOver.hitVec.xCoord - x; + float subY = (float) mc.objectMouseOver.hitVec.yCoord - y; + float subZ = (float) mc.objectMouseOver.hitVec.zCoord - z; + + Block block = mc.theWorld.getBlock(x, y, z); + + if (block == null || block == Blocks.air) return false; + + int meta = mc.theWorld.getBlockMetadata(x, y, z); + DummyWorld.INSTANCE.setBlock(x, y, z, block, meta, 3); + + return block + .onBlockActivated(DummyWorld.INSTANCE, x, y, z, ClientFakePlayer.INSTANCE, mop.sideHit, subX, subY, subZ); + } } diff --git a/src/main/java/xonin/backhand/client/world/ClientFakePlayer.java b/src/main/java/xonin/backhand/client/world/ClientFakePlayer.java new file mode 100644 index 0000000..e21a34b --- /dev/null +++ b/src/main/java/xonin/backhand/client/world/ClientFakePlayer.java @@ -0,0 +1,68 @@ +package xonin.backhand.client.world; + +import java.util.UUID; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.stats.StatBase; +import net.minecraft.util.ChunkCoordinates; +import net.minecraft.util.DamageSource; +import net.minecraft.util.IChatComponent; +import net.minecraft.world.World; + +import com.mojang.authlib.GameProfile; + +public class ClientFakePlayer extends EntityPlayer { + + public static final ClientFakePlayer INSTANCE = new ClientFakePlayer(); + + public ClientFakePlayer() { + super(DummyWorld.INSTANCE, new GameProfile(UUID.randomUUID(), "[BackhandClient]")); + } + + @Override + public void addChatMessage(IChatComponent message) {} + + @Override + public boolean canCommandSenderUseCommand(int i, String s) { + return false; + } + + @Override + public ChunkCoordinates getPlayerCoordinates() { + return new ChunkCoordinates(0, 0, 0); + } + + @Override + public void addChatComponentMessage(IChatComponent message) {} + + @Override + public void addStat(StatBase par1StatBase, int par2) {} + + @Override + public void openGui(Object mod, int modGuiId, World world, int x, int y, int z) {} + + @Override + public boolean isEntityInvulnerable() { + return true; + } + + @Override + public boolean canAttackPlayer(EntityPlayer player) { + return false; + } + + @Override + public void onDeath(DamageSource source) { + return; + } + + @Override + public void onUpdate() { + return; + } + + @Override + public void travelToDimension(int dim) { + return; + } +} diff --git a/src/main/java/xonin/backhand/client/world/DummyChunkProvider.java b/src/main/java/xonin/backhand/client/world/DummyChunkProvider.java new file mode 100644 index 0000000..50222c8 --- /dev/null +++ b/src/main/java/xonin/backhand/client/world/DummyChunkProvider.java @@ -0,0 +1,97 @@ +package xonin.backhand.client.world; + +import java.util.List; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import net.minecraft.entity.EnumCreatureType; +import net.minecraft.util.IProgressUpdate; +import net.minecraft.util.LongHashMap; +import net.minecraft.world.ChunkCoordIntPair; +import net.minecraft.world.ChunkPosition; +import net.minecraft.world.World; +import net.minecraft.world.biome.BiomeGenBase; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.IChunkProvider; + +public class DummyChunkProvider implements IChunkProvider { + + private final World world; + private LongHashMap loadedChunks = new LongHashMap(); + + public DummyChunkProvider(World world) { + this.world = world; + } + + @Nullable + @Override + public Chunk loadChunk(int x, int z) { + return (Chunk) loadedChunks.getValueByKey(ChunkCoordIntPair.chunkXZ2Int(x, z)); + } + + @Nonnull + @Override + public Chunk provideChunk(int x, int z) { + long chunkKey = ChunkCoordIntPair.chunkXZ2Int(x, z); + if (loadedChunks.containsItem(chunkKey)) { + return (Chunk) loadedChunks.getValueByKey(chunkKey); + } + + Chunk chunk = new Chunk(world, x, z); + loadedChunks.add(chunkKey, chunk); + return chunk; + } + + @Override + public void populate(IChunkProvider p_73153_1_, int p_73153_2_, int p_73153_3_) {} + + @Override + public boolean saveChunks(boolean p_73151_1_, IProgressUpdate p_73151_2_) { + return false; + } + + @Override + public boolean unloadQueuedChunks() { + return false; + } + + @Override + public boolean canSave() { + return false; + } + + @Nonnull + @Override + public String makeString() { + return "Dummy"; + } + + @Override + public List getPossibleCreatures(EnumCreatureType p_73155_1_, int p_73155_2_, + int p_73155_3_, int p_73155_4_) { + return null; + } + + @Override + public ChunkPosition func_147416_a(World p_147416_1_, String p_147416_2_, int p_147416_3_, int p_147416_4_, + int p_147416_5_) { + return null; + } + + @Override + public int getLoadedChunkCount() { + return 0; + } + + @Override + public void recreateStructures(int p_82695_1_, int p_82695_2_) {} + + @Override + public void saveExtraData() {} + + @Override + public boolean chunkExists(int x, int z) { + return true; + } +} diff --git a/src/main/java/xonin/backhand/client/world/DummySaveHandler.java b/src/main/java/xonin/backhand/client/world/DummySaveHandler.java new file mode 100644 index 0000000..a7789a3 --- /dev/null +++ b/src/main/java/xonin/backhand/client/world/DummySaveHandler.java @@ -0,0 +1,99 @@ +package xonin.backhand.client.world; + +import java.io.File; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.World; +import net.minecraft.world.WorldProvider; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.storage.IChunkLoader; +import net.minecraft.world.storage.IPlayerFileData; +import net.minecraft.world.storage.ISaveHandler; +import net.minecraft.world.storage.WorldInfo; + +public class DummySaveHandler implements ISaveHandler, IPlayerFileData, IChunkLoader { + + @Nullable + @Override + public WorldInfo loadWorldInfo() { + return null; + } + + @Override + public void checkSessionLock() {} + + @Nonnull + @Override + public IChunkLoader getChunkLoader(@Nonnull WorldProvider provider) { + return this; + } + + @Nonnull + @Override + public IPlayerFileData getSaveHandler() { + return this; + } + + @Override + public void saveWorldInfoWithPlayer(@Nonnull WorldInfo worldInformation, @Nonnull NBTTagCompound tagCompound) {} + + @Override + public void saveWorldInfo(@Nonnull WorldInfo worldInformation) {} + + @Nonnull + @Override + public File getWorldDirectory() { + return null; + } + + @Nonnull + @Override + public File getMapFileFromName(@Nonnull String mapName) { + return null; + } + + @Override + public String getWorldDirectoryName() { + return null; + } + + @Nullable + @Override + public Chunk loadChunk(@Nonnull World worldIn, int x, int z) { + return null; + } + + @Override + public void saveChunk(@Nonnull World worldIn, @Nonnull Chunk chunkIn) {} + + @Override + public void saveExtraChunkData(@Nonnull World worldIn, @Nonnull Chunk chunkIn) {} + + @Override + public void chunkTick() {} + + @Override + public void saveExtraData() {} + + @Override + public void flush() {} + + @Override + public void writePlayerData(@Nonnull EntityPlayer player) {} + + @Nullable + @Override + public NBTTagCompound readPlayerData(@Nonnull EntityPlayer player) { + return null; + } + + @Nonnull + @Override + public String[] getAvailablePlayerDat() { + return new String[0]; + } +} diff --git a/src/main/java/xonin/backhand/client/world/DummyWorld.java b/src/main/java/xonin/backhand/client/world/DummyWorld.java new file mode 100644 index 0000000..ac9337b --- /dev/null +++ b/src/main/java/xonin/backhand/client/world/DummyWorld.java @@ -0,0 +1,68 @@ +package xonin.backhand.client.world; + +import javax.annotation.Nonnull; + +import net.minecraft.entity.Entity; +import net.minecraft.profiler.Profiler; +import net.minecraft.world.EnumSkyBlock; +import net.minecraft.world.World; +import net.minecraft.world.WorldProviderSurface; +import net.minecraft.world.WorldSettings; +import net.minecraft.world.WorldType; +import net.minecraft.world.chunk.IChunkProvider; + +public class DummyWorld extends World { + + private static final WorldSettings DEFAULT_SETTINGS = new WorldSettings( + 1L, + WorldSettings.GameType.SURVIVAL, + true, + false, + WorldType.DEFAULT); + + public static final DummyWorld INSTANCE = new DummyWorld(); + + public DummyWorld() { + super(new DummySaveHandler(), "DummyServer", DEFAULT_SETTINGS, new WorldProviderSurface(), new Profiler()); + // Guarantee the dimension ID was not reset by the provider + this.provider.setDimension(Integer.MAX_VALUE); + int providerDim = this.provider.dimensionId; + this.provider.worldObj = this; + this.provider.setDimension(providerDim); + this.chunkProvider = this.createChunkProvider(); + this.calculateInitialSkylight(); + this.calculateInitialWeatherBody(); + } + + @Override + public void updateEntities() {} + + @Override + public void markBlockRangeForRenderUpdate(int x1, int y1, int z1, int x2, int y2, int z2) {} + + @Override + protected int func_152379_p() { + return 0; + } + + @Override + public Entity getEntityByID(int p_73045_1_) { + return null; + } + + @Nonnull + @Override + protected IChunkProvider createChunkProvider() { + return new DummyChunkProvider(this); + } + + @Override + protected boolean chunkExists(int x, int z) { + return chunkProvider.chunkExists(x, z); + } + + @Override + public boolean updateLightByType(EnumSkyBlock p_147463_1_, int p_147463_2_, int p_147463_3_, int p_147463_4_) { + return true; + } +} diff --git a/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java b/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java index e95e7bf..6083985 100644 --- a/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java +++ b/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java @@ -47,6 +47,7 @@ public List getMixins(Set loadedCoreMods) { mixins.add("MixinEntityPlayerMP"); mixins.add("MixinItemStack"); mixins.add("MixinNetHandlerPlayServer"); + mixins.add("MixinEntityItem"); if (FMLLaunchHandler.side() .isClient()) { mixins.add("MixinEntityOtherPlayerMP"); diff --git a/src/main/java/xonin/backhand/mixins/early/MixinEntityItem.java b/src/main/java/xonin/backhand/mixins/early/MixinEntityItem.java new file mode 100644 index 0000000..6bd933d --- /dev/null +++ b/src/main/java/xonin/backhand/mixins/early/MixinEntityItem.java @@ -0,0 +1,27 @@ +package xonin.backhand.mixins.early; + +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.player.EntityPlayer; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import xonin.backhand.ServerTickHandler; +import xonin.backhand.api.core.BackhandUtils; + +@Mixin(EntityItem.class) +public abstract class MixinEntityItem { + + @Inject( + method = "onCollideWithPlayer", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/entity/item/EntityItem;getEntityItem()Lnet/minecraft/item/ItemStack;")) + private void backhand$resetHotswapOnPickup(EntityPlayer entityIn, CallbackInfo ci) { + if (BackhandUtils.getOffhandItem(entityIn) != null) { + ServerTickHandler.resetTickingHotswap(entityIn); + } + } +} diff --git a/src/main/java/xonin/backhand/mixins/early/MixinItemRenderer.java b/src/main/java/xonin/backhand/mixins/early/MixinItemRenderer.java index 230a18e..5ad5af5 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinItemRenderer.java +++ b/src/main/java/xonin/backhand/mixins/early/MixinItemRenderer.java @@ -43,7 +43,6 @@ public abstract class MixinItemRenderer { } BackhandClientUtils.firstPersonFrame = frame; - BackhandClientUtils.onGround2 = 0; RenderOffhandPlayer.itemRenderer.updateEquippedItem(); BackhandClientUtils.offhandFPRender = true; GL11.glEnable(GL11.GL_CULL_FACE); diff --git a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayClient.java b/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayClient.java index 8a6ee23..fa0be3e 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayClient.java +++ b/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayClient.java @@ -1,17 +1,13 @@ package xonin.backhand.mixins.early; import net.minecraft.client.network.NetHandlerPlayClient; -import net.minecraft.network.play.server.S2FPacketSetSlot; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import xonin.backhand.api.core.InventoryPlayerBackhand; -import xonin.backhand.client.utils.BackhandClientUtils; @Mixin(NetHandlerPlayClient.class) public abstract class MixinNetHandlerPlayClient { @@ -26,17 +22,4 @@ public abstract class MixinNetHandlerPlayClient { // return a valid int e.g. between 0 and < 9 return InventoryPlayerBackhand.isValidSwitch(original) ? 0 : -1; } - - @Inject( - method = "handleSetSlot", - at = @At( - value = "FIELD", - target = "Lnet/minecraft/client/Minecraft;currentScreen:Lnet/minecraft/client/gui/GuiScreen;", - ordinal = 0), - cancellable = true) - private void backhand$checkIfIgnore(S2FPacketSetSlot packetIn, CallbackInfo ci) { - if (BackhandClientUtils.ignoreSetSlot) { - ci.cancel(); - } - } } diff --git a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java b/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java index 6d7fa4e..c59bd30 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java +++ b/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java @@ -1,8 +1,12 @@ package xonin.backhand.mixins.early; import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; import net.minecraft.network.NetHandlerPlayServer; +import net.minecraft.network.Packet; import net.minecraft.network.play.client.C02PacketUseEntity; +import net.minecraft.network.play.client.C07PacketPlayerDigging; +import net.minecraft.network.play.server.S2FPacketSetSlot; import net.minecraft.server.management.ItemInWorldManager; import org.spongepowered.asm.mixin.Mixin; @@ -10,7 +14,6 @@ import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import com.llamalad7.mixinextras.injector.ModifyExpressionValue; @@ -35,33 +38,39 @@ public abstract class MixinNetHandlerPlayServer { return InventoryPlayerBackhand.isValidSwitch(original) ? 0 : -1; } - @Redirect( + @Inject( method = "processPlayerDigging", at = @At( value = "INVOKE", target = "Lnet/minecraft/server/management/ItemInWorldManager;uncheckedTryHarvestBlock(III)V")) - private void backhand$playerDigging(ItemInWorldManager instance, int x, int y, int z) { + private void backhand$playerDigging(C07PacketPlayerDigging packetIn, CallbackInfo ci) { + ItemInWorldManager instance = playerEntity.theItemInWorldManager; + int x = packetIn.func_149505_c(); + int y = packetIn.func_149503_d(); + int z = packetIn.func_149502_e(); instance.theWorld.destroyBlockInWorldPartially(instance.thisPlayerMP.getEntityId(), x, y, z, -1); instance.tryHarvestBlock(x, y, z); } @Inject( method = "processUseEntity", - at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/EntityPlayerMP;func_143004_u()V")) - private void backhand$swapOnProcess(C02PacketUseEntity packetIn, CallbackInfo ci) { + at = { + @At( + value = "INVOKE", + target = "Lnet/minecraft/network/NetHandlerPlayServer;kickPlayerFromServer(Ljava/lang/String;)V"), + @At(value = "TAIL"), @At("HEAD") }) + private void backhand$hotswapOnEntityInteract(C02PacketUseEntity packetIn, CallbackInfo ci) { if (backhand$swapOffhand(packetIn.func_149565_c())) { BackhandUtils.swapOffhandItem(playerEntity); } } - @Inject( - method = "processUseEntity", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/network/NetHandlerPlayServer;kickPlayerFromServer(Ljava/lang/String;)V")) - private void backhand$swapOnKick(C02PacketUseEntity packetIn, CallbackInfo ci) { - if (backhand$swapOffhand(packetIn.func_149565_c())) { - BackhandUtils.swapOffhandItem(playerEntity); + @Inject(method = "sendPacket", at = @At(value = "HEAD"), cancellable = true) + private void backhand$skipSetSlotOnHotswap(Packet packetIn, CallbackInfo ci) { + if (packetIn instanceof S2FPacketSetSlot setSlotPacket) { + if (backhand$shouldSkipSetSlot(setSlotPacket)) { + ci.cancel(); + } } } @@ -71,4 +80,17 @@ public abstract class MixinNetHandlerPlayServer { && !BackhandUtils.checkForRightClickFunction(playerEntity.getCurrentEquippedItem()) && action == C02PacketUseEntity.Action.INTERACT; } + + @Unique + private boolean backhand$shouldSkipSetSlot(S2FPacketSetSlot setSlotPacket) { + int packetWindowId = setSlotPacket.field_149179_a; + int packetSlot = setSlotPacket.field_149177_b; + ItemStack packetStack = setSlotPacket.field_149178_c; + ItemStack offhandStack = BackhandUtils.getOffhandItem(playerEntity); + return offhandStack != null && BackhandUtils.getOffhandEP(playerEntity).ignoreSetSlot + && packetStack != null + && packetSlot == BackhandUtils.getOffhandEP(playerEntity).activeSlot + && packetStack.getItem() == offhandStack.getItem() + && packetWindowId != -1; + } } diff --git a/src/main/java/xonin/backhand/mixins/early/MixinPlayerControllerMP.java b/src/main/java/xonin/backhand/mixins/early/MixinPlayerControllerMP.java index 2f8fd69..6dc2595 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinPlayerControllerMP.java +++ b/src/main/java/xonin/backhand/mixins/early/MixinPlayerControllerMP.java @@ -1,10 +1,8 @@ package xonin.backhand.mixins.early; -import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.PlayerControllerMP; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -12,41 +10,16 @@ import com.llamalad7.mixinextras.injector.ModifyReturnValue; import xonin.backhand.client.BackhandClientTickHandler; -import xonin.backhand.client.ClientEventHandler; import xonin.backhand.client.utils.BackhandClientUtils; @Mixin(PlayerControllerMP.class) public abstract class MixinPlayerControllerMP { - @Shadow - public abstract void resetBlockRemoving(); - @Inject(method = "resetBlockRemoving", at = @At("HEAD"), cancellable = true) private void backhand$cancelRemoval(CallbackInfo ci) { if (BackhandClientUtils.countToCancel > 0) { BackhandClientUtils.countToCancel--; ci.cancel(); - } else { - if (BackhandClientUtils.hotSwapped) { - Minecraft.getMinecraft().playerController.syncCurrentPlayItem(); - BackhandClientUtils.hotSwapped = false; - } - } - } - - @Inject(method = "clickBlock", at = @At("HEAD"), cancellable = true) - private void backhand$clickBlock(CallbackInfo ci) { - if (ClientEventHandler.cancelone) { - resetBlockRemoving(); - ci.cancel(); - } - } - - @Inject(method = "onPlayerDamageBlock", at = @At("HEAD"), cancellable = true) - private void backhand$onPlayerDamageBlock(CallbackInfo ci) { - if (ClientEventHandler.cancelone) { - resetBlockRemoving(); - ci.cancel(); } } diff --git a/src/main/java/xonin/backhand/packet/BackhandPacketHandler.java b/src/main/java/xonin/backhand/packet/BackhandPacketHandler.java index ec0d290..28b422a 100644 --- a/src/main/java/xonin/backhand/packet/BackhandPacketHandler.java +++ b/src/main/java/xonin/backhand/packet/BackhandPacketHandler.java @@ -29,7 +29,6 @@ public BackhandPacketHandler() { map.put(OffhandSwapPacket.packetName, new OffhandSwapPacket()); map.put(OffhandSwapClientPacket.packetName, new OffhandSwapClientPacket()); map.put(OffhandAttackPacket.packetName, new OffhandAttackPacket()); - map.put(OffhandWorldHotswapPacket.packetName, new OffhandWorldHotswapPacket()); map.put(OffhandConfigSyncPacket.packetName, new OffhandConfigSyncPacket()); } diff --git a/src/main/java/xonin/backhand/packet/OffhandWorldHotswapPacket.java b/src/main/java/xonin/backhand/packet/OffhandWorldHotswapPacket.java deleted file mode 100644 index a950eb0..0000000 --- a/src/main/java/xonin/backhand/packet/OffhandWorldHotswapPacket.java +++ /dev/null @@ -1,34 +0,0 @@ -package xonin.backhand.packet; - -import net.minecraft.entity.player.EntityPlayer; - -import io.netty.buffer.ByteBuf; -import xonin.backhand.client.utils.BackhandClientUtils; - -public class OffhandWorldHotswapPacket extends AbstractPacket { - - public static final String packetName = "MB2|WorldHotswap"; - - boolean ignoreSwitching; - - public OffhandWorldHotswapPacket() {} - - public OffhandWorldHotswapPacket(boolean bool) { - this.ignoreSwitching = bool; - } - - @Override - public String getChannel() { - return packetName; - } - - @Override - public void write(ByteBuf out) { - out.writeBoolean(this.ignoreSwitching); - } - - @Override - public void process(ByteBuf inputStream, EntityPlayer player) { - BackhandClientUtils.ignoreSetSlot = inputStream.readBoolean(); - } -} diff --git a/src/main/resources/META-INF/backhand_at.cfg b/src/main/resources/META-INF/backhand_at.cfg index 32f4d8a..1ac515b 100644 --- a/src/main/resources/META-INF/backhand_at.cfg +++ b/src/main/resources/META-INF/backhand_at.cfg @@ -46,3 +46,7 @@ public net.minecraft.client.gui.inventory.GuiContainer field_147009_r # guiTop ( public net.minecraft.client.gui.inventory.GuiContainer field_146999_f # xSize (1.6 field_74194_b) public net.minecraft.client.gui.inventory.GuiContainer field_147000_g # ySize (1.6 field_74195_c) public net.minecraft.client.gui.GuiScreen field_146292_n # buttonList (1.6 field_73887_h) +# S2FPacketSetSlot +public net.minecraft.network.play.server.S2FPacketSetSlot field_149179_a # field_149179_a / windowId +public net.minecraft.network.play.server.S2FPacketSetSlot field_149177_b # field_149177_b / slot +public net.minecraft.network.play.server.S2FPacketSetSlot field_149178_c # field_149178_c / itemStack From 555da77101ab63b31b851dfb67ddd0909854530c Mon Sep 17 00:00:00 2001 From: Lyfts <127234178+Lyfts@users.noreply.github.com> Date: Tue, 30 Jul 2024 19:59:04 +0200 Subject: [PATCH 02/16] Stop hotswapping when player interacts with an entity & is using an item --- .../early/MixinNetHandlerPlayServer.java | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java b/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java index c59bd30..c7a9ad9 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java +++ b/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java @@ -27,6 +27,9 @@ public abstract class MixinNetHandlerPlayServer { @Shadow public EntityPlayerMP playerEntity; + @Unique + private boolean backhand$swappedOffhand = false; + @ModifyExpressionValue( method = "processHeldItemChange", at = @At( @@ -52,17 +55,25 @@ public abstract class MixinNetHandlerPlayServer { instance.tryHarvestBlock(x, y, z); } + @Inject(method = "processUseEntity", at = @At("HEAD")) + private void backhand$hotswapOnEntityInteract(C02PacketUseEntity packetIn, CallbackInfo ci) { + if (backhand$shouldSwapOffhand(packetIn.func_149565_c())) { + BackhandUtils.swapOffhandItem(playerEntity); + } + } + @Inject( method = "processUseEntity", at = { @At( value = "INVOKE", target = "Lnet/minecraft/network/NetHandlerPlayServer;kickPlayerFromServer(Ljava/lang/String;)V"), - @At(value = "TAIL"), @At("HEAD") }) - private void backhand$hotswapOnEntityInteract(C02PacketUseEntity packetIn, CallbackInfo ci) { - if (backhand$swapOffhand(packetIn.func_149565_c())) { + @At(value = "TAIL") }) + private void backhand$swapBackPostEntityInteract(C02PacketUseEntity packetIn, CallbackInfo ci) { + if (backhand$swappedOffhand) { BackhandUtils.swapOffhandItem(playerEntity); } + backhand$swappedOffhand = false; } @Inject(method = "sendPacket", at = @At(value = "HEAD"), cancellable = true) @@ -75,8 +86,9 @@ public abstract class MixinNetHandlerPlayServer { } @Unique - private boolean backhand$swapOffhand(C02PacketUseEntity.Action action) { - return BackhandUtils.checkForRightClickFunction(BackhandUtils.getOffhandItem(playerEntity)) + private boolean backhand$shouldSwapOffhand(C02PacketUseEntity.Action action) { + return !playerEntity.isUsingItem() + && BackhandUtils.checkForRightClickFunction(BackhandUtils.getOffhandItem(playerEntity)) && !BackhandUtils.checkForRightClickFunction(playerEntity.getCurrentEquippedItem()) && action == C02PacketUseEntity.Action.INTERACT; } From 9989899c157cee59eb4642af143f4907a28d7f20 Mon Sep 17 00:00:00 2001 From: Lyfts <127234178+Lyfts@users.noreply.github.com> Date: Tue, 30 Jul 2024 20:30:06 +0200 Subject: [PATCH 03/16] Fix some blocks not dropping after being harvested with offhand --- .../backhand/api/core/InventoryPlayerBackhand.java | 13 +++++++++++++ .../backhand/client/utils/BackhandClientUtils.java | 8 ++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/main/java/xonin/backhand/api/core/InventoryPlayerBackhand.java b/src/main/java/xonin/backhand/api/core/InventoryPlayerBackhand.java index 0084570..818ce36 100644 --- a/src/main/java/xonin/backhand/api/core/InventoryPlayerBackhand.java +++ b/src/main/java/xonin/backhand/api/core/InventoryPlayerBackhand.java @@ -1,5 +1,6 @@ package xonin.backhand.api.core; +import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.item.Item; @@ -137,6 +138,18 @@ public void dropAllItems() { this.setOffhandItem(null); } + @Override + public boolean func_146025_b(Block block) { + if (!super.func_146025_b(block)) { + ItemStack offhand = getOffhandItem(); + if (offhand != null && getCurrentItem() != null && offhand.getItem() == getCurrentItem().getItem()) { + return offhand.func_150998_b(block); + } + return false; + } + return true; + } + @Override public ItemStack getCurrentItem() { if (currentItem == InventoryPlayerBackhand.OFFHAND_HOTBAR_SLOT) { diff --git a/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java b/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java index 3197da1..98969bd 100644 --- a/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java +++ b/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java @@ -47,9 +47,9 @@ public static boolean canBlockBeInteractedWith(int x, int y, int z) { if (mop == null) return false; - float subX = (float) mc.objectMouseOver.hitVec.xCoord - x; - float subY = (float) mc.objectMouseOver.hitVec.yCoord - y; - float subZ = (float) mc.objectMouseOver.hitVec.zCoord - z; + float subX = (float) mop.hitVec.xCoord - x; + float subY = (float) mop.hitVec.yCoord - y; + float subZ = (float) mop.hitVec.zCoord - z; Block block = mc.theWorld.getBlock(x, y, z); @@ -57,7 +57,7 @@ public static boolean canBlockBeInteractedWith(int x, int y, int z) { int meta = mc.theWorld.getBlockMetadata(x, y, z); DummyWorld.INSTANCE.setBlock(x, y, z, block, meta, 3); - + ClientFakePlayer.INSTANCE.setSneaking(mc.thePlayer.isSneaking()); return block .onBlockActivated(DummyWorld.INSTANCE, x, y, z, ClientFakePlayer.INSTANCE, mop.sideHit, subX, subY, subZ); } From d7d9c4a34f5479bf7523a2bddbd9a79cc8518bec Mon Sep 17 00:00:00 2001 From: Lyfts <127234178+Lyfts@users.noreply.github.com> Date: Wed, 31 Jul 2024 16:37:33 +0200 Subject: [PATCH 04/16] forgot to set the flag --- .../xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java b/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java index c7a9ad9..51dee1d 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java +++ b/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java @@ -59,6 +59,7 @@ public abstract class MixinNetHandlerPlayServer { private void backhand$hotswapOnEntityInteract(C02PacketUseEntity packetIn, CallbackInfo ci) { if (backhand$shouldSwapOffhand(packetIn.func_149565_c())) { BackhandUtils.swapOffhandItem(playerEntity); + backhand$swappedOffhand = true; } } From a0527d43cbc8bbbbc94fb4c9c3fd37f572b56850 Mon Sep 17 00:00:00 2001 From: Lyfts <127234178+Lyfts@users.noreply.github.com> Date: Thu, 1 Aug 2024 12:39:03 +0200 Subject: [PATCH 05/16] have the fake player use the same item as the player when simulating block interaction --- .../java/xonin/backhand/HookContainerClass.java | 2 +- .../java/xonin/backhand/ServerTickHandler.java | 4 +--- .../client/BackhandClientTickHandler.java | 15 +++------------ .../xonin/backhand/client/ClientTickHandler.java | 3 ++- .../client/utils/BackhandClientUtils.java | 6 ++++-- .../mixins/early/MixinNetHandlerPlayServer.java | 6 ++++-- .../backhand/packet/OffhandPlaceBlockPacket.java | 2 +- 7 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/main/java/xonin/backhand/HookContainerClass.java b/src/main/java/xonin/backhand/HookContainerClass.java index 5bd89f4..38aece8 100644 --- a/src/main/java/xonin/backhand/HookContainerClass.java +++ b/src/main/java/xonin/backhand/HookContainerClass.java @@ -288,7 +288,7 @@ public void onOffhandSwing(PlayerEventChild.OffhandSwingEvent event) {} public boolean interactWithNoEvent(EntityPlayer pl, Entity p_70998_1_) { ItemStack itemstack = pl.getCurrentEquippedItem(); - ItemStack itemstack1 = itemstack != null ? itemstack.copy() : null; + ItemStack itemstack1 = ItemStack.copyItemStack(itemstack); if (!p_70998_1_.interactFirst(pl)) { if (itemstack != null && p_70998_1_ instanceof EntityLivingBase) { diff --git a/src/main/java/xonin/backhand/ServerTickHandler.java b/src/main/java/xonin/backhand/ServerTickHandler.java index 4e48fae..61fb6ef 100644 --- a/src/main/java/xonin/backhand/ServerTickHandler.java +++ b/src/main/java/xonin/backhand/ServerTickHandler.java @@ -39,9 +39,7 @@ public static void resetTickingHotswap(EntityPlayer player) { } public static void tickHotswap(EntityPlayerMP player) { - ItemStack mainhand = player.getCurrentEquippedItem() == null ? null - : player.getCurrentEquippedItem() - .copy(); + ItemStack mainhand = ItemStack.copyItemStack(player.getCurrentEquippedItem()); ItemStack offhand = BackhandUtils.getOffhandItem(player); if (offhand == null || player.currentWindowId != 0) return; UUID key = player.getUniqueID(); diff --git a/src/main/java/xonin/backhand/client/BackhandClientTickHandler.java b/src/main/java/xonin/backhand/client/BackhandClientTickHandler.java index 5bc8523..e60580d 100644 --- a/src/main/java/xonin/backhand/client/BackhandClientTickHandler.java +++ b/src/main/java/xonin/backhand/client/BackhandClientTickHandler.java @@ -121,7 +121,8 @@ public boolean tryCheckUseItem(ItemStack offhandItem, EntityPlayer player) { } if (mouseOver != null && mouseOver.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) { - if (BackhandClientUtils.canBlockBeInteractedWith(mouseOver.blockX, mouseOver.blockY, mouseOver.blockZ) + if (BackhandClientUtils + .canBlockBeInteractedWith(offhandItem, mouseOver.blockX, mouseOver.blockY, mouseOver.blockZ) && !BackhandUtils.getOffhandItem(player) .getItem() .doesSneakBypassUse(player.worldObj, mouseOver.blockX, mouseOver.blockY, mouseOver.blockZ, player) @@ -166,7 +167,6 @@ public boolean tryCheckUseItem(ItemStack offhandItem, EntityPlayer player) { int l = mouseOver.blockZ; if (!player.worldObj.getBlock(j, k, l) .isAir(player.worldObj, j, k, l)) { - final int size = offhandItem.stackSize; int i1 = mouseOver.sideHit; PlayerEventChild.UseOffhandItemEvent useItemEvent = new PlayerEventChild.UseOffhandItemEvent( new PlayerInteractEvent( @@ -241,16 +241,7 @@ private boolean onPlayerPlaceBlock(PlayerControllerMP controller, EntityPlayer p .onItemUseFirst(offhand, player, worldObj, i, j, k, l, f, f1, f2)) { return true; } - /* - * if (!player.isSneaking() || BattlegearUtils.getOffhandItem(player) == null || - * BattlegearUtils.getOffhandItem(player).getItem().doesSneakBypassUse(worldObj, i, j, k, player)){ - * if (!b.isAir(worldObj, i, j, k)){ - * flag = true; - * } - * } - */ - if (!flag && offhand.getItem() instanceof ItemBlock) { - ItemBlock itemblock = (ItemBlock) offhand.getItem(); + if (!flag && offhand.getItem() instanceof ItemBlock itemblock) { if (!itemblock.func_150936_a(worldObj, i, j, k, l, player, offhand)) { return false; } diff --git a/src/main/java/xonin/backhand/client/ClientTickHandler.java b/src/main/java/xonin/backhand/client/ClientTickHandler.java index a9e6e26..db60ea7 100644 --- a/src/main/java/xonin/backhand/client/ClientTickHandler.java +++ b/src/main/java/xonin/backhand/client/ClientTickHandler.java @@ -134,7 +134,8 @@ public void clientHelper(TickEvent.PlayerTickEvent event) { } } else { if (mop != null && !BackhandUtils.usagePriorAttack(offhandItem) - && !BackhandClientUtils.canBlockBeInteractedWith(mop.blockX, mop.blockY, mop.blockZ)) { + && !BackhandClientUtils + .canBlockBeInteractedWith(offhandItem, mop.blockX, mop.blockY, mop.blockZ)) { BackhandClientTickHandler.tryBreakBlockOffhand(mop, offhandItem, mainHandItem, event); Backhand.proxy.setLeftClickCounter(10); } else { diff --git a/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java b/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java index 98969bd..4294ca9 100644 --- a/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java +++ b/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java @@ -41,9 +41,10 @@ public static boolean entityOtherPlayerIsItemInUseHook(EntityOtherPlayerMP playe } } - public static boolean canBlockBeInteractedWith(int x, int y, int z) { + public static boolean canBlockBeInteractedWith(ItemStack offhand, int x, int y, int z) { Minecraft mc = Minecraft.getMinecraft(); MovingObjectPosition mop = mc.objectMouseOver; + ItemStack stack = ItemStack.copyItemStack(offhand); if (mop == null) return false; @@ -55,9 +56,10 @@ public static boolean canBlockBeInteractedWith(int x, int y, int z) { if (block == null || block == Blocks.air) return false; - int meta = mc.theWorld.getBlockMetadata(x, y, z); + int meta = block.getDamageValue(mc.theWorld, x, y, z); DummyWorld.INSTANCE.setBlock(x, y, z, block, meta, 3); ClientFakePlayer.INSTANCE.setSneaking(mc.thePlayer.isSneaking()); + ClientFakePlayer.INSTANCE.setCurrentItemOrArmor(0, stack); return block .onBlockActivated(DummyWorld.INSTANCE, x, y, z, ClientFakePlayer.INSTANCE, mop.sideHit, subX, subY, subZ); } diff --git a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java b/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java index 51dee1d..bc9f221 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java +++ b/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java @@ -1,6 +1,7 @@ package xonin.backhand.mixins.early; import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.EnumAction; import net.minecraft.item.ItemStack; import net.minecraft.network.NetHandlerPlayServer; import net.minecraft.network.Packet; @@ -88,8 +89,9 @@ public abstract class MixinNetHandlerPlayServer { @Unique private boolean backhand$shouldSwapOffhand(C02PacketUseEntity.Action action) { - return !playerEntity.isUsingItem() - && BackhandUtils.checkForRightClickFunction(BackhandUtils.getOffhandItem(playerEntity)) + ItemStack offhandStack = BackhandUtils.getOffhandItem(playerEntity); + return !playerEntity.isUsingItem() && BackhandUtils.checkForRightClickFunction(offhandStack) + && offhandStack.getItemUseAction() != EnumAction.bow && !BackhandUtils.checkForRightClickFunction(playerEntity.getCurrentEquippedItem()) && action == C02PacketUseEntity.Action.INTERACT; } diff --git a/src/main/java/xonin/backhand/packet/OffhandPlaceBlockPacket.java b/src/main/java/xonin/backhand/packet/OffhandPlaceBlockPacket.java index 9610216..1aaf63e 100644 --- a/src/main/java/xonin/backhand/packet/OffhandPlaceBlockPacket.java +++ b/src/main/java/xonin/backhand/packet/OffhandPlaceBlockPacket.java @@ -46,7 +46,7 @@ public OffhandPlaceBlockPacket(int par1, int par2, int par3, int par4, ItemStack this.yPosition = par2; this.zPosition = par3; this.direction = par4; - this.itemStack = par5ItemStack != null ? par5ItemStack.copy() : null; + this.itemStack = ItemStack.copyItemStack(par5ItemStack); this.xOffset = par6; this.yOffset = par7; this.zOffset = par8; From 2e14eeb089dea22ae09a5486fc98ae6d60744296 Mon Sep 17 00:00:00 2001 From: Lyfts <127234178+Lyfts@users.noreply.github.com> Date: Fri, 2 Aug 2024 17:03:25 +0200 Subject: [PATCH 06/16] copy tileentity & player position for simulated interaction --- .../client/utils/BackhandClientUtils.java | 11 +++------ .../client/world/ClientFakePlayer.java | 7 ++++++ .../backhand/client/world/DummyWorld.java | 24 +++++++++++++++++++ 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java b/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java index 4294ca9..ff5df19 100644 --- a/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java +++ b/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java @@ -3,7 +3,6 @@ import net.minecraft.block.Block; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityOtherPlayerMP; -import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; import net.minecraft.util.MovingObjectPosition; @@ -52,14 +51,10 @@ public static boolean canBlockBeInteractedWith(ItemStack offhand, int x, int y, float subY = (float) mop.hitVec.yCoord - y; float subZ = (float) mop.hitVec.zCoord - z; - Block block = mc.theWorld.getBlock(x, y, z); + Block block = DummyWorld.INSTANCE.copyAndSetBlock(mc.theWorld, x, y, z); + if (block == null) return false; + ClientFakePlayer.INSTANCE.prepareForInteraction(mc.thePlayer, stack); - if (block == null || block == Blocks.air) return false; - - int meta = block.getDamageValue(mc.theWorld, x, y, z); - DummyWorld.INSTANCE.setBlock(x, y, z, block, meta, 3); - ClientFakePlayer.INSTANCE.setSneaking(mc.thePlayer.isSneaking()); - ClientFakePlayer.INSTANCE.setCurrentItemOrArmor(0, stack); return block .onBlockActivated(DummyWorld.INSTANCE, x, y, z, ClientFakePlayer.INSTANCE, mop.sideHit, subX, subY, subZ); } diff --git a/src/main/java/xonin/backhand/client/world/ClientFakePlayer.java b/src/main/java/xonin/backhand/client/world/ClientFakePlayer.java index e21a34b..14b71f0 100644 --- a/src/main/java/xonin/backhand/client/world/ClientFakePlayer.java +++ b/src/main/java/xonin/backhand/client/world/ClientFakePlayer.java @@ -3,6 +3,7 @@ import java.util.UUID; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; import net.minecraft.stats.StatBase; import net.minecraft.util.ChunkCoordinates; import net.minecraft.util.DamageSource; @@ -65,4 +66,10 @@ public void onUpdate() { public void travelToDimension(int dim) { return; } + + public void prepareForInteraction(EntityPlayer player, ItemStack stack) { + this.setPositionAndRotation(player.posX, player.posY, player.posZ, player.rotationYaw, player.rotationPitch); + this.setCurrentItemOrArmor(0, stack); + this.setSneaking(player.isSneaking()); + } } diff --git a/src/main/java/xonin/backhand/client/world/DummyWorld.java b/src/main/java/xonin/backhand/client/world/DummyWorld.java index ac9337b..080503c 100644 --- a/src/main/java/xonin/backhand/client/world/DummyWorld.java +++ b/src/main/java/xonin/backhand/client/world/DummyWorld.java @@ -2,8 +2,12 @@ import javax.annotation.Nonnull; +import net.minecraft.block.Block; import net.minecraft.entity.Entity; +import net.minecraft.init.Blocks; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.profiler.Profiler; +import net.minecraft.tileentity.TileEntity; import net.minecraft.world.EnumSkyBlock; import net.minecraft.world.World; import net.minecraft.world.WorldProviderSurface; @@ -65,4 +69,24 @@ protected boolean chunkExists(int x, int z) { public boolean updateLightByType(EnumSkyBlock p_147463_1_, int p_147463_2_, int p_147463_3_, int p_147463_4_) { return true; } + + public Block copyAndSetBlock(World world, int x, int y, int z) { + setBlockToAir(x, y, z); + Block block = world.getBlock(x, y, z); + + if (block == null || block == Blocks.air) return null; + + int meta = block.getDamageValue(world, x, y, z); + DummyWorld.INSTANCE.setBlock(x, y, z, block, meta, 3); + TileEntity tile = world.getTileEntity(x, y, z); + if (tile != null) { + NBTTagCompound tag = new NBTTagCompound(); + tile.writeToNBT(tag); + TileEntity dummyTile = TileEntity.createAndLoadEntity(tag); + DummyWorld.INSTANCE.setTileEntity(x, y, z, dummyTile); + } + + return getBlock(x, y, z); + } + } From c79835b62a3f9b121e425e2a094362f062485168 Mon Sep 17 00:00:00 2001 From: Lyfts <127234178+Lyfts@users.noreply.github.com> Date: Fri, 2 Aug 2024 19:51:32 +0200 Subject: [PATCH 07/16] cursed fix for #22 --- .../client/utils/BackhandClientUtils.java | 2 +- .../backhand/client/world/DummyWorld.java | 50 +++++++++++++++++-- 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java b/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java index ff5df19..aaa600f 100644 --- a/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java +++ b/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java @@ -51,7 +51,7 @@ public static boolean canBlockBeInteractedWith(ItemStack offhand, int x, int y, float subY = (float) mop.hitVec.yCoord - y; float subZ = (float) mop.hitVec.zCoord - z; - Block block = DummyWorld.INSTANCE.copyAndSetBlock(mc.theWorld, x, y, z); + Block block = DummyWorld.INSTANCE.copyAndSetBlock(mc.theWorld, x, y, z, mop); if (block == null) return false; ClientFakePlayer.INSTANCE.prepareForInteraction(mc.thePlayer, stack); diff --git a/src/main/java/xonin/backhand/client/world/DummyWorld.java b/src/main/java/xonin/backhand/client/world/DummyWorld.java index 080503c..7ab6cf2 100644 --- a/src/main/java/xonin/backhand/client/world/DummyWorld.java +++ b/src/main/java/xonin/backhand/client/world/DummyWorld.java @@ -1,13 +1,17 @@ package xonin.backhand.client.world; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import net.minecraft.block.Block; import net.minecraft.entity.Entity; import net.minecraft.init.Blocks; +import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.profiler.Profiler; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.Vec3; import net.minecraft.world.EnumSkyBlock; import net.minecraft.world.World; import net.minecraft.world.WorldProviderSurface; @@ -26,6 +30,9 @@ public class DummyWorld extends World { public static final DummyWorld INSTANCE = new DummyWorld(); + public Block boundBlock; + public Vec3 boundBlockPos; + public DummyWorld() { super(new DummySaveHandler(), "DummyServer", DEFAULT_SETTINGS, new WorldProviderSurface(), new Profiler()); // Guarantee the dimension ID was not reset by the provider @@ -70,23 +77,58 @@ public boolean updateLightByType(EnumSkyBlock p_147463_1_, int p_147463_2_, int return true; } - public Block copyAndSetBlock(World world, int x, int y, int z) { + @Override + public TileEntity getTileEntity(int x, int y, int z) { + if (boundBlock == null) return super.getTileEntity(x, y, z); + return super.getTileEntity((int) boundBlockPos.xCoord, (int) boundBlockPos.yCoord, (int) boundBlockPos.zCoord); + } + + @Override + public Block getBlock(int x, int y, int z) { + if (boundBlock == null) return super.getBlock(x, y, z); + return boundBlock; + } + + @Nullable + public Block copyAndSetBlock(World world, int x, int y, int z, MovingObjectPosition mop) { + reset(); setBlockToAir(x, y, z); Block block = world.getBlock(x, y, z); if (block == null || block == Blocks.air) return null; int meta = block.getDamageValue(world, x, y, z); - DummyWorld.INSTANCE.setBlock(x, y, z, block, meta, 3); + ItemStack stack = block.getPickBlock(mop, world, x, y, z, ClientFakePlayer.INSTANCE); + + if (stack == null || !stack.getItem() + .onItemUse(stack, ClientFakePlayer.INSTANCE, this, x, y, z, mop.sideHit, x, y, z)) { + setBlock(x, y, z, block, meta, 3); + setBoundBlock(block, x, y, z); + } + TileEntity tile = world.getTileEntity(x, y, z); if (tile != null) { NBTTagCompound tag = new NBTTagCompound(); tile.writeToNBT(tag); - TileEntity dummyTile = TileEntity.createAndLoadEntity(tag); - DummyWorld.INSTANCE.setTileEntity(x, y, z, dummyTile); + TileEntity dummyTile = getTileEntity(x, y, z); + if (dummyTile == null) { + dummyTile = TileEntity.createAndLoadEntity(tag); + setTileEntity(x, y, z, dummyTile); + } + dummyTile.readFromNBT(tag); } return getBlock(x, y, z); } + public void setBoundBlock(Block block, int x, int y, int z) { + boundBlock = block; + boundBlockPos = Vec3.createVectorHelper(x, y, z); + } + + public void reset() { + boundBlock = null; + boundBlockPos = null; + } + } From 0831f58243c47e41452abdec906fd05c882b7af8 Mon Sep 17 00:00:00 2001 From: Lyfts <127234178+Lyfts@users.noreply.github.com> Date: Fri, 2 Aug 2024 20:17:39 +0200 Subject: [PATCH 08/16] address review --- .../java/xonin/backhand/client/world/DummyWorld.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/xonin/backhand/client/world/DummyWorld.java b/src/main/java/xonin/backhand/client/world/DummyWorld.java index 7ab6cf2..0d78b35 100644 --- a/src/main/java/xonin/backhand/client/world/DummyWorld.java +++ b/src/main/java/xonin/backhand/client/world/DummyWorld.java @@ -30,8 +30,8 @@ public class DummyWorld extends World { public static final DummyWorld INSTANCE = new DummyWorld(); - public Block boundBlock; - public Vec3 boundBlockPos; + private Block boundBlock; + private final Vec3 boundBlockPos = Vec3.createVectorHelper(0, 0, 0); public DummyWorld() { super(new DummySaveHandler(), "DummyServer", DEFAULT_SETTINGS, new WorldProviderSurface(), new Profiler()); @@ -123,12 +123,16 @@ public Block copyAndSetBlock(World world, int x, int y, int z, MovingObjectPosit public void setBoundBlock(Block block, int x, int y, int z) { boundBlock = block; - boundBlockPos = Vec3.createVectorHelper(x, y, z); + boundBlockPos.xCoord = x; + boundBlockPos.yCoord = y; + boundBlockPos.zCoord = z; } public void reset() { boundBlock = null; - boundBlockPos = null; + boundBlockPos.xCoord = 0; + boundBlockPos.yCoord = 0; + boundBlockPos.zCoord = 0; } } From 97d878536567be11192147425f5efadb858e1838 Mon Sep 17 00:00:00 2001 From: Lyfts <127234178+Lyfts@users.noreply.github.com> Date: Fri, 2 Aug 2024 22:41:19 +0200 Subject: [PATCH 09/16] fix #23 --- src/main/java/xonin/backhand/ServerTickHandler.java | 4 +++- .../backhand/api/core/OffhandExtendedProperty.java | 1 + .../mixins/early/MixinNetHandlerPlayServer.java | 11 +++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/xonin/backhand/ServerTickHandler.java b/src/main/java/xonin/backhand/ServerTickHandler.java index 61fb6ef..7bdfa6d 100644 --- a/src/main/java/xonin/backhand/ServerTickHandler.java +++ b/src/main/java/xonin/backhand/ServerTickHandler.java @@ -66,10 +66,12 @@ public void onUpdateWorld(TickEvent.WorldTickEvent event) { if (Backhand.OffhandTickHotswap) { for (EntityPlayer player : event.world.playerEntities) { if (!(player instanceof EntityPlayerMP playerMP)) continue; + OffhandExtendedProperty offhandProp = BackhandUtils.getOffhandEP(player); - if (event.phase == TickEvent.Phase.START && !player.isUsingItem()) { + if (event.phase == TickEvent.Phase.START && !player.isUsingItem() && offhandProp.hotswapDelay <= 0) { tickHotswap(playerMP); } else { + if (offhandProp.hotswapDelay > 0) offhandProp.hotswapDelay--; resetTickingHotswap(playerMP); } } diff --git a/src/main/java/xonin/backhand/api/core/OffhandExtendedProperty.java b/src/main/java/xonin/backhand/api/core/OffhandExtendedProperty.java index c4ca623..7ccf4c4 100644 --- a/src/main/java/xonin/backhand/api/core/OffhandExtendedProperty.java +++ b/src/main/java/xonin/backhand/api/core/OffhandExtendedProperty.java @@ -16,6 +16,7 @@ public class OffhandExtendedProperty implements IExtendedEntityProperties { public int activeSlot = -1; public boolean arrowHotSwapped = false; public boolean regularHotSwap = false; + public int hotswapDelay = 0; public OffhandExtendedProperty(EntityPlayer player) { this.player = player; diff --git a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java b/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java index bc9f221..1313bba 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java +++ b/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java @@ -19,6 +19,7 @@ import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import xonin.backhand.ServerTickHandler; import xonin.backhand.api.core.BackhandUtils; import xonin.backhand.api.core.InventoryPlayerBackhand; @@ -56,6 +57,16 @@ public abstract class MixinNetHandlerPlayServer { instance.tryHarvestBlock(x, y, z); } + @Inject( + method = "processPlayerDigging", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/entity/player/EntityPlayerMP;dropOneItem(Z)Lnet/minecraft/entity/item/EntityItem;")) + private void backhand$playerDropItem(C07PacketPlayerDigging packetIn, CallbackInfo ci) { + ServerTickHandler.resetTickingHotswap(playerEntity); + BackhandUtils.getOffhandEP(playerEntity).hotswapDelay = 5; + } + @Inject(method = "processUseEntity", at = @At("HEAD")) private void backhand$hotswapOnEntityInteract(C02PacketUseEntity packetIn, CallbackInfo ci) { if (backhand$shouldSwapOffhand(packetIn.func_149565_c())) { From ddbf53a3935a99db42d29b6f299c85676edab07c Mon Sep 17 00:00:00 2001 From: Lyfts <127234178+Lyfts@users.noreply.github.com> Date: Sat, 3 Aug 2024 18:41:15 +0200 Subject: [PATCH 10/16] finally fix #11 --- src/main/java/xonin/backhand/CommonProxy.java | 2 +- .../java/xonin/backhand/ServerEventsHandler.java | 9 +++++---- .../java/xonin/backhand/ServerTickHandler.java | 16 +++++----------- .../xonin/backhand/api/core/BackhandUtils.java | 13 +++++++++++++ .../api/core/OffhandExtendedProperty.java | 3 +-- .../backhand/mixins/early/MixinEntityItem.java | 5 +---- .../mixins/early/MixinNetHandlerPlayServer.java | 4 +--- 7 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/main/java/xonin/backhand/CommonProxy.java b/src/main/java/xonin/backhand/CommonProxy.java index bce93b1..4cc40ce 100644 --- a/src/main/java/xonin/backhand/CommonProxy.java +++ b/src/main/java/xonin/backhand/CommonProxy.java @@ -19,7 +19,7 @@ public void onServerStopping(FMLServerStoppingEvent event) { for (EntityPlayer player : Backhand.getServer() .getConfigurationManager().playerEntityList) { if (BackhandUtils.getOffhandItem(player) != null) { - ServerTickHandler.resetTickingHotswap(player); + BackhandUtils.resetAndDelayHotswap(player, 0); } } } diff --git a/src/main/java/xonin/backhand/ServerEventsHandler.java b/src/main/java/xonin/backhand/ServerEventsHandler.java index d66a2ae..70ed4a8 100644 --- a/src/main/java/xonin/backhand/ServerEventsHandler.java +++ b/src/main/java/xonin/backhand/ServerEventsHandler.java @@ -68,7 +68,7 @@ public void onLivingHurt(LivingHurtEvent event) { Item totem = ModItems.TOTEM_OF_UNDYING.get(); if (offhandItem.getItem() == totem && (mainhandItem == null || mainhandItem.getItem() != totem)) { - BackhandUtils.swapOffhandItem(player); + BackhandUtils.swapOffhandItem(player, 5); offhandProp.regularHotSwap = true; } } @@ -86,7 +86,7 @@ public void onItemUseStart(PlayerUseItemEvent.Start event) { } } - @SubscribeEvent + @SubscribeEvent(priority = EventPriority.HIGHEST) public void onArrowNock(ArrowNockEvent event) { if (!Backhand.UseOffhandArrows) { return; @@ -135,6 +135,7 @@ public void onItemStop(PlayerUseItemEvent.Stop event) { && !offhandProp.regularHotSwap) { BackhandUtils.swapOffhandItem(player); offhandProp.regularHotSwap = true; + return; } if (!Backhand.UseOffhandArrows || !(event.item.getItem() instanceof ItemBow)) { @@ -147,9 +148,9 @@ public void onItemStop(PlayerUseItemEvent.Stop event) { return; } - offhandProp.arrowHotSwapped = true; if (offhandItem.getItem() != Items.arrow) { - BackhandUtils.swapOffhandItem(player); + offhandProp.regularHotSwap = true; + BackhandUtils.swapOffhandItem(player, 5); } } } diff --git a/src/main/java/xonin/backhand/ServerTickHandler.java b/src/main/java/xonin/backhand/ServerTickHandler.java index 7bdfa6d..ea84240 100644 --- a/src/main/java/xonin/backhand/ServerTickHandler.java +++ b/src/main/java/xonin/backhand/ServerTickHandler.java @@ -7,7 +7,6 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.entity.player.PlayerInteractEvent; @@ -28,7 +27,7 @@ public class ServerTickHandler { public static final HashMap> tickStartItems = new HashMap<>(); - public static void resetTickingHotswap(EntityPlayer player) { + public static void resetTickingHotswap(EntityPlayerMP player) { List tickedItems = tickStartItems.get(player.getUniqueID()); if (tickedItems != null) { BackhandUtils.getOffhandEP(player).ignoreSetSlot = false; @@ -68,10 +67,11 @@ public void onUpdateWorld(TickEvent.WorldTickEvent event) { if (!(player instanceof EntityPlayerMP playerMP)) continue; OffhandExtendedProperty offhandProp = BackhandUtils.getOffhandEP(player); - if (event.phase == TickEvent.Phase.START && !player.isUsingItem() && offhandProp.hotswapDelay <= 0) { + if (event.phase == TickEvent.Phase.START && !player.isUsingItem() + && offhandProp.tickingHotswapDelay <= 0) { tickHotswap(playerMP); } else { - if (offhandProp.hotswapDelay > 0) offhandProp.hotswapDelay--; + if (offhandProp.tickingHotswapDelay > 0) offhandProp.tickingHotswapDelay--; resetTickingHotswap(playerMP); } } @@ -129,14 +129,8 @@ public void onUpdatePlayer(TickEvent.PlayerTickEvent event) { offhandProp.syncOffhand = false; } - if (offhandProp.arrowHotSwapped) { - if (offhand != null && offhand.getItem() != Items.arrow) { - BackhandUtils.swapOffhandItem(player); - } - offhandProp.arrowHotSwapped = false; - } if (offhandProp.regularHotSwap) { - BackhandUtils.swapOffhandItem(player); + BackhandUtils.swapOffhandItem(player, 5); offhandProp.regularHotSwap = false; } diff --git a/src/main/java/xonin/backhand/api/core/BackhandUtils.java b/src/main/java/xonin/backhand/api/core/BackhandUtils.java index 76e11ee..4c2cc52 100644 --- a/src/main/java/xonin/backhand/api/core/BackhandUtils.java +++ b/src/main/java/xonin/backhand/api/core/BackhandUtils.java @@ -10,6 +10,7 @@ import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.ai.attributes.BaseAttributeMap; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.EnumAction; import net.minecraft.item.Item; import net.minecraft.item.ItemBed; @@ -45,6 +46,7 @@ import com.google.common.io.ByteArrayDataOutput; import xonin.backhand.Backhand; +import xonin.backhand.ServerTickHandler; /** * Store commonly used method, mostly for the {@link EntityPlayer} {@link ItemStack}s management @@ -75,6 +77,11 @@ public static boolean hasOffhandInventory(EntityPlayer player) { } public static void swapOffhandItem(EntityPlayer player) { + swapOffhandItem(player, 0); + } + + public static void swapOffhandItem(EntityPlayer player, int delayHotswap) { + if (delayHotswap > 0) resetAndDelayHotswap(player, delayHotswap); final ItemStack mainhandItem = getLegalStack(player.getCurrentEquippedItem()); final ItemStack offhandItem = getLegalStack(BackhandUtils.getOffhandItem(player)); BackhandUtils.setPlayerCurrentItem(player, offhandItem); @@ -508,4 +515,10 @@ public static ItemStack getLegalStack(ItemStack stack) { return stack; } + + public static void resetAndDelayHotswap(EntityPlayer player, int delayTicks) { + if (!(player instanceof EntityPlayerMP playerMP)) return; + ServerTickHandler.resetTickingHotswap(playerMP); + getOffhandEP(player).tickingHotswapDelay = delayTicks; + } } diff --git a/src/main/java/xonin/backhand/api/core/OffhandExtendedProperty.java b/src/main/java/xonin/backhand/api/core/OffhandExtendedProperty.java index 7ccf4c4..7e568e3 100644 --- a/src/main/java/xonin/backhand/api/core/OffhandExtendedProperty.java +++ b/src/main/java/xonin/backhand/api/core/OffhandExtendedProperty.java @@ -14,9 +14,8 @@ public class OffhandExtendedProperty implements IExtendedEntityProperties { private ItemStack offhandItem; public boolean ignoreSetSlot = false; public int activeSlot = -1; - public boolean arrowHotSwapped = false; public boolean regularHotSwap = false; - public int hotswapDelay = 0; + public int tickingHotswapDelay = 0; public OffhandExtendedProperty(EntityPlayer player) { this.player = player; diff --git a/src/main/java/xonin/backhand/mixins/early/MixinEntityItem.java b/src/main/java/xonin/backhand/mixins/early/MixinEntityItem.java index 6bd933d..e2f8055 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinEntityItem.java +++ b/src/main/java/xonin/backhand/mixins/early/MixinEntityItem.java @@ -8,7 +8,6 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import xonin.backhand.ServerTickHandler; import xonin.backhand.api.core.BackhandUtils; @Mixin(EntityItem.class) @@ -20,8 +19,6 @@ public abstract class MixinEntityItem { value = "INVOKE", target = "Lnet/minecraft/entity/item/EntityItem;getEntityItem()Lnet/minecraft/item/ItemStack;")) private void backhand$resetHotswapOnPickup(EntityPlayer entityIn, CallbackInfo ci) { - if (BackhandUtils.getOffhandItem(entityIn) != null) { - ServerTickHandler.resetTickingHotswap(entityIn); - } + BackhandUtils.resetAndDelayHotswap(entityIn, 0); } } diff --git a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java b/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java index 1313bba..de1593d 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java +++ b/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java @@ -19,7 +19,6 @@ import com.llamalad7.mixinextras.injector.ModifyExpressionValue; -import xonin.backhand.ServerTickHandler; import xonin.backhand.api.core.BackhandUtils; import xonin.backhand.api.core.InventoryPlayerBackhand; @@ -63,8 +62,7 @@ public abstract class MixinNetHandlerPlayServer { value = "INVOKE", target = "Lnet/minecraft/entity/player/EntityPlayerMP;dropOneItem(Z)Lnet/minecraft/entity/item/EntityItem;")) private void backhand$playerDropItem(C07PacketPlayerDigging packetIn, CallbackInfo ci) { - ServerTickHandler.resetTickingHotswap(playerEntity); - BackhandUtils.getOffhandEP(playerEntity).hotswapDelay = 5; + BackhandUtils.resetAndDelayHotswap(playerEntity, 5); } @Inject(method = "processUseEntity", at = @At("HEAD")) From 543f88b087da6b6172937073949b5c5a55679249 Mon Sep 17 00:00:00 2001 From: Lyfts <127234178+Lyfts@users.noreply.github.com> Date: Sat, 3 Aug 2024 18:57:58 +0200 Subject: [PATCH 11/16] fix some items not updating their stacksize when placed with offhand --- .../packet/OffhandPlaceBlockPacket.java | 45 ++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/src/main/java/xonin/backhand/packet/OffhandPlaceBlockPacket.java b/src/main/java/xonin/backhand/packet/OffhandPlaceBlockPacket.java index 1aaf63e..ccfe1a4 100644 --- a/src/main/java/xonin/backhand/packet/OffhandPlaceBlockPacket.java +++ b/src/main/java/xonin/backhand/packet/OffhandPlaceBlockPacket.java @@ -18,6 +18,7 @@ import cpw.mods.fml.common.network.ByteBufUtils; import cpw.mods.fml.relauncher.Side; import io.netty.buffer.ByteBuf; +import xonin.backhand.Backhand; import xonin.backhand.HookContainerClass; import xonin.backhand.api.PlayerEventChild; import xonin.backhand.api.core.BackhandUtils; @@ -83,28 +84,28 @@ public void process(ByteBuf in, EntityPlayer player) { } catch (Exception io) { return; } - if (!(player instanceof EntityPlayerMP)) return; - ItemStack offhandWeapon = BackhandUtils.getOffhandItem(player); + if (!(player instanceof EntityPlayerMP playerMP)) return; + ItemStack offhandWeapon = BackhandUtils.getOffhandItem(playerMP); if (offhandWeapon != null && !BackhandUtils.usagePriorAttack(offhandWeapon)) return; boolean flag = true; int i = xPosition; int j = yPosition; int k = zPosition; int l = direction; - ((EntityPlayerMP) player).func_143004_u(); + playerMP.func_143004_u(); if (direction == 255) { if (offhandWeapon == null) return; PlayerInteractEvent event = new PlayerInteractEvent( - player, + playerMP, PlayerInteractEvent.Action.RIGHT_CLICK_AIR, 0, 0, 0, -1, - player.getEntityWorld()); + playerMP.getEntityWorld()); MinecraftForge.EVENT_BUS.post(new PlayerEventChild.UseOffhandItemEvent(event, offhandWeapon)); if (event.useItem != Event.Result.DENY) { - HookContainerClass.tryUseItem(player, offhandWeapon, Side.SERVER); + HookContainerClass.tryUseItem(playerMP, offhandWeapon, Side.SERVER); } flag = false; } else { @@ -115,19 +116,18 @@ public void process(ByteBuf in, EntityPlayer player) { ChatComponentTranslation chat = new ChatComponentTranslation("build.tooHigh", mcServer.getBuildLimit()); chat.getChatStyle() .setColor(EnumChatFormatting.RED); - ((EntityPlayerMP) player).playerNetServerHandler.sendPacket(new S02PacketChat(chat)); + playerMP.playerNetServerHandler.sendPacket(new S02PacketChat(chat)); } else { - double dist = ((EntityPlayerMP) player).theItemInWorldManager.getBlockReachDistance() + 1; + double dist = playerMP.theItemInWorldManager.getBlockReachDistance() + 1; dist *= dist; - if (player.getDistanceSq(i + 0.5D, j + 0.5D, k + 0.5D) < dist - && !mcServer.isBlockProtected(player.getEntityWorld(), i, j, k, player)) { - this.useItem((EntityPlayerMP) player, offhandWeapon, i, j, k, l, xOffset, yOffset, zOffset); + if (playerMP.getDistanceSq(i + 0.5D, j + 0.5D, k + 0.5D) < dist + && !mcServer.isBlockProtected(playerMP.getEntityWorld(), i, j, k, playerMP)) { + this.useItem(playerMP, offhandWeapon, i, j, k, l, xOffset, yOffset, zOffset); } } } if (flag) { - ((EntityPlayerMP) player).playerNetServerHandler - .sendPacket(new S23PacketBlockChange(i, j, k, player.getEntityWorld())); + playerMP.playerNetServerHandler.sendPacket(new S23PacketBlockChange(i, j, k, playerMP.getEntityWorld())); if (l == 0) { --j; } @@ -146,23 +146,26 @@ public void process(ByteBuf in, EntityPlayer player) { if (l == 5) { ++i; } - ((EntityPlayerMP) player).playerNetServerHandler - .sendPacket(new S23PacketBlockChange(i, j, k, player.getEntityWorld())); + playerMP.playerNetServerHandler.sendPacket(new S23PacketBlockChange(i, j, k, playerMP.getEntityWorld())); } - offhandWeapon = BackhandUtils.getOffhandItem(player); + offhandWeapon = BackhandUtils.getOffhandItem(playerMP); if (offhandWeapon != null && HookContainerClass.isItemBlock(offhandWeapon.getItem())) { if (offhandWeapon.stackSize <= 0) { - BackhandUtils.setPlayerOffhandItem(player, null); + BackhandUtils.setPlayerOffhandItem(playerMP, null); offhandWeapon = null; } if (offhandWeapon == null || offhandWeapon.getMaxItemUseDuration() == 0) { - ((EntityPlayerMP) player).isChangingQuantityOnly = true; + playerMP.isChangingQuantityOnly = true; BackhandUtils - .setPlayerOffhandItem(player, ItemStack.copyItemStack(BackhandUtils.getOffhandItem(player))); - player.openContainer.detectAndSendChanges(); - ((EntityPlayerMP) player).isChangingQuantityOnly = false; + .setPlayerOffhandItem(playerMP, ItemStack.copyItemStack(BackhandUtils.getOffhandItem(playerMP))); + playerMP.openContainer.detectAndSendChanges(); + playerMP.isChangingQuantityOnly = false; } } + + if (!ItemStack.areItemStacksEqual(itemStack, offhandWeapon)) { + Backhand.packetHandler.sendPacketToPlayer(new OffhandSyncItemPacket(playerMP).generatePacket(), playerMP); + } } public boolean useItem(EntityPlayerMP playerMP, ItemStack itemStack, int x, int y, int z, int side, float xOffset, From 6475cb20eb1ba67bca7b27404554e23b5330954c Mon Sep 17 00:00:00 2001 From: Lyfts <127234178+Lyfts@users.noreply.github.com> Date: Sun, 4 Aug 2024 13:49:56 +0200 Subject: [PATCH 12/16] more stable fix for #22 --- .../client/BackhandClientTickHandler.java | 5 +- .../client/utils/BackhandClientUtils.java | 7 ++- .../backhand/client/world/DummyWorld.java | 50 ++++++------------- .../coremod/BackhandLoadingPlugin.java | 1 + .../backhand/mixins/early/MixinWorld.java | 23 +++++++++ 5 files changed, 46 insertions(+), 40 deletions(-) create mode 100644 src/main/java/xonin/backhand/mixins/early/MixinWorld.java diff --git a/src/main/java/xonin/backhand/client/BackhandClientTickHandler.java b/src/main/java/xonin/backhand/client/BackhandClientTickHandler.java index e60580d..7ca5a8a 100644 --- a/src/main/java/xonin/backhand/client/BackhandClientTickHandler.java +++ b/src/main/java/xonin/backhand/client/BackhandClientTickHandler.java @@ -6,7 +6,6 @@ import net.minecraft.block.material.Material; import net.minecraft.client.Minecraft; import net.minecraft.client.audio.PositionedSoundRecord; -import net.minecraft.client.entity.EntityClientPlayerMP; import net.minecraft.client.multiplayer.PlayerControllerMP; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; @@ -99,7 +98,7 @@ public void tryAttackEntity(EntityPlayer player) { if (mc.objectMouseOver != null && mc.objectMouseOver.typeOfHit == MovingObjectPosition.MovingObjectType.ENTITY) { Entity target = mc.objectMouseOver.entityHit; - ((EntityClientPlayerMP) player).sendQueue + mc.getNetHandler() .addToSendQueue(new OffhandAttackPacket(player, target).generatePacket()); } } @@ -392,7 +391,7 @@ public static void tryBreakBlockOffhand(MovingObjectPosition objectMouseOver, It if (broken) { BackhandUtils.setPlayerOffhandItem(event.player, null); - ((EntityClientPlayerMP) event.player).sendQueue + mcInstance.getNetHandler() .addToSendQueue(new OffhandToServerPacket(null, event.player).generatePacket()); } } diff --git a/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java b/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java index aaa600f..a75161d 100644 --- a/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java +++ b/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java @@ -3,6 +3,7 @@ import net.minecraft.block.Block; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityOtherPlayerMP; +import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; import net.minecraft.util.MovingObjectPosition; @@ -51,8 +52,12 @@ public static boolean canBlockBeInteractedWith(ItemStack offhand, int x, int y, float subY = (float) mop.hitVec.yCoord - y; float subZ = (float) mop.hitVec.zCoord - z; + // Needs to be done before and after placing the block to ensure + // that the block placement didn't change the item or player position + ClientFakePlayer.INSTANCE.prepareForInteraction(mc.thePlayer, stack); Block block = DummyWorld.INSTANCE.copyAndSetBlock(mc.theWorld, x, y, z, mop); - if (block == null) return false; + if (block == null || block == Blocks.air) return false; + ClientFakePlayer.INSTANCE.prepareForInteraction(mc.thePlayer, stack); return block diff --git a/src/main/java/xonin/backhand/client/world/DummyWorld.java b/src/main/java/xonin/backhand/client/world/DummyWorld.java index 0d78b35..ed1036e 100644 --- a/src/main/java/xonin/backhand/client/world/DummyWorld.java +++ b/src/main/java/xonin/backhand/client/world/DummyWorld.java @@ -11,7 +11,6 @@ import net.minecraft.profiler.Profiler; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.MovingObjectPosition; -import net.minecraft.util.Vec3; import net.minecraft.world.EnumSkyBlock; import net.minecraft.world.World; import net.minecraft.world.WorldProviderSurface; @@ -30,9 +29,6 @@ public class DummyWorld extends World { public static final DummyWorld INSTANCE = new DummyWorld(); - private Block boundBlock; - private final Vec3 boundBlockPos = Vec3.createVectorHelper(0, 0, 0); - public DummyWorld() { super(new DummySaveHandler(), "DummyServer", DEFAULT_SETTINGS, new WorldProviderSurface(), new Profiler()); // Guarantee the dimension ID was not reset by the provider @@ -77,33 +73,30 @@ public boolean updateLightByType(EnumSkyBlock p_147463_1_, int p_147463_2_, int return true; } - @Override - public TileEntity getTileEntity(int x, int y, int z) { - if (boundBlock == null) return super.getTileEntity(x, y, z); - return super.getTileEntity((int) boundBlockPos.xCoord, (int) boundBlockPos.yCoord, (int) boundBlockPos.zCoord); - } - - @Override - public Block getBlock(int x, int y, int z) { - if (boundBlock == null) return super.getBlock(x, y, z); - return boundBlock; - } - @Nullable public Block copyAndSetBlock(World world, int x, int y, int z, MovingObjectPosition mop) { - reset(); - setBlockToAir(x, y, z); Block block = world.getBlock(x, y, z); if (block == null || block == Blocks.air) return null; int meta = block.getDamageValue(world, x, y, z); ItemStack stack = block.getPickBlock(mop, world, x, y, z, ClientFakePlayer.INSTANCE); + boolean placed = false; + + if (stack != null) { + for (int i = 0; i < 6; i++) { + // Adjust when placing on a block "below" + int aY = i == 1 ? y - 1 : y; + if (stack.getItem() + .onItemUse(stack, ClientFakePlayer.INSTANCE, this, x, aY, z, i, x, aY, z)) { + placed = true; + break; + } + } + } - if (stack == null || !stack.getItem() - .onItemUse(stack, ClientFakePlayer.INSTANCE, this, x, y, z, mop.sideHit, x, y, z)) { + if (!placed) { setBlock(x, y, z, block, meta, 3); - setBoundBlock(block, x, y, z); } TileEntity tile = world.getTileEntity(x, y, z); @@ -120,19 +113,4 @@ public Block copyAndSetBlock(World world, int x, int y, int z, MovingObjectPosit return getBlock(x, y, z); } - - public void setBoundBlock(Block block, int x, int y, int z) { - boundBlock = block; - boundBlockPos.xCoord = x; - boundBlockPos.yCoord = y; - boundBlockPos.zCoord = z; - } - - public void reset() { - boundBlock = null; - boundBlockPos.xCoord = 0; - boundBlockPos.yCoord = 0; - boundBlockPos.zCoord = 0; - } - } diff --git a/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java b/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java index 6083985..b7d2bb0 100644 --- a/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java +++ b/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java @@ -58,6 +58,7 @@ public List getMixins(Set loadedCoreMods) { mixins.add("MixinPlayerControllerMP"); mixins.add("MixinItemBow"); mixins.add("MixinItemStackClient"); + mixins.add("MixinWorld"); } return mixins; } diff --git a/src/main/java/xonin/backhand/mixins/early/MixinWorld.java b/src/main/java/xonin/backhand/mixins/early/MixinWorld.java new file mode 100644 index 0000000..28859e8 --- /dev/null +++ b/src/main/java/xonin/backhand/mixins/early/MixinWorld.java @@ -0,0 +1,23 @@ +package xonin.backhand.mixins.early; + +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import xonin.backhand.client.world.DummyWorld; + +@Mixin(World.class) +public abstract class MixinWorld { + + @Inject(method = "doesBlockHaveSolidTopSurface", at = @At(value = "HEAD"), cancellable = true) + private static void backhand$allowPlacementInDummyWorld(IBlockAccess worldIn, int x, int y, int z, + CallbackInfoReturnable cir) { + if (worldIn instanceof DummyWorld) { + cir.setReturnValue(true); + } + } +} From 5ca809b5bab0a44bdc5991278c773b3acb0f3600 Mon Sep 17 00:00:00 2001 From: Lyfts <127234178+Lyfts@users.noreply.github.com> Date: Mon, 5 Aug 2024 14:07:31 +0200 Subject: [PATCH 13/16] yoink hodgepodge mixin setup --- .../xonin/backhand/BackhandLateMixins.java | 23 ++ .../coremod/BackhandLoadingPlugin.java | 23 +- .../java/xonin/backhand/mixins/Mixins.java | 199 ++++++++++++++++++ .../xonin/backhand/mixins/TargetedMod.java | 29 +++ .../{ => minecraft}/MixinEntityItem.java | 2 +- .../MixinEntityOtherPlayerMP.java | 2 +- .../{ => minecraft}/MixinEntityPlayer.java | 2 +- .../MixinEntityPlayerClient.java | 2 +- .../{ => minecraft}/MixinEntityPlayerMP.java | 2 +- .../early/{ => minecraft}/MixinItemBow.java | 2 +- .../{ => minecraft}/MixinItemRenderer.java | 2 +- .../early/{ => minecraft}/MixinItemStack.java | 2 +- .../{ => minecraft}/MixinItemStackClient.java | 2 +- .../{ => minecraft}/MixinModelBiped.java | 2 +- .../MixinNetHandlerPlayClient.java | 2 +- .../MixinNetHandlerPlayServer.java | 2 +- .../MixinPlayerControllerMP.java | 2 +- .../early/{ => minecraft}/MixinWorld.java | 2 +- src/main/resources/mixins.backhand.late.json | 11 + 19 files changed, 278 insertions(+), 35 deletions(-) create mode 100644 src/main/java/xonin/backhand/BackhandLateMixins.java create mode 100644 src/main/java/xonin/backhand/mixins/Mixins.java create mode 100644 src/main/java/xonin/backhand/mixins/TargetedMod.java rename src/main/java/xonin/backhand/mixins/early/{ => minecraft}/MixinEntityItem.java (94%) rename src/main/java/xonin/backhand/mixins/early/{ => minecraft}/MixinEntityOtherPlayerMP.java (97%) rename src/main/java/xonin/backhand/mixins/early/{ => minecraft}/MixinEntityPlayer.java (99%) rename src/main/java/xonin/backhand/mixins/early/{ => minecraft}/MixinEntityPlayerClient.java (97%) rename src/main/java/xonin/backhand/mixins/early/{ => minecraft}/MixinEntityPlayerMP.java (95%) rename src/main/java/xonin/backhand/mixins/early/{ => minecraft}/MixinItemBow.java (95%) rename src/main/java/xonin/backhand/mixins/early/{ => minecraft}/MixinItemRenderer.java (97%) rename src/main/java/xonin/backhand/mixins/early/{ => minecraft}/MixinItemStack.java (96%) rename src/main/java/xonin/backhand/mixins/early/{ => minecraft}/MixinItemStackClient.java (97%) rename src/main/java/xonin/backhand/mixins/early/{ => minecraft}/MixinModelBiped.java (98%) rename src/main/java/xonin/backhand/mixins/early/{ => minecraft}/MixinNetHandlerPlayClient.java (94%) rename src/main/java/xonin/backhand/mixins/early/{ => minecraft}/MixinNetHandlerPlayServer.java (99%) rename src/main/java/xonin/backhand/mixins/early/{ => minecraft}/MixinPlayerControllerMP.java (95%) rename src/main/java/xonin/backhand/mixins/early/{ => minecraft}/MixinWorld.java (94%) create mode 100644 src/main/resources/mixins.backhand.late.json diff --git a/src/main/java/xonin/backhand/BackhandLateMixins.java b/src/main/java/xonin/backhand/BackhandLateMixins.java new file mode 100644 index 0000000..787e527 --- /dev/null +++ b/src/main/java/xonin/backhand/BackhandLateMixins.java @@ -0,0 +1,23 @@ +package xonin.backhand; + +import java.util.List; +import java.util.Set; + +import com.gtnewhorizon.gtnhmixins.ILateMixinLoader; +import com.gtnewhorizon.gtnhmixins.LateMixin; + +import xonin.backhand.mixins.Mixins; + +@LateMixin +public class BackhandLateMixins implements ILateMixinLoader { + + @Override + public String getMixinConfig() { + return "mixins.backhand.late.json"; + } + + @Override + public List getMixins(Set loadedMods) { + return Mixins.getLateMixins(loadedMods); + } +} diff --git a/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java b/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java index b7d2bb0..4121874 100644 --- a/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java +++ b/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java @@ -1,14 +1,13 @@ package xonin.backhand.coremod; -import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import com.gtnewhorizon.gtnhmixins.IEarlyMixinLoader; -import cpw.mods.fml.relauncher.FMLLaunchHandler; import cpw.mods.fml.relauncher.IFMLLoadingPlugin; +import xonin.backhand.mixins.Mixins; public final class BackhandLoadingPlugin implements IFMLLoadingPlugin, IEarlyMixinLoader { @@ -42,24 +41,6 @@ public String getMixinConfig() { @Override public List getMixins(Set loadedCoreMods) { - final List mixins = new ArrayList<>(); - mixins.add("MixinEntityPlayer"); - mixins.add("MixinEntityPlayerMP"); - mixins.add("MixinItemStack"); - mixins.add("MixinNetHandlerPlayServer"); - mixins.add("MixinEntityItem"); - if (FMLLaunchHandler.side() - .isClient()) { - mixins.add("MixinEntityOtherPlayerMP"); - mixins.add("MixinEntityPlayerClient"); - mixins.add("MixinItemRenderer"); - mixins.add("MixinModelBiped"); - mixins.add("MixinNetHandlerPlayClient"); - mixins.add("MixinPlayerControllerMP"); - mixins.add("MixinItemBow"); - mixins.add("MixinItemStackClient"); - mixins.add("MixinWorld"); - } - return mixins; + return Mixins.getEarlyMixins(loadedCoreMods); } } diff --git a/src/main/java/xonin/backhand/mixins/Mixins.java b/src/main/java/xonin/backhand/mixins/Mixins.java new file mode 100644 index 0000000..2bcec48 --- /dev/null +++ b/src/main/java/xonin/backhand/mixins/Mixins.java @@ -0,0 +1,199 @@ +package xonin.backhand.mixins; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +import cpw.mods.fml.relauncher.FMLLaunchHandler; +import xonin.backhand.Backhand; + +public enum Mixins { + + MINECRAFT(new Builder("Shared MC Mixins") + .addMixinClasses( + "minecraft.MixinEntityPlayer", + "minecraft.MixinEntityPlayerMP", + "minecraft.MixinItemStack", + "minecraft.MixinNetHandlerPlayServer", + "minecraft.MixinEntityItem") + .setPhase(Phase.EARLY) + .setSide(Side.BOTH) + .addTargetedMod(TargetedMod.VANILLA)), + MINECRAFT_CLIENT(new Builder("Client MC Mixins") + .addMixinClasses( + "minecraft.MixinEntityOtherPlayerMP", + "minecraft.MixinEntityPlayerClient", + "minecraft.MixinItemRenderer", + "minecraft.MixinModelBiped", + "minecraft.MixinNetHandlerPlayClient", + "minecraft.MixinPlayerControllerMP", + "minecraft.MixinItemBow", + "minecraft.MixinItemStackClient", + "minecraft.MixinWorld") + .setPhase(Phase.EARLY) + .setSide(Side.CLIENT) + .addTargetedMod(TargetedMod.VANILLA)); + + private final List mixinClasses; + private final Supplier applyIf; + private final Phase phase; + private final Side side; + private final List targetedMods; + private final List excludedMods; + + Mixins(Builder builder) { + this.mixinClasses = builder.mixinClasses; + this.applyIf = builder.applyIf; + this.side = builder.side; + this.targetedMods = builder.targetedMods; + this.excludedMods = builder.excludedMods; + this.phase = builder.phase; + if (this.targetedMods.isEmpty()) { + throw new RuntimeException("No targeted mods specified for " + this.name()); + } + if (this.applyIf == null) { + throw new RuntimeException("No ApplyIf function specified for " + this.name()); + } + } + + public static List getEarlyMixins(Set loadedCoreMods) { + // This may be possible to handle differently or fix. + final List mixins = new ArrayList<>(); + final List notLoading = new ArrayList<>(); + for (Mixins mixin : Mixins.values()) { + if (mixin.phase == Phase.EARLY) { + if (mixin.shouldLoad(loadedCoreMods, Collections.emptySet())) { + mixins.addAll(mixin.mixinClasses); + } else { + notLoading.addAll(mixin.mixinClasses); + } + } + } + Backhand.LOGGER.info("Not loading the following EARLY mixins: {}", notLoading); + return mixins; + } + + public static List getLateMixins(Set loadedMods) { + final List mixins = new ArrayList<>(); + final List notLoading = new ArrayList<>(); + for (Mixins mixin : Mixins.values()) { + if (mixin.phase == Phase.LATE) { + if (mixin.shouldLoad(Collections.emptySet(), loadedMods)) { + mixins.addAll(mixin.mixinClasses); + } else { + notLoading.addAll(mixin.mixinClasses); + } + } + } + Backhand.LOGGER.info("Not loading the following LATE mixins: {}", notLoading.toString()); + return mixins; + } + + private boolean shouldLoadSide() { + return side == Side.BOTH || (side == Side.SERVER && FMLLaunchHandler.side() + .isServer()) + || (side == Side.CLIENT && FMLLaunchHandler.side() + .isClient()); + } + + private boolean allModsLoaded(List targetedMods, Set loadedCoreMods, Set loadedMods) { + if (targetedMods.isEmpty()) return false; + + for (TargetedMod target : targetedMods) { + if (target == TargetedMod.VANILLA) continue; + + // Check coremod first + if (!loadedCoreMods.isEmpty() && target.coreModClass != null + && !loadedCoreMods.contains(target.coreModClass)) return false; + else if (!loadedMods.isEmpty() && target.modId != null && !loadedMods.contains(target.modId)) return false; + } + + return true; + } + + private boolean noModsLoaded(List targetedMods, Set loadedCoreMods, Set loadedMods) { + if (targetedMods.isEmpty()) return true; + + for (TargetedMod target : targetedMods) { + if (target == TargetedMod.VANILLA) continue; + + // Check coremod first + if (!loadedCoreMods.isEmpty() && target.coreModClass != null + && loadedCoreMods.contains(target.coreModClass)) return false; + else if (!loadedMods.isEmpty() && target.modId != null && loadedMods.contains(target.modId)) return false; + } + + return true; + } + + private boolean shouldLoad(Set loadedCoreMods, Set loadedMods) { + return (shouldLoadSide() && applyIf.get() + && allModsLoaded(targetedMods, loadedCoreMods, loadedMods) + && noModsLoaded(excludedMods, loadedCoreMods, loadedMods)); + } + + private static class Builder { + + private final List mixinClasses = new ArrayList<>(); + private Supplier applyIf = () -> true; + private Side side = Side.BOTH; + private Phase phase = Phase.LATE; + private final List targetedMods = new ArrayList<>(); + private final List excludedMods = new ArrayList<>(); + + public Builder(@SuppressWarnings("unused") String description) {} + + public Builder addMixinClasses(String... mixinClasses) { + this.mixinClasses.addAll(Arrays.asList(mixinClasses)); + return this; + } + + public Builder setPhase(Phase phase) { + this.phase = phase; + return this; + } + + public Builder setSide(Side side) { + this.side = side; + return this; + } + + public Builder setApplyIf(Supplier applyIf) { + this.applyIf = applyIf; + return this; + } + + public Builder addTargetedMod(TargetedMod mod) { + this.targetedMods.add(mod); + return this; + } + + public Builder addExcludedMod(TargetedMod mod) { + this.excludedMods.add(mod); + return this; + } + } + + @SuppressWarnings("SimplifyStreamApiCallChains") + private static String[] addPrefix(String prefix, String... values) { + return Arrays.stream(values) + .map(s -> prefix + s) + .collect(Collectors.toList()) + .toArray(new String[values.length]); + } + + private enum Side { + BOTH, + CLIENT, + SERVER + } + + private enum Phase { + EARLY, + LATE, + } +} diff --git a/src/main/java/xonin/backhand/mixins/TargetedMod.java b/src/main/java/xonin/backhand/mixins/TargetedMod.java new file mode 100644 index 0000000..5c3abda --- /dev/null +++ b/src/main/java/xonin/backhand/mixins/TargetedMod.java @@ -0,0 +1,29 @@ +package xonin.backhand.mixins; + +public enum TargetedMod { + + VANILLA("Minecraft", null), + CARPENTERS_BLOCKS("Carpenter's Blocks", null, "CarpentersBlocks"); + + /** The "name" in the @Mod annotation */ + public final String modName; + /** Class that implements the IFMLLoadingPlugin interface */ + public final String coreModClass; + /** The "modid" in the @Mod annotation */ + public final String modId; + + TargetedMod(String modName, String coreModClass) { + this(modName, coreModClass, null); + } + + TargetedMod(String modName, String coreModClass, String modId) { + this.modName = modName; + this.coreModClass = coreModClass; + this.modId = modId; + } + + @Override + public String toString() { + return "TargetedMod{modName='" + modName + "', coreModClass='" + coreModClass + "', modId='" + modId + "'}"; + } +} diff --git a/src/main/java/xonin/backhand/mixins/early/MixinEntityItem.java b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinEntityItem.java similarity index 94% rename from src/main/java/xonin/backhand/mixins/early/MixinEntityItem.java rename to src/main/java/xonin/backhand/mixins/early/minecraft/MixinEntityItem.java index e2f8055..fccf7cd 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinEntityItem.java +++ b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinEntityItem.java @@ -1,4 +1,4 @@ -package xonin.backhand.mixins.early; +package xonin.backhand.mixins.early.minecraft; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; diff --git a/src/main/java/xonin/backhand/mixins/early/MixinEntityOtherPlayerMP.java b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinEntityOtherPlayerMP.java similarity index 97% rename from src/main/java/xonin/backhand/mixins/early/MixinEntityOtherPlayerMP.java rename to src/main/java/xonin/backhand/mixins/early/minecraft/MixinEntityOtherPlayerMP.java index ac499e7..84cd711 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinEntityOtherPlayerMP.java +++ b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinEntityOtherPlayerMP.java @@ -1,4 +1,4 @@ -package xonin.backhand.mixins.early; +package xonin.backhand.mixins.early.minecraft; import net.minecraft.client.entity.AbstractClientPlayer; import net.minecraft.client.entity.EntityOtherPlayerMP; diff --git a/src/main/java/xonin/backhand/mixins/early/MixinEntityPlayer.java b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinEntityPlayer.java similarity index 99% rename from src/main/java/xonin/backhand/mixins/early/MixinEntityPlayer.java rename to src/main/java/xonin/backhand/mixins/early/minecraft/MixinEntityPlayer.java index 5a01b4c..7086937 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinEntityPlayer.java +++ b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinEntityPlayer.java @@ -1,4 +1,4 @@ -package xonin.backhand.mixins.early; +package xonin.backhand.mixins.early.minecraft; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; diff --git a/src/main/java/xonin/backhand/mixins/early/MixinEntityPlayerClient.java b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinEntityPlayerClient.java similarity index 97% rename from src/main/java/xonin/backhand/mixins/early/MixinEntityPlayerClient.java rename to src/main/java/xonin/backhand/mixins/early/minecraft/MixinEntityPlayerClient.java index 447740b..0bd95bd 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinEntityPlayerClient.java +++ b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinEntityPlayerClient.java @@ -1,4 +1,4 @@ -package xonin.backhand.mixins.early; +package xonin.backhand.mixins.early.minecraft; import net.minecraft.client.Minecraft; import net.minecraft.entity.EntityLivingBase; diff --git a/src/main/java/xonin/backhand/mixins/early/MixinEntityPlayerMP.java b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinEntityPlayerMP.java similarity index 95% rename from src/main/java/xonin/backhand/mixins/early/MixinEntityPlayerMP.java rename to src/main/java/xonin/backhand/mixins/early/minecraft/MixinEntityPlayerMP.java index 576a4c1..3dcba09 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinEntityPlayerMP.java +++ b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinEntityPlayerMP.java @@ -1,4 +1,4 @@ -package xonin.backhand.mixins.early; +package xonin.backhand.mixins.early.minecraft; import java.util.List; diff --git a/src/main/java/xonin/backhand/mixins/early/MixinItemBow.java b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinItemBow.java similarity index 95% rename from src/main/java/xonin/backhand/mixins/early/MixinItemBow.java rename to src/main/java/xonin/backhand/mixins/early/minecraft/MixinItemBow.java index 682bc2f..9f51e62 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinItemBow.java +++ b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinItemBow.java @@ -1,4 +1,4 @@ -package xonin.backhand.mixins.early; +package xonin.backhand.mixins.early.minecraft; import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; diff --git a/src/main/java/xonin/backhand/mixins/early/MixinItemRenderer.java b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinItemRenderer.java similarity index 97% rename from src/main/java/xonin/backhand/mixins/early/MixinItemRenderer.java rename to src/main/java/xonin/backhand/mixins/early/minecraft/MixinItemRenderer.java index 5ad5af5..f9a2f53 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinItemRenderer.java +++ b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinItemRenderer.java @@ -1,4 +1,4 @@ -package xonin.backhand.mixins.early; +package xonin.backhand.mixins.early.minecraft; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.ItemRenderer; diff --git a/src/main/java/xonin/backhand/mixins/early/MixinItemStack.java b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinItemStack.java similarity index 96% rename from src/main/java/xonin/backhand/mixins/early/MixinItemStack.java rename to src/main/java/xonin/backhand/mixins/early/minecraft/MixinItemStack.java index d02f418..8c21b0c 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinItemStack.java +++ b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinItemStack.java @@ -1,4 +1,4 @@ -package xonin.backhand.mixins.early; +package xonin.backhand.mixins.early.minecraft; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; diff --git a/src/main/java/xonin/backhand/mixins/early/MixinItemStackClient.java b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinItemStackClient.java similarity index 97% rename from src/main/java/xonin/backhand/mixins/early/MixinItemStackClient.java rename to src/main/java/xonin/backhand/mixins/early/minecraft/MixinItemStackClient.java index f0c9916..5ee3bd4 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinItemStackClient.java +++ b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinItemStackClient.java @@ -1,4 +1,4 @@ -package xonin.backhand.mixins.early; +package xonin.backhand.mixins.early.minecraft; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.EnumAction; diff --git a/src/main/java/xonin/backhand/mixins/early/MixinModelBiped.java b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinModelBiped.java similarity index 98% rename from src/main/java/xonin/backhand/mixins/early/MixinModelBiped.java rename to src/main/java/xonin/backhand/mixins/early/minecraft/MixinModelBiped.java index 7e6db57..4ba3936 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinModelBiped.java +++ b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinModelBiped.java @@ -1,4 +1,4 @@ -package xonin.backhand.mixins.early; +package xonin.backhand.mixins.early.minecraft; import net.minecraft.client.Minecraft; import net.minecraft.client.model.ModelBase; diff --git a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayClient.java b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinNetHandlerPlayClient.java similarity index 94% rename from src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayClient.java rename to src/main/java/xonin/backhand/mixins/early/minecraft/MixinNetHandlerPlayClient.java index fa0be3e..b9c5984 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayClient.java +++ b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinNetHandlerPlayClient.java @@ -1,4 +1,4 @@ -package xonin.backhand.mixins.early; +package xonin.backhand.mixins.early.minecraft; import net.minecraft.client.network.NetHandlerPlayClient; diff --git a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinNetHandlerPlayServer.java similarity index 99% rename from src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java rename to src/main/java/xonin/backhand/mixins/early/minecraft/MixinNetHandlerPlayServer.java index de1593d..dc6261e 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java +++ b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinNetHandlerPlayServer.java @@ -1,4 +1,4 @@ -package xonin.backhand.mixins.early; +package xonin.backhand.mixins.early.minecraft; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.EnumAction; diff --git a/src/main/java/xonin/backhand/mixins/early/MixinPlayerControllerMP.java b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinPlayerControllerMP.java similarity index 95% rename from src/main/java/xonin/backhand/mixins/early/MixinPlayerControllerMP.java rename to src/main/java/xonin/backhand/mixins/early/minecraft/MixinPlayerControllerMP.java index 6dc2595..4c3179c 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinPlayerControllerMP.java +++ b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinPlayerControllerMP.java @@ -1,4 +1,4 @@ -package xonin.backhand.mixins.early; +package xonin.backhand.mixins.early.minecraft; import net.minecraft.client.multiplayer.PlayerControllerMP; diff --git a/src/main/java/xonin/backhand/mixins/early/MixinWorld.java b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinWorld.java similarity index 94% rename from src/main/java/xonin/backhand/mixins/early/MixinWorld.java rename to src/main/java/xonin/backhand/mixins/early/minecraft/MixinWorld.java index 28859e8..96256dc 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinWorld.java +++ b/src/main/java/xonin/backhand/mixins/early/minecraft/MixinWorld.java @@ -1,4 +1,4 @@ -package xonin.backhand.mixins.early; +package xonin.backhand.mixins.early.minecraft; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; diff --git a/src/main/resources/mixins.backhand.late.json b/src/main/resources/mixins.backhand.late.json new file mode 100644 index 0000000..3f282dd --- /dev/null +++ b/src/main/resources/mixins.backhand.late.json @@ -0,0 +1,11 @@ +{ + "required": true, + "minVersion": "0.8.5-GTNH", + "package": "xonin.backhand.mixins.late", + "refmap": "mixins.backhand.refmap.json", + "target": "@env(DEFAULT)", + "compatibilityLevel": "JAVA_8", + "mixins": [], + "client": [], + "server": [] +} From ecfffe38b920f56b63365ecc4450589dc51b6e8e Mon Sep 17 00:00:00 2001 From: Lyfts <127234178+Lyfts@users.noreply.github.com> Date: Mon, 5 Aug 2024 15:27:22 +0200 Subject: [PATCH 14/16] fix carpenters blocks silliness --- dependencies.gradle | 1 + .../java/xonin/backhand/mixins/Mixins.java | 7 +++++- .../MixinPlayerPermissions.java | 25 +++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/main/java/xonin/backhand/mixins/late/carpentersblocks/MixinPlayerPermissions.java diff --git a/dependencies.gradle b/dependencies.gradle index 64652c2..9a2a176 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -37,4 +37,5 @@ dependencies { runtimeOnlyNonPublishable("com.github.GTNewHorizons:NotEnoughItems:2.6.14-GTNH:dev") compileOnly("com.github.GTNewHorizons:inventory-tweaks:1.6.2:dev") compileOnly(deobf("https://github.com/Roadhog360/Et-Futurum-Requiem/releases/download/2.6.0/Et_Futurum_Requiem-2.6.0-nomixin.jar", "Et Futurum Requiem")) + compileOnly("com.github.GTNewHorizons:CarpentersBlocks:3.6.2-GTNH:dev") } diff --git a/src/main/java/xonin/backhand/mixins/Mixins.java b/src/main/java/xonin/backhand/mixins/Mixins.java index 2bcec48..1ddfca6 100644 --- a/src/main/java/xonin/backhand/mixins/Mixins.java +++ b/src/main/java/xonin/backhand/mixins/Mixins.java @@ -36,7 +36,12 @@ public enum Mixins { "minecraft.MixinWorld") .setPhase(Phase.EARLY) .setSide(Side.CLIENT) - .addTargetedMod(TargetedMod.VANILLA)); + .addTargetedMod(TargetedMod.VANILLA)), + FIX_SIMULATED_INTERACTION_NPE(new Builder("Fix NPE when simulating interaction with CB blocks") + .addMixinClasses("carpentersblocks.MixinPlayerPermissions") + .setPhase(Phase.LATE) + .setSide(Side.CLIENT) + .addTargetedMod(TargetedMod.CARPENTERS_BLOCKS)); private final List mixinClasses; private final Supplier applyIf; diff --git a/src/main/java/xonin/backhand/mixins/late/carpentersblocks/MixinPlayerPermissions.java b/src/main/java/xonin/backhand/mixins/late/carpentersblocks/MixinPlayerPermissions.java new file mode 100644 index 0000000..39de8b9 --- /dev/null +++ b/src/main/java/xonin/backhand/mixins/late/carpentersblocks/MixinPlayerPermissions.java @@ -0,0 +1,25 @@ +package xonin.backhand.mixins.late.carpentersblocks; + +import net.minecraft.entity.player.EntityPlayer; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import com.carpentersblocks.util.protection.IProtected; +import com.carpentersblocks.util.protection.PlayerPermissions; + +import xonin.backhand.client.world.ClientFakePlayer; + +@Mixin(value = PlayerPermissions.class, remap = false) +public abstract class MixinPlayerPermissions { + + @Inject(method = "hasElevatedPermission", at = @At(value = "HEAD"), cancellable = true) + private static void backhand$fixFakePlayerNPE(IProtected object, EntityPlayer entityPlayer, + boolean enforceOwnership, CallbackInfoReturnable cir) { + if (entityPlayer instanceof ClientFakePlayer) { + cir.setReturnValue(true); + } + } +} From a4859cb2dd67fcd59c336aef263f9986f5e54c3e Mon Sep 17 00:00:00 2001 From: Lyfts <127234178+Lyfts@users.noreply.github.com> Date: Mon, 5 Aug 2024 16:30:04 +0200 Subject: [PATCH 15/16] adds gtnhlib dep, copy more potentially important player values, properly reset fake world & remove tile copying for now --- dependencies.gradle | 1 + src/main/java/xonin/backhand/Backhand.java | 1 + .../client/utils/BackhandClientUtils.java | 26 +--------- .../client/world/ClientFakePlayer.java | 51 +++++++++++++++---- .../backhand/client/world/DummyWorld.java | 44 +++++++++++----- 5 files changed, 74 insertions(+), 49 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 9a2a176..7080469 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -34,6 +34,7 @@ * For more details, see https://docs.gradle.org/8.0.1/userguide/java_library_plugin.html#sec:java_library_configurations_graph */ dependencies { + api("com.github.GTNewHorizons:GTNHLib:0.4.0:dev") runtimeOnlyNonPublishable("com.github.GTNewHorizons:NotEnoughItems:2.6.14-GTNH:dev") compileOnly("com.github.GTNewHorizons:inventory-tweaks:1.6.2:dev") compileOnly(deobf("https://github.com/Roadhog360/Et-Futurum-Requiem/releases/download/2.6.0/Et_Futurum_Requiem-2.6.0-nomixin.jar", "Et Futurum Requiem")) diff --git a/src/main/java/xonin/backhand/Backhand.java b/src/main/java/xonin/backhand/Backhand.java index b6f56ba..ff22a85 100644 --- a/src/main/java/xonin/backhand/Backhand.java +++ b/src/main/java/xonin/backhand/Backhand.java @@ -22,6 +22,7 @@ modid = Backhand.MODID, name = "Backhand", version = Tags.VERSION, + dependencies = "required-after:gtnhlib@[0.3.2,)", guiFactory = "xonin.backhand.client.gui.BackhandGuiFactory") public class Backhand { diff --git a/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java b/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java index a75161d..5884697 100644 --- a/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java +++ b/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java @@ -1,15 +1,10 @@ package xonin.backhand.client.utils; -import net.minecraft.block.Block; -import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityOtherPlayerMP; -import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; -import net.minecraft.util.MovingObjectPosition; import xonin.backhand.api.core.BackhandUtils; import xonin.backhand.client.world.ClientFakePlayer; -import xonin.backhand.client.world.DummyWorld; public final class BackhandClientUtils { @@ -42,25 +37,6 @@ public static boolean entityOtherPlayerIsItemInUseHook(EntityOtherPlayerMP playe } public static boolean canBlockBeInteractedWith(ItemStack offhand, int x, int y, int z) { - Minecraft mc = Minecraft.getMinecraft(); - MovingObjectPosition mop = mc.objectMouseOver; - ItemStack stack = ItemStack.copyItemStack(offhand); - - if (mop == null) return false; - - float subX = (float) mop.hitVec.xCoord - x; - float subY = (float) mop.hitVec.yCoord - y; - float subZ = (float) mop.hitVec.zCoord - z; - - // Needs to be done before and after placing the block to ensure - // that the block placement didn't change the item or player position - ClientFakePlayer.INSTANCE.prepareForInteraction(mc.thePlayer, stack); - Block block = DummyWorld.INSTANCE.copyAndSetBlock(mc.theWorld, x, y, z, mop); - if (block == null || block == Blocks.air) return false; - - ClientFakePlayer.INSTANCE.prepareForInteraction(mc.thePlayer, stack); - - return block - .onBlockActivated(DummyWorld.INSTANCE, x, y, z, ClientFakePlayer.INSTANCE, mop.sideHit, subX, subY, subZ); + return ClientFakePlayer.INSTANCE.simulateBlockInteraction(offhand, x, y, z); } } diff --git a/src/main/java/xonin/backhand/client/world/ClientFakePlayer.java b/src/main/java/xonin/backhand/client/world/ClientFakePlayer.java index 14b71f0..7e3f4e0 100644 --- a/src/main/java/xonin/backhand/client/world/ClientFakePlayer.java +++ b/src/main/java/xonin/backhand/client/world/ClientFakePlayer.java @@ -2,12 +2,16 @@ import java.util.UUID; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; import net.minecraft.stats.StatBase; import net.minecraft.util.ChunkCoordinates; import net.minecraft.util.DamageSource; import net.minecraft.util.IChatComponent; +import net.minecraft.util.MovingObjectPosition; import net.minecraft.world.World; import com.mojang.authlib.GameProfile; @@ -53,23 +57,50 @@ public boolean canAttackPlayer(EntityPlayer player) { } @Override - public void onDeath(DamageSource source) { - return; - } + public void onDeath(DamageSource source) {} @Override - public void onUpdate() { - return; - } + public void onUpdate() {} @Override - public void travelToDimension(int dim) { - return; + public void travelToDimension(int dim) {} + + public boolean simulateBlockInteraction(ItemStack offhand, int x, int y, int z) { + Minecraft mc = Minecraft.getMinecraft(); + MovingObjectPosition mop = mc.objectMouseOver; + ItemStack stack = ItemStack.copyItemStack(offhand); + + if (mop == null) return false; + + float subX = (float) mop.hitVec.xCoord - x; + float subY = (float) mop.hitVec.yCoord - y; + float subZ = (float) mop.hitVec.zCoord - z; + + copyPlayerPosition(mc.thePlayer); + Block block = DummyWorld.INSTANCE.copyAndSetBlock(mc.theWorld, x, y, z, mop); + + if (block == null || block == Blocks.air) return false; + + prepareForInteraction(mc.thePlayer, stack); + return block.onBlockActivated(DummyWorld.INSTANCE, x, y, z, this, mop.sideHit, subX, subY, subZ); + } + + private void prepareForInteraction(EntityPlayer player, ItemStack stack) { + copyPlayerPosition(player); + inventory.copyInventory(player.inventory); + setCurrentItemOrArmor(0, stack); + experienceLevel = player.experienceLevel; + experienceTotal = player.experienceTotal; + experience = player.experience; + capabilities = player.capabilities; + isAirBorne = player.isAirBorne; + inWater = player.isInWater(); + fallDistance = player.fallDistance; + this.setSprinting(player.isSprinting()); } - public void prepareForInteraction(EntityPlayer player, ItemStack stack) { + public void copyPlayerPosition(EntityPlayer player) { this.setPositionAndRotation(player.posX, player.posY, player.posZ, player.rotationYaw, player.rotationPitch); - this.setCurrentItemOrArmor(0, stack); this.setSneaking(player.isSneaking()); } } diff --git a/src/main/java/xonin/backhand/client/world/DummyWorld.java b/src/main/java/xonin/backhand/client/world/DummyWorld.java index ed1036e..e1858d3 100644 --- a/src/main/java/xonin/backhand/client/world/DummyWorld.java +++ b/src/main/java/xonin/backhand/client/world/DummyWorld.java @@ -7,9 +7,7 @@ import net.minecraft.entity.Entity; import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; import net.minecraft.profiler.Profiler; -import net.minecraft.tileentity.TileEntity; import net.minecraft.util.MovingObjectPosition; import net.minecraft.world.EnumSkyBlock; import net.minecraft.world.World; @@ -18,6 +16,11 @@ import net.minecraft.world.WorldType; import net.minecraft.world.chunk.IChunkProvider; +import com.gtnewhorizon.gtnhlib.util.CoordinatePacker; + +import it.unimi.dsi.fastutil.longs.LongOpenHashSet; +import it.unimi.dsi.fastutil.longs.LongSet; + public class DummyWorld extends World { private static final WorldSettings DEFAULT_SETTINGS = new WorldSettings( @@ -28,6 +31,7 @@ public class DummyWorld extends World { WorldType.DEFAULT); public static final DummyWorld INSTANCE = new DummyWorld(); + private static final LongSet placedBlocks = new LongOpenHashSet(); public DummyWorld() { super(new DummySaveHandler(), "DummyServer", DEFAULT_SETTINGS, new WorldProviderSurface(), new Profiler()); @@ -68,6 +72,18 @@ protected boolean chunkExists(int x, int z) { return chunkProvider.chunkExists(x, z); } + @Override + public boolean setBlock(int x, int y, int z, Block blockIn, int metadataIn, int flags) { + if (super.setBlock(x, y, z, blockIn, metadataIn, flags)) { + long key = CoordinatePacker.pack(x, y, z); + if (blockIn != Blocks.air) { + placedBlocks.add(key); + } + return true; + } + return false; + } + @Override public boolean updateLightByType(EnumSkyBlock p_147463_1_, int p_147463_2_, int p_147463_3_, int p_147463_4_) { return true; @@ -75,6 +91,7 @@ public boolean updateLightByType(EnumSkyBlock p_147463_1_, int p_147463_2_, int @Nullable public Block copyAndSetBlock(World world, int x, int y, int z, MovingObjectPosition mop) { + resetWorld(); Block block = world.getBlock(x, y, z); if (block == null || block == Blocks.air) return null; @@ -99,18 +116,17 @@ public Block copyAndSetBlock(World world, int x, int y, int z, MovingObjectPosit setBlock(x, y, z, block, meta, 3); } - TileEntity tile = world.getTileEntity(x, y, z); - if (tile != null) { - NBTTagCompound tag = new NBTTagCompound(); - tile.writeToNBT(tag); - TileEntity dummyTile = getTileEntity(x, y, z); - if (dummyTile == null) { - dummyTile = TileEntity.createAndLoadEntity(tag); - setTileEntity(x, y, z, dummyTile); - } - dummyTile.readFromNBT(tag); - } - return getBlock(x, y, z); } + + private void resetWorld() { + if (placedBlocks.isEmpty()) return; + for (long key : placedBlocks) { + int x = CoordinatePacker.unpackX(key); + int y = CoordinatePacker.unpackY(key); + int z = CoordinatePacker.unpackZ(key); + setBlockToAir(x, y, z); + } + placedBlocks.clear(); + } } From 18d0351312708e5038aec920a2e0a6dedca69574 Mon Sep 17 00:00:00 2001 From: Lyfts <127234178+Lyfts@users.noreply.github.com> Date: Tue, 6 Aug 2024 20:44:06 +0200 Subject: [PATCH 16/16] try-catch the fake player interaction --- .../xonin/backhand/client/world/ClientFakePlayer.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/xonin/backhand/client/world/ClientFakePlayer.java b/src/main/java/xonin/backhand/client/world/ClientFakePlayer.java index 7e3f4e0..2e60b0f 100644 --- a/src/main/java/xonin/backhand/client/world/ClientFakePlayer.java +++ b/src/main/java/xonin/backhand/client/world/ClientFakePlayer.java @@ -82,7 +82,13 @@ public boolean simulateBlockInteraction(ItemStack offhand, int x, int y, int z) if (block == null || block == Blocks.air) return false; prepareForInteraction(mc.thePlayer, stack); - return block.onBlockActivated(DummyWorld.INSTANCE, x, y, z, this, mop.sideHit, subX, subY, subZ); + + try { + return block.onBlockActivated(DummyWorld.INSTANCE, x, y, z, this, mop.sideHit, subX, subY, subZ); + } catch (Exception e) { + // Something went wrong, block the offhand interaction + return true; + } } private void prepareForInteraction(EntityPlayer player, ItemStack stack) {