From f1900cd9b36ba94d43dc413cd116ac616633139a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=B0=D1=82=D1=8C=D0=BA=D1=96=D0=B2=20=D0=9D=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D0=BE=D1=80-=D0=84=D0=B2=D0=B3=D0=B5=D0=BD=20?= =?UTF-8?q?=D0=92=D0=B0=D1=81=D0=B8=D0=BB=D1=8C=D0=BE=D0=B2=D0=B8=D1=87?= Date: Sun, 18 Feb 2024 11:57:54 +0200 Subject: [PATCH] The ring of ikoL awakens! (#43) * moving master block dont reset structure * Add mirroring * opsie * Mirror look * Mirror final round * refractor + new hud message * Cost balancing * F*ck you idea, you are not my homie now * Thanks idea, love you * Thanks Raven * This should be it --- .../botania/api/item/IInWorldRenderable.java | 13 + .../core/handler/BoundTileRenderer.java | 12 +- .../client/core/handler/KeyHandler.java | 11 +- .../common/core/helper/LokiCursor.java | 80 ++++ .../common/item/relic/ItemLokiRing.java | 394 ++++++++++++++---- .../botania/common/network/PacketHandler.java | 2 + .../common/network/PacketLokiMirror.java | 34 ++ .../common/network/PacketLokiMirrorAck.java | 38 ++ .../resources/assets/botania/lang/en_US.lang | 2 + 9 files changed, 513 insertions(+), 73 deletions(-) create mode 100644 src/main/java/vazkii/botania/api/item/IInWorldRenderable.java create mode 100644 src/main/java/vazkii/botania/common/core/helper/LokiCursor.java create mode 100644 src/main/java/vazkii/botania/common/network/PacketLokiMirror.java create mode 100644 src/main/java/vazkii/botania/common/network/PacketLokiMirrorAck.java diff --git a/src/main/java/vazkii/botania/api/item/IInWorldRenderable.java b/src/main/java/vazkii/botania/api/item/IInWorldRenderable.java new file mode 100644 index 000000000..972600f87 --- /dev/null +++ b/src/main/java/vazkii/botania/api/item/IInWorldRenderable.java @@ -0,0 +1,13 @@ +package vazkii.botania.api.item; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; + +/** + * An item that implements this will allow some custom render. This will be called while the item is in the inventory, + * armor slot or bauble slots. + */ +public interface IInWorldRenderable +{ + public void renderInWorld(EntityPlayer player, ItemStack stack); +} diff --git a/src/main/java/vazkii/botania/client/core/handler/BoundTileRenderer.java b/src/main/java/vazkii/botania/client/core/handler/BoundTileRenderer.java index 232d8a310..7bbfae07e 100644 --- a/src/main/java/vazkii/botania/client/core/handler/BoundTileRenderer.java +++ b/src/main/java/vazkii/botania/client/core/handler/BoundTileRenderer.java @@ -29,6 +29,7 @@ import org.lwjgl.opengl.GL11; import vazkii.botania.api.BotaniaAPI; import vazkii.botania.api.item.IExtendedWireframeCoordinateListProvider; +import vazkii.botania.api.item.IInWorldRenderable; import vazkii.botania.api.item.IWireframeCoordinateListProvider; import vazkii.botania.api.wand.ICoordBoundItem; import vazkii.botania.api.wand.IWireframeAABBProvider; @@ -36,6 +37,10 @@ import cpw.mods.fml.common.eventhandler.SubscribeEvent; public final class BoundTileRenderer { + public static int getWireframeColor(){ + return Color.HSBtoRGB(ClientTickHandler.ticksInGame % 200 / 200F, 0.6F, 1F); + } + @SubscribeEvent public void onWorldRenderLast(RenderWorldLastEvent event) { GL11.glPushMatrix(); @@ -49,7 +54,7 @@ public final class BoundTileRenderer { EntityPlayer player = Minecraft.getMinecraft().thePlayer; ItemStack stack = player.getCurrentEquippedItem(); - int color = Color.HSBtoRGB(ClientTickHandler.ticksInGame % 200 / 200F, 0.6F, 1F); + int color = getWireframeColor(); if(stack != null && stack.getItem() instanceof ICoordBoundItem) { ChunkCoordinates coords = ((ICoordBoundItem) stack.getItem()).getBinding(stack); if(coords != null) @@ -82,6 +87,11 @@ public final class BoundTileRenderer { renderBlockOutlineAt(coords, color, 5F); } } + if(stackInSlot != null && stackInSlot.getItem() instanceof IInWorldRenderable) { + IInWorldRenderable provider = (IInWorldRenderable) stackInSlot.getItem(); + provider.renderInWorld(player,stackInSlot); + } + } GL11.glEnable(GL11.GL_DEPTH_TEST); diff --git a/src/main/java/vazkii/botania/client/core/handler/KeyHandler.java b/src/main/java/vazkii/botania/client/core/handler/KeyHandler.java index d5eb42038..4eb34f0ef 100644 --- a/src/main/java/vazkii/botania/client/core/handler/KeyHandler.java +++ b/src/main/java/vazkii/botania/client/core/handler/KeyHandler.java @@ -3,6 +3,7 @@ package vazkii.botania.client.core.handler; import net.minecraft.client.settings.KeyBinding; import vazkii.botania.common.network.PacketHandler; import vazkii.botania.common.network.PacketLokiClear; +import vazkii.botania.common.network.PacketLokiMirror; import vazkii.botania.common.network.PacketLokiToggle; import cpw.mods.fml.client.registry.ClientRegistry; import cpw.mods.fml.common.FMLCommonHandler; @@ -15,11 +16,13 @@ import cpw.mods.fml.relauncher.SideOnly; public class KeyHandler { private static final KeyBinding keyToggleRingOfLoki= new KeyBinding("botaniamisc.toggleLoki", 0, "botaniamisc.keyCategory"); private static final KeyBinding keyRingOfLokiClear= new KeyBinding("botaniamisc.ringOfLokiClear", 0, "botaniamisc.keyCategory"); + private static final KeyBinding keyRingOfLokiMirror= new KeyBinding("botaniamisc.ringOfLokiMirror", 0, "botaniamisc.keyCategory"); public KeyHandler() { FMLCommonHandler.instance().bus().register(this); - ClientRegistry.registerKeyBinding(keyToggleRingOfLoki); + ClientRegistry.registerKeyBinding(keyToggleRingOfLoki); ClientRegistry.registerKeyBinding(keyRingOfLokiClear); + ClientRegistry.registerKeyBinding(keyRingOfLokiMirror); } @SideOnly(Side.CLIENT) @@ -35,6 +38,9 @@ public class KeyHandler { if(keyRingOfLokiClear.isPressed()){ ringOfLokiClear(); } + if(keyRingOfLokiMirror.isPressed()){ + toggleRingLokiMirroring(); + } } private static void toggleRingLoki() { @@ -44,4 +50,7 @@ public class KeyHandler { private static void ringOfLokiClear() { PacketHandler.INSTANCE.sendToServer(new PacketLokiClear()); } + private static void toggleRingLokiMirroring() { + PacketHandler.INSTANCE.sendToServer(new PacketLokiMirror()); + } } diff --git a/src/main/java/vazkii/botania/common/core/helper/LokiCursor.java b/src/main/java/vazkii/botania/common/core/helper/LokiCursor.java new file mode 100644 index 000000000..56de5982c --- /dev/null +++ b/src/main/java/vazkii/botania/common/core/helper/LokiCursor.java @@ -0,0 +1,80 @@ +package vazkii.botania.common.core.helper; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.ChunkCoordinates; + + +public class LokiCursor { + private static final String TAG_X_OFFSET = "xOffset"; + private static final String TAG_Y_OFFSET = "yOffset"; + private static final String TAG_Z_OFFSET = "zOffset"; + private static final String TAG_MIRROR_MODE = "mirror"; + + private static final byte xAxisBitmask = 4; //100 + private static final byte yAxisBitmask = 2; //010 + private static final byte zAxisBitmask = 1; //001 + + private byte mirrorMode; + private ChunkCoordinates coordinates; + + public LokiCursor(int x, int y, int z, byte mode){ + coordinates = new ChunkCoordinates(x,y,z); + mirrorMode = mode; + } + + public static LokiCursor fromNBT(NBTTagCompound cmp){ + int x = cmp.getInteger(TAG_X_OFFSET); + int y = cmp.getInteger(TAG_Y_OFFSET); + int z = cmp.getInteger(TAG_Z_OFFSET); + byte mirror = cmp.getByte(TAG_MIRROR_MODE); + + return new LokiCursor(x,y,z,mirror); + } + public static boolean isMirrorX(byte mirrorMode){ + return (mirrorMode & xAxisBitmask) > 0; + } + public static boolean isMirrorY(byte mirrorMode){ + return (mirrorMode & yAxisBitmask) > 0; + } + public static boolean isMirrorZ(byte mirrorMode){ + return (mirrorMode & zAxisBitmask) > 0; + } + public NBTTagCompound toNBT() { + NBTTagCompound cmp = new NBTTagCompound(); + cmp.setInteger(TAG_X_OFFSET, coordinates.posX); + cmp.setInteger(TAG_Y_OFFSET, coordinates.posY); + cmp.setInteger(TAG_Z_OFFSET, coordinates.posZ); + cmp.setInteger(TAG_MIRROR_MODE, mirrorMode); + return cmp; + } + + public int getX(){ + return coordinates.posX; + } + + public int getY(){ + return coordinates.posY; + } + + public int getZ(){ + return coordinates.posZ; + } + + public ChunkCoordinates getCoordinates(){ + return coordinates; + } + + public boolean isMirrorX(){ + return isMirrorX(mirrorMode); + } + public boolean isMirrorY(){ + return isMirrorY(mirrorMode); + } + public boolean isMirrorZ(){ + return isMirrorZ(mirrorMode); + } + + public boolean isMirror(){ + return mirrorMode!=0; + } +} diff --git a/src/main/java/vazkii/botania/common/item/relic/ItemLokiRing.java b/src/main/java/vazkii/botania/common/item/relic/ItemLokiRing.java index 8274b5b15..226685fb6 100644 --- a/src/main/java/vazkii/botania/common/item/relic/ItemLokiRing.java +++ b/src/main/java/vazkii/botania/common/item/relic/ItemLokiRing.java @@ -10,12 +10,16 @@ */ package vazkii.botania.common.item.relic; + +import java.awt.Color; import java.util.ArrayList; import java.util.List; import com.gtnewhorizon.gtnhlib.GTNHLib; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.enchantment.Enchantment; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.EntityLivingBase; @@ -24,9 +28,11 @@ import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; + +import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.ChunkCoordinates; -import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.StatCollector; import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; @@ -34,13 +40,15 @@ import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action; import net.minecraftforge.event.world.BlockEvent; +import org.lwjgl.opengl.GL11; import vazkii.botania.api.item.IExtendedWireframeCoordinateListProvider; +import vazkii.botania.api.item.IInWorldRenderable; import vazkii.botania.api.item.ISequentialBreaker; import vazkii.botania.api.mana.IManaUsingItem; import vazkii.botania.api.mana.ManaItemHandler; -import vazkii.botania.common.achievement.ModAchievements; +import vazkii.botania.client.core.handler.BoundTileRenderer; import vazkii.botania.common.core.helper.ItemNBTHelper; -import vazkii.botania.common.item.ItemTemperanceStone; +import vazkii.botania.common.core.helper.LokiCursor; import vazkii.botania.common.item.ModItems; import vazkii.botania.common.item.equipment.tool.ToolCommons; import vazkii.botania.common.lib.LibItemNames; @@ -54,23 +62,21 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -public class ItemLokiRing extends ItemRelicBauble implements IExtendedWireframeCoordinateListProvider, IManaUsingItem { +public class ItemLokiRing extends ItemRelicBauble implements IExtendedWireframeCoordinateListProvider, IManaUsingItem, IInWorldRenderable { private static final String TAG_CURSOR_LIST = "cursorList"; private static final String TAG_CURSOR_PREFIX = "cursor"; private static final String TAG_CURSOR_COUNT = "cursorCount"; - private static final String TAG_X_OFFSET = "xOffset"; - private static final String TAG_Y_OFFSET = "yOffset"; - private static final String TAG_Z_OFFSET = "zOffset"; private static final String TAG_X_ORIGIN = "xOrigin"; private static final String TAG_Y_ORIGIN = "yOrigin"; private static final String TAG_Z_ORIGIN = "zOrigin"; private static final String TAG_MODE = "mode"; private static final String TAG_BREAKING_MODE = "breaking"; + private static final String TAG_MIRROR_MODE = "mirror"; private boolean recursion = false; public static enum HUD_MESSAGE { - MODE, BREAKING, CLEAR + MODE, BREAKING, CLEAR, MIRROR, INSUFFICIENT_MANA } public ItemLokiRing() { @@ -114,15 +120,14 @@ public class ItemLokiRing extends ItemRelicBauble implements IExtendedWireframeC ItemStack heldItemStack = player.getCurrentEquippedItem(); ChunkCoordinates originCoords = getOriginPos(lokiRing); MovingObjectPosition lookPos = ToolCommons.raytraceFromEntity(player.worldObj, player, true, 10F); - List cursors = getCursorList(lokiRing); + List cursors = getCursorList(lokiRing); int cursorCount = cursors.size(); - - int cost = Math.min(cursorCount, (int) Math.pow(Math.E, cursorCount * 0.25)); + //I don`t think mana for placing should be cruel , so I just made graph with funny line + int cost = (int)(50*Math.sin(0.04* cursorCount)+cursorCount+120+20*Math.cos(0.2*cursorCount)); if (heldItemStack == null && event.action == Action.RIGHT_CLICK_BLOCK && player.isSneaking() && isRingEnabled(lokiRing)) { if(originCoords.posY == -1 && lookPos != null) { setOriginPos(lokiRing, lookPos.blockX, lookPos.blockY, lookPos.blockZ); - clearCursors(lokiRing); if(player instanceof EntityPlayerMP) PacketHandler.INSTANCE.sendTo(new PacketSyncBauble(player, slot), (EntityPlayerMP) player); } else if(lookPos != null) { @@ -136,8 +141,8 @@ public class ItemLokiRing extends ItemRelicBauble implements IExtendedWireframeC int relY = lookPos.blockY - originCoords.posY; int relZ = lookPos.blockZ - originCoords.posZ; - for(ChunkCoordinates cursor : cursors) - if(cursor.posX == relX && cursor.posY == relY && cursor.posZ == relZ) { + for(LokiCursor cursor : cursors) + if(cursor.getX() == relX && cursor.getY() == relY && cursor.getZ() == relZ) { cursors.remove(cursor); setCursorList(lokiRing, cursors); if(player instanceof EntityPlayerMP) @@ -145,56 +150,126 @@ public class ItemLokiRing extends ItemRelicBauble implements IExtendedWireframeC break addCursor; } - addCursor(lokiRing, relX, relY, relZ); + addCursor(lokiRing, relX, relY, relZ, getRingMirrorMode(lokiRing) ); if(player instanceof EntityPlayerMP) PacketHandler.INSTANCE.sendTo(new PacketSyncBauble(player, slot), (EntityPlayerMP) player); } } } } else if (heldItemStack != null && event.action == Action.RIGHT_CLICK_BLOCK && lookPos != null && isRingEnabled(lokiRing)) { - - recursion = true; + if(!ManaItemHandler.requestManaExact(lokiRing, player, cost, true)){ + renderHUDNotification(HUD_MESSAGE.INSUFFICIENT_MANA); + return; + } + + recursion = true; + double oldPosX = player.posX; double oldPosY = player.posY; double oldPosZ = player.posZ; + float oldPitch = player.rotationPitch; + float oldYaw = player.rotationYaw; + + int masterOffsetX = lookPos.blockX - originCoords.posX; + int masterOffsetY = lookPos.blockY - originCoords.posY; + int masterOffsetZ = lookPos.blockZ - originCoords.posZ; + + double playerOffsetX = player.posX - originCoords.posX; + double playerOffsetY = player.posY - originCoords.posY; + double playerOffsetZ = player.posZ - originCoords.posZ; + + for(LokiCursor cursor : cursors) { + + int x = lookPos.blockX + cursor.getX(); + int y = lookPos.blockY + cursor.getY(); + int z = lookPos.blockZ + cursor.getZ(); + + if(cursor.isMirrorX()){ + x -= 2*masterOffsetX; + } + if(cursor.isMirrorY()){ + y -= 2*masterOffsetY; + } + if(cursor.isMirrorZ()){ + z -= 2*masterOffsetZ; + } + + if (player.worldObj.isAirBlock(x, y, z) ) { + continue; + } + + player.posX = cursor.getX()+oldPosX; + player.posY = cursor.getY()+oldPosY; + player.posZ = cursor.getZ()+oldPosZ; + player.rotationYaw = oldYaw; + + if(cursor.isMirrorX()){ + player.posX -= 2*playerOffsetX; + player.rotationYaw = player.rotationYaw * (-1); + } + if(cursor.isMirrorY()){ + player.posY -= 2*playerOffsetY; + player.rotationPitch = oldPitch * (-1); + } + if(cursor.isMirrorZ()){ + player.posZ -= 2*playerOffsetZ; + player.rotationYaw = 180 - (Math.abs(player.rotationYaw)); + if(oldYaw < 0){ + player.rotationYaw *= -1; + } + } + + float hitX = (float) (lookPos.hitVec.xCoord - lookPos.blockX); + float hitY = (float) (lookPos.hitVec.yCoord - lookPos.blockY); + float hitZ = (float) (lookPos.hitVec.zCoord - lookPos.blockZ); + if(cursor.isMirrorX()){ + hitX = 1-hitX; + } + if(cursor.isMirrorY()){ + hitY = 1-hitY; + } + if(cursor.isMirrorZ()){ + hitZ = 1-hitZ; + } + + int hitSide = lookPos.sideHit; + if(cursor.isMirrorX() && (hitSide == ForgeDirection.EAST.ordinal() || hitSide == ForgeDirection.WEST.ordinal()) ){ + hitSide = hitSide ^ 1; + } + if(cursor.isMirrorY() && (hitSide == ForgeDirection.DOWN.ordinal() || hitSide == ForgeDirection.UP.ordinal()) ){ + hitSide = hitSide ^ 1; + } + if(cursor.isMirrorZ() && (hitSide == ForgeDirection.NORTH.ordinal() || hitSide == ForgeDirection.SOUTH.ordinal()) ){ + hitSide = hitSide ^ 1; + } - for(ChunkCoordinates cursor : cursors) { - int x = lookPos.blockX + cursor.posX; - int y = lookPos.blockY + cursor.posY; - int z = lookPos.blockZ + cursor.posZ; Item item = heldItemStack.getItem(); - if (!player.worldObj.isAirBlock(x, y, z) && ManaItemHandler.requestManaExact(lokiRing, player, cost, true)) { - player.posX = cursor.posX+oldPosX; - player.posY = cursor.posY+oldPosY; - player.posZ = cursor.posZ+oldPosZ; + Block markedBlock = player.worldObj.getBlock(x, y, z); - float hitX = (float) (lookPos.hitVec.xCoord - lookPos.blockX); - float hitY = (float) (lookPos.hitVec.yCoord - lookPos.blockY); - float hitZ = (float) (lookPos.hitVec.zCoord - lookPos.blockZ); - - Block markedBlock = player.worldObj.getBlock(x, y, z); - boolean wasActivated = markedBlock.onBlockActivated(player.worldObj, x, y, z, player, lookPos.sideHit, hitX,hitY,hitZ); - - if (heldItemStack.stackSize == 0 ) { + boolean wasActivated = markedBlock.onBlockActivated(player.worldObj, x, y, z, player, hitSide, hitX,hitY,hitZ); + + if (heldItemStack.stackSize == 0 ) { + event.setCanceled(true); + break; + } + if (!wasActivated) { + item.onItemUse(player.capabilities.isCreativeMode ? heldItemStack.copy() : heldItemStack, player, player.worldObj, x, y, z, hitSide, (float) lookPos.hitVec.xCoord - x, (float) lookPos.hitVec.yCoord - y, (float) lookPos.hitVec.zCoord - z); + if(heldItemStack.stackSize == 0) { event.setCanceled(true); break; } - if (!wasActivated) { - item.onItemUse(player.capabilities.isCreativeMode ? heldItemStack.copy() : heldItemStack, player, player.worldObj, x, y, z, lookPos.sideHit, (float) lookPos.hitVec.xCoord - x, (float) lookPos.hitVec.yCoord - y, (float) lookPos.hitVec.zCoord - z); - if(heldItemStack.stackSize == 0) { - event.setCanceled(true); - break; - } - } } + } recursion = false; player.posX = oldPosX; player.posY = oldPosY; player.posZ = oldPosZ; + player.rotationPitch = oldPitch; + player.rotationYaw = oldYaw; } } - + public static void setMode(ItemStack stack, boolean state) { stack.stackTagCompound.setBoolean(TAG_MODE, state); } @@ -203,6 +278,10 @@ public class ItemLokiRing extends ItemRelicBauble implements IExtendedWireframeC stack.stackTagCompound.setBoolean(TAG_BREAKING_MODE, state); } + public static void setMirrorMode (ItemStack stack, byte state) { + stack.stackTagCompound.setByte(TAG_MIRROR_MODE, state); + } + @SideOnly(Side.CLIENT) public static void renderHUDNotification(HUD_MESSAGE type){ @@ -218,6 +297,12 @@ public class ItemLokiRing extends ItemRelicBauble implements IExtendedWireframeC case CLEAR: text = getLokiCearText(getLokiRing(mc.thePlayer)); break; + case MIRROR: + text = getLokiMirrorText(getLokiRing(mc.thePlayer)); + break; + case INSUFFICIENT_MANA: + text = EnumChatFormatting.RED + StatCollector.translateToLocal("botaniamisc.insufficient_mana"); + break; default: return; @@ -231,18 +316,33 @@ public class ItemLokiRing extends ItemRelicBauble implements IExtendedWireframeC EnumChatFormatting.RED + StatCollector.translateToLocal("botaniamisc.lokiOff"); } + public static String getAxisString(byte state) { + EnumChatFormatting x = LokiCursor.isMirrorX(state) ? EnumChatFormatting.GREEN : EnumChatFormatting.RED; + EnumChatFormatting y = LokiCursor.isMirrorY(state) ? EnumChatFormatting.GREEN : EnumChatFormatting.RED; + EnumChatFormatting z = LokiCursor.isMirrorZ(state) ? EnumChatFormatting.GREEN : EnumChatFormatting.RED; + + return x + "X " + y + "Y " + z + "Z"; + } + public static String getLokiModeText(ItemStack stack){ return EnumChatFormatting.GOLD + StatCollector.translateToLocal("item.botania:lokiRing.name") + " " + getOnOffString(isRingEnabled(stack)); } + public static String getLokiMirrorText(ItemStack stack){ + return EnumChatFormatting.GOLD + StatCollector.translateToLocal("botaniamisc.lokiMirror") + " "+ + getAxisString(getRingMirrorMode(stack)); + } + + public static String getLokiCearText(ItemStack stack){ + return EnumChatFormatting.GOLD + StatCollector.translateToLocal("botaniamisc.lokiClear"); + } + public static String getLokiBreakingModeText(ItemStack stack){ return EnumChatFormatting.GOLD + StatCollector.translateToLocal("item.botania:lokiRing.name") + " "+ StatCollector.translateToLocal("botaniamisc.breaking") + " " + getOnOffString(isRingBreakingEnabled(stack)); } - public static String getLokiCearText(ItemStack stack){ - return EnumChatFormatting.GOLD + StatCollector.translateToLocal("botaniamisc.lokiClear"); - } + public static boolean isRingEnabled (final ItemStack stack){ if (stack.hasTagCompound()) @@ -260,11 +360,25 @@ public class ItemLokiRing extends ItemRelicBauble implements IExtendedWireframeC return false; } + public static byte getRingMirrorMode(final ItemStack stack){ + if(stack.hasTagCompound()){ + return stack.stackTagCompound.getByte(TAG_MIRROR_MODE); + } + return 0; + } public static void breakOnAllCursors(EntityPlayer player, Item item, ItemStack stack, int x, int y, int z, int side) { ItemStack lokiRing = getLokiRing(player); if(lokiRing == null || player.worldObj.isRemote || !isRingEnabled(lokiRing) || !isRingBreakingEnabled(lokiRing)) return; - List cursors = getCursorList(lokiRing); + List cursors = getCursorList(lokiRing); + //In case someone wants to mine ore veins with loki, this should make 1 manapool worth of mana last for 2 veins + int cost = 30 * cursors.size(); + + if(!ManaItemHandler.requestManaExact(lokiRing, player, cost, true)){ + renderHUDNotification(HUD_MESSAGE.INSUFFICIENT_MANA); + return; + } + ISequentialBreaker breaker = null; if(item instanceof ISequentialBreaker) breaker = (ISequentialBreaker) item; @@ -273,11 +387,39 @@ public class ItemLokiRing extends ItemRelicBauble implements IExtendedWireframeC int fortune = EnchantmentHelper.getEnchantmentLevel(Enchantment.fortune.effectId, stack); boolean dispose = breaker == null? true : breaker.disposeOfTrashBlocks(stack); + ChunkCoordinates originCoords = getOriginPos(lokiRing); + + int masterOffsetX = x - originCoords.posX; + int masterOffsetY = y - originCoords.posY; + int masterOffsetZ = z - originCoords.posZ; + for(int i = 0; i < cursors.size(); i++) { - ChunkCoordinates coords = cursors.get(i); - int xp = x + coords.posX; - int yp = y + coords.posY; - int zp = z + coords.posZ; + LokiCursor cursor = cursors.get(i); + int xp = x + cursor.getX(); + int yp = y + cursor.getY(); + int zp = z + cursor.getZ(); + if(cursor.isMirrorX()){ + xp -= 2*masterOffsetX; + } + if(cursor.isMirrorY()){ + yp -= 2*masterOffsetY; + } + if(cursor.isMirrorZ()){ + zp -= 2*masterOffsetZ; + } + + if(cursor.isMirrorX() && (side == ForgeDirection.EAST.ordinal() || side == ForgeDirection.WEST.ordinal()) ){ + side = side ^ 1; + } + if(cursor.isMirrorY() && (side == ForgeDirection.DOWN.ordinal() || side == ForgeDirection.UP.ordinal()) ){ + side = side ^ 1; + } + if(cursor.isMirrorZ() && (side == ForgeDirection.NORTH.ordinal() || side == ForgeDirection.SOUTH.ordinal()) ){ + side = side ^ 1; + } + + + Block block = world.getBlock(xp, yp, zp); if(breaker != null) breaker.breakOtherBlock(player, stack, xp, yp, zp, x, y, z, side); @@ -303,6 +445,7 @@ public class ItemLokiRing extends ItemRelicBauble implements IExtendedWireframeC addStringToTooltip(EnumChatFormatting.WHITE +StatCollector.translateToLocal("botaniamisc.lokiCurrent"), list); addStringToTooltip(StatCollector.translateToLocal("botaniamisc.lokiState") + ": " + getOnOffString(isRingEnabled(stack)), list); addStringToTooltip(StatCollector.translateToLocal("botaniamisc.breaking") + ": " + getOnOffString(isRingBreakingEnabled(stack)), list); + addStringToTooltip(StatCollector.translateToLocal("botaniamisc.lokiMirror") + getAxisString(getRingMirrorMode(stack)), list); addStringToTooltip("", list); addStringToTooltip(StatCollector.translateToLocal("botaniamisc.lokiToggleDescription") + " " + getOnOffString(true) + EnumChatFormatting.RESET + "/"+ getOnOffString(false), list); addStringToTooltip(StatCollector.translateToLocal("botaniamisc.lokiBreakingDescription") + " " + getOnOffString(true) + EnumChatFormatting.RESET+"/" + getOnOffString(false), list); @@ -319,22 +462,27 @@ public class ItemLokiRing extends ItemRelicBauble implements IExtendedWireframeC MovingObjectPosition lookPos = Minecraft.getMinecraft().objectMouseOver; if(lookPos != null && !player.worldObj.isAirBlock(lookPos.blockX, lookPos.blockY, lookPos.blockZ) && lookPos.entityHit == null) { - List list = getCursorList(stack); + List list = getCursorList(stack); ChunkCoordinates origin = getOriginPos(stack); + List toDraw = new ArrayList<>(); if(origin.posY != -1) { - for(ChunkCoordinates coords : list) { + for(LokiCursor cursor : list) { + ChunkCoordinates coords = cursor.getCoordinates(); coords.posX += origin.posX; coords.posY += origin.posY; coords.posZ += origin.posZ; + toDraw.add(coords); } - } else for(ChunkCoordinates coords : list) { + } else for(LokiCursor cursor : list) { + ChunkCoordinates coords = cursor.getCoordinates(); coords.posX += lookPos.blockX; coords.posY += lookPos.blockY; coords.posZ += lookPos.blockZ; + toDraw.add(coords); } - return list; + return toDraw; } return null; @@ -377,28 +525,26 @@ public class ItemLokiRing extends ItemRelicBauble implements IExtendedWireframeC ItemNBTHelper.setInt(stack, TAG_Z_ORIGIN, z); } - private static List getCursorList(ItemStack stack) { + private static List getCursorList(ItemStack stack) { NBTTagCompound cmp = ItemNBTHelper.getCompound(stack, TAG_CURSOR_LIST, false); - List cursors = new ArrayList(); + List cursors = new ArrayList(); int count = cmp.getInteger(TAG_CURSOR_COUNT); for(int i = 0; i < count; i++) { NBTTagCompound cursorCmp = cmp.getCompoundTag(TAG_CURSOR_PREFIX + i); - int x = cursorCmp.getInteger(TAG_X_OFFSET); - int y = cursorCmp.getInteger(TAG_Y_OFFSET); - int z = cursorCmp.getInteger(TAG_Z_OFFSET); - cursors.add(new ChunkCoordinates(x, y, z)); + cursors.add(LokiCursor.fromNBT(cursorCmp)); + } return cursors; } - private static void setCursorList(ItemStack stack, List cursors) { + private static void setCursorList(ItemStack stack, List cursors) { NBTTagCompound cmp = new NBTTagCompound(); if(cursors != null) { int i = 0; - for(ChunkCoordinates cursor : cursors) { - NBTTagCompound cursorCmp = cursorToCmp(cursor.posX, cursor.posY, cursor.posZ); + for(LokiCursor cursor : cursors) { + NBTTagCompound cursorCmp = cursor.toNBT(); cmp.setTag(TAG_CURSOR_PREFIX + i, cursorCmp); i++; } @@ -408,18 +554,12 @@ public class ItemLokiRing extends ItemRelicBauble implements IExtendedWireframeC ItemNBTHelper.setCompound(stack, TAG_CURSOR_LIST, cmp); } - private static NBTTagCompound cursorToCmp(int x, int y, int z) { - NBTTagCompound cmp = new NBTTagCompound(); - cmp.setInteger(TAG_X_OFFSET, x); - cmp.setInteger(TAG_Y_OFFSET, y); - cmp.setInteger(TAG_Z_OFFSET, z); - return cmp; - } - private static void addCursor(ItemStack stack, int x, int y, int z) { + + private static void addCursor(ItemStack stack, int x, int y, int z, byte mirrorMode) { NBTTagCompound cmp = ItemNBTHelper.getCompound(stack, TAG_CURSOR_LIST, false); int count = cmp.getInteger(TAG_CURSOR_COUNT); - cmp.setTag(TAG_CURSOR_PREFIX + count, cursorToCmp(x, y, z)); + cmp.setTag(TAG_CURSOR_PREFIX + count, new LokiCursor(x,y,z, mirrorMode).toNBT()); cmp.setInteger(TAG_CURSOR_COUNT, count + 1); ItemNBTHelper.setCompound(stack, TAG_CURSOR_LIST, cmp); } @@ -429,5 +569,117 @@ public class ItemLokiRing extends ItemRelicBauble implements IExtendedWireframeC return true; } + @Override + @SideOnly(Side.CLIENT) + public void renderInWorld(EntityPlayer player, ItemStack stack){ + renderMirrors(player,stack); + } + + @SideOnly(Side.CLIENT) + private void renderMirrors(EntityPlayer player,ItemStack stack) { + ItemStack lokiRing = getLokiRing(player); + if(lokiRing != stack || !isRingEnabled(lokiRing) ) + return; + + World world = Minecraft.getMinecraft().theWorld; + List cursors = getCursorList(stack); + ChunkCoordinates origin = getOriginPos(stack); + MovingObjectPosition lookPos = Minecraft.getMinecraft().objectMouseOver; + + + for(LokiCursor cursor : cursors) { + if(!cursor.isMirror()) { + continue; + } + ChunkCoordinates pos = cursor.getCoordinates(); + if(origin.posY != -1){ + + pos.posX += origin.posX; + pos.posY += origin.posY; + pos.posZ += origin.posZ; + }else{ + pos.posX += lookPos.blockX; + pos.posY += lookPos.blockY; + pos.posZ += lookPos.blockZ; + } + + + GL11.glPushMatrix(); + GL11.glTranslated(pos.posX - RenderManager.renderPosX, pos.posY - RenderManager.renderPosY, pos.posZ - RenderManager.renderPosZ + 1); + Color colorRGB = new Color(BoundTileRenderer.getWireframeColor()); + GL11.glColor4ub((byte) colorRGB.getRed(), (byte) colorRGB.getGreen(), (byte) colorRGB.getBlue(), (byte) 255); + Block block = world.getBlock(pos.posX, pos.posY, pos.posZ); + + if (block != null) { + AxisAlignedBB axis = block.getSelectedBoundingBoxFromPool(world, pos.posX, pos.posY, pos.posZ); + + if (axis != null) { + axis.minX -= pos.posX; + axis.maxX -= pos.posX; + axis.minY -= pos.posY; + axis.maxY -= pos.posY; + axis.minZ -= pos.posZ + 1; + axis.maxZ -= pos.posZ + 1; + + GL11.glScalef(1F, 1F, 1F); + + GL11.glLineWidth(1F); + Tessellator tessellator = Tessellator.instance; + tessellator.startDrawing(GL11.GL_LINES); + if (cursor.isMirrorX()) { + + tessellator.addVertex(axis.minX,axis.minY,axis.minZ); + tessellator.addVertex(axis.minX,axis.maxY,axis.maxZ); + + tessellator.addVertex(axis.minX,axis.maxY,axis.minZ); + tessellator.addVertex(axis.minX,axis.minY,axis.maxZ); + + tessellator.addVertex(axis.maxX,axis.minY,axis.minZ); + tessellator.addVertex(axis.maxX,axis.maxY,axis.maxZ); + + tessellator.addVertex(axis.maxX,axis.maxY,axis.minZ); + tessellator.addVertex(axis.maxX,axis.minY,axis.maxZ); + + } + if (cursor.isMirrorY()) { + + tessellator.addVertex(axis.minX,axis.minY,axis.minZ); + tessellator.addVertex(axis.maxX,axis.minY,axis.maxZ); + + tessellator.addVertex(axis.maxX,axis.minY,axis.minZ); + tessellator.addVertex(axis.minX,axis.minY,axis.maxZ); + + tessellator.addVertex(axis.minX,axis.maxY,axis.minZ); + tessellator.addVertex(axis.maxX,axis.maxY,axis.maxZ); + + tessellator.addVertex(axis.maxX,axis.maxY,axis.minZ); + tessellator.addVertex(axis.minX,axis.maxY,axis.maxZ); + + } + if (cursor.isMirrorZ()) { + + tessellator.addVertex(axis.minX,axis.minY,axis.minZ); + tessellator.addVertex(axis.maxX,axis.maxY,axis.minZ); + + tessellator.addVertex(axis.minX,axis.maxY,axis.minZ); + tessellator.addVertex(axis.maxX,axis.minY,axis.minZ); + + tessellator.addVertex(axis.minX,axis.minY,axis.maxZ); + tessellator.addVertex(axis.maxX,axis.maxY,axis.maxZ); + + tessellator.addVertex(axis.minX,axis.maxY,axis.maxZ); + tessellator.addVertex(axis.maxX,axis.minY,axis.maxZ); + + + } + tessellator.draw(); + } + } + + GL11.glPopMatrix(); + } + } + + } diff --git a/src/main/java/vazkii/botania/common/network/PacketHandler.java b/src/main/java/vazkii/botania/common/network/PacketHandler.java index 61b9eb7e3..7e9f32a42 100644 --- a/src/main/java/vazkii/botania/common/network/PacketHandler.java +++ b/src/main/java/vazkii/botania/common/network/PacketHandler.java @@ -18,5 +18,7 @@ public class PacketHandler { INSTANCE.registerMessage(PacketLokiToggleBreakingAck.class, PacketLokiToggleBreakingAck.class, 3, Side.CLIENT); INSTANCE.registerMessage(PacketLokiClear.class, PacketLokiClear.class, 4, Side.SERVER); INSTANCE.registerMessage(PacketLokiClearAck.class, PacketLokiClearAck.class, 5, Side.CLIENT); + INSTANCE.registerMessage(PacketLokiMirror.class, PacketLokiMirror.class, 6, Side.SERVER); + INSTANCE.registerMessage(PacketLokiMirrorAck.class, PacketLokiMirrorAck.class, 7, Side.CLIENT); } } diff --git a/src/main/java/vazkii/botania/common/network/PacketLokiMirror.java b/src/main/java/vazkii/botania/common/network/PacketLokiMirror.java new file mode 100644 index 000000000..02999f381 --- /dev/null +++ b/src/main/java/vazkii/botania/common/network/PacketLokiMirror.java @@ -0,0 +1,34 @@ +package vazkii.botania.common.network; + +import cpw.mods.fml.common.network.simpleimpl.IMessage; +import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; +import cpw.mods.fml.common.network.simpleimpl.MessageContext; +import io.netty.buffer.ByteBuf; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; +import vazkii.botania.common.item.relic.ItemLokiRing; + +public class PacketLokiMirror implements IMessage, IMessageHandler { + @Override + public void fromBytes(ByteBuf byteBuf) { + // not needed + } + + @Override + public void toBytes(ByteBuf byteBuf) { + // not needed + } + + @Override + public IMessage onMessage(PacketLokiMirror message, MessageContext ctx) { + EntityPlayerMP player = ctx.getServerHandler().playerEntity; + final ItemStack aRing = ItemLokiRing.getLokiRing(player); + if (aRing != null) { + byte mode = ItemLokiRing.getRingMirrorMode(aRing); + ItemLokiRing.setMirrorMode(aRing,(byte) ((mode+1)%8)); + PacketLokiMirrorAck ackMessage = new PacketLokiMirrorAck(); + PacketHandler.INSTANCE.sendTo(ackMessage, player); + } + return null; + } +} diff --git a/src/main/java/vazkii/botania/common/network/PacketLokiMirrorAck.java b/src/main/java/vazkii/botania/common/network/PacketLokiMirrorAck.java new file mode 100644 index 000000000..3141f21f6 --- /dev/null +++ b/src/main/java/vazkii/botania/common/network/PacketLokiMirrorAck.java @@ -0,0 +1,38 @@ +package vazkii.botania.common.network; + +import cpw.mods.fml.common.network.simpleimpl.IMessage; +import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; +import cpw.mods.fml.common.network.simpleimpl.MessageContext; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import io.netty.buffer.ByteBuf; +import net.minecraft.client.Minecraft; +import net.minecraft.item.ItemStack; +import vazkii.botania.common.item.relic.ItemLokiRing; + +public class PacketLokiMirrorAck implements IMessage, IMessageHandler { + + public boolean state; + + @Override + public void fromBytes(ByteBuf byteBuf) { + state = byteBuf.readBoolean(); + } + + @Override + public void toBytes(ByteBuf byteBuf) { + byteBuf.writeBoolean(state); + } + + @SideOnly(Side.CLIENT) + @Override + public IMessage onMessage(PacketLokiMirrorAck message, MessageContext ctx) { + Minecraft mc = Minecraft.getMinecraft(); + final ItemStack aRing = ItemLokiRing.getLokiRing(mc.thePlayer) ; + if (aRing != null) { + ItemLokiRing.renderHUDNotification(ItemLokiRing.HUD_MESSAGE.MIRROR); + } + + return null; + } +} diff --git a/src/main/resources/assets/botania/lang/en_US.lang b/src/main/resources/assets/botania/lang/en_US.lang index 6da0221f2..277197369 100644 --- a/src/main/resources/assets/botania/lang/en_US.lang +++ b/src/main/resources/assets/botania/lang/en_US.lang @@ -169,6 +169,8 @@ botaniamisc.lokiToggleDescription=Loki Switch Key to turn ring botaniamisc.lokiBreakingDescription=Loki Switch Key + Shift to toggle breaking botaniamisc.lokiCurrent=Current botaniamisc.lokiState=Ring +botaniamisc.lokiMirror=Current mirror: +botaniamisc.insufficient_mana=Not enough mana! # NEI INTEGRATION botania.nei.brewery=Botanical Brewery