From faa1e45997131ca585c9e78fe708eb8b9680e75e Mon Sep 17 00:00:00 2001 From: Pahimar Date: Thu, 31 Jul 2014 15:38:23 -0400 Subject: [PATCH] Added a GUI to the Alchemical Tome (still a WIP), got the functionality of the Research Station working, and with the help of KingLemming we have a more intelligent shift click method for our containers --- .../gui/inventory/GuiAlchemicalTome.java | 40 +++++ .../client/gui/inventory/GuiGlassBell.java | 1 - .../com/pahimar/ee3/handler/GuiHandler.java | 8 + .../inventory/ContainerAlchemicalTome.java | 31 ++++ .../pahimar/ee3/inventory/ContainerEE.java | 74 ++++++++++ .../inventory/ContainerResearchStation.java | 9 +- .../inventory/InventoryAlchemicalTome.java | 139 ++++++++++++++++++ .../pahimar/ee3/item/ItemAlchemicalTome.java | 4 + .../java/com/pahimar/ee3/reference/GuiId.java | 3 +- .../java/com/pahimar/ee3/reference/Names.java | 1 + .../com/pahimar/ee3/reference/Textures.java | 1 + .../pahimar/ee3/skill/PlayerKnowledge.java | 21 ++- .../tileentity/TileEntityResearchStation.java | 5 +- .../java/com/pahimar/ee3/util/ItemHelper.java | 37 +++++ src/main/resources/assets/ee3/lang/en_US.lang | 5 +- .../ee3/textures/gui/alchemicalTome.png | Bin 0 -> 4391 bytes .../ee3/textures/xcf/gui/alchemicalTome.xcf | Bin 0 -> 42101 bytes 17 files changed, 370 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/pahimar/ee3/client/gui/inventory/GuiAlchemicalTome.java create mode 100644 src/main/java/com/pahimar/ee3/inventory/ContainerAlchemicalTome.java create mode 100644 src/main/java/com/pahimar/ee3/inventory/InventoryAlchemicalTome.java create mode 100644 src/main/resources/assets/ee3/textures/gui/alchemicalTome.png create mode 100644 src/main/resources/assets/ee3/textures/xcf/gui/alchemicalTome.xcf diff --git a/src/main/java/com/pahimar/ee3/client/gui/inventory/GuiAlchemicalTome.java b/src/main/java/com/pahimar/ee3/client/gui/inventory/GuiAlchemicalTome.java new file mode 100644 index 00000000..3307ef94 --- /dev/null +++ b/src/main/java/com/pahimar/ee3/client/gui/inventory/GuiAlchemicalTome.java @@ -0,0 +1,40 @@ +package com.pahimar.ee3.client.gui.inventory; + +import com.pahimar.ee3.inventory.ContainerAlchemicalTome; +import com.pahimar.ee3.inventory.InventoryAlchemicalTome; +import com.pahimar.ee3.reference.Textures; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.util.StatCollector; +import org.lwjgl.opengl.GL11; + +@SideOnly(Side.CLIENT) +public class GuiAlchemicalTome extends GuiContainer +{ + private InventoryAlchemicalTome inventoryAlchemicalTome; + + public GuiAlchemicalTome(InventoryAlchemicalTome inventoryAlchemicalTome) + { + super(new ContainerAlchemicalTome(inventoryAlchemicalTome)); + this.inventoryAlchemicalTome = inventoryAlchemicalTome; + ySize = 209; + } + + @Override + protected void drawGuiContainerForegroundLayer(int x, int y) + { + String containerName = StatCollector.translateToLocal(inventoryAlchemicalTome.getInventoryName()); + fontRendererObj.drawString(containerName, xSize / 2 - fontRendererObj.getStringWidth(containerName) / 2, 6, 4210752); + } + + @Override + protected void drawGuiContainerBackgroundLayer(float var1, int var2, int var3) + { + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + this.mc.getTextureManager().bindTexture(Textures.Gui.ALCHEMICAL_TOME); + int xStart = (width - xSize) / 2; + int yStart = (height - ySize) / 2; + this.drawTexturedModalRect(xStart, yStart, 0, 0, xSize, ySize); + } +} diff --git a/src/main/java/com/pahimar/ee3/client/gui/inventory/GuiGlassBell.java b/src/main/java/com/pahimar/ee3/client/gui/inventory/GuiGlassBell.java index 8fd8b216..1c45dbe9 100644 --- a/src/main/java/com/pahimar/ee3/client/gui/inventory/GuiGlassBell.java +++ b/src/main/java/com/pahimar/ee3/client/gui/inventory/GuiGlassBell.java @@ -35,7 +35,6 @@ public class GuiGlassBell extends GuiContainer @Override protected void drawGuiContainerBackgroundLayer(float var1, int var2, int var3) { - GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); this.mc.getTextureManager().bindTexture(Textures.Gui.GLASS_BELL); int xStart = (width - xSize) / 2; diff --git a/src/main/java/com/pahimar/ee3/handler/GuiHandler.java b/src/main/java/com/pahimar/ee3/handler/GuiHandler.java index 9c14a5ee..b96f568e 100644 --- a/src/main/java/com/pahimar/ee3/handler/GuiHandler.java +++ b/src/main/java/com/pahimar/ee3/handler/GuiHandler.java @@ -27,6 +27,10 @@ public class GuiHandler implements IGuiHandler { return new ContainerAlchemicalBag(entityPlayer, new InventoryAlchemicalBag(entityPlayer.getHeldItem())); } + else if (id == GuiId.ALCHEMICAL_TOME.ordinal()) + { + return new ContainerAlchemicalTome(new InventoryAlchemicalTome(entityPlayer.getHeldItem())); + } else if (id == GuiId.CALCINATOR.ordinal()) { TileEntityCalcinator tileEntityCalcinator = (TileEntityCalcinator) world.getTileEntity(x, y, z); @@ -68,6 +72,10 @@ public class GuiHandler implements IGuiHandler { return new GuiAlchemicalBag(entityPlayer, new InventoryAlchemicalBag(entityPlayer.getHeldItem())); } + else if (id == GuiId.ALCHEMICAL_TOME.ordinal()) + { + return new GuiAlchemicalTome(new InventoryAlchemicalTome(entityPlayer.getHeldItem())); + } else if (id == GuiId.CALCINATOR.ordinal()) { TileEntityCalcinator tileEntityCalcinator = (TileEntityCalcinator) world.getTileEntity(x, y, z); diff --git a/src/main/java/com/pahimar/ee3/inventory/ContainerAlchemicalTome.java b/src/main/java/com/pahimar/ee3/inventory/ContainerAlchemicalTome.java new file mode 100644 index 00000000..ff991e91 --- /dev/null +++ b/src/main/java/com/pahimar/ee3/inventory/ContainerAlchemicalTome.java @@ -0,0 +1,31 @@ +package com.pahimar.ee3.inventory; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.Slot; + +public class ContainerAlchemicalTome extends ContainerEE +{ + private InventoryAlchemicalTome inventoryAlchemicalTome; + + public ContainerAlchemicalTome(InventoryAlchemicalTome inventoryAlchemicalTome) + { + this.inventoryAlchemicalTome = inventoryAlchemicalTome; + + for (int x = 0; x < 9; ++x) + { + for (int y = 0; y < 9; ++y) + { + if (y + x * 9 < inventoryAlchemicalTome.getSizeInventory()) + { + this.addSlotToContainer(new Slot(inventoryAlchemicalTome, y + x * 9, 8 + y * 18, 18 + x * 18) + { + public boolean canTakeStack(EntityPlayer entityPlayer) + { + return false; + } + }); + } + } + } + } +} diff --git a/src/main/java/com/pahimar/ee3/inventory/ContainerEE.java b/src/main/java/com/pahimar/ee3/inventory/ContainerEE.java index 818b2cd2..2d175260 100644 --- a/src/main/java/com/pahimar/ee3/inventory/ContainerEE.java +++ b/src/main/java/com/pahimar/ee3/inventory/ContainerEE.java @@ -1,7 +1,10 @@ package com.pahimar.ee3.inventory; +import com.pahimar.ee3.util.ItemHelper; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.Container; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; public abstract class ContainerEE extends Container { @@ -13,4 +16,75 @@ public abstract class ContainerEE extends Container { return true; } + + @Override + protected boolean mergeItemStack(ItemStack itemStack, int slotMin, int slotMax, boolean ascending) + { + boolean slotFound = false; + int currentSlotIndex = ascending ? slotMax - 1 : slotMin; + + Slot slot; + ItemStack stackInSlot; + + if (itemStack.isStackable()) + { + while (itemStack.stackSize > 0 && (!ascending && currentSlotIndex < slotMax || ascending && currentSlotIndex >= slotMin)) + { + slot = (Slot) this.inventorySlots.get(currentSlotIndex); + stackInSlot = slot.getStack(); + + if (slot.isItemValid(itemStack) && ItemHelper.equalsIgnoreStackSize(itemStack, stackInSlot)) + { + int combinedStackSize = stackInSlot.stackSize + itemStack.stackSize; + int slotStackSizeLimit = Math.min(stackInSlot.getMaxStackSize(), slot.getSlotStackLimit()); + + if (combinedStackSize <= slotStackSizeLimit) + { + itemStack.stackSize = 0; + stackInSlot.stackSize = combinedStackSize; + slot.onSlotChanged(); + slotFound = true; + } + else if (stackInSlot.stackSize < slotStackSizeLimit) + { + itemStack.stackSize -= slotStackSizeLimit - stackInSlot.stackSize; + stackInSlot.stackSize = slotStackSizeLimit; + slot.onSlotChanged(); + slotFound = true; + } + } + + currentSlotIndex += ascending ? -1 : 1; + } + } + + if (itemStack.stackSize > 0) + { + currentSlotIndex = ascending ? slotMax - 1 : slotMin; + + while (!ascending && currentSlotIndex < slotMax || ascending && currentSlotIndex >= slotMin) + { + slot = (Slot) this.inventorySlots.get(currentSlotIndex); + stackInSlot = slot.getStack(); + + if (slot.isItemValid(itemStack) && stackInSlot == null) + { + slot.putStack(ItemHelper.cloneItemStack(itemStack, Math.min(itemStack.stackSize, slot.getSlotStackLimit()))); + slot.onSlotChanged(); + + if (slot.getStack() != null) + { + itemStack.stackSize -= slot.getStack().stackSize; + slotFound = true; + } + + break; + } + + currentSlotIndex += ascending ? -1 : 1; + } + } + + return slotFound; + } } diff --git a/src/main/java/com/pahimar/ee3/inventory/ContainerResearchStation.java b/src/main/java/com/pahimar/ee3/inventory/ContainerResearchStation.java index 3bd8f071..ad46090e 100644 --- a/src/main/java/com/pahimar/ee3/inventory/ContainerResearchStation.java +++ b/src/main/java/com/pahimar/ee3/inventory/ContainerResearchStation.java @@ -19,7 +19,14 @@ public class ContainerResearchStation extends ContainerEE { this.tileEntityResearchStation = tileEntityResearchStation; - this.addSlotToContainer(new Slot(tileEntityResearchStation, TileEntityResearchStation.ITEM_SLOT_INVENTORY_INDEX, 35, 41)); + this.addSlotToContainer(new Slot(tileEntityResearchStation, TileEntityResearchStation.ITEM_SLOT_INVENTORY_INDEX, 35, 41) + { + @Override + public int getSlotStackLimit() + { + return 1; + } + }); this.addSlotToContainer(new SlotResearchStation(tileEntityResearchStation, TileEntityResearchStation.TOME_SLOT_INVENTORY_INDEX, 125, 41)); // Add the player's inventory slots to the container diff --git a/src/main/java/com/pahimar/ee3/inventory/InventoryAlchemicalTome.java b/src/main/java/com/pahimar/ee3/inventory/InventoryAlchemicalTome.java new file mode 100644 index 00000000..932afa7e --- /dev/null +++ b/src/main/java/com/pahimar/ee3/inventory/InventoryAlchemicalTome.java @@ -0,0 +1,139 @@ +package com.pahimar.ee3.inventory; + +import com.pahimar.ee3.reference.Names; +import com.pahimar.ee3.skill.PlayerKnowledge; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; + +public class InventoryAlchemicalTome implements IInventory +{ + public PlayerKnowledge playerKnowledge; + protected ItemStack[] inventory; + protected String customName; + + public InventoryAlchemicalTome(ItemStack itemStack) + { + this(PlayerKnowledge.readPlayerKnowledgeFromNBT(itemStack.getTagCompound())); + } + + public InventoryAlchemicalTome(PlayerKnowledge playerKnowledge) + { + this.playerKnowledge = playerKnowledge; + inventory = playerKnowledge.getKnownItemStacks().toArray(new ItemStack[0]); + } + + @Override + public int getSizeInventory() + { + return inventory.length; + } + + @Override + public ItemStack getStackInSlot(int slotIndex) + { + return inventory[slotIndex]; + } + + @Override + public ItemStack decrStackSize(int slotIndex, int decrementAmount) + { + ItemStack itemStack = getStackInSlot(slotIndex); + if (itemStack != null) + { + if (itemStack.stackSize <= decrementAmount) + { + setInventorySlotContents(slotIndex, null); + } + else + { + itemStack = itemStack.splitStack(decrementAmount); + if (itemStack.stackSize == 0) + { + setInventorySlotContents(slotIndex, null); + } + } + } + + return itemStack; + } + + @Override + public ItemStack getStackInSlotOnClosing(int slotIndex) + { + if (inventory[slotIndex] != null) + { + ItemStack itemStack = inventory[slotIndex]; + inventory[slotIndex] = null; + return itemStack; + } + else + { + return null; + } + } + + @Override + public void setInventorySlotContents(int slotIndex, ItemStack itemStack) + { + inventory[slotIndex] = itemStack; + } + + @Override + public String getInventoryName() + { + return this.hasCustomName() ? this.getCustomName() : Names.Containers.ALCHEMICAL_TOME; + } + + @Override + public boolean hasCustomInventoryName() + { + return false; + } + + @Override + public int getInventoryStackLimit() + { + return 1; + } + + @Override + public void markDirty() + { + // NOOP + } + + @Override + public boolean isUseableByPlayer(EntityPlayer entityPlayer) + { + return true; + } + + @Override + public void openInventory() + { + // NOOP + } + + @Override + public void closeInventory() + { + // NOOP + } + + @Override + public boolean isItemValidForSlot(int slotIndex, ItemStack itemStack) + { + return false; + } + + public boolean hasCustomName() + { + return customName != null && customName.length() > 0; + } + + public String getCustomName() + { + return customName; + } +} diff --git a/src/main/java/com/pahimar/ee3/item/ItemAlchemicalTome.java b/src/main/java/com/pahimar/ee3/item/ItemAlchemicalTome.java index c0bbe9ee..7af7bd12 100644 --- a/src/main/java/com/pahimar/ee3/item/ItemAlchemicalTome.java +++ b/src/main/java/com/pahimar/ee3/item/ItemAlchemicalTome.java @@ -1,5 +1,7 @@ package com.pahimar.ee3.item; +import com.pahimar.ee3.EquivalentExchange3; +import com.pahimar.ee3.reference.GuiId; import com.pahimar.ee3.reference.Names; import com.pahimar.ee3.skill.PlayerKnowledge; import com.pahimar.ee3.util.IOwnable; @@ -31,6 +33,8 @@ public class ItemAlchemicalTome extends ItemEE implements IOwnable { // Set the owner ItemHelper.setOwner(itemStack, entityPlayer); + + entityPlayer.openGui(EquivalentExchange3.instance, GuiId.ALCHEMICAL_TOME.ordinal(), entityPlayer.worldObj, (int) entityPlayer.posX, (int) entityPlayer.posY, (int) entityPlayer.posZ); } return itemStack; diff --git a/src/main/java/com/pahimar/ee3/reference/GuiId.java b/src/main/java/com/pahimar/ee3/reference/GuiId.java index 316a6ed7..39ed3e1f 100644 --- a/src/main/java/com/pahimar/ee3/reference/GuiId.java +++ b/src/main/java/com/pahimar/ee3/reference/GuiId.java @@ -9,5 +9,6 @@ public enum GuiId ALCHEMICAL_BAG, GLASS_BELL, RESEARCH_STATION, - AUGMENTATION_TABLE; + AUGMENTATION_TABLE, + ALCHEMICAL_TOME; } diff --git a/src/main/java/com/pahimar/ee3/reference/Names.java b/src/main/java/com/pahimar/ee3/reference/Names.java index da434ad5..6a979495 100644 --- a/src/main/java/com/pahimar/ee3/reference/Names.java +++ b/src/main/java/com/pahimar/ee3/reference/Names.java @@ -107,6 +107,7 @@ public class Names public static final String RESEARCH_STATION = "container.ee3:" + Blocks.RESEARCH_STATION; public static final String GLASS_BELL = "container.ee3:" + Blocks.GLASS_BELL; public static final String AUGMENTATION_TABLE = "container.ee3:" + Blocks.AUGMENTATION_TABLE; + public static final String ALCHEMICAL_TOME = "container.ee3:" + Items.ALCHEMICAL_TOME; } public static final class Keys diff --git a/src/main/java/com/pahimar/ee3/reference/Textures.java b/src/main/java/com/pahimar/ee3/reference/Textures.java index 676c54e7..106c256b 100644 --- a/src/main/java/com/pahimar/ee3/reference/Textures.java +++ b/src/main/java/com/pahimar/ee3/reference/Textures.java @@ -41,6 +41,7 @@ public final class Textures public static final ResourceLocation RESEARCH_STATION = ResourceLocationHelper.getResourceLocation(GUI_SHEET_LOCATION + "researchStation.png"); public static final ResourceLocation AUGMENTATION_TABLE = ResourceLocationHelper.getResourceLocation(GUI_SHEET_LOCATION + "augmentationTable.png"); public static final ResourceLocation PORTABLE_CRAFTING = new ResourceLocation("textures/gui/container/crafting_table.png"); + public static final ResourceLocation ALCHEMICAL_TOME = ResourceLocationHelper.getResourceLocation(GUI_SHEET_LOCATION + "alchemicalTome.png"); } public static final class Effect diff --git a/src/main/java/com/pahimar/ee3/skill/PlayerKnowledge.java b/src/main/java/com/pahimar/ee3/skill/PlayerKnowledge.java index a800094a..c5c99d4f 100644 --- a/src/main/java/com/pahimar/ee3/skill/PlayerKnowledge.java +++ b/src/main/java/com/pahimar/ee3/skill/PlayerKnowledge.java @@ -41,7 +41,7 @@ public class PlayerKnowledge implements INBTTaggable public boolean isItemStackKnown(ItemStack itemStack) { ItemStack unitItemStack = itemStack.copy(); - itemStack.stackSize = 1; + unitItemStack.stackSize = 1; return this.knownItemStacks.contains(unitItemStack); } @@ -53,7 +53,7 @@ public class PlayerKnowledge implements INBTTaggable public boolean learnItemStack(ItemStack itemStack) { ItemStack unitItemStack = itemStack.copy(); - itemStack.stackSize = 1; + unitItemStack.stackSize = 1; if (!this.knownItemStacks.contains(unitItemStack)) { @@ -66,7 +66,7 @@ public class PlayerKnowledge implements INBTTaggable public boolean forgetItemStack(ItemStack itemStack) { ItemStack unitItemStack = itemStack.copy(); - itemStack.stackSize = 1; + unitItemStack.stackSize = 1; if (this.knownItemStacks.contains(unitItemStack)) { @@ -123,4 +123,19 @@ public class PlayerKnowledge implements INBTTaggable return playerKnowledge; } + + @Override + public String toString() + { + StringBuilder stringBuilder = new StringBuilder(); + + stringBuilder.append("["); + for (ItemStack itemStack : knownItemStacks) + { + stringBuilder.append(ItemHelper.toString(itemStack) + ", "); + } + stringBuilder.append("]"); + + return stringBuilder.toString(); + } } diff --git a/src/main/java/com/pahimar/ee3/tileentity/TileEntityResearchStation.java b/src/main/java/com/pahimar/ee3/tileentity/TileEntityResearchStation.java index 6f734ce3..2ac707f5 100644 --- a/src/main/java/com/pahimar/ee3/tileentity/TileEntityResearchStation.java +++ b/src/main/java/com/pahimar/ee3/tileentity/TileEntityResearchStation.java @@ -1,6 +1,7 @@ package com.pahimar.ee3.tileentity; import com.pahimar.ee3.reference.Names; +import com.pahimar.ee3.skill.PlayerKnowledge; import com.pahimar.ee3.util.PlayerKnowledgeHelper; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; @@ -205,7 +206,9 @@ public class TileEntityResearchStation extends TileEntityEE implements IInventor { if (this.canLearnItemStack()) { - // TODO Add the input item to the books knowledge + PlayerKnowledge playerKnowledge = PlayerKnowledge.readPlayerKnowledgeFromNBT(this.inventory[TOME_SLOT_INVENTORY_INDEX].getTagCompound()); + playerKnowledge.learnItemStack(this.inventory[ITEM_SLOT_INVENTORY_INDEX]); + playerKnowledge.writeToNBT(this.inventory[TOME_SLOT_INVENTORY_INDEX].getTagCompound()); this.inventory[ITEM_SLOT_INVENTORY_INDEX].stackSize--; diff --git a/src/main/java/com/pahimar/ee3/util/ItemHelper.java b/src/main/java/com/pahimar/ee3/util/ItemHelper.java index 605d8007..d3660846 100644 --- a/src/main/java/com/pahimar/ee3/util/ItemHelper.java +++ b/src/main/java/com/pahimar/ee3/util/ItemHelper.java @@ -12,6 +12,13 @@ import java.util.UUID; public class ItemHelper { + public static ItemStack cloneItemStack(ItemStack itemStack, int stackSize) + { + ItemStack clonedItemStack = itemStack.copy(); + clonedItemStack.stackSize = stackSize; + return clonedItemStack; + } + public static Comparator comparator = new Comparator() { public int compare(ItemStack itemStack1, ItemStack itemStack2) @@ -88,6 +95,36 @@ public class ItemHelper return (comparator.compare(first, second) == 0); } + public static boolean equalsIgnoreStackSize(ItemStack itemStack1, ItemStack itemStack2) + { + if (itemStack1 != null && itemStack2 != null) + { + // Sort on itemID + if (Item.getIdFromItem(itemStack1.getItem()) - Item.getIdFromItem(itemStack2.getItem()) == 0) + { + // Then sort on meta + if (itemStack1.getItemDamage() == itemStack2.getItemDamage()) + { + // Then sort on NBT + if (itemStack1.hasTagCompound() && itemStack2.hasTagCompound()) + { + // Then sort on stack size + if (itemStack1.getTagCompound().equals(itemStack2.getTagCompound())) + { + return true; + } + } + else + { + return true; + } + } + } + } + + return false; + } + public static int compare(ItemStack itemStack1, ItemStack itemStack2) { return comparator.compare(itemStack1, itemStack2); diff --git a/src/main/resources/assets/ee3/lang/en_US.lang b/src/main/resources/assets/ee3/lang/en_US.lang index 419fa2a6..2b34e481 100644 --- a/src/main/resources/assets/ee3/lang/en_US.lang +++ b/src/main/resources/assets/ee3/lang/en_US.lang @@ -85,7 +85,7 @@ tile.ee3:aludel.name=Aludel Base tile.ee3:calcinator.name=Calcinator tile.ee3:chalk.name=Chalk tile.ee3:glassBell.name=Glass Bell -tile.ee3:researchStation.name=Research Station [WIP] +tile.ee3:researchStation.name=Research Station tile.ee3:augmentationTable.name=Augmentation Table [WIP] # GUIs @@ -94,8 +94,9 @@ container.ee3:alchemicalChest=Alchemical Chest container.ee3:aludel=Aludel container.ee3:calcinator=Calcinator container.ee3:glassBell=Glass Bell -container.ee3:researchStation=Research Station [WIP] +container.ee3:researchStation=Research Station container.ee3:augmentationTable=Augmentation Table [WIP] +container.ee3:alchemicalTome=Tome of Alchemical Knowledge [WIP] # Tooltips tooltip.ee3:upgradesPrefix=Upgrades (Alchemical) Chests diff --git a/src/main/resources/assets/ee3/textures/gui/alchemicalTome.png b/src/main/resources/assets/ee3/textures/gui/alchemicalTome.png new file mode 100644 index 0000000000000000000000000000000000000000..1e1bf2a05df5df482cb70191a80599d070b51de0 GIT binary patch literal 4391 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ee3/textures/xcf/gui/alchemicalTome.xcf b/src/main/resources/assets/ee3/textures/xcf/gui/alchemicalTome.xcf new file mode 100644 index 0000000000000000000000000000000000000000..0407e7b8011f022545c5bfb7bfe19d0d3855e062 GIT binary patch literal 42101 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 literal 0 HcmV?d00001