From 92fda4d25c5bdf299012ff539ba4491939e7219a Mon Sep 17 00:00:00 2001 From: Lyfts <127234178+Lyfts@users.noreply.github.com> Date: Thu, 25 Jul 2024 17:14:14 +0200 Subject: [PATCH 1/9] begin converting mysterium patches & some bg transformers to mixin --- gradle.properties | 6 +- .../asm/fixes/MysteriumPatchesFixesO.java | 979 +++++++++--------- .../client/BackhandClientTickHandler.java | 4 +- .../backhand/client/ClientEventHandler.java | 2 +- .../backhand/client/ClientTickHandler.java | 2 +- .../client/utils/BackhandClientUtils.java | 11 + .../client/utils/BackhandRenderHelper.java | 24 +- .../coremod/BackhandLoadingPlugin.java | 37 +- .../transformers/ModelBipedTransformer.java | 67 -- .../PlayerControllerMPTransformer.java | 1 + .../early/MixinEntityOtherPlayerMP.java | 48 + .../mixins/early/MixinEntityPlayer.java | 207 ++++ .../mixins/early/MixinEntityPlayerMP.java | 31 + .../mixins/early/MixinInventoryPlayer.java | 266 +++++ .../early/MixinInventoryPlayerClient.java | 39 + .../backhand/mixins/early/MixinItemBow.java | 31 + .../mixins/early/MixinItemRenderer.java | 56 + .../backhand/mixins/early/MixinItemStack.java | 61 ++ .../mixins/early/MixinModelBiped.java | 176 ++++ .../early/MixinNetHandlerPlayClient.java | 43 + .../early/MixinNetHandlerPlayServer.java | 65 ++ .../mixins/early/MixinPlayerControllerMP.java | 69 ++ .../packet/OffhandConfigSyncPacket.java | 4 +- .../packet/OffhandWorldHotswapPacket.java | 4 +- src/main/resources/mixins.backhand.early.json | 11 + src/main/resources/mixins.backhand.json | 11 + 26 files changed, 1648 insertions(+), 607 deletions(-) delete mode 100644 src/main/java/xonin/backhand/coremod/transformers/ModelBipedTransformer.java create mode 100644 src/main/java/xonin/backhand/mixins/early/MixinEntityOtherPlayerMP.java create mode 100644 src/main/java/xonin/backhand/mixins/early/MixinEntityPlayer.java create mode 100644 src/main/java/xonin/backhand/mixins/early/MixinEntityPlayerMP.java create mode 100644 src/main/java/xonin/backhand/mixins/early/MixinInventoryPlayer.java create mode 100644 src/main/java/xonin/backhand/mixins/early/MixinInventoryPlayerClient.java create mode 100644 src/main/java/xonin/backhand/mixins/early/MixinItemBow.java create mode 100644 src/main/java/xonin/backhand/mixins/early/MixinItemRenderer.java create mode 100644 src/main/java/xonin/backhand/mixins/early/MixinItemStack.java create mode 100644 src/main/java/xonin/backhand/mixins/early/MixinModelBiped.java create mode 100644 src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayClient.java create mode 100644 src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java create mode 100644 src/main/java/xonin/backhand/mixins/early/MixinPlayerControllerMP.java create mode 100644 src/main/resources/mixins.backhand.early.json create mode 100644 src/main/resources/mixins.backhand.json diff --git a/gradle.properties b/gradle.properties index d426cfc..0812a22 100644 --- a/gradle.properties +++ b/gradle.properties @@ -74,16 +74,16 @@ apiPackage = accessTransformersFile = backhand_at.cfg # Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled! -usesMixins = false +usesMixins = true # Adds some debug arguments like verbose output and class export. -usesMixinDebug = false +usesMixinDebug = true # Specify the location of your implementation of IMixinConfigPlugin. Leave it empty otherwise. mixinPlugin = # Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail! -mixinsPackage = +mixinsPackage = mixins # Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin! # This parameter is for legacy compatibility only diff --git a/src/main/java/net/tclproject/mysteriumlib/asm/fixes/MysteriumPatchesFixesO.java b/src/main/java/net/tclproject/mysteriumlib/asm/fixes/MysteriumPatchesFixesO.java index 8011871..77966e9 100644 --- a/src/main/java/net/tclproject/mysteriumlib/asm/fixes/MysteriumPatchesFixesO.java +++ b/src/main/java/net/tclproject/mysteriumlib/asm/fixes/MysteriumPatchesFixesO.java @@ -4,66 +4,32 @@ import java.lang.invoke.MethodHandles; import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.util.List; - -import net.minecraft.block.material.Material; -import net.minecraft.client.Minecraft; -import net.minecraft.client.entity.EntityClientPlayerMP; -import net.minecraft.client.gui.inventory.GuiContainerCreative; -import net.minecraft.client.model.ModelBiped; -import net.minecraft.client.multiplayer.PlayerControllerMP; -import net.minecraft.client.network.NetHandlerPlayClient; + import net.minecraft.client.particle.EffectRenderer; -import net.minecraft.client.renderer.ItemRenderer; import net.minecraft.client.renderer.entity.RendererLivingEntity; -import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.item.EntityXPOrb; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.entity.projectile.EntityArrow; -import net.minecraft.inventory.Container; -import net.minecraft.item.EnumAction; -import net.minecraft.item.ItemBow; -import net.minecraft.item.ItemMap; import net.minecraft.item.ItemStack; import net.minecraft.network.NetHandlerPlayServer; import net.minecraft.network.play.client.C02PacketUseEntity; -import net.minecraft.network.play.client.C07PacketPlayerDigging; -import net.minecraft.network.play.client.C09PacketHeldItemChange; -import net.minecraft.network.play.server.S23PacketBlockChange; -import net.minecraft.network.play.server.S2FPacketSetSlot; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.management.ItemInWorldManager; -import net.minecraft.util.IIcon; -import net.minecraft.util.MathHelper; import net.minecraft.util.MovingObjectPosition; import net.minecraft.world.WorldServer; -import net.minecraftforge.event.ForgeEventFactory; import net.tclproject.mysteriumlib.asm.annotations.EnumReturnSetting; import net.tclproject.mysteriumlib.asm.annotations.Fix; import net.tclproject.mysteriumlib.asm.annotations.ReturnedValue; -import org.lwjgl.opengl.GL11; - -import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.Optional; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import invtweaks.InvTweaksContainerManager; import invtweaks.InvTweaksContainerSectionManager; import invtweaks.api.container.ContainerSection; -import xonin.backhand.Backhand; -import xonin.backhand.HookContainerClass; import xonin.backhand.api.core.BackhandUtils; -import xonin.backhand.api.core.IBackhandPlayer; -import xonin.backhand.api.core.InventoryPlayerBackhand; -import xonin.backhand.client.BackhandClientTickHandler; import xonin.backhand.client.ClientEventHandler; -import xonin.backhand.client.renderer.RenderOffhandPlayer; public class MysteriumPatchesFixesO { @@ -71,112 +37,113 @@ public class MysteriumPatchesFixesO { * Dirty hack to prevent random resetting of block removal (why does this even happen?!) when breaking blocks with * the offhand. */ - public static int countToCancel = 0; - /** 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; - - public static boolean receivedConfigs = false; - - @Fix(returnSetting = EnumReturnSetting.ALWAYS) - public static boolean isPlayer(EntityPlayer p) { - return false; - } - - @Fix(insertOnExit = true) - public static void damageItem(ItemStack itemStack, int p_77972_1_, EntityLivingBase p_77972_2_) { - if (!(p_77972_2_ instanceof EntityPlayer) || itemStack == null) return; - - EntityPlayer player = (EntityPlayer) p_77972_2_; - ItemStack offhandItem = BackhandUtils.getOffhandItem(player); - if (offhandItem != null && itemStack == offhandItem && itemStack.stackSize == 0) { - BackhandUtils.setPlayerOffhandItem(player, null); - ForgeEventFactory.onPlayerDestroyItem(player, offhandItem); - } - } - - @Fix(insertOnExit = true, returnSetting = EnumReturnSetting.ALWAYS) - public static EnumAction getItemUseAction(ItemStack itemStack, @ReturnedValue EnumAction returnedAction) { - if (returnedAction != EnumAction.none) { - if (FMLCommonHandler.instance() - .getEffectiveSide() == Side.CLIENT && ClientEventHandler.renderingPlayer != null) { - EntityPlayer player = ClientEventHandler.renderingPlayer; - ItemStack offhandItem = BackhandUtils.getOffhandItem(player); - - if (offhandItem != null) { - ItemStack mainHandItem = player.getCurrentEquippedItem(); - if (mainHandItem != null && (BackhandUtils.checkForRightClickFunctionNoAction(mainHandItem) - || HookContainerClass.isItemBlock(mainHandItem.getItem()))) { - if (itemStack == offhandItem) { - return EnumAction.none; - } - } else if (itemStack == mainHandItem - && (!(BackhandUtils.checkForRightClickFunctionNoAction(offhandItem) - || HookContainerClass.isItemBlock(offhandItem.getItem())) - || player.getItemInUse() != mainHandItem)) { - return EnumAction.none; - } - } - } - } - return itemStack != null && itemStack.getItem() != null ? itemStack.getItem() - .getItemUseAction(itemStack) : EnumAction.none; - } - - private static boolean disableMainhandAnimation = false; - - @SideOnly(Side.CLIENT) - @Fix(insertOnExit = true, returnSetting = EnumReturnSetting.ALWAYS) - public static IIcon getItemIcon(EntityLivingBase entity, ItemStack p_70620_1_, int p_70620_2_, - @ReturnedValue IIcon returnValue) { - if (entity instanceof EntityPlayer) { - EntityPlayer player = (EntityPlayer) entity; - if (p_70620_1_ == player.getCurrentEquippedItem() && player.getCurrentEquippedItem() != null - && player.getItemInUse() != null - && player.getCurrentEquippedItem() - .getItem() instanceof ItemBow - && player.getCurrentEquippedItem() != player.getItemInUse()) { - disableMainhandAnimation = true; - } - } - return returnValue; - } - - @SideOnly(Side.CLIENT) - @Fix(insertOnExit = true, returnSetting = EnumReturnSetting.ALWAYS) - public static IIcon getItemIconForUseDuration(ItemBow bow, int p_94599_1_, @ReturnedValue IIcon returnValue) { - if (disableMainhandAnimation) { - disableMainhandAnimation = false; - EntityPlayer player = Minecraft.getMinecraft().thePlayer; - return bow.getIcon(player.getCurrentEquippedItem(), 0, player, player.getItemInUse(), 0); - } - return returnValue; - } + // public static int countToCancel = 0; + // /** 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; + // + // public static boolean receivedConfigs = false; - @SideOnly(Side.CLIENT) - @Fix(returnSetting = EnumReturnSetting.ON_TRUE) - public static boolean resetBlockRemoving(PlayerControllerMP controller) { - if (countToCancel > 0) { - countToCancel--; - return true; - } else { - if (MysteriumPatchesFixesO.hotSwapped) { - Minecraft.getMinecraft().playerController.syncCurrentPlayItem(); - MysteriumPatchesFixesO.hotSwapped = false; - } - return false; - } - } + // @Fix(returnSetting = EnumReturnSetting.ALWAYS) + // public static boolean isPlayer(EntityPlayer p) { + // return false; + // } - @Fix(returnSetting = EnumReturnSetting.ON_TRUE) - @SideOnly(Side.CLIENT) - public static boolean clickBlock(PlayerControllerMP mp, int p_78743_1_, int p_78743_2_, int p_78743_3_, - int p_78743_4_) { - if (ClientEventHandler.cancelone) { - mp.resetBlockRemoving(); - return true; - } - return false; - } + // @Fix(insertOnExit = true) + // public static void damageItem(ItemStack itemStack, int p_77972_1_, EntityLivingBase p_77972_2_) { + // if (!(p_77972_2_ instanceof EntityPlayer) || itemStack == null) return; + // + // EntityPlayer player = (EntityPlayer) p_77972_2_; + // ItemStack offhandItem = BackhandUtils.getOffhandItem(player); + // if (offhandItem != null && itemStack == offhandItem && itemStack.stackSize == 0) { + // BackhandUtils.setPlayerOffhandItem(player, null); + // ForgeEventFactory.onPlayerDestroyItem(player, offhandItem); + // } + // } + // + // @Fix(insertOnExit = true, returnSetting = EnumReturnSetting.ALWAYS) + // public static EnumAction getItemUseAction(ItemStack itemStack, @ReturnedValue EnumAction returnedAction) { + // if (returnedAction != EnumAction.none) { + // if (FMLCommonHandler.instance() + // .getEffectiveSide() == Side.CLIENT && ClientEventHandler.renderingPlayer != null) { + // EntityPlayer player = ClientEventHandler.renderingPlayer; + // ItemStack offhandItem = BackhandUtils.getOffhandItem(player); + // + // if (offhandItem != null) { + // ItemStack mainHandItem = player.getCurrentEquippedItem(); + // if (mainHandItem != null && (BackhandUtils.checkForRightClickFunctionNoAction(mainHandItem) + // || HookContainerClass.isItemBlock(mainHandItem.getItem()))) { + // if (itemStack == offhandItem) { + // return EnumAction.none; + // } + // } else if (itemStack == mainHandItem + // && (!(BackhandUtils.checkForRightClickFunctionNoAction(offhandItem) + // || HookContainerClass.isItemBlock(offhandItem.getItem())) + // || player.getItemInUse() != mainHandItem)) { + // return EnumAction.none; + // } + // } + // } + // } + // return itemStack != null && itemStack.getItem() != null ? itemStack.getItem() + // .getItemUseAction(itemStack) : EnumAction.none; + // } + + // private static boolean disableMainhandAnimation = false; + + // @SideOnly(Side.CLIENT) + // @Fix(insertOnExit = true, returnSetting = EnumReturnSetting.ALWAYS) + // public static IIcon getItemIcon(EntityLivingBase entity, ItemStack p_70620_1_, int p_70620_2_, + // @ReturnedValue IIcon returnValue) { + // if (entity instanceof EntityPlayer) { + // EntityPlayer player = (EntityPlayer) entity; + // if (p_70620_1_ == player.getCurrentEquippedItem() && player.getCurrentEquippedItem() != null + // && player.getItemInUse() != null + // && player.getCurrentEquippedItem() + // .getItem() instanceof ItemBow + // && player.getCurrentEquippedItem() != player.getItemInUse()) { + // disableMainhandAnimation = true; + // } + // } + // return returnValue; + // } + + // @SideOnly(Side.CLIENT) + // @Fix(insertOnExit = true, returnSetting = EnumReturnSetting.ALWAYS) + // public static IIcon getItemIconForUseDuration(ItemBow bow, int p_94599_1_, @ReturnedValue IIcon returnValue) { + // if (disableMainhandAnimation) { + // disableMainhandAnimation = false; + // EntityPlayer player = Minecraft.getMinecraft().thePlayer; + // return bow.getIcon(player.getCurrentEquippedItem(), 0, player, player.getItemInUse(), 0); + // } + // return returnValue; + // } + // + // @SideOnly(Side.CLIENT) + // @Fix(returnSetting = EnumReturnSetting.ON_TRUE) + // public static boolean resetBlockRemoving(PlayerControllerMP controller) { + // if (countToCancel > 0) { + // countToCancel--; + // return true; + // } else { + // if (MysteriumPatchesFixesO.hotSwapped) { + // Minecraft.getMinecraft().playerController.syncCurrentPlayItem(); + // MysteriumPatchesFixesO.hotSwapped = false; + // } + // return false; + // } + // } + + // @Fix(returnSetting = EnumReturnSetting.ON_TRUE) + // @SideOnly(Side.CLIENT) + // public static boolean clickBlock(PlayerControllerMP mp, int p_78743_1_, int p_78743_2_, int p_78743_3_, + // int p_78743_4_) { + // if (ClientEventHandler.cancelone) { + // mp.resetBlockRemoving(); + // return true; + // } + // return false; + // } @Fix(returnSetting = EnumReturnSetting.ON_TRUE) @SideOnly(Side.CLIENT) @@ -187,355 +154,357 @@ public static boolean addBlockHitEffects(EffectRenderer er, int x, int y, int z, return false; } - @Fix(returnSetting = EnumReturnSetting.ON_TRUE) - @SideOnly(Side.CLIENT) - public static boolean onPlayerDamageBlock(PlayerControllerMP mp, int p_78759_1_, int p_78759_2_, int p_78759_3_, - int p_78759_4_) { - if (ClientEventHandler.cancelone) { - mp.resetBlockRemoving(); - return true; - } - return false; - } - - public static float onGround2; - public static float firstPersonFrame; - public static boolean offhandFPRender; - - @Fix(insertOnExit = true) - @SideOnly(Side.CLIENT) - public static void renderItemInFirstPerson(ItemRenderer itemRenderer, float frame) { - if (offhandFPRender) return; - - EntityPlayer player = Minecraft.getMinecraft().thePlayer; - ClientEventHandler.renderingPlayer = player; - - ItemStack mainhandItem = player.getCurrentEquippedItem(); - ItemStack offhandItem = BackhandUtils.getOffhandItem(player); - if (!Backhand.EmptyOffhand && !Backhand.RenderEmptyOffhandAtRest && offhandItem == null) { - return; - } - if (offhandItem == null && !Backhand.RenderEmptyOffhandAtRest - && ((IBackhandPlayer) player).getOffSwingProgress(frame) == 0) { - return; - } - if (mainhandItem != null && mainhandItem.getItem() instanceof ItemMap) { - return; - } - - MysteriumPatchesFixesO.firstPersonFrame = frame; - - MysteriumPatchesFixesO.onGround2 = 0; - RenderOffhandPlayer.itemRenderer.updateEquippedItem(); - offhandFPRender = true; - GL11.glEnable(GL11.GL_CULL_FACE); - GL11.glCullFace(GL11.GL_FRONT); - ClientEventHandler.renderOffhandPlayer.renderOffhandItem(itemRenderer, frame); - GL11.glCullFace(GL11.GL_BACK); - offhandFPRender = false; - } - - @SideOnly(Side.CLIENT) - @Fix(insertOnExit = true, returnSetting = EnumReturnSetting.ALWAYS) - public static float getSwingProgress(EntityLivingBase entityLivingBase, float partialTicks, - @ReturnedValue float returnedValue) { - if (offhandFPRender) { - return ((IBackhandPlayer) entityLivingBase).getOffSwingProgress(partialTicks); - } - return returnedValue; - } + // @Fix(returnSetting = EnumReturnSetting.ON_TRUE) + // @SideOnly(Side.CLIENT) + // public static boolean onPlayerDamageBlock(PlayerControllerMP mp, int p_78759_1_, int p_78759_2_, int p_78759_3_, + // int p_78759_4_) { + // if (ClientEventHandler.cancelone) { + // mp.resetBlockRemoving(); + // return true; + // } + // return false; + // } + + // public static float onGround2; + // public static float firstPersonFrame; + // public static boolean offhandFPRender; + // + // @Fix(insertOnExit = true) + // @SideOnly(Side.CLIENT) + // public static void renderItemInFirstPerson(ItemRenderer itemRenderer, float frame) { + // if (offhandFPRender) return; + // + // EntityPlayer player = Minecraft.getMinecraft().thePlayer; + // ClientEventHandler.renderingPlayer = player; + // + // ItemStack mainhandItem = player.getCurrentEquippedItem(); + // ItemStack offhandItem = BackhandUtils.getOffhandItem(player); + // if (!Backhand.EmptyOffhand && !Backhand.RenderEmptyOffhandAtRest && offhandItem == null) { + // return; + // } + // if (offhandItem == null && !Backhand.RenderEmptyOffhandAtRest + // && ((IBackhandPlayer) player).getOffSwingProgress(frame) == 0) { + // return; + // } + // if (mainhandItem != null && mainhandItem.getItem() instanceof ItemMap) { + // return; + // } + // + // MysteriumPatchesFixesO.firstPersonFrame = frame; + // + // MysteriumPatchesFixesO.onGround2 = 0; + // RenderOffhandPlayer.itemRenderer.updateEquippedItem(); + // offhandFPRender = true; + // GL11.glEnable(GL11.GL_CULL_FACE); + // GL11.glCullFace(GL11.GL_FRONT); + // ClientEventHandler.renderOffhandPlayer.renderOffhandItem(itemRenderer, frame); + // GL11.glCullFace(GL11.GL_BACK); + // offhandFPRender = false; + // } + + // @SideOnly(Side.CLIENT) + // @Fix(insertOnExit = true, returnSetting = EnumReturnSetting.ALWAYS) + // public static float getSwingProgress(EntityLivingBase entityLivingBase, float partialTicks, + // @ReturnedValue float returnedValue) { + // if (offhandFPRender) { + // return ((IBackhandPlayer) entityLivingBase).getOffSwingProgress(partialTicks); + // } + // return returnedValue; + // } @Fix @SideOnly(Side.CLIENT) public static void doRender(RendererLivingEntity l, EntityLivingBase p_76986_1_, double p_76986_2_, double p_76986_4_, double p_76986_6_, float p_76986_8_, float p_76986_9_) { if (p_76986_1_ instanceof EntityPlayer) { - onGround2 = ((IBackhandPlayer) p_76986_1_).getOffSwingProgress(p_76986_9_); - } - } - - @Fix(returnSetting = EnumReturnSetting.ALWAYS) - @SideOnly(Side.CLIENT) - public static void setRotationAngles(ModelBiped b, float p_78087_1_, float p_78087_2_, float p_78087_3_, - float p_78087_4_, float p_78087_5_, float p_78087_6_, Entity p_78087_7_) { - b.bipedHead.rotateAngleY = p_78087_4_ / (180F / (float) Math.PI); - b.bipedHead.rotateAngleX = p_78087_5_ / (180F / (float) Math.PI); - b.bipedHeadwear.rotateAngleY = b.bipedHead.rotateAngleY; - b.bipedHeadwear.rotateAngleX = b.bipedHead.rotateAngleX; - b.bipedRightArm.rotateAngleX = MathHelper.cos(p_78087_1_ * 0.6662F + (float) Math.PI) * 2.0F - * p_78087_2_ - * 0.5F; - b.bipedLeftArm.rotateAngleX = MathHelper.cos(p_78087_1_ * 0.6662F) * 2.0F * p_78087_2_ * 0.5F; - b.bipedRightArm.rotateAngleZ = 0.0F; - b.bipedLeftArm.rotateAngleZ = 0.0F; - b.bipedRightLeg.rotateAngleX = MathHelper.cos(p_78087_1_ * 0.6662F) * 1.4F * p_78087_2_; - b.bipedLeftLeg.rotateAngleX = MathHelper.cos(p_78087_1_ * 0.6662F + (float) Math.PI) * 1.4F * p_78087_2_; - b.bipedRightLeg.rotateAngleY = 0.0F; - b.bipedLeftLeg.rotateAngleY = 0.0F; - - if (b.isRiding) { - b.bipedRightArm.rotateAngleX += -((float) Math.PI / 5F); - b.bipedLeftArm.rotateAngleX += -((float) Math.PI / 5F); - b.bipedRightLeg.rotateAngleX = -((float) Math.PI * 2F / 5F); - b.bipedLeftLeg.rotateAngleX = -((float) Math.PI * 2F / 5F); - b.bipedRightLeg.rotateAngleY = ((float) Math.PI / 10F); - b.bipedLeftLeg.rotateAngleY = -((float) Math.PI / 10F); - } - - if (b.heldItemLeft != 0) { - b.bipedLeftArm.rotateAngleX = b.bipedLeftArm.rotateAngleX * 0.5F - - ((float) Math.PI / 10F) * (float) b.heldItemLeft; - } - - if (b.heldItemRight != 0) { - b.bipedRightArm.rotateAngleX = b.bipedRightArm.rotateAngleX * 0.5F - - ((float) Math.PI / 10F) * (float) b.heldItemRight; - } - - b.bipedRightArm.rotateAngleY = 0.0F; - b.bipedLeftArm.rotateAngleY = 0.0F; - float f6; - float f7; - - if (b.onGround > -9990.0F) { - f6 = b.onGround; - b.bipedBody.rotateAngleY = MathHelper.sin(MathHelper.sqrt_float(f6) * (float) Math.PI * 2.0F) * 0.2F; - b.bipedRightArm.rotationPointZ = MathHelper.sin(b.bipedBody.rotateAngleY) * 5.0F; - b.bipedRightArm.rotationPointX = -MathHelper.cos(b.bipedBody.rotateAngleY) * 5.0F; - b.bipedLeftArm.rotationPointZ = -MathHelper.sin(b.bipedBody.rotateAngleY) * 5.0F; - b.bipedLeftArm.rotationPointX = MathHelper.cos(b.bipedBody.rotateAngleY) * 5.0F; - b.bipedRightArm.rotateAngleY += b.bipedBody.rotateAngleY; - b.bipedLeftArm.rotateAngleY += b.bipedBody.rotateAngleY; - b.bipedLeftArm.rotateAngleX += b.bipedBody.rotateAngleY; - f6 = 1.0F - b.onGround; - f6 *= f6; - f6 *= f6; - f6 = 1.0F - f6; - f7 = MathHelper.sin(f6 * (float) Math.PI); - float f8 = MathHelper.sin(b.onGround * (float) Math.PI) * -(b.bipedHead.rotateAngleX - 0.7F) * 0.75F; - b.bipedRightArm.rotateAngleX = (float) ((double) b.bipedRightArm.rotateAngleX - - ((double) f7 * 1.2D + (double) f8)); - b.bipedRightArm.rotateAngleY += b.bipedBody.rotateAngleY * 2.0F; - b.bipedRightArm.rotateAngleZ = MathHelper.sin(b.onGround * (float) Math.PI) * -0.4F; - } - - if (p_78087_7_ instanceof EntityPlayer && (p_78087_7_ != Minecraft.getMinecraft().thePlayer - || ((IBackhandPlayer) p_78087_7_).getOffSwingProgress(MysteriumPatchesFixesO.firstPersonFrame) != 0)) { - if (onGround2 > -9990.0F) { - f6 = onGround2; - b.bipedBody.rotateAngleY = MathHelper.sin(MathHelper.sqrt_float(f6) * (float) Math.PI * 2.0F) * 0.2F; - b.bipedRightArm.rotationPointZ = MathHelper.sin(b.bipedBody.rotateAngleY) * 5.0F; - b.bipedRightArm.rotationPointX = -MathHelper.cos(b.bipedBody.rotateAngleY) * 5.0F; - b.bipedLeftArm.rotationPointZ = -MathHelper.sin(b.bipedBody.rotateAngleY) * 5.0F; - b.bipedLeftArm.rotationPointX = MathHelper.cos(b.bipedBody.rotateAngleY) * 5.0F; - b.bipedRightArm.rotateAngleY += b.bipedBody.rotateAngleY; - b.bipedLeftArm.rotateAngleY += b.bipedBody.rotateAngleY; - b.bipedLeftArm.rotateAngleX += b.bipedBody.rotateAngleY; - f6 = 1.0F - onGround2; - f6 *= f6; - f6 *= f6; - f6 = 1.0F - f6; - f7 = MathHelper.sin(f6 * (float) Math.PI); - float f8 = MathHelper.sin(onGround2 * (float) Math.PI) * -(b.bipedHead.rotateAngleX - 0.7F) * 0.75F; - b.bipedLeftArm.rotateAngleX = (float) ((double) b.bipedLeftArm.rotateAngleX - - ((double) f7 * 1.2D + (double) f8)); - b.bipedLeftArm.rotateAngleY -= b.bipedBody.rotateAngleY * 2.0F; - b.bipedLeftArm.rotateAngleZ = -MathHelper.sin(onGround2 * (float) Math.PI) * -0.4F; - } - } - - if (b.isSneak) { - b.bipedBody.rotateAngleX = 0.5F; - b.bipedRightArm.rotateAngleX += 0.4F; - b.bipedLeftArm.rotateAngleX += 0.4F; - b.bipedRightLeg.rotationPointZ = 4.0F; - b.bipedLeftLeg.rotationPointZ = 4.0F; - b.bipedRightLeg.rotationPointY = 9.0F; - b.bipedLeftLeg.rotationPointY = 9.0F; - b.bipedHead.rotationPointY = 1.0F; - b.bipedHeadwear.rotationPointY = 1.0F; - } else { - b.bipedBody.rotateAngleX = 0.0F; - b.bipedRightLeg.rotationPointZ = 0.1F; - b.bipedLeftLeg.rotationPointZ = 0.1F; - b.bipedRightLeg.rotationPointY = 12.0F; - b.bipedLeftLeg.rotationPointY = 12.0F; - b.bipedHead.rotationPointY = 0.0F; - b.bipedHeadwear.rotationPointY = 0.0F; - } - - b.bipedRightArm.rotateAngleZ += MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; - b.bipedLeftArm.rotateAngleZ -= MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; - b.bipedRightArm.rotateAngleX += MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; - b.bipedLeftArm.rotateAngleX -= MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; - - if (b.aimedBow) { - if (p_78087_7_ instanceof EntityPlayer && p_78087_7_ == Minecraft.getMinecraft().thePlayer - && BackhandUtils.getOffhandItem((EntityPlayer) p_78087_7_) != null - && ((EntityClientPlayerMP) p_78087_7_).getItemInUse() - == BackhandUtils.getOffhandItem((EntityPlayer) p_78087_7_)) { - f6 = 0.0F; - f7 = 0.0F; - b.bipedLeftArm.rotateAngleZ = 0.0F; - b.bipedRightArm.rotateAngleZ = 0.0F; - b.bipedLeftArm.rotateAngleY = 0.1F + b.bipedHead.rotateAngleY; - b.bipedRightArm.rotateAngleY = -0.5F + b.bipedHead.rotateAngleY; - b.bipedLeftArm.rotateAngleX = -((float) Math.PI / 2F) + b.bipedHead.rotateAngleX; - b.bipedRightArm.rotateAngleX = -((float) Math.PI / 2F) + b.bipedHead.rotateAngleX; - b.bipedLeftArm.rotateAngleX -= f6 * 1.2F - f7 * 0.4F; - b.bipedRightArm.rotateAngleX -= f6 * 1.2F - f7 * 0.4F; - b.bipedLeftArm.rotateAngleZ -= MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; - b.bipedRightArm.rotateAngleZ += MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; - b.bipedLeftArm.rotateAngleX -= MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; - b.bipedRightArm.rotateAngleX += MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; - } else { - f6 = 0.0F; - f7 = 0.0F; - b.bipedRightArm.rotateAngleZ = 0.0F; - b.bipedLeftArm.rotateAngleZ = 0.0F; - b.bipedRightArm.rotateAngleY = -(0.1F - f6 * 0.6F) + b.bipedHead.rotateAngleY; - b.bipedLeftArm.rotateAngleY = 0.1F - f6 * 0.6F + b.bipedHead.rotateAngleY + 0.4F; - b.bipedRightArm.rotateAngleX = -((float) Math.PI / 2F) + b.bipedHead.rotateAngleX; - b.bipedLeftArm.rotateAngleX = -((float) Math.PI / 2F) + b.bipedHead.rotateAngleX; - b.bipedRightArm.rotateAngleX -= f6 * 1.2F - f7 * 0.4F; - b.bipedLeftArm.rotateAngleX -= f6 * 1.2F - f7 * 0.4F; - b.bipedRightArm.rotateAngleZ += MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; - b.bipedLeftArm.rotateAngleZ -= MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; - b.bipedRightArm.rotateAngleX += MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; - b.bipedLeftArm.rotateAngleX -= MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; - } + // onGround2 = ((IBackhandPlayer) p_76986_1_).getOffSwingProgress(p_76986_9_); } } - @Fix(returnSetting = EnumReturnSetting.ON_TRUE) - public static boolean processPlayerDigging(NetHandlerPlayServer serv, C07PacketPlayerDigging p_147345_1_) { - WorldServer worldserver = MinecraftServer.getServer() - .worldServerForDimension(serv.playerEntity.dimension); - serv.playerEntity.func_143004_u(); - - if (p_147345_1_.func_149506_g() == 4) { - serv.playerEntity.dropOneItem(false); - return true; - } else if (p_147345_1_.func_149506_g() == 3) { - serv.playerEntity.dropOneItem(true); - return true; - } else if (p_147345_1_.func_149506_g() == 5) { - serv.playerEntity.stopUsingItem(); - return true; - } else { - boolean flag = false; - - if (p_147345_1_.func_149506_g() == 0) { - flag = true; - } - - if (p_147345_1_.func_149506_g() == 1) { - flag = true; - } - - if (p_147345_1_.func_149506_g() == 2) { - flag = true; - } - - int i = p_147345_1_.func_149505_c(); - int j = p_147345_1_.func_149503_d(); - int k = p_147345_1_.func_149502_e(); - if (flag) { - double d0 = serv.playerEntity.posX - ((double) i + 0.5D); - double d1 = serv.playerEntity.posY - ((double) j + 0.5D) + 1.5D; - double d2 = serv.playerEntity.posZ - ((double) k + 0.5D); - double d3 = d0 * d0 + d1 * d1 + d2 * d2; - - double dist = serv.playerEntity.theItemInWorldManager.getBlockReachDistance() + 1; - dist *= dist; - - if (d3 > dist) { - return true; - } - } - - if (p_147345_1_.func_149506_g() == 2) { - customUncheckedTryHarvestBlock(serv.playerEntity.theItemInWorldManager, i, j, k); - serv.playerEntity.theItemInWorldManager.uncheckedTryHarvestBlock(i, j, k); - - if (worldserver.getBlock(i, j, k) - .getMaterial() != Material.air) { - serv.playerEntity.playerNetServerHandler.sendPacket(new S23PacketBlockChange(i, j, k, worldserver)); - } - return true; - } else if (p_147345_1_.func_149506_g() == 1) { - serv.playerEntity.theItemInWorldManager.cancelDestroyingBlock(i, j, k); - - if (worldserver.getBlock(i, j, k) - .getMaterial() != Material.air) { - serv.playerEntity.playerNetServerHandler.sendPacket(new S23PacketBlockChange(i, j, k, worldserver)); - } - return true; - } - } - return false; - } + // @Fix(returnSetting = EnumReturnSetting.ALWAYS) + // @SideOnly(Side.CLIENT) + // public static void setRotationAngles(ModelBiped b, float p_78087_1_, float p_78087_2_, float p_78087_3_, + // float p_78087_4_, float p_78087_5_, float p_78087_6_, Entity p_78087_7_) { + // b.bipedHead.rotateAngleY = p_78087_4_ / (180F / (float) Math.PI); + // b.bipedHead.rotateAngleX = p_78087_5_ / (180F / (float) Math.PI); + // b.bipedHeadwear.rotateAngleY = b.bipedHead.rotateAngleY; + // b.bipedHeadwear.rotateAngleX = b.bipedHead.rotateAngleX; + // b.bipedRightArm.rotateAngleX = MathHelper.cos(p_78087_1_ * 0.6662F + (float) Math.PI) * 2.0F + // * p_78087_2_ + // * 0.5F; + // b.bipedLeftArm.rotateAngleX = MathHelper.cos(p_78087_1_ * 0.6662F) * 2.0F * p_78087_2_ * 0.5F; + // b.bipedRightArm.rotateAngleZ = 0.0F; + // b.bipedLeftArm.rotateAngleZ = 0.0F; + // b.bipedRightLeg.rotateAngleX = MathHelper.cos(p_78087_1_ * 0.6662F) * 1.4F * p_78087_2_; + // b.bipedLeftLeg.rotateAngleX = MathHelper.cos(p_78087_1_ * 0.6662F + (float) Math.PI) * 1.4F * p_78087_2_; + // b.bipedRightLeg.rotateAngleY = 0.0F; + // b.bipedLeftLeg.rotateAngleY = 0.0F; + // + // if (b.isRiding) { + // b.bipedRightArm.rotateAngleX += -((float) Math.PI / 5F); + // b.bipedLeftArm.rotateAngleX += -((float) Math.PI / 5F); + // b.bipedRightLeg.rotateAngleX = -((float) Math.PI * 2F / 5F); + // b.bipedLeftLeg.rotateAngleX = -((float) Math.PI * 2F / 5F); + // b.bipedRightLeg.rotateAngleY = ((float) Math.PI / 10F); + // b.bipedLeftLeg.rotateAngleY = -((float) Math.PI / 10F); + // } + // + // if (b.heldItemLeft != 0) { + // b.bipedLeftArm.rotateAngleX = b.bipedLeftArm.rotateAngleX * 0.5F + // - ((float) Math.PI / 10F) * (float) b.heldItemLeft; + // } + // + // if (b.heldItemRight != 0) { + // b.bipedRightArm.rotateAngleX = b.bipedRightArm.rotateAngleX * 0.5F + // - ((float) Math.PI / 10F) * (float) b.heldItemRight; + // } + // + // b.bipedRightArm.rotateAngleY = 0.0F; + // b.bipedLeftArm.rotateAngleY = 0.0F; + // float f6; + // float f7; + // + // if (b.onGround > -9990.0F) { + // f6 = b.onGround; + // b.bipedBody.rotateAngleY = MathHelper.sin(MathHelper.sqrt_float(f6) * (float) Math.PI * 2.0F) * 0.2F; + // b.bipedRightArm.rotationPointZ = MathHelper.sin(b.bipedBody.rotateAngleY) * 5.0F; + // b.bipedRightArm.rotationPointX = -MathHelper.cos(b.bipedBody.rotateAngleY) * 5.0F; + // b.bipedLeftArm.rotationPointZ = -MathHelper.sin(b.bipedBody.rotateAngleY) * 5.0F; + // b.bipedLeftArm.rotationPointX = MathHelper.cos(b.bipedBody.rotateAngleY) * 5.0F; + // b.bipedRightArm.rotateAngleY += b.bipedBody.rotateAngleY; + // b.bipedLeftArm.rotateAngleY += b.bipedBody.rotateAngleY; + // b.bipedLeftArm.rotateAngleX += b.bipedBody.rotateAngleY; + // f6 = 1.0F - b.onGround; + // f6 *= f6; + // f6 *= f6; + // f6 = 1.0F - f6; + // f7 = MathHelper.sin(f6 * (float) Math.PI); + // float f8 = MathHelper.sin(b.onGround * (float) Math.PI) * -(b.bipedHead.rotateAngleX - 0.7F) * 0.75F; + // b.bipedRightArm.rotateAngleX = (float) ((double) b.bipedRightArm.rotateAngleX + // - ((double) f7 * 1.2D + (double) f8)); + // b.bipedRightArm.rotateAngleY += b.bipedBody.rotateAngleY * 2.0F; + // b.bipedRightArm.rotateAngleZ = MathHelper.sin(b.onGround * (float) Math.PI) * -0.4F; + // } + // + // if (p_78087_7_ instanceof EntityPlayer && (p_78087_7_ != Minecraft.getMinecraft().thePlayer + // || ((IBackhandPlayer) p_78087_7_).getOffSwingProgress(MysteriumPatchesFixesO.firstPersonFrame) != 0)) { + // if (onGround2 > -9990.0F) { + // f6 = onGround2; + // b.bipedBody.rotateAngleY = MathHelper.sin(MathHelper.sqrt_float(f6) * (float) Math.PI * 2.0F) * 0.2F; + // b.bipedRightArm.rotationPointZ = MathHelper.sin(b.bipedBody.rotateAngleY) * 5.0F; + // b.bipedRightArm.rotationPointX = -MathHelper.cos(b.bipedBody.rotateAngleY) * 5.0F; + // b.bipedLeftArm.rotationPointZ = -MathHelper.sin(b.bipedBody.rotateAngleY) * 5.0F; + // b.bipedLeftArm.rotationPointX = MathHelper.cos(b.bipedBody.rotateAngleY) * 5.0F; + // b.bipedRightArm.rotateAngleY += b.bipedBody.rotateAngleY; + // b.bipedLeftArm.rotateAngleY += b.bipedBody.rotateAngleY; + // b.bipedLeftArm.rotateAngleX += b.bipedBody.rotateAngleY; + // f6 = 1.0F - onGround2; + // f6 *= f6; + // f6 *= f6; + // f6 = 1.0F - f6; + // f7 = MathHelper.sin(f6 * (float) Math.PI); + // float f8 = MathHelper.sin(onGround2 * (float) Math.PI) * -(b.bipedHead.rotateAngleX - 0.7F) * 0.75F; + // b.bipedLeftArm.rotateAngleX = (float) ((double) b.bipedLeftArm.rotateAngleX + // - ((double) f7 * 1.2D + (double) f8)); + // b.bipedLeftArm.rotateAngleY -= b.bipedBody.rotateAngleY * 2.0F; + // b.bipedLeftArm.rotateAngleZ = -MathHelper.sin(onGround2 * (float) Math.PI) * -0.4F; + // } + // } + // + // if (b.isSneak) { + // b.bipedBody.rotateAngleX = 0.5F; + // b.bipedRightArm.rotateAngleX += 0.4F; + // b.bipedLeftArm.rotateAngleX += 0.4F; + // b.bipedRightLeg.rotationPointZ = 4.0F; + // b.bipedLeftLeg.rotationPointZ = 4.0F; + // b.bipedRightLeg.rotationPointY = 9.0F; + // b.bipedLeftLeg.rotationPointY = 9.0F; + // b.bipedHead.rotationPointY = 1.0F; + // b.bipedHeadwear.rotationPointY = 1.0F; + // } else { + // b.bipedBody.rotateAngleX = 0.0F; + // b.bipedRightLeg.rotationPointZ = 0.1F; + // b.bipedLeftLeg.rotationPointZ = 0.1F; + // b.bipedRightLeg.rotationPointY = 12.0F; + // b.bipedLeftLeg.rotationPointY = 12.0F; + // b.bipedHead.rotationPointY = 0.0F; + // b.bipedHeadwear.rotationPointY = 0.0F; + // } + // + // b.bipedRightArm.rotateAngleZ += MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; + // b.bipedLeftArm.rotateAngleZ -= MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; + // b.bipedRightArm.rotateAngleX += MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; + // b.bipedLeftArm.rotateAngleX -= MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; + // + // if (b.aimedBow) { + // if (p_78087_7_ instanceof EntityPlayer && p_78087_7_ == Minecraft.getMinecraft().thePlayer + // && BackhandUtils.getOffhandItem((EntityPlayer) p_78087_7_) != null + // && ((EntityClientPlayerMP) p_78087_7_).getItemInUse() + // == BackhandUtils.getOffhandItem((EntityPlayer) p_78087_7_)) { + // f6 = 0.0F; + // f7 = 0.0F; + // b.bipedLeftArm.rotateAngleZ = 0.0F; + // b.bipedRightArm.rotateAngleZ = 0.0F; + // b.bipedLeftArm.rotateAngleY = 0.1F + b.bipedHead.rotateAngleY; + // b.bipedRightArm.rotateAngleY = -0.5F + b.bipedHead.rotateAngleY; + // b.bipedLeftArm.rotateAngleX = -((float) Math.PI / 2F) + b.bipedHead.rotateAngleX; + // b.bipedRightArm.rotateAngleX = -((float) Math.PI / 2F) + b.bipedHead.rotateAngleX; + // b.bipedLeftArm.rotateAngleX -= f6 * 1.2F - f7 * 0.4F; + // b.bipedRightArm.rotateAngleX -= f6 * 1.2F - f7 * 0.4F; + // b.bipedLeftArm.rotateAngleZ -= MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; + // b.bipedRightArm.rotateAngleZ += MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; + // b.bipedLeftArm.rotateAngleX -= MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; + // b.bipedRightArm.rotateAngleX += MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; + // } else { + // f6 = 0.0F; + // f7 = 0.0F; + // b.bipedRightArm.rotateAngleZ = 0.0F; + // b.bipedLeftArm.rotateAngleZ = 0.0F; + // b.bipedRightArm.rotateAngleY = -(0.1F - f6 * 0.6F) + b.bipedHead.rotateAngleY; + // b.bipedLeftArm.rotateAngleY = 0.1F - f6 * 0.6F + b.bipedHead.rotateAngleY + 0.4F; + // b.bipedRightArm.rotateAngleX = -((float) Math.PI / 2F) + b.bipedHead.rotateAngleX; + // b.bipedLeftArm.rotateAngleX = -((float) Math.PI / 2F) + b.bipedHead.rotateAngleX; + // b.bipedRightArm.rotateAngleX -= f6 * 1.2F - f7 * 0.4F; + // b.bipedLeftArm.rotateAngleX -= f6 * 1.2F - f7 * 0.4F; + // b.bipedRightArm.rotateAngleZ += MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; + // b.bipedLeftArm.rotateAngleZ -= MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; + // b.bipedRightArm.rotateAngleX += MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; + // b.bipedLeftArm.rotateAngleX -= MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; + // } + // } + // } + + // @Fix(returnSetting = EnumReturnSetting.ON_TRUE) + // public static boolean processPlayerDigging(NetHandlerPlayServer serv, C07PacketPlayerDigging p_147345_1_) { + // WorldServer worldserver = MinecraftServer.getServer() + // .worldServerForDimension(serv.playerEntity.dimension); + // serv.playerEntity.func_143004_u(); + // + // if (p_147345_1_.func_149506_g() == 4) { + // serv.playerEntity.dropOneItem(false); + // return true; + // } else if (p_147345_1_.func_149506_g() == 3) { + // serv.playerEntity.dropOneItem(true); + // return true; + // } else if (p_147345_1_.func_149506_g() == 5) { + // serv.playerEntity.stopUsingItem(); + // return true; + // } else { + // boolean flag = false; + // + // if (p_147345_1_.func_149506_g() == 0) { + // flag = true; + // } + // + // if (p_147345_1_.func_149506_g() == 1) { + // flag = true; + // } + // + // if (p_147345_1_.func_149506_g() == 2) { + // flag = true; + // } + // + // int i = p_147345_1_.func_149505_c(); + // int j = p_147345_1_.func_149503_d(); + // int k = p_147345_1_.func_149502_e(); + // if (flag) { + // double d0 = serv.playerEntity.posX - ((double) i + 0.5D); + // double d1 = serv.playerEntity.posY - ((double) j + 0.5D) + 1.5D; + // double d2 = serv.playerEntity.posZ - ((double) k + 0.5D); + // double d3 = d0 * d0 + d1 * d1 + d2 * d2; + // + // double dist = serv.playerEntity.theItemInWorldManager.getBlockReachDistance() + 1; + // dist *= dist; + // + // if (d3 > dist) { + // return true; + // } + // } + // + // if (p_147345_1_.func_149506_g() == 2) { + // customUncheckedTryHarvestBlock(serv.playerEntity.theItemInWorldManager, i, j, k); + // serv.playerEntity.theItemInWorldManager.uncheckedTryHarvestBlock(i, j, k); + // + // if (worldserver.getBlock(i, j, k) + // .getMaterial() != Material.air) { + // serv.playerEntity.playerNetServerHandler.sendPacket(new S23PacketBlockChange(i, j, k, worldserver)); + // } + // return true; + // } else if (p_147345_1_.func_149506_g() == 1) { + // serv.playerEntity.theItemInWorldManager.cancelDestroyingBlock(i, j, k); + // + // if (worldserver.getBlock(i, j, k) + // .getMaterial() != Material.air) { + // serv.playerEntity.playerNetServerHandler.sendPacket(new S23PacketBlockChange(i, j, k, worldserver)); + // } + // return true; + // } + // } + // return false; + // } // This might be a bad idea. (but if I didn't do this I would have to insert ~10 more fixes into forge-hooked // methods and it might not even have worked) - @Fix - public static void uncheckedTryHarvestBlock(ItemInWorldManager m, int p_73082_1_, int p_73082_2_, int p_73082_3_) { - m.theWorld.destroyBlockInWorldPartially(m.thisPlayerMP.getEntityId(), p_73082_1_, p_73082_2_, p_73082_3_, -1); - m.tryHarvestBlock(p_73082_1_, p_73082_2_, p_73082_3_); - } - - public static void customUncheckedTryHarvestBlock(ItemInWorldManager m, int p_73082_1_, int p_73082_2_, - int p_73082_3_) { - m.theWorld.destroyBlockInWorldPartially(m.thisPlayerMP.getEntityId(), p_73082_1_, p_73082_2_, p_73082_3_, -1); - m.tryHarvestBlock(p_73082_1_, p_73082_2_, p_73082_3_); - } - - @Fix(returnSetting = EnumReturnSetting.ALWAYS, insertOnExit = true) - public static void sendContainerAndContentsToPlayer(EntityPlayerMP player, Container p_71110_1_, List p_71110_2_) { - BackhandUtils.getOffhandEP(player).syncOffhand = true; - } - - public static boolean ignoreSetSlot = false; - - @Fix(returnSetting = EnumReturnSetting.ALWAYS) - public static void handleSetSlot(NetHandlerPlayClient netClient, S2FPacketSetSlot p_147266_1_) { - EntityClientPlayerMP player = netClient.gameController.thePlayer; - - if (p_147266_1_.func_149175_c() == -1) { - player.inventory.setItemStack( - p_147266_1_.func_149174_e() == null || p_147266_1_.func_149174_e().stackSize == 0 ? null - : p_147266_1_.func_149174_e()); - } else if (!ignoreSetSlot) { - boolean flag = false; - - if (netClient.gameController.currentScreen instanceof GuiContainerCreative) { - GuiContainerCreative guicontainercreative = (GuiContainerCreative) netClient.gameController.currentScreen; - flag = guicontainercreative.func_147056_g() != CreativeTabs.tabInventory.getTabIndex(); - } - - if (p_147266_1_.func_149175_c() == 0 && p_147266_1_.func_149173_d() >= 36 - && p_147266_1_.func_149173_d() < 45) { - ItemStack itemstack = player.inventoryContainer.getSlot(p_147266_1_.func_149173_d()) - .getStack(); - - if (p_147266_1_.func_149174_e() != null && p_147266_1_.func_149174_e().stackSize != 0 - && (itemstack == null || itemstack.stackSize < p_147266_1_.func_149174_e().stackSize)) { - p_147266_1_.func_149174_e().animationsToGo = 5; - } - - player.inventoryContainer.putStackInSlot( - p_147266_1_.func_149173_d(), - p_147266_1_.func_149174_e() == null || p_147266_1_.func_149174_e().stackSize == 0 ? null - : p_147266_1_.func_149174_e()); - } else if (p_147266_1_.func_149175_c() == player.openContainer.windowId - && (p_147266_1_.func_149175_c() != 0 || !flag)) { - player.openContainer.putStackInSlot( - p_147266_1_.func_149173_d(), - p_147266_1_.func_149174_e() == null || p_147266_1_.func_149174_e().stackSize == 0 ? null - : p_147266_1_.func_149174_e()); - } - } - } + // @Fix + // public static void uncheckedTryHarvestBlock(ItemInWorldManager m, int p_73082_1_, int p_73082_2_, int p_73082_3_) + // { + // m.theWorld.destroyBlockInWorldPartially(m.thisPlayerMP.getEntityId(), p_73082_1_, p_73082_2_, p_73082_3_, -1); + // m.tryHarvestBlock(p_73082_1_, p_73082_2_, p_73082_3_); + // } + + // public static void customUncheckedTryHarvestBlock(ItemInWorldManager m, int p_73082_1_, int p_73082_2_, + // int p_73082_3_) { + // m.theWorld.destroyBlockInWorldPartially(m.thisPlayerMP.getEntityId(), p_73082_1_, p_73082_2_, p_73082_3_, -1); + // m.tryHarvestBlock(p_73082_1_, p_73082_2_, p_73082_3_); + // } + + // @Fix(returnSetting = EnumReturnSetting.ALWAYS, insertOnExit = true) + // public static void sendContainerAndContentsToPlayer(EntityPlayerMP player, Container p_71110_1_, List p_71110_2_) + // { + // BackhandUtils.getOffhandEP(player).syncOffhand = true; + // } + + // public static boolean ignoreSetSlot = false; + + // @Fix(returnSetting = EnumReturnSetting.ALWAYS) + // public static void handleSetSlot(NetHandlerPlayClient netClient, S2FPacketSetSlot p_147266_1_) { + // EntityClientPlayerMP player = netClient.gameController.thePlayer; + // + // if (p_147266_1_.func_149175_c() == -1) { + // player.inventory.setItemStack( + // p_147266_1_.func_149174_e() == null || p_147266_1_.func_149174_e().stackSize == 0 ? null + // : p_147266_1_.func_149174_e()); + // } else if (!ignoreSetSlot) { + // boolean flag = false; + // + // if (netClient.gameController.currentScreen instanceof GuiContainerCreative) { + // GuiContainerCreative guicontainercreative = (GuiContainerCreative) netClient.gameController.currentScreen; + // flag = guicontainercreative.func_147056_g() != CreativeTabs.tabInventory.getTabIndex(); + // } + // + // if (p_147266_1_.func_149175_c() == 0 && p_147266_1_.func_149173_d() >= 36 + // && p_147266_1_.func_149173_d() < 45) { + // ItemStack itemstack = player.inventoryContainer.getSlot(p_147266_1_.func_149173_d()) + // .getStack(); + // + // if (p_147266_1_.func_149174_e() != null && p_147266_1_.func_149174_e().stackSize != 0 + // && (itemstack == null || itemstack.stackSize < p_147266_1_.func_149174_e().stackSize)) { + // p_147266_1_.func_149174_e().animationsToGo = 5; + // } + // + // player.inventoryContainer.putStackInSlot( + // p_147266_1_.func_149173_d(), + // p_147266_1_.func_149174_e() == null || p_147266_1_.func_149174_e().stackSize == 0 ? null + // : p_147266_1_.func_149174_e()); + // } else if (p_147266_1_.func_149175_c() == player.openContainer.windowId + // && (p_147266_1_.func_149175_c() != 0 || !flag)) { + // player.openContainer.putStackInSlot( + // p_147266_1_.func_149173_d(), + // p_147266_1_.func_149174_e() == null || p_147266_1_.func_149174_e().stackSize == 0 ? null + // : p_147266_1_.func_149174_e()); + // } + // } + // } @Fix(returnSetting = EnumReturnSetting.ALWAYS) public static void processUseEntity(NetHandlerPlayServer netServer, C02PacketUseEntity p_147340_1_) { @@ -585,35 +554,35 @@ public static void processUseEntity(NetHandlerPlayServer netServer, C02PacketUse } } - @SideOnly(Side.CLIENT) - @Fix(insertOnExit = true, returnSetting = EnumReturnSetting.ALWAYS) - public static boolean interactWithEntitySendPacket(PlayerControllerMP controllerMP, EntityPlayer p_78768_1_, - Entity p_78768_2_, @ReturnedValue boolean interacted) { - if (interacted) { - BackhandClientTickHandler.attackDelay = 5; - } - return interacted; - } - - @Fix(returnSetting = EnumReturnSetting.ALWAYS) - public static void processHeldItemChange(NetHandlerPlayServer server, C09PacketHeldItemChange p_147355_1_) { - if (p_147355_1_.func_149614_c() >= 0 && p_147355_1_.func_149614_c() < (InventoryPlayer.getHotbarSize()) - || p_147355_1_.func_149614_c() == InventoryPlayerBackhand.OFFHAND_HOTBAR_SLOT) { - server.playerEntity.inventory.currentItem = p_147355_1_.func_149614_c(); - server.playerEntity.func_143004_u(); - } else { - System.out.println( - server.playerEntity.getCommandSenderName() + " tried to set an invalid carried item " - + p_147355_1_.func_149614_c()); - } - } - - @Fix(insertOnExit = true, returnSetting = EnumReturnSetting.ON_NOT_NULL) - public static ItemStack getCurrentItem(InventoryPlayer inv) { - return inv.currentItem < 9 && inv.currentItem >= 0 ? inv.mainInventory[inv.currentItem] - : inv.currentItem == InventoryPlayerBackhand.OFFHAND_HOTBAR_SLOT ? BackhandUtils.getOffhandItem(inv.player) - : null; - } + // @SideOnly(Side.CLIENT) + // @Fix(insertOnExit = true, returnSetting = EnumReturnSetting.ALWAYS) + // public static boolean interactWithEntitySendPacket(PlayerControllerMP controllerMP, EntityPlayer p_78768_1_, + // Entity p_78768_2_, @ReturnedValue boolean interacted) { + // if (interacted) { + // BackhandClientTickHandler.attackDelay = 5; + // } + // return interacted; + // } + + // @Fix(returnSetting = EnumReturnSetting.ALWAYS) + // public static void processHeldItemChange(NetHandlerPlayServer server, C09PacketHeldItemChange p_147355_1_) { + // if (p_147355_1_.func_149614_c() >= 0 && p_147355_1_.func_149614_c() < (InventoryPlayer.getHotbarSize()) + // || p_147355_1_.func_149614_c() == InventoryPlayerBackhand.OFFHAND_HOTBAR_SLOT) { + // server.playerEntity.inventory.currentItem = p_147355_1_.func_149614_c(); + // server.playerEntity.func_143004_u(); + // } else { + // System.out.println( + // server.playerEntity.getCommandSenderName() + " tried to set an invalid carried item " + // + p_147355_1_.func_149614_c()); + // } + // } + + // @Fix(insertOnExit = true, returnSetting = EnumReturnSetting.ON_NOT_NULL) + // public static ItemStack getCurrentItem(InventoryPlayer inv) { + // return inv.currentItem < 9 && inv.currentItem >= 0 ? inv.mainInventory[inv.currentItem] + // : inv.currentItem == InventoryPlayerBackhand.OFFHAND_HOTBAR_SLOT ? BackhandUtils.getOffhandItem(inv.player) + // : null; + // } private static final MethodHandle fieldGetSection; private static final MethodHandle fieldGetContainerMgr; diff --git a/src/main/java/xonin/backhand/client/BackhandClientTickHandler.java b/src/main/java/xonin/backhand/client/BackhandClientTickHandler.java index 223ee84..1e2b33b 100644 --- a/src/main/java/xonin/backhand/client/BackhandClientTickHandler.java +++ b/src/main/java/xonin/backhand/client/BackhandClientTickHandler.java @@ -24,7 +24,6 @@ import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.ForgeEventFactory; import net.minecraftforge.event.entity.player.PlayerInteractEvent; -import net.tclproject.mysteriumlib.asm.fixes.MysteriumPatchesFixesO; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.gameevent.TickEvent; @@ -37,6 +36,7 @@ import xonin.backhand.api.core.BackhandUtils; import xonin.backhand.api.core.IBackhandPlayer; import xonin.backhand.api.core.InventoryPlayerBackhand; +import xonin.backhand.client.utils.BackhandClientUtils; import xonin.backhand.packet.OffhandAttackPacket; import xonin.backhand.packet.OffhandPlaceBlockPacket; import xonin.backhand.packet.OffhandToServerPacket; @@ -349,7 +349,7 @@ public static void tryBreakBlockOffhand(MovingObjectPosition objectMouseOver, It mcInstance.playerController.isHittingBlock = false; return; } - MysteriumPatchesFixesO.countToCancel = 5; + BackhandClientUtils.countToCancel = 5; mcInstance.playerController.curBlockDamageMP += block .getPlayerRelativeBlockHardness(mcInstance.thePlayer, mcInstance.thePlayer.worldObj, i, j, k); diff --git a/src/main/java/xonin/backhand/client/ClientEventHandler.java b/src/main/java/xonin/backhand/client/ClientEventHandler.java index 9093d1c..1167d25 100644 --- a/src/main/java/xonin/backhand/client/ClientEventHandler.java +++ b/src/main/java/xonin/backhand/client/ClientEventHandler.java @@ -150,7 +150,7 @@ public void render3rdPersonOffhand(RenderPlayerEvent.Specials.Post event) { } GL11.glPushMatrix(); - ModelBiped biped = (ModelBiped) event.renderer.modelBipedMain; + ModelBiped biped = event.renderer.modelBipedMain; RenderOffhandPlayer.itemRenderer.updateEquippedItem(); renderOffhandPlayer.updateFovModifierHand(); RenderOffhandPlayer.itemRenderer diff --git a/src/main/java/xonin/backhand/client/ClientTickHandler.java b/src/main/java/xonin/backhand/client/ClientTickHandler.java index 0852521..84b63b4 100644 --- a/src/main/java/xonin/backhand/client/ClientTickHandler.java +++ b/src/main/java/xonin/backhand/client/ClientTickHandler.java @@ -40,7 +40,7 @@ public void onKeyInputEvent(InputEvent.KeyInputEvent event) { .getMethod("invTweaksSwapPatch"); invTweaksSwapPatch(); } catch (Exception ignored) {} - ((EntityClientPlayerMP) player).sendQueue.addToSendQueue(new OffhandSwapPacket(player).generatePacket()); + player.sendQueue.addToSendQueue(new OffhandSwapPacket(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 f351cc4..84e3f43 100644 --- a/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java +++ b/src/main/java/xonin/backhand/client/utils/BackhandClientUtils.java @@ -7,6 +7,17 @@ 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 * diff --git a/src/main/java/xonin/backhand/client/utils/BackhandRenderHelper.java b/src/main/java/xonin/backhand/client/utils/BackhandRenderHelper.java index 27d98b1..3060ba1 100644 --- a/src/main/java/xonin/backhand/client/utils/BackhandRenderHelper.java +++ b/src/main/java/xonin/backhand/client/utils/BackhandRenderHelper.java @@ -1,17 +1,13 @@ package xonin.backhand.client.utils; -import java.nio.FloatBuffer; - import net.minecraft.client.Minecraft; import net.minecraft.client.model.ModelBiped; -import net.minecraft.client.renderer.GLAllocation; import net.minecraft.client.renderer.ItemRenderer; import net.minecraft.client.renderer.Tessellator; import net.minecraft.entity.Entity; import net.minecraft.item.ItemStack; import net.minecraft.util.MathHelper; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.Vec3; import org.lwjgl.opengl.GL11; @@ -45,18 +41,10 @@ public final class BackhandRenderHelper { } } - private static FloatBuffer colorBuffer = GLAllocation.createDirectFloatBuffer(16); - public static boolean renderingItem; - private static final Vec3 field_82884_b = Vec3.createVectorHelper(0.20000000298023224D, 1.0D, -0.699999988079071D) - .normalize(); - private static final Vec3 field_82885_c = Vec3.createVectorHelper(-0.20000000298023224D, 1.0D, 0.699999988079071D) - .normalize(); - + @SuppressWarnings("SuspiciousNameCombination") public static void moveOffHandArm(Entity entity, ModelBiped biped, float frame) { - if (entity instanceof IBackhandPlayer) { - IBackhandPlayer player = (IBackhandPlayer) entity; - float offhandSwing = 0.0F; - offhandSwing = player.getOffSwingProgress(frame); + if (entity instanceof IBackhandPlayer player) { + float offhandSwing = player.getOffSwingProgress(frame); if (offhandSwing > 0.0F) { if (biped.bipedBody.rotateAngleY != 0.0F) { @@ -66,14 +54,8 @@ public static void moveOffHandArm(Entity entity, ModelBiped biped, float frame) biped.bipedBody.rotateAngleY = -MathHelper .sin(MathHelper.sqrt_float(offhandSwing) * (float) Math.PI * 2.0F) * 0.2F; - // biped.bipedRightArm.rotationPointZ = MathHelper.sin(biped.bipedBody.rotateAngleY) * 5.0F; - // biped.bipedRightArm.rotationPointX = -MathHelper.cos(biped.bipedBody.rotateAngleY) * 5.0F; - biped.bipedLeftArm.rotationPointZ = -MathHelper.sin(biped.bipedBody.rotateAngleY) * 5.0F; biped.bipedLeftArm.rotationPointX = MathHelper.cos(biped.bipedBody.rotateAngleY) * 5.0F; - - // biped.bipedRightArm.rotateAngleY += biped.bipedBody.rotateAngleY; - // biped.bipedRightArm.rotateAngleX += biped.bipedBody.rotateAngleY; float f6 = 1.0F - offhandSwing; f6 = 1.0F - f6 * f6 * f6; double f8 = MathHelper.sin(f6 * (float) Math.PI) * 1.2D; diff --git a/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java b/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java index aefde96..354e166 100644 --- a/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java +++ b/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java @@ -1,24 +1,30 @@ package xonin.backhand.coremod; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + import net.tclproject.mysteriumlib.asm.common.CustomClassTransformer; import net.tclproject.mysteriumlib.asm.common.CustomLoadingPlugin; import net.tclproject.mysteriumlib.asm.common.FirstClassTransformer; +import com.gtnewhorizon.gtnhmixins.IEarlyMixinLoader; + +import cpw.mods.fml.relauncher.FMLLaunchHandler; import cpw.mods.fml.relauncher.IFMLLoadingPlugin; import xonin.backhand.coremod.transformers.EntityAIControlledByPlayerTransformer; import xonin.backhand.coremod.transformers.EntityOtherPlayerMPTransformer; import xonin.backhand.coremod.transformers.EntityPlayerTransformer; import xonin.backhand.coremod.transformers.ItemInWorldTransformer; -import xonin.backhand.coremod.transformers.ModelBipedTransformer; import xonin.backhand.coremod.transformers.NetClientHandlerTransformer; import xonin.backhand.coremod.transformers.PlayerControllerMPTransformer; import xonin.backhand.coremod.transformers.TransformerBase; -public final class BackhandLoadingPlugin extends CustomLoadingPlugin implements IFMLLoadingPlugin { +public final class BackhandLoadingPlugin extends CustomLoadingPlugin implements IFMLLoadingPlugin, IEarlyMixinLoader { TransformerBase[] bt_transformers = { new EntityPlayerTransformer(), new PlayerControllerMPTransformer(), new ItemInWorldTransformer(), new EntityAIControlledByPlayerTransformer(), new EntityOtherPlayerMPTransformer(), - new ModelBipedTransformer(), new NetClientHandlerTransformer() }; + new NetClientHandlerTransformer() }; @Override public String[] getASMTransformerClass() { @@ -33,4 +39,29 @@ public void registerFixes() { registerClassWithFixes("net.tclproject.mysteriumlib.asm.fixes.MysteriumPatchesFixesO"); } + + @Override + public String getMixinConfig() { + return "mixins.backhand.early.json"; + } + + @Override + public List getMixins(Set loadedCoreMods) { + final List mixins = new ArrayList<>(); + mixins.add("MixinEntityPlayer"); + mixins.add("MixinItemStack"); + mixins.add("MixinInventoryPlayer"); + mixins.add("MixinNetHandlerPlayServer"); + if (FMLLaunchHandler.side() + .isClient()) { + mixins.add("MixinEntityOtherPlayerMP"); + mixins.add("MixinInventoryPlayerClient"); + mixins.add("MixinItemRenderer"); + mixins.add("MixinModelBiped"); + mixins.add("MixinNetHandlerPlayClient"); + mixins.add("MixinPlayerControllerMP"); + mixins.add("MixinItemBow"); + } + return mixins; + } } diff --git a/src/main/java/xonin/backhand/coremod/transformers/ModelBipedTransformer.java b/src/main/java/xonin/backhand/coremod/transformers/ModelBipedTransformer.java deleted file mode 100644 index 93c364e..0000000 --- a/src/main/java/xonin/backhand/coremod/transformers/ModelBipedTransformer.java +++ /dev/null @@ -1,67 +0,0 @@ -package xonin.backhand.coremod.transformers; - -import java.util.Iterator; - -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.FieldInsnNode; -import org.objectweb.asm.tree.InsnList; -import org.objectweb.asm.tree.MethodInsnNode; -import org.objectweb.asm.tree.MethodNode; -import org.objectweb.asm.tree.VarInsnNode; - -import xonin.backhand.api.core.BackhandTranslator; - -public final class ModelBipedTransformer extends TransformerMethodProcess { - - public ModelBipedTransformer() { - super( - "net.minecraft.client.model.ModelBiped", - "func_78087_a", - new String[] { "setRotationAngles", "(FFFFFFLnet/minecraft/entity/Entity;)V" }); - } - - private String modelBipedClassName; - private String entityClassName; - private String isSneakFieldName; - - @Override - void setupMappings() { - super.setupMappings(); - modelBipedClassName = BackhandTranslator.getMapedClassName("client.model.ModelBiped"); - entityClassName = BackhandTranslator.getMapedClassName("entity.Entity"); - isSneakFieldName = "field_78117_n!isSneak"; - } - - @Override - void processMethod(MethodNode method) { - - sendPatchLog("setRotationAngles"); - Iterator it = method.instructions.iterator(); - AbstractInsnNode nextInsn = null; - while (it.hasNext()) { - nextInsn = it.next(); - if (nextInsn.getOpcode() == ALOAD && ((VarInsnNode) nextInsn).var == 0) { - AbstractInsnNode follow = nextInsn.getNext(); - if (follow.getOpcode() == GETFIELD && ((FieldInsnNode) follow).desc.equals("Z") - && (((FieldInsnNode) follow).name.equals(isSneakFieldName.split("!")[0]) - || ((FieldInsnNode) follow).name.equals(isSneakFieldName.split("!")[1]))) { - break; - } - } - nextInsn = null; - } - if (nextInsn != null) { - InsnList newInsn = new InsnList(); - newInsn.add(new VarInsnNode(ALOAD, 7)); - newInsn.add(new VarInsnNode(ALOAD, 0)); - newInsn.add(new VarInsnNode(FLOAD, 6)); - newInsn.add( - new MethodInsnNode( - INVOKESTATIC, - "xonin/backhand/client/utils/BackhandRenderHelper", - "moveOffHandArm", - "(L" + entityClassName + ";L" + modelBipedClassName + ";F)V")); - method.instructions.insertBefore(nextInsn, newInsn); - } - } -} diff --git a/src/main/java/xonin/backhand/coremod/transformers/PlayerControllerMPTransformer.java b/src/main/java/xonin/backhand/coremod/transformers/PlayerControllerMPTransformer.java index 547bbb4..6558dac 100644 --- a/src/main/java/xonin/backhand/coremod/transformers/PlayerControllerMPTransformer.java +++ b/src/main/java/xonin/backhand/coremod/transformers/PlayerControllerMPTransformer.java @@ -6,6 +6,7 @@ public final class PlayerControllerMPTransformer extends TransformerMethodProcess { + // Todo: This is converted and clashing with mixin but replaceInventoryArrayAccess is needed? public PlayerControllerMPTransformer() { super( "net.minecraft.client.multiplayer.PlayerControllerMP", diff --git a/src/main/java/xonin/backhand/mixins/early/MixinEntityOtherPlayerMP.java b/src/main/java/xonin/backhand/mixins/early/MixinEntityOtherPlayerMP.java new file mode 100644 index 0000000..7dc4fa8 --- /dev/null +++ b/src/main/java/xonin/backhand/mixins/early/MixinEntityOtherPlayerMP.java @@ -0,0 +1,48 @@ +package xonin.backhand.mixins.early; + +import net.minecraft.client.entity.AbstractClientPlayer; +import net.minecraft.client.entity.EntityOtherPlayerMP; +import net.minecraft.world.World; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import com.mojang.authlib.GameProfile; + +@Mixin(EntityOtherPlayerMP.class) +public abstract class MixinEntityOtherPlayerMP extends AbstractClientPlayer { + + @Shadow + private boolean isItemInUse; + + private MixinEntityOtherPlayerMP(World p_i45074_1_, GameProfile p_i45074_2_) { + super(p_i45074_1_, p_i45074_2_); + } + + // @Inject( + // method = "onUpdate", + // cancellable = true, + // at = @At( + // value = "FIELD", + // target = "Lnet/minecraft/client/entity/EntityOtherPlayerMP;isItemInUse:Z", + // shift = At.Shift.BEFORE, + // ordinal = 0)) + // private void battlegear2$isItemInUseHook(CallbackInfo ci) { + // if (BattlegearUtils.isPlayerInBattlemode(this)) { + // ci.cancel(); + // ItemStack itemStack = this.getCurrentEquippedItem(); + // ItemStack offhand = ((IInventoryPlayerBattle) this.inventory).battlegear2$getCurrentOffhandWeapon(); + // if (offhand != null && BattlegearUtils.usagePriorAttack(offhand, this, true)) { + // itemStack = offhand; + // } + // if (!this.isItemInUse && this.isEating() && itemStack != null) { + // this.setItemInUse(itemStack, itemStack.getMaxItemUseDuration()); + // this.isItemInUse = true; + // } else if (this.isItemInUse && !this.isEating()) { + // this.clearItemInUse(); + // this.isItemInUse = false; + // } + // } + // } + +} diff --git a/src/main/java/xonin/backhand/mixins/early/MixinEntityPlayer.java b/src/main/java/xonin/backhand/mixins/early/MixinEntityPlayer.java new file mode 100644 index 0000000..8739dab --- /dev/null +++ b/src/main/java/xonin/backhand/mixins/early/MixinEntityPlayer.java @@ -0,0 +1,207 @@ +package xonin.backhand.mixins.early; + +import net.minecraft.client.Minecraft; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.item.ItemBow; +import net.minecraft.item.ItemStack; +import net.minecraft.util.IIcon; +import net.minecraft.world.World; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +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.callback.CallbackInfoReturnable; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.ModifyReturnValue; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import xonin.backhand.api.core.IBackhandPlayer; +import xonin.backhand.client.utils.BackhandClientUtils; + +@Mixin(EntityPlayer.class) +public abstract class MixinEntityPlayer extends EntityLivingBase implements IBackhandPlayer { + + @Shadow + private ItemStack itemInUse; + @Shadow + public InventoryPlayer inventory; + @Unique + private float backhand$offHandSwingProgress = 0F; + @Unique + private float backhand$prevOffHandSwingProgress = 0F; + @Unique + private int backhand$offHandSwingProgressInt = 0; + @Unique + private boolean backhand$isOffHandSwingInProgress = false; + @Unique + private int backhand$specialActionTimer = 0; + @Unique + private boolean backhand$isShielding = false; + + private MixinEntityPlayer(World p_i1594_1_) { + super(p_i1594_1_); + } + + @Unique + private int backhand$local$onItemFinish$i; + + @ModifyExpressionValue( + method = "onItemUseFinish", + at = @At(value = "FIELD", target = "Lnet/minecraft/item/ItemStack;stackSize:I", ordinal = 0)) + private int backhand$captureLocal$onItemFinish(int i) { + this.backhand$local$onItemFinish$i = i; + return i; + } + + // TODO: move client side stuff to a different class + @SideOnly(Side.CLIENT) + @Inject(method = "getItemIcon", at = @At(value = "HEAD")) + private void backhand2$getItemIcon(ItemStack itemStackIn, int p_70620_2_, CallbackInfoReturnable cir) { + if (worldObj.isRemote) { + EntityPlayer player = Minecraft.getMinecraft().thePlayer; + if (itemStackIn == player.getCurrentEquippedItem() && player.getCurrentEquippedItem() != null + && player.getItemInUse() != null + && player.getCurrentEquippedItem() + .getItem() instanceof ItemBow + && player.getCurrentEquippedItem() != player.getItemInUse()) { + BackhandClientUtils.disableMainhandAnimation = true; + } + } + } + + @SideOnly(Side.CLIENT) + @Override + public float getSwingProgress(float partialTicks) { + if (BackhandClientUtils.offhandFPRender) { + return getOffSwingProgress(partialTicks); + } + return super.getSwingProgress(partialTicks); + } + + // TODO: Why are we doing this? + @ModifyReturnValue(method = "isPlayer", at = @At(value = "RETURN")) + private boolean backhand$isPlayer(boolean original) { + return false; + } + + // @ModifyExpressionValue( + // method = "onItemUseFinish", + // at = @At( + // value = "INVOKE", + // target = + // "Lnet/minecraftforge/event/ForgeEventFactory;onItemUseFinish(Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/item/ItemStack;ILnet/minecraft/item/ItemStack;)Lnet/minecraft/item/ItemStack;", + // remap = false)) + // private ItemStack backhand$onItemUseFinish$beforeFinishUse(ItemStack itemStack) { + // return BattlegearUtils.beforeFinishUseEvent( + // (EntityPlayer) (Object) this, + // this.itemInUse, + // itemStack, + // this.backhand$local$onItemFinish$i); + // } + // + // @ModifyExpressionValue( + // method = "onUpdate", + // at = @At( + // value = "INVOKE", + // target = "Lnet/minecraft/entity/player/InventoryPlayer;getCurrentItem()Lnet/minecraft/item/ItemStack;")) + // private ItemStack backhand$onUpdate$getCurrentItem(ItemStack currentItemStack) { + // if (BattlegearUtils.isPlayerInBattlemode((EntityPlayer) (Object) this)) { + // ItemStack itemStack = ((IInventoryPlayerBattle) this.inventory).backhand$getCurrentOffhandWeapon(); + // if (itemInUse == itemStack) { + // return itemStack; + // } + // } + // return currentItemStack; + // } + // + // /** + // * @author Alexdoru + // * @reason IDK it's the original mod that does that + // */ + // @Overwrite + // public boolean interactWith(Entity var1) { + // return BattlegearUtils.interactWith((EntityPlayer) (Object) this, var1); + // } + // + // @Override + // protected void updateArmSwingProgress() { + // super.updateArmSwingProgress(); + // this.backhand$prevOffHandSwingProgress = this.backhand$offHandSwingProgress; + // int var1 = this.getArmSwingAnimationEnd(); + // if (this.backhand$isOffHandSwingInProgress) { + // ++this.backhand$offHandSwingProgressInt; + // if (this.backhand$offHandSwingProgressInt >= var1) { + // this.backhand$offHandSwingProgressInt = 0; + // this.backhand$isOffHandSwingInProgress = false; + // } + // } else { + // this.backhand$offHandSwingProgressInt = 0; + // } + // + // this.backhand$offHandSwingProgress = (float) this.backhand$offHandSwingProgressInt / (float) var1; + // if (this.backhand$specialActionTimer > 0) { + // this.backhand$isOffHandSwingInProgress = false; + // this.isSwingInProgress = false; + // this.backhand$offHandSwingProgress = 0.0F; + // this.backhand$offHandSwingProgressInt = 0; + // this.swingProgress = 0.0F; + // this.swingProgressInt = 0; + // } + // + // } + // + // @Override + // public void backhand$swingOffItem() { + // if (!this.backhand$isOffHandSwingInProgress + // || this.backhand$offHandSwingProgressInt >= this.getArmSwingAnimationEnd() / 2 + // || this.backhand$offHandSwingProgressInt < 0) { + // this.backhand$offHandSwingProgressInt = -1; + // this.backhand$isOffHandSwingInProgress = true; + // } + // } + // + // @Override + // public float backhand$getOffSwingProgress(float frame) { + // float diff = this.backhand$offHandSwingProgress - this.backhand$prevOffHandSwingProgress; + // if (diff < 0.0F) { + // ++diff; + // } + // return this.backhand$prevOffHandSwingProgress + diff * frame; + // } + // + // public void backhand$attackTargetEntityWithCurrentOffItem(Entity target) { + // BattlegearUtils.attackTargetEntityWithCurrentOffItem((EntityPlayer) (Object) this, target); + // } + // + // @Override + // public boolean backhand$isBattlemode() { + // return BattlegearUtils.isPlayerInBattlemode((EntityPlayer) (Object) this); + // } + // + // @Override + // public boolean backhand$isBlockingWithShield() { + // return BattlegearUtils.canBlockWithShield((EntityPlayer) (Object) this) && this.backhand$isShielding; + // } + // + // @Override + // public void backhand$setBlockingWithShield(boolean block) { + // this.backhand$isShielding = block && BattlegearUtils.canBlockWithShield((EntityPlayer) (Object) this); + // } + // + // @Override + // public int backhand$getSpecialActionTimer() { + // return this.backhand$specialActionTimer; + // } + // + // @Override + // public void backhand$setSpecialActionTimer(int time) { + // this.backhand$specialActionTimer = time; + // } + +} diff --git a/src/main/java/xonin/backhand/mixins/early/MixinEntityPlayerMP.java b/src/main/java/xonin/backhand/mixins/early/MixinEntityPlayerMP.java new file mode 100644 index 0000000..576a4c1 --- /dev/null +++ b/src/main/java/xonin/backhand/mixins/early/MixinEntityPlayerMP.java @@ -0,0 +1,31 @@ +package xonin.backhand.mixins.early; + +import java.util.List; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.inventory.Container; +import net.minecraft.item.ItemStack; +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.CallbackInfo; + +import com.mojang.authlib.GameProfile; + +import xonin.backhand.api.core.BackhandUtils; + +@Mixin(EntityPlayerMP.class) +public abstract class MixinEntityPlayerMP extends EntityPlayer { + + public MixinEntityPlayerMP(World p_i45324_1_, GameProfile p_i45324_2_) { + super(p_i45324_1_, p_i45324_2_); + } + + @Inject(method = "sendContainerAndContentsToPlayer", at = @At(value = "TAIL")) + private void backhand$syncOffhand(Container p_71110_1_, List p_71110_2_, CallbackInfo ci) { + BackhandUtils.getOffhandEP(this).syncOffhand = true; + } +} diff --git a/src/main/java/xonin/backhand/mixins/early/MixinInventoryPlayer.java b/src/main/java/xonin/backhand/mixins/early/MixinInventoryPlayer.java new file mode 100644 index 0000000..aff1312 --- /dev/null +++ b/src/main/java/xonin/backhand/mixins/early/MixinInventoryPlayer.java @@ -0,0 +1,266 @@ +package xonin.backhand.mixins.early; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.item.ItemStack; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; + +import xonin.backhand.api.core.BackhandUtils; +import xonin.backhand.api.core.InventoryPlayerBackhand; + +@Mixin(InventoryPlayer.class) +public abstract class MixinInventoryPlayer { + + @Shadow + public int currentItem; + + @Shadow + public EntityPlayer player; + + @ModifyReturnValue(method = "getCurrentItem", at = @At("RETURN")) + private ItemStack backhand$getOffhandItem(ItemStack original) { + if (currentItem == InventoryPlayerBackhand.OFFHAND_HOTBAR_SLOT) { + return BackhandUtils.getOffhandItem(player); + } + + return original; + } + + // @Unique + // public boolean battlegear2$isDirty = true; + // @Unique + // private ItemStack[] battlegear2$extraItems = new ItemStack[EXTRA_INV_SIZE]; + // + // @Shadow + // public int currentItem; + // @Shadow + // public EntityPlayer player; + // + // @Shadow + // public abstract ItemStack getStackInSlot(int slotIn); + // + // @Shadow + // public abstract ItemStack getCurrentItem(); + // + // @Shadow + // public abstract void setInventorySlotContents(int index, ItemStack stack); + // + // @Inject(method = "getCurrentItem", at = @At("HEAD"), cancellable = true) + // private void battlegear2$getCurrentItem(CallbackInfoReturnable cir) { + // if (battlegear2$isBattlemode()) { + // cir.setReturnValue(battlegear2$extraItems[currentItem - OFFSET]); + // } + // } + // + // @Inject(method = "func_146023_a", at = @At("HEAD"), cancellable = true) + // private void battlegear2$func_146023_a(Block block, CallbackInfoReturnable cir) { + // if (battlegear2$isBattlemode()) { + // ItemStack currentItemStack = getCurrentItem(); + // cir.setReturnValue(currentItemStack != null ? currentItemStack.func_150997_a(block) : 1.0F); + // } + // } + // + // @Inject(method = "getStackInSlot", at = @At("HEAD"), cancellable = true) + // private void battlegear2$getStackInSlot(int slotIn, CallbackInfoReturnable cir) { + // if (slotIn >= OFFSET) { + // cir.setReturnValue(battlegear2$extraItems[slotIn - OFFSET]); + // } + // } + // + // @ModifyReturnValue(method = "hasItem", at = @At("RETURN")) + // private boolean battlegear2$hasItem(boolean original, Item item) { + // if (original) { + // return true; + // } + // return battlegear2$getInventorySlotContainItem(item) >= 0; + // } + // + // /** + // * Returns a slot index in extra item inventory containing a specific item + // */ + // @Unique + // private int battlegear2$getInventorySlotContainItem(Item item) { + // for (int i = 0; i < this.battlegear2$extraItems.length; ++i) { + // if (this.battlegear2$extraItems[i] != null && this.battlegear2$extraItems[i].getItem() == item) { + // return i; + // } + // } + // return -1; + // } + // + // @Inject(method = "decrementAnimations", at = @At("RETURN")) + // private void battlegear2$decrementAnimations(CallbackInfo ci) { + // for (int i = 0; i < this.battlegear2$extraItems.length; ++i) { + // if (this.battlegear2$extraItems[i] != null) { + // this.battlegear2$extraItems[i] + // .updateAnimation(this.player.worldObj, this.player, i + OFFSET, this.currentItem == i + OFFSET); + // } + // } + // } + // + // @Inject(method = "decrStackSize", at = @At("HEAD"), cancellable = true) + // private void battlegear2$decrStackSize(int index, int count, CallbackInfoReturnable cir) { + // if (index >= OFFSET) { + // ItemStack targetStack = battlegear2$extraItems[index - OFFSET]; + // if (targetStack != null) { + // battlegear2$isDirty = true; + // if (targetStack.stackSize <= count) { + // battlegear2$extraItems[index - OFFSET] = null; + // } else { + // targetStack = battlegear2$extraItems[index - OFFSET].splitStack(count); + // if (battlegear2$extraItems[index - OFFSET].stackSize == 0) { + // battlegear2$extraItems[index - OFFSET] = null; + // } + // } + // cir.setReturnValue(targetStack); + // return; + // } + // cir.setReturnValue(null); + // } + // } + // + // @Inject(method = "setInventorySlotContents", at = @At("HEAD"), cancellable = true) + // private void battlegear2$setInventorySlotContents(int index, ItemStack stack, CallbackInfo ci) { + // if (index >= OFFSET) { + // battlegear2$isDirty = true; + // battlegear2$extraItems[index - OFFSET] = stack; + // ci.cancel(); + // } + // } + // + // @Override + // public void battlegear2$setInventorySlotContents(int index, ItemStack stack, boolean changed) { + // if (index >= OFFSET) { + // battlegear2$isDirty = changed; + // battlegear2$extraItems[index - OFFSET] = stack; + // } else { + // this.setInventorySlotContents(index, stack); + // } + // } + // + // @ModifyReturnValue(method = "clearInventory", at = @At("RETURN")) + // private int battlegear2$clearInventory(int original, Item targetItem, int targetDamage) { + // int stacks = 0; + // for (int i = 0; i < battlegear2$extraItems.length; i++) { + // if (battlegear2$extraItems[i] != null + // && (targetItem == null || battlegear2$extraItems[i].getItem() == targetItem) + // && (targetDamage <= -1 || battlegear2$extraItems[i].getItemDamage() == targetDamage)) { + // stacks += battlegear2$extraItems[i].stackSize; + // battlegear2$extraItems[i] = null; + // } + // } + // battlegear2$isDirty = stacks > 0; + // return original + stacks; + // } + // + // @Inject(method = "getStackInSlotOnClosing", at = @At("HEAD"), cancellable = true) + // private void battlegear2$getStackInSlotOnClosing(int slot, CallbackInfoReturnable cir) { + // if (slot >= OFFSET) { + // cir.setReturnValue(battlegear2$extraItems[slot - OFFSET]); + // } + // } + // + // @Inject(method = "consumeInventoryItem", at = @At("HEAD"), cancellable = true) + // private void battlegear2$consumeInventoryItem(Item item, CallbackInfoReturnable cir) { + // int j = battlegear2$getInventorySlotContainItem(item); + // if (j >= 0) { + // this.battlegear2$isDirty = true; + // if (--this.battlegear2$extraItems[j].stackSize <= 0) { + // this.battlegear2$extraItems[j] = null; + // } + // cir.setReturnValue(true); + // } + // } + // + // @Inject(method = "dropAllItems", at = @At("RETURN")) + // private void battlegear2$dropAllItems(CallbackInfo ci) { + // this.battlegear2$isDirty = true; + // for (int i = 0; i < this.battlegear2$extraItems.length; ++i) { + // if (this.battlegear2$extraItems[i] != null) { + // this.player.func_146097_a(this.battlegear2$extraItems[i], true, false); + // this.battlegear2$extraItems[i] = null; + // } + // } + // } + // + // @Inject(method = "copyInventory", at = @At("RETURN")) + // private void battlegear2$copyInventory(InventoryPlayer otherInventory, CallbackInfo ci) { + // for (int i = 0; i < battlegear2$extraItems.length; i++) { + // this.battlegear2$extraItems[i] = ItemStack.copyItemStack(otherInventory.getStackInSlot(i + OFFSET)); + // } + // } + // + // @ModifyReturnValue(method = "writeToNBT", at = @At("RETURN")) + // private NBTTagList battlegear2$writeToNBT(NBTTagList nbtTagList) { + // NBTTagCompound nbttagcompound; + // for (int i = 0; i < battlegear2$extraItems.length; ++i) { + // if (battlegear2$extraItems[i] != null) { + // nbttagcompound = new NBTTagCompound(); + // // This will be -ve, but meh still works + // nbttagcompound.setByte("Slot", (byte) (i + OFFSET)); + // this.battlegear2$extraItems[i].writeToNBT(nbttagcompound); + // nbtTagList.appendTag(nbttagcompound); + // } + // } + // return nbtTagList; + // } + // + // @Inject(method = "readFromNBT", at = @At("HEAD")) + // private void battlegear2$readFromNBT$initInventory(NBTTagList taglist, CallbackInfo ci) { + // this.battlegear2$extraItems = new ItemStack[EXTRA_INV_SIZE]; + // } + // + // @Inject( + // method = "readFromNBT", + // at = @At( + // value = "INVOKE", + // target = + // "Lnet/minecraft/item/ItemStack;loadItemStackFromNBT(Lnet/minecraft/nbt/NBTTagCompound;)Lnet/minecraft/item/ItemStack;", + // shift = At.Shift.BY, + // by = 2), + // locals = LocalCapture.CAPTURE_FAILHARD) + // private void battlegear2$readFromNBT$setItems(NBTTagList p_70443_1_, CallbackInfo ci, int i, + // NBTTagCompound nbttagcompound, int j, ItemStack stack) { + // if (stack != null && j >= OFFSET && j - OFFSET < this.battlegear2$extraItems.length) { + // this.battlegear2$extraItems[j - OFFSET] = stack; + // } + // } + // + // @Override + // public boolean battlegear2$isDirty() { + // return battlegear2$isDirty; + // } + // + // @Override + // public void battlegear2$setDirty(boolean dirty) { + // this.battlegear2$isDirty = dirty; + // } + // + // /** + // * @return true if the current item value is offset in the battle slot range + // */ + // @Override + // public boolean battlegear2$isBattlemode() { + // return this.currentItem >= OFFSET && this.currentItem < OFFSET + EXTRA_ITEMS; + // } + // + // /** + // * Get the offset item (for the left hand) + // * + // * @return the item held in left hand, if any + // */ + // @Override + // public ItemStack battlegear2$getCurrentOffhandWeapon() { + // if (battlegear2$isBattlemode()) { + // return getStackInSlot(currentItem + WEAPON_SETS); + // } else { + // return null; + // } + // } + +} diff --git a/src/main/java/xonin/backhand/mixins/early/MixinInventoryPlayerClient.java b/src/main/java/xonin/backhand/mixins/early/MixinInventoryPlayerClient.java new file mode 100644 index 0000000..3265319 --- /dev/null +++ b/src/main/java/xonin/backhand/mixins/early/MixinInventoryPlayerClient.java @@ -0,0 +1,39 @@ +package xonin.backhand.mixins.early; + +import net.minecraft.entity.player.InventoryPlayer; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(InventoryPlayer.class) +public abstract class MixinInventoryPlayerClient { + + @Shadow + public int currentItem; + + // @Inject(method = "func_146030_a", at = @At("HEAD"), cancellable = true) + // private void battlegear2$setCurrentItem(Item itemIn, int metadataIn, boolean isMetaSpecific, + // boolean forceInEmptySlots, CallbackInfo ci) { + // if (battlegear2$isBattlemode()) { + // ci.cancel(); + // } + // } + // + // @Inject(method = "changeCurrentItem", at = @At("HEAD"), cancellable = true) + // private void battlegear2$changeCurrentItem(int direction, CallbackInfo ci) { + // if (battlegear2$isBattlemode()) { + // if (direction > 0) { + // direction = 1; + // } else if (direction != 0) { + // direction = -1; + // } + // // noinspection StatementWithEmptyBody + // for (currentItem -= direction; currentItem < OFFSET; currentItem += WEAPON_SETS) {} + // while (currentItem >= OFFSET + WEAPON_SETS) { + // currentItem -= WEAPON_SETS; + // } + // ci.cancel(); + // } + // } + +} diff --git a/src/main/java/xonin/backhand/mixins/early/MixinItemBow.java b/src/main/java/xonin/backhand/mixins/early/MixinItemBow.java new file mode 100644 index 0000000..682bc2f --- /dev/null +++ b/src/main/java/xonin/backhand/mixins/early/MixinItemBow.java @@ -0,0 +1,31 @@ +package xonin.backhand.mixins.early; + +import net.minecraft.client.Minecraft; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemBow; +import net.minecraft.util.IIcon; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import xonin.backhand.client.utils.BackhandClientUtils; + +@Mixin(ItemBow.class) +public abstract class MixinItemBow extends Item { + + @SideOnly(Side.CLIENT) + @ModifyReturnValue(method = "getItemIconForUseDuration", at = @At("RETURN")) + private IIcon backhand$cancelAnimation(IIcon original) { + if (BackhandClientUtils.disableMainhandAnimation) { + BackhandClientUtils.disableMainhandAnimation = false; + EntityPlayer player = Minecraft.getMinecraft().thePlayer; + return getIcon(player.getCurrentEquippedItem(), 0, player, player.getItemInUse(), 0); + } + return original; + } +} diff --git a/src/main/java/xonin/backhand/mixins/early/MixinItemRenderer.java b/src/main/java/xonin/backhand/mixins/early/MixinItemRenderer.java new file mode 100644 index 0000000..a46b959 --- /dev/null +++ b/src/main/java/xonin/backhand/mixins/early/MixinItemRenderer.java @@ -0,0 +1,56 @@ +package xonin.backhand.mixins.early; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.ItemRenderer; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemMap; +import net.minecraft.item.ItemStack; + +import org.lwjgl.opengl.GL11; +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.Backhand; +import xonin.backhand.api.core.BackhandUtils; +import xonin.backhand.api.core.IBackhandPlayer; +import xonin.backhand.client.ClientEventHandler; +import xonin.backhand.client.renderer.RenderOffhandPlayer; +import xonin.backhand.client.utils.BackhandClientUtils; + +@Mixin(ItemRenderer.class) +public abstract class MixinItemRenderer { + + @Inject(method = "renderItemInFirstPerson", at = @At("RETURN")) + private void backhand$renderItemInFirstPerson(float frame, CallbackInfo ci) { + if (BackhandClientUtils.offhandFPRender) return; + + EntityPlayer player = Minecraft.getMinecraft().thePlayer; + ClientEventHandler.renderingPlayer = player; + + ItemStack mainhandItem = player.getCurrentEquippedItem(); + ItemStack offhandItem = BackhandUtils.getOffhandItem(player); + if (!Backhand.EmptyOffhand && !Backhand.RenderEmptyOffhandAtRest && offhandItem == null) { + return; + } + if (offhandItem == null && !Backhand.RenderEmptyOffhandAtRest + && ((IBackhandPlayer) player).getOffSwingProgress(frame) == 0) { + return; + } + if (mainhandItem != null && mainhandItem.getItem() instanceof ItemMap) { + return; + } + + BackhandClientUtils.firstPersonFrame = frame; + + BackhandClientUtils.onGround2 = 0; + RenderOffhandPlayer.itemRenderer.updateEquippedItem(); + BackhandClientUtils.offhandFPRender = true; + GL11.glEnable(GL11.GL_CULL_FACE); + GL11.glCullFace(GL11.GL_FRONT); + ClientEventHandler.renderOffhandPlayer.renderOffhandItem((ItemRenderer) (Object) this, frame); + GL11.glCullFace(GL11.GL_BACK); + BackhandClientUtils.offhandFPRender = false; + } +} diff --git a/src/main/java/xonin/backhand/mixins/early/MixinItemStack.java b/src/main/java/xonin/backhand/mixins/early/MixinItemStack.java new file mode 100644 index 0000000..3a1095a --- /dev/null +++ b/src/main/java/xonin/backhand/mixins/early/MixinItemStack.java @@ -0,0 +1,61 @@ +package xonin.backhand.mixins.early; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; +import net.minecraft.item.ItemStack; +import net.minecraftforge.event.ForgeEventFactory; + +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.ModifyReturnValue; + +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.relauncher.Side; +import xonin.backhand.HookContainerClass; +import xonin.backhand.api.core.BackhandUtils; +import xonin.backhand.client.ClientEventHandler; + +@Mixin(ItemStack.class) +public abstract class MixinItemStack { + + @Inject(method = "damageItem", at = @At(value = "TAIL")) + private void backhand$damageOffhand(int p_77972_1_, EntityLivingBase entity, CallbackInfo ci) { + if (!(entity instanceof EntityPlayer player)) return; + + ItemStack itemStack = (ItemStack) (Object) this; + ItemStack offhandItem = BackhandUtils.getOffhandItem(player); + if (offhandItem != null && itemStack == offhandItem && itemStack.stackSize == 0) { + BackhandUtils.setPlayerOffhandItem(player, null); + ForgeEventFactory.onPlayerDestroyItem(player, offhandItem); + } + } + + @ModifyReturnValue(method = "getItemUseAction", at = @At(value = "TAIL")) + private EnumAction backhand$getOffhandUseAction(EnumAction original) { + if (original == EnumAction.none || FMLCommonHandler.instance() + .getEffectiveSide() == Side.CLIENT && ClientEventHandler.renderingPlayer == null) { + return original; + } + EntityPlayer player = ClientEventHandler.renderingPlayer; + ItemStack itemStack = (ItemStack) (Object) this; + ItemStack offhandItem = BackhandUtils.getOffhandItem(player); + if (offhandItem != null) { + ItemStack mainHandItem = player.getCurrentEquippedItem(); + if (mainHandItem != null && (BackhandUtils.checkForRightClickFunctionNoAction(mainHandItem) + || HookContainerClass.isItemBlock(mainHandItem.getItem()))) { + if (itemStack == offhandItem) { + return EnumAction.none; + } + } else if (itemStack == mainHandItem && (!(BackhandUtils.checkForRightClickFunctionNoAction(offhandItem) + || HookContainerClass.isItemBlock(offhandItem.getItem())) || player.getItemInUse() != mainHandItem)) { + return EnumAction.none; + } + } + return original; + } + +} diff --git a/src/main/java/xonin/backhand/mixins/early/MixinModelBiped.java b/src/main/java/xonin/backhand/mixins/early/MixinModelBiped.java new file mode 100644 index 0000000..0972baf --- /dev/null +++ b/src/main/java/xonin/backhand/mixins/early/MixinModelBiped.java @@ -0,0 +1,176 @@ +package xonin.backhand.mixins.early; + +import net.minecraft.client.model.ModelBiped; +import net.minecraft.entity.Entity; + +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.client.utils.BackhandRenderHelper; + +@Mixin(ModelBiped.class) +public abstract class MixinModelBiped { + + @Inject( + method = "setRotationAngles", + at = @At(value = "FIELD", target = "Lnet/minecraft/client/model/ModelBiped;isSneak:Z", shift = At.Shift.BEFORE)) + private void backhand$moveOffHandArm(float f1, float f2, float f3, float f4, float f5, float f6, Entity entity, + CallbackInfo ci) { + BackhandRenderHelper.moveOffHandArm(entity, (ModelBiped) (Object) this, f6); + } + + // TODO: Decipher this shit + // private static void setRotationAngles(ModelBiped b, float p_78087_1_, float p_78087_2_, float p_78087_3_, + // float p_78087_4_, float p_78087_5_, float p_78087_6_, Entity p_78087_7_) { + // b.bipedHead.rotateAngleY = p_78087_4_ / (180F / (float) Math.PI); + // b.bipedHead.rotateAngleX = p_78087_5_ / (180F / (float) Math.PI); + // b.bipedHeadwear.rotateAngleY = b.bipedHead.rotateAngleY; + // b.bipedHeadwear.rotateAngleX = b.bipedHead.rotateAngleX; + // b.bipedRightArm.rotateAngleX = MathHelper.cos(p_78087_1_ * 0.6662F + (float) Math.PI) * 2.0F + // * p_78087_2_ + // * 0.5F; + // b.bipedLeftArm.rotateAngleX = MathHelper.cos(p_78087_1_ * 0.6662F) * 2.0F * p_78087_2_ * 0.5F; + // b.bipedRightArm.rotateAngleZ = 0.0F; + // b.bipedLeftArm.rotateAngleZ = 0.0F; + // b.bipedRightLeg.rotateAngleX = MathHelper.cos(p_78087_1_ * 0.6662F) * 1.4F * p_78087_2_; + // b.bipedLeftLeg.rotateAngleX = MathHelper.cos(p_78087_1_ * 0.6662F + (float) Math.PI) * 1.4F * p_78087_2_; + // b.bipedRightLeg.rotateAngleY = 0.0F; + // b.bipedLeftLeg.rotateAngleY = 0.0F; + // + // if (b.isRiding) { + // b.bipedRightArm.rotateAngleX += -((float) Math.PI / 5F); + // b.bipedLeftArm.rotateAngleX += -((float) Math.PI / 5F); + // b.bipedRightLeg.rotateAngleX = -((float) Math.PI * 2F / 5F); + // b.bipedLeftLeg.rotateAngleX = -((float) Math.PI * 2F / 5F); + // b.bipedRightLeg.rotateAngleY = ((float) Math.PI / 10F); + // b.bipedLeftLeg.rotateAngleY = -((float) Math.PI / 10F); + // } + // + // if (b.heldItemLeft != 0) { + // b.bipedLeftArm.rotateAngleX = b.bipedLeftArm.rotateAngleX * 0.5F + // - ((float) Math.PI / 10F) * (float) b.heldItemLeft; + // } + // + // if (b.heldItemRight != 0) { + // b.bipedRightArm.rotateAngleX = b.bipedRightArm.rotateAngleX * 0.5F + // - ((float) Math.PI / 10F) * (float) b.heldItemRight; + // } + // + // b.bipedRightArm.rotateAngleY = 0.0F; + // b.bipedLeftArm.rotateAngleY = 0.0F; + // float f6; + // float f7; + // + // if (b.onGround > -9990.0F) { + // f6 = b.onGround; + // b.bipedBody.rotateAngleY = MathHelper.sin(MathHelper.sqrt_float(f6) * (float) Math.PI * 2.0F) * 0.2F; + // b.bipedRightArm.rotationPointZ = MathHelper.sin(b.bipedBody.rotateAngleY) * 5.0F; + // b.bipedRightArm.rotationPointX = -MathHelper.cos(b.bipedBody.rotateAngleY) * 5.0F; + // b.bipedLeftArm.rotationPointZ = -MathHelper.sin(b.bipedBody.rotateAngleY) * 5.0F; + // b.bipedLeftArm.rotationPointX = MathHelper.cos(b.bipedBody.rotateAngleY) * 5.0F; + // b.bipedRightArm.rotateAngleY += b.bipedBody.rotateAngleY; + // b.bipedLeftArm.rotateAngleY += b.bipedBody.rotateAngleY; + // b.bipedLeftArm.rotateAngleX += b.bipedBody.rotateAngleY; + // f6 = 1.0F - b.onGround; + // f6 *= f6; + // f6 *= f6; + // f6 = 1.0F - f6; + // f7 = MathHelper.sin(f6 * (float) Math.PI); + // float f8 = MathHelper.sin(b.onGround * (float) Math.PI) * -(b.bipedHead.rotateAngleX - 0.7F) * 0.75F; + // b.bipedRightArm.rotateAngleX = (float) ((double) b.bipedRightArm.rotateAngleX + // - ((double) f7 * 1.2D + (double) f8)); + // b.bipedRightArm.rotateAngleY += b.bipedBody.rotateAngleY * 2.0F; + // b.bipedRightArm.rotateAngleZ = MathHelper.sin(b.onGround * (float) Math.PI) * -0.4F; + // } + // + // if (p_78087_7_ instanceof EntityPlayer && (p_78087_7_ != Minecraft.getMinecraft().thePlayer + // || ((IBackhandPlayer) p_78087_7_).getOffSwingProgress(MysteriumPatchesFixesO.firstPersonFrame) != 0)) { + // if (onGround2 > -9990.0F) { + // f6 = onGround2; + // b.bipedBody.rotateAngleY = MathHelper.sin(MathHelper.sqrt_float(f6) * (float) Math.PI * 2.0F) * 0.2F; + // b.bipedRightArm.rotationPointZ = MathHelper.sin(b.bipedBody.rotateAngleY) * 5.0F; + // b.bipedRightArm.rotationPointX = -MathHelper.cos(b.bipedBody.rotateAngleY) * 5.0F; + // b.bipedLeftArm.rotationPointZ = -MathHelper.sin(b.bipedBody.rotateAngleY) * 5.0F; + // b.bipedLeftArm.rotationPointX = MathHelper.cos(b.bipedBody.rotateAngleY) * 5.0F; + // b.bipedRightArm.rotateAngleY += b.bipedBody.rotateAngleY; + // b.bipedLeftArm.rotateAngleY += b.bipedBody.rotateAngleY; + // b.bipedLeftArm.rotateAngleX += b.bipedBody.rotateAngleY; + // f6 = 1.0F - onGround2; + // f6 *= f6; + // f6 *= f6; + // f6 = 1.0F - f6; + // f7 = MathHelper.sin(f6 * (float) Math.PI); + // float f8 = MathHelper.sin(onGround2 * (float) Math.PI) * -(b.bipedHead.rotateAngleX - 0.7F) * 0.75F; + // b.bipedLeftArm.rotateAngleX = (float) ((double) b.bipedLeftArm.rotateAngleX + // - ((double) f7 * 1.2D + (double) f8)); + // b.bipedLeftArm.rotateAngleY -= b.bipedBody.rotateAngleY * 2.0F; + // b.bipedLeftArm.rotateAngleZ = -MathHelper.sin(onGround2 * (float) Math.PI) * -0.4F; + // } + // } + // + // if (b.isSneak) { + // b.bipedBody.rotateAngleX = 0.5F; + // b.bipedRightArm.rotateAngleX += 0.4F; + // b.bipedLeftArm.rotateAngleX += 0.4F; + // b.bipedRightLeg.rotationPointZ = 4.0F; + // b.bipedLeftLeg.rotationPointZ = 4.0F; + // b.bipedRightLeg.rotationPointY = 9.0F; + // b.bipedLeftLeg.rotationPointY = 9.0F; + // b.bipedHead.rotationPointY = 1.0F; + // b.bipedHeadwear.rotationPointY = 1.0F; + // } else { + // b.bipedBody.rotateAngleX = 0.0F; + // b.bipedRightLeg.rotationPointZ = 0.1F; + // b.bipedLeftLeg.rotationPointZ = 0.1F; + // b.bipedRightLeg.rotationPointY = 12.0F; + // b.bipedLeftLeg.rotationPointY = 12.0F; + // b.bipedHead.rotationPointY = 0.0F; + // b.bipedHeadwear.rotationPointY = 0.0F; + // } + // + // b.bipedRightArm.rotateAngleZ += MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; + // b.bipedLeftArm.rotateAngleZ -= MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; + // b.bipedRightArm.rotateAngleX += MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; + // b.bipedLeftArm.rotateAngleX -= MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; + // + // if (b.aimedBow) { + // if (p_78087_7_ instanceof EntityPlayer && p_78087_7_ == Minecraft.getMinecraft().thePlayer + // && BackhandUtils.getOffhandItem((EntityPlayer) p_78087_7_) != null + // && ((EntityClientPlayerMP) p_78087_7_).getItemInUse() + // == BackhandUtils.getOffhandItem((EntityPlayer) p_78087_7_)) { + // f6 = 0.0F; + // f7 = 0.0F; + // b.bipedLeftArm.rotateAngleZ = 0.0F; + // b.bipedRightArm.rotateAngleZ = 0.0F; + // b.bipedLeftArm.rotateAngleY = 0.1F + b.bipedHead.rotateAngleY; + // b.bipedRightArm.rotateAngleY = -0.5F + b.bipedHead.rotateAngleY; + // b.bipedLeftArm.rotateAngleX = -((float) Math.PI / 2F) + b.bipedHead.rotateAngleX; + // b.bipedRightArm.rotateAngleX = -((float) Math.PI / 2F) + b.bipedHead.rotateAngleX; + // b.bipedLeftArm.rotateAngleX -= f6 * 1.2F - f7 * 0.4F; + // b.bipedRightArm.rotateAngleX -= f6 * 1.2F - f7 * 0.4F; + // b.bipedLeftArm.rotateAngleZ -= MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; + // b.bipedRightArm.rotateAngleZ += MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; + // b.bipedLeftArm.rotateAngleX -= MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; + // b.bipedRightArm.rotateAngleX += MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; + // } else { + // f6 = 0.0F; + // f7 = 0.0F; + // b.bipedRightArm.rotateAngleZ = 0.0F; + // b.bipedLeftArm.rotateAngleZ = 0.0F; + // b.bipedRightArm.rotateAngleY = -(0.1F - f6 * 0.6F) + b.bipedHead.rotateAngleY; + // b.bipedLeftArm.rotateAngleY = 0.1F - f6 * 0.6F + b.bipedHead.rotateAngleY + 0.4F; + // b.bipedRightArm.rotateAngleX = -((float) Math.PI / 2F) + b.bipedHead.rotateAngleX; + // b.bipedLeftArm.rotateAngleX = -((float) Math.PI / 2F) + b.bipedHead.rotateAngleX; + // b.bipedRightArm.rotateAngleX -= f6 * 1.2F - f7 * 0.4F; + // b.bipedLeftArm.rotateAngleX -= f6 * 1.2F - f7 * 0.4F; + // b.bipedRightArm.rotateAngleZ += MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; + // b.bipedLeftArm.rotateAngleZ -= MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; + // b.bipedRightArm.rotateAngleX += MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; + // b.bipedLeftArm.rotateAngleX -= MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; + // } + // } + // } + +} diff --git a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayClient.java b/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayClient.java new file mode 100644 index 0000000..759c480 --- /dev/null +++ b/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayClient.java @@ -0,0 +1,43 @@ +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 { + + @ModifyExpressionValue( + method = "handleHeldItemChange", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/network/play/server/S09PacketHeldItemChange;func_149385_c()I", + ordinal = 1)) + private int backhand$isValidIventorySlot(int original) { + // 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 new file mode 100644 index 0000000..5a899c8 --- /dev/null +++ b/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java @@ -0,0 +1,65 @@ +package xonin.backhand.mixins.early; + +import net.minecraft.network.NetHandlerPlayServer; +import net.minecraft.server.management.ItemInWorldManager; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; + +import xonin.backhand.api.core.InventoryPlayerBackhand; + +@Mixin(NetHandlerPlayServer.class) +public abstract class MixinNetHandlerPlayServer { + + @ModifyExpressionValue( + method = "processHeldItemChange", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/network/play/client/C09PacketHeldItemChange;func_149614_c()I", + ordinal = 1)) + private int backhand$isValidIventorySlot(int original) { + // return a valid int e.g. between 0 and < 9 + return InventoryPlayerBackhand.isValidSwitch(original) ? 0 : -1; + } + + // @WrapOperation( + // method = "processPlayerBlockPlacement", + // at = @At( + // value = "INVOKE", + // target = + // "Lnet/minecraft/inventory/Container;getSlotFromInventory(Lnet/minecraft/inventory/IInventory;I)Lnet/minecraft/inventory/Slot;")) + // private Slot battlegear2$captureSlotVariable(Container instance, IInventory j, int i, Operation original, + // @Share("slot") LocalRef slotRef) { + // Slot slot = original.call(instance, j, i); + // slotRef.set(slot); + // return slot; + // } + // + // @Inject( + // method = "processPlayerBlockPlacement", + // at = @At( + // value = "FIELD", + // target = "Lnet/minecraft/entity/player/EntityPlayerMP;isChangingQuantityOnly:Z", + // shift = At.Shift.AFTER, + // ordinal = 1), + // cancellable = true) + // private void battlegear2$fixNPE(C08PacketPlayerBlockPlacement packetIn, CallbackInfo ci, + // @Share("slot") LocalRef slotRef) { + // if (slotRef.get() == null) { + // ci.cancel(); + // } + // } + + @Redirect( + 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) { + instance.theWorld.destroyBlockInWorldPartially(instance.thisPlayerMP.getEntityId(), x, y, z, -1); + instance.tryHarvestBlock(x, y, z); + } +} diff --git a/src/main/java/xonin/backhand/mixins/early/MixinPlayerControllerMP.java b/src/main/java/xonin/backhand/mixins/early/MixinPlayerControllerMP.java new file mode 100644 index 0000000..d9be78c --- /dev/null +++ b/src/main/java/xonin/backhand/mixins/early/MixinPlayerControllerMP.java @@ -0,0 +1,69 @@ +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; + +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(); + } + } + + @ModifyReturnValue(method = "interactWithEntitySendPacket", at = @At("RETURN")) + private boolean backhand$setAttackDelay(boolean original) { + if (original) { + BackhandClientTickHandler.attackDelay = 5; + } + return original; + } + + // @Inject(method = "sendUseItem", at = @At(value = "FIELD", opcode = Opcodes.GETFIELD, target = + // "Lnet/minecraft/entity/player/InventoryPlayer;mainInventory:[Lnet/minecraft/item/ItemStack;")) + // private void backhand$sendUseItem(EntityPlayer player, World worldIn, ItemStack itemStackIn, + // CallbackInfoReturnable cir, @Local(ordinal = 1) ItemStack rightClickStack) { + // ItemStack stack = rightClickStack.stackSize == 0 ? null : rightClickStack; + // BackhandUtils.setPlayerCurrentItem(player, stack); + // cir.cancel(); + // } +} diff --git a/src/main/java/xonin/backhand/packet/OffhandConfigSyncPacket.java b/src/main/java/xonin/backhand/packet/OffhandConfigSyncPacket.java index f468d2e..0ea655a 100644 --- a/src/main/java/xonin/backhand/packet/OffhandConfigSyncPacket.java +++ b/src/main/java/xonin/backhand/packet/OffhandConfigSyncPacket.java @@ -2,10 +2,10 @@ package xonin.backhand.packet; import net.minecraft.entity.player.EntityPlayer; -import net.tclproject.mysteriumlib.asm.fixes.MysteriumPatchesFixesO; import io.netty.buffer.ByteBuf; import xonin.backhand.Backhand; +import xonin.backhand.client.utils.BackhandClientUtils; public final class OffhandConfigSyncPacket extends AbstractPacket { @@ -28,7 +28,7 @@ public void process(ByteBuf inputStream, EntityPlayer player) { Backhand.OffhandTickHotswap = inputStream.readBoolean(); Backhand.AlternateOffhandSlot = inputStream.readInt(); Backhand.UseInventorySlot = inputStream.readBoolean(); - MysteriumPatchesFixesO.receivedConfigs = true; + BackhandClientUtils.receivedConfigs = true; } @Override diff --git a/src/main/java/xonin/backhand/packet/OffhandWorldHotswapPacket.java b/src/main/java/xonin/backhand/packet/OffhandWorldHotswapPacket.java index 2a46282..a950eb0 100644 --- a/src/main/java/xonin/backhand/packet/OffhandWorldHotswapPacket.java +++ b/src/main/java/xonin/backhand/packet/OffhandWorldHotswapPacket.java @@ -1,9 +1,9 @@ package xonin.backhand.packet; import net.minecraft.entity.player.EntityPlayer; -import net.tclproject.mysteriumlib.asm.fixes.MysteriumPatchesFixesO; import io.netty.buffer.ByteBuf; +import xonin.backhand.client.utils.BackhandClientUtils; public class OffhandWorldHotswapPacket extends AbstractPacket { @@ -29,6 +29,6 @@ public void write(ByteBuf out) { @Override public void process(ByteBuf inputStream, EntityPlayer player) { - MysteriumPatchesFixesO.ignoreSetSlot = inputStream.readBoolean(); + BackhandClientUtils.ignoreSetSlot = inputStream.readBoolean(); } } diff --git a/src/main/resources/mixins.backhand.early.json b/src/main/resources/mixins.backhand.early.json new file mode 100644 index 0000000..d6009d3 --- /dev/null +++ b/src/main/resources/mixins.backhand.early.json @@ -0,0 +1,11 @@ +{ + "required": true, + "minVersion": "0.8.5-GTNH", + "package": "xonin.backhand.mixins.early", + "refmap": "mixins.backhand.refmap.json", + "target": "@env(DEFAULT)", + "compatibilityLevel": "JAVA_8", + "mixins": [], + "client": [], + "server": [] +} diff --git a/src/main/resources/mixins.backhand.json b/src/main/resources/mixins.backhand.json new file mode 100644 index 0000000..4b5925f --- /dev/null +++ b/src/main/resources/mixins.backhand.json @@ -0,0 +1,11 @@ +{ + "required": true, + "minVersion": "0.8.5-GTNH", + "package": "xonin.backhand.mixins", + "refmap": "mixins.backhand.refmap.json", + "target": "@env(DEFAULT)", + "compatibilityLevel": "JAVA_8", + "mixins": [], + "client": [], + "server": [] +} From d91856d50f2a32748ebee56b99cf85f7d269c2b3 Mon Sep 17 00:00:00 2001 From: Lyfts <127234178+Lyfts@users.noreply.github.com> Date: Thu, 25 Jul 2024 20:51:55 +0200 Subject: [PATCH 2/9] convert all the needed bg transformers --- .../asm/fixes/MysteriumPatchesFixesO.java | 614 +----------------- .../coremod/BackhandLoadingPlugin.java | 20 +- ...EntityAIControlledByPlayerTransformer.java | 31 - .../EntityOtherPlayerMPTransformer.java | 120 ---- .../transformers/EntityPlayerTransformer.java | 424 ------------ .../transformers/ItemInWorldTransformer.java | 79 --- .../NetClientHandlerTransformer.java | 78 --- .../PlayerControllerMPTransformer.java | 34 - .../coremod/transformers/TransformerBase.java | 209 ------ .../TransformerMethodProcess.java | 46 -- .../early/MixinEntityOtherPlayerMP.java | 51 +- .../mixins/early/MixinEntityPlayer.java | 246 +++---- .../mixins/early/MixinEntityPlayerClient.java | 45 ++ .../mixins/early/MixinInventoryPlayer.java | 236 +------ .../early/MixinInventoryPlayerClient.java | 39 -- .../backhand/mixins/early/MixinItemStack.java | 32 - .../mixins/early/MixinItemStackClient.java | 42 ++ .../mixins/early/MixinModelBiped.java | 2 +- .../early/MixinNetHandlerPlayClient.java | 1 - .../early/MixinNetHandlerPlayServer.java | 28 - .../mixins/early/MixinPlayerControllerMP.java | 22 +- 21 files changed, 255 insertions(+), 2144 deletions(-) delete mode 100644 src/main/java/xonin/backhand/coremod/transformers/EntityAIControlledByPlayerTransformer.java delete mode 100644 src/main/java/xonin/backhand/coremod/transformers/EntityOtherPlayerMPTransformer.java delete mode 100644 src/main/java/xonin/backhand/coremod/transformers/EntityPlayerTransformer.java delete mode 100644 src/main/java/xonin/backhand/coremod/transformers/ItemInWorldTransformer.java delete mode 100644 src/main/java/xonin/backhand/coremod/transformers/NetClientHandlerTransformer.java delete mode 100644 src/main/java/xonin/backhand/coremod/transformers/PlayerControllerMPTransformer.java delete mode 100644 src/main/java/xonin/backhand/coremod/transformers/TransformerBase.java delete mode 100644 src/main/java/xonin/backhand/coremod/transformers/TransformerMethodProcess.java create mode 100644 src/main/java/xonin/backhand/mixins/early/MixinEntityPlayerClient.java delete mode 100644 src/main/java/xonin/backhand/mixins/early/MixinInventoryPlayerClient.java create mode 100644 src/main/java/xonin/backhand/mixins/early/MixinItemStackClient.java diff --git a/src/main/java/net/tclproject/mysteriumlib/asm/fixes/MysteriumPatchesFixesO.java b/src/main/java/net/tclproject/mysteriumlib/asm/fixes/MysteriumPatchesFixesO.java index 77966e9..2378e73 100644 --- a/src/main/java/net/tclproject/mysteriumlib/asm/fixes/MysteriumPatchesFixesO.java +++ b/src/main/java/net/tclproject/mysteriumlib/asm/fixes/MysteriumPatchesFixesO.java @@ -3,24 +3,18 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.reflect.Field; -import java.lang.reflect.Method; import net.minecraft.client.particle.EffectRenderer; -import net.minecraft.client.renderer.entity.RendererLivingEntity; import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.item.EntityXPOrb; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.projectile.EntityArrow; -import net.minecraft.item.ItemStack; import net.minecraft.network.NetHandlerPlayServer; import net.minecraft.network.play.client.C02PacketUseEntity; import net.minecraft.util.MovingObjectPosition; import net.minecraft.world.WorldServer; import net.tclproject.mysteriumlib.asm.annotations.EnumReturnSetting; import net.tclproject.mysteriumlib.asm.annotations.Fix; -import net.tclproject.mysteriumlib.asm.annotations.ReturnedValue; import cpw.mods.fml.common.Optional; import cpw.mods.fml.relauncher.Side; @@ -33,118 +27,6 @@ public class MysteriumPatchesFixesO { - /** - * Dirty hack to prevent random resetting of block removal (why does this even happen?!) when breaking blocks with - * the offhand. - */ - // public static int countToCancel = 0; - // /** 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; - // - // public static boolean receivedConfigs = false; - - // @Fix(returnSetting = EnumReturnSetting.ALWAYS) - // public static boolean isPlayer(EntityPlayer p) { - // return false; - // } - - // @Fix(insertOnExit = true) - // public static void damageItem(ItemStack itemStack, int p_77972_1_, EntityLivingBase p_77972_2_) { - // if (!(p_77972_2_ instanceof EntityPlayer) || itemStack == null) return; - // - // EntityPlayer player = (EntityPlayer) p_77972_2_; - // ItemStack offhandItem = BackhandUtils.getOffhandItem(player); - // if (offhandItem != null && itemStack == offhandItem && itemStack.stackSize == 0) { - // BackhandUtils.setPlayerOffhandItem(player, null); - // ForgeEventFactory.onPlayerDestroyItem(player, offhandItem); - // } - // } - // - // @Fix(insertOnExit = true, returnSetting = EnumReturnSetting.ALWAYS) - // public static EnumAction getItemUseAction(ItemStack itemStack, @ReturnedValue EnumAction returnedAction) { - // if (returnedAction != EnumAction.none) { - // if (FMLCommonHandler.instance() - // .getEffectiveSide() == Side.CLIENT && ClientEventHandler.renderingPlayer != null) { - // EntityPlayer player = ClientEventHandler.renderingPlayer; - // ItemStack offhandItem = BackhandUtils.getOffhandItem(player); - // - // if (offhandItem != null) { - // ItemStack mainHandItem = player.getCurrentEquippedItem(); - // if (mainHandItem != null && (BackhandUtils.checkForRightClickFunctionNoAction(mainHandItem) - // || HookContainerClass.isItemBlock(mainHandItem.getItem()))) { - // if (itemStack == offhandItem) { - // return EnumAction.none; - // } - // } else if (itemStack == mainHandItem - // && (!(BackhandUtils.checkForRightClickFunctionNoAction(offhandItem) - // || HookContainerClass.isItemBlock(offhandItem.getItem())) - // || player.getItemInUse() != mainHandItem)) { - // return EnumAction.none; - // } - // } - // } - // } - // return itemStack != null && itemStack.getItem() != null ? itemStack.getItem() - // .getItemUseAction(itemStack) : EnumAction.none; - // } - - // private static boolean disableMainhandAnimation = false; - - // @SideOnly(Side.CLIENT) - // @Fix(insertOnExit = true, returnSetting = EnumReturnSetting.ALWAYS) - // public static IIcon getItemIcon(EntityLivingBase entity, ItemStack p_70620_1_, int p_70620_2_, - // @ReturnedValue IIcon returnValue) { - // if (entity instanceof EntityPlayer) { - // EntityPlayer player = (EntityPlayer) entity; - // if (p_70620_1_ == player.getCurrentEquippedItem() && player.getCurrentEquippedItem() != null - // && player.getItemInUse() != null - // && player.getCurrentEquippedItem() - // .getItem() instanceof ItemBow - // && player.getCurrentEquippedItem() != player.getItemInUse()) { - // disableMainhandAnimation = true; - // } - // } - // return returnValue; - // } - - // @SideOnly(Side.CLIENT) - // @Fix(insertOnExit = true, returnSetting = EnumReturnSetting.ALWAYS) - // public static IIcon getItemIconForUseDuration(ItemBow bow, int p_94599_1_, @ReturnedValue IIcon returnValue) { - // if (disableMainhandAnimation) { - // disableMainhandAnimation = false; - // EntityPlayer player = Minecraft.getMinecraft().thePlayer; - // return bow.getIcon(player.getCurrentEquippedItem(), 0, player, player.getItemInUse(), 0); - // } - // return returnValue; - // } - // - // @SideOnly(Side.CLIENT) - // @Fix(returnSetting = EnumReturnSetting.ON_TRUE) - // public static boolean resetBlockRemoving(PlayerControllerMP controller) { - // if (countToCancel > 0) { - // countToCancel--; - // return true; - // } else { - // if (MysteriumPatchesFixesO.hotSwapped) { - // Minecraft.getMinecraft().playerController.syncCurrentPlayItem(); - // MysteriumPatchesFixesO.hotSwapped = false; - // } - // return false; - // } - // } - - // @Fix(returnSetting = EnumReturnSetting.ON_TRUE) - // @SideOnly(Side.CLIENT) - // public static boolean clickBlock(PlayerControllerMP mp, int p_78743_1_, int p_78743_2_, int p_78743_3_, - // int p_78743_4_) { - // if (ClientEventHandler.cancelone) { - // mp.resetBlockRemoving(); - // return true; - // } - // return false; - // } - @Fix(returnSetting = EnumReturnSetting.ON_TRUE) @SideOnly(Side.CLIENT) public static boolean addBlockHitEffects(EffectRenderer er, int x, int y, int z, MovingObjectPosition target) { @@ -154,358 +36,6 @@ public static boolean addBlockHitEffects(EffectRenderer er, int x, int y, int z, return false; } - // @Fix(returnSetting = EnumReturnSetting.ON_TRUE) - // @SideOnly(Side.CLIENT) - // public static boolean onPlayerDamageBlock(PlayerControllerMP mp, int p_78759_1_, int p_78759_2_, int p_78759_3_, - // int p_78759_4_) { - // if (ClientEventHandler.cancelone) { - // mp.resetBlockRemoving(); - // return true; - // } - // return false; - // } - - // public static float onGround2; - // public static float firstPersonFrame; - // public static boolean offhandFPRender; - // - // @Fix(insertOnExit = true) - // @SideOnly(Side.CLIENT) - // public static void renderItemInFirstPerson(ItemRenderer itemRenderer, float frame) { - // if (offhandFPRender) return; - // - // EntityPlayer player = Minecraft.getMinecraft().thePlayer; - // ClientEventHandler.renderingPlayer = player; - // - // ItemStack mainhandItem = player.getCurrentEquippedItem(); - // ItemStack offhandItem = BackhandUtils.getOffhandItem(player); - // if (!Backhand.EmptyOffhand && !Backhand.RenderEmptyOffhandAtRest && offhandItem == null) { - // return; - // } - // if (offhandItem == null && !Backhand.RenderEmptyOffhandAtRest - // && ((IBackhandPlayer) player).getOffSwingProgress(frame) == 0) { - // return; - // } - // if (mainhandItem != null && mainhandItem.getItem() instanceof ItemMap) { - // return; - // } - // - // MysteriumPatchesFixesO.firstPersonFrame = frame; - // - // MysteriumPatchesFixesO.onGround2 = 0; - // RenderOffhandPlayer.itemRenderer.updateEquippedItem(); - // offhandFPRender = true; - // GL11.glEnable(GL11.GL_CULL_FACE); - // GL11.glCullFace(GL11.GL_FRONT); - // ClientEventHandler.renderOffhandPlayer.renderOffhandItem(itemRenderer, frame); - // GL11.glCullFace(GL11.GL_BACK); - // offhandFPRender = false; - // } - - // @SideOnly(Side.CLIENT) - // @Fix(insertOnExit = true, returnSetting = EnumReturnSetting.ALWAYS) - // public static float getSwingProgress(EntityLivingBase entityLivingBase, float partialTicks, - // @ReturnedValue float returnedValue) { - // if (offhandFPRender) { - // return ((IBackhandPlayer) entityLivingBase).getOffSwingProgress(partialTicks); - // } - // return returnedValue; - // } - - @Fix - @SideOnly(Side.CLIENT) - public static void doRender(RendererLivingEntity l, EntityLivingBase p_76986_1_, double p_76986_2_, - double p_76986_4_, double p_76986_6_, float p_76986_8_, float p_76986_9_) { - if (p_76986_1_ instanceof EntityPlayer) { - // onGround2 = ((IBackhandPlayer) p_76986_1_).getOffSwingProgress(p_76986_9_); - } - } - - // @Fix(returnSetting = EnumReturnSetting.ALWAYS) - // @SideOnly(Side.CLIENT) - // public static void setRotationAngles(ModelBiped b, float p_78087_1_, float p_78087_2_, float p_78087_3_, - // float p_78087_4_, float p_78087_5_, float p_78087_6_, Entity p_78087_7_) { - // b.bipedHead.rotateAngleY = p_78087_4_ / (180F / (float) Math.PI); - // b.bipedHead.rotateAngleX = p_78087_5_ / (180F / (float) Math.PI); - // b.bipedHeadwear.rotateAngleY = b.bipedHead.rotateAngleY; - // b.bipedHeadwear.rotateAngleX = b.bipedHead.rotateAngleX; - // b.bipedRightArm.rotateAngleX = MathHelper.cos(p_78087_1_ * 0.6662F + (float) Math.PI) * 2.0F - // * p_78087_2_ - // * 0.5F; - // b.bipedLeftArm.rotateAngleX = MathHelper.cos(p_78087_1_ * 0.6662F) * 2.0F * p_78087_2_ * 0.5F; - // b.bipedRightArm.rotateAngleZ = 0.0F; - // b.bipedLeftArm.rotateAngleZ = 0.0F; - // b.bipedRightLeg.rotateAngleX = MathHelper.cos(p_78087_1_ * 0.6662F) * 1.4F * p_78087_2_; - // b.bipedLeftLeg.rotateAngleX = MathHelper.cos(p_78087_1_ * 0.6662F + (float) Math.PI) * 1.4F * p_78087_2_; - // b.bipedRightLeg.rotateAngleY = 0.0F; - // b.bipedLeftLeg.rotateAngleY = 0.0F; - // - // if (b.isRiding) { - // b.bipedRightArm.rotateAngleX += -((float) Math.PI / 5F); - // b.bipedLeftArm.rotateAngleX += -((float) Math.PI / 5F); - // b.bipedRightLeg.rotateAngleX = -((float) Math.PI * 2F / 5F); - // b.bipedLeftLeg.rotateAngleX = -((float) Math.PI * 2F / 5F); - // b.bipedRightLeg.rotateAngleY = ((float) Math.PI / 10F); - // b.bipedLeftLeg.rotateAngleY = -((float) Math.PI / 10F); - // } - // - // if (b.heldItemLeft != 0) { - // b.bipedLeftArm.rotateAngleX = b.bipedLeftArm.rotateAngleX * 0.5F - // - ((float) Math.PI / 10F) * (float) b.heldItemLeft; - // } - // - // if (b.heldItemRight != 0) { - // b.bipedRightArm.rotateAngleX = b.bipedRightArm.rotateAngleX * 0.5F - // - ((float) Math.PI / 10F) * (float) b.heldItemRight; - // } - // - // b.bipedRightArm.rotateAngleY = 0.0F; - // b.bipedLeftArm.rotateAngleY = 0.0F; - // float f6; - // float f7; - // - // if (b.onGround > -9990.0F) { - // f6 = b.onGround; - // b.bipedBody.rotateAngleY = MathHelper.sin(MathHelper.sqrt_float(f6) * (float) Math.PI * 2.0F) * 0.2F; - // b.bipedRightArm.rotationPointZ = MathHelper.sin(b.bipedBody.rotateAngleY) * 5.0F; - // b.bipedRightArm.rotationPointX = -MathHelper.cos(b.bipedBody.rotateAngleY) * 5.0F; - // b.bipedLeftArm.rotationPointZ = -MathHelper.sin(b.bipedBody.rotateAngleY) * 5.0F; - // b.bipedLeftArm.rotationPointX = MathHelper.cos(b.bipedBody.rotateAngleY) * 5.0F; - // b.bipedRightArm.rotateAngleY += b.bipedBody.rotateAngleY; - // b.bipedLeftArm.rotateAngleY += b.bipedBody.rotateAngleY; - // b.bipedLeftArm.rotateAngleX += b.bipedBody.rotateAngleY; - // f6 = 1.0F - b.onGround; - // f6 *= f6; - // f6 *= f6; - // f6 = 1.0F - f6; - // f7 = MathHelper.sin(f6 * (float) Math.PI); - // float f8 = MathHelper.sin(b.onGround * (float) Math.PI) * -(b.bipedHead.rotateAngleX - 0.7F) * 0.75F; - // b.bipedRightArm.rotateAngleX = (float) ((double) b.bipedRightArm.rotateAngleX - // - ((double) f7 * 1.2D + (double) f8)); - // b.bipedRightArm.rotateAngleY += b.bipedBody.rotateAngleY * 2.0F; - // b.bipedRightArm.rotateAngleZ = MathHelper.sin(b.onGround * (float) Math.PI) * -0.4F; - // } - // - // if (p_78087_7_ instanceof EntityPlayer && (p_78087_7_ != Minecraft.getMinecraft().thePlayer - // || ((IBackhandPlayer) p_78087_7_).getOffSwingProgress(MysteriumPatchesFixesO.firstPersonFrame) != 0)) { - // if (onGround2 > -9990.0F) { - // f6 = onGround2; - // b.bipedBody.rotateAngleY = MathHelper.sin(MathHelper.sqrt_float(f6) * (float) Math.PI * 2.0F) * 0.2F; - // b.bipedRightArm.rotationPointZ = MathHelper.sin(b.bipedBody.rotateAngleY) * 5.0F; - // b.bipedRightArm.rotationPointX = -MathHelper.cos(b.bipedBody.rotateAngleY) * 5.0F; - // b.bipedLeftArm.rotationPointZ = -MathHelper.sin(b.bipedBody.rotateAngleY) * 5.0F; - // b.bipedLeftArm.rotationPointX = MathHelper.cos(b.bipedBody.rotateAngleY) * 5.0F; - // b.bipedRightArm.rotateAngleY += b.bipedBody.rotateAngleY; - // b.bipedLeftArm.rotateAngleY += b.bipedBody.rotateAngleY; - // b.bipedLeftArm.rotateAngleX += b.bipedBody.rotateAngleY; - // f6 = 1.0F - onGround2; - // f6 *= f6; - // f6 *= f6; - // f6 = 1.0F - f6; - // f7 = MathHelper.sin(f6 * (float) Math.PI); - // float f8 = MathHelper.sin(onGround2 * (float) Math.PI) * -(b.bipedHead.rotateAngleX - 0.7F) * 0.75F; - // b.bipedLeftArm.rotateAngleX = (float) ((double) b.bipedLeftArm.rotateAngleX - // - ((double) f7 * 1.2D + (double) f8)); - // b.bipedLeftArm.rotateAngleY -= b.bipedBody.rotateAngleY * 2.0F; - // b.bipedLeftArm.rotateAngleZ = -MathHelper.sin(onGround2 * (float) Math.PI) * -0.4F; - // } - // } - // - // if (b.isSneak) { - // b.bipedBody.rotateAngleX = 0.5F; - // b.bipedRightArm.rotateAngleX += 0.4F; - // b.bipedLeftArm.rotateAngleX += 0.4F; - // b.bipedRightLeg.rotationPointZ = 4.0F; - // b.bipedLeftLeg.rotationPointZ = 4.0F; - // b.bipedRightLeg.rotationPointY = 9.0F; - // b.bipedLeftLeg.rotationPointY = 9.0F; - // b.bipedHead.rotationPointY = 1.0F; - // b.bipedHeadwear.rotationPointY = 1.0F; - // } else { - // b.bipedBody.rotateAngleX = 0.0F; - // b.bipedRightLeg.rotationPointZ = 0.1F; - // b.bipedLeftLeg.rotationPointZ = 0.1F; - // b.bipedRightLeg.rotationPointY = 12.0F; - // b.bipedLeftLeg.rotationPointY = 12.0F; - // b.bipedHead.rotationPointY = 0.0F; - // b.bipedHeadwear.rotationPointY = 0.0F; - // } - // - // b.bipedRightArm.rotateAngleZ += MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; - // b.bipedLeftArm.rotateAngleZ -= MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; - // b.bipedRightArm.rotateAngleX += MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; - // b.bipedLeftArm.rotateAngleX -= MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; - // - // if (b.aimedBow) { - // if (p_78087_7_ instanceof EntityPlayer && p_78087_7_ == Minecraft.getMinecraft().thePlayer - // && BackhandUtils.getOffhandItem((EntityPlayer) p_78087_7_) != null - // && ((EntityClientPlayerMP) p_78087_7_).getItemInUse() - // == BackhandUtils.getOffhandItem((EntityPlayer) p_78087_7_)) { - // f6 = 0.0F; - // f7 = 0.0F; - // b.bipedLeftArm.rotateAngleZ = 0.0F; - // b.bipedRightArm.rotateAngleZ = 0.0F; - // b.bipedLeftArm.rotateAngleY = 0.1F + b.bipedHead.rotateAngleY; - // b.bipedRightArm.rotateAngleY = -0.5F + b.bipedHead.rotateAngleY; - // b.bipedLeftArm.rotateAngleX = -((float) Math.PI / 2F) + b.bipedHead.rotateAngleX; - // b.bipedRightArm.rotateAngleX = -((float) Math.PI / 2F) + b.bipedHead.rotateAngleX; - // b.bipedLeftArm.rotateAngleX -= f6 * 1.2F - f7 * 0.4F; - // b.bipedRightArm.rotateAngleX -= f6 * 1.2F - f7 * 0.4F; - // b.bipedLeftArm.rotateAngleZ -= MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; - // b.bipedRightArm.rotateAngleZ += MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; - // b.bipedLeftArm.rotateAngleX -= MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; - // b.bipedRightArm.rotateAngleX += MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; - // } else { - // f6 = 0.0F; - // f7 = 0.0F; - // b.bipedRightArm.rotateAngleZ = 0.0F; - // b.bipedLeftArm.rotateAngleZ = 0.0F; - // b.bipedRightArm.rotateAngleY = -(0.1F - f6 * 0.6F) + b.bipedHead.rotateAngleY; - // b.bipedLeftArm.rotateAngleY = 0.1F - f6 * 0.6F + b.bipedHead.rotateAngleY + 0.4F; - // b.bipedRightArm.rotateAngleX = -((float) Math.PI / 2F) + b.bipedHead.rotateAngleX; - // b.bipedLeftArm.rotateAngleX = -((float) Math.PI / 2F) + b.bipedHead.rotateAngleX; - // b.bipedRightArm.rotateAngleX -= f6 * 1.2F - f7 * 0.4F; - // b.bipedLeftArm.rotateAngleX -= f6 * 1.2F - f7 * 0.4F; - // b.bipedRightArm.rotateAngleZ += MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; - // b.bipedLeftArm.rotateAngleZ -= MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; - // b.bipedRightArm.rotateAngleX += MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; - // b.bipedLeftArm.rotateAngleX -= MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; - // } - // } - // } - - // @Fix(returnSetting = EnumReturnSetting.ON_TRUE) - // public static boolean processPlayerDigging(NetHandlerPlayServer serv, C07PacketPlayerDigging p_147345_1_) { - // WorldServer worldserver = MinecraftServer.getServer() - // .worldServerForDimension(serv.playerEntity.dimension); - // serv.playerEntity.func_143004_u(); - // - // if (p_147345_1_.func_149506_g() == 4) { - // serv.playerEntity.dropOneItem(false); - // return true; - // } else if (p_147345_1_.func_149506_g() == 3) { - // serv.playerEntity.dropOneItem(true); - // return true; - // } else if (p_147345_1_.func_149506_g() == 5) { - // serv.playerEntity.stopUsingItem(); - // return true; - // } else { - // boolean flag = false; - // - // if (p_147345_1_.func_149506_g() == 0) { - // flag = true; - // } - // - // if (p_147345_1_.func_149506_g() == 1) { - // flag = true; - // } - // - // if (p_147345_1_.func_149506_g() == 2) { - // flag = true; - // } - // - // int i = p_147345_1_.func_149505_c(); - // int j = p_147345_1_.func_149503_d(); - // int k = p_147345_1_.func_149502_e(); - // if (flag) { - // double d0 = serv.playerEntity.posX - ((double) i + 0.5D); - // double d1 = serv.playerEntity.posY - ((double) j + 0.5D) + 1.5D; - // double d2 = serv.playerEntity.posZ - ((double) k + 0.5D); - // double d3 = d0 * d0 + d1 * d1 + d2 * d2; - // - // double dist = serv.playerEntity.theItemInWorldManager.getBlockReachDistance() + 1; - // dist *= dist; - // - // if (d3 > dist) { - // return true; - // } - // } - // - // if (p_147345_1_.func_149506_g() == 2) { - // customUncheckedTryHarvestBlock(serv.playerEntity.theItemInWorldManager, i, j, k); - // serv.playerEntity.theItemInWorldManager.uncheckedTryHarvestBlock(i, j, k); - // - // if (worldserver.getBlock(i, j, k) - // .getMaterial() != Material.air) { - // serv.playerEntity.playerNetServerHandler.sendPacket(new S23PacketBlockChange(i, j, k, worldserver)); - // } - // return true; - // } else if (p_147345_1_.func_149506_g() == 1) { - // serv.playerEntity.theItemInWorldManager.cancelDestroyingBlock(i, j, k); - // - // if (worldserver.getBlock(i, j, k) - // .getMaterial() != Material.air) { - // serv.playerEntity.playerNetServerHandler.sendPacket(new S23PacketBlockChange(i, j, k, worldserver)); - // } - // return true; - // } - // } - // return false; - // } - - // This might be a bad idea. (but if I didn't do this I would have to insert ~10 more fixes into forge-hooked - // methods and it might not even have worked) - // @Fix - // public static void uncheckedTryHarvestBlock(ItemInWorldManager m, int p_73082_1_, int p_73082_2_, int p_73082_3_) - // { - // m.theWorld.destroyBlockInWorldPartially(m.thisPlayerMP.getEntityId(), p_73082_1_, p_73082_2_, p_73082_3_, -1); - // m.tryHarvestBlock(p_73082_1_, p_73082_2_, p_73082_3_); - // } - - // public static void customUncheckedTryHarvestBlock(ItemInWorldManager m, int p_73082_1_, int p_73082_2_, - // int p_73082_3_) { - // m.theWorld.destroyBlockInWorldPartially(m.thisPlayerMP.getEntityId(), p_73082_1_, p_73082_2_, p_73082_3_, -1); - // m.tryHarvestBlock(p_73082_1_, p_73082_2_, p_73082_3_); - // } - - // @Fix(returnSetting = EnumReturnSetting.ALWAYS, insertOnExit = true) - // public static void sendContainerAndContentsToPlayer(EntityPlayerMP player, Container p_71110_1_, List p_71110_2_) - // { - // BackhandUtils.getOffhandEP(player).syncOffhand = true; - // } - - // public static boolean ignoreSetSlot = false; - - // @Fix(returnSetting = EnumReturnSetting.ALWAYS) - // public static void handleSetSlot(NetHandlerPlayClient netClient, S2FPacketSetSlot p_147266_1_) { - // EntityClientPlayerMP player = netClient.gameController.thePlayer; - // - // if (p_147266_1_.func_149175_c() == -1) { - // player.inventory.setItemStack( - // p_147266_1_.func_149174_e() == null || p_147266_1_.func_149174_e().stackSize == 0 ? null - // : p_147266_1_.func_149174_e()); - // } else if (!ignoreSetSlot) { - // boolean flag = false; - // - // if (netClient.gameController.currentScreen instanceof GuiContainerCreative) { - // GuiContainerCreative guicontainercreative = (GuiContainerCreative) netClient.gameController.currentScreen; - // flag = guicontainercreative.func_147056_g() != CreativeTabs.tabInventory.getTabIndex(); - // } - // - // if (p_147266_1_.func_149175_c() == 0 && p_147266_1_.func_149173_d() >= 36 - // && p_147266_1_.func_149173_d() < 45) { - // ItemStack itemstack = player.inventoryContainer.getSlot(p_147266_1_.func_149173_d()) - // .getStack(); - // - // if (p_147266_1_.func_149174_e() != null && p_147266_1_.func_149174_e().stackSize != 0 - // && (itemstack == null || itemstack.stackSize < p_147266_1_.func_149174_e().stackSize)) { - // p_147266_1_.func_149174_e().animationsToGo = 5; - // } - // - // player.inventoryContainer.putStackInSlot( - // p_147266_1_.func_149173_d(), - // p_147266_1_.func_149174_e() == null || p_147266_1_.func_149174_e().stackSize == 0 ? null - // : p_147266_1_.func_149174_e()); - // } else if (p_147266_1_.func_149175_c() == player.openContainer.windowId - // && (p_147266_1_.func_149175_c() != 0 || !flag)) { - // player.openContainer.putStackInSlot( - // p_147266_1_.func_149173_d(), - // p_147266_1_.func_149174_e() == null || p_147266_1_.func_149174_e().stackSize == 0 ? null - // : p_147266_1_.func_149174_e()); - // } - // } - // } - @Fix(returnSetting = EnumReturnSetting.ALWAYS) public static void processUseEntity(NetHandlerPlayServer netServer, C02PacketUseEntity p_147340_1_) { WorldServer worldserver = netServer.serverController.worldServerForDimension(netServer.playerEntity.dimension); @@ -554,55 +84,13 @@ public static void processUseEntity(NetHandlerPlayServer netServer, C02PacketUse } } - // @SideOnly(Side.CLIENT) - // @Fix(insertOnExit = true, returnSetting = EnumReturnSetting.ALWAYS) - // public static boolean interactWithEntitySendPacket(PlayerControllerMP controllerMP, EntityPlayer p_78768_1_, - // Entity p_78768_2_, @ReturnedValue boolean interacted) { - // if (interacted) { - // BackhandClientTickHandler.attackDelay = 5; - // } - // return interacted; - // } - - // @Fix(returnSetting = EnumReturnSetting.ALWAYS) - // public static void processHeldItemChange(NetHandlerPlayServer server, C09PacketHeldItemChange p_147355_1_) { - // if (p_147355_1_.func_149614_c() >= 0 && p_147355_1_.func_149614_c() < (InventoryPlayer.getHotbarSize()) - // || p_147355_1_.func_149614_c() == InventoryPlayerBackhand.OFFHAND_HOTBAR_SLOT) { - // server.playerEntity.inventory.currentItem = p_147355_1_.func_149614_c(); - // server.playerEntity.func_143004_u(); - // } else { - // System.out.println( - // server.playerEntity.getCommandSenderName() + " tried to set an invalid carried item " - // + p_147355_1_.func_149614_c()); - // } - // } - - // @Fix(insertOnExit = true, returnSetting = EnumReturnSetting.ON_NOT_NULL) - // public static ItemStack getCurrentItem(InventoryPlayer inv) { - // return inv.currentItem < 9 && inv.currentItem >= 0 ? inv.mainInventory[inv.currentItem] - // : inv.currentItem == InventoryPlayerBackhand.OFFHAND_HOTBAR_SLOT ? BackhandUtils.getOffhandItem(inv.player) - // : null; - // } - private static final MethodHandle fieldGetSection; private static final MethodHandle fieldGetContainerMgr; - // private static final MethodHandle fieldSetLightLevel; - // private static final Field fieldlightlevel; - // - // private static final MethodHandle fieldGetEntity; - // private static final Field fieldentity; - // - // private static final MethodHandle fieldGetEnabled; - // private static final Field fieldenabled; - static { MethodHandle fs, fs2, fg, fg2, fg3; Field f, f2, f3, f4; try { - // f = HandlerCheckPin.class.getDeclaredField("shouldReset"); - // f.setAccessible(true); - // fs = MethodHandles.publicLookup().unreflectSetter(f); f2 = InvTweaksContainerSectionManager.class.getDeclaredField("containerMgr"); f3 = InvTweaksContainerSectionManager.class.getDeclaredField("section"); @@ -614,65 +102,16 @@ public static void processUseEntity(NetHandlerPlayServer netServer, C02PacketUse .unreflectGetter(f2); fg2 = MethodHandles.publicLookup() .unreflectGetter(f3); - } catch (Exception e) { + } catch (Exception | NoClassDefFoundError e) { f = null; fs = null; fg = null; fg2 = null; - System.out.println( - "The 'Locks' mod compatibility hasn't been loaded due to not being able to find HandlerCheckPin. " - + "If you don't have the Locks mod installed, you can ignore this error."); - } catch (NoClassDefFoundError e) { - f = null; - fs = null; - fg = null; - fg2 = null; - System.out.println( - "The 'Locks' mod compatibility hasn't been loaded due to not being able to find HandlerCheckPin. " - + "If you don't have the Locks mod installed, you can ignore this error."); } - - // try { - // f2 = PlayerSelfAdaptor.class.getDeclaredField("thePlayer"); - // f3 = BaseAdaptor.class.getDeclaredField("lightLevel"); - // f4 = BaseAdaptor.class.getDeclaredField("enabled"); - // - // f2.setAccessible(true); - // f3.setAccessible(true); - // f4.setAccessible(true); - // - // fs2 = MethodHandles.publicLookup().unreflectSetter(f3); - // fg = MethodHandles.publicLookup().unreflectGetter(f2); - // fg2 = MethodHandles.publicLookup().unreflectGetter(f4); - // } catch (Exception e) { - // f2 = f3 = f4 = null; - // fs2 = fg = fg2 = fg3 = null; - // System.out.println("The 'Dynamic Lights' mod compatibility hasn't been loaded due to not being able to find - // BaseAdaptor. " + - // "If you don't have the Dynamic Lights mod installed, you can ignore this error."); - // } catch (NoClassDefFoundError e) { - // f2 = f3 = f4 = null; - // fs2 = fg = fg2 = fg3 = null; - // System.out.println("The 'Dynamic Lights' mod compatibility hasn't been loaded due to not being able to find - // BaseAdaptor. " + - // "If you don't have the Dynamic Lights mod installed, you can ignore this error."); - // } - - // field = f; - // fieldSet = fs; - fieldGetContainerMgr = fg; fieldGetSection = fg2; - // fieldlightlevel = f3; - // fieldentity = f2; - // fieldenabled = f4; - // - // fieldGetEnabled = fg2; - // fieldGetEntity = fg; - // fieldSetLightLevel = fs2; - - System.out.println("Loaded Mod Compatibility!"); + // System.out.println("Loaded Mod Compatibility!"); } @Optional.Method(modid = "inventorytweaks") @@ -710,36 +149,25 @@ public static InvTweaksContainerManager getContainerManager(InvTweaksContainerSe return manager; } - @Optional.Method(modid = "Optifine") - @SideOnly(Side.CLIENT) - @Fix(insertOnExit = true, returnSetting = EnumReturnSetting.ALWAYS) - public static int getLightLevel(Entity entity, @ReturnedValue int returned) { - if (entity instanceof EntityPlayer) { - EntityPlayer player = (EntityPlayer) entity; - ItemStack offhand = BackhandUtils.getOffhandItem(player); - try { - Method getLightLevel = Class.forName("DynamicLights") - .getMethod("getLightLevel", ItemStack.class); - int levelMain = (int) getLightLevel.invoke(null, offhand); - ItemStack stackHead = player.getEquipmentInSlot(4); - int levelHead = (int) getLightLevel.invoke(null, stackHead); - return Math.max(levelMain, levelHead); - } catch (Exception ignored) {} - } - return returned; - } + // Todo: Angelica is a thing so this is probably not needed - // inv tweaks compat starts here + // @Optional.Method(modid = "Optifine") + // @SideOnly(Side.CLIENT) + // @Fix(insertOnExit = true, returnSetting = EnumReturnSetting.ALWAYS) + // public static int getLightLevel(Entity entity, @ReturnedValue int returned) { + // if (entity instanceof EntityPlayer) { + // EntityPlayer player = (EntityPlayer) entity; + // ItemStack offhand = BackhandUtils.getOffhandItem(player); + // try { + // Method getLightLevel = Class.forName("DynamicLights") + // .getMethod("getLightLevel", ItemStack.class); + // int levelMain = (int) getLightLevel.invoke(null, offhand); + // ItemStack stackHead = player.getEquipmentInSlot(4); + // int levelHead = (int) getLightLevel.invoke(null, stackHead); + // return Math.max(levelMain, levelHead); + // } catch (Exception ignored) {} + // } + // return returned; + // } - /* - * @Optional.Method(modid="inventorytweaks") - * @Fix(returnSetting = EnumReturnSetting.ALWAYS) - * public static boolean move(InvTweaksContainerSectionManager itcm, int srcIndex, int destIndex) { - * if (CommonProxy.invTweaksDisableMove > 0) { - * CommonProxy.invTweaksDisableMove--; - * return getContainerManager(itcm).move(getContainerSection(itcm), srcIndex, getContainerSection(itcm), srcIndex); - * } - * return getContainerManager(itcm).move(getContainerSection(itcm), srcIndex, getContainerSection(itcm), destIndex); - * } - */ } diff --git a/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java b/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java index 354e166..3cd09e1 100644 --- a/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java +++ b/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java @@ -4,7 +4,6 @@ import java.util.List; import java.util.Set; -import net.tclproject.mysteriumlib.asm.common.CustomClassTransformer; import net.tclproject.mysteriumlib.asm.common.CustomLoadingPlugin; import net.tclproject.mysteriumlib.asm.common.FirstClassTransformer; @@ -12,20 +11,9 @@ import cpw.mods.fml.relauncher.FMLLaunchHandler; import cpw.mods.fml.relauncher.IFMLLoadingPlugin; -import xonin.backhand.coremod.transformers.EntityAIControlledByPlayerTransformer; -import xonin.backhand.coremod.transformers.EntityOtherPlayerMPTransformer; -import xonin.backhand.coremod.transformers.EntityPlayerTransformer; -import xonin.backhand.coremod.transformers.ItemInWorldTransformer; -import xonin.backhand.coremod.transformers.NetClientHandlerTransformer; -import xonin.backhand.coremod.transformers.PlayerControllerMPTransformer; -import xonin.backhand.coremod.transformers.TransformerBase; public final class BackhandLoadingPlugin extends CustomLoadingPlugin implements IFMLLoadingPlugin, IEarlyMixinLoader { - TransformerBase[] bt_transformers = { new EntityPlayerTransformer(), new PlayerControllerMPTransformer(), - new ItemInWorldTransformer(), new EntityAIControlledByPlayerTransformer(), new EntityOtherPlayerMPTransformer(), - new NetClientHandlerTransformer() }; - @Override public String[] getASMTransformerClass() { return new String[] { FirstClassTransformer.class.getName() }; @@ -33,10 +21,6 @@ public String[] getASMTransformerClass() { @Override public void registerFixes() { - for (TransformerBase transformer : bt_transformers) { - CustomClassTransformer.registerPostTransformer(transformer); - } - registerClassWithFixes("net.tclproject.mysteriumlib.asm.fixes.MysteriumPatchesFixesO"); } @@ -49,18 +33,20 @@ public String getMixinConfig() { public List getMixins(Set loadedCoreMods) { final List mixins = new ArrayList<>(); mixins.add("MixinEntityPlayer"); + mixins.add("MixinEntityPlayerMP"); mixins.add("MixinItemStack"); mixins.add("MixinInventoryPlayer"); mixins.add("MixinNetHandlerPlayServer"); if (FMLLaunchHandler.side() .isClient()) { mixins.add("MixinEntityOtherPlayerMP"); - mixins.add("MixinInventoryPlayerClient"); + mixins.add("MixinEntityPlayerClient"); mixins.add("MixinItemRenderer"); mixins.add("MixinModelBiped"); mixins.add("MixinNetHandlerPlayClient"); mixins.add("MixinPlayerControllerMP"); mixins.add("MixinItemBow"); + mixins.add("MixinItemStackClient"); } return mixins; } diff --git a/src/main/java/xonin/backhand/coremod/transformers/EntityAIControlledByPlayerTransformer.java b/src/main/java/xonin/backhand/coremod/transformers/EntityAIControlledByPlayerTransformer.java deleted file mode 100644 index ecf44ef..0000000 --- a/src/main/java/xonin/backhand/coremod/transformers/EntityAIControlledByPlayerTransformer.java +++ /dev/null @@ -1,31 +0,0 @@ -package xonin.backhand.coremod.transformers; - -import org.objectweb.asm.tree.MethodNode; - -import xonin.backhand.api.core.BackhandTranslator; - -public final class EntityAIControlledByPlayerTransformer extends TransformerMethodProcess { - - public EntityAIControlledByPlayerTransformer() { - super( - "net.minecraft.entity.ai.EntityAIControlledByPlayer", - "func_75246_d", - new String[] { "updateTask", SIMPLEST_METHOD_DESC }); - } - - private String entityPlayerClassName; - private String playerInventoryFieldName; - - @Override - void processMethod(MethodNode method) { - sendPatchLog("updateTask"); - replaceInventoryArrayAccess(method, entityPlayerClassName, playerInventoryFieldName, 8, 23); - } - - @Override - void setupMappings() { - super.setupMappings(); - entityPlayerClassName = BackhandTranslator.getMapedClassName("entity.player.EntityPlayer"); - playerInventoryFieldName = "field_71071_by!inventory"; - } -} diff --git a/src/main/java/xonin/backhand/coremod/transformers/EntityOtherPlayerMPTransformer.java b/src/main/java/xonin/backhand/coremod/transformers/EntityOtherPlayerMPTransformer.java deleted file mode 100644 index e547951..0000000 --- a/src/main/java/xonin/backhand/coremod/transformers/EntityOtherPlayerMPTransformer.java +++ /dev/null @@ -1,120 +0,0 @@ -package xonin.backhand.coremod.transformers; - -import java.util.Iterator; -import java.util.List; - -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.FieldInsnNode; -import org.objectweb.asm.tree.FieldNode; -import org.objectweb.asm.tree.InsnList; -import org.objectweb.asm.tree.InsnNode; -import org.objectweb.asm.tree.MethodInsnNode; -import org.objectweb.asm.tree.MethodNode; -import org.objectweb.asm.tree.VarInsnNode; - -import xonin.backhand.api.core.BackhandTranslator; - -public final class EntityOtherPlayerMPTransformer extends TransformerBase { - - public EntityOtherPlayerMPTransformer() { - super("net.minecraft.client.entity.EntityOtherPlayerMP"); - } - - private String entityOtherPlayerMPClassName; - private String playerInventoryFieldName; - private String onUpdateMethodName; - private String setCurrentItemMethodName; - private String setCurrentItemMethodDesc; - private String isItemInUseFieldName; - private String limbSwingFieldName; - - private void processOnUpdateMethod2(MethodNode mn) { - - sendPatchLog("onUpdate"); - InsnList newList = new InsnList(); - - Iterator it = mn.instructions.iterator(); - - boolean done = false; - while (it.hasNext() && !done) { - AbstractInsnNode node = it.next(); - if (node instanceof FieldInsnNode && node.getOpcode() == PUTFIELD - && ((FieldInsnNode) node).owner.equals(entityOtherPlayerMPClassName) - && (((FieldInsnNode) node).name.equals(limbSwingFieldName.split("!")[0]) - || ((FieldInsnNode) node).name.equals(limbSwingFieldName.split("!")[1]))) { - newList.add(node); - newList.add(new VarInsnNode(ALOAD, 0)); - newList.add(new VarInsnNode(ALOAD, 0)); - newList.add(new VarInsnNode(ALOAD, 0)); - - newList.add(new FieldInsnNode(GETFIELD, entityOtherPlayerMPClassName, isItemInUseFieldName, "Z")); - newList.add( - new MethodInsnNode( - INVOKESTATIC, - "xonin/backhand/client/utils/BackhandClientUtils", - "entityOtherPlayerIsItemInUseHook", - "(L" + entityOtherPlayerMPClassName + ";Z)Z")); - newList.add(new FieldInsnNode(PUTFIELD, entityOtherPlayerMPClassName, isItemInUseFieldName, "Z")); - - node = it.next(); - while (!(node instanceof InsnNode && node.getOpcode() == RETURN)) { - node = it.next(); - } - newList.add(node); - while (it.hasNext()) { - node = it.next(); - newList.add(node); - } - - done = true; - } else { - newList.add(node); - } - - } - mn.instructions = newList; - } - - private void processSetCurrentItemMethod(MethodNode mn) { - sendPatchLog("setCurrentItem"); - replaceInventoryArrayAccess(mn, entityOtherPlayerMPClassName, playerInventoryFieldName, 4, 3, 3); - } - - @Override - boolean processMethods(List methods) { - int found = 0; - for (MethodNode mn : methods) { - if ((mn.name.equals(setCurrentItemMethodName.split("!")[0]) - || mn.name.equals(setCurrentItemMethodName.split("!")[1])) - && mn.desc.equals(setCurrentItemMethodDesc)) { - processSetCurrentItemMethod(mn); - found++; - } - - if ((mn.name.equals(onUpdateMethodName.split("!")[0]) || mn.name.equals(onUpdateMethodName.split("!")[1])) - && mn.desc.equals(SIMPLEST_METHOD_DESC)) { - processOnUpdateMethod2(mn); - found++; - } - } - return found == 2; - } - - @Override - boolean processFields(List fields) { - return true; - } - - @Override - void setupMappings() { - String itemStackClassName = BackhandTranslator.getMapedClassName("item.ItemStack"); - entityOtherPlayerMPClassName = BackhandTranslator.getMapedClassName("client.entity.EntityOtherPlayerMP"); - - isItemInUseFieldName = BackhandTranslator.getMapedFieldName("field_71186_a", "isItemInUse"); - limbSwingFieldName = "field_70754_ba!limbSwing"; - playerInventoryFieldName = "field_71071_by!inventory"; - setCurrentItemMethodName = "func_70062_b!setCurrentItemOrArmor"; - setCurrentItemMethodDesc = "(IL" + itemStackClassName + ";)V"; - onUpdateMethodName = "func_70071_h_!onUpdate"; - } -} diff --git a/src/main/java/xonin/backhand/coremod/transformers/EntityPlayerTransformer.java b/src/main/java/xonin/backhand/coremod/transformers/EntityPlayerTransformer.java deleted file mode 100644 index 64a07dd..0000000 --- a/src/main/java/xonin/backhand/coremod/transformers/EntityPlayerTransformer.java +++ /dev/null @@ -1,424 +0,0 @@ -package xonin.backhand.coremod.transformers; - -import java.util.List; -import java.util.ListIterator; - -import net.tclproject.mysteriumlib.asm.common.CustomLoadingPlugin; - -import org.apache.logging.log4j.Level; -import org.objectweb.asm.Label; -import org.objectweb.asm.Type; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.FieldInsnNode; -import org.objectweb.asm.tree.FieldNode; -import org.objectweb.asm.tree.InsnList; -import org.objectweb.asm.tree.MethodInsnNode; -import org.objectweb.asm.tree.MethodNode; -import org.objectweb.asm.tree.TypeInsnNode; -import org.objectweb.asm.tree.VarInsnNode; - -import xonin.backhand.api.core.BackhandTranslator; -import xonin.backhand.api.core.IBackhandPlayer; - -public final class EntityPlayerTransformer extends TransformerBase { - - public EntityPlayerTransformer() { - super("net.minecraft.entity.player.EntityPlayer"); - } - - private String entityPlayerClassName; - private String inventoryClassName; - private String inventoryContainerClassName; - private String itemStackClassName; - private String entityClassName; - private String entityLivingClassName; - - private String playerInventoryFieldName; - private String playerItemInUseField; - private String swingProgressBooleanField; - private String swingProgressIntField; - private String swingProgressFloatField; - - private String onItemFinishMethodName; - private String setCurrentItemArmourMethodName; - private String setCurrentItemArmourMethodDesc; - private String onUpdateMethodName; - private String playerUpdateArmSwingMethodName; - private String getArmSwingEndMethodName; - - @Override - void addInterface(List interfaces) { - interfaces.add(Type.getInternalName(IBackhandPlayer.class)); - } - - @Override - boolean processFields(List fields) { - logger.log(Level.INFO, "\tAdding new fields to EntityPlayer"); - fields.add(fields.size(), new FieldNode(ACC_PUBLIC, "offHandSwingProgress", "F", null, 0F)); - fields.add(fields.size(), new FieldNode(ACC_PUBLIC, "prevOffHandSwingProgress", "F", null, 0F)); - fields.add(fields.size(), new FieldNode(ACC_PUBLIC, "offHandSwingProgressInt", "I", null, 0)); - fields.add(fields.size(), new FieldNode(ACC_PUBLIC, "isOffHandSwingInProgress", "Z", null, false)); - fields.add(fields.size(), new FieldNode(ACC_PUBLIC, "specialActionTimer", "I", null, 0)); - fields.add(fields.size(), new FieldNode(ACC_PUBLIC, "isShielding", "Z", null, false)); - return true; - } - - @Override - boolean processMethods(List methods) { - int found = 0; - for (MethodNode mn : methods) { - if (mn.name.equals("")) { - logger.log(Level.INFO, "\tPatching constructor in EntityPlayer"); - ListIterator it = mn.instructions.iterator(); - - while (it.hasNext()) { - AbstractInsnNode insn = it.next(); - if (insn instanceof TypeInsnNode) { - if (((TypeInsnNode) insn).desc.equals(inventoryClassName)) { - ((TypeInsnNode) insn).desc = "xonin/backhand/api/core/InventoryPlayerBackhand"; - } - } else if (insn instanceof MethodInsnNode) { - if (((MethodInsnNode) insn).owner.equals(inventoryClassName)) { - ((MethodInsnNode) insn).owner = "xonin/backhand/api/core/InventoryPlayerBackhand"; - } - } - } - found++; - } else if ((mn.name.equals(onItemFinishMethodName.split("!")[0]) - || mn.name.equals(onItemFinishMethodName.split("!")[1])) && mn.desc.equals(SIMPLEST_METHOD_DESC)) { - sendPatchLog("onItemUseFinish"); - InsnList newList = new InsnList(); - ListIterator it = mn.instructions.iterator(); - while (it.hasNext()) { - AbstractInsnNode next = it.next(); - if (next instanceof MethodInsnNode - && ((MethodInsnNode) next).owner.equals("net/minecraftforge/event/ForgeEventFactory")) { - found++; - logger.log(Level.INFO, "net/minecraftforge/event/ForgeEventFactory" + " EntityPlayer!!!"); - int index = ((MethodInsnNode) next).desc.indexOf(")"); - String newDesc = ((MethodInsnNode) next).desc.substring(0, index) + "I" - + ((MethodInsnNode) next).desc.substring(index); - newList.add(new VarInsnNode(ILOAD, 1)); - newList - .add(new MethodInsnNode(INVOKESTATIC, UTILITY_CLASS, "beforeFinishUseEvent", newDesc)); - } else { - newList.add(next); - } - } - mn.instructions = newList; - } else if ((mn.name.equals(onUpdateMethodName.split("!")[0]) - || mn.name.equals(onUpdateMethodName.split("!")[1])) && mn.desc.equals(SIMPLEST_METHOD_DESC)) { - sendPatchLog("onUpdate"); - InsnList newList = new InsnList(); - ListIterator it = mn.instructions.iterator(); - while (it.hasNext()) { - AbstractInsnNode next = it.next(); - if (next instanceof FieldInsnNode - && ((FieldInsnNode) next).owner.equals(entityPlayerClassName) - && (((FieldInsnNode) next).name.equals(playerInventoryFieldName.split("!")[0]) - || ((FieldInsnNode) next).name.equals(playerInventoryFieldName.split("!")[1]))) { - found++; - logger.log(Level.INFO, entityPlayerClassName + "EntityPlayer!!!"); - newList.add(new VarInsnNode(ALOAD, 0)); - newList.add( - new FieldInsnNode( - GETFIELD, - entityPlayerClassName, - playerItemInUseField, - "L" + itemStackClassName + ";")); - newList.add( - new MethodInsnNode( - INVOKESTATIC, - UTILITY_CLASS, - "getCurrentItemOnUpdate", - "(L" + entityPlayerClassName - + ";L" - + itemStackClassName - + ";)L" - + itemStackClassName - + ";")); - next = it.next(); - } else { - newList.add(next); - } - } - mn.instructions = newList; - } else if ((mn.name.equals(setCurrentItemArmourMethodName.split("!")[0]) - || mn.name.equals(setCurrentItemArmourMethodName.split("!")[1])) - && mn.desc.equals(setCurrentItemArmourMethodDesc)) { - - sendPatchLog("setCurrentItemOrArmor"); - replaceInventoryArrayAccess( - mn, - entityPlayerClassName, - playerInventoryFieldName, - mn.maxStack, - mn.maxLocals); - found++; - } - } - - logger.log(Level.INFO, "\tCreating new methods in EntityPlayer"); - methods.add(methods.size(), generateAttackOffhandMethod()); - methods.add(methods.size(), generateSwingOffhand()); - methods.add(methods.size(), generateGetOffSwingMethod()); - methods.add(methods.size(), generateUpdateSwingArm()); - return found == 4; - } - - private MethodNode generateAttackOffhandMethod() { - - MethodNode mv = new MethodNode( - ACC_PUBLIC, - "attackTargetEntityWithCurrentOffItem", - "(L" + entityClassName + ";)V", - null, - null); - mv.visitCode(); - Label l0 = new Label(); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, 0); - mv.visitVarInsn(ALOAD, 1); - mv.visitMethodInsn( - INVOKESTATIC, - UTILITY_CLASS, - "attackTargetEntityWithCurrentOffItem", - "(L" + entityPlayerClassName + ";L" + entityClassName + ";)V"); - Label l1 = new Label(); - mv.visitLabel(l1); - mv.visitInsn(RETURN); - Label l2 = new Label(); - mv.visitLabel(l2); - mv.visitLocalVariable("this", "L" + entityPlayerClassName + ";", null, l0, l2, 0); - mv.visitLocalVariable("target", "L" + entityClassName + ";", null, l0, l2, 1); - mv.visitMaxs(2, 2); - mv.visitEnd(); - - return mv; - } - - private MethodNode generateSwingOffhand() { - MethodNode mv = new MethodNode(ACC_PUBLIC, "swingOffItem", SIMPLEST_METHOD_DESC, null, null); - mv.visitCode(); - Label l0 = new Label(); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, entityPlayerClassName, "isOffHandSwingInProgress", "Z"); - Label l1 = new Label(); - mv.visitJumpInsn(IFEQ, l1); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, entityPlayerClassName, "offHandSwingProgressInt", "I"); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKEVIRTUAL, entityPlayerClassName, getArmSwingEndMethodName, "()I"); - mv.visitInsn(ICONST_2); - mv.visitInsn(IDIV); - mv.visitJumpInsn(IF_ICMPGE, l1); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, entityPlayerClassName, "offHandSwingProgressInt", "I"); - Label l2 = new Label(); - mv.visitJumpInsn(IFGE, l2); - mv.visitLabel(l1); - mv.visitFrame(F_SAME, 0, null, 0, null); - mv.visitVarInsn(ALOAD, 0); - mv.visitInsn(ICONST_M1); - mv.visitFieldInsn(PUTFIELD, entityPlayerClassName, "offHandSwingProgressInt", "I"); - Label l3 = new Label(); - mv.visitLabel(l3); - mv.visitVarInsn(ALOAD, 0); - mv.visitInsn(ICONST_1); - mv.visitFieldInsn(PUTFIELD, entityPlayerClassName, "isOffHandSwingInProgress", "Z"); - mv.visitLabel(l2); - mv.visitFrame(F_SAME, 0, null, 0, null); - mv.visitInsn(RETURN); - Label l4 = new Label(); - mv.visitLabel(l4); - mv.visitLocalVariable("this", "L" + entityPlayerClassName + ";", null, l0, l4, 0); - mv.visitMaxs(3, 1); - mv.visitEnd(); - - return mv; - } - - private MethodNode generateGetOffSwingMethod() { - - MethodNode mv = new MethodNode(ACC_PUBLIC, "getOffSwingProgress", "(F)F", null, null); - mv.visitCode(); - Label l0 = new Label(); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, entityPlayerClassName, "offHandSwingProgress", "F"); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, entityPlayerClassName, "prevOffHandSwingProgress", "F"); - mv.visitInsn(FSUB); - mv.visitVarInsn(FSTORE, 2); - Label l1 = new Label(); - mv.visitLabel(l1); - mv.visitVarInsn(FLOAD, 2); - mv.visitInsn(FCONST_0); - mv.visitInsn(FCMPG); - Label l2 = new Label(); - mv.visitJumpInsn(IFGE, l2); - Label l3 = new Label(); - mv.visitLabel(l3); - mv.visitVarInsn(FLOAD, 2); - mv.visitInsn(FCONST_1); - mv.visitInsn(FADD); - mv.visitVarInsn(FSTORE, 2); - mv.visitLabel(l2); - mv.visitFrame(F_APPEND, 1, new Object[] { FLOAT }, 0, null); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, entityPlayerClassName, "prevOffHandSwingProgress", "F"); - mv.visitVarInsn(FLOAD, 2); - mv.visitVarInsn(FLOAD, 1); - mv.visitInsn(FMUL); - mv.visitInsn(FADD); - mv.visitInsn(FRETURN); - Label l4 = new Label(); - mv.visitLabel(l4); - mv.visitLocalVariable("this", "L" + entityPlayerClassName + ";", null, l0, l4, 0); - mv.visitLocalVariable("frame", "F", null, l0, l4, 1); - mv.visitLocalVariable("diff", "F", null, l1, l4, 2); - mv.visitMaxs(3, 3); - mv.visitEnd(); - - return mv; - } - - private MethodNode generateUpdateSwingArm() { - - MethodNode mv = new MethodNode(ACC_PROTECTED, playerUpdateArmSwingMethodName, SIMPLEST_METHOD_DESC, null, null); - mv.visitCode(); - Label l0 = new Label(); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, entityLivingClassName, playerUpdateArmSwingMethodName, SIMPLEST_METHOD_DESC); - Label l1 = new Label(); - mv.visitLabel(l1); - mv.visitVarInsn(ALOAD, 0); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, entityPlayerClassName, "offHandSwingProgress", "F"); - mv.visitFieldInsn(PUTFIELD, entityPlayerClassName, "prevOffHandSwingProgress", "F"); - Label l2 = new Label(); - mv.visitLabel(l2); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKEVIRTUAL, entityPlayerClassName, getArmSwingEndMethodName, "()I"); - mv.visitVarInsn(ISTORE, 1); - Label l3 = new Label(); - mv.visitLabel(l3); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, entityPlayerClassName, "isOffHandSwingInProgress", "Z"); - Label l4 = new Label(); - mv.visitJumpInsn(IFEQ, l4); - Label l5 = new Label(); - mv.visitLabel(l5); - mv.visitVarInsn(ALOAD, 0); - mv.visitInsn(DUP); - mv.visitFieldInsn(GETFIELD, entityPlayerClassName, "offHandSwingProgressInt", "I"); - mv.visitInsn(ICONST_1); - mv.visitInsn(IADD); - mv.visitFieldInsn(PUTFIELD, entityPlayerClassName, "offHandSwingProgressInt", "I"); - Label l6 = new Label(); - mv.visitLabel(l6); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, entityPlayerClassName, "offHandSwingProgressInt", "I"); - mv.visitVarInsn(ILOAD, 1); - Label l7 = new Label(); - mv.visitJumpInsn(IF_ICMPLT, l7); - Label l8 = new Label(); - mv.visitLabel(l8); - mv.visitVarInsn(ALOAD, 0); - mv.visitInsn(ICONST_0); - mv.visitFieldInsn(PUTFIELD, entityPlayerClassName, "offHandSwingProgressInt", "I"); - Label l9 = new Label(); - mv.visitLabel(l9); - mv.visitVarInsn(ALOAD, 0); - mv.visitInsn(ICONST_0); - mv.visitFieldInsn(PUTFIELD, entityPlayerClassName, "isOffHandSwingInProgress", "Z"); - mv.visitJumpInsn(GOTO, l7); - mv.visitLabel(l4); - mv.visitFrame(F_APPEND, 1, new Object[] { INTEGER }, 0, null); - mv.visitVarInsn(ALOAD, 0); - mv.visitInsn(ICONST_0); - mv.visitFieldInsn(PUTFIELD, entityPlayerClassName, "offHandSwingProgressInt", "I"); - mv.visitLabel(l7); - mv.visitFrame(F_SAME, 0, null, 0, null); - mv.visitVarInsn(ALOAD, 0); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, entityPlayerClassName, "offHandSwingProgressInt", "I"); - mv.visitInsn(I2F); - mv.visitVarInsn(ILOAD, 1); - mv.visitInsn(I2F); - mv.visitInsn(FDIV); - mv.visitFieldInsn(PUTFIELD, entityPlayerClassName, "offHandSwingProgress", "F"); - Label l10 = new Label(); - mv.visitLabel(l10); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, entityPlayerClassName, "specialActionTimer", "I"); - Label l11 = new Label(); - mv.visitJumpInsn(IFLE, l11); - Label l12 = new Label(); - mv.visitLabel(l12); - mv.visitVarInsn(ALOAD, 0); - mv.visitInsn(ICONST_0); - mv.visitFieldInsn(PUTFIELD, entityPlayerClassName, "isOffHandSwingInProgress", "Z"); - Label l13 = new Label(); - mv.visitLabel(l13); - mv.visitVarInsn(ALOAD, 0); - mv.visitInsn(ICONST_0); - mv.visitFieldInsn(PUTFIELD, entityPlayerClassName, swingProgressBooleanField, "Z"); - Label l14 = new Label(); - mv.visitLabel(l14); - mv.visitVarInsn(ALOAD, 0); - mv.visitInsn(FCONST_0); - mv.visitFieldInsn(PUTFIELD, entityPlayerClassName, "offHandSwingProgress", "F"); - Label l15 = new Label(); - mv.visitLabel(l15); - mv.visitVarInsn(ALOAD, 0); - mv.visitInsn(ICONST_0); - mv.visitFieldInsn(PUTFIELD, entityPlayerClassName, "offHandSwingProgressInt", "I"); - Label l16 = new Label(); - mv.visitLabel(l16); - mv.visitVarInsn(ALOAD, 0); - mv.visitInsn(FCONST_0); - mv.visitFieldInsn(PUTFIELD, entityPlayerClassName, swingProgressFloatField, "F"); - Label l17 = new Label(); - mv.visitLabel(l17); - mv.visitVarInsn(ALOAD, 0); - mv.visitInsn(ICONST_0); - mv.visitFieldInsn(PUTFIELD, entityPlayerClassName, swingProgressIntField, "I"); - mv.visitLabel(l11); - mv.visitFrame(F_SAME, 0, null, 0, null); - mv.visitInsn(RETURN); - Label l18 = new Label(); - mv.visitLabel(l18); - mv.visitLocalVariable("this", "L" + entityPlayerClassName + ";", null, l0, l18, 0); - mv.visitLocalVariable("var1", "I", null, l3, l18, 1); - mv.visitMaxs(3, 2); - mv.visitEnd(); - - return mv; - } - - @Override - void setupMappings() { - entityPlayerClassName = BackhandTranslator.getMapedClassName("entity.player.EntityPlayer"); - inventoryClassName = BackhandTranslator.getMapedClassName("entity.player.InventoryPlayer"); - inventoryContainerClassName = BackhandTranslator.getMapedClassName("inventory.ContainerPlayer"); - itemStackClassName = BackhandTranslator.getMapedClassName("item.ItemStack"); - entityClassName = BackhandTranslator.getMapedClassName("entity.Entity"); - entityLivingClassName = BackhandTranslator.getMapedClassName("entity.EntityLivingBase"); - - playerInventoryFieldName = "field_71071_by!inventory"; - playerItemInUseField = BackhandTranslator.getMapedFieldName("field_71074_e", "itemInUse"); - swingProgressBooleanField = BackhandTranslator.getMapedFieldName("field_82175_bq", "isSwingInProgress"); - swingProgressIntField = BackhandTranslator.getMapedFieldName("field_110158_av", "swingProgressInt"); - swingProgressFloatField = BackhandTranslator.getMapedFieldName("field_70733_aJ", "swingProgress"); - onItemFinishMethodName = "func_71036_o!onItemUseFinish"; - setCurrentItemArmourMethodName = "func_70062_b!setCurrentItemOrArmor"; - setCurrentItemArmourMethodDesc = "(IL" + itemStackClassName + ";)V"; - onUpdateMethodName = "func_70071_h_!onUpdate"; - playerUpdateArmSwingMethodName = CustomLoadingPlugin.isObfuscated() ? "func_82168_bl" - : "updateArmSwingProgress"; - getArmSwingEndMethodName = CustomLoadingPlugin.isObfuscated() ? "func_82166_i" : "getArmSwingAnimationEnd"; - } -} diff --git a/src/main/java/xonin/backhand/coremod/transformers/ItemInWorldTransformer.java b/src/main/java/xonin/backhand/coremod/transformers/ItemInWorldTransformer.java deleted file mode 100644 index 9e12bea..0000000 --- a/src/main/java/xonin/backhand/coremod/transformers/ItemInWorldTransformer.java +++ /dev/null @@ -1,79 +0,0 @@ -package xonin.backhand.coremod.transformers; - -import java.util.Iterator; - -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.FieldInsnNode; -import org.objectweb.asm.tree.InsnList; -import org.objectweb.asm.tree.MethodInsnNode; -import org.objectweb.asm.tree.MethodNode; - -import xonin.backhand.api.core.BackhandTranslator; - -public final class ItemInWorldTransformer extends TransformerMethodProcess { - - public ItemInWorldTransformer() { - super( - "net.minecraft.server.management.ItemInWorldManager", - "func_73085_a", - new String[] { "tryUseItem", - "(Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/world/World;Lnet/minecraft/item/ItemStack;)Z" }); - } - - private String entityPlayerClassName; - private String inventoryPlayerClassName; - private String itemStackClassName; - - private String playerInventoryFieldName; - private String mainInventoryArrayFieldName; - - private String setInventorySlotMethodName; - private String setInventorySlotMethodDesc; - - @Override - void processMethod(MethodNode mn) { - sendPatchLog("tryUseItem"); - replaceInventoryArrayAccess(mn, entityPlayerClassName, playerInventoryFieldName, 5, 7); - - InsnList newList = new InsnList(); - - Iterator it = mn.instructions.iterator(); - - while (it.hasNext()) { - AbstractInsnNode node = it.next(); - - if (node instanceof FieldInsnNode && ((FieldInsnNode) node).owner.equals(inventoryPlayerClassName) - && (((FieldInsnNode) node).name.equals(mainInventoryArrayFieldName.split("!")[0]) - || ((FieldInsnNode) node).name.equals(mainInventoryArrayFieldName.split("!")[1])) - && ((FieldInsnNode) node).desc.equals("[L" + itemStackClassName + ";")) { - - // Do Nothing - } else if (node.getOpcode() == AASTORE) { - newList.add( - new MethodInsnNode( - INVOKEVIRTUAL, - inventoryPlayerClassName, - setInventorySlotMethodName, - setInventorySlotMethodDesc)); - } else { - newList.add(node); - } - } - - mn.instructions = newList; - } - - @Override - void setupMappings() { - super.setupMappings(); - entityPlayerClassName = BackhandTranslator.getMapedClassName("entity.player.EntityPlayer"); - inventoryPlayerClassName = BackhandTranslator.getMapedClassName("entity.player.InventoryPlayer"); - itemStackClassName = BackhandTranslator.getMapedClassName("item.ItemStack"); - - playerInventoryFieldName = "field_71071_by!inventory"; - mainInventoryArrayFieldName = "field_70462_a!mainInventory"; - setInventorySlotMethodName = BackhandTranslator.getMapedMethodName("func_70299_a", "setInventorySlotContents"); - setInventorySlotMethodDesc = "(IL" + itemStackClassName + ";)V"; - } - -} diff --git a/src/main/java/xonin/backhand/coremod/transformers/NetClientHandlerTransformer.java b/src/main/java/xonin/backhand/coremod/transformers/NetClientHandlerTransformer.java deleted file mode 100644 index 215f92f..0000000 --- a/src/main/java/xonin/backhand/coremod/transformers/NetClientHandlerTransformer.java +++ /dev/null @@ -1,78 +0,0 @@ -package xonin.backhand.coremod.transformers; - -import java.util.List; -import java.util.ListIterator; - -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.FieldNode; -import org.objectweb.asm.tree.InsnList; -import org.objectweb.asm.tree.JumpInsnNode; -import org.objectweb.asm.tree.LabelNode; -import org.objectweb.asm.tree.MethodInsnNode; -import org.objectweb.asm.tree.MethodNode; - -public final class NetClientHandlerTransformer extends TransformerBase { - - public NetClientHandlerTransformer() { - super("net.minecraft.client.network.NetHandlerPlayClient"); - } - - private String netClientHandlerHandleBlockItemSwitchMethodName; - private String netClientHandlerHandleBlockItemSwitchMethodDesc; - - @Override - boolean processMethods(List methods) { - int found = 0; - for (MethodNode method : methods) { - if ((method.name.equals(netClientHandlerHandleBlockItemSwitchMethodName.split("!")[0]) - || method.name.equals(netClientHandlerHandleBlockItemSwitchMethodName.split("!")[1])) - && method.desc.equals(netClientHandlerHandleBlockItemSwitchMethodDesc)) { - sendPatchLog("handleHeldItemChange"); - - ListIterator insn = method.instructions.iterator(); - InsnList newList = new InsnList(); - - while (insn.hasNext()) { - - AbstractInsnNode nextNode = insn.next(); - - if (nextNode instanceof JumpInsnNode && nextNode.getOpcode() == IFLT) { - LabelNode label = ((JumpInsnNode) nextNode).label; - newList.add( - new MethodInsnNode( - INVOKESTATIC, - "xonin/backhand/api/core/InventoryPlayerBackhand", - "isValidSwitch", - "(I)Z")); - newList.add(new JumpInsnNode(IFEQ, label));// "if equal" branch - - found++; - nextNode = insn.next(); - while (insn.hasNext() && !(nextNode instanceof JumpInsnNode) - && nextNode.getOpcode() != IF_ICMPGE) { - nextNode = insn.next();// continue till "if int greater than or equal to" branch - } - - } else { - newList.add(nextNode); - } - - } - - method.instructions = newList; - } - } - return found == 1; - } - - @Override - boolean processFields(List fields) { - return true; - } - - @Override - void setupMappings() { - netClientHandlerHandleBlockItemSwitchMethodName = "func_147257_a!handleHeldItemChange"; - netClientHandlerHandleBlockItemSwitchMethodDesc = "(Lnet/minecraft/network/play/server/S09PacketHeldItemChange;)V"; - } -} diff --git a/src/main/java/xonin/backhand/coremod/transformers/PlayerControllerMPTransformer.java b/src/main/java/xonin/backhand/coremod/transformers/PlayerControllerMPTransformer.java deleted file mode 100644 index 6558dac..0000000 --- a/src/main/java/xonin/backhand/coremod/transformers/PlayerControllerMPTransformer.java +++ /dev/null @@ -1,34 +0,0 @@ -package xonin.backhand.coremod.transformers; - -import org.objectweb.asm.tree.MethodNode; - -import xonin.backhand.api.core.BackhandTranslator; - -public final class PlayerControllerMPTransformer extends TransformerMethodProcess { - - // Todo: This is converted and clashing with mixin but replaceInventoryArrayAccess is needed? - public PlayerControllerMPTransformer() { - super( - "net.minecraft.client.multiplayer.PlayerControllerMP", - "func_78769_a", - new String[] { "sendUseItem", - "(Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/world/World;Lnet/minecraft/item/ItemStack;)Z" }); - } - - private String entityPlayerClassName; - private String playerInventoryFieldName; - - @Override - void processMethod(MethodNode method) { - sendPatchLog("sendUseItem"); - replaceInventoryArrayAccess(method, entityPlayerClassName, playerInventoryFieldName, 11, 13); - } - - @Override - void setupMappings() { - super.setupMappings(); - entityPlayerClassName = BackhandTranslator.getMapedClassName("entity.player.EntityPlayer"); - playerInventoryFieldName = "field_71071_by!inventory"; - } - -} diff --git a/src/main/java/xonin/backhand/coremod/transformers/TransformerBase.java b/src/main/java/xonin/backhand/coremod/transformers/TransformerBase.java deleted file mode 100644 index 0d7f0aa..0000000 --- a/src/main/java/xonin/backhand/coremod/transformers/TransformerBase.java +++ /dev/null @@ -1,209 +0,0 @@ -package xonin.backhand.coremod.transformers; - -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.util.Iterator; -import java.util.List; - -import net.minecraft.launchwrapper.IClassTransformer; - -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.ClassNode; -import org.objectweb.asm.tree.FieldInsnNode; -import org.objectweb.asm.tree.FieldNode; -import org.objectweb.asm.tree.InsnList; -import org.objectweb.asm.tree.MethodInsnNode; -import org.objectweb.asm.tree.MethodNode; - -import xonin.backhand.api.core.BackhandTranslator; -import xonin.backhand.coremod.BackhandLoadingPlugin; - -public abstract class TransformerBase implements IClassTransformer, Opcodes { - - public static final String UTILITY_CLASS = "xonin/backhand/api/core/BackhandUtils"; - public static final String SIMPLEST_METHOD_DESC = "()V"; - public Logger logger = LogManager.getLogger("battlegear2"); - protected final String classPath; - protected final String unobfClass; - private boolean skipDebug; - - public TransformerBase(String classPath) { - this.classPath = classPath; - this.unobfClass = classPath.substring(classPath.lastIndexOf('.') + 1); - setDebug(false); - } - - protected final void setDebug(boolean debug) { - this.skipDebug = !debug; - } - - @Override - public byte[] transform(String name, String transformedName, byte[] bytes) { - if (transformedName.equals(classPath)) { - logger.log(Level.INFO, "M&B - Patching Class " + unobfClass + " (" + name + ")"); - - ClassReader cr = new ClassReader(bytes); - ClassNode cn = new ClassNode(); - - cr.accept(cn, skipDebug ? ClassReader.SKIP_DEBUG : 0); - - setupMappings(); - boolean success = processFields(cn.fields) && processMethods(cn.methods); - addInterface(cn.interfaces); - - ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); - cn.accept(cw); - - logger.log( - success ? Level.INFO : Level.ERROR, - "M&B - Patching Class " + unobfClass + (success ? " done" : " FAILED!")); - if (!success && BackhandTranslator.debug) { - writeClassFile(cw, unobfClass + " (" + name + ")"); - } - - return cw.toByteArray(); - - } - return bytes; - } - - void addInterface(List interfaces) {} - - abstract boolean processMethods(List methods); - - abstract boolean processFields(List fields); - - abstract void setupMappings(); - - public static void writeClassFile(ClassWriter cw, String name) { - try { - File outDir = BackhandLoadingPlugin.debugOutputLocation; - outDir.mkdirs(); - DataOutputStream dout = new DataOutputStream(new FileOutputStream(new File(outDir, name + ".class"))); - dout.write(cw.toByteArray()); - dout.flush(); - dout.close(); - - } catch (Exception e) { - e.printStackTrace(); - } - } - - public static MethodNode replaceInventoryArrayAccess(MethodNode method, String className, String fieldName, - int maxStack, int maxLocal) { - return replaceInventoryArrayAccess(method, className, fieldName, 4, maxStack, maxLocal); - } - - public static MethodNode replaceInventoryArrayAccess(MethodNode method, String className, String fieldName, - int todelete, int maxStack, int maxLocal) { - - InsnList newList = new InsnList(); - - Iterator it = method.instructions.iterator(); - - while (it.hasNext()) { - AbstractInsnNode nextNode = it.next(); - - if (nextNode instanceof FieldInsnNode && nextNode.getNext() instanceof FieldInsnNode - && ((FieldInsnNode) nextNode).owner.equals(className) - && (((FieldInsnNode) nextNode).name.equals(fieldName.split("!")[0]) - || ((FieldInsnNode) nextNode).name.equals(fieldName.split("!")[1])) - && ((FieldInsnNode) nextNode.getNext()).owner - .equals(BackhandTranslator.getMapedClassName("entity.player.InventoryPlayer")) - && (((FieldInsnNode) nextNode.getNext()).name.equals("field_70462_a") - || ((FieldInsnNode) nextNode.getNext()).name.equals("mainInventory"))) { - - // skip the next 4 - for (int i = 0; i < todelete; i++) { - nextNode = it.next(); - } - // add all until the AAStore - nextNode = it.next(); - while (it.hasNext() && nextNode.getOpcode() != AASTORE) { - newList.add(nextNode); - nextNode = it.next(); - } - - // Add New - newList.add( - new MethodInsnNode( - INVOKESTATIC, - UTILITY_CLASS, - "setPlayerCurrentItem", - "(L" + BackhandTranslator.getMapedClassName("entity.player.EntityPlayer") - + ";L" - + BackhandTranslator.getMapedClassName("item.ItemStack") - + ";)V")); - - } else { - newList.add(nextNode); - } - } - - method.instructions = newList; - - method.maxStack = maxStack; - method.maxLocals = maxLocal; - - return method; - - } - - public void sendPatchLog(String method) { - logger.log(Level.INFO, "\tPatching method " + method + " in " + unobfClass); - } - - public static MethodNode generateSetter(String className, String methodName, String fieldName, String fieldType) { - MethodNode mn = new MethodNode(ACC_PUBLIC, methodName, "(" + fieldType + ")V", null, null); - mn.visitCode(); - mn.visitVarInsn(ALOAD, 0); - int opCode; - if (fieldType.equals("I") || fieldType.equals("Z")) { - opCode = ILOAD; - } else if (fieldType.equals("L")) { - opCode = LLOAD; - } else if (fieldType.equals("F")) { - opCode = FLOAD; - } else if (fieldType.equals("D")) { - opCode = DLOAD; - } else { - opCode = ALOAD; - } - mn.visitVarInsn(opCode, 1); - mn.visitFieldInsn(PUTFIELD, className, fieldName, fieldType); - mn.visitInsn(RETURN); - mn.visitMaxs(2, 2); - mn.visitEnd(); - return mn; - } - - public static MethodNode generateGetter(String className, String methodName, String fieldName, String fieldType) { - MethodNode mn = new MethodNode(ACC_PUBLIC, methodName, "()" + fieldType, null, null); - mn.visitCode(); - mn.visitVarInsn(ALOAD, 0); - mn.visitFieldInsn(GETFIELD, className, fieldName, fieldType); - int opCode; - if (fieldType.equals("I") || fieldType.equals("Z")) { - opCode = IRETURN; - } else if (fieldType.equals("L")) { - opCode = LRETURN; - } else if (fieldType.equals("F")) { - opCode = FRETURN; - } else if (fieldType.equals("D")) { - opCode = DRETURN; - } else { - opCode = ARETURN; - } - mn.visitInsn(opCode); - mn.visitMaxs(1, 1); - mn.visitEnd(); - return mn; - } -} diff --git a/src/main/java/xonin/backhand/coremod/transformers/TransformerMethodProcess.java b/src/main/java/xonin/backhand/coremod/transformers/TransformerMethodProcess.java deleted file mode 100644 index dd8238f..0000000 --- a/src/main/java/xonin/backhand/coremod/transformers/TransformerMethodProcess.java +++ /dev/null @@ -1,46 +0,0 @@ -package xonin.backhand.coremod.transformers; - -import java.util.List; - -import org.objectweb.asm.tree.FieldNode; -import org.objectweb.asm.tree.MethodNode; - -public abstract class TransformerMethodProcess extends TransformerBase { - - private final String meth; - private final String devName; - private final String desc; - private String methName; - - public TransformerMethodProcess(String classPath, String method, String[] devs) { - super(classPath); - this.meth = method; - this.devName = devs[0]; - this.desc = devs[1]; - } - - @Override - boolean processMethods(List methods) { - for (MethodNode method : methods) { - if ((method.name.equals(methName.split("!")[0]) || method.name.equals(methName.split("!")[1])) - && method.desc.equals(desc)) { - processMethod(method); - return true; - } - } - return false; - } - - abstract void processMethod(MethodNode method); - - @Override - boolean processFields(List fields) { - return true; - } - - @Override - void setupMappings() { - methName = meth + "!" + devName; - } - -} diff --git a/src/main/java/xonin/backhand/mixins/early/MixinEntityOtherPlayerMP.java b/src/main/java/xonin/backhand/mixins/early/MixinEntityOtherPlayerMP.java index 7dc4fa8..ac499e7 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinEntityOtherPlayerMP.java +++ b/src/main/java/xonin/backhand/mixins/early/MixinEntityOtherPlayerMP.java @@ -2,13 +2,19 @@ import net.minecraft.client.entity.AbstractClientPlayer; import net.minecraft.client.entity.EntityOtherPlayerMP; +import net.minecraft.item.ItemStack; import net.minecraft.world.World; 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; import com.mojang.authlib.GameProfile; +import xonin.backhand.api.core.BackhandUtils; + @Mixin(EntityOtherPlayerMP.class) public abstract class MixinEntityOtherPlayerMP extends AbstractClientPlayer { @@ -19,30 +25,25 @@ private MixinEntityOtherPlayerMP(World p_i45074_1_, GameProfile p_i45074_2_) { super(p_i45074_1_, p_i45074_2_); } - // @Inject( - // method = "onUpdate", - // cancellable = true, - // at = @At( - // value = "FIELD", - // target = "Lnet/minecraft/client/entity/EntityOtherPlayerMP;isItemInUse:Z", - // shift = At.Shift.BEFORE, - // ordinal = 0)) - // private void battlegear2$isItemInUseHook(CallbackInfo ci) { - // if (BattlegearUtils.isPlayerInBattlemode(this)) { - // ci.cancel(); - // ItemStack itemStack = this.getCurrentEquippedItem(); - // ItemStack offhand = ((IInventoryPlayerBattle) this.inventory).battlegear2$getCurrentOffhandWeapon(); - // if (offhand != null && BattlegearUtils.usagePriorAttack(offhand, this, true)) { - // itemStack = offhand; - // } - // if (!this.isItemInUse && this.isEating() && itemStack != null) { - // this.setItemInUse(itemStack, itemStack.getMaxItemUseDuration()); - // this.isItemInUse = true; - // } else if (this.isItemInUse && !this.isEating()) { - // this.clearItemInUse(); - // this.isItemInUse = false; - // } - // } - // } + @Inject( + method = "onUpdate", + cancellable = true, + at = @At( + value = "FIELD", + target = "Lnet/minecraft/client/entity/EntityOtherPlayerMP;isItemInUse:Z", + ordinal = 0)) + private void backhand$isItemInUseHook(CallbackInfo ci) { + ItemStack itemStack = getCurrentEquippedItem(); + ItemStack offhand = BackhandUtils.getOffhandItem(this); + if (BackhandUtils.usagePriorAttack(offhand)) itemStack = offhand; + if (!isItemInUse && isEating() && itemStack != null) { + setItemInUse(itemStack, itemStack.getMaxItemUseDuration()); + isItemInUse = true; + } else if (isItemInUse && !isEating()) { + clearItemInUse(); + isItemInUse = false; + } + ci.cancel(); + } } diff --git a/src/main/java/xonin/backhand/mixins/early/MixinEntityPlayer.java b/src/main/java/xonin/backhand/mixins/early/MixinEntityPlayer.java index 8739dab..d4e9e86 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinEntityPlayer.java +++ b/src/main/java/xonin/backhand/mixins/early/MixinEntityPlayer.java @@ -1,28 +1,24 @@ package xonin.backhand.mixins.early; -import net.minecraft.client.Minecraft; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; -import net.minecraft.item.ItemBow; +import net.minecraft.inventory.Container; import net.minecraft.item.ItemStack; -import net.minecraft.util.IIcon; import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; 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.callback.CallbackInfoReturnable; import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.injector.ModifyReturnValue; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; +import xonin.backhand.api.core.BackhandUtils; import xonin.backhand.api.core.IBackhandPlayer; -import xonin.backhand.client.utils.BackhandClientUtils; +import xonin.backhand.api.core.InventoryPlayerBackhand; @Mixin(EntityPlayer.class) public abstract class MixinEntityPlayer extends EntityLivingBase implements IBackhandPlayer { @@ -30,7 +26,11 @@ public abstract class MixinEntityPlayer extends EntityLivingBase implements IBac @Shadow private ItemStack itemInUse; @Shadow - public InventoryPlayer inventory; + private int itemInUseCount; + @Shadow + public InventoryPlayer inventory = new InventoryPlayerBackhand((EntityPlayer) (Object) this); + @Shadow + public Container inventoryContainer; @Unique private float backhand$offHandSwingProgress = 0F; @Unique @@ -41,167 +41,109 @@ public abstract class MixinEntityPlayer extends EntityLivingBase implements IBac private boolean backhand$isOffHandSwingInProgress = false; @Unique private int backhand$specialActionTimer = 0; - @Unique - private boolean backhand$isShielding = false; private MixinEntityPlayer(World p_i1594_1_) { super(p_i1594_1_); } - @Unique - private int backhand$local$onItemFinish$i; + // TODO: Why are we doing this? + @ModifyReturnValue(method = "isPlayer", at = @At(value = "RETURN")) + private boolean backhand$isPlayer(boolean original) { + return false; + } + + // //TODO: InventoryPlayerBackhand doesn't override setInventorySlotContents so is this even needed? + // @ModifyExpressionValue( + // method = "setCurrentItemOrArmor", + // at = @At( + // value = "FIELD", + // opcode = Opcodes.GETFIELD, + // target = "Lnet/minecraft/entity/player/InventoryPlayer;mainInventory:[Lnet/minecraft/item/ItemStack;")) + // private ItemStack[] backhand$setCurrentItemOrArmor(ItemStack[] original, @Local(argsOnly = true) ItemStack stack) + // { + // BackhandUtils.setPlayerCurrentItem((EntityPlayer) (Object) this, stack); + // return new ItemStack[inventory.mainInventory.length]; + // } @ModifyExpressionValue( method = "onItemUseFinish", - at = @At(value = "FIELD", target = "Lnet/minecraft/item/ItemStack;stackSize:I", ordinal = 0)) - private int backhand$captureLocal$onItemFinish(int i) { - this.backhand$local$onItemFinish$i = i; - return i; + at = @At( + value = "INVOKE", + target = "Lnet/minecraftforge/event/ForgeEventFactory;onItemUseFinish(Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/item/ItemStack;ILnet/minecraft/item/ItemStack;)Lnet/minecraft/item/ItemStack;", + remap = false)) + private ItemStack backhand$onItemUseFinish$beforeFinishUse(ItemStack itemStack) { + return BackhandUtils.beforeFinishUseEvent( + (EntityPlayer) (Object) this, + this.itemInUse, + this.itemInUseCount, + itemStack, + this.itemInUse.stackSize); } - // TODO: move client side stuff to a different class - @SideOnly(Side.CLIENT) - @Inject(method = "getItemIcon", at = @At(value = "HEAD")) - private void backhand2$getItemIcon(ItemStack itemStackIn, int p_70620_2_, CallbackInfoReturnable cir) { - if (worldObj.isRemote) { - EntityPlayer player = Minecraft.getMinecraft().thePlayer; - if (itemStackIn == player.getCurrentEquippedItem() && player.getCurrentEquippedItem() != null - && player.getItemInUse() != null - && player.getCurrentEquippedItem() - .getItem() instanceof ItemBow - && player.getCurrentEquippedItem() != player.getItemInUse()) { - BackhandClientUtils.disableMainhandAnimation = true; - } + @ModifyExpressionValue( + method = "onUpdate", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/entity/player/InventoryPlayer;getCurrentItem()Lnet/minecraft/item/ItemStack;")) + private ItemStack backhand$onUpdate$getCurrentItem(ItemStack original) { + ItemStack itemStack = BackhandUtils.getOffhandItem((EntityPlayer) (Object) this); + if (itemInUse == itemStack) { + return itemStack; } + + return original; } - @SideOnly(Side.CLIENT) @Override - public float getSwingProgress(float partialTicks) { - if (BackhandClientUtils.offhandFPRender) { - return getOffSwingProgress(partialTicks); + public void attackTargetEntityWithCurrentOffItem(Entity target) { + BackhandUtils.attackTargetEntityWithCurrentOffItem((EntityPlayer) (Object) this, target); + } + + @Override + public void swingOffItem() { + if (!this.backhand$isOffHandSwingInProgress + || this.backhand$offHandSwingProgressInt >= this.getArmSwingAnimationEnd() / 2 + || this.backhand$offHandSwingProgressInt < 0) { + this.backhand$offHandSwingProgressInt = -1; + this.backhand$isOffHandSwingInProgress = true; } - return super.getSwingProgress(partialTicks); + } - // TODO: Why are we doing this? - @ModifyReturnValue(method = "isPlayer", at = @At(value = "RETURN")) - private boolean backhand$isPlayer(boolean original) { - return false; + @Override + public float getOffSwingProgress(float frame) { + float diff = this.backhand$offHandSwingProgress - this.backhand$prevOffHandSwingProgress; + if (diff < 0.0F) { + ++diff; + } + + return this.backhand$prevOffHandSwingProgress + diff * frame; } - // @ModifyExpressionValue( - // method = "onItemUseFinish", - // at = @At( - // value = "INVOKE", - // target = - // "Lnet/minecraftforge/event/ForgeEventFactory;onItemUseFinish(Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/item/ItemStack;ILnet/minecraft/item/ItemStack;)Lnet/minecraft/item/ItemStack;", - // remap = false)) - // private ItemStack backhand$onItemUseFinish$beforeFinishUse(ItemStack itemStack) { - // return BattlegearUtils.beforeFinishUseEvent( - // (EntityPlayer) (Object) this, - // this.itemInUse, - // itemStack, - // this.backhand$local$onItemFinish$i); - // } - // - // @ModifyExpressionValue( - // method = "onUpdate", - // at = @At( - // value = "INVOKE", - // target = "Lnet/minecraft/entity/player/InventoryPlayer;getCurrentItem()Lnet/minecraft/item/ItemStack;")) - // private ItemStack backhand$onUpdate$getCurrentItem(ItemStack currentItemStack) { - // if (BattlegearUtils.isPlayerInBattlemode((EntityPlayer) (Object) this)) { - // ItemStack itemStack = ((IInventoryPlayerBattle) this.inventory).backhand$getCurrentOffhandWeapon(); - // if (itemInUse == itemStack) { - // return itemStack; - // } - // } - // return currentItemStack; - // } - // - // /** - // * @author Alexdoru - // * @reason IDK it's the original mod that does that - // */ - // @Overwrite - // public boolean interactWith(Entity var1) { - // return BattlegearUtils.interactWith((EntityPlayer) (Object) this, var1); - // } - // - // @Override - // protected void updateArmSwingProgress() { - // super.updateArmSwingProgress(); - // this.backhand$prevOffHandSwingProgress = this.backhand$offHandSwingProgress; - // int var1 = this.getArmSwingAnimationEnd(); - // if (this.backhand$isOffHandSwingInProgress) { - // ++this.backhand$offHandSwingProgressInt; - // if (this.backhand$offHandSwingProgressInt >= var1) { - // this.backhand$offHandSwingProgressInt = 0; - // this.backhand$isOffHandSwingInProgress = false; - // } - // } else { - // this.backhand$offHandSwingProgressInt = 0; - // } - // - // this.backhand$offHandSwingProgress = (float) this.backhand$offHandSwingProgressInt / (float) var1; - // if (this.backhand$specialActionTimer > 0) { - // this.backhand$isOffHandSwingInProgress = false; - // this.isSwingInProgress = false; - // this.backhand$offHandSwingProgress = 0.0F; - // this.backhand$offHandSwingProgressInt = 0; - // this.swingProgress = 0.0F; - // this.swingProgressInt = 0; - // } - // - // } - // - // @Override - // public void backhand$swingOffItem() { - // if (!this.backhand$isOffHandSwingInProgress - // || this.backhand$offHandSwingProgressInt >= this.getArmSwingAnimationEnd() / 2 - // || this.backhand$offHandSwingProgressInt < 0) { - // this.backhand$offHandSwingProgressInt = -1; - // this.backhand$isOffHandSwingInProgress = true; - // } - // } - // - // @Override - // public float backhand$getOffSwingProgress(float frame) { - // float diff = this.backhand$offHandSwingProgress - this.backhand$prevOffHandSwingProgress; - // if (diff < 0.0F) { - // ++diff; - // } - // return this.backhand$prevOffHandSwingProgress + diff * frame; - // } - // - // public void backhand$attackTargetEntityWithCurrentOffItem(Entity target) { - // BattlegearUtils.attackTargetEntityWithCurrentOffItem((EntityPlayer) (Object) this, target); - // } - // - // @Override - // public boolean backhand$isBattlemode() { - // return BattlegearUtils.isPlayerInBattlemode((EntityPlayer) (Object) this); - // } - // - // @Override - // public boolean backhand$isBlockingWithShield() { - // return BattlegearUtils.canBlockWithShield((EntityPlayer) (Object) this) && this.backhand$isShielding; - // } - // - // @Override - // public void backhand$setBlockingWithShield(boolean block) { - // this.backhand$isShielding = block && BattlegearUtils.canBlockWithShield((EntityPlayer) (Object) this); - // } - // - // @Override - // public int backhand$getSpecialActionTimer() { - // return this.backhand$specialActionTimer; - // } - // - // @Override - // public void backhand$setSpecialActionTimer(int time) { - // this.backhand$specialActionTimer = time; - // } + @Override + protected void updateArmSwingProgress() { + super.updateArmSwingProgress(); + this.backhand$prevOffHandSwingProgress = this.backhand$offHandSwingProgress; + int var1 = this.getArmSwingAnimationEnd(); + if (this.backhand$isOffHandSwingInProgress) { + ++this.backhand$offHandSwingProgressInt; + if (this.backhand$offHandSwingProgressInt >= var1) { + this.backhand$offHandSwingProgressInt = 0; + this.backhand$isOffHandSwingInProgress = false; + } + } else { + this.backhand$offHandSwingProgressInt = 0; + } + this.backhand$offHandSwingProgress = (float) this.backhand$offHandSwingProgressInt / (float) var1; + if (this.backhand$specialActionTimer > 0) { + this.backhand$isOffHandSwingInProgress = false; + this.isSwingInProgress = false; + this.backhand$offHandSwingProgress = 0.0F; + this.backhand$offHandSwingProgressInt = 0; + this.swingProgress = 0.0F; + this.swingProgressInt = 0; + } + + } } diff --git a/src/main/java/xonin/backhand/mixins/early/MixinEntityPlayerClient.java b/src/main/java/xonin/backhand/mixins/early/MixinEntityPlayerClient.java new file mode 100644 index 0000000..447740b --- /dev/null +++ b/src/main/java/xonin/backhand/mixins/early/MixinEntityPlayerClient.java @@ -0,0 +1,45 @@ +package xonin.backhand.mixins.early; + +import net.minecraft.client.Minecraft; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemBow; +import net.minecraft.item.ItemStack; +import net.minecraft.util.IIcon; +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.api.core.IBackhandPlayer; +import xonin.backhand.client.utils.BackhandClientUtils; + +@Mixin(EntityPlayer.class) +public abstract class MixinEntityPlayerClient extends EntityLivingBase implements IBackhandPlayer { + + private MixinEntityPlayerClient(World p_i1594_1_) { + super(p_i1594_1_); + } + + @Inject(method = "getItemIcon", at = @At(value = "HEAD")) + private void backhand2$getItemIcon(ItemStack itemStackIn, int p_70620_2_, CallbackInfoReturnable cir) { + EntityPlayer player = Minecraft.getMinecraft().thePlayer; + if (itemStackIn == player.getCurrentEquippedItem() && player.getCurrentEquippedItem() != null + && player.getItemInUse() != null + && player.getCurrentEquippedItem() + .getItem() instanceof ItemBow + && player.getCurrentEquippedItem() != player.getItemInUse()) { + BackhandClientUtils.disableMainhandAnimation = true; + } + } + + @Override + public float getSwingProgress(float partialTicks) { + if (BackhandClientUtils.offhandFPRender) { + return getOffSwingProgress(partialTicks); + } + return super.getSwingProgress(partialTicks); + } +} diff --git a/src/main/java/xonin/backhand/mixins/early/MixinInventoryPlayer.java b/src/main/java/xonin/backhand/mixins/early/MixinInventoryPlayer.java index aff1312..989fe2c 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinInventoryPlayer.java +++ b/src/main/java/xonin/backhand/mixins/early/MixinInventoryPlayer.java @@ -16,6 +16,9 @@ @Mixin(InventoryPlayer.class) public abstract class MixinInventoryPlayer { + // Todo: We're already replacing the inventory in EntityPlayer, can this instead be an @Override in + // InventoryPlayerBackhand? + @Shadow public int currentItem; @@ -30,237 +33,4 @@ public abstract class MixinInventoryPlayer { return original; } - - // @Unique - // public boolean battlegear2$isDirty = true; - // @Unique - // private ItemStack[] battlegear2$extraItems = new ItemStack[EXTRA_INV_SIZE]; - // - // @Shadow - // public int currentItem; - // @Shadow - // public EntityPlayer player; - // - // @Shadow - // public abstract ItemStack getStackInSlot(int slotIn); - // - // @Shadow - // public abstract ItemStack getCurrentItem(); - // - // @Shadow - // public abstract void setInventorySlotContents(int index, ItemStack stack); - // - // @Inject(method = "getCurrentItem", at = @At("HEAD"), cancellable = true) - // private void battlegear2$getCurrentItem(CallbackInfoReturnable cir) { - // if (battlegear2$isBattlemode()) { - // cir.setReturnValue(battlegear2$extraItems[currentItem - OFFSET]); - // } - // } - // - // @Inject(method = "func_146023_a", at = @At("HEAD"), cancellable = true) - // private void battlegear2$func_146023_a(Block block, CallbackInfoReturnable cir) { - // if (battlegear2$isBattlemode()) { - // ItemStack currentItemStack = getCurrentItem(); - // cir.setReturnValue(currentItemStack != null ? currentItemStack.func_150997_a(block) : 1.0F); - // } - // } - // - // @Inject(method = "getStackInSlot", at = @At("HEAD"), cancellable = true) - // private void battlegear2$getStackInSlot(int slotIn, CallbackInfoReturnable cir) { - // if (slotIn >= OFFSET) { - // cir.setReturnValue(battlegear2$extraItems[slotIn - OFFSET]); - // } - // } - // - // @ModifyReturnValue(method = "hasItem", at = @At("RETURN")) - // private boolean battlegear2$hasItem(boolean original, Item item) { - // if (original) { - // return true; - // } - // return battlegear2$getInventorySlotContainItem(item) >= 0; - // } - // - // /** - // * Returns a slot index in extra item inventory containing a specific item - // */ - // @Unique - // private int battlegear2$getInventorySlotContainItem(Item item) { - // for (int i = 0; i < this.battlegear2$extraItems.length; ++i) { - // if (this.battlegear2$extraItems[i] != null && this.battlegear2$extraItems[i].getItem() == item) { - // return i; - // } - // } - // return -1; - // } - // - // @Inject(method = "decrementAnimations", at = @At("RETURN")) - // private void battlegear2$decrementAnimations(CallbackInfo ci) { - // for (int i = 0; i < this.battlegear2$extraItems.length; ++i) { - // if (this.battlegear2$extraItems[i] != null) { - // this.battlegear2$extraItems[i] - // .updateAnimation(this.player.worldObj, this.player, i + OFFSET, this.currentItem == i + OFFSET); - // } - // } - // } - // - // @Inject(method = "decrStackSize", at = @At("HEAD"), cancellable = true) - // private void battlegear2$decrStackSize(int index, int count, CallbackInfoReturnable cir) { - // if (index >= OFFSET) { - // ItemStack targetStack = battlegear2$extraItems[index - OFFSET]; - // if (targetStack != null) { - // battlegear2$isDirty = true; - // if (targetStack.stackSize <= count) { - // battlegear2$extraItems[index - OFFSET] = null; - // } else { - // targetStack = battlegear2$extraItems[index - OFFSET].splitStack(count); - // if (battlegear2$extraItems[index - OFFSET].stackSize == 0) { - // battlegear2$extraItems[index - OFFSET] = null; - // } - // } - // cir.setReturnValue(targetStack); - // return; - // } - // cir.setReturnValue(null); - // } - // } - // - // @Inject(method = "setInventorySlotContents", at = @At("HEAD"), cancellable = true) - // private void battlegear2$setInventorySlotContents(int index, ItemStack stack, CallbackInfo ci) { - // if (index >= OFFSET) { - // battlegear2$isDirty = true; - // battlegear2$extraItems[index - OFFSET] = stack; - // ci.cancel(); - // } - // } - // - // @Override - // public void battlegear2$setInventorySlotContents(int index, ItemStack stack, boolean changed) { - // if (index >= OFFSET) { - // battlegear2$isDirty = changed; - // battlegear2$extraItems[index - OFFSET] = stack; - // } else { - // this.setInventorySlotContents(index, stack); - // } - // } - // - // @ModifyReturnValue(method = "clearInventory", at = @At("RETURN")) - // private int battlegear2$clearInventory(int original, Item targetItem, int targetDamage) { - // int stacks = 0; - // for (int i = 0; i < battlegear2$extraItems.length; i++) { - // if (battlegear2$extraItems[i] != null - // && (targetItem == null || battlegear2$extraItems[i].getItem() == targetItem) - // && (targetDamage <= -1 || battlegear2$extraItems[i].getItemDamage() == targetDamage)) { - // stacks += battlegear2$extraItems[i].stackSize; - // battlegear2$extraItems[i] = null; - // } - // } - // battlegear2$isDirty = stacks > 0; - // return original + stacks; - // } - // - // @Inject(method = "getStackInSlotOnClosing", at = @At("HEAD"), cancellable = true) - // private void battlegear2$getStackInSlotOnClosing(int slot, CallbackInfoReturnable cir) { - // if (slot >= OFFSET) { - // cir.setReturnValue(battlegear2$extraItems[slot - OFFSET]); - // } - // } - // - // @Inject(method = "consumeInventoryItem", at = @At("HEAD"), cancellable = true) - // private void battlegear2$consumeInventoryItem(Item item, CallbackInfoReturnable cir) { - // int j = battlegear2$getInventorySlotContainItem(item); - // if (j >= 0) { - // this.battlegear2$isDirty = true; - // if (--this.battlegear2$extraItems[j].stackSize <= 0) { - // this.battlegear2$extraItems[j] = null; - // } - // cir.setReturnValue(true); - // } - // } - // - // @Inject(method = "dropAllItems", at = @At("RETURN")) - // private void battlegear2$dropAllItems(CallbackInfo ci) { - // this.battlegear2$isDirty = true; - // for (int i = 0; i < this.battlegear2$extraItems.length; ++i) { - // if (this.battlegear2$extraItems[i] != null) { - // this.player.func_146097_a(this.battlegear2$extraItems[i], true, false); - // this.battlegear2$extraItems[i] = null; - // } - // } - // } - // - // @Inject(method = "copyInventory", at = @At("RETURN")) - // private void battlegear2$copyInventory(InventoryPlayer otherInventory, CallbackInfo ci) { - // for (int i = 0; i < battlegear2$extraItems.length; i++) { - // this.battlegear2$extraItems[i] = ItemStack.copyItemStack(otherInventory.getStackInSlot(i + OFFSET)); - // } - // } - // - // @ModifyReturnValue(method = "writeToNBT", at = @At("RETURN")) - // private NBTTagList battlegear2$writeToNBT(NBTTagList nbtTagList) { - // NBTTagCompound nbttagcompound; - // for (int i = 0; i < battlegear2$extraItems.length; ++i) { - // if (battlegear2$extraItems[i] != null) { - // nbttagcompound = new NBTTagCompound(); - // // This will be -ve, but meh still works - // nbttagcompound.setByte("Slot", (byte) (i + OFFSET)); - // this.battlegear2$extraItems[i].writeToNBT(nbttagcompound); - // nbtTagList.appendTag(nbttagcompound); - // } - // } - // return nbtTagList; - // } - // - // @Inject(method = "readFromNBT", at = @At("HEAD")) - // private void battlegear2$readFromNBT$initInventory(NBTTagList taglist, CallbackInfo ci) { - // this.battlegear2$extraItems = new ItemStack[EXTRA_INV_SIZE]; - // } - // - // @Inject( - // method = "readFromNBT", - // at = @At( - // value = "INVOKE", - // target = - // "Lnet/minecraft/item/ItemStack;loadItemStackFromNBT(Lnet/minecraft/nbt/NBTTagCompound;)Lnet/minecraft/item/ItemStack;", - // shift = At.Shift.BY, - // by = 2), - // locals = LocalCapture.CAPTURE_FAILHARD) - // private void battlegear2$readFromNBT$setItems(NBTTagList p_70443_1_, CallbackInfo ci, int i, - // NBTTagCompound nbttagcompound, int j, ItemStack stack) { - // if (stack != null && j >= OFFSET && j - OFFSET < this.battlegear2$extraItems.length) { - // this.battlegear2$extraItems[j - OFFSET] = stack; - // } - // } - // - // @Override - // public boolean battlegear2$isDirty() { - // return battlegear2$isDirty; - // } - // - // @Override - // public void battlegear2$setDirty(boolean dirty) { - // this.battlegear2$isDirty = dirty; - // } - // - // /** - // * @return true if the current item value is offset in the battle slot range - // */ - // @Override - // public boolean battlegear2$isBattlemode() { - // return this.currentItem >= OFFSET && this.currentItem < OFFSET + EXTRA_ITEMS; - // } - // - // /** - // * Get the offset item (for the left hand) - // * - // * @return the item held in left hand, if any - // */ - // @Override - // public ItemStack battlegear2$getCurrentOffhandWeapon() { - // if (battlegear2$isBattlemode()) { - // return getStackInSlot(currentItem + WEAPON_SETS); - // } else { - // return null; - // } - // } - } diff --git a/src/main/java/xonin/backhand/mixins/early/MixinInventoryPlayerClient.java b/src/main/java/xonin/backhand/mixins/early/MixinInventoryPlayerClient.java deleted file mode 100644 index 3265319..0000000 --- a/src/main/java/xonin/backhand/mixins/early/MixinInventoryPlayerClient.java +++ /dev/null @@ -1,39 +0,0 @@ -package xonin.backhand.mixins.early; - -import net.minecraft.entity.player.InventoryPlayer; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -@Mixin(InventoryPlayer.class) -public abstract class MixinInventoryPlayerClient { - - @Shadow - public int currentItem; - - // @Inject(method = "func_146030_a", at = @At("HEAD"), cancellable = true) - // private void battlegear2$setCurrentItem(Item itemIn, int metadataIn, boolean isMetaSpecific, - // boolean forceInEmptySlots, CallbackInfo ci) { - // if (battlegear2$isBattlemode()) { - // ci.cancel(); - // } - // } - // - // @Inject(method = "changeCurrentItem", at = @At("HEAD"), cancellable = true) - // private void battlegear2$changeCurrentItem(int direction, CallbackInfo ci) { - // if (battlegear2$isBattlemode()) { - // if (direction > 0) { - // direction = 1; - // } else if (direction != 0) { - // direction = -1; - // } - // // noinspection StatementWithEmptyBody - // for (currentItem -= direction; currentItem < OFFSET; currentItem += WEAPON_SETS) {} - // while (currentItem >= OFFSET + WEAPON_SETS) { - // currentItem -= WEAPON_SETS; - // } - // ci.cancel(); - // } - // } - -} diff --git a/src/main/java/xonin/backhand/mixins/early/MixinItemStack.java b/src/main/java/xonin/backhand/mixins/early/MixinItemStack.java index 3a1095a..7bef385 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinItemStack.java +++ b/src/main/java/xonin/backhand/mixins/early/MixinItemStack.java @@ -2,7 +2,6 @@ import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; import net.minecraft.item.ItemStack; import net.minecraftforge.event.ForgeEventFactory; @@ -11,13 +10,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.llamalad7.mixinextras.injector.ModifyReturnValue; - -import cpw.mods.fml.common.FMLCommonHandler; -import cpw.mods.fml.relauncher.Side; -import xonin.backhand.HookContainerClass; import xonin.backhand.api.core.BackhandUtils; -import xonin.backhand.client.ClientEventHandler; @Mixin(ItemStack.class) public abstract class MixinItemStack { @@ -33,29 +26,4 @@ public abstract class MixinItemStack { ForgeEventFactory.onPlayerDestroyItem(player, offhandItem); } } - - @ModifyReturnValue(method = "getItemUseAction", at = @At(value = "TAIL")) - private EnumAction backhand$getOffhandUseAction(EnumAction original) { - if (original == EnumAction.none || FMLCommonHandler.instance() - .getEffectiveSide() == Side.CLIENT && ClientEventHandler.renderingPlayer == null) { - return original; - } - EntityPlayer player = ClientEventHandler.renderingPlayer; - ItemStack itemStack = (ItemStack) (Object) this; - ItemStack offhandItem = BackhandUtils.getOffhandItem(player); - if (offhandItem != null) { - ItemStack mainHandItem = player.getCurrentEquippedItem(); - if (mainHandItem != null && (BackhandUtils.checkForRightClickFunctionNoAction(mainHandItem) - || HookContainerClass.isItemBlock(mainHandItem.getItem()))) { - if (itemStack == offhandItem) { - return EnumAction.none; - } - } else if (itemStack == mainHandItem && (!(BackhandUtils.checkForRightClickFunctionNoAction(offhandItem) - || HookContainerClass.isItemBlock(offhandItem.getItem())) || player.getItemInUse() != mainHandItem)) { - return EnumAction.none; - } - } - return original; - } - } diff --git a/src/main/java/xonin/backhand/mixins/early/MixinItemStackClient.java b/src/main/java/xonin/backhand/mixins/early/MixinItemStackClient.java new file mode 100644 index 0000000..f0c9916 --- /dev/null +++ b/src/main/java/xonin/backhand/mixins/early/MixinItemStackClient.java @@ -0,0 +1,42 @@ +package xonin.backhand.mixins.early; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; +import net.minecraft.item.ItemStack; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; + +import xonin.backhand.HookContainerClass; +import xonin.backhand.api.core.BackhandUtils; +import xonin.backhand.client.ClientEventHandler; + +@Mixin(ItemStack.class) +public abstract class MixinItemStackClient { + + @ModifyReturnValue(method = "getItemUseAction", at = @At(value = "TAIL")) + private EnumAction backhand$getOffhandUseAction(EnumAction original) { + if (original == EnumAction.none || ClientEventHandler.renderingPlayer == null) { + return original; + } + EntityPlayer player = ClientEventHandler.renderingPlayer; + ItemStack itemStack = (ItemStack) (Object) this; + ItemStack offhandItem = BackhandUtils.getOffhandItem(player); + if (offhandItem != null) { + ItemStack mainHandItem = player.getCurrentEquippedItem(); + if (mainHandItem != null && (BackhandUtils.checkForRightClickFunctionNoAction(mainHandItem) + || HookContainerClass.isItemBlock(mainHandItem.getItem()))) { + if (itemStack == offhandItem) { + return EnumAction.none; + } + } else if (itemStack == mainHandItem && (!(BackhandUtils.checkForRightClickFunctionNoAction(offhandItem) + || HookContainerClass.isItemBlock(offhandItem.getItem())) || player.getItemInUse() != mainHandItem)) { + return EnumAction.none; + } + } + return original; + } + +} diff --git a/src/main/java/xonin/backhand/mixins/early/MixinModelBiped.java b/src/main/java/xonin/backhand/mixins/early/MixinModelBiped.java index 0972baf..2fe92b8 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinModelBiped.java +++ b/src/main/java/xonin/backhand/mixins/early/MixinModelBiped.java @@ -21,7 +21,7 @@ public abstract class MixinModelBiped { BackhandRenderHelper.moveOffHandArm(entity, (ModelBiped) (Object) this, f6); } - // TODO: Decipher this shit + // TODO: Decipher this shit & is it even needed in the first place // private static void setRotationAngles(ModelBiped b, float p_78087_1_, float p_78087_2_, float p_78087_3_, // float p_78087_4_, float p_78087_5_, float p_78087_6_, Entity p_78087_7_) { // b.bipedHead.rotateAngleY = p_78087_4_ / (180F / (float) Math.PI); diff --git a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayClient.java b/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayClient.java index 759c480..9c778fe 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayClient.java +++ b/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayClient.java @@ -39,5 +39,4 @@ public abstract class MixinNetHandlerPlayClient { 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 5a899c8..a26a029 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java +++ b/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java @@ -25,34 +25,6 @@ public abstract class MixinNetHandlerPlayServer { return InventoryPlayerBackhand.isValidSwitch(original) ? 0 : -1; } - // @WrapOperation( - // method = "processPlayerBlockPlacement", - // at = @At( - // value = "INVOKE", - // target = - // "Lnet/minecraft/inventory/Container;getSlotFromInventory(Lnet/minecraft/inventory/IInventory;I)Lnet/minecraft/inventory/Slot;")) - // private Slot battlegear2$captureSlotVariable(Container instance, IInventory j, int i, Operation original, - // @Share("slot") LocalRef slotRef) { - // Slot slot = original.call(instance, j, i); - // slotRef.set(slot); - // return slot; - // } - // - // @Inject( - // method = "processPlayerBlockPlacement", - // at = @At( - // value = "FIELD", - // target = "Lnet/minecraft/entity/player/EntityPlayerMP;isChangingQuantityOnly:Z", - // shift = At.Shift.AFTER, - // ordinal = 1), - // cancellable = true) - // private void battlegear2$fixNPE(C08PacketPlayerBlockPlacement packetIn, CallbackInfo ci, - // @Share("slot") LocalRef slotRef) { - // if (slotRef.get() == null) { - // ci.cancel(); - // } - // } - @Redirect( method = "processPlayerDigging", at = @At( diff --git a/src/main/java/xonin/backhand/mixins/early/MixinPlayerControllerMP.java b/src/main/java/xonin/backhand/mixins/early/MixinPlayerControllerMP.java index d9be78c..89c1e60 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinPlayerControllerMP.java +++ b/src/main/java/xonin/backhand/mixins/early/MixinPlayerControllerMP.java @@ -58,12 +58,30 @@ public abstract class MixinPlayerControllerMP { return original; } - // @Inject(method = "sendUseItem", at = @At(value = "FIELD", opcode = Opcodes.GETFIELD, target = - // "Lnet/minecraft/entity/player/InventoryPlayer;mainInventory:[Lnet/minecraft/item/ItemStack;")) + // @Inject( + // method = "sendUseItem", + // at = @At( + // value = "FIELD", + // opcode = Opcodes.GETFIELD, + // target = "Lnet/minecraft/entity/player/InventoryPlayer;mainInventory:[Lnet/minecraft/item/ItemStack;")) // private void backhand$sendUseItem(EntityPlayer player, World worldIn, ItemStack itemStackIn, // CallbackInfoReturnable cir, @Local(ordinal = 1) ItemStack rightClickStack) { // ItemStack stack = rightClickStack.stackSize == 0 ? null : rightClickStack; // BackhandUtils.setPlayerCurrentItem(player, stack); // cir.cancel(); // } + + // + // @Redirect( + // method = "sendUseItem", + // at = @At( + // value = "FIELD", + // opcode = Opcodes.GETFIELD, + // target = "Lnet/minecraft/entity/player/InventoryPlayer;mainInventory:[Lnet/minecraft/item/ItemStack;")) + // private ItemStack[] backhand$sendUseItem(InventoryPlayer inventory, @Local(ordinal = 1) ItemStack + // rightClickStack) { + // ItemStack stack = rightClickStack.stackSize == 0 ? null : rightClickStack; + // BackhandUtils.setPlayerCurrentItem(inventory.player, stack); + // return new ItemStack[inventory.mainInventory.length]; + // } } From bcb7307e2913207bdc9a442f25b499587390d539 Mon Sep 17 00:00:00 2001 From: Lyfts <127234178+Lyfts@users.noreply.github.com> Date: Thu, 25 Jul 2024 21:03:20 +0200 Subject: [PATCH 3/9] Convert final transformer --- .../asm/fixes/MysteriumPatchesFixesO.java | 73 ------------------- .../early/MixinNetHandlerPlayServer.java | 37 ++++++++++ 2 files changed, 37 insertions(+), 73 deletions(-) diff --git a/src/main/java/net/tclproject/mysteriumlib/asm/fixes/MysteriumPatchesFixesO.java b/src/main/java/net/tclproject/mysteriumlib/asm/fixes/MysteriumPatchesFixesO.java index 2378e73..e9f69b5 100644 --- a/src/main/java/net/tclproject/mysteriumlib/asm/fixes/MysteriumPatchesFixesO.java +++ b/src/main/java/net/tclproject/mysteriumlib/asm/fixes/MysteriumPatchesFixesO.java @@ -4,86 +4,13 @@ import java.lang.invoke.MethodHandles; import java.lang.reflect.Field; -import net.minecraft.client.particle.EffectRenderer; -import net.minecraft.entity.Entity; -import net.minecraft.entity.item.EntityItem; -import net.minecraft.entity.item.EntityXPOrb; -import net.minecraft.entity.projectile.EntityArrow; -import net.minecraft.network.NetHandlerPlayServer; -import net.minecraft.network.play.client.C02PacketUseEntity; -import net.minecraft.util.MovingObjectPosition; -import net.minecraft.world.WorldServer; -import net.tclproject.mysteriumlib.asm.annotations.EnumReturnSetting; -import net.tclproject.mysteriumlib.asm.annotations.Fix; - import cpw.mods.fml.common.Optional; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; import invtweaks.InvTweaksContainerManager; import invtweaks.InvTweaksContainerSectionManager; import invtweaks.api.container.ContainerSection; -import xonin.backhand.api.core.BackhandUtils; -import xonin.backhand.client.ClientEventHandler; public class MysteriumPatchesFixesO { - @Fix(returnSetting = EnumReturnSetting.ON_TRUE) - @SideOnly(Side.CLIENT) - public static boolean addBlockHitEffects(EffectRenderer er, int x, int y, int z, MovingObjectPosition target) { - if (ClientEventHandler.cancelone) { - return true; - } - return false; - } - - @Fix(returnSetting = EnumReturnSetting.ALWAYS) - public static void processUseEntity(NetHandlerPlayServer netServer, C02PacketUseEntity p_147340_1_) { - WorldServer worldserver = netServer.serverController.worldServerForDimension(netServer.playerEntity.dimension); - Entity entity = p_147340_1_.func_149564_a(worldserver); - netServer.playerEntity.func_143004_u(); - - boolean swappedOffhand = BackhandUtils - .checkForRightClickFunction(BackhandUtils.getOffhandItem(netServer.playerEntity)) - && !BackhandUtils.checkForRightClickFunction(netServer.playerEntity.getCurrentEquippedItem()) - && p_147340_1_.func_149565_c() == C02PacketUseEntity.Action.INTERACT; - if (swappedOffhand) { - BackhandUtils.swapOffhandItem(netServer.playerEntity); - } - - if (entity != null) { - boolean flag = netServer.playerEntity.canEntityBeSeen(entity); - double d0 = 36.0D; - - if (!flag) { - d0 = 9.0D; - } - - if (netServer.playerEntity.getDistanceSqToEntity(entity) < d0) { - if (p_147340_1_.func_149565_c() == C02PacketUseEntity.Action.INTERACT) { - netServer.playerEntity.interactWith(entity); - } else if (p_147340_1_.func_149565_c() == C02PacketUseEntity.Action.ATTACK) { - if (entity instanceof EntityItem || entity instanceof EntityXPOrb - || entity instanceof EntityArrow - || entity == netServer.playerEntity) { - netServer.kickPlayerFromServer("Attempting to attack an invalid entity"); - netServer.serverController.logWarning( - "Player " + netServer.playerEntity.getCommandSenderName() - + " tried to attack an invalid entity"); - if (swappedOffhand) { - BackhandUtils.swapOffhandItem(netServer.playerEntity); - } - } - - netServer.playerEntity.attackTargetEntityWithCurrentItem(entity); - } - } - } - - if (swappedOffhand) { - BackhandUtils.swapOffhandItem(netServer.playerEntity); - } - } - private static final MethodHandle fieldGetSection; private static final MethodHandle fieldGetContainerMgr; diff --git a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java b/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java index a26a029..6fb31bb 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java +++ b/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java @@ -1,19 +1,29 @@ package xonin.backhand.mixins.early; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.network.NetHandlerPlayServer; +import net.minecraft.network.play.client.C02PacketUseEntity; import net.minecraft.server.management.ItemInWorldManager; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +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; +import xonin.backhand.api.core.BackhandUtils; import xonin.backhand.api.core.InventoryPlayerBackhand; @Mixin(NetHandlerPlayServer.class) public abstract class MixinNetHandlerPlayServer { + @Shadow + public EntityPlayerMP playerEntity; + @ModifyExpressionValue( method = "processHeldItemChange", at = @At( @@ -34,4 +44,31 @@ public abstract class MixinNetHandlerPlayServer { 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) { + 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); + } + } + + @Unique + private boolean backhand$swapOffhand(C02PacketUseEntity.Action action) { + return BackhandUtils.checkForRightClickFunction(BackhandUtils.getOffhandItem(playerEntity)) + && !BackhandUtils.checkForRightClickFunction(playerEntity.getCurrentEquippedItem()) + && action == C02PacketUseEntity.Action.INTERACT; + } } From f17c6fd8690499126ed9d162660a6998f4f9a95b Mon Sep 17 00:00:00 2001 From: Lyfts <127234178+Lyfts@users.noreply.github.com> Date: Thu, 25 Jul 2024 21:54:17 +0200 Subject: [PATCH 4/9] ditch this cursed lib once and for all --- .../asm/annotations/EnumReturnSetting.java | 39 - .../asm/annotations/EnumReturnType.java | 36 - .../mysteriumlib/asm/annotations/Fix.java | 159 --- .../asm/annotations/FixOrder.java | 10 - .../asm/annotations/LocalVariable.java | 16 - .../asm/annotations/ReturnedValue.java | 12 - .../mysteriumlib/asm/common/BuiltinFixes.java | 29 - .../asm/common/CustomClassTransformer.java | 140 --- .../asm/common/CustomLoadingPlugin.java | 222 ---- .../asm/common/FirstClassTransformer.java | 118 -- .../asm/common/MinecraftMetaReader.java | 172 --- .../mysteriumlib/asm/core/ASMFix.java | 1099 ----------------- .../mysteriumlib/asm/core/FileASMLib.java | 74 -- .../mysteriumlib/asm/core/FixInserter.java | 119 -- .../asm/core/FixInserterClassVisitor.java | 92 -- .../asm/core/FixInserterFactory.java | 77 -- .../mysteriumlib/asm/core/FixParser.java | 420 ------- .../mysteriumlib/asm/core/MetaReader.java | 444 ------- .../mysteriumlib/asm/core/MiscUtils.java | 223 ---- .../asm/core/TargetClassTransformer.java | 155 --- .../mysteriumlib/asm/core/TypeUtils.java | 100 -- .../asm/fixes/MysteriumPatchesFixesO.java | 100 -- .../mysteriumlib/math/LocalityHelper.java | 24 - .../mysteriumlib/math/NoiseStretch.java | 39 - .../mysteriumlib/math/SimplexNoise.java | 441 ------- .../math/SpiralPatternGenerator.java | 114 -- .../mysteriumlib/math/Stopwatch.java | 51 - .../backhand/api/core/BackhandTranslator.java | 17 +- .../backhand/api/core/BackhandUtils.java | 1 - .../coremod/BackhandLoadingPlugin.java | 25 +- src/main/resources/methods.bin | Bin 84382 -> 0 bytes 31 files changed, 23 insertions(+), 4545 deletions(-) delete mode 100644 src/main/java/net/tclproject/mysteriumlib/asm/annotations/EnumReturnSetting.java delete mode 100644 src/main/java/net/tclproject/mysteriumlib/asm/annotations/EnumReturnType.java delete mode 100644 src/main/java/net/tclproject/mysteriumlib/asm/annotations/Fix.java delete mode 100644 src/main/java/net/tclproject/mysteriumlib/asm/annotations/FixOrder.java delete mode 100644 src/main/java/net/tclproject/mysteriumlib/asm/annotations/LocalVariable.java delete mode 100644 src/main/java/net/tclproject/mysteriumlib/asm/annotations/ReturnedValue.java delete mode 100644 src/main/java/net/tclproject/mysteriumlib/asm/common/BuiltinFixes.java delete mode 100644 src/main/java/net/tclproject/mysteriumlib/asm/common/CustomClassTransformer.java delete mode 100644 src/main/java/net/tclproject/mysteriumlib/asm/common/CustomLoadingPlugin.java delete mode 100644 src/main/java/net/tclproject/mysteriumlib/asm/common/FirstClassTransformer.java delete mode 100644 src/main/java/net/tclproject/mysteriumlib/asm/common/MinecraftMetaReader.java delete mode 100644 src/main/java/net/tclproject/mysteriumlib/asm/core/ASMFix.java delete mode 100644 src/main/java/net/tclproject/mysteriumlib/asm/core/FileASMLib.java delete mode 100644 src/main/java/net/tclproject/mysteriumlib/asm/core/FixInserter.java delete mode 100644 src/main/java/net/tclproject/mysteriumlib/asm/core/FixInserterClassVisitor.java delete mode 100644 src/main/java/net/tclproject/mysteriumlib/asm/core/FixInserterFactory.java delete mode 100644 src/main/java/net/tclproject/mysteriumlib/asm/core/FixParser.java delete mode 100644 src/main/java/net/tclproject/mysteriumlib/asm/core/MetaReader.java delete mode 100644 src/main/java/net/tclproject/mysteriumlib/asm/core/MiscUtils.java delete mode 100644 src/main/java/net/tclproject/mysteriumlib/asm/core/TargetClassTransformer.java delete mode 100644 src/main/java/net/tclproject/mysteriumlib/asm/core/TypeUtils.java delete mode 100644 src/main/java/net/tclproject/mysteriumlib/asm/fixes/MysteriumPatchesFixesO.java delete mode 100644 src/main/java/net/tclproject/mysteriumlib/math/LocalityHelper.java delete mode 100644 src/main/java/net/tclproject/mysteriumlib/math/NoiseStretch.java delete mode 100644 src/main/java/net/tclproject/mysteriumlib/math/SimplexNoise.java delete mode 100644 src/main/java/net/tclproject/mysteriumlib/math/SpiralPatternGenerator.java delete mode 100644 src/main/java/net/tclproject/mysteriumlib/math/Stopwatch.java delete mode 100644 src/main/resources/methods.bin diff --git a/src/main/java/net/tclproject/mysteriumlib/asm/annotations/EnumReturnSetting.java b/src/main/java/net/tclproject/mysteriumlib/asm/annotations/EnumReturnSetting.java deleted file mode 100644 index cc17ee7..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/asm/annotations/EnumReturnSetting.java +++ /dev/null @@ -1,39 +0,0 @@ -package net.tclproject.mysteriumlib.asm.annotations; - -/** Determines if return gets called after a fix method. */ -public enum EnumReturnSetting { - - /** - * return never gets called. - */ - NEVER(false), - - /** - * return always gets called. - */ - ALWAYS(false), - - /** - * return gets called, if the fix method returned true. - * You can't use this, if the fix method doesn't return a boolean. - */ - ON_TRUE(true), - - /** - * return gets called, if the fix method returned null. - * You can't use this, if the fix method returns a primitive or void. - */ - ON_NULL(true), - - /** - * return gets called, if the fix method returned null. - * You can't use this, if the fix method returns a primitive or void. - */ - ON_NOT_NULL(true); - - public final boolean conditionRequiredToReturn; - - EnumReturnSetting(boolean conditionRequiredToReturn) { - this.conditionRequiredToReturn = conditionRequiredToReturn; - } -} diff --git a/src/main/java/net/tclproject/mysteriumlib/asm/annotations/EnumReturnType.java b/src/main/java/net/tclproject/mysteriumlib/asm/annotations/EnumReturnType.java deleted file mode 100644 index 907b691..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/asm/annotations/EnumReturnType.java +++ /dev/null @@ -1,36 +0,0 @@ -package net.tclproject.mysteriumlib.asm.annotations; - -/** Specifies what the fix method returns. */ -public enum EnumReturnType { - - /** - * Returns void. - * Only use if the target method returns void. - */ - VOID, - - /** - * Returns a pre-established primitive value. - * Only use if the target method returns a primitive. - */ - PRIMITIVE_CONSTANT, - - /** - * Returns null. - * Only use if the target method returns an object. - */ - NULL, - - /** - * Returns the primitive or object, that the fix method returned. - * Can use in all cases except for when the target method returns void. - */ - FIX_METHOD_RETURN_VALUE, - - /** - * Calls a different method in the same class with the same parameters that the fix method has, but with a different - * name. - * Returns the value that the called method returned. - */ - ANOTHER_METHOD_RETURN_VALUE -} diff --git a/src/main/java/net/tclproject/mysteriumlib/asm/annotations/Fix.java b/src/main/java/net/tclproject/mysteriumlib/asm/annotations/Fix.java deleted file mode 100644 index 1c84c57..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/asm/annotations/Fix.java +++ /dev/null @@ -1,159 +0,0 @@ -package net.tclproject.mysteriumlib.asm.annotations; - -// TODO: Add this everywhere -/* - * Copyright TCLProject - All Rights Reserved - * Unauthorized copying of this file, via any medium is strictly prohibited - * Proprietary and confidential - * Written by TCLProject , December 2020 - */ - -import java.lang.annotation.ElementType; -import java.lang.annotation.Target; - -/** - * To make a method a fix, you need to add this annotation to it and register the class with the fixes. - *

- * The target class is determined by the first argument of the method. - * If the target method is static, then it becomes null, otherwise - this. - *

- * The name of the target method by default is assumed to be the name than that of the fix method, - * but you can change it by specifying targetMethod. - *

- * The arguments of the target method are assumed by the arguments of the fix. You need to specify all the - * arguments in exactly the same order. - *

- * The return type of the target method isn't specified by default. We assume, that there are no methods - * with the same name and arguments. If you need to specify it though, you can do it through returnedType. - */ -@Target(ElementType.METHOD) -public @interface Fix { - - /** - * Specifies a condition, on which after the fix method has been called, return will be called. - * If the target method doesn't return void, by default it will return the value that the fix returned. - * You can override that using a few parameters in this annotation: - * anotherMethodReturned, nullReturned and %type%AlwaysReturned. - */ - EnumReturnSetting returnSetting() default EnumReturnSetting.NEVER; - - /** - * Specifies when the fix method will be called. - * FIRST will be inserted first, LAST will be inserted last therefore will be the actual first/last set of - * instructions. - */ - FixOrder order() default FixOrder.USUAL; - - /** - * Specifies the name of the target method. - * By default the name of the fix method is used. - * This option is useful, when you need to apply a fix to a constructor or to the initialization of a class. - * For a constructor, targetMethod must be "", for the initialization of a class - "". - */ - String targetMethod() default ""; - - /** - * Specifies the type returned by the target method. - * From the point of view of JVM there can be methods, that only differ by the return type. - * In practice, compilers don't generate such methods, but in some cases, they can exist - * (for example, ProGuard can make such methods while obfuscating). - * If the return type isn't specified, the fix will be applied to the first method - * that matches the name and arguments. - * - * The main proposed use of this parameter is with createMethod = true. - * The created method will by default have the same return type as the fix method, - * but you can change that with this parameter. - * - * You need to specify the full name of the class: java.lang.String, void, int etc. - */ - String returnedType() default ""; - - /** - * Allows not only to insert fixes into already existing methods, but also add new ones. This can be useful, - * if you need to override a method of the superclass. Doesn't actually add anything inside the target method except - * for a super call (if possible) and a return statement, so you have to insert a fix into the created method to add - * some functionality. - */ - boolean createNewMethod() default false; - - /** - * Allows to make the fix mandatory for the game to launch. If the insertion of the fix fails, - * the game will crash. - */ - boolean isFatal() default false; - - /** - * By default the fix is injected into the beginning of the target method. - * If this will be set to true, it will be injected in the end and before every return call. - */ - boolean insertOnExit() default false; - - /** - * By default, the fix is inserted into the beginning of the target method. - * If you set this, it will be inserted at the said line. - * The use of this is NOT recommended because it can break very easily, - * (for example, if some mod *cough* optifine *cough* will replace the class fully). - *

- * NOTE: the line numbers in mcp and in minecraft are sometimes different, beware. - */ - @Deprecated - int insertOnLine() default -1; - - /** - * If you specify this name, when return will be called in the target method, this method will be called. - * It must be in the same class and have the same arguments, as the fix method. - * In the end, the returned value will be the one that this method will return. - */ - String anotherMethodReturned() default ""; - - /** - * If true, return in the target method will always return null. - */ - boolean nullReturned() default false; - - /** - * If you specify one of those, it will be returned instead of the original value from the target method. - */ - - boolean booleanAlwaysReturned() default false; - - /** - * If you specify one of those, it will be returned instead of the original value from the target method. - */ - byte byteAlwaysReturned() default 0; - - /** - * If you specify one of those, it will be returned instead of the original value from the target method. - */ - short shortAlwaysReturned() default 0; - - /** - * If you specify one of those, it will be returned instead of the original value from the target method. - */ - int intAlwaysReturned() default 0; - - /** - * If you specify one of those, it will be returned instead of the original value from the target method. - */ - long longAlwaysReturned() default 0L; - - /** - * If you specify one of those, it will be returned instead of the original value from the target method. - */ - float floatAlwaysReturned() default 0.0F; - - /** - * If you specify one of those, it will be returned instead of the original value from the target method. - */ - double doubleAlwaysReturned() default 0.0D; - - /** - * If you specify one of those, it will be returned instead of the original value from the target method. - */ - char charAlwaysReturned() default 0; - - /** - * If you specify one of those, it will be returned instead of the original value from the target method. - */ - String stringAlwaysReturned() default ""; -} diff --git a/src/main/java/net/tclproject/mysteriumlib/asm/annotations/FixOrder.java b/src/main/java/net/tclproject/mysteriumlib/asm/annotations/FixOrder.java deleted file mode 100644 index 1679cc1..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/asm/annotations/FixOrder.java +++ /dev/null @@ -1,10 +0,0 @@ -package net.tclproject.mysteriumlib.asm.annotations; - -public enum FixOrder { - FIRST, // Gets called first - BEFORE_USUAL, - USUAL, - AFTER_USUAL, - LAST // Gets called last - -} diff --git a/src/main/java/net/tclproject/mysteriumlib/asm/annotations/LocalVariable.java b/src/main/java/net/tclproject/mysteriumlib/asm/annotations/LocalVariable.java deleted file mode 100644 index 0b48835..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/asm/annotations/LocalVariable.java +++ /dev/null @@ -1,16 +0,0 @@ -package net.tclproject.mysteriumlib.asm.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Target; - -/** - * Intercepts a local variable. Use as follows: @LocalVariable(variable_number). - * The names of the variables might not save in code, that's why we need a number. - * In order to find out the number, you can use methods in the MetaReader class, - * specifically getLocalVariables. - */ -@Target(ElementType.PARAMETER) -public @interface LocalVariable { - - int number(); -} diff --git a/src/main/java/net/tclproject/mysteriumlib/asm/annotations/ReturnedValue.java b/src/main/java/net/tclproject/mysteriumlib/asm/annotations/ReturnedValue.java deleted file mode 100644 index 99452cb..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/asm/annotations/ReturnedValue.java +++ /dev/null @@ -1,12 +0,0 @@ -package net.tclproject.mysteriumlib.asm.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Target; - -/** - * Intercepts the value that has originally been returned and passes it into the fix method. - * In other words, passes the last value in the stack. - * Can only use if injectOnExit() == true and the target method doesn't return void. - */ -@Target(ElementType.PARAMETER) -public @interface ReturnedValue {} diff --git a/src/main/java/net/tclproject/mysteriumlib/asm/common/BuiltinFixes.java b/src/main/java/net/tclproject/mysteriumlib/asm/common/BuiltinFixes.java deleted file mode 100644 index 6fe5fab..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/asm/common/BuiltinFixes.java +++ /dev/null @@ -1,29 +0,0 @@ -package net.tclproject.mysteriumlib.asm.common; - -import net.minecraft.launchwrapper.LaunchClassLoader; -import net.tclproject.mysteriumlib.asm.annotations.Fix; - -import cpw.mods.fml.common.Loader; - -/** Contails built-in fixes. */ -public class BuiltinFixes { - - /** - * Built-in fix to register CustomClassTransformer after forge's deobfuscation - * has already happened. This makes it easier to work with minecraft code from it. - *

- * In order to work with other/non-mc code, use FirstClassTransformer, which is how this fix is applied. - * It transforms classes earlier on. - */ - @Fix - public static void injectData(Loader loader, Object... data) { - ClassLoader classLoader = BuiltinFixes.class.getClassLoader(); - if (classLoader instanceof LaunchClassLoader) { - ((LaunchClassLoader) classLoader).registerTransformer(CustomClassTransformer.class.getName()); - } else { - System.out.println( - "MysteriumASM Lib was not loaded by LaunchClassLoader. Fixes for minecraft code will not have any effect."); - } - } - -} diff --git a/src/main/java/net/tclproject/mysteriumlib/asm/common/CustomClassTransformer.java b/src/main/java/net/tclproject/mysteriumlib/asm/common/CustomClassTransformer.java deleted file mode 100644 index d46597a..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/asm/common/CustomClassTransformer.java +++ /dev/null @@ -1,140 +0,0 @@ -package net.tclproject.mysteriumlib.asm.common; - -import java.io.BufferedInputStream; -import java.io.DataInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import net.minecraft.launchwrapper.IClassTransformer; -import net.tclproject.mysteriumlib.asm.core.ASMFix; -import net.tclproject.mysteriumlib.asm.core.FixInserterClassVisitor; -import net.tclproject.mysteriumlib.asm.core.TargetClassTransformer; - -import org.objectweb.asm.ClassWriter; - -/** - * This class is responsible for inserting fixes into minecraft code - * from the moment when forge deobfuscation was applied. - */ -public class CustomClassTransformer extends TargetClassTransformer implements IClassTransformer { - - /** An instance of itself that gets created every time the cunstructor gets called. */ - static CustomClassTransformer instance; - - /** A map of "method index" : "mcp method name" for all the methods in methods.csv. */ - private Map methodsMap; - - /** Transformers that will be executed after all the normal ones are. */ - private static List postTransformers = new ArrayList<>(); - - public CustomClassTransformer() { - instance = this; - - if (CustomLoadingPlugin.isObfuscated()) { // If running in obf environment, load obf method names - try { - long timeStart = System.currentTimeMillis(); - methodsMap = loadMethods(); - long time = System.currentTimeMillis() - timeStart; - logger.debug("Methods dictionary loaded in " + time + " ms"); - } catch (IOException e) { - logger.severe("Can not load obfuscated method names", e); - } - } - - this.metaReader = CustomLoadingPlugin.getMetaReader(); - - this.fixesMap.putAll(FirstClassTransformer.instance.getFixesMap()); // Puts all fixes loaded in - // FirstClassTransformer into this class. - FirstClassTransformer.instance.getFixesMap() - .clear(); - FirstClassTransformer.instance.registeredBuiltinFixes = true; - } - - /** - * Loads method indexes and obfuscated method names from a methods.bin file. - * - * @throws IOException if the methods.bin file is not found. - * @return A HashMap of "method index" : "mcp method name" for all the methods in methods.csv. - */ - private HashMap loadMethods() throws IOException { - InputStream resourceStream = getClass().getResourceAsStream("/methods.bin"); - if (resourceStream == null) throw new IOException("Methods dictionary not found."); - DataInputStream input = new DataInputStream(new BufferedInputStream(resourceStream)); - int numMethods = input.readInt(); - HashMap map = new HashMap<>(numMethods); - for (int i = 0; i < numMethods; i++) { - map.put(input.readInt(), input.readUTF()); - } - input.close(); - return map; - } - - /** - * Inserts fixes into classes passed in. First, runs the class through the normal transformer, - * and only then, through the post transformers (ones that are to be executed after the normal ones). - *

- * Forge passes in the arguments and takes the return value of this method, unless you want some - * special behavior you shouldn't interact with this method or modify it. - */ - @Override - public byte[] transform(String name, String deobfName, byte[] bytecode) { - bytecode = transform(deobfName, bytecode); - for (IClassTransformer postTransformer : postTransformers) { - bytecode = postTransformer.transform(name, deobfName, bytecode); - } - return bytecode; - } - - /** - * Creates a custom Class Visitor to return custom method visitors to insert fixes. - * Has custom logic to check if a method is the target method of a fix, accounting for an obfuscated name. - */ - @Override - public FixInserterClassVisitor createInserterClassVisitor(ClassWriter classWriter, List fixes) { - return new FixInserterClassVisitor(this, classWriter, fixes) { - - @Override - protected boolean isTheTarget(ASMFix fix, String name, String descriptor) { - if (CustomLoadingPlugin.isObfuscated()) { - String deobfName = methodsMap.get(getMethodIndex(name)); - if (deobfName != null && super.isTheTarget(fix, deobfName, descriptor)) { - return true; - } - } - return super.isTheTarget(fix, name, descriptor); - } - }; - } - - /** Getter for methodsMap. */ - public Map getMethodNames() { - return methodsMap; - } - - /** - * Gets a method index from a method name. - * - * @return the method index (or -1 if it's not found). - */ - public static int getMethodIndex(String srgName) { - if (srgName.startsWith("func_")) { - int first = srgName.indexOf('_'); - int second = srgName.indexOf('_', first + 1); - return Integer.valueOf(srgName.substring(first + 1, second)); - } else { - return -1; - } - } - - /** - * Registers a transformer that will be executed after the normal transformers (including the deobfuscation - * transformer). - */ - public static void registerPostTransformer(IClassTransformer transformer) { - postTransformers.add(transformer); - } -} diff --git a/src/main/java/net/tclproject/mysteriumlib/asm/common/CustomLoadingPlugin.java b/src/main/java/net/tclproject/mysteriumlib/asm/common/CustomLoadingPlugin.java deleted file mode 100644 index 193740a..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/asm/common/CustomLoadingPlugin.java +++ /dev/null @@ -1,222 +0,0 @@ -package net.tclproject.mysteriumlib.asm.common; - -import java.io.File; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Map; -import java.util.logging.Logger; - -import net.tclproject.mysteriumlib.asm.core.ASMFix; -import net.tclproject.mysteriumlib.asm.core.MetaReader; -import net.tclproject.mysteriumlib.asm.core.TargetClassTransformer; - -import org.apache.logging.log4j.Level; - -import cpw.mods.fml.common.FMLLog; -import cpw.mods.fml.common.asm.transformers.DeobfuscationTransformer; -import cpw.mods.fml.relauncher.CoreModManager; -import cpw.mods.fml.relauncher.IFMLLoadingPlugin; -import xonin.backhand.api.core.BackhandTranslator; -import xonin.backhand.coremod.BackhandLoadingPlugin; - -/** - * Custom IFMLLoadingPlugin implementation. - * - * @see IFMLLoadingPlugin - */ -@IFMLLoadingPlugin.TransformerExclusions({ "net.tclproject", "xonin.backhand.coremod" }) -public class CustomLoadingPlugin implements IFMLLoadingPlugin { - - /** A DeobfuscationTransformer instance for use inside this class. */ - private static DeobfuscationTransformer deobfuscationTransformer; - /** If we have checked if we're running inside an obfuscated environment. */ - private static boolean checkedObfuscation; - /** If we're running inside an obfuscated environment. */ - private static boolean obfuscated; - /** A Metadata Reader instance for use inside this class. */ - private static MetaReader mcMetaReader; - - public static boolean foundThaumcraft = false; - private static boolean foundOptiFine = false; - private static boolean confirmedOptiFine = false; - public static boolean foundDragonAPI = false; - public static boolean isDevEnvironment = false; - - public static File debugOutputLocation; - - static { - mcMetaReader = new MinecraftMetaReader(); - } - - /** - * Returns the transformer that we are using at the current moment in time to modify classes. - * See why we have to use two separate ones in the documentation for FirstClassTransformer. - * - * @return FirstClassTransformer if our built-in fixes haven't been applied, otherwise - CustomClassTransformer. - */ - public static TargetClassTransformer getTransformer() { - return FirstClassTransformer.instance.registeredBuiltinFixes ? CustomClassTransformer.instance - : FirstClassTransformer.instance; - } - - public static boolean isOptiFinePresent() { - if (!confirmedOptiFine && foundOptiFine) { - // Check presence of OptiFine core classes - try { - Class.forName("optifine.OptiFineForgeTweaker"); - } catch (ClassNotFoundException exception1) { - try { - Class.forName("optifine.OptiFineTweaker"); - } catch (ClassNotFoundException exception2) { - foundOptiFine = false; - } - } - if (foundOptiFine) { - Logger.getGlobal() - .info("Core: OptiFine presence has been confirmed."); - } else { - Logger.getGlobal() - .info("Core: OptiFine doesn't seem to be there actually."); - } - confirmedOptiFine = true; - } - return foundOptiFine; - } - - /** - * Registers a single manually made ASMFix. - * It is not the most efficient way to make fixes, but if you want to go this way, - * look at how the code already there builds an ASMFix out of a fix method or just - * take a look at the documentation of the builder class within ASMFix. - */ - public static void registerFix(ASMFix fix) { - getTransformer().registerFix(fix); - } - - /** Registers all fix methods within a class. */ - public static void registerClassWithFixes(String className) { - getTransformer().registerClassWithFixes(className); - } - - /** Getter for mcMetaReader. */ - public static MetaReader getMetaReader() { - return mcMetaReader; - } - - static DeobfuscationTransformer getDeobfuscationTransformer() { - if (isObfuscated() && deobfuscationTransformer == null) { - deobfuscationTransformer = new DeobfuscationTransformer(); - } - return deobfuscationTransformer; - } - - /** - * If the obfuscation has not yet been checked, checks and returns it. - * If it has, returns the value that the previous check returned. - * - * @return If the mod is run in an obfuscated environment. - */ - public static boolean isObfuscated() { - if (!checkedObfuscation) { - try { - Field deobfuscatedField = CoreModManager.class.getDeclaredField("deobfuscatedEnvironment"); - deobfuscatedField.setAccessible(true); - obfuscated = !deobfuscatedField.getBoolean(null); - } catch (Exception e) { - FMLLog.log("Mysterium Patches", Level.ERROR, "Error occured when checking obfuscation."); - FMLLog.log( - "Mysterium Patches", - Level.ERROR, - "THIS IS MOST LIKELY HAPPENING BECAUSE OF MOD CONFLICTS. PLEASE CONTACT ME TO LET ME KNOW."); - FMLLog.log("Mysterium Patches", Level.ERROR, e.getMessage()); - } - checkedObfuscation = true; - } - return obfuscated; - } - - // For further methods, forge has way better documentation than what I could ever write. - - // Only exists in 1.7.10. Comment out if not needed. - @Override - public String getAccessTransformerClass() { - return null; - } - - @Override - public String[] getASMTransformerClass() { - return null; - } - - @Override - public String getModContainerClass() { - return null; - } - - @Override - public String getSetupClass() { - return null; - } - - @Override - public void injectData(Map data) { - debugOutputLocation = new File( - data.get("mcLocation") - .toString(), - "bg edited classes"); - BackhandLoadingPlugin.debugOutputLocation = new File( - data.get("mcLocation") - .toString(), - "bg edited classes"); - BackhandTranslator.obfuscatedEnv = Boolean.class.cast(data.get("runtimeDeobfuscationEnabled")); - if (((ArrayList) data.get("coremodList")).contains("DragonAPIASMHandler")) { - Logger.getGlobal() - .info("Core: Located DragonAPI in list of coremods"); - foundDragonAPI = true; - } - - // This is very crude check for mods presence using filename. - // Some mods may refer to others in their name, so we'll to confirm those assumption with class presence check. - File loc = (File) data.get("mcLocation"); - - Logger.getGlobal() - .info("MC located at: " + loc.getAbsolutePath()); - isDevEnvironment = !(Boolean) data.get("runtimeDeobfuscationEnabled"); - - File mcFolder = new File(loc.getAbsolutePath() + File.separatorChar + "mods"); - File mcVersionFolder = new File(mcFolder.getAbsolutePath() + File.separatorChar + "1.7.10"); - ArrayList subfiles = new ArrayList<>(); - if (mcFolder.listFiles() != null) { - subfiles = new ArrayList<>(Arrays.asList(mcFolder.listFiles())); - if (mcVersionFolder.listFiles() != null) { - subfiles.addAll(Arrays.asList(mcVersionFolder.listFiles())); - } - } - for (File file : subfiles) { - String name = file.getName(); - if (name != null) { - name = name.toLowerCase(); - if (name.endsWith(".jar") || name.endsWith(".zip")) { - if (name.contains("thaumcraft")) { - Logger.getGlobal() - .info("Core: Located Thaumcraft in " + file.getName()); - foundThaumcraft = true; - } else if (name.contains("optifine")) { - Logger.getGlobal() - .info("Core: Located OptiFine in " + file.getName() + ". We'll to confirm that..."); - foundOptiFine = true; - } else if (name.contains("dragonapi")) { - Logger.getGlobal() - .info("Core: Located DragonAPI in " + file.getName()); - foundDragonAPI = true; - } - } - } - } - registerFixes(); - } - - public void registerFixes() {} - -} diff --git a/src/main/java/net/tclproject/mysteriumlib/asm/common/FirstClassTransformer.java b/src/main/java/net/tclproject/mysteriumlib/asm/common/FirstClassTransformer.java deleted file mode 100644 index 73dc73c..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/asm/common/FirstClassTransformer.java +++ /dev/null @@ -1,118 +0,0 @@ -package net.tclproject.mysteriumlib.asm.common; - -import java.util.HashMap; -import java.util.List; - -import net.minecraft.launchwrapper.IClassTransformer; -import net.tclproject.mysteriumlib.asm.core.ASMFix; -import net.tclproject.mysteriumlib.asm.core.FixInserterClassVisitor; -import net.tclproject.mysteriumlib.asm.core.TargetClassTransformer; - -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.Type; - -import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; - -/** - * This transformer transforms any classes that load before minecraft's classes do. - * When minecraft classes start loading (actually, a bit earlier - in Loader.injectData) - * all fixes from this class are transferred to CustomClassTransformer. This is needed - * in order for the fixes in MysteriumASM Lib to be applied after forge deobfuscation. - */ -public class FirstClassTransformer extends TargetClassTransformer implements IClassTransformer { - - /** To check if some mod is using the library before it is loaded. */ - public static FirstClassTransformer instance = new FirstClassTransformer(); - /** If the fixes from here have been transferred into CustomClassTransformer. */ - boolean registeredBuiltinFixes; - - public FirstClassTransformer() { - this.metaReader = CustomLoadingPlugin.getMetaReader(); - - if (instance != null) { - // If the lib has been loaded, clear all fixes that for some reason have been put in and transfer them into - // this instance. - this.fixesMap.putAll(FirstClassTransformer.instance.getFixesMap()); - FirstClassTransformer.instance.getFixesMap() - .clear(); - } else { - registerClassWithFixes(BuiltinFixes.class.getName()); // Register the built-in fixes - } - instance = this; // Change the global instance to this one. - } - - /** - * Forge passes in all the classes here to be transformed. - * We are passing them to the actual transformer with the right arguments. - */ - @Override - public byte[] transform(String name, String deobfName, byte[] bytes) { - return transform(deobfName, bytes); - } - - /** - * Creates a custom Class Visitor to return custom method visitors to insert fixes. - * Has custom logic to see if the method is the target method, accounting for an obfuscated descriptor. - */ - @Override - public FixInserterClassVisitor createInserterClassVisitor(ClassWriter classWriter, List fixes) { - return new FixInserterClassVisitor(this, classWriter, fixes) { - - @Override - protected boolean isTheTarget(ASMFix fix, String name, String descriptor) { - return super.isTheTarget(fix, name, obfuscateDescriptor(descriptor)); - } - }; - } - - /** Getter for fixesMap. */ - public HashMap> getFixesMap() { - return fixesMap; - } - - /** - * @param descriptor a deobfuscater descriptor. - * @return an obfuscated equivalent of the descriptor. - */ - static String obfuscateDescriptor(String descriptor) { - if (!CustomLoadingPlugin.isObfuscated()) return descriptor; - - Type methodType = Type.getMethodType(descriptor); - Type mappedReturnType = map(methodType.getReturnType()); - Type[] argTypes = methodType.getArgumentTypes(); - Type[] mappedArgTypes = new Type[argTypes.length]; - for (int i = 0; i < mappedArgTypes.length; i++) { - mappedArgTypes[i] = map(argTypes[i]); - } - return Type.getMethodDescriptor(mappedReturnType, mappedArgTypes); - } - - /** - * Returns an obfuscated equivalent of a type. - * - * @param type A type. - * @return an obfuscated equivalent of the type. - */ - static Type map(Type type) { - // void or primitive - if (!CustomLoadingPlugin.isObfuscated() || (type.getSort() < 9)) return type; - - // array - if (type.getSort() == 9) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < type.getDimensions(); i++) { - sb.append("["); - } - boolean isPrimitiveArray = type.getSort() < 9; - if (!isPrimitiveArray) sb.append("L"); - sb.append(map(type.getElementType()).getInternalName()); - if (!isPrimitiveArray) sb.append(";"); - return Type.getType(sb.toString()); - } else if (type.getSort() == 10) { - String unmappedName = FMLDeobfuscatingRemapper.INSTANCE.map(type.getInternalName()); - return Type.getType("L" + unmappedName + ";"); - } else { - throw new IllegalArgumentException("Can not map method type!"); - } - } -} diff --git a/src/main/java/net/tclproject/mysteriumlib/asm/common/MinecraftMetaReader.java b/src/main/java/net/tclproject/mysteriumlib/asm/common/MinecraftMetaReader.java deleted file mode 100644 index 90a433f..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/asm/common/MinecraftMetaReader.java +++ /dev/null @@ -1,172 +0,0 @@ -package net.tclproject.mysteriumlib.asm.common; - -import java.io.IOException; -import java.lang.reflect.Method; - -import net.minecraft.launchwrapper.Launch; -import net.minecraft.launchwrapper.LaunchClassLoader; -import net.tclproject.mysteriumlib.asm.core.MetaReader; - -import org.apache.logging.log4j.Level; - -import cpw.mods.fml.common.FMLLog; -import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; - -/** An add-on to MetaReader for getting information related to minecraft obfuscation and deobfuscation. */ -public class MinecraftMetaReader extends MetaReader { - - /** The runTransformers method inside the LaunchClassLoader class. */ - private static Method runTransformers; - - static { - try { - runTransformers = LaunchClassLoader.class.getDeclaredMethod( - "runTransformers", // get the runTransformers method frm LaunchClassLoader - String.class, - String.class, - byte[].class); // arguments of runTransformers - runTransformers.setAccessible(true); // make it ignore access checks - } catch (Exception e) { - FMLLog.log( - "Mysterium Patches", - Level.ERROR, - "Error occured when making runTransformers in LaunchClassLoader usable."); - FMLLog.log( - "Mysterium Patches", - Level.ERROR, - "THIS IS MOST LIKELY HAPPENING BECAUSE OF MOD CONFLICTS. PLEASE CONTACT ME TO LET ME KNOW."); - FMLLog.log("Mysterium Patches", Level.ERROR, e.getMessage()); - } - } - - /** - * Returns the deobfuscated class (bytes) from a deobfuscated name in an obfuscated environment. - * - * @param name The unobfuscated class name. - * @return The unobfuscated class (bytes). - */ - @Override - public byte[] classToBytes(String name) throws IOException { - byte[] bytes = super.classToBytes(getRelevantName(name.replace('.', '/'))); - return deobfuscateClass(name, bytes); - } - - /** - * Checks if an srg-named method is the equivalent of an mcp-named method. - *

- * NOTE: It does not check the mcp vs srg descriptors, it only checks if they are the same which in most cases will - * not be the case if it's srg vs mcp. - * - * @param obfuscatedName the obfuscated (srg) name. - * @param sourceDescriptor the descriptor of the first method. - * @param mcpName the deobfuscated (mcp) name. - * @param targetDescriptor the descriptor of the second method. - * @return If they are the same method. - */ - @Override - public boolean checkSameMethod(String obfuscatedName, String sourceDescriptor, String mcpName, - String targetDescriptor) { - return checkSameMethod(obfuscatedName, mcpName) && sourceDescriptor.equals(targetDescriptor); - } - - // TODO: make a method for the automatic generation of obfuscated/non-obfuscated descriptors - - /** - * Forge and others can create methods at runtime. - * This method gets a method reference, even if the target method is runtime-generated - * by other mods or forge. - * - * @param ownerClass the class inside which the target method is located. - * @param methodName the name of the target method. - * @param descriptor the descriptor of the target method. - * @return A MethodReference for the method or null if the method is not found. - */ - @Override - public MethodReference getMethodReferenceASM(String ownerClass, String methodName, String descriptor) - throws IOException { - FindMethodClassVisitor classVisitor = new FindMethodClassVisitor(methodName, descriptor); - byte[] bytes = getTransformedBytes(ownerClass); - acceptVisitor(bytes, classVisitor); - return classVisitor.found - ? new MethodReference(ownerClass, classVisitor.targetName, classVisitor.targetDescriptor) - : null; - } - - /** - * Returns a deobfuscated version of a class. - * - * @param className the name of the class. - * @param bytes the class (bytes). - * @return the deobfuscated class (bytes). - */ - public static byte[] deobfuscateClass(String className, byte[] bytes) { - if (CustomLoadingPlugin.getDeobfuscationTransformer() != null) { - bytes = CustomLoadingPlugin.getDeobfuscationTransformer() - .transform(className, className, bytes); - } - return bytes; - } - - /** - * Gets the modified class from a deobfuscated class name. - * The modified class is the class with all the fixes, mixins, asm etc. - * applied to it from everywhere. - * - * @param name The deobfuscated class name. - * @return bytes the class (bytes) with all the changes applied to it. - */ - public static byte[] getTransformedBytes(String name) throws IOException { - String className = getRelevantName(name); - byte[] bytes = Launch.classLoader.getClassBytes(className); - if (bytes == null) { - throw new RuntimeException("The byte representation of " + className + " cannot be found."); - } - try { - bytes = (byte[]) runTransformers.invoke(Launch.classLoader, className, name, bytes); - } catch (Exception e) { - FMLLog.log( - "Mysterium Patches", - Level.ERROR, - "Error occured when making runTransformers in LaunchClassLoader usable."); - FMLLog.log( - "Mysterium Patches", - Level.ERROR, - "THIS IS MOST LIKELY HAPPENING BECAUSE OF MOD CONFLICTS. PLEASE CONTACT ME TO LET ME KNOW."); - FMLLog.log("Mysterium Patches", Level.ERROR, e.getMessage()); - } - return bytes; - } - - /** - * Returns an obfuscated name from a deobfuscated one if run in an obfuscated environment. - * If run in a deobfuscated environment, the name stays the same. - * - * @param deobfName the deobfuscated name. - * @return the name that is usable in the environment this method is called. - */ - public static String getRelevantName(String deobfName) { - if (CustomLoadingPlugin.isObfuscated()) { - return FMLDeobfuscatingRemapper.INSTANCE.unmap(deobfName); - } - return deobfName; - } - - /** - * Checks if two method names are the same, accounting for if the first name is obfuscated. - * - * @param srgName the name of the method that might be obfuscated. - * @param mcpName a deobfuscated method name. - * @return if the two names are the same. - */ - public static boolean checkSameMethod(String srgName, String mcpName) { - if (CustomLoadingPlugin.isObfuscated() && CustomClassTransformer.instance != null) { - int methodId = CustomClassTransformer.getMethodIndex(srgName); - String remappedName = CustomClassTransformer.instance.getMethodNames() - .get(methodId); - if (remappedName != null && remappedName.equals(mcpName)) { - return true; - } - } - return srgName.equals(mcpName); - } -} diff --git a/src/main/java/net/tclproject/mysteriumlib/asm/core/ASMFix.java b/src/main/java/net/tclproject/mysteriumlib/asm/core/ASMFix.java deleted file mode 100644 index de11c8e..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/asm/core/ASMFix.java +++ /dev/null @@ -1,1099 +0,0 @@ -package net.tclproject.mysteriumlib.asm.core; - -import static org.objectweb.asm.Opcodes.*; -import static org.objectweb.asm.Type.*; - -import java.util.ArrayList; -import java.util.List; - -import net.tclproject.mysteriumlib.asm.annotations.EnumReturnSetting; -import net.tclproject.mysteriumlib.asm.annotations.EnumReturnType; -import net.tclproject.mysteriumlib.asm.annotations.FixOrder; -import net.tclproject.mysteriumlib.asm.core.FixInserterFactory.OnExit; - -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; - -/** - * The main ASM class, responsible for the insertion of a fix into a method. - * PLEASE DO NOT MODIFY ANY OF THE FIELDS INSIDE MANUALLY, USE THE BUILDER AND IT'S SETTERS - * OR YOU RISK BREAKING THINGS. - *

- * --*-- - *

- * Terms used: - *

- * Fix - the execution of your static code from minecraft's, forge's, or another mod's code - *

- * Target Method - method, inside which you put your fix - *

- * Target Class - the class that has the method inside which you put your fix - *

- * Fix Method - your static method that gets called from other's code - *

- * Fix Class (Class with fixes) - the class, inside which your fix method/s is located. - */ -public class ASMFix implements Cloneable, Comparable { - - // Variables - - /** List of arguments the target method takes. */ - public List targetMethodArguments = new ArrayList<>(2); - public List transmittableVariableIndexes = new ArrayList<>(2); - /** List of arguments the fix method takes. */ - public List fixMethodArguments = new ArrayList<>(2); - - /** The return type of the fix method. */ - public Type fixMethodReturnType = Type.VOID_TYPE; - /** The return type of the target method. If it isn't specified, isn't verified. */ - public Type targetMethodReturnType; - - /** The order in which the fixes for the same target method will be inserted. */ - public FixOrder priority = FixOrder.USUAL; - - /** What the fix method returns. e.g. another method, a constant integer, etc. */ - EnumReturnType EnumReturnType = net.tclproject.mysteriumlib.asm.annotations.EnumReturnType.VOID; - - /** In what situations the fix method returns something. */ - EnumReturnSetting EnumReturnSetting = net.tclproject.mysteriumlib.asm.annotations.EnumReturnSetting.NEVER; - - /** The fix inserter factory used. */ - public FixInserterFactory injectorFactory = ON_ENTER_FACTORY; - /** An instance of a factory that makes fix inserters that insert fixes on the start of the method. */ - public static final FixInserterFactory ON_ENTER_FACTORY = FixInserterFactory.OnEnter.INSTANCE; - /** An instance of a factory that makes fix inserters that insert fixes on the end of the method. */ - public static final FixInserterFactory ON_EXIT_FACTORY = FixInserterFactory.OnExit.INSTANCE; - - /** The primitive value that is to be always returned, if specified. */ - private Object primitiveAlwaysReturned; - - /** The name of the class that holds the target method. */ - public String targetClassName; - /** The target method's name. */ - public String targetMethodName; - /** The class with the fix method from which this fix has been created. */ - public String classWithFixes; - /** The fix method's name. */ - public String fixMethodName; - /** The target method's descriptor. Can be without the return type. */ - public String targetMethodDescriptor; - /** The fix method's descriptor. */ - public String fixMethodDescriptor; - /** - * The return method's name. The return method is the method the return value of which is passed if returnType is - * ANOTHER_METHOD_RETURN_VALUE. - */ - public String returnMethodName; - /** - * The return method's descriptor. Can be without the return type. The return method is the method the return value - * of which is passed if returnType is ANOTHER_METHOD_RETURN_VALUE. - */ - public String returnMethodDescriptor; - /** If the value from return is passed to the fix method. */ - public boolean hasReturnedValueParameter; - /** If the fix needs to create a method to be inserted into. */ - public boolean createMethod; - /** If the game should crash if the inserting fails. */ - public boolean isFatal; - - // Methods - - /** Getter for targetClassName. */ - public String getTargetClassName() { - return targetClassName; - } - - /** Getter for targetClassName with '.'s replaced with '/'s. */ - public String getTargetClassInternalName() { - return targetClassName.replace('.', '/'); - } - - /** Getter for classWithFixes with '.'s replaced with '/'s. */ - public String getClassWithFixesInternalName() { - return classWithFixes.replace('.', '/'); - } - - /** Returns if the method is the target of this ASMFix. */ - public boolean isTheTarget(String name, String descriptor) { - return (targetMethodReturnType == null && descriptor.startsWith(targetMethodDescriptor) - || descriptor.equals(targetMethodDescriptor)) && name.equals(targetMethodName); - } - - /** Getter for createMethod. */ - public boolean getCreateMethod() { - return createMethod; - } - - /** Getter for isFatal. */ - public boolean isMandatory() { - return isFatal; - } - - /** Getter for injectorFactory. */ - public FixInserterFactory getInjectorFactory() { - return injectorFactory; - } - - /** - * Returns if a fix method is stored inside this ASMFix (in other words, if fixMethodName != null && classWithFixes - * != null). - */ - public boolean hasFixMethod() { - return fixMethodName != null && classWithFixes != null; - } - - /** Creates a method in the target class. */ - public void createMethod(FixInserterClassVisitor classVisitor) { - MetaReader.MethodReference superMethod = classVisitor.transformer.metaReader - .findMethod(getTargetClassInternalName(), targetMethodName, targetMethodDescriptor); - // We're using the name of the super method to avoid any errors - MethodVisitor methodVisitor = classVisitor.visitMethod( - Opcodes.ACC_PUBLIC, - superMethod == null ? targetMethodName : superMethod.name, - targetMethodDescriptor, - null, - null); - if (methodVisitor instanceof FixInserter) { // If the method is, indeed, to be created - FixInserter inserter = (FixInserter) methodVisitor; - inserter.visitCode(); - inserter.visitLabel(new Label()); - if (superMethod == null) { - insertPushDefaultReturnValue(inserter, targetMethodReturnType); - } else { - insertSuperCall(inserter, superMethod); - } - insertReturn(inserter, targetMethodReturnType); - inserter.visitLabel(new Label()); - inserter.visitMaxs(0, 0); - inserter.visitEnd(); - } else { - throw new IllegalArgumentException( - "A fix inserter hasn't been created for this method, which means the method isn't to be fixed. Likely, something is broken."); - } - } - - /** - * Inserts the fix needed. - * - * @param inserter the FixInserter that has called this method. - */ - public void insertFix(FixInserter inserter) { - Type targetMethodReturnType = inserter.methodType.getReturnType(); - - // Store the value that has been passed into return to a local variable - int returnLocalIndex = -1; - if (hasReturnedValueParameter) { - returnLocalIndex = inserter.newLocal(targetMethodReturnType); - inserter.visitVarInsn(targetMethodReturnType.getOpcode(54), returnLocalIndex); // storeLocal - } - - // insert a call to the fix method - int fixResultLocalIndex = -1; - if (hasFixMethod()) { - insertInvokeStatic(inserter, returnLocalIndex, fixMethodName, fixMethodDescriptor); - - if (EnumReturnType == net.tclproject.mysteriumlib.asm.annotations.EnumReturnType.FIX_METHOD_RETURN_VALUE - || EnumReturnSetting.conditionRequiredToReturn) { - fixResultLocalIndex = inserter.newLocal(fixMethodReturnType); - inserter.visitVarInsn(fixMethodReturnType.getOpcode(54), fixResultLocalIndex); // storeLocal - } - } - - // insert return - if (EnumReturnSetting != net.tclproject.mysteriumlib.asm.annotations.EnumReturnSetting.NEVER) { - Label label = inserter.newLabel(); - - // insert a GOTO to label after return has been called - if (EnumReturnSetting != net.tclproject.mysteriumlib.asm.annotations.EnumReturnSetting.ALWAYS) { - inserter.visitVarInsn(fixMethodReturnType.getOpcode(21), fixResultLocalIndex); // loadLocal - if (EnumReturnSetting == net.tclproject.mysteriumlib.asm.annotations.EnumReturnSetting.ON_TRUE) { - inserter.visitJumpInsn(IFEQ, label); - } else if (EnumReturnSetting == net.tclproject.mysteriumlib.asm.annotations.EnumReturnSetting.ON_NULL) { - inserter.visitJumpInsn(IFNONNULL, label); - } else if (EnumReturnSetting - == net.tclproject.mysteriumlib.asm.annotations.EnumReturnSetting.ON_NOT_NULL) { - inserter.visitJumpInsn(IFNULL, label); - } - } - - // insert the value that has to be returned into the stack - if (EnumReturnType == net.tclproject.mysteriumlib.asm.annotations.EnumReturnType.NULL) { - inserter.visitInsn(Opcodes.ACONST_NULL); - } else - if (EnumReturnType == net.tclproject.mysteriumlib.asm.annotations.EnumReturnType.PRIMITIVE_CONSTANT) { - inserter.visitLdcInsn(primitiveAlwaysReturned); - } else if (EnumReturnType - == net.tclproject.mysteriumlib.asm.annotations.EnumReturnType.FIX_METHOD_RETURN_VALUE) { - inserter.visitVarInsn(fixMethodReturnType.getOpcode(21), fixResultLocalIndex); // loadLocal - } else if (EnumReturnType - == net.tclproject.mysteriumlib.asm.annotations.EnumReturnType.ANOTHER_METHOD_RETURN_VALUE) { - String returnMethodDescription = this.returnMethodDescriptor; - // If the needed target method's return type hasn't been specified, adding it to the - // descriptor - if (returnMethodDescription.endsWith(")")) { - returnMethodDescription += targetMethodReturnType.getDescriptor(); - } - insertInvokeStatic(inserter, returnLocalIndex, returnMethodName, returnMethodDescription); - } - - // call return - insertReturn(inserter, targetMethodReturnType); - - // inserting a label, to which GOTO will jump - inserter.visitLabel(label); - } - - // putting the returned value into the stack - if (hasReturnedValueParameter) { - insertLoad(inserter, targetMethodReturnType, returnLocalIndex); - } - } - - /** - * Inserts a load instruction for the type passed. A load instruction loads a variable from the local variable table - * onto the stack. - * - * @param inserter Inserter that is inserting this fix. - * @param parameterType The type of variable to be loaded. - * @param variableIndex The index of the variable in the table. - */ - public void insertLoad(FixInserter inserter, Type parameterType, int variableIndex) { - int opcode; - if (parameterType == INT_TYPE || parameterType == BYTE_TYPE - || parameterType == CHAR_TYPE - || parameterType == BOOLEAN_TYPE - || parameterType == SHORT_TYPE) { - opcode = ILOAD; - } else if (parameterType == LONG_TYPE) { - opcode = LLOAD; - } else if (parameterType == FLOAT_TYPE) { - opcode = FLOAD; - } else if (parameterType == DOUBLE_TYPE) { - opcode = DLOAD; - } else { - opcode = ALOAD; - } - inserter.visitVarInsn(opcode, variableIndex); - } - - /** - * Inserts a call to super(). - * - * @param inserter Inserter that is inserting this fix. - */ - public void insertSuperCall(FixInserter inserter, MetaReader.MethodReference method) { - int variableIndex = 0; - for (int i = 0; i <= targetMethodArguments.size(); i++) { - Type argumentType = i == 0 ? TypeUtils.getType(targetClassName) : targetMethodArguments.get(i - 1); - insertLoad(inserter, argumentType, variableIndex); - if (argumentType.getSort() == Type.DOUBLE || argumentType.getSort() == Type.LONG) { // if it is a long or a - // double, it occupies - // two variables, - // therefore we need to - // insert the load for - // the one two later, - // skipping one - variableIndex += 2; - } else { - variableIndex++; - } - } - inserter.visitMethodInsn(INVOKESPECIAL, method.owner, method.name, method.descriptor, false); - } - - /** - * Inserts an instruction to push the target method return type's default value onto the stack, e.g. int -> 0, - * object -> null - * - * @param inserter Inserter that is inserting this fix. - * @param targetMethodReturnType the return type of the target method. - */ - public void insertPushDefaultReturnValue(FixInserter inserter, Type targetMethodReturnType) { - switch (targetMethodReturnType.getSort()) { - case Type.VOID: - break; - case Type.BOOLEAN: - case Type.CHAR: - case Type.BYTE: - case Type.SHORT: - case Type.INT: - inserter.visitInsn(Opcodes.ICONST_0); - break; - case Type.FLOAT: - inserter.visitInsn(Opcodes.FCONST_0); - break; - case Type.LONG: - inserter.visitInsn(Opcodes.LCONST_0); - break; - case Type.DOUBLE: - inserter.visitInsn(Opcodes.DCONST_0); - break; - default: - inserter.visitInsn(Opcodes.ACONST_NULL); - break; - } - } - - /** - * Inserts a return instruction. - * - * @param inserter Inserter that is inserting this fix. - * @param targetMethodReturnType the return type of the target method. - */ - public void insertReturn(FixInserter inserter, Type targetMethodReturnType) { - if (targetMethodReturnType == INT_TYPE || targetMethodReturnType == SHORT_TYPE - || targetMethodReturnType == BOOLEAN_TYPE - || targetMethodReturnType == BYTE_TYPE - || targetMethodReturnType == CHAR_TYPE) { - inserter.visitInsn(IRETURN); - } else if (targetMethodReturnType == LONG_TYPE) { - inserter.visitInsn(LRETURN); - } else if (targetMethodReturnType == FLOAT_TYPE) { - inserter.visitInsn(FRETURN); - } else if (targetMethodReturnType == DOUBLE_TYPE) { - inserter.visitInsn(DRETURN); - } else if (targetMethodReturnType == VOID_TYPE) { - inserter.visitInsn(RETURN); - } else { - inserter.visitInsn(ARETURN); - } - } - - /** - * Inserts an instruction to call a static method. This instruction is used to insert a call to the fix methods - * inside the target methods. - * - * @param inserter Inserter that is inserting this fix. - * @param indexOfReturnArgument Index at which the argument for passing the return value is. - */ - public void insertInvokeStatic(FixInserter inserter, int indexOfReturnArgument, String name, String descriptor) { - for (int i = 0; i < fixMethodArguments.size(); i++) { // Iterate through all the fix method's arguments - Type parameterType = fixMethodArguments.get(i); - int variableIndex = transmittableVariableIndexes.get(i); - if (inserter.isStatic) { - // if we need to pass this from a static method, we pass null - if (variableIndex == 0) { - inserter.visitInsn(Opcodes.ACONST_NULL); - continue; - } - // otherwise, move the index of the local variable - if (variableIndex > 0) variableIndex--; - } - if (variableIndex == -1) variableIndex = indexOfReturnArgument; - insertLoad(inserter, parameterType, variableIndex); - } - - inserter.visitMethodInsn(INVOKESTATIC, getClassWithFixesInternalName(), name, descriptor, false); // instruction, - // owner - // class, - // method - // name, - // method - // descriptor, - // if the - // owner class - // is an - // interface - } - - /** Gets the target method's full name, as class#method+descriptor. */ - public String getFullTargetMethodName() { - return targetClassName + '#' + targetMethodName + targetMethodDescriptor; - } - - // already has good java docs - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("ASMFix: "); - - sb.append(targetClassName) - .append('#') - .append(targetMethodName); - sb.append(targetMethodDescriptor); - sb.append(" -> "); - sb.append(classWithFixes) - .append('#') - .append(fixMethodName); - sb.append(fixMethodDescriptor); - - sb.append(", EnumReturnSetting=" + EnumReturnSetting); - sb.append(", EnumReturnType=" + EnumReturnType); - if (EnumReturnType == net.tclproject.mysteriumlib.asm.annotations.EnumReturnType.PRIMITIVE_CONSTANT) - sb.append(", Constant=" + primitiveAlwaysReturned); - sb.append( - ", InjectorFactory: " + injectorFactory.getClass() - .getName()); - sb.append(", CreateMethod = " + createMethod); - - return sb.toString(); - } - - // also has good java docs, this one just compares the order at which the fixes will be inserted. 1: the priority is - // greater (HIGHEST equiv.), -1: less (LOWEST equiv.) - @Override - public int compareTo(ASMFix fix) { - if (injectorFactory.priorityReversed && fix.injectorFactory.priorityReversed) { // if both are inserted at the - // end - return priority.ordinal() > fix.priority.ordinal() ? -1 : 1; // Since priority is reversed, if our priority - // is greater (>) it is actually less (-1) - } else if (!injectorFactory.priorityReversed && !fix.injectorFactory.priorityReversed) { // if both are inserted - // at the beginning - return priority.ordinal() > fix.priority.ordinal() ? 1 : -1; // If our priority is greater (>), it's greater - // (1) - } else { - return injectorFactory.priorityReversed ? 1 : -1; // If both are inserted at different places: If we are - // inserted at the end, we have greater priority. - } - } - - /** - * A factory for a builder object. - * - * @return a new builder for a new ASMFix object. - */ - public static Builder newBuilder() { - return new ASMFix().new Builder(); - } - - /** ASMFix with additional setters. */ - public class Builder extends ASMFix { - - private Builder() { - - } - - /** - * -----[NECESSARY TO CALL THIS FOR EVERY BUILDER]----- - *

- * Defines the name of the class, into which the fix will be inserted. - * - * @param name The full name and path of the class, e.g. net.minecraft.world.World - * @return this - */ - public Builder setTargetClass(String name) { - ASMFix.this.targetClassName = name; - return this; - } - - /** - * -----[NECESSARY TO CALL THIS FOR EVERY BUILDER]----- - *

- * Defines the name of the method, into which the fix will be inserted. - * If fixing a constructor is needed, the method name is . - * - * @param name Name of the target method, e.g. getBlockId. - * @return this - */ - public Builder setTargetMethod(String name) { - ASMFix.this.targetMethodName = name; - return this; - } - - /** - * -----[NECESSARY TO CALL THIS IF THE TARGET METHOD HAS ARGUMENTS]----- - *

- * Adds one or more arguments to the list of arguments of the target method. - *

- * Those arguments are used to create the descriptor of the target method. - * In order to precisely find the target method, the name by itself is not enough, as methods with the same name - * but different arguments exist. - *

- * Example of use: - *

- * import static net.tclproject.mysteriumlib.asm.core.TypeUtils.* - *

- * //... - *

- * addTargetMethodParameters(Type.INT_TYPE) - *

- * Type worldType = getType("net.minecraft.world.World") - *

- * Type playerType = getType("net.minecraft.entity.player.EntityPlayer") - *

- * addTargetMethodParameters(worldType, playerType, playerType) - * - * @param argumentTypes The types of arguments of the target method - * @see TypeUtils - * @return this - */ - public Builder addTargetMethodParameters(Type... argumentTypes) { - for (Type type : argumentTypes) { - ASMFix.this.targetMethodArguments.add(type); - } - return this; - } - - /** - * Adds one or more arguments to the list of arguments of the target method. - * This is an abstraction layer for addTargetMethodParameters(Type... parameterTypes), that resolves the types - * from names. - *

- * - * @param argumentTypeNames Names of classes of the arguments of the target method, e.g. - * net.minecraft.world.World - * @return this - */ - public Builder addTargetMethodParameters(String... argumentTypeNames) { - Type[] types = new Type[argumentTypeNames.length]; - for (int i = 0; i < argumentTypeNames.length; i++) { - types[i] = TypeUtils.getType(argumentTypeNames[i]); - } - return addTargetMethodParameters(types); - } - - /** - * Specifies the return type of the target method. - * The return type is used to create the descriptor of the target method. - * In order to precisely find the target method, the name by itself is not enough, the descriptor is also - * needed. - * By default, the fix inserts into all methods with the right name and arguments. - * - * @param returnType The return type of the target method. - * @see TypeUtils - * @return this - */ - public Builder setTargetMethodReturnType(Type returnType) { - ASMFix.this.targetMethodReturnType = returnType; - return this; - } - - /** - * Specifies the return type of the target method. - * This is an abstraction layer for setTargetMethodReturnType(Type returnType), that resolves the type from it's - * name. - * - * @param returnType Name of the class, instance of which the target method returns. - * @return this - */ - public Builder setTargetMethodReturnType(String returnType) { - return setTargetMethodReturnType(TypeUtils.getType(returnType)); - } - - /** - * -----[NECESSARY TO CALL THIS IF A FULL FIX IS NEEDED (NOT ONLY AlwaysReturned)]----- - *

- * Specifies the name of the class with the fix method. - * - * @param name The full name of the class, e.g. com.example.examplemod.asm.MyFixes - * @return this - */ - public Builder setFixesClass(String name) { - ASMFix.this.classWithFixes = name; - return this; - } - - // TODO: Add a check - /** - * -----[NECESSARY TO CALL THIS IF A FULL FIX IS NEEDED (NOT ONLY AlwaysReturned)]----- - *

- * Specifies the name of the fix method. - * The fix method MUST be static, and there is no check to verify that. Be careful, please. - * - * @param name The name of the fix method, e.g. myFix - * @return this - */ - public Builder setFixMethod(String name) { - ASMFix.this.fixMethodName = name; - return this; - } - - /** - * -----[NECESSARY TO CALL THIS IF THE FIX METHOD HAS ARGUMENTS]----- - *

- * Adds an argument to the list of arguments of the fix method. - * In bytecode, the names of the arguments aren't saved. Instead, the use of indexes is needed. - *

- * For example, in the class EntityLivingBase there is a method: attackEntityFrom(DamageSource damageSource, - * float damage). - * Inside it, these indexes will be used: - *

- * 1 - damageSource - * 2 - damage - *

- * IMPORTANT: longs and doubles take up two spaces. - * Theoretically, not only the original aguments can be passed in to the fix method but also local variables, - * but their indexes will be way harder to calculate. - *

- * For example, in the class Entity there is a method: setPosition(double x, double y, double z). - * Inside it, these indexes will be used: - *

- * 1 - x - * 2 - пропущено - * 3 - y - * 4 - пропущено - * 5 - z - * 6 - пропущено - *

- * The code of this method: - *

- * //... - * float f = ...; - * float f1 = ...; - * //... - *

- * In this case, the index of f will be 7, and f1: 8. - *

- * If the target method is static, you don't start counting the indexes from 0, - * The numbers will be moved automatically. - * - * @param parameterType Type of argument of the fix method - * @param variableIndex Index of the variable passed to the fix method - * @throws IllegalStateException If the name of the fix method or class isn't specified - * @return this - */ - public Builder addFixMethodParameter(Type parameterType, int variableIndex) { - if (!ASMFix.this.hasFixMethod()) { - throw new IllegalStateException( - "Fix method is not specified, can't append argument to its arguments list."); - } - ASMFix.this.fixMethodArguments.add(parameterType); - ASMFix.this.transmittableVariableIndexes.add(variableIndex); - return this; - } - - /** - * Adds an argument to the list of arguments of the fix method. - * This is an abstraction layer for addFixMethodParameter(Type parameterType, int variableIndex), that resolves - * the type from it's name. - * - * @param parameterTypeName Name of the type of the argument, e.g. net.minecraft.world.World - * @param variableIndex Index of the variable passed to the fix method - * @return this - */ - public Builder addFixMethodParameter(String parameterTypeName, int variableIndex) { - return addFixMethodParameter(TypeUtils.getType(parameterTypeName), variableIndex); - } - - /** - * Adds the target class to the fix method's list of arguments to later be passed this. - * If the target method is static, null will be passed. - * - * @throws IllegalStateException If the fix method is not specified - * @return this - */ - public Builder addThisToFixMethodParameters() { - if (!ASMFix.this.hasFixMethod()) { - throw new IllegalStateException( - "Fix method is not specified, can't append argument to its arguments list."); - } - ASMFix.this.fixMethodArguments.add(TypeUtils.getType(ASMFix.this.targetClassName)); - ASMFix.this.transmittableVariableIndexes.add(0); - return this; - } - - /** - * Adds the return type of the target method to the fix method's list of arguments to later be passed the - * returned value. - * In other words, it's the top value on the stack when the fix method is called. - *

- * e.g. this is the code of a method: - *

- * int foo = bar(); - *

- * return foo; - *

- * Or this is the code of the method: - *

- * return bar() - *

- * In both cases we can pass the fix method the returned value before return is called, because of how bytecode - * works. - * - * @throws IllegalStateException if the target method returns void - * @throws IllegalStateException if the fix method isn't specified - * @return this - */ - public Builder addReturnedValueToFixMethodParameters() { - if (!ASMFix.this.hasFixMethod()) { - throw new IllegalStateException( - "Fix method is not specified, can't append argument to its arguments list."); - } - if (ASMFix.this.targetMethodReturnType == Type.VOID_TYPE) { - throw new IllegalStateException( - "Target method's return type is void so it doesn't make sense to transmit it's return value to the fix method, as frankly, there is none."); - } - ASMFix.this.fixMethodArguments.add(ASMFix.this.targetMethodReturnType); - ASMFix.this.transmittableVariableIndexes.add(-1); - ASMFix.this.hasReturnedValueParameter = true; - return this; - } - - /** - * Specifies a setting, in which, return is called after the fix method has been. - * By default, return isn't called at all. - *

- * Besides that, this method changes the return type of the fix method: - *

- * NEVER -> void - * ALWAYS -> void - * ON_TRUE -> boolean - * ON_NULL -> Object - * ON_NOT_NULL -> Object - * - * @param setting The condition, if which, it will exit from the target method after the fix method has been - * called. - * @throws IllegalArgumentException if setting == ON_TRUE, ON_NULL or ON_NOT_NULL, but the fix method isn't - * specified. - * @see EnumReturnSetting - * @return this - */ - public Builder setReturnSetting(EnumReturnSetting setting) { - if (setting.conditionRequiredToReturn && ASMFix.this.fixMethodName == null) { - throw new IllegalArgumentException( - "Fix method isn't specified, can't use a return condition that depends on it."); - } - - ASMFix.this.EnumReturnSetting = setting; - Type returnType; - switch (setting) { - case NEVER: - case ALWAYS: - returnType = VOID_TYPE; - break; - case ON_TRUE: - returnType = BOOLEAN_TYPE; - break; - default: - returnType = getType(Object.class); - break; - } - ASMFix.this.fixMethodReturnType = returnType; - return this; - } - - /** - * -----[NECESSARY TO CALL THIS IF THE TARGET METHOD DOESN'T RETURN void AND setReturnSetting HAS BEEN - * CALLED]----- - *

- * Specifies the type that gets returned after the fix method has been called. - * Call this after setReturnSetting. - * By default, void is returned. - *

- * Besides that, if value == EnumReturnType.FIX_RETURN_VALUE, this method changes the return type - * of the fix method to the type, specified in setTargetMethodReturnType() - * - * @param type the return type, e.g. EnumReturnType.FIX_RETURN_VALUE, PRIMITIVE_CONSTANT etc. - * @throws IllegalStateException if EnumReturnSetting == NEVER it doesn't make sense to specify the return - * type, since return doesn't get called. - * @throws IllegalArgumentException if value == EnumReturnType.FIX_RETURN_VALUE, but the return type of the - * target method is void (or setTargetMethodReturnType hasn't been called). - * It doesn't make sense to use the value that the fix method returned, if it - * returned void (it must match the type returned by the target method). - * @return this - */ - public Builder setReturnType(EnumReturnType type) { - classWithFixes = ASMFix.this.classWithFixes; - fixMethodName = ASMFix.this.fixMethodName; - if (ASMFix.this.EnumReturnSetting == net.tclproject.mysteriumlib.asm.annotations.EnumReturnSetting.NEVER) { - throw new IllegalStateException( - "Current return condition is never, so it does not make sense to specify the return value."); - } - Type returnType = ASMFix.this.targetMethodReturnType; - if (type != net.tclproject.mysteriumlib.asm.annotations.EnumReturnType.VOID && returnType == VOID_TYPE) { - throw new IllegalArgumentException( - "Target method return type is void, so it does not make sense to return anything else."); - } - if (type == net.tclproject.mysteriumlib.asm.annotations.EnumReturnType.VOID && returnType != VOID_TYPE) { - throw new IllegalArgumentException( - "Target method return type is not void, so it is impossible to return void."); - } - if (type == net.tclproject.mysteriumlib.asm.annotations.EnumReturnType.PRIMITIVE_CONSTANT - && returnType != null - && !isPrimitive(returnType)) { - throw new IllegalArgumentException( - "Target method return type isn't a primitive, so it is impossible to return one."); - } - if (type == net.tclproject.mysteriumlib.asm.annotations.EnumReturnType.NULL && returnType != null - && isPrimitive(returnType)) { - throw new IllegalArgumentException( - "Target method return type is a primitive, so it is impossible to return null."); - } - if (type == net.tclproject.mysteriumlib.asm.annotations.EnumReturnType.FIX_METHOD_RETURN_VALUE - && !hasFixMethod()) { - throw new IllegalArgumentException("Fix method is not specified, can't use it's return value."); - } - - ASMFix.this.EnumReturnType = type; - if (type == net.tclproject.mysteriumlib.asm.annotations.EnumReturnType.FIX_METHOD_RETURN_VALUE) { // If the - // return - // type is - // the - // type of - // the fix - // method, - // we set - // the - // return - // type of - // the fix - // method - // to one - // of the - // target - // method. - ASMFix.this.fixMethodReturnType = ASMFix.this.targetMethodReturnType; // That is because the type must - // fit to be returned from the - // target method. - } - return this; - } - - /** - * Getter for fixMethodReturnType (In case it's hard to figure out). - * - * @return the fix method's return type. - */ - public Type getFixMethodReturnType() { - return fixMethodReturnType; - } - - /** - * Setter for fixMethodReturnType. - * - * @param type the fix method's return type. - */ - public void setFixMethodReturnType(Type type) { - ASMFix.this.fixMethodReturnType = type; - } - - /** - * Figures out if the type passed in is a primitive. - * - * @param type a type. - * @return if the type passed in is a primitive. - */ - public boolean isPrimitive(Type type) { - return type.getSort() > 0 && type.getSort() < 9; // more than 0 and less than 9 - } - - /** - * -----[NECESSARY TO CALL THIS IF setReturnType HAS BEEN CALLED AND SET TO PRIMITIVE_CONSTANT]----- - *

- * Call this after setReturnType(EnumReturnType.PRIMITIVE_CONSTANT). - * Specifies the primitive, that will always be returned. - * - * @param object Object, class of which represents the primitive, e.g. int -> Integer. - * @throws IllegalStateException If specified return type isn't PRIMITIVE_CONSTANT - * @throws IllegalArgumentException If the class of the passed in value isn't a wrapper for a primitive - * @return this - */ - public Builder setPrimitiveAlwaysReturned(Object object) { - if (ASMFix.this.EnumReturnType - != net.tclproject.mysteriumlib.asm.annotations.EnumReturnType.PRIMITIVE_CONSTANT) { - throw new IllegalStateException( - "Return type is not PRIMITIVE_CONSTANT, so it doesn't make sense to specify that constant."); - } - Type returnType = ASMFix.this.targetMethodReturnType; - if (returnType == BOOLEAN_TYPE && !(object instanceof Boolean) - || returnType == CHAR_TYPE && !(object instanceof Character) - || returnType == BYTE_TYPE && !(object instanceof Byte) - || returnType == SHORT_TYPE && !(object instanceof Short) - || returnType == INT_TYPE && !(object instanceof Integer) - || returnType == LONG_TYPE && !(object instanceof Long) - || returnType == FLOAT_TYPE && !(object instanceof Float) - || returnType == DOUBLE_TYPE && !(object instanceof Double)) { - throw new IllegalArgumentException( - "Given object class does not match the target method's return type."); - } - - ASMFix.this.primitiveAlwaysReturned = object; - return this; - } - - /** - * -----[NECESSARY TO CALL THIS IF setReturnType HAS BEEN CALLED AND SET TO ANOTHER_METHOD_RETURN_METHOD]----- - *

- * Call this after setReturnType(EnumReturnType.ANOTHER_METHOD_RETURN_VALUE). - * Specifies the method, the return value of which will be returned. - * - * @param name the method's name - * @throws IllegalStateException if the return type isn't ANOTHER_METHOD_RETURN_VALUE - * @return this - */ - public Builder setReturnMethod(String name) { - if (ASMFix.this.EnumReturnType - != net.tclproject.mysteriumlib.asm.annotations.EnumReturnType.ANOTHER_METHOD_RETURN_VALUE) { - throw new IllegalStateException( - "Return type is not ANOTHER_METHOD_RETURN_VALUE, so it does not make sence to specify that method."); - } - - ASMFix.this.returnMethodName = name; - return this; - } - - /** - * Sets the factory that will specify the inserter type. - * In other words, specifies, if the fix will be inserted at the start (ASMFix.ON_ENTER_FACTORY) or end - * (ON_EXIT_FACTORY) of a method. If you need OnLine, create your own factory. - * - * @param factory Factory, creating the inserter for this fix - * @return this - */ - public Builder setInjectorFactory(FixInserterFactory factory) { - ASMFix.this.injectorFactory = factory; - return this; - } - - /** - * Sets the priority of inserting this fix. - * Fixes with higher priority will be inserted first. - * - * @return this - */ - public Builder setPriority(FixOrder priority) { - ASMFix.this.priority = priority; - return this; - } - - // TODO: Create a way to actually have the fix method called inside the newly created method. - /** - * Setter for createMethod. - * NOTE: The method body is a call to super() if it's an override, or only the return statement otherwise. - * - * @return this - */ - public Builder setCreateMethod(boolean createMethod) { - ASMFix.this.createMethod = createMethod; - return this; - } - - /** - * Setter for isFatal. (if a fix with isFatal == true fails, the game crashes) - * - * @return this - */ - public Builder setFatal(boolean isMandatory) { - ASMFix.this.isFatal = isMandatory; - return this; - } - - /** - * Builds a method descriptor from the return type and arguments. - * - * @param returnType the return type of the method. - * @param argumentTypes the argument types of the method. - * @return a string method descriptor. - */ - private String getMethodDescriptor(Type returnType, List argumentTypes) { - Type[] paramTypesArray = argumentTypes.toArray(new Type[0]); - if (returnType == null) { - String voidDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, paramTypesArray); - return voidDescriptor.substring(0, voidDescriptor.length() - 1); - } else { - return Type.getMethodDescriptor(returnType, paramTypesArray); - } - } - - /** - * Creates an ASMFix from the specified parameters. - * - * @return The ASMFix. - * @throws IllegalStateException If one or more of the necessary methods hasn't been called. - */ - public ASMFix build() { - ASMFix fix = ASMFix.this; - - if (fix.createMethod && fix.targetMethodReturnType == null) { - fix.targetMethodReturnType = fix.fixMethodReturnType; // If we're to create a method, it's return type - // is the one of the fix method - } - fix.targetMethodDescriptor = getMethodDescriptor(fix.targetMethodReturnType, fix.targetMethodArguments); // Creates - // the - // target - // method - // descriptor - // out - // of - // the - // arguments - // and - // return - // type - - if (fix.hasFixMethod()) { - fix.fixMethodDescriptor = Type - .getMethodDescriptor(fix.fixMethodReturnType, fix.fixMethodArguments.toArray(new Type[0])); // If we - // have - // a - // full - // fix - // method - // specified, - // we - // create - // it's - // descriptor - // out - // of - // it's - // return - // type - // and - // arguments - } - if (fix.EnumReturnType - == net.tclproject.mysteriumlib.asm.annotations.EnumReturnType.ANOTHER_METHOD_RETURN_VALUE) { - fix.returnMethodDescriptor = getMethodDescriptor(fix.targetMethodReturnType, fix.fixMethodArguments); // If - // we're - // to - // return - // what - // a - // third - // method - // returns, - // we - // create - // it's - // desctiptor - // out - // of - // it's - // return - // type - // and - // arguments - } - - try { - fix = (ASMFix) ASMFix.this.clone(); // We turn this ASMFix builder into an ASMFix. - } catch (CloneNotSupportedException impossible) { - // It will never happen but I don't want to document the throws keyword if I put it in - } - - if (fix.targetClassName == null) { - throw new IllegalStateException( - "Target class name is not specified. Call setTargetClassName() before build()."); - } - - if (fix.targetMethodName == null) { - throw new IllegalStateException( - "Target method name is not specified. Call setTargetMethodName() before build()."); - } - - if (fix.EnumReturnType == net.tclproject.mysteriumlib.asm.annotations.EnumReturnType.PRIMITIVE_CONSTANT - && fix.primitiveAlwaysReturned == null) { - throw new IllegalStateException( - "Return type is PRIMITIVE_CONSTANT, but the constant is not specified. Call setReturnType() before build()."); - } - - if (fix.EnumReturnType - == net.tclproject.mysteriumlib.asm.annotations.EnumReturnType.ANOTHER_METHOD_RETURN_VALUE - && fix.returnMethodName == null) { - throw new IllegalStateException( - "Return type is ANOTHER_METHOD_RETURN_VALUE, but the method is not specified. Call setReturnMethod() before build()."); - } - - if (!(fix.injectorFactory instanceof OnExit) && fix.hasReturnedValueParameter) { - throw new IllegalStateException( - "Can not pass the returned value to the fix method because the fix is not inserted on exit."); - } - - return fix; - } - - } -} diff --git a/src/main/java/net/tclproject/mysteriumlib/asm/core/FileASMLib.java b/src/main/java/net/tclproject/mysteriumlib/asm/core/FileASMLib.java deleted file mode 100644 index 3326a69..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/asm/core/FileASMLib.java +++ /dev/null @@ -1,74 +0,0 @@ -package net.tclproject.mysteriumlib.asm.core; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; - -/** - * Class that enables Mysterium ASMLib to work outside of minecraft. - * It has a main method that must be executed first. - *

- * IMPORTANT: This is not a ready-to-go class, for it to work, you need to implement - * some form of interaction with the modified classes, but that is up to you. - */ -public class FileASMLib { - - /** public static void main. For now, just calls the process() method. */ - public static void main(String[] args) throws IOException { - new FileASMLib().transform(); - } - - /** Directory with the original unchanged classes. */ - File originalClasses = new File("classes"); - /** Directory with classes containing fix methods. */ - File fixesDir = new File("fixes"); - - /** - * Registers classes with fix methods, and runs the transformer through the original classes to insert the fixes. - */ - void transform() throws IOException { - TargetClassTransformer transformer = new TargetClassTransformer(); - for (File file : getFiles(".class", fixesDir)) { - transformer.registerClassWithFixes(FileUtils.readFileToByteArray(file)); - // That just registered all the classes in the 'fixes' folder as classes with fix methods. - } - for (File file : getFiles(".class", originalClasses)) { - byte[] bytes = IOUtils.toByteArray(new FileInputStream(file)); - String className = ""; // we need to get the class name e.g. com.example.ExampleMod out of a path - byte[] newBytes = transformer.transform(className, bytes); - - // IMPORTANT: Now you need to do something with newBytes[]. Perhaps, look at how forge loads modified - // minecraft classes. - } - } - - /** - * Gets a list of files in a directory and all it's subdirectories that end with a specific string. - * - * @param extension The string with which the files have to end with to match. - * @param directory the directory in which to search for files. - * @return A list of files. - */ - private static List getFiles(String extension, File directory) throws IOException { - ArrayList files = new ArrayList<>(); - File[] filesArray = directory.listFiles(); - if (filesArray != null) { - for (File file : directory.listFiles()) { - if (file.isDirectory()) { - files.addAll(getFiles(extension, file)); - } else if (file.getName() - .toLowerCase() - .endsWith(extension)) { - files.add(file); - } - } - } - return files; - } - -} diff --git a/src/main/java/net/tclproject/mysteriumlib/asm/core/FixInserter.java b/src/main/java/net/tclproject/mysteriumlib/asm/core/FixInserter.java deleted file mode 100644 index 7c6aaaf..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/asm/core/FixInserter.java +++ /dev/null @@ -1,119 +0,0 @@ -package net.tclproject.mysteriumlib.asm.core; - -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; -import org.objectweb.asm.commons.AdviceAdapter; - -/** Custom MethodVisitor that calls the insert method in ASMFix to insert fixes. */ -public abstract class FixInserter extends AdviceAdapter { - - /** The fix that this visitor needs to insert. */ - protected final ASMFix fix; - /** The class visitor that visited this method and created this MethodVisitor. */ - protected final FixInserterClassVisitor classVisitor; - /** The target method name. */ - public final String methodName; - /** The target method return type. */ - public final Type methodType; - /** If the target method is static. */ - public final boolean isStatic; - - protected FixInserter(MethodVisitor mv, int access, String name, String descriptor, ASMFix fix, - FixInserterClassVisitor classVisitor) { - super(Opcodes.ASM5, mv, access, name, descriptor); - this.fix = fix; - this.classVisitor = classVisitor; - isStatic = (access & Opcodes.ACC_STATIC) != 0; - this.methodName = name; - this.methodType = Type.getMethodType(descriptor); - } - - /** - * Inserts the fix into the bytecode. - */ - protected final void insertFix() { - if (!classVisitor.visitingFix) { - classVisitor.visitingFix = true; - fix.insertFix(this); - classVisitor.visitingFix = false; - } - } - - /** - * Inserts the fix when visiting the start of the method. - */ - public static class OnEnterInserter extends FixInserter { - - public OnEnterInserter(MethodVisitor mv, int access, String name, String desc, ASMFix fix, - FixInserterClassVisitor cv) { - super(mv, access, name, desc, fix, cv); - } - - /** - * Inserts the fix into the bytecode. - */ - @Override - protected void onMethodEnter() { - insertFix(); - } - - } - - /** - * Inserts the fix when visiting every exit from the method, except for exiting through throwing an error - * (configurable). - */ - public static class OnExitInserter extends FixInserter { - - public boolean insertOnThrows; - - public OnExitInserter(MethodVisitor mv, int access, String name, String desc, ASMFix fix, - FixInserterClassVisitor cv) { - super(mv, access, name, desc, fix, cv); - this.insertOnThrows = false; - } - - public OnExitInserter(MethodVisitor mv, int access, String name, String desc, ASMFix fix, - FixInserterClassVisitor cv, boolean insertOnThrows) { - super(mv, access, name, desc, fix, cv); - this.insertOnThrows = insertOnThrows; - } - - /** - * Inserts the fix into the bytecode. - */ - @Override - protected void onMethodExit(int opcode) { - if (opcode != Opcodes.ATHROW || this.insertOnThrows) { - insertFix(); - } - } - } - - /** - * Inserts the fix when visiting the specific line number. - */ - public static class OnLineNumberInserter extends FixInserter { - - private int lineNumber; - - public OnLineNumberInserter(MethodVisitor mv, int access, String name, String desc, ASMFix fix, - FixInserterClassVisitor cv, int lineNumber) { - super(mv, access, name, desc, fix, cv); - this.lineNumber = lineNumber; - } - - /** - * Inserts the fix into the bytecode. - */ - @Override - public void visitLineNumber(int lineVisiting, Label start) { - super.visitLineNumber(lineVisiting, start); - if (lineVisiting == this.lineNumber) { - insertFix(); - } - } - } -} diff --git a/src/main/java/net/tclproject/mysteriumlib/asm/core/FixInserterClassVisitor.java b/src/main/java/net/tclproject/mysteriumlib/asm/core/FixInserterClassVisitor.java deleted file mode 100644 index 5116d95..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/asm/core/FixInserterClassVisitor.java +++ /dev/null @@ -1,92 +0,0 @@ -package net.tclproject.mysteriumlib.asm.core; - -import java.util.ArrayList; -import java.util.List; - -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; - -/** - * Custom ClassVisitor that visits the class of a target method. Returns custom FixInserters as method visitors and - * creates new methods inside the visited class if necessary. - */ -public class FixInserterClassVisitor extends ClassVisitor { - - /** Fixes we have to insert. */ - List fixes; - - /** Fixes we have already inserted. */ - List insertedFixes = new ArrayList<>(1); - - /** If a method visitor created by this class visitor is currently in the process of inserting a fix. */ - boolean visitingFix; - - /** The TargetClassTransformer that has created this instance. */ - TargetClassTransformer transformer; - - /** Name of the superclass of the class this class is visiting. */ - String superName; - - public FixInserterClassVisitor(TargetClassTransformer transformer, ClassWriter cv, List fixs) { - super(Opcodes.ASM5, cv); - this.fixes = fixs; - this.transformer = transformer; - } - - @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - this.superName = superName; - super.visit(version, access, name, signature, superName, interfaces); - } - - /** - * Visits a method of the class but instead of returning a normal MethodVisitor returns a FixInserter from the set - * factory, if the method is to be fixed. - * - * @param access the method's access flags (see Opcodes). This parameter also indicates if the method is - * synthetic and/or deprecated. - * @param name the method's name. - * @param desc the method's descriptor (see Type). - * @param signature the method's signature. May be null if the method parameters, return type and exceptions do not - * use generic types. - * @param exceptions the internal names of the method's exception classes (see getInternalName). May be null. - * @return an object to visit the byte code of the method, or null if this class visitor is not interested in - * visiting the code of this method. - */ - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); - for (ASMFix fix : fixes) { - if (isTheTarget(fix, name, desc) && !insertedFixes.contains(fix)) { // if it's the target and it has not - // been inserted already - mv = fix.getInjectorFactory() - .createFixInserter(mv, access, name, desc, fix, this); // create a new fix inserter for this method - insertedFixes.add(fix); // set it so we know we have already inserted this fix - } - } - return mv; - } - - /** - * Visits the end of the class. This method, which is the last one to be called, - * is used to inform the visitor that all the fields and methods of the class have been visited. - * This custom implementation creates new methods in the target class if there are fixes telling us to do so. - */ - @Override - public void visitEnd() { - for (ASMFix fix : fixes) { - if (fix.getCreateMethod() && !insertedFixes.contains(fix)) { // if the method is to be created and we - // haven't done so already - fix.createMethod(this); // create the said method - } - } - super.visitEnd(); - } - - // Returns true if the method is the target method of the fix. - protected boolean isTheTarget(ASMFix fix, String name, String desc) { - return fix.isTheTarget(name, desc); - } -} diff --git a/src/main/java/net/tclproject/mysteriumlib/asm/core/FixInserterFactory.java b/src/main/java/net/tclproject/mysteriumlib/asm/core/FixInserterFactory.java deleted file mode 100644 index fb42371..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/asm/core/FixInserterFactory.java +++ /dev/null @@ -1,77 +0,0 @@ -package net.tclproject.mysteriumlib.asm.core; - -import org.objectweb.asm.MethodVisitor; - -/** - * Factory, specifying the type of the fix inserter. Factually, from the choice of the factory depends - * in what part of the code the fix will be inserted. - * By deault, there are two types of inserters: OnEnter, which inserts the fix to the start of the method, - * and OnExit, which inserts it on every exit. - */ -public abstract class FixInserterFactory { - - /** - * The method AdviceAdapter#visitInsn() is a weird thing. For some reason, the calling of the next MethodVisitor - * is done after the logic and not before, like in all the other cases. That's why for MethodExit the priority - * of fixes is the reverse. - */ - protected boolean priorityReversed = false; - - /** Creates a fix inserter object. A fix inserter will insert the fix using methods in ASMFix. */ - abstract FixInserter createFixInserter(MethodVisitor mv, int access, String name, String desc, ASMFix fix, - FixInserterClassVisitor cv); - - /** Creates an inserter that will insert fixes at the start of a method. */ - public static class OnEnter extends FixInserterFactory { - - public static final OnEnter INSTANCE = new OnEnter(); - - public OnEnter() {} - - @Override - public FixInserter createFixInserter(MethodVisitor mv, int access, String name, String desc, ASMFix fix, - FixInserterClassVisitor cv) { - return new FixInserter.OnEnterInserter(mv, access, name, desc, fix, cv); - } - - } - - /** Creates an inserter that will insert fixes at exits from a method. */ - public static class OnExit extends FixInserterFactory { - - public static final OnExit INSTANCE = new OnExit(); - public boolean insertOnThrows; - - public OnExit() { - priorityReversed = true; - insertOnThrows = false; - } - - public OnExit(boolean insertOnThrows) { - this.insertOnThrows = insertOnThrows; - priorityReversed = true; - } - - @Override - public FixInserter createFixInserter(MethodVisitor mv, int access, String name, String desc, ASMFix fix, - FixInserterClassVisitor cv) { - return new FixInserter.OnExitInserter(mv, access, name, desc, fix, cv, insertOnThrows); - } - } - - /** Creates an inserter that will insert fixes at a specific line number in a method. */ - public static class OnLineNumber extends FixInserterFactory { - - private int lineNumber; - - public OnLineNumber(int lineNumber) { - this.lineNumber = lineNumber; - } - - @Override - public FixInserter createFixInserter(MethodVisitor mv, int access, String name, String desc, ASMFix fix, - FixInserterClassVisitor cv) { - return new FixInserter.OnLineNumberInserter(mv, access, name, desc, fix, cv, lineNumber); - } - } -} diff --git a/src/main/java/net/tclproject/mysteriumlib/asm/core/FixParser.java b/src/main/java/net/tclproject/mysteriumlib/asm/core/FixParser.java deleted file mode 100644 index ce05f62..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/asm/core/FixParser.java +++ /dev/null @@ -1,420 +0,0 @@ -package net.tclproject.mysteriumlib.asm.core; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map.Entry; - -import net.tclproject.mysteriumlib.asm.annotations.EnumReturnSetting; -import net.tclproject.mysteriumlib.asm.annotations.Fix; -import net.tclproject.mysteriumlib.asm.annotations.FixOrder; -import net.tclproject.mysteriumlib.asm.annotations.LocalVariable; -import net.tclproject.mysteriumlib.asm.annotations.ReturnedValue; - -import org.objectweb.asm.AnnotationVisitor; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; - -/** Class for parsing fix methods and creating fixes out of them. */ -public class FixParser { - - /** The class transformer that has created this fix parser. */ - private TargetClassTransformer transformer; - /** The class to be parsed for fix methods. */ - private String fixesClassName; - /** The method to be parsed. */ - private String currentFixMethodName; - /** The descriptor of the method to be parsed. */ - private String currentFixMethodDescriptor; - /** If the method to be parsed is public and static. */ - private boolean currentMethodIsPublicAndStatic; - - /** - * Key: A key inside the annotation, Value: annotation key's value - */ - private HashMap annotationValues; - - /** - * Key: the number of the argument, value - the number of the local variable for interception - * or -1 for the interception of the parameter on the top of the stack. - */ - private HashMap argumentAnnotations = new HashMap<>(); - - /** If an annotation visitor is currenty visiting a @Fix annotation. */ - private boolean inFixAnnotation; - - /** The descriptor of the Fix annotation class. */ - private static final String fixDescriptor = Type.getDescriptor(Fix.class); - /** The descriptor of the LocalVariable annotation class. */ - private static final String localVariableDescriptor = Type.getDescriptor(LocalVariable.class); - /** The descriptor of the ReturnedValue annotation class. */ - private static final String returnedValueDescriptor = Type.getDescriptor(ReturnedValue.class); - - public FixParser(TargetClassTransformer transformer) { - this.transformer = transformer; - } - - /** - * Parses a class for fix methods via a FixClassVisitor. - * - * @param className The full name of the class. - */ - protected void parseForFixes(String className) { - transformer.logger.debug("Parsing class with fix methods " + className); - try { - transformer.metaReader.acceptVisitor(className, new FixClassVisitor()); - } catch (IOException e) { - transformer.logger.severe("Can not parse class with fix methods " + className, e); - } - } - - /** - * Parses a class for fix methods via a FixClassVisitor. - * - * @param classBytes The class (bytes). - */ - protected void parseForFixes(byte[] classBytes) { - FixClassVisitor fixMethodSearchClassVisitor = new FixClassVisitor(); - try { - transformer.metaReader.acceptVisitor(classBytes, fixMethodSearchClassVisitor); - transformer.logger.debug("Parsing class with fix methods " + fixMethodSearchClassVisitor.fixesClassName); - } catch (Exception e) { - transformer.logger.severe( - fixMethodSearchClassVisitor.fixesClassName != "" - ? ("Can not parse class with fix methods " + fixMethodSearchClassVisitor.fixesClassName) - : ("Can not create a class visitor to search a class for fix methods."), - e); - } - } - - /** - * Displays a warning about an invalid fix method, e.g. if it's not public and static. - * - * @param message A message to add to the warning. - */ - private void warnInvalidFix(String message) { - transformer.logger.warning("Found invalid fix " + fixesClassName + "#" + currentFixMethodName); - transformer.logger.warning(message); - } - - /** - * Creates a fix out of the values currently stored in annotationValues, currentFixMethodName/Descriptor and - * argumentAnnotations, and adds it to the list to be applied - */ - private void createAndRegisterFix(String clsName) { - ASMFix.Builder builder = ASMFix.newBuilder(); - Type methodType = Type.getMethodType(currentFixMethodDescriptor); - Type[] argumentTypes = methodType.getArgumentTypes(); // The types of all the arguments of the fix method - - if (!currentMethodIsPublicAndStatic) { - warnInvalidFix("Fix method must be public and static."); - return; - } - - if (argumentTypes.length < 1) { - warnInvalidFix( - "Fix method has no arguments. First argument of a fix method must be a of the type of the target class."); - return; - } - - if (argumentTypes[0].getSort() != Type.OBJECT) { - warnInvalidFix( - "First argument of the fix method is not an object. First argument of a fix method must be of the type of the target class."); - return; - } - - builder.setTargetClass(argumentTypes[0].getClassName()); // Set the target class to apply the fix to - - if (annotationValues.containsKey("targetMethod")) { - builder.setTargetMethod((String) annotationValues.get("targetMethod")); // Set the target method to apply - // the fix to - } else { - builder.setTargetMethod(currentFixMethodName); // Set the target method to apply the fix to, if none is - // specified, we take it that it's the fix method's name - } - - builder.setFixesClass(clsName); // Set the class with fixes from where this fix originated from - builder.setFixMethod(currentFixMethodName); // Set name of the fix method - builder.addThisToFixMethodParameters(); // Adds the target class to the arguments of the fix method and passes - // this into it. If the target method is static, the value passed will - // be null. - - boolean insertOnExit = Boolean.TRUE.equals(annotationValues.get("insertOnExit")); // If we have to insert the - // fix on the exits from a - // method - - int currentParameterId = 1; - for (int i = 1; i < argumentTypes.length; i++) { // loop to deal with ReturnedValue or LocalVariable annotations - // inside the fix method's arguments - Type currentArgumentType = argumentTypes[i]; - if (argumentAnnotations.containsKey(i)) { // if the argument is a ReturnedValue or LocalVariable annotation - // (all of those are added to argumentAnnotations) - int stackIndexToBePassed = argumentAnnotations.get(i); - if (stackIndexToBePassed == -1) { // if the stack index to be passed is -1, it's the value at the top - builder.setTargetMethodReturnType(currentArgumentType); // The return type of the target method - // obviously has to be the returnedValue's - // type we want passed into the fix method - builder.addReturnedValueToFixMethodParameters(); - } else { - builder.addFixMethodParameter(currentArgumentType, stackIndexToBePassed); - } - } else { - builder.addTargetMethodParameters(currentArgumentType); - builder.addFixMethodParameter(currentArgumentType, currentParameterId); - currentParameterId += currentArgumentType == Type.LONG_TYPE || currentArgumentType == Type.DOUBLE_TYPE - ? 2 - : 1; - } - } - - if (insertOnExit) builder.setInjectorFactory(ASMFix.ON_EXIT_FACTORY); // If we have to insert the fix on the - // exits from a method, we set the factory - // to the one that makes fixes that insert - // themselves on the exits - - if (annotationValues.containsKey("insertOnLine")) { - int lineToBeInsertedOn = (Integer) annotationValues.get("insertOnLine"); - builder.setInjectorFactory(new FixInserterFactory.OnLineNumber(lineToBeInsertedOn)); // If we have to insert - // the fix on a line - // number, we set the - // factory to the one - // that makes fixes - // that inserts that - // insert themselves on - // the specific line - // number - } - - if (annotationValues.containsKey("returnedType")) { - builder.setTargetMethodReturnType((String) annotationValues.get("returnedType")); - } - - EnumReturnSetting EnumReturnSetting = net.tclproject.mysteriumlib.asm.annotations.EnumReturnSetting.NEVER; - if (annotationValues.containsKey("returnSetting")) { - EnumReturnSetting = net.tclproject.mysteriumlib.asm.annotations.EnumReturnSetting - .valueOf((String) annotationValues.get("returnSetting")); - builder.setReturnSetting(EnumReturnSetting); - } - - // A lot of this is easy to read without comments, and if not, you can look at the documentation of the methods - // called. - - if (EnumReturnSetting != net.tclproject.mysteriumlib.asm.annotations.EnumReturnSetting.NEVER) { // if we have - // custom logic - // for if we - // return - // something - // different - // from the - // original - // target method - Object primitiveConstant = getAlwaysReturnedValue(); - if (primitiveConstant != null) { - builder.setReturnType(net.tclproject.mysteriumlib.asm.annotations.EnumReturnType.PRIMITIVE_CONSTANT); - builder.setPrimitiveAlwaysReturned(primitiveConstant); - } else if (Boolean.TRUE.equals(annotationValues.get("nullReturned"))) { - builder.setReturnType(net.tclproject.mysteriumlib.asm.annotations.EnumReturnType.NULL); - } else if (annotationValues.containsKey("anotherMethodReturned")) { - builder.setReturnType( - net.tclproject.mysteriumlib.asm.annotations.EnumReturnType.ANOTHER_METHOD_RETURN_VALUE); - builder.setReturnMethod((String) annotationValues.get("anotherMethodReturned")); - } else if (methodType.getReturnType() != Type.VOID_TYPE) { - builder - .setReturnType(net.tclproject.mysteriumlib.asm.annotations.EnumReturnType.FIX_METHOD_RETURN_VALUE); - } - } - // returnSetting and *AlwaysReturned set the type of the fix method, so we can only set them now - - builder.setFixMethodReturnType(methodType.getReturnType()); - - if (EnumReturnSetting == net.tclproject.mysteriumlib.asm.annotations.EnumReturnSetting.ON_TRUE - && methodType.getReturnType() != Type.BOOLEAN_TYPE) { - warnInvalidFix( - "Fix method must return boolean if returnSetting is ON_TRUE. (if we only return our custom value/ the original value if the fix method returns true, how do we know if it's true if it's not a boolean?)"); - return; - } - if ((EnumReturnSetting == net.tclproject.mysteriumlib.asm.annotations.EnumReturnSetting.ON_NULL - || EnumReturnSetting == net.tclproject.mysteriumlib.asm.annotations.EnumReturnSetting.ON_NOT_NULL) - && methodType.getReturnType() - .getSort() != Type.OBJECT - && methodType.getReturnType() - .getSort() != Type.ARRAY) { - warnInvalidFix( - "Fix method must return object if returnSetting is ON_NULL or ON_NOT_NULL. (if we only return our custom value/ the original value if the fix method returns a null/ non null object, how do we know if it's a null/ not null object if it's not an object?)"); - return; - } - - if (annotationValues.containsKey("order")) { - builder.setPriority(FixOrder.valueOf((String) annotationValues.get("order"))); - } - - if (annotationValues.containsKey("createNewMethod")) { - builder.setCreateMethod(Boolean.TRUE.equals(annotationValues.get("createNewMethod"))); - } - if (annotationValues.containsKey("isFatal")) { - builder.setFatal(Boolean.TRUE.equals(annotationValues.get("isFatal"))); - } - - transformer.registerFix(builder.build()); // Adds the fix to the list to be inserted - } - - /** - * @return The value of the annotation key storing an always-returned value. Null if there is no such value - * specified. - */ - private Object getAlwaysReturnedValue() { - for (Entry entry : annotationValues.entrySet()) { - if (entry.getKey() - .endsWith("AlwaysReturned")) { - return entry.getValue(); - } - } - return null; - } - - /** - * Custom class visitor that visits the class with fix methods and returns custom method visitors to be executed. - */ - private class FixClassVisitor extends ClassVisitor { - - String fixesClassName = ""; - - public FixClassVisitor() { - super(Opcodes.ASM5); - } - - @Override - public void visit(int version, int access, String name, String signature, String superName, - String[] interfaces) { - fixesClassName = name.replace('/', '.'); - } - - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - currentFixMethodName = name; // Method currently parsing - currentFixMethodDescriptor = desc; // Descriptor of method currently parsing - currentMethodIsPublicAndStatic = (access & Opcodes.ACC_PUBLIC) != 0 && (access & Opcodes.ACC_STATIC) != 0; // e.g. - // access - // codes - // 1000 - // & - // 1000 - // = - // 1000 - // (8). - // 1000 - // & - // 0001 - // = - // 0. - // If - // access - // is - // the - // same, - // it - // will - // be - // the - // number - // of - // the - // access. - return new FixMethodVisitor(fixesClassName); // Custom method visitor to be executed - } - } - - /** - * Custom method visitor. If the method it's visiting has a @Fix annotaion, returns a FixAnnotationVisitor instead - * of a normal AnnotationVisitor and creates a fix when finished reading the values. - */ - private class FixMethodVisitor extends MethodVisitor { - - String clsName; - - public FixMethodVisitor(String className) { - super(Opcodes.ASM5); - clsName = className; - } - - @Override - public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { - if (fixDescriptor.equals(descriptor)) { // If it has a fix annotation - annotationValues = new HashMap<>(); // Store it's keys and values - inFixAnnotation = true; - } - return new FixAnnotationVisitor(); - } - - // An argument is meant by a parameter. This calls when visiting arguments of the method that are annotations. - @Override - public AnnotationVisitor visitParameterAnnotation(final int indexOfArgument, String descriptor, - boolean visible) { - if (returnedValueDescriptor.equals(descriptor)) { - argumentAnnotations.put(indexOfArgument, -1); // If it is a returnedValue argument, we want to have the - // value on the top of the stack passed in to argument - // number indexOfArgument in the fix method - } - if (localVariableDescriptor.equals(descriptor)) { - return new AnnotationVisitor(Opcodes.ASM5) { // If it is a localVariable argument, we return a custom - // AnnotationVisitor that will add the annotation to the - // list when visiting it - - @Override - public void visit(String name, Object value) { - argumentAnnotations.put(indexOfArgument, (Integer) value); // We want to have the value at x - // index in stack passed in to - // argument number indexOfArgument in - // the fix method - } - }; - } - return null; // If it is some other annotation, ignore it - } - - // We are at the end and have parsed the fix method - @Override - public void visitEnd() { - if (annotationValues != null) { - createAndRegisterFix(this.clsName); // If the annotation exists, we create a fix (there are some default - // values, so if it's there it's values are never null). We need - // this check because not all methods inside the class with fixes - // might be fixes. - } - // clean up the variables for the next fix method to occupy them - argumentAnnotations.clear(); - currentFixMethodName = null; - currentFixMethodDescriptor = null; - currentMethodIsPublicAndStatic = false; - annotationValues = null; - } - } - - /** Custom annotation visitor that stores the annotation's keys and values inside annotationValues. */ - private class FixAnnotationVisitor extends AnnotationVisitor { - - public FixAnnotationVisitor() { - super(Opcodes.ASM5); - } - - @Override - public void visit(String name, Object value) { - if (inFixAnnotation) { // If we are currently visiting a fix annotation. - annotationValues.put(name, value); // Store the keys and values inside the annotation - } - } - - // If a value in the annotation is an enum, it calls this one - @Override - public void visitEnum(String name, String descriptor, String value) { - visit(name, value); - } - - // When it has finished visiting an annotation, we are no longer inside one so we reset it back to false - @Override - public void visitEnd() { - inFixAnnotation = false; - } - } -} diff --git a/src/main/java/net/tclproject/mysteriumlib/asm/core/MetaReader.java b/src/main/java/net/tclproject/mysteriumlib/asm/core/MetaReader.java deleted file mode 100644 index 615e15a..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/asm/core/MetaReader.java +++ /dev/null @@ -1,444 +0,0 @@ -package net.tclproject.mysteriumlib.asm.core; - -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.apache.commons.io.IOUtils; -import org.apache.logging.log4j.Level; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; - -import cpw.mods.fml.common.FMLLog; - -/** Utilities for getting information out of classes and methods and performing basic tasks on them. */ -public class MetaReader { - - /** The findLoadedClass method inside the ClassLoader class. */ - private static Method findLoadedClass; - - static { - try { - findLoadedClass = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class); - findLoadedClass.setAccessible(true); - } catch (NoSuchMethodException e) { - FMLLog.log( - "Mysterium Patches", - Level.ERROR, - "Error occured when making findLoadedClass in ClassLoader usable."); - FMLLog.log( - "Mysterium Patches", - Level.ERROR, - "THIS IS MOST LIKELY HAPPENING BECAUSE OF MOD CONFLICTS. PLEASE CONTACT ME TO LET ME KNOW."); - FMLLog.log("Mysterium Patches", Level.ERROR, e.getMessage()); - } - } - - // TODO: test a static method - /** - * Gets a list of local variables (index: , type, name) in a method. - * - * @param classBytes the class that contains the method (bytes). - * @param methodName the name of the target method. - * @param argumentTypes the types of the arguments in the method, represented by Type instances. - * @return a list of local variables. - */ - public List getLocalVariables(byte[] classBytes, final String methodName, Type... argumentTypes) { - final List localVariables = new ArrayList<>(); - String methodDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, argumentTypes); // We don't actually use the - // return type, hence the - // next variable - final String methodDescriptorWithoutReturnType = methodDescriptor.substring(0, methodDescriptor.length() - 1); - - ClassVisitor classVisitor = new ClassVisitor(Opcodes.ASM5) { - - @Override - public MethodVisitor visitMethod(final int access, String name, String descriptor, String signature, - String[] exceptions) { - if (methodName.equals(name) && descriptor.startsWith(methodDescriptorWithoutReturnType)) { - return new MethodVisitor(Opcodes.ASM5) { - - @Override - public void visitLocalVariable(String name, String descriptor, String signature, Label start, - Label end, int index) { - String typeName = Type.getType(descriptor) - .getClassName(); - int fixedIndex = index + ((access & Opcodes.ACC_STATIC) == 0 ? 0 : 1); // If access is - // static, we add 1, - // if not, we add 0. - localVariables.add(fixedIndex + ": " + typeName + " " + name); - } - }; - } - return null; - } - }; - - acceptVisitor(classBytes, classVisitor); - return localVariables; - } - - /** - * Gets a list of local variables (index: , type, name) in a method. - * - * @param className the class that contains the method (full class path without ".class"). - * @param methodName the name of the target method. - * @param argumentTypes the types of the arguments in the method, represented by Type instances. - * @return a list of local variables. - */ - public List getLocalVariables(String className, final String methodName, Type... argTypes) - throws IOException { - return getLocalVariables(classToBytes(className), methodName, argTypes); - } - - /** - * Prints a list of local variables (index: , type, name) in a method. - * - * @param classBytes the class that contains the method (bytes). - * @param methodName the name of the target method. - * @param argumentTypes the types of the arguments in the method, represented by Type instances. - */ - public void printLocalVariables(byte[] classBytes, String methodName, Type... argumentTypes) { - List locals = getLocalVariables(classBytes, methodName, argumentTypes); - for (String str : locals) { - System.out.println(str); - } - } - - /** - * Prints a list of local variables (index: , type, name) in a method. - * - * @param className the class that contains the method (full class path without ".class"). - * @param methodName the name of the target method. - * @param argumentTypes the types of the arguments in the method, represented by Type instances. - */ - public void printLocalVariables(String className, String methodName, Type... argumentTypes) throws IOException { - printLocalVariables(classToBytes(className), methodName, argumentTypes); - } - - /** - * Gets the passed in class in an InputStream. - * - * @param name full class path without ".class". - * @return the passed in class (InputStream) - */ - public static InputStream classToStream(String name) { - String classResourceName = '/' + name.replace('.', '/') + ".class"; - return MetaReader.class.getResourceAsStream(classResourceName); - } - - /** - * Gets the passed in class in bytes. - * - * @param name full class path without ".class". - * @return the passed in class (bytes) - */ - public byte[] classToBytes(String name) throws IOException { - String classLocationName = '/' + name.replace('.', '/') + ".class"; - return IOUtils.toByteArray(MetaReader.class.getResourceAsStream(classLocationName)); - } - - /** - * Makes the given visitor visit the Java class. - * - * @param classBytes class (bytes). - * @param visitor your class visitor. - */ - public void acceptVisitor(byte[] classBytes, ClassVisitor visitor) { - new ClassReader(classBytes).accept(visitor, 0); - } - - /** - * Makes the given visitor visit the Java class. - * - * @param name full class path without ".class". - * @param visitor your class visitor. - */ - public void acceptVisitor(String name, ClassVisitor visitor) throws IOException { - acceptVisitor(classToBytes(name), visitor); - } - - /** - * Makes the given visitor visit the Java class. - * - * @param classStream the class as an InputStream. - * @param visitor your class visitor. - */ - public static void acceptVisitor(InputStream classStream, ClassVisitor visitor) { - try { - ClassReader reader = new ClassReader(classStream); - reader.accept(visitor, 0); - classStream.close(); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - /** - * Finds a method in a Java class. The method must be virtual. - * - * @param owner the class that has the method. - * @param methodName the method name. - * @param descriptor the method descriptor. - * @return a MethodReference of the method. - */ - public MethodReference findMethod(String owner, String methodName, String descriptor) { - ArrayList superClasses = getSuperClasses(owner); - for (int i = superClasses.size() - 1; i > 0; i--) { // There is no use in checking the current class, for that - // we have getMethodReference. - String className = superClasses.get(i); - MethodReference methodReference = getMethodReference(className, methodName, descriptor); - if (methodReference != null) { - return methodReference; - } - } - return null; - } - - /** - * Helper method to create a MethodReference out of a method, tries Reflection if ASM fails. - * - * @param className full class path without ".class". - * @param methodName the name of the method. - * @param descriptor the descriptor of the method. - * @return a MethodReference. - */ - public MethodReference getMethodReference(String className, String methodName, String descriptor) { - try { - return getMethodReferenceASM(className, methodName, descriptor); - } catch (Exception e) { - return getMethodReferenceReflect(className, methodName, descriptor); - } - } - - /** - * Helper method to create a MethodReference out of a method, using ASM. - * - * @param className full class path without ".class". - * @param methodName the name of the method. - * @param descriptor the descriptor of the method. - * @return a MethodReference. - */ - public MethodReference getMethodReferenceASM(String className, String methodName, String descriptor) - throws IOException { - FindMethodClassVisitor cv = new FindMethodClassVisitor(methodName, descriptor); - acceptVisitor(className, cv); - if (cv.found) { - return new MethodReference(className, cv.targetName, cv.targetDescriptor); - } - return null; - } - - /** - * Helper method to create a MethodReference out of a method, using Reflection. - * - * @param className full class path without ".class". - * @param methodName the name of the method. - * @param descriptor the descriptor of the method. - * @return a MethodReference. - */ - public MethodReference getMethodReferenceReflect(String className, String methodName, String descriptor) { - Class loadedClass = getLoadedClass(className); - if (loadedClass != null) { - for (Method m : loadedClass.getDeclaredMethods()) { - if (checkSameMethod(methodName, descriptor, m.getName(), Type.getMethodDescriptor(m))) { - return new MethodReference(className, m.getName(), Type.getMethodDescriptor(m)); - } - } - } - return null; - } - - /** - * Checks if two methods are the same. - * - * @param sourceName first method name - * @param sourceDesc first method descriptor - * @param targetName second method name - * @param targetDesc second method descriptor - * @return if the two names and descriptors are equal. - */ - public boolean checkSameMethod(String sourceName, String sourceDesc, String targetName, String targetDesc) { - return sourceName.equals(targetName) && sourceDesc.equals(targetDesc); - } - - /** - * Gets all the super classes of a class. - * - * @param name full class path without ".class". - * @return superclasses in order of increasing specificity (starting with java/lang/Object - * and ending with the name passed in) - */ - public ArrayList getSuperClasses(String name) { - ArrayList superClasses = new ArrayList<>(1); - superClasses.add(name); - - // Loop that iterates over all super classes, getting super class of super class of super class etc - while ((name = getSuperClass(name)) != null) { - superClasses.add(name); - } - - Collections.reverse(superClasses); - return superClasses; - } - - /** - * Gets the class from the name passed in. - * - * @param name full class path without ".class". - * @return the class. - */ - public Class getLoadedClass(String name) { - if (findLoadedClass != null) { - try { - // We get the class loader that loaded our class. - ClassLoader classLoader = MetaReader.class.getClassLoader(); - // We invoke our class loader on the class name and it returns to us the loaded class. - return (Class) findLoadedClass.invoke(classLoader, name.replace('/', '.')); - } catch (Exception e) { - FMLLog.log("Mysterium Patches", Level.ERROR, "Error occured when getting a class from a name."); - FMLLog.log( - "Mysterium Patches", - Level.ERROR, - "THIS IS MOST LIKELY HAPPENING BECAUSE OF MOD CONFLICTS. PLEASE CONTACT ME TO LET ME KNOW."); - FMLLog.log("Mysterium Patches", Level.ERROR, e.getMessage()); - } - } - return null; - } - - /** - * Gets the super class of the class passed in using all methods (if ASM doesn't work, tries reflection). - * - * @param name full class path without ".class". - * @return full class path of the superclass without ".class". - */ - public String getSuperClass(String name) { - try { - return getSuperClassASM(name); - } catch (Exception e) { - return getSuperClassReflect(name); - } - } - - /** - * Gets the super class of the class passed in using ASM using a custom class visitor. - * - * @param name full class path without ".class". - * @return full class path of the superclass without ".class". - */ - public String getSuperClassASM(String name) throws IOException { - CheckSuperClassVisitor cv = new CheckSuperClassVisitor(); - acceptVisitor(name, cv); - return cv.superClassName; - } - - /** - * Gets the super class of the class passed in using reflection. - * - * @param name full class path without ".class". - * @return full class path of the superclass without ".class". - */ - public String getSuperClassReflect(String name) { - Class loadedClass = getLoadedClass(name); - if (loadedClass != null) { - if (loadedClass.getSuperclass() == null) return null; - return loadedClass.getSuperclass() - .getName() - .replace('.', '/'); - } - return "java/lang/Object"; - } - - /** Custom class visitor that stores the superclass name. */ - protected class CheckSuperClassVisitor extends ClassVisitor { - - /** Name of superclass */ - String superClassName; - - public CheckSuperClassVisitor() { - // ASM version is 5 - super(Opcodes.ASM5); - } - - @Override - public void visit(int version, int access, String name, String signature, String superName, - String[] interfaces) { - this.superClassName = superName; - } - } - - /** Custom class visitor that finds a method in a class. */ - protected class FindMethodClassVisitor extends ClassVisitor { - - public String targetName; - public String targetDescriptor; - public boolean found; - - public FindMethodClassVisitor(String name, String desctiptor) { - super(Opcodes.ASM5); - this.targetName = name; - this.targetDescriptor = desctiptor; - } - - @Override - public MethodVisitor visitMethod(int access, String name, String desctiptor, String signature, - String[] exceptions) { - - // Check ofr if access is public (01(public),10(private),11(protected) & 10 will only be 00 if it's 01) and - // it's the same method you're looking for. - if ((access & Opcodes.ACC_PRIVATE) == 0 - && checkSameMethod(name, desctiptor, targetName, targetDescriptor)) { - found = true; - targetName = name; - targetDescriptor = desctiptor; - } - return null; - } - } - - /** Helper class that stores a method reference. */ - public static class MethodReference { - - /** Class that contains the said method. */ - public final String owner; - - /** The method name. */ - public final String name; - - /** The method descriptor. */ - public final String descriptor; - - public MethodReference(String owner, String name, String descriptor) { - this.owner = owner; - this.name = name; - this.descriptor = descriptor; - } - - /** Gets the return type of the method. */ - public Type getReturnType() { - return Type.getMethodType(descriptor); - } - - @Override - public String toString() { - return "MethodReference{" + "owner='" - + owner - + '\'' - + ", name='" - + name - + '\'' - + ", desc='" - + descriptor - + '\'' - + '}'; - } - } -} diff --git a/src/main/java/net/tclproject/mysteriumlib/asm/core/MiscUtils.java b/src/main/java/net/tclproject/mysteriumlib/asm/core/MiscUtils.java deleted file mode 100644 index 283e2bf..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/asm/core/MiscUtils.java +++ /dev/null @@ -1,223 +0,0 @@ -package net.tclproject.mysteriumlib.asm.core; - -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.apache.commons.io.FileUtils; -import org.objectweb.asm.ClassWriter; - -/** General purpose class with utilities. */ -public class MiscUtils { - - /** - * ClassWriter with a custom implementation of getCommonSuperClass. When it's used, no class loading occurs. - * But, the loading of classes itself is rarely the problem, because the init of the class (the calling of static - * blocks) doesn't happen when class loading occurs. The problems occur, when fixes are inserted into - * classes dependent on each other, then the standard implementation fails with ClassCircularityError. - */ - public class SafeCommonSuperClassWriter extends ClassWriter { - - /** An instance of MetaReader. */ - private final MetaReader metaReader; - - public SafeCommonSuperClassWriter(MetaReader metaReader, int flags) { - super(flags); - this.metaReader = metaReader; - } - - @Override - protected String getCommonSuperClass(String type1, String type2) { - ArrayList superClasses1 = metaReader.getSuperClasses(type1); // super classes of type1 - ArrayList superClasses2 = metaReader.getSuperClasses(type2); // super classes of type2 - int size = Math.min(superClasses1.size(), superClasses2.size()); // the maximum time both can be super'd - // until one reaches one of classes passed - // in - int i; - - for (i = 0; i < size && superClasses1.get(i) - .equals(superClasses2.get(i)); i++); // For every super class, 1 is added. - - if (i == 0) { - return "java/lang/Object"; // If there are no common classes, Object is automatically returned - } else { - return superClasses1.get(i - 1); // e.g: you have 1 common class so "i" is going to be 1. But list - // indices start with 0, that's why it takes away 1. - } // The common class returned is the most specific one, e.g. if we have 'class a extends b extends c', b is - // returned - } - } - - public interface LogHelper { - - /** Used for debugging information. */ - void debug(String message); - - /** - * Used for general information. Does not appear in the game console, in order to see it, one must open up - * fml-server/client-latest.log. - */ - void info(String message); - - /** Used for not-so-important warnings. */ - void warning(String message); - - /** Used for severe warnings. */ - void severe(String message); - - /** Used for severe warnings. Prints the stack trace. */ - void severe(String message, Throwable cause); - - /** Used for fatal warnings. */ - void fatal(String message); - - /** Used for fatal warnings. Prints the stack trace. */ - void fatal(String message, Throwable cause); - } - - public class SystemLogHelper implements LogHelper { - - @Override - public void debug(String message) { - System.out.println("[DEBUG] " + message); - } - - @Override - public void warning(String message) { - System.out.println("[WARNING] " + message); - } - - @Override - public void severe(String message) { - System.out.println("[SEVERE] " + message); - } - - @Override - public void severe(String message, Throwable cause) { - severe(message); - cause.printStackTrace(); - } - - @Override - public void info(String message) { - System.out.println("[INFORMATION] " + message); - } - - @Override - public void fatal(String message) { - System.out.println("[---------------[!!!FATAL!!!]---------------]"); - System.out.println(message); - System.out.println("[---------------[!!!FATAL!!!]---------------]"); - - } - - @Override - public void fatal(String message, Throwable cause) { - fatal(message); - cause.printStackTrace(); - - } - } - - public class MinecraftLogHelper implements LogHelper { - - private Logger logger; - - public MinecraftLogHelper(Logger logger) { - this.logger = logger; - } - - @Override - public void debug(String message) { - logger.log(Level.FINE, message); - } - - /** Used for detailed log messages. */ - public void detailed(String message) { - logger.log(Level.FINEST, message); - } - - /** Used for log messages related to how the user configured something. */ - public void configInfo(String message) { - logger.log(Level.CONFIG, message); - } - - @Override - public void warning(String message) { - logger.log(Level.WARNING, message); - } - - @Override - public void severe(String message) { - logger.log(Level.SEVERE, message); - } - - @Override - public void severe(String message, Throwable cause) { - logger.log(Level.SEVERE, message, cause); - } - - @Override - public void info(String message) { - logger.log(Level.INFO, message); - } - - @Override - public void fatal(String message) { - logger.log(Level.SEVERE, "[---------------[!!!FATAL!!!]---------------]"); - logger.log(Level.SEVERE, message); - logger.log(Level.SEVERE, "[---------------[!!!FATAL!!!]---------------]"); - - } - - @Override - public void fatal(String message, Throwable cause) { - logger.log(Level.SEVERE, "[---------------[!!!FATAL!!!]---------------]"); - logger.log(Level.SEVERE, message, cause); - logger.log(Level.SEVERE, "[---------------[!!!FATAL!!!]---------------]"); - } - } - - /** - * Generates a methods.bin file for the use in MysteriumASMLib out of a methods.csv file. - * methods.csv is located inside mcp/conf/. (mcp is the folder you unzipped mcp into). - * If you didn't know, forge uses mcp to provide you with readable method names. - * Inside this folder, there are ready-to-go methods.bin files for 1.6.4, 1.7.10, and 1.8. - *

- * It is still highly recommended to generate methods.bin for your own version of mcp, - * otherwise errors like "can't find target method of fix" will most likely occur at some point. - * - * @throws Exception if something went wrong, e.g. the program doesn't have the permissions to access the file or - * folder it's in. - */ - public static void generateMethodsDictionary() throws Exception { - List lines = FileUtils.readLines(new File("methods.csv")); - lines.remove(0); - HashMap map = new HashMap<>(); - for (String str : lines) { - String[] splitted = str.split(","); - int first = splitted[0].indexOf('_'); - int second = splitted[0].indexOf('_', first + 1); - int id = Integer.valueOf(splitted[0].substring(first + 1, second)); - map.put(id, splitted[1]); - } - - DataOutputStream out = new DataOutputStream(new FileOutputStream("methods.bin")); - out.writeInt(map.size()); - - for (Map.Entry entry : map.entrySet()) { - out.writeInt(entry.getKey()); - out.writeUTF(entry.getValue()); - } - - out.close(); - - } - -} diff --git a/src/main/java/net/tclproject/mysteriumlib/asm/core/TargetClassTransformer.java b/src/main/java/net/tclproject/mysteriumlib/asm/core/TargetClassTransformer.java deleted file mode 100644 index be3d3ef..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/asm/core/TargetClassTransformer.java +++ /dev/null @@ -1,155 +0,0 @@ -package net.tclproject.mysteriumlib.asm.core; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; - -import net.tclproject.mysteriumlib.asm.core.MiscUtils.LogHelper; - -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassWriter; - -/** - * Class that processes byte[] classes, to be integrated with IFMLLoadingPlugin to get classes passed into transform - * method. - */ -public class TargetClassTransformer { - - /** Instance of MiscUtils needed in order to make a logger. */ - MiscUtils utils = new MiscUtils(); - /** System logger that this class uses (messages will only appear in console, to my knowledge.) */ - public LogHelper logger = utils.new SystemLogHelper(); - /** Map of "target class name":"List of ASMFix/es to be applied". */ - protected HashMap> fixesMap = new HashMap<>(); - /** Class that will parse the fix class and methods. */ - private FixParser containerParser = new FixParser(this); - /** MetaReader instance used. */ - protected MetaReader metaReader = new MetaReader(); - - /** Adds a fix to the list to be inserted. */ - public void registerFix(ASMFix fix) { - if (fixesMap.containsKey(fix.getTargetClassName())) { - fixesMap.get(fix.getTargetClassName()) - .add(fix); // If a class is already to be transformed, we just add one more fix to it. - } else { // If the class doesn't exist in the list to have a fix applied to. - List list = new ArrayList<>(2); // Create a new list of fixes to be applied to the class. - list.add(fix); // Add this fix to the list. - fixesMap.put(fix.getTargetClassName(), list); // Put the class and the list of fixes for it into the map. - } - } - - /** Registers the class with all the fix methods. */ - public void registerClassWithFixes(String className) { - containerParser.parseForFixes(className); - } - - /** Registers the class with all the fix methods. */ - public void registerClassWithFixes(byte[] classBytes) { - containerParser.parseForFixes(classBytes); - } - - /** Takes the original bytecode of a class and returns the modified version of it with fixes applied. */ - public byte[] transform(String className, byte[] classBytes) { - List fixes = fixesMap.get(className); // gets the fixes for the class - - if (fixes != null) { // if there are any - Collections.sort(fixes); // sort fixes using method inside ASMFix - logger.debug("Injecting fixes into class " + className + "."); - try { - /* - * Starting with java 7, the process of bytecode verification got changed pretty drastically. - * Because of this, we have to turn on the automatic generation of stack map frames. - * On older versions of java, this is just a waste of time. - * More details here: http://stackoverflow.com/questions/25109942 - */ - - // Some random java version verification algorithm from google - int javaVersion = ((classBytes[6] & 0xFF) << 8) | (classBytes[7] & 0xFF); - boolean java7 = javaVersion > 50; - - ClassReader classReader = new ClassReader(classBytes); - ClassWriter classWriter = createClassWriter( - java7 ? ClassWriter.COMPUTE_FRAMES : ClassWriter.COMPUTE_MAXS); // If java is 7+, compute frames, if - // not, set everything to max - // possible - FixInserterClassVisitor fixInserterVisitor = createInserterClassVisitor(classWriter, fixes); - classReader.accept(fixInserterVisitor, java7 ? ClassReader.SKIP_FRAMES : ClassReader.EXPAND_FRAMES); // Make - // the - // fix - // inserter - // class - // visitor - // run - // through - // the - // methods - // and - // return - // fix - // inserter - // method - // visitors - - // Chain: register class with fix methods -> parse the class for fix methods and add them to the list to - // be inserted -> make custom class visitor -> visit target class and return custom method visitors that - // will be executed -> custom method visitors call ASMFix method to insert fixes from the list -> ASMFix - // inserts the fixes - - classBytes = classWriter.toByteArray(); // Overwrite the class bytes with the new class bytes - - for (ASMFix fix : fixInserterVisitor.insertedFixes) { - logger.debug("Fixed method " + fix.getFullTargetMethodName()); - } // Print out all fixed methods - - fixes.removeAll(fixInserterVisitor.insertedFixes); // remove inserted fixes from the list of fixes to be - // inserted - - } catch (Exception e) { - logger.severe("A problem has occurred during transformation of class " + className + "."); - logger.severe("Fixes to be applied to this class:"); - for (ASMFix fix : fixes) { - logger.severe(fix.toString()); - } - logger.severe("Stack trace:", e); - } - - for (ASMFix notInserted : fixes) { // since inserted fixes get removed, we can just iterate through ones - // left - if (notInserted.isMandatory()) { - throw new RuntimeException("Can not find the target method of fatal fix: " + notInserted); - } else { - logger.warning("Can not find the target method of fix: " + notInserted); - } - } - } - return classBytes; - } - - /** - * Creates a custom Class Visitor to return custom method visitors to insert fixes. - * This method can be overridden, if inside the ClassVisitor, custom logic is needed to check if - * the methods are the target methods. - * - * @param cw ClassWriter, that needs to save the changes - * @param fixes List of fixes inserted into the target class - * @return ClassVisitor that returns the custom method visitors - */ - public FixInserterClassVisitor createInserterClassVisitor(ClassWriter classWriter, List fixes) { - return new FixInserterClassVisitor(this, classWriter, fixes); - } - - /** - * Creates a Class Writer for storing the transformed class. - * This method can be overridden, if a custom implementation of getCommonSuperClass is needed. - * The standard implementation works only for classes, the .class files of which - * are already inside classpath, but aren't loaded. The loading (but not init) of classes occurs. - * If the loading of classes is a problem, you can use SafeCommonSuperClassWriter. - * - * @param flags Flags you need to pass into the constructor of the ClassWriter - * @return ClassWriter, that saves the transformed class - */ - public ClassWriter createClassWriter(int flags) { - return utils.new SafeCommonSuperClassWriter(metaReader, flags); - } -} diff --git a/src/main/java/net/tclproject/mysteriumlib/asm/core/TypeUtils.java b/src/main/java/net/tclproject/mysteriumlib/asm/core/TypeUtils.java deleted file mode 100644 index 1ecd83a..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/asm/core/TypeUtils.java +++ /dev/null @@ -1,100 +0,0 @@ -package net.tclproject.mysteriumlib.asm.core; - -import java.util.HashMap; -import java.util.Map; - -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; - -/** - * Class that allows to create Types out of different input data. - * We need these Types for setting arguments and return types of methods. - */ -public class TypeUtils { - - private static final Map primitives = new HashMap<>(9); - - /** - * Creates a Type based on the name of the class or primitive. - * e.g.: getType("net.minecraft.world.World") - will return a type for World - * - * @param name name of the class (not obfuscated) or primitive e.g. "void" or "double" - * @return the corresponding Type. - */ - public static Type getType(String name) { - return getArrayType(name, 0); - } - - /** - * Creates a Type for an array with the immersion of 1 of the said class or primitive. - * e.g.: getArrayType("net.minecraft.world.World") - will return a type for World[] - * - * @param name name of the class (not obfuscated) or primitive e.g. "void" or "double" - * @return the corresponding Type. - */ - public static Type getArrayType(String name) { - return getArrayType(name, 1); - } - - /** - * Creates a Type for an array with the immersion of arrayDimensions of the said class or primitive. - * e.g. getArrayType("net.minecraft.world.World", 2) - will return a type for World[][] - * e.g. getArrayType("net.minecraft.world.World", 1) - will return a type for World[] - * e.g. getArrayType("net.minecraft.world.World", 0) - will return a type for World - * - * @param name name of the class (not obfuscated) or primitive e.g. "void" or "double" - * @return the corresponding Type. - */ - public static Type getArrayType(String name, int arrayDimensions) { - StringBuilder stringBuilder = new StringBuilder(); - for (int i = 0; i < arrayDimensions; i++) { - stringBuilder.append("["); - } - Type primitive = primitives.get(name); - if (primitive == null) { - stringBuilder.append("L"); - stringBuilder.append(name.replace(".", "/")); - stringBuilder.append(";"); - } else { - stringBuilder.append(primitive.getDescriptor()); - } - return Type.getType(stringBuilder.toString()); - } - - /** - * Returns what's used in stack map frames for a Type. - * - * @param type a Type. - * @return the corresponding type in the format used by StackMapTable frames. - */ - public static Object getStackMapFormat(Type type) { - if (type == Type.BOOLEAN_TYPE || type == Type.BYTE_TYPE - || type == Type.SHORT_TYPE - || type == Type.CHAR_TYPE - || type == Type.INT_TYPE) { - return Opcodes.INTEGER; - } - if (type == Type.FLOAT_TYPE) { - return Opcodes.FLOAT; - } - if (type == Type.DOUBLE_TYPE) { - return Opcodes.DOUBLE; - } - if (type == Type.LONG_TYPE) { - return Opcodes.LONG; - } - return type.getInternalName(); - } - - static { - primitives.put("void", Type.VOID_TYPE); - primitives.put("boolean", Type.BOOLEAN_TYPE); - primitives.put("byte", Type.BYTE_TYPE); - primitives.put("short", Type.SHORT_TYPE); - primitives.put("char", Type.CHAR_TYPE); - primitives.put("int", Type.INT_TYPE); - primitives.put("float", Type.FLOAT_TYPE); - primitives.put("long", Type.LONG_TYPE); - primitives.put("double", Type.DOUBLE_TYPE); - } -} diff --git a/src/main/java/net/tclproject/mysteriumlib/asm/fixes/MysteriumPatchesFixesO.java b/src/main/java/net/tclproject/mysteriumlib/asm/fixes/MysteriumPatchesFixesO.java deleted file mode 100644 index e9f69b5..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/asm/fixes/MysteriumPatchesFixesO.java +++ /dev/null @@ -1,100 +0,0 @@ -package net.tclproject.mysteriumlib.asm.fixes; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.reflect.Field; - -import cpw.mods.fml.common.Optional; -import invtweaks.InvTweaksContainerManager; -import invtweaks.InvTweaksContainerSectionManager; -import invtweaks.api.container.ContainerSection; - -public class MysteriumPatchesFixesO { - - private static final MethodHandle fieldGetSection; - private static final MethodHandle fieldGetContainerMgr; - - static { - MethodHandle fs, fs2, fg, fg2, fg3; - Field f, f2, f3, f4; - try { - - f2 = InvTweaksContainerSectionManager.class.getDeclaredField("containerMgr"); - f3 = InvTweaksContainerSectionManager.class.getDeclaredField("section"); - - f2.setAccessible(true); - f3.setAccessible(true); - - fg = MethodHandles.publicLookup() - .unreflectGetter(f2); - fg2 = MethodHandles.publicLookup() - .unreflectGetter(f3); - } catch (Exception | NoClassDefFoundError e) { - f = null; - fs = null; - fg = null; - fg2 = null; - } - fieldGetContainerMgr = fg; - fieldGetSection = fg2; - - // System.out.println("Loaded Mod Compatibility!"); - } - - @Optional.Method(modid = "inventorytweaks") - public static ContainerSection getContainerSection(InvTweaksContainerSectionManager itcm) { - ContainerSection section; - try { - section = (ContainerSection) fieldGetSection.invokeExact((InvTweaksContainerSectionManager) itcm); - } catch (Throwable e) { - /* - * System.out. - * println("The 'Inventory Tweaks' mod compatibility hasn't been loaded due to not being able to find ContainerSection. " - * + - * "If you don't have the 'Inventory Tweaks' mod installed, you can ignore this error."); - */ - section = null; - } - return section; - } - - @Optional.Method(modid = "inventorytweaks") - public static InvTweaksContainerManager getContainerManager(InvTweaksContainerSectionManager itcm) { - InvTweaksContainerManager manager; - try { - manager = (InvTweaksContainerManager) fieldGetContainerMgr - .invokeExact((InvTweaksContainerSectionManager) itcm); - } catch (Throwable e) { - /* - * System.out. - * println("The 'Inventory Tweaks' mod compatibility hasn't been loaded due to not being able to find InvTweaksContainerManager. " - * + - * "If you don't have the 'Inventory Tweaks' mod installed, you can ignore this error."); - */ - manager = null; - } - return manager; - } - - // Todo: Angelica is a thing so this is probably not needed - - // @Optional.Method(modid = "Optifine") - // @SideOnly(Side.CLIENT) - // @Fix(insertOnExit = true, returnSetting = EnumReturnSetting.ALWAYS) - // public static int getLightLevel(Entity entity, @ReturnedValue int returned) { - // if (entity instanceof EntityPlayer) { - // EntityPlayer player = (EntityPlayer) entity; - // ItemStack offhand = BackhandUtils.getOffhandItem(player); - // try { - // Method getLightLevel = Class.forName("DynamicLights") - // .getMethod("getLightLevel", ItemStack.class); - // int levelMain = (int) getLightLevel.invoke(null, offhand); - // ItemStack stackHead = player.getEquipmentInSlot(4); - // int levelHead = (int) getLightLevel.invoke(null, stackHead); - // return Math.max(levelMain, levelHead); - // } catch (Exception ignored) {} - // } - // return returned; - // } - -} diff --git a/src/main/java/net/tclproject/mysteriumlib/math/LocalityHelper.java b/src/main/java/net/tclproject/mysteriumlib/math/LocalityHelper.java deleted file mode 100644 index 6dc5dbb..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/math/LocalityHelper.java +++ /dev/null @@ -1,24 +0,0 @@ -package net.tclproject.mysteriumlib.math; - -public class LocalityHelper { - - public static int locality(int x, int y, int seed, int width) { - return localitySingle(x, y, seed, width) * 7 + localitySingle(x, y, seed, width / 2) * 4 - + localitySingle(x, y, seed, width / 4); - } - - public static int localitySingle(int x, int y, int seed, int width) { - int qa = localityAxis(x, seed, width); - int qb = localityAxis(y, seed, width); - return Math.abs(qa - 6) > Math.abs(qb - 6) ? qa : qb; - } - - public static int localityAxis(int coordinate, int seed, int width) { - int q = Math.abs(coordinate) + Math.abs(seed); - int q1 = q / width % width; - q %= width; - int q2 = (q1 + 1) * 21 % 13; - q1 = q1 * 21 % 13; - return (q2 - q1) * q / width + q1; - } -} diff --git a/src/main/java/net/tclproject/mysteriumlib/math/NoiseStretch.java b/src/main/java/net/tclproject/mysteriumlib/math/NoiseStretch.java deleted file mode 100644 index d00bffe..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/math/NoiseStretch.java +++ /dev/null @@ -1,39 +0,0 @@ -package net.tclproject.mysteriumlib.math; - -public class NoiseStretch { - - protected final double stretchX; - protected final double stretchY; - protected final double stretchZ; - protected final double offsetX; - protected final double offsetY; - protected final double offsetZ; - protected final SimplexNoise noise; - - public NoiseStretch(SimplexNoise noise, double stretchX, double stretchZ, double offsetX, double offsetZ) { - this(noise, stretchX, 100.0D, stretchZ, offsetX, 0.0D, offsetZ); - } - - public NoiseStretch(SimplexNoise noise, double stretchX, double stretchY, double stretchZ, double offsetX, - double offsetY, double offsetZ) { - this.noise = noise; - this.stretchX = stretchX; - this.stretchY = stretchY + 100D; - this.stretchZ = stretchZ; - this.offsetX = offsetX; - this.offsetY = offsetY; - this.offsetZ = offsetZ; - } - - public double getNoise(double blockX, double blockZ) { - return this.noise - .noise(blockX / (this.stretchX * 2.5) + this.offsetX, blockZ / (this.stretchZ * 2.5) + this.offsetZ); - } - - public double getNoise(double blockX, double blockY, double blockZ) { - return this.noise.noise( - blockX / this.stretchX + this.offsetX, - blockY / this.stretchY + this.offsetY, - blockZ / this.stretchZ + this.offsetZ); - } -} diff --git a/src/main/java/net/tclproject/mysteriumlib/math/SimplexNoise.java b/src/main/java/net/tclproject/mysteriumlib/math/SimplexNoise.java deleted file mode 100644 index df5088b..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/math/SimplexNoise.java +++ /dev/null @@ -1,441 +0,0 @@ -package net.tclproject.mysteriumlib.math; - -import java.util.Random; - -public class SimplexNoise { - - private static final SimplexNoise.Grad[] grad3 = new SimplexNoise.Grad[] { new SimplexNoise.Grad(1.0D, 1.0D, 0.0D), - new SimplexNoise.Grad(-1.0D, 1.0D, 0.0D), new SimplexNoise.Grad(1.0D, -1.0D, 0.0D), - new SimplexNoise.Grad(-1.0D, -1.0D, 0.0D), new SimplexNoise.Grad(1.0D, 0.0D, 1.0D), - new SimplexNoise.Grad(-1.0D, 0.0D, 1.0D), new SimplexNoise.Grad(1.0D, 0.0D, -1.0D), - new SimplexNoise.Grad(-1.0D, 0.0D, -1.0D), new SimplexNoise.Grad(0.0D, 1.0D, 1.0D), - new SimplexNoise.Grad(0.0D, -1.0D, 1.0D), new SimplexNoise.Grad(0.0D, 1.0D, -1.0D), - new SimplexNoise.Grad(0.0D, -1.0D, -1.0D) }; - private static final SimplexNoise.Grad[] grad4 = new SimplexNoise.Grad[] { - new SimplexNoise.Grad(0.0D, 1.0D, 1.0D, 1.0D), new SimplexNoise.Grad(0.0D, 1.0D, 1.0D, -1.0D), - new SimplexNoise.Grad(0.0D, 1.0D, -1.0D, 1.0D), new SimplexNoise.Grad(0.0D, 1.0D, -1.0D, -1.0D), - new SimplexNoise.Grad(0.0D, -1.0D, 1.0D, 1.0D), new SimplexNoise.Grad(0.0D, -1.0D, 1.0D, -1.0D), - new SimplexNoise.Grad(0.0D, -1.0D, -1.0D, 1.0D), new SimplexNoise.Grad(0.0D, -1.0D, -1.0D, -1.0D), - new SimplexNoise.Grad(1.0D, 0.0D, 1.0D, 1.0D), new SimplexNoise.Grad(1.0D, 0.0D, 1.0D, -1.0D), - new SimplexNoise.Grad(1.0D, 0.0D, -1.0D, 1.0D), new SimplexNoise.Grad(1.0D, 0.0D, -1.0D, -1.0D), - new SimplexNoise.Grad(-1.0D, 0.0D, 1.0D, 1.0D), new SimplexNoise.Grad(-1.0D, 0.0D, 1.0D, -1.0D), - new SimplexNoise.Grad(-1.0D, 0.0D, -1.0D, 1.0D), new SimplexNoise.Grad(-1.0D, 0.0D, -1.0D, -1.0D), - new SimplexNoise.Grad(1.0D, 1.0D, 0.0D, 1.0D), new SimplexNoise.Grad(1.0D, 1.0D, 0.0D, -1.0D), - new SimplexNoise.Grad(1.0D, -1.0D, 0.0D, 1.0D), new SimplexNoise.Grad(1.0D, -1.0D, 0.0D, -1.0D), - new SimplexNoise.Grad(-1.0D, 1.0D, 0.0D, 1.0D), new SimplexNoise.Grad(-1.0D, 1.0D, 0.0D, -1.0D), - new SimplexNoise.Grad(-1.0D, -1.0D, 0.0D, 1.0D), new SimplexNoise.Grad(-1.0D, -1.0D, 0.0D, -1.0D), - new SimplexNoise.Grad(1.0D, 1.0D, 1.0D, 0.0D), new SimplexNoise.Grad(1.0D, 1.0D, -1.0D, 0.0D), - new SimplexNoise.Grad(1.0D, -1.0D, 1.0D, 0.0D), new SimplexNoise.Grad(1.0D, -1.0D, -1.0D, 0.0D), - new SimplexNoise.Grad(-1.0D, 1.0D, 1.0D, 0.0D), new SimplexNoise.Grad(-1.0D, 1.0D, -1.0D, 0.0D), - new SimplexNoise.Grad(-1.0D, -1.0D, 1.0D, 0.0D), new SimplexNoise.Grad(-1.0D, -1.0D, -1.0D, 0.0D) }; - private static final double F2 = 0.5D * (Math.sqrt(3.0D) - 1.0D); - private static final double G2 = (3.0D - Math.sqrt(3.0D)) / 6.0D; - private static final double F4 = (Math.sqrt(5.0D) - 1.0D) / 4.0D; - private static final double G4 = (5.0D - Math.sqrt(5.0D)) / 20.0D; - protected final short[] doubledPermutationTable; - protected final short[] variatedPermutationTable; - protected final Random random; - - private static int fastfloor(double x) { - int xi = (int) x; - return x < xi ? xi - 1 : xi; - } - - private static double dot(SimplexNoise.Grad g, double x, double y) { - return g.x * x + g.y * y; - } - - private static double dot(SimplexNoise.Grad g, double x, double y, double z) { - return g.x * x + g.y * y + g.z * z; - } - - private static double dot(SimplexNoise.Grad g, double x, double y, double z, double w) { - return g.x * x + g.y * y + g.z * z + g.w * w; - } - - public SimplexNoise(Random random) { - byte[] bytes = new byte[1024]; - this.random = random; - random.nextBytes(bytes); - this.doubledPermutationTable = new short[bytes.length * 2]; - this.variatedPermutationTable = new short[this.doubledPermutationTable.length]; - - for (int i = 0; i < bytes.length; ++i) { - short value = (short) (bytes[i] & 255); - this.doubledPermutationTable[i] = value; - this.variatedPermutationTable[i] = (short) (value % 12); - } - - System.arraycopy(this.doubledPermutationTable, 0, this.doubledPermutationTable, bytes.length, bytes.length); - System.arraycopy(this.variatedPermutationTable, 0, this.variatedPermutationTable, bytes.length, bytes.length); - } - - public Random getRandom() { - return this.random; - } - - public NoiseStretch generateNoiseStretcher(double stretchX, double stretchZ, double offsetX, double offsetZ) { - return new NoiseStretch(this, stretchX, stretchZ, offsetX, offsetZ); - } - - public NoiseStretch generateNoiseStretcher(double stretchX, double stretchY, double stretchZ, double offsetX, - double offsetY, double offsetZ) { - return new NoiseStretch(this, stretchX, stretchY, stretchZ, offsetX, offsetY, offsetZ); - } - - public double noise(double xin, double yin) { - double s = (xin + yin) * F2; - int i = fastfloor(xin + s); - int j = fastfloor(yin + s); - double t = (i + j) * G2; - double X0 = i - t; - double Y0 = j - t; - double x0 = xin - X0; - double y0 = yin - Y0; - byte i1; - byte j1; - if (x0 > y0) { - i1 = 1; - j1 = 0; - } else { - i1 = 0; - j1 = 1; - } - - double x1 = x0 - i1 + G2; - double y1 = y0 - j1 + G2; - double x2 = x0 - 1.0D + 2.0D * G2; - double y2 = y0 - 1.0D + 2.0D * G2; - int ii = i & 1023; - int jj = j & 1023; - int gi0 = this.variatedPermutationTable[ii + this.doubledPermutationTable[jj]]; - int gi1 = this.variatedPermutationTable[ii + i1 + this.doubledPermutationTable[jj + j1]]; - int gi2 = this.variatedPermutationTable[ii + 1 + this.doubledPermutationTable[jj + 1]]; - double t0 = 0.5D - x0 * x0 - y0 * y0; - double n0; - if (t0 < 0.0D) { - n0 = 0.0D; - } else { - t0 *= t0; - n0 = t0 * t0 * dot(grad3[gi0], x0, y0); - } - - double t1 = 0.5D - x1 * x1 - y1 * y1; - double n1; - if (t1 < 0.0D) { - n1 = 0.0D; - } else { - t1 *= t1; - n1 = t1 * t1 * dot(grad3[gi1], x1, y1); - } - - double t2 = 0.5D - x2 * x2 - y2 * y2; - double n2; - if (t2 < 0.0D) { - n2 = 0.0D; - } else { - t2 *= t2; - n2 = t2 * t2 * dot(grad3[gi2], x2, y2); - } - - return 70.0D * (n0 + n1 + n2); - } - - public double noise(double xin, double yin, double zin) { - double s = (xin + yin + zin) * 0.3333333333333333D; - int i = fastfloor(xin + s); - int j = fastfloor(yin + s); - int k = fastfloor(zin + s); - double t = (i + j + k) * 0.16666666666666666D; - double X0 = i - t; - double Y0 = j - t; - double Z0 = k - t; - double x0 = xin - X0; - double y0 = yin - Y0; - double z0 = zin - Z0; - byte i1; - byte j1; - byte k1; - byte i2; - byte j2; - byte k2; - if (x0 >= y0) { - if (y0 >= z0) { - i1 = 1; - j1 = 0; - k1 = 0; - i2 = 1; - j2 = 1; - k2 = 0; - } else if (x0 >= z0) { - i1 = 1; - j1 = 0; - k1 = 0; - i2 = 1; - j2 = 0; - k2 = 1; - } else { - i1 = 0; - j1 = 0; - k1 = 1; - i2 = 1; - j2 = 0; - k2 = 1; - } - } else if (y0 < z0) { - i1 = 0; - j1 = 0; - k1 = 1; - i2 = 0; - j2 = 1; - k2 = 1; - } else if (x0 < z0) { - i1 = 0; - j1 = 1; - k1 = 0; - i2 = 0; - j2 = 1; - k2 = 1; - } else { - i1 = 0; - j1 = 1; - k1 = 0; - i2 = 1; - j2 = 1; - k2 = 0; - } - - double x1 = x0 - i1 + 0.16666666666666666D; - double y1 = y0 - j1 + 0.16666666666666666D; - double z1 = z0 - k1 + 0.16666666666666666D; - double x2 = x0 - i2 + 0.3333333333333333D; - double y2 = y0 - j2 + 0.3333333333333333D; - double z2 = z0 - k2 + 0.3333333333333333D; - double x3 = x0 - 1.0D + 0.5D; - double y3 = y0 - 1.0D + 0.5D; - double z3 = z0 - 1.0D + 0.5D; - int ii = i & 255; - int jj = j & 255; - int kk = k & 255; - int gi0 = this.variatedPermutationTable[ii - + this.doubledPermutationTable[jj + this.doubledPermutationTable[kk]]]; - int gi1 = this.variatedPermutationTable[ii + i1 - + this.doubledPermutationTable[jj + j1 + this.doubledPermutationTable[kk + k1]]]; - int gi2 = this.variatedPermutationTable[ii + i2 - + this.doubledPermutationTable[jj + j2 + this.doubledPermutationTable[kk + k2]]]; - int gi3 = this.variatedPermutationTable[ii + 1 - + this.doubledPermutationTable[jj + 1 + this.doubledPermutationTable[kk + 1]]]; - double t0 = 0.6D - x0 * x0 - y0 * y0 - z0 * z0; - double n0; - if (t0 < 0.0D) { - n0 = 0.0D; - } else { - t0 *= t0; - n0 = t0 * t0 * dot(grad3[gi0], x0, y0, z0); - } - - double t1 = 0.6D - x1 * x1 - y1 * y1 - z1 * z1; - double n1; - if (t1 < 0.0D) { - n1 = 0.0D; - } else { - t1 *= t1; - n1 = t1 * t1 * dot(grad3[gi1], x1, y1, z1); - } - - double t2 = 0.6D - x2 * x2 - y2 * y2 - z2 * z2; - double n2; - if (t2 < 0.0D) { - n2 = 0.0D; - } else { - t2 *= t2; - n2 = t2 * t2 * dot(grad3[gi2], x2, y2, z2); - } - - double t3 = 0.6D - x3 * x3 - y3 * y3 - z3 * z3; - double n3; - if (t3 < 0.0D) { - n3 = 0.0D; - } else { - t3 *= t3; - n3 = t3 * t3 * dot(grad3[gi3], x3, y3, z3); - } - - return 32.0D * (n0 + n1 + n2 + n3); - } - - public double noise(double x, double y, double z, double w) { - double s = (x + y + z + w) * F4; - int i = fastfloor(x + s); - int j = fastfloor(y + s); - int k = fastfloor(z + s); - int l = fastfloor(w + s); - double t = (i + j + k + l) * G4; - double X0 = i - t; - double Y0 = j - t; - double Z0 = k - t; - double W0 = l - t; - double x0 = x - X0; - double y0 = y - Y0; - double z0 = z - Z0; - double w0 = w - W0; - int rankx = 0; - int ranky = 0; - int rankz = 0; - int rankw = 0; - if (x0 > y0) { - ++rankx; - } else { - ++ranky; - } - - if (x0 > z0) { - ++rankx; - } else { - ++rankz; - } - - if (x0 > w0) { - ++rankx; - } else { - ++rankw; - } - - if (y0 > z0) { - ++ranky; - } else { - ++rankz; - } - - if (y0 > w0) { - ++ranky; - } else { - ++rankw; - } - - if (z0 > w0) { - ++rankz; - } else { - ++rankw; - } - - int i1 = rankx >= 3 ? 1 : 0; - int j1 = ranky >= 3 ? 1 : 0; - int k1 = rankz >= 3 ? 1 : 0; - int l1 = rankw >= 3 ? 1 : 0; - int i2 = rankx >= 2 ? 1 : 0; - int j2 = ranky >= 2 ? 1 : 0; - int k2 = rankz >= 2 ? 1 : 0; - int l2 = rankw >= 2 ? 1 : 0; - int i3 = rankx >= 1 ? 1 : 0; - int j3 = ranky >= 1 ? 1 : 0; - int k3 = rankz >= 1 ? 1 : 0; - int l3 = rankw >= 1 ? 1 : 0; - double x1 = x0 - i1 + G4; - double y1 = y0 - j1 + G4; - double z1 = z0 - k1 + G4; - double w1 = w0 - l1 + G4; - double x2 = x0 - i2 + 2.0D * G4; - double y2 = y0 - j2 + 2.0D * G4; - double z2 = z0 - k2 + 2.0D * G4; - double w2 = w0 - l2 + 2.0D * G4; - double x3 = x0 - i3 + 3.0D * G4; - double y3 = y0 - j3 + 3.0D * G4; - double z3 = z0 - k3 + 3.0D * G4; - double w3 = w0 - l3 + 3.0D * G4; - double x4 = x0 - 1.0D + 4.0D * G4; - double y4 = y0 - 1.0D + 4.0D * G4; - double z4 = z0 - 1.0D + 4.0D * G4; - double w4 = w0 - 1.0D + 4.0D * G4; - int ii = i & 255; - int jj = j & 255; - int kk = k & 255; - int ll = l & 255; - int gi0 = this.doubledPermutationTable[ii - + this.doubledPermutationTable[jj + this.doubledPermutationTable[kk + this.doubledPermutationTable[ll]]]] - % 32; - int gi1 = this.doubledPermutationTable[ii + i1 - + this.doubledPermutationTable[jj + j1 - + this.doubledPermutationTable[kk + k1 + this.doubledPermutationTable[ll + l1]]]] - % 32; - int gi2 = this.doubledPermutationTable[ii + i2 - + this.doubledPermutationTable[jj + j2 - + this.doubledPermutationTable[kk + k2 + this.doubledPermutationTable[ll + l2]]]] - % 32; - int gi3 = this.doubledPermutationTable[ii + i3 - + this.doubledPermutationTable[jj + j3 - + this.doubledPermutationTable[kk + k3 + this.doubledPermutationTable[ll + l3]]]] - % 32; - int gi4 = this.doubledPermutationTable[ii + 1 - + this.doubledPermutationTable[jj + 1 - + this.doubledPermutationTable[kk + 1 + this.doubledPermutationTable[ll + 1]]]] - % 32; - double t0 = 0.6D - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0; - double n0; - if (t0 < 0.0D) { - n0 = 0.0D; - } else { - t0 *= t0; - n0 = t0 * t0 * dot(grad4[gi0], x0, y0, z0, w0); - } - - double t1 = 0.6D - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1; - double n1; - if (t1 < 0.0D) { - n1 = 0.0D; - } else { - t1 *= t1; - n1 = t1 * t1 * dot(grad4[gi1], x1, y1, z1, w1); - } - - double t2 = 0.6D - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2; - double n2; - if (t2 < 0.0D) { - n2 = 0.0D; - } else { - t2 *= t2; - n2 = t2 * t2 * dot(grad4[gi2], x2, y2, z2, w2); - } - - double t3 = 0.6D - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3; - double n3; - if (t3 < 0.0D) { - n3 = 0.0D; - } else { - t3 *= t3; - n3 = t3 * t3 * dot(grad4[gi3], x3, y3, z3, w3); - } - - double t4 = 0.6D - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4; - double n4; - if (t4 < 0.0D) { - n4 = 0.0D; - } else { - t4 *= t4; - n4 = t4 * t4 * dot(grad4[gi4], x4, y4, z4, w4); - } - - return 27.0D * (n0 + n1 + n2 + n3 + n4); - } - - private static class Grad { - - double x; - double y; - double z; - double w; - - Grad(double x, double y, double z) { - this.x = x; - this.y = y; - this.z = z; - } - - Grad(double x, double y, double z, double w) { - this.x = x; - this.y = y; - this.z = z; - this.w = w; - } - } -} diff --git a/src/main/java/net/tclproject/mysteriumlib/math/SpiralPatternGenerator.java b/src/main/java/net/tclproject/mysteriumlib/math/SpiralPatternGenerator.java deleted file mode 100644 index 11b6fd4..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/math/SpiralPatternGenerator.java +++ /dev/null @@ -1,114 +0,0 @@ -package net.tclproject.mysteriumlib.math; - -import java.util.Iterator; - -import net.minecraft.world.ChunkCoordIntPair; - -import joptsimple.internal.Objects; - -public class SpiralPatternGenerator implements Iterable { - - protected final ChunkCoordIntPair center; - protected final int rangeMax; - - public SpiralPatternGenerator(ChunkCoordIntPair center) { - this(center, Integer.MAX_VALUE); - } - - public SpiralPatternGenerator(ChunkCoordIntPair center, int rangeMax) { - Objects.ensureNotNull(center); - if (rangeMax < 0) { - throw new IllegalArgumentException("The maximum range must be more than or equal to 0."); - } else { - this.center = center; - this.rangeMax = rangeMax; - } - } - - @Override - public Iterator iterator() { - return new Iterator() { - - private int currentX; - private int currentZ; - protected SpiralPatternGenerator.SpiralDirection currentDirection; - private int currentRange = 0; - - @Override - public boolean hasNext() { - return this.currentRange <= SpiralPatternGenerator.this.rangeMax; - } - - @Override - public ChunkCoordIntPair next() { - if (this.currentRange == 0) { - ++this.currentRange; - this.currentX = SpiralPatternGenerator.this.center.chunkXPos - this.currentRange; - this.currentZ = SpiralPatternGenerator.this.center.chunkZPos - this.currentRange; - this.currentDirection = SpiralPatternGenerator.SpiralDirection.right; - return SpiralPatternGenerator.this.center; - } else { - ChunkCoordIntPair result = new ChunkCoordIntPair(this.currentX, this.currentZ); - this.step(); - return result; - } - } - - protected void step() { - switch (this.currentDirection) { - case right: - if (this.currentX < SpiralPatternGenerator.this.center.chunkXPos + this.currentRange) { - ++this.currentX; - } else { - this.currentDirection = SpiralPatternGenerator.SpiralDirection.down; - this.step(); - } - case down: - if (this.currentZ < SpiralPatternGenerator.this.center.chunkZPos + this.currentRange) { - ++this.currentZ; - } else { - this.currentDirection = SpiralPatternGenerator.SpiralDirection.left; - this.step(); - } - case left: - if (this.currentX > SpiralPatternGenerator.this.center.chunkXPos - this.currentRange) { - --this.currentX; - } else { - this.currentDirection = SpiralPatternGenerator.SpiralDirection.up; - this.step(); - } - case up: - if (this.currentZ - 1 > SpiralPatternGenerator.this.center.chunkZPos - this.currentRange) { - --this.currentZ; - } else { - this.currentDirection = SpiralPatternGenerator.SpiralDirection.right; - ++this.currentRange; - this.currentX = SpiralPatternGenerator.this.center.chunkXPos - this.currentRange; - this.currentZ = SpiralPatternGenerator.this.center.chunkZPos - this.currentRange; - } - default: - } - } - - @Override - public void remove() { - throw new UnsupportedOperationException("Not supported at this moment in time."); - } - }; - } - - public ChunkCoordIntPair getCenter() { - return this.center; - } - - public int getRangeMax() { - return this.rangeMax; - } - - private static enum SpiralDirection { - right, - down, - left, - up; - } -} diff --git a/src/main/java/net/tclproject/mysteriumlib/math/Stopwatch.java b/src/main/java/net/tclproject/mysteriumlib/math/Stopwatch.java deleted file mode 100644 index 0231b6e..0000000 --- a/src/main/java/net/tclproject/mysteriumlib/math/Stopwatch.java +++ /dev/null @@ -1,51 +0,0 @@ -package net.tclproject.mysteriumlib.math; - -/** Class for measuring time passed. */ -public class Stopwatch { - - /** The name of the stopwatch. */ - final String name; - /** The time at which the stopwatch started counting. */ - long timeStart; - /** How much times the stopwatch has been started and stopped. */ - double calls; - /** The total time across all the time the stopwatch has been counting time. */ - double timeTotal; - /** The maximum time ever taken between start and stop calls. */ - double timeMax; - /** The minimum time ever taken between start and stop calls. */ - double timeMin; - /** The time taken between the most recent start and stop calls. */ - double timeTaken; - - public Stopwatch(String stopwatchName) { - this.name = stopwatchName; - this.timeMax = -1.0D; - this.timeMin = -1.0D; - } - - /** Starts the counting. */ - public void start() { - this.timeStart = System.nanoTime(); - } - - /** Stops the counting and updates the variables. */ - public void stop() { - ++this.calls; - double timeTaken = (System.nanoTime() - this.timeStart) / 1000000.0D; - this.timeTotal += timeTaken; - this.timeMax = this.timeMax == -1.0D ? timeTaken : Math.max(timeTaken, this.timeMax); - this.timeMin = this.timeMin == -1.0D ? timeTaken : Math.min(timeTaken, this.timeMin); - } - - /** Prints out all the variables in an easy to see manner. */ - @Override - public String toString() { - return String.format( - "[%s]: Time [avg]: %3.2f ms, [min]: %3.2f ms, [max]: %3.2f ms", - this.name, - this.timeTotal / this.calls, - this.timeMin, - this.timeMax); - } -} diff --git a/src/main/java/xonin/backhand/api/core/BackhandTranslator.java b/src/main/java/xonin/backhand/api/core/BackhandTranslator.java index dba69a4..0c6845d 100644 --- a/src/main/java/xonin/backhand/api/core/BackhandTranslator.java +++ b/src/main/java/xonin/backhand/api/core/BackhandTranslator.java @@ -1,21 +1,14 @@ package xonin.backhand.api.core; -import net.tclproject.mysteriumlib.asm.common.CustomLoadingPlugin; +import net.minecraft.launchwrapper.Launch; public class BackhandTranslator { - public static boolean debug = false; - public static boolean obfuscatedEnv; - - /** @deprecated */ - @Deprecated - public static String getMapedFieldName(String className, String fieldName, String devName) { - return getMapedFieldName(fieldName, devName); + static { + obfuscatedEnv = (Boolean) Launch.blackboard.get("fml.deobfuscatedEnvironment"); } - public static String getMapedFieldName(String fieldName, String devName) { - return CustomLoadingPlugin.isObfuscated() ? fieldName : devName; - } + public static boolean obfuscatedEnv; public static String getMapedClassName(String className) { return "net/minecraft/" + className.replace(".", "/"); @@ -28,7 +21,7 @@ public static String getMapedMethodName(String className, String methodName, Str } public static String getMapedMethodName(String methodName, String devName) { - return CustomLoadingPlugin.isObfuscated() ? methodName : devName; + return obfuscatedEnv ? devName : methodName; } /** @deprecated */ diff --git a/src/main/java/xonin/backhand/api/core/BackhandUtils.java b/src/main/java/xonin/backhand/api/core/BackhandUtils.java index ebb290f..2f2f4b2 100644 --- a/src/main/java/xonin/backhand/api/core/BackhandUtils.java +++ b/src/main/java/xonin/backhand/api/core/BackhandUtils.java @@ -494,7 +494,6 @@ public static void closeStream(Closeable c) { */ public static ItemStack beforeFinishUseEvent(EntityPlayer entityPlayer, ItemStack itemInUse, int itemInUseCount, ItemStack result, int previousStackSize) { - result = ForgeEventFactory.onItemUseFinish(entityPlayer, itemInUse, itemInUseCount, result); if (result != itemInUse || (result != null && result.stackSize != previousStackSize)) { // Compare with either hands content if (itemInUse == entityPlayer.getCurrentEquippedItem()) { diff --git a/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java b/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java index 3cd09e1..0085817 100644 --- a/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java +++ b/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java @@ -2,26 +2,37 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Set; -import net.tclproject.mysteriumlib.asm.common.CustomLoadingPlugin; -import net.tclproject.mysteriumlib.asm.common.FirstClassTransformer; - import com.gtnewhorizon.gtnhmixins.IEarlyMixinLoader; import cpw.mods.fml.relauncher.FMLLaunchHandler; import cpw.mods.fml.relauncher.IFMLLoadingPlugin; -public final class BackhandLoadingPlugin extends CustomLoadingPlugin implements IFMLLoadingPlugin, IEarlyMixinLoader { +public final class BackhandLoadingPlugin implements IFMLLoadingPlugin, IEarlyMixinLoader { @Override public String[] getASMTransformerClass() { - return new String[] { FirstClassTransformer.class.getName() }; + return null; } @Override - public void registerFixes() { - registerClassWithFixes("net.tclproject.mysteriumlib.asm.fixes.MysteriumPatchesFixesO"); + public String getModContainerClass() { + return null; + } + + @Override + public String getSetupClass() { + return null; + } + + @Override + public void injectData(Map data) {} + + @Override + public String getAccessTransformerClass() { + return null; } @Override diff --git a/src/main/resources/methods.bin b/src/main/resources/methods.bin deleted file mode 100644 index 0b753708f3be57ac19788e7c6ee20381f4dda536..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 84382 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 q%_ierD0Rx?Tf+t==&- Date: Thu, 25 Jul 2024 22:11:40 +0200 Subject: [PATCH 5/9] forgot a few things --- .../api/core/InventoryPlayerBackhand.java | 8 + .../client/utils/BackhandRenderHelper.java | 3 +- .../mixins/early/MixinEntityPlayer.java | 16 -- .../mixins/early/MixinInventoryPlayer.java | 36 ---- .../mixins/early/MixinItemRenderer.java | 1 - .../mixins/early/MixinModelBiped.java | 191 ++++-------------- .../mixins/early/MixinPlayerControllerMP.java | 27 --- 7 files changed, 49 insertions(+), 233 deletions(-) delete mode 100644 src/main/java/xonin/backhand/mixins/early/MixinInventoryPlayer.java diff --git a/src/main/java/xonin/backhand/api/core/InventoryPlayerBackhand.java b/src/main/java/xonin/backhand/api/core/InventoryPlayerBackhand.java index e8c2573..0084570 100644 --- a/src/main/java/xonin/backhand/api/core/InventoryPlayerBackhand.java +++ b/src/main/java/xonin/backhand/api/core/InventoryPlayerBackhand.java @@ -136,4 +136,12 @@ public void dropAllItems() { this.player.func_146097_a(this.getOffhandItem(), true, false); this.setOffhandItem(null); } + + @Override + public ItemStack getCurrentItem() { + if (currentItem == InventoryPlayerBackhand.OFFHAND_HOTBAR_SLOT) { + return BackhandUtils.getOffhandItem(player); + } + return super.getCurrentItem(); + } } diff --git a/src/main/java/xonin/backhand/client/utils/BackhandRenderHelper.java b/src/main/java/xonin/backhand/client/utils/BackhandRenderHelper.java index 3060ba1..1e0118d 100644 --- a/src/main/java/xonin/backhand/client/utils/BackhandRenderHelper.java +++ b/src/main/java/xonin/backhand/client/utils/BackhandRenderHelper.java @@ -43,7 +43,8 @@ public final class BackhandRenderHelper { @SuppressWarnings("SuspiciousNameCombination") public static void moveOffHandArm(Entity entity, ModelBiped biped, float frame) { - if (entity instanceof IBackhandPlayer player) { + if (entity instanceof IBackhandPlayer player && (player != Minecraft.getMinecraft().thePlayer + || player.getOffSwingProgress(BackhandClientUtils.firstPersonFrame) != 0)) { float offhandSwing = player.getOffSwingProgress(frame); if (offhandSwing > 0.0F) { diff --git a/src/main/java/xonin/backhand/mixins/early/MixinEntityPlayer.java b/src/main/java/xonin/backhand/mixins/early/MixinEntityPlayer.java index d4e9e86..5a01b4c 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinEntityPlayer.java +++ b/src/main/java/xonin/backhand/mixins/early/MixinEntityPlayer.java @@ -4,7 +4,6 @@ import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; -import net.minecraft.inventory.Container; import net.minecraft.item.ItemStack; import net.minecraft.world.World; @@ -29,8 +28,6 @@ public abstract class MixinEntityPlayer extends EntityLivingBase implements IBac private int itemInUseCount; @Shadow public InventoryPlayer inventory = new InventoryPlayerBackhand((EntityPlayer) (Object) this); - @Shadow - public Container inventoryContainer; @Unique private float backhand$offHandSwingProgress = 0F; @Unique @@ -52,19 +49,6 @@ private MixinEntityPlayer(World p_i1594_1_) { return false; } - // //TODO: InventoryPlayerBackhand doesn't override setInventorySlotContents so is this even needed? - // @ModifyExpressionValue( - // method = "setCurrentItemOrArmor", - // at = @At( - // value = "FIELD", - // opcode = Opcodes.GETFIELD, - // target = "Lnet/minecraft/entity/player/InventoryPlayer;mainInventory:[Lnet/minecraft/item/ItemStack;")) - // private ItemStack[] backhand$setCurrentItemOrArmor(ItemStack[] original, @Local(argsOnly = true) ItemStack stack) - // { - // BackhandUtils.setPlayerCurrentItem((EntityPlayer) (Object) this, stack); - // return new ItemStack[inventory.mainInventory.length]; - // } - @ModifyExpressionValue( method = "onItemUseFinish", at = @At( diff --git a/src/main/java/xonin/backhand/mixins/early/MixinInventoryPlayer.java b/src/main/java/xonin/backhand/mixins/early/MixinInventoryPlayer.java deleted file mode 100644 index 989fe2c..0000000 --- a/src/main/java/xonin/backhand/mixins/early/MixinInventoryPlayer.java +++ /dev/null @@ -1,36 +0,0 @@ -package xonin.backhand.mixins.early; - -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.entity.player.InventoryPlayer; -import net.minecraft.item.ItemStack; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; - -import com.llamalad7.mixinextras.injector.ModifyReturnValue; - -import xonin.backhand.api.core.BackhandUtils; -import xonin.backhand.api.core.InventoryPlayerBackhand; - -@Mixin(InventoryPlayer.class) -public abstract class MixinInventoryPlayer { - - // Todo: We're already replacing the inventory in EntityPlayer, can this instead be an @Override in - // InventoryPlayerBackhand? - - @Shadow - public int currentItem; - - @Shadow - public EntityPlayer player; - - @ModifyReturnValue(method = "getCurrentItem", at = @At("RETURN")) - private ItemStack backhand$getOffhandItem(ItemStack original) { - if (currentItem == InventoryPlayerBackhand.OFFHAND_HOTBAR_SLOT) { - return BackhandUtils.getOffhandItem(player); - } - - return original; - } -} diff --git a/src/main/java/xonin/backhand/mixins/early/MixinItemRenderer.java b/src/main/java/xonin/backhand/mixins/early/MixinItemRenderer.java index a46b959..230a18e 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; diff --git a/src/main/java/xonin/backhand/mixins/early/MixinModelBiped.java b/src/main/java/xonin/backhand/mixins/early/MixinModelBiped.java index 2fe92b8..e6ac0d1 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinModelBiped.java +++ b/src/main/java/xonin/backhand/mixins/early/MixinModelBiped.java @@ -1,17 +1,31 @@ package xonin.backhand.mixins.early; +import net.minecraft.client.Minecraft; +import net.minecraft.client.model.ModelBase; import net.minecraft.client.model.ModelBiped; +import net.minecraft.client.model.ModelRenderer; import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.MathHelper; 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; +import xonin.backhand.api.core.BackhandUtils; import xonin.backhand.client.utils.BackhandRenderHelper; @Mixin(ModelBiped.class) -public abstract class MixinModelBiped { +public abstract class MixinModelBiped extends ModelBase { + + @Shadow + public ModelRenderer bipedHead; + @Shadow + public ModelRenderer bipedRightArm; + @Shadow + public ModelRenderer bipedLeftArm; @Inject( method = "setRotationAngles", @@ -21,156 +35,29 @@ public abstract class MixinModelBiped { BackhandRenderHelper.moveOffHandArm(entity, (ModelBiped) (Object) this, f6); } - // TODO: Decipher this shit & is it even needed in the first place - // private static void setRotationAngles(ModelBiped b, float p_78087_1_, float p_78087_2_, float p_78087_3_, - // float p_78087_4_, float p_78087_5_, float p_78087_6_, Entity p_78087_7_) { - // b.bipedHead.rotateAngleY = p_78087_4_ / (180F / (float) Math.PI); - // b.bipedHead.rotateAngleX = p_78087_5_ / (180F / (float) Math.PI); - // b.bipedHeadwear.rotateAngleY = b.bipedHead.rotateAngleY; - // b.bipedHeadwear.rotateAngleX = b.bipedHead.rotateAngleX; - // b.bipedRightArm.rotateAngleX = MathHelper.cos(p_78087_1_ * 0.6662F + (float) Math.PI) * 2.0F - // * p_78087_2_ - // * 0.5F; - // b.bipedLeftArm.rotateAngleX = MathHelper.cos(p_78087_1_ * 0.6662F) * 2.0F * p_78087_2_ * 0.5F; - // b.bipedRightArm.rotateAngleZ = 0.0F; - // b.bipedLeftArm.rotateAngleZ = 0.0F; - // b.bipedRightLeg.rotateAngleX = MathHelper.cos(p_78087_1_ * 0.6662F) * 1.4F * p_78087_2_; - // b.bipedLeftLeg.rotateAngleX = MathHelper.cos(p_78087_1_ * 0.6662F + (float) Math.PI) * 1.4F * p_78087_2_; - // b.bipedRightLeg.rotateAngleY = 0.0F; - // b.bipedLeftLeg.rotateAngleY = 0.0F; - // - // if (b.isRiding) { - // b.bipedRightArm.rotateAngleX += -((float) Math.PI / 5F); - // b.bipedLeftArm.rotateAngleX += -((float) Math.PI / 5F); - // b.bipedRightLeg.rotateAngleX = -((float) Math.PI * 2F / 5F); - // b.bipedLeftLeg.rotateAngleX = -((float) Math.PI * 2F / 5F); - // b.bipedRightLeg.rotateAngleY = ((float) Math.PI / 10F); - // b.bipedLeftLeg.rotateAngleY = -((float) Math.PI / 10F); - // } - // - // if (b.heldItemLeft != 0) { - // b.bipedLeftArm.rotateAngleX = b.bipedLeftArm.rotateAngleX * 0.5F - // - ((float) Math.PI / 10F) * (float) b.heldItemLeft; - // } - // - // if (b.heldItemRight != 0) { - // b.bipedRightArm.rotateAngleX = b.bipedRightArm.rotateAngleX * 0.5F - // - ((float) Math.PI / 10F) * (float) b.heldItemRight; - // } - // - // b.bipedRightArm.rotateAngleY = 0.0F; - // b.bipedLeftArm.rotateAngleY = 0.0F; - // float f6; - // float f7; - // - // if (b.onGround > -9990.0F) { - // f6 = b.onGround; - // b.bipedBody.rotateAngleY = MathHelper.sin(MathHelper.sqrt_float(f6) * (float) Math.PI * 2.0F) * 0.2F; - // b.bipedRightArm.rotationPointZ = MathHelper.sin(b.bipedBody.rotateAngleY) * 5.0F; - // b.bipedRightArm.rotationPointX = -MathHelper.cos(b.bipedBody.rotateAngleY) * 5.0F; - // b.bipedLeftArm.rotationPointZ = -MathHelper.sin(b.bipedBody.rotateAngleY) * 5.0F; - // b.bipedLeftArm.rotationPointX = MathHelper.cos(b.bipedBody.rotateAngleY) * 5.0F; - // b.bipedRightArm.rotateAngleY += b.bipedBody.rotateAngleY; - // b.bipedLeftArm.rotateAngleY += b.bipedBody.rotateAngleY; - // b.bipedLeftArm.rotateAngleX += b.bipedBody.rotateAngleY; - // f6 = 1.0F - b.onGround; - // f6 *= f6; - // f6 *= f6; - // f6 = 1.0F - f6; - // f7 = MathHelper.sin(f6 * (float) Math.PI); - // float f8 = MathHelper.sin(b.onGround * (float) Math.PI) * -(b.bipedHead.rotateAngleX - 0.7F) * 0.75F; - // b.bipedRightArm.rotateAngleX = (float) ((double) b.bipedRightArm.rotateAngleX - // - ((double) f7 * 1.2D + (double) f8)); - // b.bipedRightArm.rotateAngleY += b.bipedBody.rotateAngleY * 2.0F; - // b.bipedRightArm.rotateAngleZ = MathHelper.sin(b.onGround * (float) Math.PI) * -0.4F; - // } - // - // if (p_78087_7_ instanceof EntityPlayer && (p_78087_7_ != Minecraft.getMinecraft().thePlayer - // || ((IBackhandPlayer) p_78087_7_).getOffSwingProgress(MysteriumPatchesFixesO.firstPersonFrame) != 0)) { - // if (onGround2 > -9990.0F) { - // f6 = onGround2; - // b.bipedBody.rotateAngleY = MathHelper.sin(MathHelper.sqrt_float(f6) * (float) Math.PI * 2.0F) * 0.2F; - // b.bipedRightArm.rotationPointZ = MathHelper.sin(b.bipedBody.rotateAngleY) * 5.0F; - // b.bipedRightArm.rotationPointX = -MathHelper.cos(b.bipedBody.rotateAngleY) * 5.0F; - // b.bipedLeftArm.rotationPointZ = -MathHelper.sin(b.bipedBody.rotateAngleY) * 5.0F; - // b.bipedLeftArm.rotationPointX = MathHelper.cos(b.bipedBody.rotateAngleY) * 5.0F; - // b.bipedRightArm.rotateAngleY += b.bipedBody.rotateAngleY; - // b.bipedLeftArm.rotateAngleY += b.bipedBody.rotateAngleY; - // b.bipedLeftArm.rotateAngleX += b.bipedBody.rotateAngleY; - // f6 = 1.0F - onGround2; - // f6 *= f6; - // f6 *= f6; - // f6 = 1.0F - f6; - // f7 = MathHelper.sin(f6 * (float) Math.PI); - // float f8 = MathHelper.sin(onGround2 * (float) Math.PI) * -(b.bipedHead.rotateAngleX - 0.7F) * 0.75F; - // b.bipedLeftArm.rotateAngleX = (float) ((double) b.bipedLeftArm.rotateAngleX - // - ((double) f7 * 1.2D + (double) f8)); - // b.bipedLeftArm.rotateAngleY -= b.bipedBody.rotateAngleY * 2.0F; - // b.bipedLeftArm.rotateAngleZ = -MathHelper.sin(onGround2 * (float) Math.PI) * -0.4F; - // } - // } - // - // if (b.isSneak) { - // b.bipedBody.rotateAngleX = 0.5F; - // b.bipedRightArm.rotateAngleX += 0.4F; - // b.bipedLeftArm.rotateAngleX += 0.4F; - // b.bipedRightLeg.rotationPointZ = 4.0F; - // b.bipedLeftLeg.rotationPointZ = 4.0F; - // b.bipedRightLeg.rotationPointY = 9.0F; - // b.bipedLeftLeg.rotationPointY = 9.0F; - // b.bipedHead.rotationPointY = 1.0F; - // b.bipedHeadwear.rotationPointY = 1.0F; - // } else { - // b.bipedBody.rotateAngleX = 0.0F; - // b.bipedRightLeg.rotationPointZ = 0.1F; - // b.bipedLeftLeg.rotationPointZ = 0.1F; - // b.bipedRightLeg.rotationPointY = 12.0F; - // b.bipedLeftLeg.rotationPointY = 12.0F; - // b.bipedHead.rotationPointY = 0.0F; - // b.bipedHeadwear.rotationPointY = 0.0F; - // } - // - // b.bipedRightArm.rotateAngleZ += MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; - // b.bipedLeftArm.rotateAngleZ -= MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; - // b.bipedRightArm.rotateAngleX += MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; - // b.bipedLeftArm.rotateAngleX -= MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; - // - // if (b.aimedBow) { - // if (p_78087_7_ instanceof EntityPlayer && p_78087_7_ == Minecraft.getMinecraft().thePlayer - // && BackhandUtils.getOffhandItem((EntityPlayer) p_78087_7_) != null - // && ((EntityClientPlayerMP) p_78087_7_).getItemInUse() - // == BackhandUtils.getOffhandItem((EntityPlayer) p_78087_7_)) { - // f6 = 0.0F; - // f7 = 0.0F; - // b.bipedLeftArm.rotateAngleZ = 0.0F; - // b.bipedRightArm.rotateAngleZ = 0.0F; - // b.bipedLeftArm.rotateAngleY = 0.1F + b.bipedHead.rotateAngleY; - // b.bipedRightArm.rotateAngleY = -0.5F + b.bipedHead.rotateAngleY; - // b.bipedLeftArm.rotateAngleX = -((float) Math.PI / 2F) + b.bipedHead.rotateAngleX; - // b.bipedRightArm.rotateAngleX = -((float) Math.PI / 2F) + b.bipedHead.rotateAngleX; - // b.bipedLeftArm.rotateAngleX -= f6 * 1.2F - f7 * 0.4F; - // b.bipedRightArm.rotateAngleX -= f6 * 1.2F - f7 * 0.4F; - // b.bipedLeftArm.rotateAngleZ -= MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; - // b.bipedRightArm.rotateAngleZ += MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; - // b.bipedLeftArm.rotateAngleX -= MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; - // b.bipedRightArm.rotateAngleX += MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; - // } else { - // f6 = 0.0F; - // f7 = 0.0F; - // b.bipedRightArm.rotateAngleZ = 0.0F; - // b.bipedLeftArm.rotateAngleZ = 0.0F; - // b.bipedRightArm.rotateAngleY = -(0.1F - f6 * 0.6F) + b.bipedHead.rotateAngleY; - // b.bipedLeftArm.rotateAngleY = 0.1F - f6 * 0.6F + b.bipedHead.rotateAngleY + 0.4F; - // b.bipedRightArm.rotateAngleX = -((float) Math.PI / 2F) + b.bipedHead.rotateAngleX; - // b.bipedLeftArm.rotateAngleX = -((float) Math.PI / 2F) + b.bipedHead.rotateAngleX; - // b.bipedRightArm.rotateAngleX -= f6 * 1.2F - f7 * 0.4F; - // b.bipedLeftArm.rotateAngleX -= f6 * 1.2F - f7 * 0.4F; - // b.bipedRightArm.rotateAngleZ += MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; - // b.bipedLeftArm.rotateAngleZ -= MathHelper.cos(p_78087_3_ * 0.09F) * 0.05F + 0.05F; - // b.bipedRightArm.rotateAngleX += MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; - // b.bipedLeftArm.rotateAngleX -= MathHelper.sin(p_78087_3_ * 0.067F) * 0.05F; - // } - // } - // } + @Inject( + method = "setRotationAngles", + at = @At(value = "FIELD", target = "Lnet/minecraft/client/model/ModelBiped;aimedBow:Z", shift = At.Shift.AFTER), + cancellable = true) + private void backhand$moveOffhandAimedBow(float f1, float f2, float f3, float f4, float f5, float f6, Entity entity, + CallbackInfo ci) { + if (entity instanceof EntityPlayer player && entity == Minecraft.getMinecraft().thePlayer + && BackhandUtils.getOffhandItem(player) != null + && player.getItemInUse() == BackhandUtils.getOffhandItem(player)) { + bipedLeftArm.rotateAngleZ = 0.0F; + bipedRightArm.rotateAngleZ = 0.0F; + bipedLeftArm.rotateAngleY = 0.1F + bipedHead.rotateAngleY; + bipedRightArm.rotateAngleY = -0.5F + bipedHead.rotateAngleY; + bipedLeftArm.rotateAngleX = -((float) Math.PI / 2F) + bipedHead.rotateAngleX; + bipedRightArm.rotateAngleX = -((float) Math.PI / 2F) + bipedHead.rotateAngleX; + bipedLeftArm.rotateAngleX -= 0.4F; + bipedRightArm.rotateAngleX -= 0.4F; + bipedLeftArm.rotateAngleZ -= MathHelper.cos(f3 * 0.09F) * 0.05F + 0.05F; + bipedRightArm.rotateAngleZ += MathHelper.cos(f3 * 0.09F) * 0.05F + 0.05F; + bipedLeftArm.rotateAngleX -= MathHelper.sin(f3 * 0.067F) * 0.05F; + bipedRightArm.rotateAngleX += MathHelper.sin(f3 * 0.067F) * 0.05F; + ci.cancel(); + } + } } diff --git a/src/main/java/xonin/backhand/mixins/early/MixinPlayerControllerMP.java b/src/main/java/xonin/backhand/mixins/early/MixinPlayerControllerMP.java index 89c1e60..2f8fd69 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinPlayerControllerMP.java +++ b/src/main/java/xonin/backhand/mixins/early/MixinPlayerControllerMP.java @@ -57,31 +57,4 @@ public abstract class MixinPlayerControllerMP { } return original; } - - // @Inject( - // method = "sendUseItem", - // at = @At( - // value = "FIELD", - // opcode = Opcodes.GETFIELD, - // target = "Lnet/minecraft/entity/player/InventoryPlayer;mainInventory:[Lnet/minecraft/item/ItemStack;")) - // private void backhand$sendUseItem(EntityPlayer player, World worldIn, ItemStack itemStackIn, - // CallbackInfoReturnable cir, @Local(ordinal = 1) ItemStack rightClickStack) { - // ItemStack stack = rightClickStack.stackSize == 0 ? null : rightClickStack; - // BackhandUtils.setPlayerCurrentItem(player, stack); - // cir.cancel(); - // } - - // - // @Redirect( - // method = "sendUseItem", - // at = @At( - // value = "FIELD", - // opcode = Opcodes.GETFIELD, - // target = "Lnet/minecraft/entity/player/InventoryPlayer;mainInventory:[Lnet/minecraft/item/ItemStack;")) - // private ItemStack[] backhand$sendUseItem(InventoryPlayer inventory, @Local(ordinal = 1) ItemStack - // rightClickStack) { - // ItemStack stack = rightClickStack.stackSize == 0 ? null : rightClickStack; - // BackhandUtils.setPlayerCurrentItem(inventory.player, stack); - // return new ItemStack[inventory.mainInventory.length]; - // } } From 0313e9ca88b5d31c03dc362a282a7a46420435b3 Mon Sep 17 00:00:00 2001 From: Lyfts <127234178+Lyfts@users.noreply.github.com> Date: Thu, 25 Jul 2024 22:27:26 +0200 Subject: [PATCH 6/9] don't add removed mixin --- .../java/xonin/backhand/coremod/BackhandLoadingPlugin.java | 1 - .../java/xonin/backhand/mixins/early/MixinModelBiped.java | 6 +++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java b/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java index 0085817..e95e7bf 100644 --- a/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java +++ b/src/main/java/xonin/backhand/coremod/BackhandLoadingPlugin.java @@ -46,7 +46,6 @@ public List getMixins(Set loadedCoreMods) { mixins.add("MixinEntityPlayer"); mixins.add("MixinEntityPlayerMP"); mixins.add("MixinItemStack"); - mixins.add("MixinInventoryPlayer"); mixins.add("MixinNetHandlerPlayServer"); if (FMLLaunchHandler.side() .isClient()) { diff --git a/src/main/java/xonin/backhand/mixins/early/MixinModelBiped.java b/src/main/java/xonin/backhand/mixins/early/MixinModelBiped.java index e6ac0d1..7e6db57 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinModelBiped.java +++ b/src/main/java/xonin/backhand/mixins/early/MixinModelBiped.java @@ -37,7 +37,11 @@ public abstract class MixinModelBiped extends ModelBase { @Inject( method = "setRotationAngles", - at = @At(value = "FIELD", target = "Lnet/minecraft/client/model/ModelBiped;aimedBow:Z", shift = At.Shift.AFTER), + at = @At( + value = "FIELD", + target = "Lnet/minecraft/client/model/ModelBiped;aimedBow:Z", + shift = At.Shift.BY, + by = 2), cancellable = true) private void backhand$moveOffhandAimedBow(float f1, float f2, float f3, float f4, float f5, float f6, Entity entity, CallbackInfo ci) { From bca411d0fe6ed5c7209375271d897daa7687fb81 Mon Sep 17 00:00:00 2001 From: Lyfts <127234178+Lyfts@users.noreply.github.com> Date: Fri, 26 Jul 2024 20:42:31 +0200 Subject: [PATCH 7/9] fix #17 and make getOffhandItem fakeplayer safe --- src/main/java/xonin/backhand/api/core/BackhandUtils.java | 7 ++++++- .../java/xonin/backhand/mixins/early/MixinItemStack.java | 3 ++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/xonin/backhand/api/core/BackhandUtils.java b/src/main/java/xonin/backhand/api/core/BackhandUtils.java index 2f2f4b2..cbc6dc0 100644 --- a/src/main/java/xonin/backhand/api/core/BackhandUtils.java +++ b/src/main/java/xonin/backhand/api/core/BackhandUtils.java @@ -3,6 +3,8 @@ import java.io.Closeable; import java.io.IOException; +import javax.annotation.Nullable; + import net.minecraft.block.Block; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; @@ -36,6 +38,7 @@ import net.minecraft.nbt.NBTSizeTracker; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; +import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.event.ForgeEventFactory; import net.minecraftforge.event.entity.player.AttackEntityEvent; @@ -93,7 +96,9 @@ public static void setPlayerOffhandItem(EntityPlayer player, ItemStack stack) { } } - public static ItemStack getOffhandItem(EntityPlayer player) { + public static @Nullable ItemStack getOffhandItem(EntityPlayer player) { + if (player instanceof FakePlayer) return null; + if (Backhand.UseInventorySlot) { return player.inventory.getStackInSlot(Backhand.AlternateOffhandSlot); } else { diff --git a/src/main/java/xonin/backhand/mixins/early/MixinItemStack.java b/src/main/java/xonin/backhand/mixins/early/MixinItemStack.java index 7bef385..d02f418 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinItemStack.java +++ b/src/main/java/xonin/backhand/mixins/early/MixinItemStack.java @@ -3,6 +3,7 @@ import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; +import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.event.ForgeEventFactory; import org.spongepowered.asm.mixin.Mixin; @@ -17,7 +18,7 @@ public abstract class MixinItemStack { @Inject(method = "damageItem", at = @At(value = "TAIL")) private void backhand$damageOffhand(int p_77972_1_, EntityLivingBase entity, CallbackInfo ci) { - if (!(entity instanceof EntityPlayer player)) return; + if (!(entity instanceof EntityPlayer player) || entity instanceof FakePlayer) return; ItemStack itemStack = (ItemStack) (Object) this; ItemStack offhandItem = BackhandUtils.getOffhandItem(player); From c63624214a316deb5b0379a64db960d2d5e9ed0c Mon Sep 17 00:00:00 2001 From: Lyft <127234178+Lyfts@users.noreply.github.com> Date: Sat, 27 Jul 2024 00:11:59 +0200 Subject: [PATCH 8/9] Update MixinNetHandlerPlayClient.java --- .../xonin/backhand/mixins/early/MixinNetHandlerPlayClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayClient.java b/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayClient.java index 9c778fe..8a6ee23 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayClient.java +++ b/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayClient.java @@ -22,7 +22,7 @@ public abstract class MixinNetHandlerPlayClient { value = "INVOKE", target = "Lnet/minecraft/network/play/server/S09PacketHeldItemChange;func_149385_c()I", ordinal = 1)) - private int backhand$isValidIventorySlot(int original) { + private int backhand$isValidInventorySlot(int original) { // return a valid int e.g. between 0 and < 9 return InventoryPlayerBackhand.isValidSwitch(original) ? 0 : -1; } From 99021b1ea4076b0d8a2e06da75f50a8af35892b1 Mon Sep 17 00:00:00 2001 From: Lyft <127234178+Lyfts@users.noreply.github.com> Date: Sat, 27 Jul 2024 00:12:24 +0200 Subject: [PATCH 9/9] Update MixinNetHandlerPlayServer.java --- .../xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java b/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java index 6fb31bb..6d7fa4e 100644 --- a/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java +++ b/src/main/java/xonin/backhand/mixins/early/MixinNetHandlerPlayServer.java @@ -30,7 +30,7 @@ public abstract class MixinNetHandlerPlayServer { value = "INVOKE", target = "Lnet/minecraft/network/play/client/C09PacketHeldItemChange;func_149614_c()I", ordinal = 1)) - private int backhand$isValidIventorySlot(int original) { + private int backhand$isValidInventorySlot(int original) { // return a valid int e.g. between 0 and < 9 return InventoryPlayerBackhand.isValidSwitch(original) ? 0 : -1; }