From cfb0986a4854fea5f7b81392f012f22c7a55ad67 Mon Sep 17 00:00:00 2001 From: aidancbrady Date: Tue, 1 Mar 2016 13:37:19 -0500 Subject: [PATCH] Added fancy graphs to display boil rate and max boil value of boilers, boiler valves now connect to corresponding tanks of multiblock based on location --- .../mekanism/client/gui/GuiBoilerStats.java | 39 ++++- .../mekanism/client/gui/element/GuiGraph.java | 152 ++++++++++++++++++ .../client/gui/element/GuiScrollList.java | 4 +- .../content/boiler/BoilerUpdateProtocol.java | 1 + .../common/tile/TileEntityBoilerCasing.java | 8 +- .../common/tile/TileEntityBoilerValve.java | 83 ++++++++-- .../assets/mekanism/gui/GuiBoilerStats.png | Bin 0 -> 3075 bytes .../assets/mekanism/gui/GuiDictionary.png | Bin 3365 -> 3394 bytes .../assets/mekanism/gui/elements/GuiGraph.png | Bin 0 -> 2331 bytes 9 files changed, 267 insertions(+), 20 deletions(-) create mode 100644 src/main/java/mekanism/client/gui/element/GuiGraph.java create mode 100644 src/main/resources/assets/mekanism/gui/GuiBoilerStats.png create mode 100644 src/main/resources/assets/mekanism/gui/elements/GuiGraph.png diff --git a/src/main/java/mekanism/client/gui/GuiBoilerStats.java b/src/main/java/mekanism/client/gui/GuiBoilerStats.java index 02fd50c80..fcb976f18 100644 --- a/src/main/java/mekanism/client/gui/GuiBoilerStats.java +++ b/src/main/java/mekanism/client/gui/GuiBoilerStats.java @@ -9,6 +9,8 @@ import mekanism.api.util.UnitDisplayUtils.TemperatureUnit; import mekanism.client.gui.element.GuiBoilerTab; import mekanism.client.gui.element.GuiBoilerTab.BoilerTab; import mekanism.client.gui.element.GuiElement.IInfoHandler; +import mekanism.client.gui.element.GuiGraph; +import mekanism.client.gui.element.GuiGraph.GraphDataHandler; import mekanism.client.gui.element.GuiHeatInfo; import mekanism.common.content.boiler.BoilerUpdateProtocol; import mekanism.common.content.boiler.SynchronizedBoilerData; @@ -28,12 +30,15 @@ import cpw.mods.fml.relauncher.SideOnly; public class GuiBoilerStats extends GuiMekanism { public TileEntityBoilerCasing tileEntity; + + public GuiGraph boilGraph; + public GuiGraph maxGraph; public GuiBoilerStats(InventoryPlayer inventory, TileEntityBoilerCasing tentity) { super(tentity, new ContainerNull(inventory.player, tentity)); tileEntity = tentity; - guiElements.add(new GuiBoilerTab(this, tileEntity, BoilerTab.MAIN, 6, MekanismUtils.getResource(ResourceType.GUI, "GuiNull.png"))); + guiElements.add(new GuiBoilerTab(this, tileEntity, BoilerTab.MAIN, 6, MekanismUtils.getResource(ResourceType.GUI, "GuiBoilerStats.png"))); guiElements.add(new GuiHeatInfo(new IInfoHandler() { @Override public List getInfo() @@ -41,7 +46,22 @@ public class GuiBoilerStats extends GuiMekanism String loss = UnitDisplayUtils.getDisplayShort(tileEntity.structure.lastEnvironmentLoss, TemperatureUnit.KELVIN); return ListUtils.asList(LangUtils.localize("gui.dissipated") + ": " + loss + "/t"); } - }, this, MekanismUtils.getResource(ResourceType.GUI, "GuiNull.png"))); + }, this, MekanismUtils.getResource(ResourceType.GUI, "GuiBoilerStats.png"))); + guiElements.add(boilGraph = new GuiGraph(this, MekanismUtils.getResource(ResourceType.GUI, "GuiBoilerStats.png"), 8, 83, 160, 36, new GraphDataHandler() { + @Override + public String getDataDisplay(int data) + { + return LangUtils.localize("gui.boilRate") + ": " + data + " mB/t"; + } + })); + guiElements.add(maxGraph = new GuiGraph(this, MekanismUtils.getResource(ResourceType.GUI, "GuiBoilerStats.png"), 8, 122, 160, 36, new GraphDataHandler() { + @Override + public String getDataDisplay(int data) + { + return LangUtils.localize("gui.maxBoil") + ": " + data + " mB/t"; + } + })); + maxGraph.enableFixedScale((int)((tentity.structure.superheatingElements*general.superheatingHeatTransfer)/SynchronizedBoilerData.getHeatEnthalpy())); } @Override @@ -54,8 +74,8 @@ public class GuiBoilerStats extends GuiMekanism fontRendererObj.drawString(stats, (xSize/2)-(fontRendererObj.getStringWidth(stats)/2), 6, 0x404040); - fontRendererObj.drawString(LangUtils.localize("gui.maxWater") + ": " + tileEntity.structure.waterVolume*BoilerUpdateProtocol.WATER_PER_TANK, 8, 26, 0x404040); - fontRendererObj.drawString(LangUtils.localize("gui.maxSteam") + ": " + tileEntity.structure.steamVolume*BoilerUpdateProtocol.STEAM_PER_TANK, 8, 35, 0x404040); + fontRendererObj.drawString(LangUtils.localize("gui.maxWater") + ": " + tileEntity.clientWaterCapacity + " mB", 8, 26, 0x404040); + fontRendererObj.drawString(LangUtils.localize("gui.maxSteam") + ": " + tileEntity.clientSteamCapacity + " mB", 8, 35, 0x404040); fontRendererObj.drawString(LangUtils.localize("gui.heatTransfer"), 8, 49, 0x797979); fontRendererObj.drawString(LangUtils.localize("gui.superheaters") + ": " + tileEntity.structure.superheatingElements, 14, 58, 0x404040); @@ -66,10 +86,19 @@ public class GuiBoilerStats extends GuiMekanism super.drawGuiContainerForegroundLayer(mouseX, mouseY); } + @Override + public void updateScreen() + { + super.updateScreen(); + + boilGraph.addData(tileEntity.structure.lastBoilRate); + maxGraph.addData(tileEntity.structure.lastMaxBoil); + } + @Override protected void drawGuiContainerBackgroundLayer(float partialTick, int mouseX, int mouseY) { - mc.renderEngine.bindTexture(MekanismUtils.getResource(ResourceType.GUI, "GuiNull.png")); + mc.renderEngine.bindTexture(MekanismUtils.getResource(ResourceType.GUI, "GuiBoilerStats.png")); GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); int guiWidth = (width - xSize) / 2; int guiHeight = (height - ySize) / 2; diff --git a/src/main/java/mekanism/client/gui/element/GuiGraph.java b/src/main/java/mekanism/client/gui/element/GuiGraph.java new file mode 100644 index 000000000..4fbd0f4b2 --- /dev/null +++ b/src/main/java/mekanism/client/gui/element/GuiGraph.java @@ -0,0 +1,152 @@ +package mekanism.client.gui.element; + +import java.util.ArrayList; +import java.util.List; + +import mekanism.client.gui.IGuiWrapper; +import mekanism.client.render.MekanismRenderer; +import mekanism.common.util.MekanismUtils; +import mekanism.common.util.MekanismUtils.ResourceType; +import net.minecraft.util.ResourceLocation; + +import org.lwjgl.opengl.GL11; + +import codechicken.lib.vec.Rectangle4i; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +@SideOnly(Side.CLIENT) +public class GuiGraph extends GuiElement +{ + public int xPosition; + public int yPosition; + + public int xSize; + public int ySize; + + public int currentScale = 10; + public boolean fixedScale = false; + + public List graphData = new ArrayList(); + + public GraphDataHandler dataHandler; + + public GuiGraph(IGuiWrapper gui, ResourceLocation def, int x, int y, int sizeX, int sizeY, GraphDataHandler handler) + { + super(MekanismUtils.getResource(ResourceType.GUI_ELEMENT, "GuiGraph.png"), gui, def); + + xPosition = x; + yPosition = y; + + xSize = sizeX; + ySize = sizeY; + + dataHandler = handler; + } + + public void enableFixedScale(int scale) + { + fixedScale = true; + currentScale = scale; + } + + public void addData(int data) + { + if(graphData.size() == xSize) + { + graphData.remove(0); + } + + graphData.add(data); + + if(!fixedScale) + { + for(int i : graphData) + { + if(i > currentScale) + { + currentScale = i; + } + } + } + } + + @Override + public Rectangle4i getBounds(int guiWidth, int guiHeight) + { + return new Rectangle4i(guiWidth + xPosition, guiHeight + yPosition, xSize, ySize); + } + + @Override + public void renderBackground(int xAxis, int yAxis, int guiWidth, int guiHeight) + { + mc.renderEngine.bindTexture(RESOURCE); + + drawBlack(guiWidth, guiHeight); + drawGraph(guiWidth, guiHeight); + + mc.renderEngine.bindTexture(defaultLocation); + } + + @Override + public void renderForeground(int xAxis, int yAxis) + { + if(xAxis >= xPosition && xAxis <= xPosition+xSize && yAxis >= yPosition && yAxis <= yPosition+ySize) + { + int height = ySize-(yAxis-yPosition); + int scaled = (int)(((double)height/(double)ySize)*currentScale); + + displayTooltip(dataHandler.getDataDisplay(scaled), xAxis, yAxis); + } + } + + @Override + public void preMouseClicked(int xAxis, int yAxis, int button) {} + + @Override + public void mouseClicked(int xAxis, int yAxis, int button) {} + + public void drawBlack(int guiWidth, int guiHeight) + { + int xDisplays = xSize/10 + (xSize%10 > 0 ? 1 : 0); + int yDisplays = ySize/10 + (ySize%10 > 0 ? 1 : 0); + + for(int yIter = 0; yIter < yDisplays; yIter++) + { + for(int xIter = 0; xIter < xDisplays; xIter++) + { + int width = (xSize%10 > 0 && xIter == xDisplays-1 ? xSize%10 : 10); + int height = (ySize%10 > 0 && yIter == yDisplays-1 ? ySize%10 : 10); + + guiObj.drawTexturedRect(guiWidth + xPosition + (xIter*10), guiHeight + yPosition + (yIter*10), 0, 0, width, height); + } + } + } + + public void drawGraph(int guiWidth, int guiHeight) + { + for(int i = 0; i < graphData.size(); i++) + { + int data = Math.min(currentScale, graphData.get(i)); + int relativeHeight = (int)(((double)data/(double)currentScale)*ySize); + + guiObj.drawTexturedRect(guiWidth + xPosition + i, guiHeight + yPosition + (ySize-relativeHeight), 10, 0, 1, 1); + + int displays = (relativeHeight-1)/10 + ((relativeHeight-1)%10 > 0 ? 1 : 0); + + for(int iter = 0; iter < displays; iter++) + { + MekanismRenderer.blendOn(); + GL11.glColor4f(1.0F, 1.0F, 1.0F, 0.2F + (0.8F*((float)i/(float)graphData.size()))); + int height = ((relativeHeight-1)%10 > 0 && iter == displays-1 ? (relativeHeight-1)%10 : 10); + guiObj.drawTexturedRect(guiWidth + xPosition + i, guiHeight + yPosition + (ySize-(iter*10)) - 10 + (10-height), 11, 0, 1, height); + MekanismRenderer.blendOff(); + } + } + } + + public static interface GraphDataHandler + { + public String getDataDisplay(int data); + } +} diff --git a/src/main/java/mekanism/client/gui/element/GuiScrollList.java b/src/main/java/mekanism/client/gui/element/GuiScrollList.java index 647f85b7f..5c9f0a421 100644 --- a/src/main/java/mekanism/client/gui/element/GuiScrollList.java +++ b/src/main/java/mekanism/client/gui/element/GuiScrollList.java @@ -100,7 +100,7 @@ public class GuiScrollList extends GuiElement { for(int xIter = 0; xIter < xDisplays; xIter++) { - int width = (xSize%10 > 0 && xIter == xDisplays ? xSize%10 : 10); + int width = (xSize%10 > 0 && xIter == xDisplays-1 ? xSize%10 : 10); guiObj.drawTexturedRect(guiWidth + xPosition + (xIter*10), guiHeight + yPosition + (yIter*10), 0, 0, width, 10); } } @@ -116,7 +116,7 @@ public class GuiScrollList extends GuiElement for(int xIter = 0; xIter < xDisplays; xIter++) { - int width = (xSize%10 > 0 && xIter == xDisplays ? xSize%10 : 10); + int width = (xSize%10 > 0 && xIter == xDisplays-1 ? xSize%10 : 10); guiObj.drawTexturedRect(guiWidth + xPosition + (xIter*10), guiHeight + yPosition + (index-scroll)*10, 0, 10, width, 10); } } diff --git a/src/main/java/mekanism/common/content/boiler/BoilerUpdateProtocol.java b/src/main/java/mekanism/common/content/boiler/BoilerUpdateProtocol.java index 4c6fcaacf..a8cc2c4af 100644 --- a/src/main/java/mekanism/common/content/boiler/BoilerUpdateProtocol.java +++ b/src/main/java/mekanism/common/content/boiler/BoilerUpdateProtocol.java @@ -143,6 +143,7 @@ public class BoilerUpdateProtocol extends UpdateProtocol return false; } + //Gradle build requires these fields to be final final Coord4D renderLocation = structure.renderLocation.clone(); final int volLength = structure.volLength; final int volWidth = structure.volWidth; diff --git a/src/main/java/mekanism/common/tile/TileEntityBoilerCasing.java b/src/main/java/mekanism/common/tile/TileEntityBoilerCasing.java index e8a6f1ec9..4ef947cfd 100644 --- a/src/main/java/mekanism/common/tile/TileEntityBoilerCasing.java +++ b/src/main/java/mekanism/common/tile/TileEntityBoilerCasing.java @@ -235,10 +235,10 @@ public class TileEntityBoilerCasing extends TileEntityMultiblock toSend = new HashSet(); for(ValveData valveData : structure.valves) @@ -293,11 +293,11 @@ public class TileEntityBoilerCasing extends TileEntityMultiblock= structure.upperRenderLocation.yCoord) + { + if(structure.steamStored != null && structure.steamStored.amount > 0) + { + for(ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) + { + TileEntity tile = Coord4D.get(this).getFromSide(side).getTileEntity(worldObj); + + if(tile instanceof IFluidHandler && !(tile instanceof TileEntityBoilerValve)) + { + if(((IFluidHandler)tile).canFill(side.getOpposite(), structure.steamStored.getFluid())) + { + structure.steamStored.amount -= ((IFluidHandler)tile).fill(side.getOpposite(), structure.steamStored, true); + + if(structure.steamStored.amount <= 0) + { + structure.steamStored = null; + } + } + } + } + } + } + } + } @Override public FluidTankInfo[] getTankInfo(ForgeDirection from) { - return ((!worldObj.isRemote && structure != null) || (worldObj.isRemote && clientHasStructure)) ? new FluidTankInfo[] {waterTank.getInfo(), steamTank.getInfo()} : PipeUtils.EMPTY; + if((!worldObj.isRemote && structure != null) || (worldObj.isRemote && clientHasStructure)) + { + if(structure.upperRenderLocation != null && yCoord >= structure.upperRenderLocation.yCoord) + { + return new FluidTankInfo[] {steamTank.getInfo()}; + } + else { + return new FluidTankInfo[] {waterTank.getInfo()}; + } + } + + return PipeUtils.EMPTY; } @Override public int fill(ForgeDirection from, FluidStack resource, boolean doFill) { - return waterTank.fill(resource, doFill); + if(structure != null && structure.upperRenderLocation != null && yCoord < structure.upperRenderLocation.yCoord) + { + return waterTank.fill(resource, doFill); + } + + return 0; } @Override public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain) { - if(structure != null && structure.steamStored != null) + if(structure != null && structure.upperRenderLocation != null && yCoord >= structure.upperRenderLocation.yCoord) { - if(resource.getFluid() == structure.steamStored.getFluid()) + if(structure.steamStored != null) { - return steamTank.drain(resource.amount, doDrain); + if(resource.getFluid() == structure.steamStored.getFluid()) + { + return steamTank.drain(resource.amount, doDrain); + } } } @@ -51,7 +106,7 @@ public class TileEntityBoilerValve extends TileEntityBoilerCasing implements IFl @Override public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) { - if(structure != null) + if(structure != null && structure.upperRenderLocation != null && yCoord >= structure.upperRenderLocation.yCoord) { return steamTank.drain(maxDrain, doDrain); } @@ -62,12 +117,22 @@ public class TileEntityBoilerValve extends TileEntityBoilerCasing implements IFl @Override public boolean canFill(ForgeDirection from, Fluid fluid) { - return ((!worldObj.isRemote && structure != null) || (worldObj.isRemote && clientHasStructure)); + if((!worldObj.isRemote && structure != null) || (worldObj.isRemote && clientHasStructure)) + { + return structure.upperRenderLocation != null && yCoord < structure.upperRenderLocation.yCoord; + } + + return false; } @Override public boolean canDrain(ForgeDirection from, Fluid fluid) { - return ((!worldObj.isRemote && structure != null) || (worldObj.isRemote && clientHasStructure)); + if((!worldObj.isRemote && structure != null) || (worldObj.isRemote && clientHasStructure)) + { + return structure.upperRenderLocation != null && yCoord >= structure.upperRenderLocation.yCoord; + } + + return false; } } diff --git a/src/main/resources/assets/mekanism/gui/GuiBoilerStats.png b/src/main/resources/assets/mekanism/gui/GuiBoilerStats.png new file mode 100644 index 0000000000000000000000000000000000000000..71f0b307b26af82972f9f317997a8d94a6598faf GIT binary patch literal 3075 zcmeH}*H=>s5XSGlCRAyLE=`f5G(iLuBvBAWT4>S*r3q^&!KFw`77>spqM?(ps~|qtmw!IRYi|82br2^5ejwYOf>UW`W z<9e;fd`e?O3aZBSKN8UN)Y9cV!&7+ytu<4=D>2L>Msf5?i$4QSZ>ex5WQl^}`7bmi zbmqd6GLz4#J-C}hlHe+FvXxcyD7S?4Z1^J@+@?)lM|*zycalwf-ee{#rVuKBqwdQy z{^U$>wal?E9K5rWC68QkmD{{QZ_-9}Y29g_^&WW>W*nCu;P+X5ZZH|{XdjrIBb@oZ z`-j;-xGOjFQsomcQ1EWnt`#*J%q&r}O)wqfB>qUPWErjKvbq zd|Qm6Gw%{KxOboCJW3GjN=S|`F+0CWn`75ZToFDX6)3%69#KKv`tI58PjN4THdzprb@&RV-oc$@$qDVI$pSH?#ZNf zJ}c(~B0j1pu4(bno8<|DTsor9MWyb0miS2=rcsR6&(`PlcamQ}V!wUsnXuhVtv}(D zWc-JCt@Lh2mH43VT4kcUHv$=_t`8xVr4$Z*N*K7NW4@UcsskR4x^HB)nJrU`@L}wX zUb%JgnvwqS-mA1zcBKUuC(qQkk-YX#ov?JbAE{CoY`mw~cboaa#ddUbSPXe|T=r_Pl>zxYBJG%oPue3r zhplEOX35dVHVbwE!uE#ti1M1D^Fm2=rQswD#M+hpw>+rUZs{NIsaVKm@NCesK)+ao z#Xs3Mq+jZtAmlI6lb=c6duy3-(>`eo<9Zm*nA*tPD9~vWLbz#ODr6m`kdbR&S(3N4p@Z0G1poiy0;b`qi7esj1Q69q`>EWxX zDK@%XxoMclFq{1!^~}y!VdIs*Z++Y9WidXQ&XmK$ZDQNZa#-+f_S#4K*o%Di>hZnZ z+P&`$1(w?FtgTF^)qZ3@9Zt6M8gJ|y-#)yIBzd}SWI~bA(JUdYWhI`NV#-?N?)Dsw zxxHQ)&ufYHWW&+&w$?< za&rb@ghOb+qB}qe@`m`l-uDGS7QCvsr*riO@!BB#MHEV?P6%?p0 zR_4o-##yedRmQ8XL;`+t8(Lc#j4f95rI=y>UkY)e3^CC4=xg8=jx?R|0}HLoE?s*g z1rbloX#F`b-|hnBG)*>sV@^$~A(|CuE`2aWWfM1vxNMx9$_Ez|c-wkllGl@v^MezV6|N0_>+(9N^+Z(<-69uQzmR7rjFXdMh{o#H$jW!xdl-+f0tyF!(68p_2!Vru5T5IFEN|*c3Fo;7 N%r9D-zPRA^$A9Gss8|31 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/mekanism/gui/GuiDictionary.png b/src/main/resources/assets/mekanism/gui/GuiDictionary.png index 05fdc0e539735c0f3fd39a9f1913ee6c5ca18d9b..5c8d64c25e2148e8d32b0d4d87d90bf755c361f0 100644 GIT binary patch delta 1067 zcmV+`1l0Sb8p0ZoBYy-9X+uL$Nkc;*P;zf(X>4Tx062|}Rb6NtRTMtEb7vzY&QokO zg>Hg1+lHrgWSWcKdPn90sKGrRqvPeo9CG3uKX#J{(IASm?@ z+di}}l?o-=)F3E6wD^Ni=!>T7nL9I?X}YoAW$t|Qo$sD|?ti&w?*-_&s#unh6af~R zt}Pcb;&X?Oh&?NigomIP2BB9`9V=a_OaeAf3wO0!-$TNCU)j~&{-3S4MjaI(aUWu{ z=BNvZj{)$fRm*k(dis$cKk8Z@_G0L_F+jvGdbr_Z*TZu@evN5nWtO z;Zej(s*;~Z{0QP}ZGE;J;MNT3ndwE3s`n-8a z_I+}nIqm6u=<|e@EeHIimz0AQ#Dj=`p+-UW=i>gc+)5Aw8EP8kNq;VqqYhgy<6Uj0 z=+8?G7dO-&OBU<;fl{FVM6-)>fUj8wt5J-NPueZH>g)MY#m*OepL~TjtAT&M4YLUa zD3~yZy?+W#SOXDcC_o0^7T9R1gAN8V6s;5)ieI5-7aQlmJn}lUna#nz!j%5V$X|o` zxX!dHWQRV27P1=rj;t2bW$~+pTw@bIek?ZvKPDL<64`^#UNTAck#RBsB6*5DP4<%< zvJ+(Q`q)ZrMP58N*8RMUGg79TMcp~HyP#nIGk+>fTvOMqEDpAYBg-lK1zo-T#$T~q z=`1%wHmU-|3&GWIL{YNX(Qxa>rWCyRuBf>}*(bcU2l~2ICg+(V4}G z#U1l;@#I$zMt+vbndh(cT|8NDE)GVlmj(K2`BoWDjYO>UgY<{AEWIavDE-F0&3(#! z&3}E)eZgG6#@QDHLj zCkzNR&Px>zCja= zBtvA3lr~iNxL5O`B9%|&QfUxVJ5v*>v47M-4~Mg+cA#wn`}`f%scy1T>e6H0eF9n2 zI&SL?%@ub`(vxBuuQn={n(F9?s2GOGOpa(%huUpg8wKy)^pEtLGP@5GTP{bO`wYOo zKk@AQF5-@~0G1qpfyX0m7|+TF-UT@Ggxa#(!5xuEd<)>z_w4q+`Z9Qa{nY8)#2<64 l=PiJ>H#?ob-|uwRK0yDg0B4PV0id6JRZw95Z?hc)2njB(8i4=+ delta 1038 zcmV+p1o8XA8l@VLBYy+%X+uL$Nkc;*P;zf(X>4Tx062|}Ro!pfR1`mnZ(O7nKcKOW z4i$^9Ra0BJ8yc;~21%2p=|UR0&DbiW$#rfTQ`a`O(`{9s_5yDV_yd5l2Of}kLK+Oj z_Ok5(v`JGz71bo9J#^YYXp{DWs&KBaQ@dTpxRI}aIp=pi?|;!XK*v{_pO}_ARv`(`K_~P;r>1*Ox?C;-F2;pN*27;R!QM9q+Ux&wbylgT10KeMtdQo=mnqksdx=&F5&oys0TJd`E>GI|#kK((J)n0eU)DVBJ zYq?3pFC)I@_!%aD74f~sTqTWoFF^8{ntPr?L_-if$s_=TxZzG%&qCb(^K zdCoqnhMa4x{ z6hi)zV+ON`xsmg3L#>3I8=9NTb3f!hwJM>{)UK+QWxX9ld>D=;G@xL^4DLEuumLit zkcSMu9e;39Qv(A`lu*=Clo*MpVGd>OdF6n^am1Jntk;<}MrqIC5$=Q>n{*R}?8oOI zDUw5En2dl--Xw34!z7E+5pr%d2c?H4INKjdmEV*< zl@;X+<-BrtTbJ8*N%&OwR`^l)PWWE<8D!y-a9Q|CxFUQbT#TL7ym&1JoWQ-+)%LMCuYy_wP6ZWs zL5D3kvu*xEYtl=GNMYO54zpQqF~pph71JP#d&LoPNE~Olm7ll=btAavwoIM=mAd9q7A z>MqdgAh7QszoH+g!S^k(^Lixn-v&7J7v5PnBH45U;A;<{`?W~chj-$$p8;Grpf}uw z@Xk*pegW`m`}gsGT^YQaZZ(?^@V@H!1YqOiX7iurW^?09^uGph$@~{t0C9K{wF2RW IvpNI_3H*c$FaQ7m diff --git a/src/main/resources/assets/mekanism/gui/elements/GuiGraph.png b/src/main/resources/assets/mekanism/gui/elements/GuiGraph.png new file mode 100644 index 0000000000000000000000000000000000000000..0a87e28b352cc7d11b182fcef777a6cd969a8a09 GIT binary patch literal 2331 zcmeH}`#aMM0LH%?n@fgV=8{EpQEoLgLPkd9Zbojo=9W>@P0XcX6iKu~+MLr7GdWlh z84Hz!r${2#(#ERAoRw{q|Ka@Vr}y*o`@HY_y!l=p$6)f>@&Ew9T%0jJ007!R5FiWP zkYGYhGyq7$;v5{jTpS$qya-9raS5jYz_PFq7ZR(3Q?qSPjxpFdh)p<{bFKyr+XXA} zJ6OeR%b1)*B~n~a~)2$k18T`}L2m?nvikqXfotCV4{^oL5-(SRK8j z_b&TFPs^deuKc#3@}(C9F&=wwnKQq5sJuTl1tSqXO>q_y3Dm>i7SgzaY>J7D zCL|tgUmjK;H$Yqt_m6!Bf73|o+!(Q z_8ZfDjgZ+80Il;bDD)gRd9uh`_3jX}h~b_6_7?MYg>HZ_<`rXTXO~ zE!E`&N2;RJjV-|F-CBAoA4o$dkuJjGvq+GB%2gY8VTn$YY7}2Ic09rHq>aVs+S3Aa zpXv(7$-~TcTG(&%eQv?n_Y7mj$GHamd&Q8D4$1S-#^42G3-8BsT9s}7gR7ydJPA^0 zB#FO2lkwSqsfF+&@O68WTld$56Ui5G+IZ+E_>VVbz4^Te!P%wH{z^{il)f@f!%B!v zK$5AV6XP~S6u;`H#O z1?&uLlFpUW%nX;ok?r)u02Pw}u(YhQo?RvY+JsFLHj}W~g8$P3iTu-*XxKyNnS)sy Prw4Fx^uRnk8g}ImZ0yEQ literal 0 HcmV?d00001