From bb912ec8a125fa06daf98fb709a7365446d3b14e Mon Sep 17 00:00:00 2001 From: lordIcocain Date: Fri, 11 Apr 2025 02:00:31 +0300 Subject: [PATCH] Fix filters Add oredictionary filter Fix inconsistent with WCT Gui improvements Filter caching GuiFCImgButton 3/4 size support --- .../github/client/gui/GuiFCImgButton.java | 102 +++++------- .../github/client/gui/GuiMagnetFilter.java | 71 ++++++-- .../gui/container/ContainerMagnetFilter.java | 16 +- .../inventory/item/BaseWirelessInventory.java | 18 +- .../inventory/item/IWirelessMagnetFilter.java | 8 + .../github/inventory/item/WirelessMagnet.java | 49 ++---- .../WirelessMagnetCardFilterInventory.java | 154 +++++++++++++----- .../network/CPacketFluidPatternTermBtns.java | 6 + .../glodblock/github/proxy/CommonProxy.java | 85 ++++------ .../com/glodblock/github/util/NameConst.java | 2 + .../java/com/glodblock/github/util/Util.java | 30 ++-- .../resources/assets/ae2fc/lang/en_US.lang | 1 + .../ae2fc/textures/gui/magnet_filter.png | Bin 16636 -> 16664 bytes .../assets/ae2fc/textures/gui/states3.png | Bin 1803 -> 1808 bytes 14 files changed, 310 insertions(+), 232 deletions(-) diff --git a/src/main/java/com/glodblock/github/client/gui/GuiFCImgButton.java b/src/main/java/com/glodblock/github/client/gui/GuiFCImgButton.java index 82e727a5..123bb50e 100644 --- a/src/main/java/com/glodblock/github/client/gui/GuiFCImgButton.java +++ b/src/main/java/com/glodblock/github/client/gui/GuiFCImgButton.java @@ -22,6 +22,7 @@ public class GuiFCImgButton extends GuiButton implements ITooltip { private static Map appearances; private final String buttonSetting; private boolean halfSize = false; + private boolean threeFourths = false; private String fillVar; private String currentValue; private final boolean background; @@ -145,6 +146,14 @@ public class GuiFCImgButton extends GuiButton implements ITooltip { this.halfSize = halfSize; } + public boolean isThreeFourths() { + return threeFourths; + } + + public void setThreeFourths(boolean threeFourths) { + this.threeFourths = threeFourths; + } + public String getFillVar() { return this.fillVar; } @@ -165,12 +174,12 @@ public class GuiFCImgButton extends GuiButton implements ITooltip { @Override public int getWidth() { - return this.halfSize ? 8 : 16; + return this.halfSize ? 8 : threeFourths ? 12 : 16; } @Override public int getHeight() { - return this.halfSize ? 8 : 16; + return this.halfSize ? 8 : threeFourths ? 12 : 16; } @Override @@ -227,79 +236,44 @@ public class GuiFCImgButton extends GuiButton implements ITooltip { if (this.visible) { final int iconIndex = this.getIconIndex(); final int iconPage = this.getIconPage(); + this.width = getWidth(); + this.height = getHeight(); + float scaleFactor = halfSize ? 3 : threeFourths ? 4.5f : 6; - if (this.halfSize) { - this.width = 8; - this.height = 8; - - GL11.glPushMatrix(); - GL11.glTranslatef(this.xPosition, this.yPosition, 0.0F); - GL11.glScalef(0.5f / 16 * 3, 0.5f / 16 * 3, 0.5f / 16 * 3); - - if (this.enabled) { - GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - } else { - GL11.glColor4f(0.5f, 0.5f, 0.5f, 1.0f); - } - - par1Minecraft.renderEngine.bindTexture(FluidCraft.resource("textures/gui/states" + iconPage + ".png")); - this.field_146123_n = par2 >= this.xPosition && par3 >= this.yPosition - && par2 < this.xPosition + this.width - && par3 < this.yPosition + this.height; - - final int uv_y = (int) Math.floor(iconIndex / 3.0); - final int uv_x = iconIndex - uv_y * 3; - if (this.background) { - this.drawTexturedModalRect( - 0, - 0, - Math.round(32F * 16F / 3F), - Math.round(32F * 16F / 3F), - Math.round(16F * 16F / 3F), - Math.round(16F * 16F / 3F)); - } - this.drawTexturedModalRect( - 0, - 0, - Math.round(uv_x * 16F * 16F / 3F), - Math.round(uv_y * 16F * 16F / 3F), - Math.round(16F * 16F / 3F), - Math.round(16F * 16F / 3F)); + GL11.glPushMatrix(); + GL11.glTranslatef(this.xPosition, this.yPosition, 0.0F); + GL11.glScalef(0.5f / 16 * scaleFactor, 0.5f / 16 * scaleFactor, 0.5f / 16 * scaleFactor); + if (this.enabled) { + GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); } else { - GL11.glPushMatrix(); - GL11.glTranslatef(this.xPosition, this.yPosition, 0.0F); - GL11.glScalef(0.5f / 16 * 6, 0.5f / 16 * 6, 0.5f / 16 * 6); - if (this.enabled) { - GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - } else { - GL11.glColor4f(0.5f, 0.5f, 0.5f, 1.0f); - } + GL11.glColor4f(0.5f, 0.5f, 0.5f, 1.0f); + } - par1Minecraft.renderEngine.bindTexture(FluidCraft.resource("textures/gui/states" + iconPage + ".png")); - this.field_146123_n = par2 >= this.xPosition && par3 >= this.yPosition - && par2 < this.xPosition + this.width - && par3 < this.yPosition + this.height; + par1Minecraft.renderEngine.bindTexture(FluidCraft.resource("textures/gui/states" + iconPage + ".png")); + this.field_146123_n = par2 >= this.xPosition && par3 >= this.yPosition + && par2 < this.xPosition + this.width + && par3 < this.yPosition + this.height; - final int uv_y = (int) Math.floor(iconIndex / 3.0); - final int uv_x = iconIndex - uv_y * 3; - if (this.background) { - this.drawTexturedModalRect( - 0, - 0, - Math.round(32F * 16F / 3F), - Math.round(32F * 16F / 3F), - Math.round(16F * 16F / 3F), - Math.round(16F * 16F / 3F)); - } + final int uv_y = (int) Math.floor(iconIndex / 3.0); + final int uv_x = iconIndex - uv_y * 3; + if (this.background) { this.drawTexturedModalRect( 0, 0, - Math.round(uv_x * 16F * 16F / 3F), - Math.round(uv_y * 16F * 16F / 3F), + Math.round(32F * 16F / 3F), + Math.round(32F * 16F / 3F), Math.round(16F * 16F / 3F), Math.round(16F * 16F / 3F)); } + this.drawTexturedModalRect( + 0, + 0, + Math.round(uv_x * 16F * 16F / 3F), + Math.round(uv_y * 16F * 16F / 3F), + Math.round(16F * 16F / 3F), + Math.round(16F * 16F / 3F)); + this.mouseDragged(par1Minecraft, par2, par3); GL11.glPopMatrix(); } diff --git a/src/main/java/com/glodblock/github/client/gui/GuiMagnetFilter.java b/src/main/java/com/glodblock/github/client/gui/GuiMagnetFilter.java index 331a2a3f..4bca8b64 100644 --- a/src/main/java/com/glodblock/github/client/gui/GuiMagnetFilter.java +++ b/src/main/java/com/glodblock/github/client/gui/GuiMagnetFilter.java @@ -5,6 +5,8 @@ import net.minecraft.client.gui.GuiButton; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.util.ResourceLocation; +import org.lwjgl.input.Keyboard; + import com.glodblock.github.FluidCraft; import com.glodblock.github.client.gui.container.ContainerMagnetFilter; import com.glodblock.github.client.gui.widget.FCGuiBaseButton; @@ -20,6 +22,7 @@ import appeng.api.storage.ITerminalHost; import appeng.client.gui.AEBaseMEGui; import appeng.client.gui.widgets.GuiImgButton; import appeng.client.gui.widgets.GuiTabButton; +import appeng.client.gui.widgets.MEGuiTextField; public class GuiMagnetFilter extends AEBaseMEGui { @@ -27,7 +30,8 @@ public class GuiMagnetFilter extends AEBaseMEGui { protected ContainerMagnetFilter cont; private static final ResourceLocation TEX_BG = FluidCraft.resource("textures/gui/magnet_filter.png"); - protected Component components[] = new Component[3]; + protected Component[] components = new Component[4]; + protected MEGuiTextField oreDict; protected GuiTabButton originalGuiBtn; protected GuiImgButton clearBtn; @@ -36,13 +40,14 @@ public class GuiMagnetFilter extends AEBaseMEGui { this.xSize = 195; this.ySize = 214; this.cont = (ContainerMagnetFilter) this.inventorySlots; + oreDict = new MEGuiTextField(149, 12, NameConst.i18n(NameConst.TT_MAGNET_CARD_OREDICT)); } private class Component { - private GuiFCImgButton enable; - private GuiFCImgButton disable; - private String action; + private final GuiFCImgButton enable; + private final GuiFCImgButton disable; + private final String action; private boolean var; public Component(int x, int y, boolean var, String action) { @@ -50,6 +55,8 @@ public class GuiMagnetFilter extends AEBaseMEGui { this.disable = new GuiFCImgButton(x, y, "DISABLE_12x", "DISABLE", false); this.var = var; this.action = action; + enable.setThreeFourths(true); + disable.setThreeFourths(true); buttonList.add(this.enable); buttonList.add(this.disable); } @@ -98,20 +105,29 @@ public class GuiMagnetFilter extends AEBaseMEGui { ? NameConst.GUI_MAGNET_CARD_WhiteList : NameConst.GUI_MAGNET_CARD_BlackList))); this.components[0] = new Component( - this.guiLeft + 156, + this.guiLeft + 157, this.guiTop + 18, this.cont.nbt, "WirelessTerminal.magnet.NBT"); this.components[1] = new Component( - this.guiLeft + 156, + this.guiLeft + 157, this.guiTop + 31, this.cont.meta, "WirelessTerminal.magnet.Meta"); this.components[2] = new Component( - this.guiLeft + 156, + this.guiLeft + 157, this.guiTop + 44, this.cont.ore, "WirelessTerminal.magnet.Ore"); + this.components[3] = new Component( + this.guiLeft + 157, + this.guiTop + 112, + this.cont.oreDict, + "WirelessTerminal.magnet.OreDictState"); + + oreDict.x = this.guiLeft + 7; + oreDict.y = this.guiTop + 112; + oreDict.setText(this.cont.oreDictFilter); this.buttonList.add( this.originalGuiBtn = new GuiTabButton( @@ -122,23 +138,27 @@ public class GuiMagnetFilter extends AEBaseMEGui { itemRender)); this.originalGuiBtn.setHideEdge(13); // GuiTabButton implementation // - this.clearBtn = new GuiImgButton(this.guiLeft + 8, this.guiTop + 48, Settings.ACTIONS, ActionItems.CLOSE); + this.clearBtn = new GuiImgButton(this.guiLeft + 7, this.guiTop + 48, Settings.ACTIONS, ActionItems.CLOSE); this.clearBtn.setHalfSize(true); this.buttonList.add(this.clearBtn); } + @Override + public void drawScreen(int mouseX, int mouseY, float btn) { + handleTooltip(mouseX, mouseY, oreDict); + super.drawScreen(mouseX, mouseY, btn); + } + @Override public void drawFG(int offsetX, int offsetY, int mouseX, int mouseY) { - this.fontRendererObj.drawString(getGuiDisplayName(NameConst.i18n(NameConst.GUI_MAGNET_CARD)), 8, 6, 0x404040); - this.fontRendererObj - .drawString(getGuiDisplayName(NameConst.i18n(NameConst.GUI_MAGNET_CARD_NBT)), 61, 22, 0x404040); - this.fontRendererObj - .drawString(getGuiDisplayName(NameConst.i18n(NameConst.GUI_MAGNET_CARD_META)), 61, 34, 0x404040); - this.fontRendererObj - .drawString(getGuiDisplayName(NameConst.i18n(NameConst.GUI_MAGNET_CARD_ORE)), 61, 46, 0x404040); + this.fontRendererObj.drawString(NameConst.i18n(NameConst.GUI_MAGNET_CARD), 8, 6, 0x404040); + this.fontRendererObj.drawString(NameConst.i18n(NameConst.GUI_MAGNET_CARD_NBT), 61, 22, 0x404040); + this.fontRendererObj.drawString(NameConst.i18n(NameConst.GUI_MAGNET_CARD_META), 61, 34, 0x404040); + this.fontRendererObj.drawString(NameConst.i18n(NameConst.GUI_MAGNET_CARD_ORE), 61, 46, 0x404040); this.components[0].setVar(this.cont.nbt); this.components[1].setVar(this.cont.meta); this.components[2].setVar(this.cont.ore); + this.components[3].setVar(this.cont.oreDict); for (Component c : components) { c.draw(); } @@ -149,8 +169,25 @@ public class GuiMagnetFilter extends AEBaseMEGui { @Override public void drawBG(int offsetX, int offsetY, int mouseX, int mouseY) { - mc.getTextureManager().bindTexture(TEX_BG); - drawTexturedModalRect(offsetX, offsetY, 0, 0, 176, ySize); + bindTexture(TEX_BG); + drawTexturedModalRect(offsetX, offsetY, 0, 0, xSize, ySize); + oreDict.drawTextBox(); + } + + @Override + protected void keyTyped(char typedChar, int keyCode) { + if (oreDict.isFocused() && (Keyboard.KEY_NUMPADENTER == keyCode || Keyboard.KEY_RETURN == keyCode)) { + FluidCraft.proxy.netHandler.sendToServer( + new CPacketFluidPatternTermBtns("WirelessTerminal.magnet.OreDictFilter", oreDict.getText())); + } + + if (!oreDict.textboxKeyTyped(typedChar, keyCode)) super.keyTyped(typedChar, keyCode); + } + + @Override + protected void mouseClicked(int xCoord, int yCoord, int btn) { + oreDict.mouseClicked(xCoord, yCoord, btn); + super.mouseClicked(xCoord, yCoord, btn); } @Override diff --git a/src/main/java/com/glodblock/github/client/gui/container/ContainerMagnetFilter.java b/src/main/java/com/glodblock/github/client/gui/container/ContainerMagnetFilter.java index 09c9672d..7b801892 100644 --- a/src/main/java/com/glodblock/github/client/gui/container/ContainerMagnetFilter.java +++ b/src/main/java/com/glodblock/github/client/gui/container/ContainerMagnetFilter.java @@ -15,6 +15,7 @@ import appeng.api.storage.ITerminalHost; import appeng.container.guisync.GuiSync; import appeng.container.slot.AppEngSlot; import appeng.container.slot.IOptionalSlotHost; +import appeng.container.slot.OptionalSlotFake; import appeng.container.slot.SlotFake; import appeng.container.slot.SlotPatternOutputs; import appeng.util.Platform; @@ -32,13 +33,21 @@ public class ContainerMagnetFilter extends FCBaseContainer implements IOptionalS @GuiSync(104) public boolean ore; - protected SlotFake[] filterSlots; + + @GuiSync(105) + public boolean oreDict; + + @GuiSync(106) + public String oreDictFilter; + + protected OptionalSlotFake[] filterSlots; protected final IInventory filter; public ContainerMagnetFilter(InventoryPlayer ip, ITerminalHost monitorable) { super(ip, monitorable); this.filter = ((IItemTerminal) monitorable).getInventoryByName("config"); - this.filterSlots = new SlotFake[27]; + this.filterSlots = new OptionalSlotFake[27]; + oreDictFilter = ((IWirelessMagnetFilter) getHost()).getOreDictFilter(); for (int y = 0; y < 3; y++) { for (int x = 0; x < 9; x++) { this.addSlotToContainer( @@ -51,6 +60,7 @@ public class ContainerMagnetFilter extends FCBaseContainer implements IOptionalS 0, 0, 1)); + this.filterSlots[x + y * 9].setRenderDisabled(false); } } bindPlayerInventory(ip, 0, 126); @@ -84,6 +94,8 @@ public class ContainerMagnetFilter extends FCBaseContainer implements IOptionalS this.meta = host.getMetaMode(); this.nbt = host.getNBTMode(); this.ore = host.getOreMode(); + this.oreDict = host.getOreDictMode(); + this.oreDictFilter = host.getOreDictFilter(); } super.detectAndSendChanges(); } diff --git a/src/main/java/com/glodblock/github/inventory/item/BaseWirelessInventory.java b/src/main/java/com/glodblock/github/inventory/item/BaseWirelessInventory.java index 50c30c62..55b16174 100644 --- a/src/main/java/com/glodblock/github/inventory/item/BaseWirelessInventory.java +++ b/src/main/java/com/glodblock/github/inventory/item/BaseWirelessInventory.java @@ -26,6 +26,7 @@ import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEStack; import appeng.api.util.AECableType; import appeng.items.tools.powered.ToolWirelessTerminal; +import appeng.me.storage.NullInventory; import appeng.util.Platform; public abstract class BaseWirelessInventory extends MEMonitorHandler implements IWirelessTerminal, IWirelessExtendCard { @@ -55,6 +56,19 @@ public abstract class BaseWirelessInventory extends MEMonitorHandler implements this.readFromNBT(); } + @SuppressWarnings("unchecked") + public BaseWirelessInventory(final ItemStack is, final int slot, IGridNode gridNode, EntityPlayer player, + StorageChannel channel, boolean nullInventory) { + super(new NullInventory<>()); + this.ips = (ToolWirelessTerminal) is.getItem(); + this.grid = gridNode; + this.target = is; + this.inventorySlot = slot; + this.channel = channel; + this.source = new PlayerSource(player, this); + this.readFromNBT(); + } + private void readFromNBT() { NBTTagCompound data = Platform.openNbtData(this.target); this.setMagnetCardMode(WirelessMagnet.Mode.values()[data.getInteger(modeKey)]); @@ -100,9 +114,7 @@ public abstract class BaseWirelessInventory extends MEMonitorHandler implements } @Override - public void saveChanges() { - - } + public void saveChanges() {} @Override public IGridNode getActionableNode() { diff --git a/src/main/java/com/glodblock/github/inventory/item/IWirelessMagnetFilter.java b/src/main/java/com/glodblock/github/inventory/item/IWirelessMagnetFilter.java index 65ace4c1..2cbee079 100644 --- a/src/main/java/com/glodblock/github/inventory/item/IWirelessMagnetFilter.java +++ b/src/main/java/com/glodblock/github/inventory/item/IWirelessMagnetFilter.java @@ -10,6 +10,10 @@ public interface IWirelessMagnetFilter extends IWirelessTerminal, IItemTerminal boolean getOreMode(); + boolean getOreDictMode(); + + String getOreDictFilter(); + void setListMode(WirelessMagnet.ListMode mode); void setNBTMode(boolean ignoreNBT); @@ -18,6 +22,10 @@ public interface IWirelessMagnetFilter extends IWirelessTerminal, IItemTerminal void setOreMode(boolean useOre); + void setOreDictMode(boolean useOreDict); + + void setOreDictFilter(String str); + default void clearConfig() {}; } diff --git a/src/main/java/com/glodblock/github/inventory/item/WirelessMagnet.java b/src/main/java/com/glodblock/github/inventory/item/WirelessMagnet.java index c144b97f..a1885075 100644 --- a/src/main/java/com/glodblock/github/inventory/item/WirelessMagnet.java +++ b/src/main/java/com/glodblock/github/inventory/item/WirelessMagnet.java @@ -3,8 +3,6 @@ package com.glodblock.github.inventory.item; import static com.glodblock.github.common.Config.magnetRange; -import java.util.ArrayList; -import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -17,11 +15,7 @@ import net.minecraft.util.AxisAlignedBB; import net.minecraft.world.World; import com.glodblock.github.common.item.ItemWirelessUltraTerminal; -import com.glodblock.github.inventory.ItemBiggerAppEngInventory; -import appeng.api.storage.data.IAEItemStack; -import appeng.api.storage.data.IItemList; -import appeng.tile.inventory.AppEngInternalInventory; import appeng.util.Platform; public class WirelessMagnet { @@ -54,32 +48,13 @@ public class WirelessMagnet { } @SuppressWarnings("unchecked") - public static List getFilteredItems(ItemStack wirelessTerm) { - if (wirelessTerm == null) { - return null; - } - if (wirelessTerm.getItem() instanceof ItemWirelessUltraTerminal) { - if (wirelessTerm.hasTagCompound()) { - NBTTagCompound data = Platform.openNbtData(wirelessTerm); - if (!data.hasKey(filterKey)) { - return Collections.emptyList(); - } - AppEngInternalInventory filterList = new ItemBiggerAppEngInventory(wirelessTerm, filterKey, 27); - ArrayList list = new ArrayList<>(); - filterList.iterator().forEachRemaining(list::add); - return list; - } - } - return Collections.emptyList(); - } public static boolean isConfigured(ItemStack wirelessTerm) { NBTTagCompound data = Platform.openNbtData(wirelessTerm); return data.hasKey(modeKey); } - public static void doMagnet(ItemStack wirelessTerm, World world, EntityPlayer player, - WirelessMagnetCardFilterInventory inv) { + public static void doMagnet(ItemStack wirelessTerm, World world, EntityPlayer player) { if (Platform.isClient() || wirelessTerm == null || getMode(wirelessTerm) == Mode.Off || player == null @@ -94,7 +69,6 @@ public class WirelessMagnet { (int) player.posY, (int) player.posZ, magnetRange).iterator(); - IItemList filteredList = inv.getAEFilteredItems(); while (iterator.hasNext()) { EntityItem itemToGet = (EntityItem) iterator.next(); if (itemToGet.func_145800_j() != null && itemToGet.func_145800_j() @@ -107,19 +81,16 @@ public class WirelessMagnet { if (closestPlayer != null && closestPlayer != player) { continue; } - ItemStack stack = itemToGet.getEntityItem(); - if ((inv.getListMode() == ListMode.WhiteList && !filteredList.isEmpty() - && inv.isItemFiltered(stack, filteredList)) - || (inv.getListMode() == ListMode.BlackList && !inv.isItemFiltered(stack, filteredList))) { - if (itemToGet.delayBeforeCanPickup > 0) { - itemToGet.delayBeforeCanPickup = 0; - } - itemToGet.motionX = itemToGet.motionY = itemToGet.motionZ = 0; - itemToGet.setPosition( - player.posX - 0.2 + (world.rand.nextDouble() * 0.4), - player.posY - 0.6, - player.posZ - 0.2 + (world.rand.nextDouble() * 0.4)); + + if (itemToGet.delayBeforeCanPickup > 0) { + itemToGet.delayBeforeCanPickup = 0; } + itemToGet.motionX = itemToGet.motionY = itemToGet.motionZ = 0; + itemToGet.setPosition( + player.posX - 0.2 + (world.rand.nextDouble() * 0.4), + player.posY - 0.6, + player.posZ - 0.2 + (world.rand.nextDouble() * 0.4)); + } // xp diff --git a/src/main/java/com/glodblock/github/inventory/item/WirelessMagnetCardFilterInventory.java b/src/main/java/com/glodblock/github/inventory/item/WirelessMagnetCardFilterInventory.java index 9b74cb03..c23a5667 100644 --- a/src/main/java/com/glodblock/github/inventory/item/WirelessMagnetCardFilterInventory.java +++ b/src/main/java/com/glodblock/github/inventory/item/WirelessMagnetCardFilterInventory.java @@ -4,7 +4,8 @@ package com.glodblock.github.inventory.item; import static com.glodblock.github.inventory.item.WirelessMagnet.filterConfigKey; import static com.glodblock.github.inventory.item.WirelessMagnet.filterKey; -import java.util.List; +import java.util.HashMap; +import java.util.function.Predicate; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; @@ -15,7 +16,6 @@ import net.minecraft.world.World; import com.glodblock.github.inventory.ItemBiggerAppEngInventory; -import appeng.api.AEApi; import appeng.api.config.Actionable; import appeng.api.config.PowerMultiplier; import appeng.api.networking.IGridNode; @@ -23,24 +23,33 @@ import appeng.api.storage.IMEMonitor; import appeng.api.storage.StorageChannel; import appeng.api.storage.data.IAEFluidStack; import appeng.api.storage.data.IAEItemStack; -import appeng.api.storage.data.IItemList; import appeng.api.util.IConfigManager; import appeng.tile.inventory.AppEngInternalInventory; import appeng.tile.inventory.InvOperation; import appeng.util.Platform; +import appeng.util.item.AEItemStack; +import appeng.util.item.OreHelper; +import appeng.util.prioitylist.OreFilteredList; public class WirelessMagnetCardFilterInventory extends BaseWirelessInventory implements IWirelessMagnetFilter { private boolean ignoreNbt; private boolean ignoreMeta; + private boolean useOre; private boolean useOreDict; + private String oreDictFilter; + protected Predicate filterPredicate = null; private WirelessMagnet.ListMode listMode = WirelessMagnet.ListMode.WhiteList; - protected AppEngInternalInventory filterList; + private final AppEngInternalInventory filterInventory; + private final NBTTagCompound settingCache; + private final NBTTagCompound filterCache; @SuppressWarnings("unchecked") public WirelessMagnetCardFilterInventory(ItemStack is, int slot, IGridNode gridNode, EntityPlayer player) { - super(is, slot, gridNode, player, StorageChannel.ITEMS); - this.filterList = new ItemBiggerAppEngInventory(is, filterKey, 27); + super(is, slot, gridNode, player, StorageChannel.ITEMS, true); + filterInventory = new ItemBiggerAppEngInventory(is, filterKey, 27); + settingCache = getSettingTag(is); + filterCache = getFilterTag(is); readFromNBT(); } @@ -50,7 +59,9 @@ public class WirelessMagnetCardFilterInventory extends BaseWirelessInventory imp NBTTagCompound tag = (NBTTagCompound) data.getTag(filterConfigKey); ignoreNbt = tag.getBoolean("nbt"); ignoreMeta = tag.getBoolean("meta"); - useOreDict = tag.getBoolean("ore"); + useOre = tag.getBoolean("ore"); + useOreDict = tag.getBoolean("oreDict"); + oreDictFilter = tag.getString("oreDictFilter"); this.listMode = WirelessMagnet.ListMode.values()[tag.getInteger("list")]; } @@ -59,11 +70,21 @@ public class WirelessMagnetCardFilterInventory extends BaseWirelessInventory imp NBTTagCompound tmp = new NBTTagCompound(); tmp.setBoolean("nbt", ignoreNbt); tmp.setBoolean("meta", ignoreMeta); - tmp.setBoolean("ore", useOreDict); + tmp.setBoolean("ore", useOre); + tmp.setBoolean("oreDict", useOreDict); + tmp.setString("oreDictFilter", oreDictFilter); tmp.setInteger("list", this.listMode.ordinal()); data.setTag(filterConfigKey, tmp); } + private NBTTagCompound getSettingTag(ItemStack is) { + return (NBTTagCompound) is.getTagCompound().getCompoundTag(filterConfigKey).copy(); + } + + private NBTTagCompound getFilterTag(ItemStack is) { + return (NBTTagCompound) is.getTagCompound().getCompoundTag(filterKey).copy(); + } + @Override public WirelessMagnet.ListMode getListMode() { return this.listMode; @@ -81,9 +102,19 @@ public class WirelessMagnetCardFilterInventory extends BaseWirelessInventory imp @Override public boolean getOreMode() { + return useOre; + } + + @Override + public boolean getOreDictMode() { return useOreDict; } + @Override + public String getOreDictFilter() { + return oreDictFilter; + } + @Override public void setListMode(WirelessMagnet.ListMode mode) { this.listMode = mode; @@ -101,7 +132,18 @@ public class WirelessMagnetCardFilterInventory extends BaseWirelessInventory imp @Override public void setOreMode(boolean useOre) { - useOreDict = useOre; + this.useOre = useOre; + } + + @Override + public void setOreDictMode(boolean useOreDict) { + this.useOreDict = useOreDict; + } + + @Override + public void setOreDictFilter(String str) { + oreDictFilter = str; + filterPredicate = null; } @Override @@ -129,7 +171,7 @@ public class WirelessMagnetCardFilterInventory extends BaseWirelessInventory imp @Override public IMEMonitor getItemInventory() { - return this; + return null; } @Override @@ -144,9 +186,7 @@ public class WirelessMagnetCardFilterInventory extends BaseWirelessInventory imp @Override public void onChangeInventory(IInventory inv, int slot, InvOperation mc, ItemStack removedStack, - ItemStack newStack) { - - } + ItemStack newStack) {} @Override public void saveSettings() { @@ -157,7 +197,7 @@ public class WirelessMagnetCardFilterInventory extends BaseWirelessInventory imp @Override public IInventory getInventoryByName(String name) { if (name.equals("config")) { - return this.filterList; + return filterInventory; } return null; } @@ -177,39 +217,67 @@ public class WirelessMagnetCardFilterInventory extends BaseWirelessInventory imp return true; } - public List getFilteredItems() { - return WirelessMagnet.getFilteredItems(this.target); - } - - public IItemList getAEFilteredItems() { - IItemList list = AEApi.instance().storage().createItemList(); - for (ItemStack is : this.getFilteredItems()) { - list.add(AEApi.instance().storage().createItemStack(is)); + public boolean isItemFiltered(ItemStack inputItemStack) { + if (useOreDict && !oreDictFilter.isEmpty()) { + if (filterPredicate == null) filterPredicate = OreFilteredList.makeFilter(oreDictFilter); + if (filterPredicate.test(AEItemStack.create(inputItemStack))) return true; } - return list; - } - public boolean isItemFiltered(ItemStack is, IItemList list) { - if (is == null && list.isEmpty()) return false; - IAEItemStack ais = AEApi.instance().storage().createItemStack(is); - for (IAEItemStack i : list) { - if (useOreDict) { - // use oredict - return i.sameOre(ais); - } else if (ignoreMeta && ignoreNbt) { - // ignore meta & nbt - return ais.getItem() == i.getItem(); - } else if (ignoreMeta) { - // ignore meta only - return ais.getItemStack().getTagCompound().equals(i.getItemStack().getTagCompound()); - } else if (ignoreNbt) { - // ignore nbt only - return i.getItemDamage() == ais.getItemDamage(); - } else { - // ignore nothing/don't use oredict--must be exact match - return ais.equals(i); + for (int i = 0; i < filterInventory.getSizeInventory(); i++) { + ItemStack is = filterInventory.getStackInSlot(i); + if (is != null) { + if (useOre) { + // use oredict + if (OreHelper.INSTANCE + .sameOre(OreHelper.INSTANCE.isOre(is), OreHelper.INSTANCE.isOre(inputItemStack))) + return true; + } + if (ignoreMeta && ignoreNbt) { + // ignore meta & nbt + return is.getItem().equals(inputItemStack.getItem()); + } else if (ignoreMeta) { + // ignore meta only + return ItemStack.areItemStackTagsEqual(is, inputItemStack) + && is.getItem() == inputItemStack.getItem(); + } else if (ignoreNbt) { + // ignore nbt only + return is.getItem() == inputItemStack.getItem() + && is.getItemDamage() == inputItemStack.getItemDamage(); + } else { + // ignore nothing/don't use oredict--must be exact match + return is.isItemEqual(inputItemStack) && ItemStack.areItemStackTagsEqual(is, inputItemStack); + } } } return false; } + + public boolean isPassFilter(ItemStack is) { + return is != null && (listMode == WirelessMagnet.ListMode.WhiteList) == isItemFiltered(is); + } + + public boolean checkCache(ItemStack is) { + return settingCache.equals(getSettingTag(is)) && filterCache.equals(getFilterTag(is)); + } + + public static class FilterCache { + + private static final HashMap cache = new HashMap<>(); + + public static WirelessMagnetCardFilterInventory getFilter(ItemStack is, int slot, IGridNode gridNode, + EntityPlayer player) { + WirelessMagnetCardFilterInventory cachedInv = cache.get(player); + if (cachedInv != null && cachedInv.checkCache(is)) { + return cachedInv; + } else { + WirelessMagnetCardFilterInventory newInv = new WirelessMagnetCardFilterInventory( + is, + slot, + gridNode, + player); + cache.put(player, newInv); + return newInv; + } + } + } } diff --git a/src/main/java/com/glodblock/github/network/CPacketFluidPatternTermBtns.java b/src/main/java/com/glodblock/github/network/CPacketFluidPatternTermBtns.java index 8613aa45..98a49ad8 100644 --- a/src/main/java/com/glodblock/github/network/CPacketFluidPatternTermBtns.java +++ b/src/main/java/com/glodblock/github/network/CPacketFluidPatternTermBtns.java @@ -111,6 +111,12 @@ public class CPacketFluidPatternTermBtns implements IMessage { case "WirelessTerminal.magnet.Ore": ((IWirelessMagnetFilter) itemTerminal).setOreMode(Value.equals("1")); break; + case "WirelessTerminal.magnet.OreDictState": + ((IWirelessMagnetFilter) itemTerminal).setOreDictMode(Value.equals("1")); + break; + case "WirelessTerminal.magnet.OreDictFilter": + ((IWirelessMagnetFilter) itemTerminal).setOreDictFilter(Value); + break; case "WirelessTerminal.magnet.FilterMode": ((IWirelessMagnetFilter) itemTerminal).setListMode( Value.equals("1") ? WirelessMagnet.ListMode.WhiteList diff --git a/src/main/java/com/glodblock/github/proxy/CommonProxy.java b/src/main/java/com/glodblock/github/proxy/CommonProxy.java index 03284d37..cf6903af 100644 --- a/src/main/java/com/glodblock/github/proxy/CommonProxy.java +++ b/src/main/java/com/glodblock/github/proxy/CommonProxy.java @@ -21,6 +21,7 @@ import com.glodblock.github.crossmod.thaumcraft.ThaumicEnergisticsCrafting; import com.glodblock.github.inventory.external.AEFluidInterfaceHandler; import com.glodblock.github.inventory.item.WirelessMagnet; import com.glodblock.github.inventory.item.WirelessMagnetCardFilterInventory; +import com.glodblock.github.inventory.item.WirelessMagnetCardFilterInventory.FilterCache; import com.glodblock.github.loader.ItemAndBlockHolder; import com.glodblock.github.network.SPacketMEUpdateBuffer; import com.glodblock.github.network.wrapper.FCNetworkWrapper; @@ -31,8 +32,6 @@ import appeng.api.AEApi; import appeng.api.IAppEngApi; import appeng.api.config.Upgrades; import appeng.api.networking.IGridNode; -import appeng.api.storage.data.IAEItemStack; -import appeng.api.storage.data.IItemList; import appeng.util.Platform; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.event.FMLInitializationEvent; @@ -54,48 +53,38 @@ public class CommonProxy { @SuppressWarnings("unchecked") @SubscribeEvent public void pickupEvent(EntityItemPickupEvent e) { - try { - if (Platform.isClient() || e.entityPlayer == null) return; - EntityPlayer player = e.entityPlayer; - EntityItem itemEntity = e.item; - ItemStack stack = itemEntity.getEntityItem(); - World world = player.getEntityWorld(); + if (Platform.isServer() && e.entityPlayer != null) { + try { + EntityPlayer player = e.entityPlayer; + EntityItem itemEntity = e.item; + ItemStack stack = itemEntity.getEntityItem(); + World world = player.getEntityWorld(); - ImmutablePair result = Util.getUltraWirelessTerm(player); - if (result == null) return; - final ItemStack wirelessTerm = result.getRight(); - WirelessMagnet.Mode mode = WirelessMagnet.getMode(wirelessTerm); - if (mode != WirelessMagnet.Mode.ME) return; - IGridNode gridNode = Util.getWirelessGrid(wirelessTerm); - if (gridNode == null || !Util.rangeCheck(wirelessTerm, player, gridNode)) return; - WirelessMagnetCardFilterInventory inv = new WirelessMagnetCardFilterInventory( - wirelessTerm, - result.getLeft(), - gridNode, - player); + ImmutablePair result = Util.getUltraWirelessTerm(player); + if (result != null) { + final ItemStack wirelessTerm = result.getRight(); + WirelessMagnet.Mode mode = WirelessMagnet.getMode(wirelessTerm); + if (mode == WirelessMagnet.Mode.ME) { + IGridNode gridNode = Util.getWirelessGrid(wirelessTerm); + if (gridNode != null && Util.rangeCheck(wirelessTerm, player, gridNode)) { + WirelessMagnetCardFilterInventory inv = FilterCache + .getFilter(wirelessTerm, result.getLeft(), gridNode, player); - IItemList filteredList = inv.getAEFilteredItems(); - IAEItemStack ais = AEApi.instance().storage().createItemStack(stack); - if (inv.getListMode() == WirelessMagnet.ListMode.WhiteList) { // whitelisting - if (!filteredList.isEmpty() && inv.isItemFiltered(stack, filteredList)) { - if (inv.doInject(ais, itemEntity, world)) { - stack = null; - itemEntity.setDead(); - e.setCanceled(true); - } - } - } else if (inv.getListMode() == WirelessMagnet.ListMode.BlackList) { - if (!inv.isItemFiltered(stack, filteredList)) { - if (inv.doInject(ais, itemEntity, world)) { - stack = null; - itemEntity.setDead(); - e.setCanceled(true); + if (inv.isPassFilter(stack)) { + if (inv.doInject( + AEApi.instance().storage().createItemStack(stack), + itemEntity, + world)) { + itemEntity.setDead(); + e.setCanceled(true); + } + } + } } } + } catch (NullPointerException ex) { + ex.printStackTrace(); } - - } catch (NullPointerException ex) { - ex.printStackTrace(); } } @@ -103,18 +92,12 @@ public class CommonProxy { public void tickEvent(TickEvent.PlayerTickEvent e) { EntityPlayer player = e.player; ImmutablePair result = Util.getUltraWirelessTerm(player); - if (result == null) return; - final ItemStack wirelessTerm = result.getRight(); - if (WirelessMagnet.getMode(wirelessTerm) == WirelessMagnet.Mode.Off) return; - IGridNode gridNode = Util.getWirelessGrid(wirelessTerm); - if (gridNode == null || !Util.rangeCheck(wirelessTerm, player, gridNode)) return; - WirelessMagnetCardFilterInventory inv = new WirelessMagnetCardFilterInventory( - wirelessTerm, - result.getLeft(), - gridNode, - player); - WirelessMagnet.doMagnet(wirelessTerm, e.player.worldObj, e.player, inv); - + if (result != null) { + final ItemStack wirelessTerm = result.getRight(); + if (WirelessMagnet.getMode(wirelessTerm) != WirelessMagnet.Mode.Off) { + WirelessMagnet.doMagnet(wirelessTerm, e.player.worldObj, e.player); + } + } } public void preInit(FMLPreInitializationEvent event) { diff --git a/src/main/java/com/glodblock/github/util/NameConst.java b/src/main/java/com/glodblock/github/util/NameConst.java index ce61cce2..ca421ebf 100644 --- a/src/main/java/com/glodblock/github/util/NameConst.java +++ b/src/main/java/com/glodblock/github/util/NameConst.java @@ -112,6 +112,8 @@ public class NameConst { public static final String TT_ULTRA_TERMINAL_RESTOCK_ON = TT_ULTRA_TERMINAL_RESTOCK + ".on"; public static final String TT_ULTRA_TERMINAL_RESTOCK_OFF = TT_ULTRA_TERMINAL_RESTOCK + ".off"; + public static final String TT_MAGNET_CARD_OREDICT = TT_KEY + "magnet_card.oreDictFilter"; + public static final String WAILA_KEY = FluidCraft.MODID + ".waila."; public static final String WAILA_ENABLE = WAILA_KEY + "enable"; public static final String WAILA_DISABLE = WAILA_KEY + "disable"; diff --git a/src/main/java/com/glodblock/github/util/Util.java b/src/main/java/com/glodblock/github/util/Util.java index 094213f4..0b183788 100644 --- a/src/main/java/com/glodblock/github/util/Util.java +++ b/src/main/java/com/glodblock/github/util/Util.java @@ -162,22 +162,26 @@ public final class Util { } public static IMEInventoryHandler getWirelessInv(ItemStack is, EntityPlayer player, StorageChannel channel) { - if (Platform.isClient()) return new NullInventory<>(); - IGridNode gridNode = getWirelessGrid(is); - if (gridNode == null) return null; - IGrid grid = gridNode.getGrid(); - if (grid == null) return null; - if (rangeCheck(is, player, grid)) { - IStorageGrid gridCache = grid.getCache(IStorageGrid.class); - if (gridCache != null) { - if (channel == StorageChannel.FLUIDS) { - return gridCache.getFluidInventory(); - } else { - return gridCache.getItemInventory(); + if (Platform.isServer()) { + IGridNode gridNode = getWirelessGrid(is); + if (gridNode != null) { + IGrid grid = gridNode.getGrid(); + if (grid != null) { + if (rangeCheck(is, player, grid)) { + IStorageGrid gridCache = grid.getCache(IStorageGrid.class); + if (gridCache != null) { + if (channel == StorageChannel.FLUIDS) { + return gridCache.getFluidInventory(); + } else { + return gridCache.getItemInventory(); + } + } + } } } + return null; } - return null; + return new NullInventory<>(); } public static ItemStack getWirelessTerminal(EntityPlayer player, int x) { diff --git a/src/main/resources/assets/ae2fc/lang/en_US.lang b/src/main/resources/assets/ae2fc/lang/en_US.lang index bbcfcd2d..fbb59d5b 100644 --- a/src/main/resources/assets/ae2fc/lang/en_US.lang +++ b/src/main/resources/assets/ae2fc/lang/en_US.lang @@ -170,6 +170,7 @@ ae2fc.tooltip.magnet_card.inv.hint=Pickup to Inventory ae2fc.tooltip.magnet_card.me=Magnet Card ae2fc.tooltip.magnet_card.me.hint=Pickup to ME ae2fc.tooltip.magnet_card.filter=Magnet Filter +ae2fc.tooltip.magnet_card.oreDictFilter=Oredictionary filter ae2fc.tooltip.restock.on=Toggle Restock ae2fc.tooltip.restock.on.hint=Enable ae2fc.tooltip.restock.off=Toggle Restock diff --git a/src/main/resources/assets/ae2fc/textures/gui/magnet_filter.png b/src/main/resources/assets/ae2fc/textures/gui/magnet_filter.png index 7312b62cba9b2d064f899a226fe64d665c3be2b1..1efe6ad3aa47589d43e3a1419e8289211f4b0b8a 100644 GIT binary patch delta 1327 zcmey<$T*{kae~U^x7OOi44efXk;M!Qd+j}2pJu$rW}^MPxpId}ckjL1x0XZa!|~5&XV1TX>ha^pJBl;JB}D(KGWh%Z zFLy7P`|kbw?Z4aG+Y6tY*EbsX+-Lar=q$hPeinudK?V+Cx}thw?b}_u?{CGnzaPGQ z*>ZRPk3T;@zr0vD->!Do&u?#Uzg+(K%*@~R=YRhA`1s}W`Ec)|VoV)YgXDrTPu{tql=hWgHmR&N^jeJJwc~60~-f>erAzF_v*CG9z!R+^0 zZL_N&^Rv$Vi@C+IrLWh49mp#J($kZbFE~Csvvv-Ue!7E=D7Qnr2=YPN{>r1vW?2?L z3p;yrzPEJawfdQQERESIiYKftGwiXsxZ%+5^7sF?-h0i#81eipLytIb*pKyJt8 zSm`l2&0uiAif(+-XWU=^f8XD)Vrw4hGp;{v!cfr5k}x-u;n?-&`PntLTi)-lpKDp1 zeC}Vpf>1;0J)Q#pL@No5a>xRycS^EdgliFhMV>LyWg*!Z=9ZYbo%i_7Kbu1`sYpR|gQH}EWwG{iAZ@vh5ySoUIJ^Y35o|?%+{Tq@=jQATE&lfW zlG}n(a^e_Y6xYM!_*{u1M~pJJ>uZs^ICuO l_WWdIAPFeEeD=&=po)2&T2g@m0|OTWgQu&X%Q~loCIH$N*zf=V delta 1296 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