From bb0ad74295b674d3bdac0757f3f5f1f56ddfd63f Mon Sep 17 00:00:00 2001 From: "Aidan C. Brady" Date: Sun, 9 Mar 2014 18:23:06 -0400 Subject: [PATCH] Work on sorter material filters --- .../client/gui/GuiLogisticalSorter.java | 25 +- .../client/gui/GuiMMaterialFilter.java | 2 +- .../mekanism/client/gui/GuiTFilterSelect.java | 114 +++++++++ .../client/gui/GuiTMaterialFilter.java | 225 ++++++++++++++++++ .../common/transporter/TMaterialFilter.java | 97 ++++++++ .../common/transporter/TransporterFilter.java | 11 +- .../mekanism/gui/GuiLogisticalSorter.png | Bin 5086 -> 5288 bytes ...terialFilter.png => GuiMaterialFilter.png} | Bin resources/assets/mekanism/lang/en_US.lang | 1 + 9 files changed, 468 insertions(+), 7 deletions(-) create mode 100644 common/mekanism/client/gui/GuiTFilterSelect.java create mode 100644 common/mekanism/client/gui/GuiTMaterialFilter.java create mode 100644 common/mekanism/common/transporter/TMaterialFilter.java rename resources/assets/mekanism/gui/{GuiMMaterialFilter.png => GuiMaterialFilter.png} (100%) diff --git a/common/mekanism/client/gui/GuiLogisticalSorter.java b/common/mekanism/client/gui/GuiLogisticalSorter.java index e59388222..97bc473dc 100644 --- a/common/mekanism/client/gui/GuiLogisticalSorter.java +++ b/common/mekanism/client/gui/GuiLogisticalSorter.java @@ -17,6 +17,7 @@ import mekanism.common.network.PacketLogisticalSorterGui.SorterGuiPacket; import mekanism.common.network.PacketTileEntity; import mekanism.common.tile.TileEntityLogisticalSorter; import mekanism.common.transporter.TItemStackFilter; +import mekanism.common.transporter.TMaterialFilter; import mekanism.common.transporter.TOreDictFilter; import mekanism.common.transporter.TransporterFilter; import mekanism.common.util.MekanismUtils; @@ -243,8 +244,7 @@ public class GuiLogisticalSorter extends GuiMekanism int guiHeight = (height - ySize) / 2; buttonList.clear(); - buttonList.add(new GuiButton(0, guiWidth + 56, guiHeight + 136, 54, 20, MekanismUtils.localize("gui.itemstack"))); - buttonList.add(new GuiButton(1, guiWidth + 110, guiHeight + 136, 43, 20, MekanismUtils.localize("gui.oredict"))); + buttonList.add(new GuiButton(0, guiWidth + 56, guiHeight + 136, 96, 20, MekanismUtils.localize("gui.newFilter"))); } @Override @@ -271,9 +271,9 @@ public class GuiLogisticalSorter extends GuiMekanism fontRenderer.drawString(tileEntity.getInvName(), 43, 6, 0x404040); fontRenderer.drawString(MekanismUtils.localize("gui.filters") + ":", 11, 19, 0x00CD00); - fontRenderer.drawString("T: " + tileEntity.filters.size(), 11, 28, 0x00CD00); - fontRenderer.drawString("IS: " + getItemStackFilters().size(), 11, 37, 0x00CD00); - fontRenderer.drawString("OD: " + getOreDictFilters().size(), 11, 46, 0x00CD00); + fontRenderer.drawString("IS: " + getItemStackFilters(), 11, 28, 0x00CD00); + fontRenderer.drawString("OD: " + getOreDictFilters().size(), 11, 37, 0x00CD00); + fontRenderer.drawString("M: " + getMaterialFilters().size(), 11, 46, 0x00CD00); fontRenderer.drawString("RR:", 12, 74, 0x00CD00); fontRenderer.drawString(MekanismUtils.localize("gui." + (tileEntity.roundRobin ? "on" : "off")), 27, 86, 0x00CD00); @@ -452,6 +452,21 @@ public class GuiLogisticalSorter extends GuiMekanism return list; } + + public ArrayList getMaterialFilters() + { + ArrayList list = new ArrayList(); + + for(TransporterFilter filter : tileEntity.filters) + { + if(filter instanceof TMaterialFilter) + { + list.add(filter); + } + } + + return list; + } private void updateStackList(TOreDictFilter filter) { diff --git a/common/mekanism/client/gui/GuiMMaterialFilter.java b/common/mekanism/client/gui/GuiMMaterialFilter.java index e83c299b9..e172223a4 100644 --- a/common/mekanism/client/gui/GuiMMaterialFilter.java +++ b/common/mekanism/client/gui/GuiMMaterialFilter.java @@ -149,7 +149,7 @@ public class GuiMMaterialFilter extends GuiMekanism { super.drawGuiContainerBackgroundLayer(partialTick, mouseX, mouseY); - mc.renderEngine.bindTexture(MekanismUtils.getResource(ResourceType.GUI, "GuiMMaterialFilter.png")); + mc.renderEngine.bindTexture(MekanismUtils.getResource(ResourceType.GUI, "GuiMaterialFilter.png")); GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); int guiWidth = (width - xSize) / 2; int guiHeight = (height - ySize) / 2; diff --git a/common/mekanism/client/gui/GuiTFilterSelect.java b/common/mekanism/client/gui/GuiTFilterSelect.java new file mode 100644 index 000000000..d8fdf87cc --- /dev/null +++ b/common/mekanism/client/gui/GuiTFilterSelect.java @@ -0,0 +1,114 @@ +package mekanism.client.gui; + +import mekanism.api.Coord4D; +import mekanism.common.PacketHandler; +import mekanism.common.PacketHandler.Transmission; +import mekanism.common.inventory.container.ContainerNull; +import mekanism.common.network.PacketDigitalMinerGui; +import mekanism.common.network.PacketDigitalMinerGui.MinerGuiPacket; +import mekanism.common.network.PacketLogisticalSorterGui; +import mekanism.common.network.PacketLogisticalSorterGui.SorterGuiPacket; +import mekanism.common.tile.TileEntityLogisticalSorter; +import mekanism.common.util.MekanismUtils; +import mekanism.common.util.MekanismUtils.ResourceType; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.entity.player.EntityPlayer; + +import org.lwjgl.opengl.GL11; + +public class GuiTFilterSelect extends GuiMekanism +{ + public TileEntityLogisticalSorter tileEntity; + + public GuiTFilterSelect(EntityPlayer player, TileEntityLogisticalSorter tentity) + { + super(new ContainerNull(player, tentity)); + + tileEntity = tentity; + } + + @Override + public void initGui() + { + super.initGui(); + + int guiWidth = (width - xSize) / 2; + int guiHeight = (height - ySize) / 2; + + buttonList.clear(); + buttonList.add(new GuiButton(0, guiWidth + 24, guiHeight + 32, 128, 20, MekanismUtils.localize("gui.itemstack"))); + buttonList.add(new GuiButton(1, guiWidth + 24, guiHeight + 52, 128, 20, MekanismUtils.localize("gui.oredict"))); + buttonList.add(new GuiButton(2, guiWidth + 24, guiHeight + 72, 128, 20, MekanismUtils.localize("gui.material"))); + } + + @Override + protected void actionPerformed(GuiButton guibutton) + { + super.actionPerformed(guibutton); + + if(guibutton.id == 0) + { + PacketHandler.sendPacket(Transmission.SERVER, new PacketLogisticalSorterGui().setParams(SorterGuiPacket.SERVER, Coord4D.get(tileEntity), 1)); + } + else if(guibutton.id == 1) + { + PacketHandler.sendPacket(Transmission.SERVER, new PacketLogisticalSorterGui().setParams(SorterGuiPacket.SERVER, Coord4D.get(tileEntity), 2)); + } + else if(guibutton.id == 2) + { + PacketHandler.sendPacket(Transmission.SERVER, new PacketLogisticalSorterGui().setParams(SorterGuiPacket.SERVER, Coord4D.get(tileEntity), 3)); + } + } + + @Override + protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) + { + int xAxis = (mouseX - (width - xSize) / 2); + int yAxis = (mouseY - (height - ySize) / 2); + + fontRenderer.drawString(MekanismUtils.localize("gui.filterSelect.title"), 43, 6, 0x404040); + + super.drawGuiContainerForegroundLayer(mouseX, mouseY); + } + + @Override + protected void drawGuiContainerBackgroundLayer(float partialTick, int mouseX, int mouseY) + { + super.drawGuiContainerBackgroundLayer(partialTick, mouseX, mouseY); + + mc.renderEngine.bindTexture(MekanismUtils.getResource(ResourceType.GUI, "GuiFilterSelect.png")); + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + int guiWidth = (width - xSize) / 2; + int guiHeight = (height - ySize) / 2; + drawTexturedModalRect(guiWidth, guiHeight, 0, 0, xSize, ySize); + + int xAxis = (mouseX - (width - xSize) / 2); + int yAxis = (mouseY - (height - ySize) / 2); + + if(xAxis >= 5 && xAxis <= 16 && yAxis >= 5 && yAxis <= 16) + { + drawTexturedModalRect(guiWidth + 5, guiHeight + 5, 176, 0, 11, 11); + } + else { + drawTexturedModalRect(guiWidth + 5, guiHeight + 5, 176, 11, 11, 11); + } + } + + @Override + public void mouseClicked(int mouseX, int mouseY, int button) + { + super.mouseClicked(mouseX, mouseY, button); + + if(button == 0) + { + int xAxis = (mouseX - (width - xSize) / 2); + int yAxis = (mouseY - (height - ySize) / 2); + + if(xAxis >= 5 && xAxis <= 16 && yAxis >= 5 && yAxis <= 16) + { + mc.sndManager.playSoundFX("random.click", 1.0F, 1.0F); + PacketHandler.sendPacket(Transmission.SERVER, new PacketDigitalMinerGui().setParams(MinerGuiPacket.SERVER, Coord4D.get(tileEntity), 0)); + } + } + } +} diff --git a/common/mekanism/client/gui/GuiTMaterialFilter.java b/common/mekanism/client/gui/GuiTMaterialFilter.java new file mode 100644 index 000000000..9fa768c98 --- /dev/null +++ b/common/mekanism/client/gui/GuiTMaterialFilter.java @@ -0,0 +1,225 @@ +package mekanism.client.gui; + +import mekanism.api.Coord4D; +import mekanism.api.EnumColor; +import mekanism.common.PacketHandler; +import mekanism.common.PacketHandler.Transmission; +import mekanism.common.inventory.container.ContainerFilter; +import mekanism.common.network.PacketEditFilter; +import mekanism.common.network.PacketLogisticalSorterGui; +import mekanism.common.network.PacketLogisticalSorterGui.SorterGuiPacket; +import mekanism.common.network.PacketNewFilter; +import mekanism.common.tile.TileEntityLogisticalSorter; +import mekanism.common.transporter.TMaterialFilter; +import mekanism.common.util.MekanismUtils; +import mekanism.common.util.MekanismUtils.ResourceType; +import net.minecraft.block.Block; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; + +import org.lwjgl.input.Keyboard; +import org.lwjgl.opengl.GL11; + +public class GuiTMaterialFilter extends GuiMekanism +{ + public TileEntityLogisticalSorter tileEntity; + + public boolean isNew = false; + + public TMaterialFilter origFilter; + + public TMaterialFilter filter = new TMaterialFilter(); + + public String status = EnumColor.DARK_GREEN + MekanismUtils.localize("gui.allOK"); + + public int ticker; + + public GuiTMaterialFilter(EntityPlayer player, TileEntityLogisticalSorter tentity, int index) + { + super(new ContainerFilter(player.inventory, tentity)); + tileEntity = tentity; + + origFilter = (TMaterialFilter)tileEntity.filters.get(index); + filter = ((TMaterialFilter)tileEntity.filters.get(index)).clone(); + } + + public GuiTMaterialFilter(EntityPlayer player, TileEntityLogisticalSorter tentity) + { + super(new ContainerFilter(player.inventory, tentity)); + tileEntity = tentity; + + isNew = true; + } + + @Override + public void initGui() + { + super.initGui(); + + int guiWidth = (width - xSize) / 2; + int guiHeight = (height - ySize) / 2; + + buttonList.clear(); + buttonList.add(new GuiButton(0, guiWidth + 27, guiHeight + 62, 60, 20, MekanismUtils.localize("gui.save"))); + buttonList.add(new GuiButton(1, guiWidth + 89, guiHeight + 62, 60, 20, MekanismUtils.localize("gui.delete"))); + + if(isNew) + { + ((GuiButton)buttonList.get(1)).enabled = false; + } + } + + @Override + protected void actionPerformed(GuiButton guibutton) + { + super.actionPerformed(guibutton); + + if(guibutton.id == 0) + { + if(filter.materialItem != null) + { + if(isNew) + { + PacketHandler.sendPacket(Transmission.SERVER, new PacketNewFilter().setParams(Coord4D.get(tileEntity), filter)); + } + else { + PacketHandler.sendPacket(Transmission.SERVER, new PacketEditFilter().setParams(Coord4D.get(tileEntity), false, origFilter, filter)); + } + + PacketHandler.sendPacket(Transmission.SERVER, new PacketLogisticalSorterGui().setParams(SorterGuiPacket.SERVER, Coord4D.get(tileEntity), 0)); + } + else if(filter.materialItem == null) + { + status = EnumColor.DARK_RED + MekanismUtils.localize("gui.itemFilter.noItem"); + ticker = 20; + } + } + else if(guibutton.id == 1) + { + PacketHandler.sendPacket(Transmission.SERVER, new PacketEditFilter().setParams(Coord4D.get(tileEntity), true, origFilter)); + PacketHandler.sendPacket(Transmission.SERVER, new PacketLogisticalSorterGui().setParams(SorterGuiPacket.SERVER, Coord4D.get(tileEntity), 0)); + } + } + + @Override + protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) + { + int xAxis = (mouseX - (width - xSize) / 2); + int yAxis = (mouseY - (height - ySize) / 2); + + fontRenderer.drawString((isNew ? MekanismUtils.localize("gui.new") : MekanismUtils.localize("gui.edit")) + " " + MekanismUtils.localize("gui.materialFilter"), 43, 6, 0x404040); + fontRenderer.drawString(MekanismUtils.localize("gui.status") + ": " + status, 35, 20, 0x00CD00); + fontRenderer.drawString(MekanismUtils.localize("gui.materialFilter.details") + ":", 35, 32, 0x00CD00); + + if(filter.materialItem != null) + { + fontRenderer.drawString(filter.materialItem.getDisplayName(), 35, 41, 0x00CD00); + } + + if(filter.materialItem != null) + { + GL11.glPushMatrix(); + GL11.glEnable(GL11.GL_LIGHTING); + itemRenderer.renderItemAndEffectIntoGUI(fontRenderer, mc.getTextureManager(), filter.materialItem, 12, 19); + GL11.glDisable(GL11.GL_LIGHTING); + GL11.glPopMatrix(); + } + + super.drawGuiContainerForegroundLayer(mouseX, mouseY); + } + + @Override + public void updateScreen() + { + super.updateScreen(); + + if(ticker > 0) + { + ticker--; + } + else { + status = EnumColor.DARK_GREEN + MekanismUtils.localize("gui.allOK"); + } + } + + @Override + protected void drawGuiContainerBackgroundLayer(float partialTick, int mouseX, int mouseY) + { + super.drawGuiContainerBackgroundLayer(partialTick, mouseX, mouseY); + + mc.renderEngine.bindTexture(MekanismUtils.getResource(ResourceType.GUI, "GuiMaterialFilter.png")); + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + int guiWidth = (width - xSize) / 2; + int guiHeight = (height - ySize) / 2; + drawTexturedModalRect(guiWidth, guiHeight, 0, 0, xSize, ySize); + + int xAxis = (mouseX - (width - xSize) / 2); + int yAxis = (mouseY - (height - ySize) / 2); + + if(xAxis >= 5 && xAxis <= 16 && yAxis >= 5 && yAxis <= 16) + { + drawTexturedModalRect(guiWidth + 5, guiHeight + 5, 176, 0, 11, 11); + } + else { + drawTexturedModalRect(guiWidth + 5, guiHeight + 5, 176, 11, 11, 11); + } + + if(xAxis >= 12 && xAxis <= 28 && yAxis >= 19 && yAxis <= 35) + { + GL11.glPushMatrix(); + GL11.glDisable(GL11.GL_LIGHTING); + GL11.glDisable(GL11.GL_DEPTH_TEST); + + int x = guiWidth + 12; + int y = guiHeight + 19; + drawGradientRect(x, y, x + 16, y + 16, -2130706433, -2130706433); + + GL11.glEnable(GL11.GL_LIGHTING); + GL11.glEnable(GL11.GL_DEPTH_TEST); + GL11.glPopMatrix(); + } + } + + @Override + protected void mouseClicked(int mouseX, int mouseY, int button) + { + super.mouseClicked(mouseX, mouseY, button); + + if(button == 0) + { + int xAxis = (mouseX - (width - xSize) / 2); + int yAxis = (mouseY - (height - ySize) / 2); + + if(xAxis >= 5 && xAxis <= 16 && yAxis >= 5 && yAxis <= 16) + { + mc.sndManager.playSoundFX("random.click", 1.0F, 1.0F); + PacketHandler.sendPacket(Transmission.SERVER, new PacketLogisticalSorterGui().setParams(SorterGuiPacket.SERVER, Coord4D.get(tileEntity), isNew ? 5 : 0)); + } + + if(xAxis >= 12 && xAxis <= 28 && yAxis >= 19 && yAxis <= 35) + { + ItemStack stack = mc.thePlayer.inventory.getItemStack(); + + if(stack != null && !Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) + { + if(stack.getItem() instanceof ItemBlock) + { + if(stack.itemID != Block.bedrock.blockID) + { + filter.materialItem = stack.copy(); + filter.materialItem.stackSize = 1; + } + } + } + else if(stack == null && Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) + { + filter.materialItem = null; + } + + mc.sndManager.playSoundFX("random.click", 1.0F, 1.0F); + } + } + } +} diff --git a/common/mekanism/common/transporter/TMaterialFilter.java b/common/mekanism/common/transporter/TMaterialFilter.java new file mode 100644 index 000000000..2fa13cd6d --- /dev/null +++ b/common/mekanism/common/transporter/TMaterialFilter.java @@ -0,0 +1,97 @@ +package mekanism.common.transporter; + +import java.util.ArrayList; + +import mekanism.common.transporter.Finder.MaterialFinder; +import mekanism.common.transporter.Finder.OreDictFinder; +import mekanism.common.util.InventoryUtils; +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.common.ForgeDirection; + +import com.google.common.io.ByteArrayDataInput; + +public class TMaterialFilter extends TransporterFilter +{ + public ItemStack materialItem; + + public Material getMaterial() + { + return Block.blocksList[materialItem.itemID].blockMaterial; + } + + @Override + public boolean canFilter(ItemStack itemStack) + { + if(itemStack == null || !(itemStack.getItem() instanceof ItemBlock)) + { + return false; + } + + return new MaterialFinder(getMaterial()).modifies(itemStack); + } + + @Override + public InvStack getStackFromInventory(IInventory inv, ForgeDirection side) + { + return InventoryUtils.takeTopStack(inv, side.ordinal(), new MaterialFinder(getMaterial())); + } + + @Override + public void write(NBTTagCompound nbtTags) + { + nbtTags.setInteger("type", 2); + materialItem.writeToNBT(nbtTags); + } + + @Override + protected void read(NBTTagCompound nbtTags) + { + materialItem = ItemStack.loadItemStackFromNBT(nbtTags); + } + + @Override + public void write(ArrayList data) + { + data.add(2); + + data.add(materialItem.itemID); + data.add(materialItem.stackSize); + data.add(materialItem.getItemDamage()); + } + + @Override + protected void read(ByteArrayDataInput dataStream) + { + materialItem = new ItemStack(dataStream.readInt(), dataStream.readInt(), dataStream.readInt()); + } + + @Override + public int hashCode() + { + int code = 1; + code = 31 * code + materialItem.itemID; + code = 31 * code + materialItem.stackSize; + code = 31 * code + materialItem.getItemDamage(); + return code; + } + + @Override + public boolean equals(Object filter) + { + return super.equals(filter) && filter instanceof TMaterialFilter && ((TMaterialFilter)filter).materialItem.isItemEqual(materialItem); + } + + @Override + public TMaterialFilter clone() + { + TMaterialFilter filter = new TMaterialFilter(); + filter.materialItem = materialItem; + + return filter; + } +} diff --git a/common/mekanism/common/transporter/TransporterFilter.java b/common/mekanism/common/transporter/TransporterFilter.java index a7041dd08..1462b345f 100644 --- a/common/mekanism/common/transporter/TransporterFilter.java +++ b/common/mekanism/common/transporter/TransporterFilter.java @@ -69,9 +69,14 @@ public abstract class TransporterFilter { filter = new TItemStackFilter(); } - else { + else if(type == 1) + { filter = new TOreDictFilter(); } + else if(type == 2) + { + filter = new TMaterialFilter(); + } filter.read(nbtTags); @@ -92,6 +97,10 @@ public abstract class TransporterFilter { filter = new TOreDictFilter(); } + else if(type == 3) + { + filter = new TMaterialFilter(); + } filter.read(dataStream); diff --git a/resources/assets/mekanism/gui/GuiLogisticalSorter.png b/resources/assets/mekanism/gui/GuiLogisticalSorter.png index cddb8ec1b9a2cacac28a0138d332234226f31bc0..0010929c7695be6e700b0b14bdc32d2c30c5fb33 100644 GIT binary patch delta 3127 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