From 4f91277261c40ad3e45b30f599aa785a63d79526 Mon Sep 17 00:00:00 2001 From: Archtikz Date: Sun, 8 Mar 2015 19:16:21 +0000 Subject: [PATCH] Completely remade Seismic Reader, may not be 100% efficient as it could be and I've bug tested as much as I can. --- .../java/mekanism/client/ClientProxy.java | 2 +- .../mekanism/client/gui/GuiSeismicReader.java | 582 ++++++------------ .../assets/mekanism/gui/GuiSeismicReader.png | Bin 3560 -> 3306 bytes .../mekanism/gui/elements/GuiTooltips.png | Bin 0 -> 1620 bytes .../mekanism/textures/items/SeismicReader.png | Bin 1613 -> 2366 bytes 5 files changed, 181 insertions(+), 403 deletions(-) create mode 100644 src/main/resources/assets/mekanism/gui/elements/GuiTooltips.png diff --git a/src/main/java/mekanism/client/ClientProxy.java b/src/main/java/mekanism/client/ClientProxy.java index adb967f70..6acaf1448 100644 --- a/src/main/java/mekanism/client/ClientProxy.java +++ b/src/main/java/mekanism/client/ClientProxy.java @@ -481,7 +481,7 @@ public class ClientProxy extends CommonProxy if(itemStack1 != null && itemStack1.getItem() instanceof ItemSeismicReader) { - return new GuiSeismicReader(new Coord4D(x, y, z, world.provider.dimensionId), itemStack1); + return new GuiSeismicReader(world, new Coord4D(x, y, z, world.provider.dimensionId), itemStack1); } case 39: return new GuiSeismicVibrator(player.inventory, (TileEntitySeismicVibrator)tileEntity); diff --git a/src/main/java/mekanism/client/gui/GuiSeismicReader.java b/src/main/java/mekanism/client/gui/GuiSeismicReader.java index b9537e905..8556cedaa 100644 --- a/src/main/java/mekanism/client/gui/GuiSeismicReader.java +++ b/src/main/java/mekanism/client/gui/GuiSeismicReader.java @@ -1,425 +1,203 @@ package mekanism.client.gui; import java.util.ArrayList; -import java.util.List; import mekanism.api.Coord4D; import mekanism.common.item.ItemSeismicReader; import mekanism.common.util.MekanismUtils; import mekanism.common.util.MekanismUtils.ResourceType; - import net.minecraft.block.Block; -import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.renderer.RenderHelper; import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; import net.minecraft.world.World; -import net.minecraftforge.fluids.Fluid; -import net.minecraftforge.fluids.IFluidBlock; + +import org.apache.commons.lang3.tuple.Pair; +import org.lwjgl.opengl.GL11; +import org.lwjgl.util.Rectangle; + import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import org.lwjgl.input.Mouse; -import org.lwjgl.opengl.GL11; - @SideOnly(Side.CLIENT) -public class GuiSeismicReader extends GuiScreen -{ - private World worldObj = Minecraft.getMinecraft().theWorld; - - public ItemStack itemStack; - - public int scroll; - - public int prevMouseY; - - public Coord4D pos; - - public boolean prevMouseDown; - - public boolean isDragging = false; - - public List seismicCalculation = new ArrayList(); - - public int scrollStartX = 10; - public int scrollStartY = 12; - - protected int xSize = 118; - protected int ySize = 166; - - public GuiSeismicReader(Coord4D coord, ItemStack stack) - { - pos = coord; - pos.yCoord = Math.min(255, pos.yCoord); - - itemStack = stack; - - calculate(); - } +public class GuiSeismicReader extends GuiScreen { + private World worldObj; - @Override - public void drawScreen(int mouseX, int mouseY, float partialTick) - { - GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); - mc.renderEngine.bindTexture(MekanismUtils.getResource(ResourceType.GUI, "GuiSeismicReader.png")); + public ItemStack itemStack; - int guiWidth = (width - xSize) / 2; - int guiHeight = (height - ySize) / 2; - - int xAxis = mouseX - guiWidth; - int yAxis = mouseY - guiHeight; - - if(Mouse.isButtonDown(0)) - { - if(!isDragging && (xAxis >= 10 && xAxis <= 48 && yAxis >= 12 && yAxis <= 154)) - { - if(!prevMouseDown) - { - prevMouseDown = true; - } - else { - int mouseDiff = prevMouseY-yAxis; - - scroll = Math.max(0, Math.min(scroll+mouseDiff, calcMaxScroll())); - } - } - - int maxScroll = calcMaxScroll(); - - if(!isDragging && maxScroll > 0 && (xAxis >= 49 && xAxis <= 53 && yAxis >= getScrollButtonY() && yAxis <= getScrollButtonY()+4)) - { - if(!prevMouseDown) - { - prevMouseDown = true; - isDragging = true; - } - } - - if(isDragging) - { - int relY = Math.max(13, Math.min(149, yAxis))-13; - scroll = calcScrollFromButton(relY); - } - - prevMouseY = yAxis; - } - else { - prevMouseDown = false; - isDragging = false; - } - - drawTexturedModalRect(guiWidth + scrollStartX, guiHeight + scrollStartY, xSize, 13, 38, 142); - - drawChartLayer(guiWidth, guiHeight); - - drawTexturedModalRect(guiWidth, guiHeight, 0, 0, xSize, ySize); - - drawTexturedModalRect(guiWidth + scrollStartX + 38 + 1, guiHeight + getScrollButtonY(), xSize, 0, 4, 4); - - fontRendererObj.drawString(MekanismUtils.localize("gui.seismicReader.short"), guiWidth + 62, guiHeight + 18, 0x000000); - - fontRendererObj.drawString(MekanismUtils.localize("gui.seismicReader.solids"), guiWidth + 70, guiHeight + 40, 0x0404040); - fontRendererObj.drawString(MekanismUtils.localize("gui.seismicReader.fluids"), guiWidth + 70, guiHeight + 62, 0x0404040); - fontRendererObj.drawString(MekanismUtils.localize("gui.empty"), guiWidth + 70, guiHeight + 78, 0x0404040); - - fontRendererObj.drawString(MekanismUtils.localize("gui.seismicReader.reading"), guiWidth + 62, guiHeight + 114, 0x00CD00); - fontRendererObj.drawString(MekanismUtils.localize("gui.energy") + ":", guiWidth + 62, guiHeight + 132, 0x00CD00); - fontRendererObj.drawString(MekanismUtils.getEnergyDisplay(getEnergy()), guiWidth + 62, guiHeight + 141, 0x00CD00); - - super.drawScreen(mouseX, mouseY, partialTick); - } - - public double getEnergy() - { - return ((ItemSeismicReader)itemStack.getItem()).getEnergy(itemStack); - } - - public void drawChartLayer(int guiWidth, int guiHeight) - { - if(scroll <= 5) - { - drawTexturedModalRect(guiWidth + scrollStartX, guiHeight + scrollStartY+5-scroll, xSize, 4, 38, 1); - } - - int amount = Math.min((142/2)+Math.min(0, (scroll/2)-3), pos.yCoord); - int start = pos.yCoord-(scroll/2)+Math.min(3, scroll/2); - int yStart = scrollStartY + Math.max(0, 6-scroll); - - drawScale(guiWidth, guiHeight, amount, start, yStart, scroll%2==1); - - if(calcMaxScroll() > 0 && scroll == calcMaxScroll()) - { - drawTexturedModalRect(guiWidth + scrollStartX, guiHeight + scrollStartY+142-1, xSize, 4, 38, 1); - } - else if(calcMaxScroll() <= 0) - { - int dist = yStart + amount*2; - drawTexturedModalRect(guiWidth + scrollStartX, guiHeight + dist, xSize, 4, 38, 1); - } - } - - public void drawScale(int guiWidth, int guiHeight, int amount, int start, int yStart, boolean half) - { - int starting = 0; - int toRender = amount; - int nextRender = guiHeight + yStart; - - if(half) - { - starting++; - } - - if(scroll < 6) - { - nextRender += (half ? 1 : 0); - } - - if(start%4 != 0) - { - starting += (4-(start%4))*2; - drawTexturedModalRect(guiWidth + 30, nextRender, xSize, 5+starting, 3, 8-starting); - toRender -= (8-starting)/2; - nextRender += (8-starting); - - if(!seismicCalculation.isEmpty()) - { - int rendered = 8-starting+(half && scroll > 6 ? 1 : 0); - int nextY = guiHeight + yStart - (half && scroll > 6 ? 1 : 0); - - seismicCalculation.get(start-1).render(this, xSize, guiWidth, nextY); - - if(rendered > 2) - { - seismicCalculation.get(start-2).render(this, xSize, guiWidth, nextY+2); - } - - if(rendered > 4) - { - seismicCalculation.get(start-3).render(this, xSize, guiWidth, nextY+4); - } - } - } - else { - nextRender -= half ? 1 : 0; - } - - while(toRender >= 4) - { - toRender -= 4; - - drawTexturedModalRect(guiWidth + 30, nextRender, xSize, 5, 3, 8); - - int index = start-(amount-toRender); - - if((index-1)%2 == 0) - { - index -= 1; - } - - if(index%8 == 0 && pos.yCoord-index > 6) - { - int yPos = nextRender+2; - - if(index == 0) - { - yPos -= 2; - } - - fontRendererObj.drawString(Integer.toString(index), guiWidth + 28-fontRendererObj.getStringWidth(Integer.toString(index)), yPos, 0xFFFFFF); - mc.renderEngine.bindTexture(MekanismUtils.getResource(ResourceType.GUI, "GuiSeismicReader.png")); - } - - if(!seismicCalculation.isEmpty()) - { - seismicCalculation.get(index+3).render(this, xSize, guiWidth, nextRender); - seismicCalculation.get(index+2).render(this, xSize, guiWidth, nextRender+2); - seismicCalculation.get(index+1).render(this, xSize, guiWidth, nextRender+4); - seismicCalculation.get(index+0).render(this, xSize, guiWidth, nextRender+6); - } - - nextRender += 8; - } - - if(toRender > 0) - { - drawTexturedModalRect(guiWidth + 30, nextRender, xSize, 5, 3, toRender*2); - - if(!seismicCalculation.isEmpty()) - { - int index = start-(amount-toRender); - - if((index-1)%2 == 0) - { - index -= 1; - } - - if(index-1 >= 0) - { - seismicCalculation.get(index-1).render(this, xSize, guiWidth, nextRender); - } - - if(toRender > 1 && index-2 >= 0) - { - seismicCalculation.get(index-2).render(this, xSize, guiWidth, nextRender+2); - } - - if(toRender > 2 && index-3 >= 0) - { - seismicCalculation.get(index-3).render(this, xSize, guiWidth, nextRender+4); - } - } - } - } - - public int getScrollButtonY() - { - int max = calcMaxScroll(); - - if(max == 0) - { - return scrollStartY+1; - } - - return scrollStartY+1+(int)(((float)scroll/max)*136); - } - - public int calcScrollFromButton(int relButtonY) - { - return (int)(((float)relButtonY/136)*calcMaxScroll()); - } - - public int calcMaxScroll() - { - int ret = 6; - - ret += (pos.yCoord*2); //2 pixels per block - ret += 1; //Bottom layer thing - ret -= 142; //142 total pixels lengthwise on display - - return ret; - } - - public void calculate() - { - seismicCalculation.clear(); - - for(int y = 1; y <= pos.yCoord; y++) - { - Coord4D coord = new Coord4D(pos.xCoord, y, pos.zCoord, pos.dimensionId); - - if(coord.isAirBlock(worldObj)) - { - seismicCalculation.add(SeismicType.EMPTY); - continue; - } - - Block block = coord.getBlock(worldObj); - int meta = coord.getMetadata(worldObj); + private ArrayList> blockList = new ArrayList>(); - if(block == Blocks.grass) - { - seismicCalculation.add(SeismicType.GRASS); - continue; - } - else if(block == Blocks.dirt) - { - seismicCalculation.add(SeismicType.DIRT); - continue; - } - else if(block == Blocks.stone) - { - seismicCalculation.add(SeismicType.STONE); - continue; - } - else if(block == Blocks.bedrock) - { - seismicCalculation.add(SeismicType.BEDROCK); - continue; - } - else if(block == Blocks.water || block == Blocks.flowing_water) - { - seismicCalculation.add(SeismicType.WATER); - continue; - } - else if(block == Blocks.lava || block == Blocks.flowing_lava) - { - seismicCalculation.add(SeismicType.LAVA); - continue; - } - - if(block instanceof IFluidBlock) - { - Fluid fluid = ((IFluidBlock)block).getFluid(); - - if(fluid != null) - { - String name = fluid.getName().toLowerCase(); - - if(name.equals("water")) - { - seismicCalculation.add(SeismicType.WATER); - continue; - } - else if(name.equals("lava")) - { - seismicCalculation.add(SeismicType.LAVA); - continue; - } - else if(name.equals("oil")) - { - seismicCalculation.add(SeismicType.OIL); - continue; - } - } - } - - List oreDictNames = MekanismUtils.getOreDictName(new ItemStack(block, 1, meta)); - boolean foundName = false; - - if(oreDictNames != null && !oreDictNames.isEmpty()) - { - for(String s : oreDictNames) - { - if(s.trim().startsWith("ore")) - { - seismicCalculation.add(SeismicType.ORE); - foundName = true; - break; - } - } - } - - if(foundName) - { - continue; - } - - seismicCalculation.add(SeismicType.OTHER); - } + public Coord4D pos; + + protected int xSize = 137; + protected int ySize = 179; + + private Rectangle upButton, downButton; + + private int currentLayer = 0; + + public GuiSeismicReader(World world, Coord4D coord, ItemStack stack) { + pos = coord; + pos.yCoord = Math.min(255, pos.yCoord); + worldObj = world; + + itemStack = stack; + calculate(); + currentLayer = Math.max(0, blockList.size() - 1); + } + + @Override + public void initGui() { + upButton = new Rectangle((width - xSize) / 2 + 70, (height - ySize) / 2 + 75, 13, 13); + downButton = new Rectangle((width - xSize) / 2 + 70, (height - ySize) / 2 + 92, 13, 13); + super.initGui(); + } + + int rotation = 0; + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTick) { + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + int guiWidth = (width - xSize) / 2; + int guiHeight = (height - ySize) / 2; + + mc.renderEngine.bindTexture(MekanismUtils.getResource(ResourceType.GUI, "GuiSeismicReader.png")); + + drawTexturedModalRect(guiWidth, guiHeight, 0, 0, xSize, ySize); + if (upButton.intersects(new Rectangle(mouseX, mouseY, 1, 1))) { + GL11.glColor3f(0.5f, 0.5f, 1f); } - - @Override - public boolean doesGuiPauseGame() - { - return false; - } - - public static enum SeismicType - { - GRASS, - DIRT, - OTHER, - ORE, - STONE, - BEDROCK, - WATER, - LAVA, - OIL, - EMPTY; - - public void render(GuiSeismicReader gui, int xSize, int guiWidth, int y) - { - gui.drawTexturedModalRect(guiWidth + 33, y, xSize, 155+(ordinal()*2), 4, 2); - } + drawTexturedModalRect(upButton.getX(), upButton.getY(), 137, 0, upButton.getWidth(), upButton.getHeight()); + GL11.glColor3f(1, 1, 1); + if (downButton.intersects(new Rectangle(mouseX, mouseY, 1, 1))) { + GL11.glColor3f(0.5f, 0.5f, 1f); } + drawTexturedModalRect(downButton.getX(), downButton.getY(), 150, 0, downButton.getWidth(), downButton.getHeight()); + GL11.glColor3f(1, 1, 1); + + GL11.glPushMatrix(); + GL11.glTranslatef(guiWidth + 48, guiHeight + 87, 0); + if (currentLayer >= 100) { + GL11.glTranslatef(0, 1, 0); + GL11.glScalef(0.7f, 0.7f, 0.7f); + } + fontRendererObj.drawString(String.format("%s", currentLayer), 0, 0, 0xAFAFAF); + GL11.glPopMatrix(); + + for (int i = 0; i < 7; i++) { + int centralX = guiWidth + 32, centralY = guiHeight + 103; + int layer = currentLayer + (i - 4); + if (0 <= layer && layer < blockList.size()) { + ItemStack stack = new ItemStack(blockList.get(layer).getRight(), 1, blockList.get(layer).getLeft()); + if (stack.getItem() == null) { + continue; + } + GL11.glPushMatrix(); + GL11.glTranslatef(centralX - 2, centralY - i * 20 + (20 * 2), 0); + itemRender.renderItemAndEffectIntoGUI(fontRendererObj, this.mc.getTextureManager(), stack, 0, 0); + GL11.glPopMatrix(); + } + } + mc.renderEngine.bindTexture(MekanismUtils.getResource(ResourceType.GUI_ELEMENT, "GuiTooltips.png")); + if (currentLayer - 1 >= 0) { + ItemStack nameStack = new ItemStack(blockList.get(currentLayer - 1).getRight(), 0, blockList.get(currentLayer - 1).getLeft()); + String renderString = "unknown"; + if (nameStack.getItem() != null) { + renderString = nameStack.getDisplayName(); + } else if (blockList.get(currentLayer - 1).getRight() == Blocks.air) { + renderString = "Air"; + } + String capitalised = renderString.substring(0, 1).toUpperCase() + renderString.substring(1); + float renderScale = 1.0f; + int lengthX = fontRendererObj.getStringWidth(capitalised); + + renderScale = lengthX > 53 ? 53f / lengthX : 1.0f; + + GL11.glPushMatrix(); + GL11.glTranslatef(guiWidth + 72, guiHeight + 16, 0); + GL11.glScalef(renderScale, renderScale, renderScale); + fontRendererObj.drawString(capitalised, 0, 0, 0x919191); + GL11.glPopMatrix(); + } + int frequency = 0; + for (Pair pair : blockList) { + if (blockList.get(currentLayer - 1) != null) { + Block block = blockList.get(currentLayer - 1).getRight(); + if (pair.getRight() == block && pair.getLeft() == blockList.get(currentLayer - 1).getLeft()) { + frequency++; + } + } + } + GL11.glPushMatrix(); + GL11.glTranslatef(guiWidth + 72, guiHeight + 26, 0); + GL11.glScalef(0.70f, 0.70f, 0.70f); + fontRendererObj.drawString(String.format("Abundancy: %s", frequency), 0, 0, 0x919191); + GL11.glPopMatrix(); + super.drawScreen(mouseX, mouseY, partialTick); + } + + public String wrapString(String str, int index) { + String string = str; + for (int i = 0; i < string.length(); i++) { + if (i == index) { + string = string.substring(0, i) + "\n" + string.substring(i); + } + } + return string; + } + + @Override + public void drawBackground(int p_146278_1_) { + super.drawBackground(p_146278_1_); + } + + @Override + public void onGuiClosed() { + blockList.clear(); + super.onGuiClosed(); + } + + public void calculate() { + for (int y = 0; y < pos.yCoord; y++) { + Block block = worldObj.getBlock(pos.xCoord - 1, y, pos.zCoord - 1); + int metadata = worldObj.getBlockMetadata(pos.xCoord - 1, y, pos.zCoord - 1); + blockList.add(Pair.of(metadata, block)); + } + } + + @Override + protected void mouseClicked(int xPos, int yPos, int buttonClicked) { + if (upButton.intersects(new Rectangle(xPos, yPos, 1, 1))) { + if (currentLayer + 1 <= blockList.size() - 1) { + currentLayer++; + } + } + if (downButton.intersects(new Rectangle(xPos, yPos, 1, 1))) { + if (currentLayer - 1 >= 1) { + currentLayer--; + } + } + super.mouseClicked(xPos, yPos, buttonClicked); + } + + @Override + protected void actionPerformed(GuiButton button) { + super.actionPerformed(button); + } + + @Override + protected void keyTyped(char c, int p_73869_2_) { + super.keyTyped(c, p_73869_2_); + } + + public double getEnergy() { + return ((ItemSeismicReader) itemStack.getItem()).getEnergy(itemStack); + } + + @Override + public boolean doesGuiPauseGame() { + return false; + } } diff --git a/src/main/resources/assets/mekanism/gui/GuiSeismicReader.png b/src/main/resources/assets/mekanism/gui/GuiSeismicReader.png index a77239c811928ad65f6c7e1f8a3ae9afdff85495..27dd769d30b2d2a585e5f2f82ee12c1fd0ff9196 100644 GIT binary patch literal 3306 zcmeHIdoh+ZLJgQRHk2rlpwP2%UR?5qG7WG$*H7KzpxKDMXq03ay< zkRS)Zaw-7V#sP@F0st!%0QeICcDROOys`m+&iNw{jz|PT!!bC>&;ODy0Jd$nPmcr* zJ1fF(26^Odh3A$h$}7c}opy4s`C6rP`=}Hl{w9Ki_vz3}sMlhQUw_yKd zY}xkReP$+dJDNW4X-rN@B4=hCa?zCTvf8y^ng2tyeXWPSn0{;AvHoV1=2NrWGD4RnVZ@EYIy3wR+1r%uv(cdBfE^B7^y-W+PQ~1yiS~ z-Dfl6^9CySGIUz_M*Eg8ZRDz6snl}Nn^LLmh&mZIbKm>5YpsK$u**2;z!^>y=i~gu z&Ll=%QlD3NTkj@9DW(S5VxZMH!P~x*pu}lt_0YK;VPH9b?|yXNv*nj2TUkzQ4f;*$ zMP6K?W8;NaX*;O_!I7O7Mc1=2wI;XBuPSdIE$XpOnbfjO_rn#VZbY+gmv_^?nbkWn zaR$GY^}WvQG3;nhYx|ApO@t3aQ{r82u0QyBjSJ#*6H)TGP5pWm&hIU59%;yJwVWNu zZ>8#)jWIQY-3>jB5*4ilcYGu(Zq%f30}&AfBLW2cu~9?km1hcOvM=9$Q)|F>N*fs8k1s0l zpe#JayBXP;IYvG{Za$^oJ*7cmYta6xUhs5DubdmD%^j6AT~MaGne2EI0v*FBTMBo0X zvqqSazOlYB^48iI02|=QBUa84UNb{>fr|brN8gep)*~jKZF_4zN zCcfn?G+`S>JUlM8g8pF|D?n4?*tk5c^k*F3E$8S?dvDQPJnrZU-?b&F-_2j)uP(KB zk>Npt>7C){=fkK{`hPZV4`-}Ax~xVlL(#nO%k$#}WQ*9^81BTYK1!E)YIU<(YLeDGoc}#{vPRyt2H|gz52mm{9uaSd0 ztOFd#7JM4U9Wq!O6zd6Q?{=VoDNMG>kp6(hGLb+F8yAfsRFokBG8VBLusEf{Nb?D@ z8IB*?;+eWE3)-^8C~!I-BZ9_`3L<|GofUa!t@g__@$Y;AVmo{wgQtFpA!Dg5=gumL9@tW~`76JIxMFiN!`1NqMO<<0hOV$u)}&XReAD89xI((9E^)LX5hki+ z6Y(U7da)*932Y!AG`Y$EvP~kF^nbv=k%y{MNQsk~o^M7Vkc(&@fT6q>eMw1*E?v zU&1j6e1M|0Ww*u9 z2o^E(Y&Hof&arnn QXgxaesQr;rYxI?$0i1)ONB{r; delta 2563 zcmcgtYgAKL7CyOLLPDqnY6zmFVSEA#NCX`N_R2#9Euhk1vAkkOWg^6Cl)ymljUp&a zKrIxsh^aO{cqm$VL%9Vp)inW>SBek?Mu{~LR0M&N^!jtwQm1Rp8qcq@*FN9+zWtrO z&-rbhcK(Tl43n`qU*FI`Utf0Ue&MdTy?+B>jqJK;zy!6f7)S?z`eUHq`Y7_);A)uFps;OyC*R?c>!^UHeO!l0FdO}Fse(~H{=mD;+W`1Y7R%#YhA@lm*E zSULRQZoR)>vuJ5?$*O}1tquB}j%ww>l(xwf<+V1MZ=KuPY8|UjRB{QTjnp%l%q&TQ zP^dSeU(DF{z^&d6>i)WRZ4KVk=-jQvs)48nq1`Ft(_cK zE|#3Ua`Lp7#8_ogz|~uoY@4eNk)ZRrMx1M?Gs=K1bYN@4)@78#$6c45j4+Gl0_ zy$E|f?uhv0cWsPGM|5*=uHm1Ifzf4BH4xA0UqpKuo>c^f4KX&!t@fG6*wZOC$NEWP zrDfEspodIi+gG1-pc75;xCE&xXi`4{w!J};*sJe)B{-fM&XHb0#vO6ld>%=ls2*BSJ+&tw#O2G=iA$+nG?$HZ=K3QzBwKZo2P!{mp?L>T|1i@ z@`gyP42hopO-NK!Y6ATXLG0?Oprve3N+JUEKccq;^qDL~|8S;CYX}LCc6pyO7xWrO zyV<)-8yP!IASx70daHk3CE=H3QBhH>`1p9)Xg^xV>=L(F?}7Otq%%y(fnU|?f~XnG zH+IRBpM`U!JOtddzDkA7DHwjy`849p1`*UA7$UkPrXz2&oIwX= zX#z+})L8yBXh}P9j@RTNMMxyNTD17%J;XWZfis941C+hBr>Hlf>!{Hc9~|Th+!{0* z&AZD}ll&@nT!({*E=;zyI!1K$mJ!}^=~e{fvNpiyi3Sd9(N0u=RP zwLMPq3arGoVLC&}x-Sus<_aF~CMNNNgy;ujdOH#Nf2p`|zRy%*_v-Y}bUTX3Wz36I z{$NU%{WWejiLSeSVGhfkm19Xxu%a;6pggd7$v5lW%1TQu&SwwJz5epaCoRpa+48#3 zzE~tC1aAY&-wds?mjus@SB~cxmp>d6<`jD!c~+(mU6NqtmK$7r1g8?i9gKBn2&Z%< z#>_a4L2heDFECe=wo~B4rZA3t*H|lw?@aN?pGcM~oSvD&Fiv~aHC~1a1cDY3@7lw& z*$uC0Hb)jhsy1LV;ZmpCJsZHhcT#CLu@R>=2B_9HU#a9`M~T0LQ<(1CwkhVofgh8K zUvTgw@0#Ixh4{UrgUy46s_K!a_o6B%CmVej|N88aR*Bi%>D%LNC7m|SCL^;P&*q)f z`st}_EklN>iGJbpE?(+etvIK>uLBt3EM@{{YMz-f;i` diff --git a/src/main/resources/assets/mekanism/gui/elements/GuiTooltips.png b/src/main/resources/assets/mekanism/gui/elements/GuiTooltips.png new file mode 100644 index 0000000000000000000000000000000000000000..3efb2898db5bf7acf0ee290ff035b779619f7d0d GIT binary patch literal 1620 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