diff --git a/src/api/java/appeng/api/definitions/IParts.java b/src/api/java/appeng/api/definitions/IParts.java index 3ecab0c2d..a3d2638ce 100644 --- a/src/api/java/appeng/api/definitions/IParts.java +++ b/src/api/java/appeng/api/definitions/IParts.java @@ -30,103 +30,106 @@ import appeng.api.util.AEColoredItemDefinition; /** * A list of all parts in AE */ -public interface IParts -{ - AEColoredItemDefinition cableSmart(); +public interface IParts { + AEColoredItemDefinition cableSmart(); - AEColoredItemDefinition cableCovered(); + AEColoredItemDefinition cableCovered(); - AEColoredItemDefinition cableGlass(); + AEColoredItemDefinition cableGlass(); - AEColoredItemDefinition cableDenseCovered(); + AEColoredItemDefinition cableDenseCovered(); - AEColoredItemDefinition cableDenseSmart(); + AEColoredItemDefinition cableDenseSmart(); - AEColoredItemDefinition lumenCableSmart(); + AEColoredItemDefinition lumenCableSmart(); - AEColoredItemDefinition lumenCableCovered(); + AEColoredItemDefinition lumenCableCovered(); - AEColoredItemDefinition lumenCableGlass(); + AEColoredItemDefinition lumenCableGlass(); - AEColoredItemDefinition lumenDenseCableSmart(); + AEColoredItemDefinition lumenDenseCableSmart(); - IItemDefinition quartzFiber(); + IItemDefinition quartzFiber(); - IItemDefinition toggleBus(); + IItemDefinition toggleBus(); - IItemDefinition invertedToggleBus(); + IItemDefinition invertedToggleBus(); - IItemDefinition storageBus(); + IItemDefinition storageBus(); - IItemDefinition oreDictStorageBus(); + IItemDefinition oreDictStorageBus(); - IItemDefinition importBus(); + IItemDefinition importBus(); - IItemDefinition exportBus(); + IItemDefinition exportBus(); - IItemDefinition iface(); + IItemDefinition iface(); - IItemDefinition fluidIface(); + IItemDefinition fluidIface(); - IItemDefinition levelEmitter(); + IItemDefinition levelEmitter(); - IItemDefinition annihilationPlane(); + IItemDefinition annihilationPlane(); - IItemDefinition identityAnnihilationPlane(); + IItemDefinition identityAnnihilationPlane(); - IItemDefinition formationPlane(); + IItemDefinition formationPlane(); - IItemDefinition p2PTunnelME(); + IItemDefinition p2PTunnelME(); - IItemDefinition p2PTunnelRedstone(); + IItemDefinition p2PTunnelRedstone(); - IItemDefinition p2PTunnelItems(); + IItemDefinition p2PTunnelItems(); - IItemDefinition p2PTunnelFluids(); + IItemDefinition p2PTunnelFluids(); - IItemDefinition p2PTunnelEU(); + IItemDefinition p2PTunnelEU(); - IItemDefinition p2PTunnelFE(); + IItemDefinition p2PTunnelFE(); - IItemDefinition p2PTunnelGTEU(); + IItemDefinition p2PTunnelGTEU(); - IItemDefinition p2PTunnelLight(); + IItemDefinition p2PTunnelLight(); - // IItemDefinition p2PTunnelOpenComputers(); + // IItemDefinition p2PTunnelOpenComputers(); - IItemDefinition cableAnchor(); + IItemDefinition cableAnchor(); - IItemDefinition monitor(); + IItemDefinition monitor(); - IItemDefinition semiDarkMonitor(); + IItemDefinition semiDarkMonitor(); - IItemDefinition darkMonitor(); + IItemDefinition darkMonitor(); - IItemDefinition interfaceTerminal(); + IItemDefinition interfaceTerminal(); - IItemDefinition patternTerminal(); + IItemDefinition patternTerminal(); - IItemDefinition expandedProcessingPatternTerminal(); + IItemDefinition expandedProcessingPatternTerminal(); - IItemDefinition craftingTerminal(); + IItemDefinition interfaceConfigurationTerminal(); - IItemDefinition terminal(); + IItemDefinition fluidInterfaceConfigurationTerminal(); - IItemDefinition storageMonitor(); + IItemDefinition craftingTerminal(); - IItemDefinition conversionMonitor(); + IItemDefinition terminal(); - IItemDefinition fluidTerminal(); + IItemDefinition storageMonitor(); - IItemDefinition fluidImportBus(); + IItemDefinition conversionMonitor(); - IItemDefinition fluidExportBus(); + IItemDefinition fluidTerminal(); - IItemDefinition fluidStorageBus(); + IItemDefinition fluidImportBus(); - IItemDefinition fluidLevelEmitter(); + IItemDefinition fluidExportBus(); - IItemDefinition fluidAnnihilationPlane(); + IItemDefinition fluidStorageBus(); - IItemDefinition fluidFormationnPlane(); + IItemDefinition fluidLevelEmitter(); + + IItemDefinition fluidAnnihilationPlane(); + + IItemDefinition fluidFormationnPlane(); } diff --git a/src/main/java/appeng/client/gui/implementations/GuiFluidInterfaceConfigurationTerminal.java b/src/main/java/appeng/client/gui/implementations/GuiFluidInterfaceConfigurationTerminal.java new file mode 100644 index 000000000..963818b82 --- /dev/null +++ b/src/main/java/appeng/client/gui/implementations/GuiFluidInterfaceConfigurationTerminal.java @@ -0,0 +1,495 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved. + * + * Applied Energistics 2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Applied Energistics 2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Applied Energistics 2. If not, see . + */ + +package appeng.client.gui.implementations; + + +import appeng.api.AEApi; +import appeng.api.config.ActionItems; +import appeng.api.config.Settings; +import appeng.api.storage.channels.IItemStorageChannel; +import appeng.api.storage.data.IAEFluidStack; +import appeng.client.gui.AEBaseGui; +import appeng.client.gui.widgets.GuiCustomSlot; +import appeng.client.gui.widgets.GuiImgButton; +import appeng.client.gui.widgets.GuiScrollbar; +import appeng.client.gui.widgets.MEGuiTextField; +import appeng.client.me.ClientDCInternalFluidInv; +import appeng.client.me.SlotDisconnected; +import appeng.container.implementations.ContainerFluidInterfaceConfigurationTerminal; +import appeng.container.interfaces.IJEIGhostIngredients; +import appeng.core.localization.GuiText; +import appeng.core.sync.network.NetworkHandler; +import appeng.core.sync.packets.PacketInventoryAction; +import appeng.fluids.client.gui.widgets.GuiFluidSlot; +import appeng.fluids.client.gui.widgets.GuiFluidTank; +import appeng.fluids.container.IFluidSyncContainer; +import appeng.fluids.util.AEFluidStack; +import appeng.helpers.InventoryAction; +import appeng.parts.reporting.PartFluidInterfaceConfigurationTerminal; +import appeng.util.BlockPosUtils; +import appeng.util.Platform; +import appeng.util.item.AEItemStack; +import com.google.common.collect.HashMultimap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import mezz.jei.api.gui.IGhostIngredientHandler; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTUtil; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.TextComponentString; +import net.minecraftforge.common.DimensionManager; +import org.lwjgl.input.Mouse; + +import java.awt.*; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.WeakHashMap; + +import static appeng.client.render.BlockPosHighlighter.hilightBlock; + + +public class GuiFluidInterfaceConfigurationTerminal extends AEBaseGui implements IJEIGhostIngredients { + + private static final int LINES_ON_PAGE = 6; + + // TODO: copied from GuiMEMonitorable. It looks not changed, maybe unneeded? + private final int offsetX = 21; + + private final HashMap byId = new HashMap<>(); + private final HashMultimap byName = HashMultimap.create(); + private final HashMap blockPosHashMap = new HashMap<>(); + private final HashMap guiButtonHashMap = new HashMap<>(); + + private final Map guiFluidTankClientDCInternalFluidInvMap = new Object2ObjectOpenHashMap<>(); + private final Map numUpgradesMap = new HashMap<>(); + private final ArrayList names = new ArrayList<>(); + private final ArrayList lines = new ArrayList<>(); + private final Set matchedStacks = new HashSet<>(); + + private final Map> cachedSearches = new WeakHashMap<>(); + + private boolean refreshList = false; + private MEGuiTextField searchFieldInputs; + private final PartFluidInterfaceConfigurationTerminal partInterfaceTerminal; + private final HashMap dimHashMap = new HashMap<>(); + public Map, Object> mapTargetSlot = new HashMap<>(); + + public GuiFluidInterfaceConfigurationTerminal(final InventoryPlayer inventoryPlayer, final PartFluidInterfaceConfigurationTerminal te) { + super(new ContainerFluidInterfaceConfigurationTerminal(inventoryPlayer, te)); + + this.partInterfaceTerminal = te; + final GuiScrollbar scrollbar = new GuiScrollbar(); + this.setScrollBar(scrollbar); + this.xSize = 208; + this.ySize = 235; + } + + @Override + public void initGui() { + super.initGui(); + + this.getScrollBar().setLeft(189); + this.getScrollBar().setHeight(106); + this.getScrollBar().setTop(31); + + this.searchFieldInputs = new MEGuiTextField(this.fontRenderer, this.guiLeft + Math.max(32, this.offsetX), this.guiTop + 17, 65, 12); + this.searchFieldInputs.setEnableBackgroundDrawing(false); + this.searchFieldInputs.setMaxStringLength(25); + this.searchFieldInputs.setTextColor(0xFFFFFF); + this.searchFieldInputs.setVisible(true); + this.searchFieldInputs.setFocused(false); + + this.searchFieldInputs.setText(partInterfaceTerminal.in); + } + + @Override + public void onGuiClosed() { + partInterfaceTerminal.saveSearchStrings(this.searchFieldInputs.getText().toLowerCase()); + super.onGuiClosed(); + } + + @Override + public void drawFG(final int offsetX, final int offsetY, final int mouseX, final int mouseY) { + this.buttonList.clear(); + + this.fontRenderer.drawString(this.getGuiDisplayName(GuiText.InterfaceConfigurationTerminal.getLocal()), 8, 6, 4210752); + this.fontRenderer.drawString(GuiText.inventory.getLocal(), this.offsetX + 2, this.ySize - 96 + 3, 4210752); + + final int currentScroll = this.getScrollBar().getCurrentScroll(); + + this.guiSlots.removeIf(slot -> slot instanceof GuiFluidTank); + + int offset = 30; + int linesDraw = 0; + for (int x = 0; x < LINES_ON_PAGE && linesDraw < LINES_ON_PAGE && currentScroll + x < this.lines.size(); x++) { + final Object lineObj = this.lines.get(currentScroll + x); + if (lineObj instanceof ClientDCInternalFluidInv) { + final ClientDCInternalFluidInv inv = (ClientDCInternalFluidInv) lineObj; + + GuiButton guiButton = new GuiImgButton(guiLeft + 4, guiTop + offset, Settings.ACTIONS, ActionItems.HIGHLIGHT_INTERFACE); + guiButtonHashMap.put(guiButton, inv); + this.buttonList.add(guiButton); + int extraLines = numUpgradesMap.get(inv); + + for (int row = 0; row < 1 + extraLines && linesDraw < LINES_ON_PAGE; ++row) { + for (int z = 0; z < 5; z++) { + GuiFluidTank tankSlot = new GuiFluidTank(inv.getInventory(), z + (row * 5), z + (row * 5), (z * 18 + 22), offset, 16, 16); + this.guiSlots.add(tankSlot); + guiFluidTankClientDCInternalFluidInvMap.put(tankSlot, inv); + if (this.matchedStacks.contains(inv.getInventory().getFluidInSlot(z + (row * 5)))) { + drawRect(z * 18 + 22, offset, z * 18 + 22 + 16, offset + 16, 0x2A00FF00); + } + } + linesDraw++; + offset += 18; + } + } else if (lineObj instanceof String) { + String name = (String) lineObj; + final int rows = this.byName.get(name).size(); + if (rows > 1) { + name = name + " (" + rows + ')'; + } + + while (name.length() > 2 && this.fontRenderer.getStringWidth(name) > 155) { + name = name.substring(0, name.length() - 1); + } + this.fontRenderer.drawString(name, this.offsetX + 2, 5 + offset, 4210752); + linesDraw++; + offset += 18; + } + } + + if (searchFieldInputs.isMouseIn(mouseX, mouseY)) { + drawTooltip(Mouse.getEventX() * this.width / this.mc.displayWidth - offsetX, mouseY - guiTop, "Inputs OR names"); + } + } + + @Override + protected void mouseClicked(final int xCoord, final int yCoord, final int btn) throws IOException { + this.searchFieldInputs.mouseClicked(xCoord, yCoord, btn); + + if (btn == 1 && this.searchFieldInputs.isMouseIn(xCoord, yCoord)) { + this.searchFieldInputs.setText(""); + this.refreshList(); + } + + for (GuiCustomSlot slot : this.guiSlots) { + if (slot instanceof GuiFluidTank) { + if (this.isPointInRegion(slot.xPos(), slot.yPos(), slot.getWidth(), slot.getHeight(), xCoord, yCoord) && slot.canClick(this.mc.player)) { + NetworkHandler.instance().sendToServer(new PacketInventoryAction(InventoryAction.PICKUP_OR_SET_DOWN, slot.getId(), guiFluidTankClientDCInternalFluidInvMap.get(slot).getId())); + + return; + } + } + } + + super.mouseClicked(xCoord, yCoord, btn); + } + + @Override + protected void actionPerformed(final GuiButton btn) throws IOException { + if (guiButtonHashMap.containsKey(btn)) { + BlockPos blockPos = blockPosHashMap.get(guiButtonHashMap.get(this.selectedButton)); + BlockPos blockPos2 = mc.player.getPosition(); + int playerDim = mc.world.provider.getDimension(); + int interfaceDim = dimHashMap.get(guiButtonHashMap.get(this.selectedButton)); + if (playerDim != interfaceDim) { + try { + mc.player.sendStatusMessage(new TextComponentString("Interface located at dimension: " + interfaceDim + " [" + DimensionManager.getWorld(interfaceDim).provider.getDimensionType().getName() + "] and cant be highlighted"), false); + } catch (Exception e) { + mc.player.sendStatusMessage(new TextComponentString("Interface is located in another dimension and cannot be highlighted"), false); + } + } else { + hilightBlock(blockPos, System.currentTimeMillis() + 500 * BlockPosUtils.getDistance(blockPos, blockPos2), playerDim); + mc.player.sendStatusMessage(new TextComponentString("The interface is now highlighted at " + "X: " + blockPos.getX() + " Y: " + blockPos.getY() + " Z: " + blockPos.getZ()), false); + } + mc.player.closeScreen(); + } + } + + @Override + public void drawBG(final int offsetX, final int offsetY, final int mouseX, final int mouseY) { + this.bindTexture("guis/interfaceconfigurationterminal.png"); + this.drawTexturedModalRect(offsetX, offsetY, 0, 0, this.xSize, this.ySize); + + int offset = 29; + final int ex = this.getScrollBar().getCurrentScroll(); + int linesDraw = 0; + for (int x = 0; x < LINES_ON_PAGE && linesDraw < LINES_ON_PAGE && ex + x < this.lines.size(); x++) { + final Object lineObj = this.lines.get(ex + x); + if (lineObj instanceof ClientDCInternalFluidInv) { + GlStateManager.color(1, 1, 1, 1); + final int width = 9 * 18; + + int extraLines = numUpgradesMap.get(lineObj); + + for (int row = 0; row < 1 + extraLines && linesDraw < LINES_ON_PAGE; ++row) { + this.drawTexturedModalRect(offsetX + 20, offsetY + offset, 20, 170, width, 18); + offset += 18; + linesDraw++; + } + } else { + offset += 18; + linesDraw++; + } + } + + if (this.searchFieldInputs != null) { + this.searchFieldInputs.drawTextBox(); + } + } + + @Override + protected void keyTyped(final char character, final int key) throws IOException { + if (!this.checkHotbarKeys(key)) { + if (character == ' ' && this.searchFieldInputs.getText().isEmpty() && this.searchFieldInputs.isFocused()) { + return; + } + + if (this.searchFieldInputs.textboxKeyTyped(character, key)) { + this.refreshList(); + } else { + super.keyTyped(character, key); + } + } + } + + public void postUpdate(final NBTTagCompound in) { + if (in.getBoolean("clear")) { + this.byId.clear(); + this.refreshList = true; + } + + for (final Object oKey : in.getKeySet()) { + final String key = (String) oKey; + if (key.startsWith("=")) { + try { + final long id = Long.parseLong(key.substring(1), Character.MAX_RADIX); + final NBTTagCompound invData = in.getCompoundTag(key); + final ClientDCInternalFluidInv current = this.getById(id, invData.getLong("sortBy"), invData.getString("un")); + blockPosHashMap.put(current, NBTUtil.getPosFromTag(invData.getCompoundTag("pos"))); + dimHashMap.put(current, invData.getInteger("dim")); + numUpgradesMap.put(current, invData.getInteger("numUpgrades")); + + for (int x = 0; x < current.getInventory().getSlots(); x++) { + final String which = Integer.toString(x); + if (invData.hasKey(which)) { + current.getInventory().setFluidInSlot(x, AEFluidStack.fromNBT(invData.getCompoundTag(which))); + } + } + } catch (final NumberFormatException ignored) { + } + } + } + + if (this.refreshList) { + this.refreshList = false; + // invalid caches on refresh + this.cachedSearches.clear(); + this.refreshList(); + } + } + + /** + * Rebuilds the list of interfaces. + *

+ * Respects a search term if present (ignores case) and adding only matching patterns. + */ + private void refreshList() { + this.byName.clear(); + this.buttonList.clear(); + this.matchedStacks.clear(); + + final String searchFieldInputs = this.searchFieldInputs.getText().toLowerCase(); + + final Set cachedSearch = this.getCacheForSearchTerm(searchFieldInputs); + final boolean rebuild = cachedSearch.isEmpty(); + + for (final ClientDCInternalFluidInv entry : this.byId.values()) { + // ignore inventory if not doing a full rebuild and cache already marks it as miss. + if (!rebuild && !cachedSearch.contains(entry)) { + continue; + } + + // Shortcut to skip any filter if search term is ""/empty + + boolean found = searchFieldInputs.isEmpty(); + + // Search if the current inventory holds a pattern containing the search term. + if (!found) { + int slot = 0; + for (int i = 0; i < entry.getInventory().getSlots(); i++) { + if (slot > 8 + numUpgradesMap.get(entry) * 9) { + break; + } + IAEFluidStack fs = entry.getInventory().getFluidInSlot(i); + if (this.fluidStackMatchesSearchTerm(fs, searchFieldInputs)) { + found = true; + matchedStacks.add(fs); + } + slot++; + } + } + // if found, filter skipped or machine name matching the search term, add it + if (found || entry.getName().toLowerCase().contains(searchFieldInputs)) { + this.byName.put(entry.getName(), entry); + cachedSearch.add(entry); + } else { + cachedSearch.remove(entry); + } + } + + this.names.clear(); + this.names.addAll(this.byName.keySet()); + + Collections.sort(this.names); + + this.lines.clear(); + this.lines.ensureCapacity(this.getMaxRows()); + + for (final String n : this.names) { + this.lines.add(n); + + final ArrayList clientInventories = new ArrayList<>(); + clientInventories.addAll(this.byName.get(n)); + + Collections.sort(clientInventories); + this.lines.addAll(clientInventories); + } + + this.getScrollBar().setRange(0, this.lines.size() - 1, 1); + } + + private boolean fluidStackMatchesSearchTerm(final IAEFluidStack iaeFluidStack, final String searchTerm) { + if (iaeFluidStack == null) { + return false; + } + + boolean foundMatchingItemStack = false; + + final String displayName = Platform + .getItemDisplayName(AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class).createStack(iaeFluidStack)) + .toLowerCase(); + + for (String term : searchTerm.split(" ")) { + if (term.length() > 1 && (term.startsWith("-") || term.startsWith("!"))) { + term = term.substring(1); + if (displayName.contains(term)) { + return false; + } + } else if (displayName.contains(term)) { + foundMatchingItemStack = true; + } + } + return foundMatchingItemStack; + } + + /** + * Tries to retrieve a cache for a with search term as keyword. + *

+ * If this cache should be empty, it will populate it with an earlier cache if available or at least the cache for + * the empty string. + * + * @param searchTerm the corresponding search + * @return a Set matching a superset of the search term + */ + private Set getCacheForSearchTerm(final String searchTerm) { + if (!this.cachedSearches.containsKey(searchTerm)) { + this.cachedSearches.put(searchTerm, new HashSet<>()); + } + + final Set cache = this.cachedSearches.get(searchTerm); + + if (cache.isEmpty() && searchTerm.length() > 1) { + cache.addAll(this.getCacheForSearchTerm(searchTerm.substring(0, searchTerm.length() - 1))); + return cache; + } + + return cache; + } + + /** + * The max amount of unique names and each inv row. Not affected by the filtering. + * + * @return max amount of unique names and each inv row + */ + private int getMaxRows() { + return this.names.size() + this.byId.size(); + } + + private ClientDCInternalFluidInv getById(final long id, final long sortBy, final String string) { + ClientDCInternalFluidInv o = this.byId.get(id); + + if (o == null) { + this.byId.put(id, o = new ClientDCInternalFluidInv(5, id, sortBy, string, 64)); + this.refreshList = true; + } + + return o; + } + + @Override + public List> getPhantomTargets(Object ingredient) { + if (!(ingredient instanceof ItemStack)) { + return Collections.emptyList(); + } + List> targets = new ArrayList<>(); + for (Slot slot : this.inventorySlots.inventorySlots) { + if (slot instanceof SlotDisconnected) { + ItemStack itemStack = (ItemStack) ingredient; + IGhostIngredientHandler.Target target = new IGhostIngredientHandler.Target() { + @Override + public Rectangle getArea() { + return new Rectangle(getGuiLeft() + slot.xPos, getGuiTop() + slot.yPos, 16, 16); + } + + @Override + public void accept(Object ingredient) { + final PacketInventoryAction p; + try { + p = new PacketInventoryAction(InventoryAction.PLACE_JEI_GHOST_ITEM, (SlotDisconnected) slot, AEItemStack.fromItemStack(itemStack)); + NetworkHandler.instance().sendToServer(p); + + } catch (IOException e) { + e.printStackTrace(); + } + } + }; + targets.add(target); + mapTargetSlot.putIfAbsent(target, slot); + } + } + return targets; + } + + @Override + public Map, Object> getFakeSlotTargetMap() { + return IJEIGhostIngredients.super.getFakeSlotTargetMap(); + } +} diff --git a/src/main/java/appeng/client/me/ClientDCInternalFluidInv.java b/src/main/java/appeng/client/me/ClientDCInternalFluidInv.java new file mode 100644 index 000000000..f129a6263 --- /dev/null +++ b/src/main/java/appeng/client/me/ClientDCInternalFluidInv.java @@ -0,0 +1,72 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved. + * + * Applied Energistics 2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Applied Energistics 2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Applied Energistics 2. If not, see . + */ + +package appeng.client.me; + + +import appeng.fluids.util.AEFluidInventory; +import appeng.fluids.util.IAEFluidTank; +import appeng.tile.inventory.AppEngInternalInventory; +import net.minecraft.util.text.translation.I18n; + +import javax.annotation.Nonnull; + + +public class ClientDCInternalFluidInv implements Comparable { + + private final String unlocalizedName; + private final IAEFluidTank inventory; + + private final long id; + private final long sortBy; + + public ClientDCInternalFluidInv(final int size, final long id, final long sortBy, final String unlocalizedName) { + this.inventory = new AEFluidInventory(null, size, 1); + this.unlocalizedName = unlocalizedName; + this.id = id; + this.sortBy = sortBy; + } + + public ClientDCInternalFluidInv(final int size, final long id, final long sortBy, final String unlocalizedName, int stackSize) { + this.inventory = new AEFluidInventory(null, size, stackSize); + this.unlocalizedName = unlocalizedName; + this.id = id; + this.sortBy = sortBy; + } + + public String getName() { + final String s = I18n.translateToLocal(this.unlocalizedName + ".name"); + if (s.equals(this.unlocalizedName + ".name")) { + return I18n.translateToLocal(this.unlocalizedName); + } + return s; + } + + @Override + public int compareTo(@Nonnull final ClientDCInternalFluidInv o) { + return Long.compare(this.sortBy, o.sortBy); + } + + public IAEFluidTank getInventory() { + return this.inventory; + } + + public long getId() { + return this.id; + } +} diff --git a/src/main/java/appeng/container/implementations/ContainerFluidInterfaceConfigurationTerminal.java b/src/main/java/appeng/container/implementations/ContainerFluidInterfaceConfigurationTerminal.java new file mode 100644 index 000000000..971f5cb62 --- /dev/null +++ b/src/main/java/appeng/container/implementations/ContainerFluidInterfaceConfigurationTerminal.java @@ -0,0 +1,302 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved. + * + * Applied Energistics 2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Applied Energistics 2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Applied Energistics 2. If not, see . + */ + +package appeng.container.implementations; + + +import appeng.api.config.Settings; +import appeng.api.config.YesNo; +import appeng.api.networking.IGrid; +import appeng.api.networking.IGridNode; +import appeng.api.networking.security.IActionHost; +import appeng.api.storage.data.IAEFluidStack; +import appeng.container.AEBaseContainer; +import appeng.core.sync.network.NetworkHandler; +import appeng.core.sync.packets.PacketCompressedNBT; +import appeng.core.sync.packets.PacketTargetFluidStack; +import appeng.fluids.helper.DualityFluidInterface; +import appeng.fluids.helper.IFluidInterfaceHost; +import appeng.fluids.parts.PartFluidInterface; +import appeng.fluids.tile.TileFluidInterface; +import appeng.fluids.util.AEFluidInventory; +import appeng.fluids.util.AEFluidStack; +import appeng.fluids.util.IAEFluidTank; +import appeng.helpers.InventoryAction; +import appeng.parts.misc.PartInterface; +import appeng.parts.reporting.PartFluidInterfaceConfigurationTerminal; +import appeng.tile.misc.TileInterface; +import appeng.util.Platform; +import appeng.util.helpers.ItemHandlerUtil; +import appeng.util.inv.WrapperRangeItemHandler; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTUtil; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandlerItem; +import net.minecraftforge.items.IItemHandler; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + + +public final class ContainerFluidInterfaceConfigurationTerminal extends AEBaseContainer { + + /** + * this stuff is all server side.. + */ + + private static long autoBase = Long.MIN_VALUE; + private final Map diList = new HashMap<>(); + private final Map byId = new HashMap<>(); + private IGrid grid; + private NBTTagCompound data = new NBTTagCompound(); + private IAEFluidStack clientRequestedTargetFluid; + + public ContainerFluidInterfaceConfigurationTerminal(final InventoryPlayer ip, final PartFluidInterfaceConfigurationTerminal anchor) { + super(ip, anchor); + + if (Platform.isServer()) { + this.grid = anchor.getActionableNode().getGrid(); + } + + this.bindPlayerInventory(ip, 14, 235 - /* height of player inventory */82); + } + + @Override + public void detectAndSendChanges() { + if (Platform.isClient()) { + return; + } + + super.detectAndSendChanges(); + + if (this.grid == null) { + return; + } + + int total = 0; + boolean missing = false; + + final IActionHost host = this.getActionHost(); + if (host != null) { + final IGridNode agn = host.getActionableNode(); + if (agn != null && agn.isActive()) { + for (final IGridNode gn : this.grid.getMachines(TileFluidInterface.class)) { + if (gn.isActive()) { + final IFluidInterfaceHost ih = (IFluidInterfaceHost) gn.getMachine(); + if (ih.getDualityFluidInterface().getConfigManager().getSetting(Settings.INTERFACE_TERMINAL) == YesNo.NO) { + continue; + } + + final FluidConfigTracker t = this.diList.get(ih); + + if (t == null) { + missing = true; + } else { + final DualityFluidInterface dual = ih.getDualityFluidInterface(); + if (!t.unlocalizedName.equals(dual.getTermName())) { + missing = true; + } + } + + total++; + } + } + + for (final IGridNode gn : this.grid.getMachines(PartFluidInterface.class)) { + if (gn.isActive()) { + final IFluidInterfaceHost ih = (IFluidInterfaceHost) gn.getMachine(); + if (ih.getDualityFluidInterface().getConfigManager().getSetting(Settings.INTERFACE_TERMINAL) == YesNo.NO) { + continue; + } + + final FluidConfigTracker t = this.diList.get(ih); + + if (t == null) { + missing = true; + } else { + final DualityFluidInterface dual = ih.getDualityFluidInterface(); + if (!t.unlocalizedName.equals(dual.getTermName())) { + missing = true; + } + } + + total++; + } + } + } + } + + if (total != this.diList.size() || missing) { + this.regenList(this.data); + } else { + for (final Entry en : this.diList.entrySet()) { + final FluidConfigTracker inv = en.getValue(); + for (int x = 0; x < inv.server.getSlots(); x++) { + if ((inv.server.getFluidInSlot(x) == null && inv.client.getFluidInSlot(x) != null) || + (inv.server.getFluidInSlot(x) != null && !inv.server.getFluidInSlot(x).equals(inv.client.getFluidInSlot(x)))) { + this.addFluids(this.data, inv, x, 1); + } + } + } + } + + if (!this.data.hasNoTags()) { + try { + NetworkHandler.instance().sendTo(new PacketCompressedNBT(this.data), (EntityPlayerMP) this.getPlayerInv().player); + } catch (final IOException e) { + // :P + } + + this.data = new NBTTagCompound(); + } + } + + public FluidConfigTracker getSlotByID(long id) { + return this.byId.get(id); + } + + @Override + public void doAction(final EntityPlayerMP player, final InventoryAction action, final int slot, final long id) { + final FluidConfigTracker inv = this.byId.get(id); + if (inv != null) { + ItemStack itemInHand = player.inventory.getItemStack(); + IFluidHandlerItem c = itemInHand.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null); + if (c != null) { + FluidStack fs = c.drain(Integer.MAX_VALUE, false); + if (fs != null) { + inv.server.setFluidInSlot(slot, AEFluidStack.fromFluidStack(fs)); + return; + } + return; + } + inv.server.setFluidInSlot(slot, null); + + this.updateHeld(player); + } + } + + public void setTargetStack(final IAEFluidStack stack) { + if (Platform.isClient()) { + if (stack == null && this.clientRequestedTargetFluid == null) { + return; + } + if (stack != null && this.clientRequestedTargetFluid != null && stack.getFluidStack().isFluidEqual(this.clientRequestedTargetFluid.getFluidStack())) { + return; + } + NetworkHandler.instance().sendToServer(new PacketTargetFluidStack((AEFluidStack) stack)); + } + + this.clientRequestedTargetFluid = stack == null ? null : stack.copy(); + } + + private void regenList(final NBTTagCompound data) { + this.byId.clear(); + this.diList.clear(); + + final IActionHost host = this.getActionHost(); + if (host != null) { + final IGridNode agn = host.getActionableNode(); + if (agn != null && agn.isActive()) { + for (final IGridNode gn : this.grid.getMachines(TileFluidInterface.class)) { + final IFluidInterfaceHost ih = (IFluidInterfaceHost) gn.getMachine(); + final DualityFluidInterface dual = ih.getDualityFluidInterface(); + if (gn.isActive() && dual.getConfigManager().getSetting(Settings.INTERFACE_TERMINAL) == YesNo.YES) { + this.diList.put(ih, new FluidConfigTracker(dual, (AEFluidInventory) dual.getConfig(), dual.getTermName())); + } + } + + for (final IGridNode gn : this.grid.getMachines(PartFluidInterface.class)) { + final IFluidInterfaceHost ih = (IFluidInterfaceHost) gn.getMachine(); + final DualityFluidInterface dual = ih.getDualityFluidInterface(); + if (gn.isActive() && dual.getConfigManager().getSetting(Settings.INTERFACE_TERMINAL) == YesNo.YES) { + this.diList.put(ih, new FluidConfigTracker(dual, (AEFluidInventory) dual.getConfig(), dual.getTermName())); + } + } + } + } + + data.setBoolean("clear", true); + + for (final Entry en : this.diList.entrySet()) { + final FluidConfigTracker inv = en.getValue(); + this.byId.put(inv.which, inv); + this.addFluids(data, inv, 0, inv.server.getSlots()); + } + } + + private void addFluids(final NBTTagCompound data, final FluidConfigTracker inv, final int offset, final int length) { + final String name = '=' + Long.toString(inv.which, Character.MAX_RADIX); + final NBTTagCompound tag = data.getCompoundTag(name); + + if (tag.hasNoTags()) { + tag.setLong("sortBy", inv.sortBy); + tag.setString("un", inv.unlocalizedName); + tag.setTag("pos", NBTUtil.createPosTag(inv.pos)); + tag.setInteger("dim", inv.dim); + } + + for (int x = 0; x < length; x++) { + final NBTTagCompound fluidNBT = new NBTTagCompound(); + + final IAEFluidStack iaeFluidStack = inv.server.getFluidInSlot(x + offset); + + // "update" client side. + inv.client.setFluidInSlot(x + offset, iaeFluidStack == null ? null : iaeFluidStack.copy()); + + if (iaeFluidStack != null) { + iaeFluidStack.writeToNBT(fluidNBT); + } + + tag.setTag(Integer.toString(x + offset), fluidNBT); + } + + data.setTag(name, tag); + } + + public static class FluidConfigTracker { + + private final long sortBy; + private final long which = autoBase++; + private final String unlocalizedName; + private final IAEFluidTank client; + private final IAEFluidTank server; + private final BlockPos pos; + private final int dim; + + public FluidConfigTracker(final DualityFluidInterface dual, final AEFluidInventory configSlots, final String unlocalizedName) { + this.server = configSlots; + this.client = new AEFluidInventory(null, this.server.getSlots()); + this.unlocalizedName = unlocalizedName; + this.sortBy = dual.getSortValue(); + this.pos = dual.getLocation().getPos(); + this.dim = dual.getLocation().getWorld().provider.getDimension(); + } + + public IAEFluidTank getServer() { + return server; + } + } +} diff --git a/src/main/java/appeng/core/api/definitions/ApiParts.java b/src/main/java/appeng/core/api/definitions/ApiParts.java index 626232226..d146716ab 100644 --- a/src/main/java/appeng/core/api/definitions/ApiParts.java +++ b/src/main/java/appeng/core/api/definitions/ApiParts.java @@ -80,6 +80,7 @@ public final class ApiParts implements IParts { private final IItemDefinition patternTerminal; private final IItemDefinition expandedProcessingPatternTerminal; private final IItemDefinition interfaceConfigurationTerminal; + private final IItemDefinition fluidInterfaceConfigurationTerminal; private final IItemDefinition craftingTerminal; private final IItemDefinition terminal; private final IItemDefinition storageMonitor; @@ -141,6 +142,7 @@ public final class ApiParts implements IParts { this.patternTerminal = new DamagedItemDefinition("part.terminal.pattern", itemPart.createPart(PartType.PATTERN_TERMINAL)); this.expandedProcessingPatternTerminal = new DamagedItemDefinition("part.terminal.expanded_processing_pattern", itemPart.createPart(PartType.EXPANDED_PROCESSING_PATTERN_TERMINAL)); this.interfaceConfigurationTerminal = new DamagedItemDefinition("part.terminal.interface_configuration_terminal", itemPart.createPart(PartType.INTERFACE_CONFIGURATION_TERMINAL)); + this.fluidInterfaceConfigurationTerminal = new DamagedItemDefinition("part.terminal.fluid_interface_configuration_terminal", itemPart.createPart(PartType.FLUID_INTERFACE_CONFIGURATION_TERMINAL)); this.craftingTerminal = new DamagedItemDefinition("part.terminal.crafting", itemPart.createPart(PartType.CRAFTING_TERMINAL)); this.terminal = new DamagedItemDefinition("part.terminal", itemPart.createPart(PartType.TERMINAL)); this.storageMonitor = new DamagedItemDefinition("part.monitor.storage", itemPart.createPart(PartType.STORAGE_MONITOR)); @@ -359,6 +361,16 @@ public final class ApiParts implements IParts { return this.expandedProcessingPatternTerminal; } + @Override + public IItemDefinition interfaceConfigurationTerminal() { + return this.interfaceConfigurationTerminal; + } + + @Override + public IItemDefinition fluidInterfaceConfigurationTerminal() { + return this.fluidInterfaceConfigurationTerminal; + } + @Override public IItemDefinition craftingTerminal() { return this.craftingTerminal; diff --git a/src/main/java/appeng/core/sync/GuiBridge.java b/src/main/java/appeng/core/sync/GuiBridge.java index 64fcb6c26..48fd3bdad 100644 --- a/src/main/java/appeng/core/sync/GuiBridge.java +++ b/src/main/java/appeng/core/sync/GuiBridge.java @@ -170,6 +170,7 @@ public enum GuiBridge implements IGuiHandler { GUI_CRAFTING_STATUS(ContainerCraftingStatus.class, ITerminalHost.class, GuiHostType.ITEM_OR_WORLD, SecurityPermissions.CRAFT), GUI_INTERFACE_CONFIGURATION_TERMINAL(ContainerInterfaceConfigurationTerminal.class, PartInterfaceConfigurationTerminal.class, GuiHostType.WORLD, SecurityPermissions.BUILD), + GUI_FLUID_INTERFACE_CONFIGURATION_TERMINAL(ContainerFluidInterfaceConfigurationTerminal.class, PartFluidInterfaceConfigurationTerminal.class, GuiHostType.WORLD, SecurityPermissions.BUILD), GUI_RENAMER(ContainerRenamer.class, ICustomNameObject.class, GuiHostType.WORLD, SecurityPermissions.BUILD); diff --git a/src/main/java/appeng/core/sync/packets/PacketCompressedNBT.java b/src/main/java/appeng/core/sync/packets/PacketCompressedNBT.java index 9bdec09ad..1fc735578 100644 --- a/src/main/java/appeng/core/sync/packets/PacketCompressedNBT.java +++ b/src/main/java/appeng/core/sync/packets/PacketCompressedNBT.java @@ -19,6 +19,7 @@ package appeng.core.sync.packets; +import appeng.client.gui.implementations.GuiFluidInterfaceConfigurationTerminal; import appeng.client.gui.implementations.GuiInterfaceConfigurationTerminal; import appeng.client.gui.implementations.GuiInterfaceTerminal; import appeng.core.sync.AppEngPacket; @@ -99,6 +100,8 @@ public class PacketCompressedNBT extends AppEngPacket { ((GuiInterfaceTerminal) gs).postUpdate(this.in); } else if (gs instanceof GuiInterfaceConfigurationTerminal) { ((GuiInterfaceConfigurationTerminal) gs).postUpdate(this.in); + } else if (gs instanceof GuiFluidInterfaceConfigurationTerminal) { + ((GuiFluidInterfaceConfigurationTerminal) gs).postUpdate(this.in); } } } diff --git a/src/main/java/appeng/core/sync/packets/PacketTargetFluidStack.java b/src/main/java/appeng/core/sync/packets/PacketTargetFluidStack.java index d978b4c52..35d888226 100644 --- a/src/main/java/appeng/core/sync/packets/PacketTargetFluidStack.java +++ b/src/main/java/appeng/core/sync/packets/PacketTargetFluidStack.java @@ -19,6 +19,7 @@ package appeng.core.sync.packets; +import appeng.container.implementations.ContainerFluidInterfaceConfigurationTerminal; import appeng.core.AELog; import appeng.core.sync.AppEngPacket; import appeng.core.sync.network.INetworkInfo; @@ -75,6 +76,8 @@ public class PacketTargetFluidStack extends AppEngPacket { ((ContainerFluidTerminal) player.openContainer).setTargetStack(this.stack); } else if (player.openContainer instanceof ContainerFluidInterface) { ((ContainerFluidInterface) player.openContainer).setTargetStack(this.stack); + } else if (player.openContainer instanceof ContainerFluidInterfaceConfigurationTerminal) { + ((ContainerFluidInterfaceConfigurationTerminal) player.openContainer).setTargetStack(this.stack); } } } diff --git a/src/main/java/appeng/fluids/client/gui/widgets/GuiFluidTank.java b/src/main/java/appeng/fluids/client/gui/widgets/GuiFluidTank.java index 6590babc8..de37ef87f 100644 --- a/src/main/java/appeng/fluids/client/gui/widgets/GuiFluidTank.java +++ b/src/main/java/appeng/fluids/client/gui/widgets/GuiFluidTank.java @@ -127,9 +127,9 @@ public class GuiFluidTank extends GuiCustomSlot implements ITooltip { public void slotClicked(ItemStack clickStack, final int mouseButton) { if (getFluidStack() != null) { - NetworkHandler.instance().sendToServer(new PacketInventoryAction(InventoryAction.FILL_ITEM, slot, 0)); + NetworkHandler.instance().sendToServer(new PacketInventoryAction(InventoryAction.FILL_ITEM, slot, id)); } else { - NetworkHandler.instance().sendToServer(new PacketInventoryAction(InventoryAction.EMPTY_ITEM, slot, 0)); + NetworkHandler.instance().sendToServer(new PacketInventoryAction(InventoryAction.EMPTY_ITEM, slot, id)); } } diff --git a/src/main/java/appeng/fluids/helper/DualityFluidInterface.java b/src/main/java/appeng/fluids/helper/DualityFluidInterface.java index 8ca574498..17e8e4491 100644 --- a/src/main/java/appeng/fluids/helper/DualityFluidInterface.java +++ b/src/main/java/appeng/fluids/helper/DualityFluidInterface.java @@ -21,9 +21,13 @@ package appeng.fluids.helper; import appeng.api.AEApi; import appeng.api.config.Actionable; +import appeng.api.config.Settings; import appeng.api.config.Upgrades; +import appeng.api.config.YesNo; import appeng.api.implementations.IUpgradeableHost; +import appeng.api.implementations.tiles.ICraftingMachine; import appeng.api.networking.GridFlags; +import appeng.api.networking.IGrid; import appeng.api.networking.IGridNode; import appeng.api.networking.energy.IEnergySource; import appeng.api.networking.security.IActionHost; @@ -46,7 +50,10 @@ import appeng.core.settings.TickRates; import appeng.fluids.util.AEFluidInventory; import appeng.fluids.util.IAEFluidInventory; import appeng.fluids.util.IAEFluidTank; +import appeng.helpers.ICustomNameObject; +import appeng.helpers.IInterfaceHost; import appeng.me.GridAccessException; +import appeng.me.GridNodeCollection; import appeng.me.helpers.AENetworkProxy; import appeng.me.helpers.MachineSource; import appeng.me.storage.MEMonitorIFluidHandler; @@ -54,24 +61,40 @@ import appeng.me.storage.MEMonitorPassThrough; import appeng.me.storage.NullInventory; import appeng.util.ConfigManager; import appeng.util.IConfigManagerHost; +import appeng.util.InventoryAdaptor; import appeng.util.Platform; +import gregtech.api.block.machines.BlockMachine; +import gregtech.api.metatileentity.MetaTileEntity; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.init.Items; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fml.common.Loader; import net.minecraftforge.items.IItemHandler; +import java.util.Collection; +import java.util.EnumSet; +import java.util.HashSet; import java.util.Optional; public class DualityFluidInterface implements IGridTickable, IStorageMonitorable, IAEFluidInventory, IUpgradeableHost, IConfigManagerHost, IConfigurableFluidInventory { public static final int NUMBER_OF_TANKS = 6; public static final int TANK_CAPACITY = Fluid.BUCKET_VOLUME * 4; - + private static final Collection BAD_BLOCKS = new HashSet<>(100); private final ConfigManager cm = new ConfigManager(this); private final AENetworkProxy gridProxy; private final IFluidInterfaceHost iHost; @@ -93,6 +116,9 @@ public class DualityFluidInterface implements IGridTickable, IStorageMonitorable public DualityFluidInterface(final AENetworkProxy networkProxy, final IFluidInterfaceHost ih) { this.gridProxy = networkProxy; this.gridProxy.setFlags(GridFlags.REQUIRE_CHANNEL); + + this.cm.registerSetting(Settings.INTERFACE_TERMINAL, YesNo.YES); + this.iHost = ih; this.mySource = new MachineSource(this.iHost); @@ -192,6 +218,90 @@ public class DualityFluidInterface implements IGridTickable, IStorageMonitorable return new DimensionalCoord(this.iHost.getTileEntity()); } + private boolean sameGrid(final IGrid grid) throws GridAccessException { + return grid == this.gridProxy.getGrid(); + } + + public String getTermName() { + final TileEntity hostTile = this.iHost.getTileEntity(); + final World hostWorld = hostTile.getWorld(); + + if (((ICustomNameObject) this.iHost).hasCustomInventoryName()) { + return ((ICustomNameObject) this.iHost).getCustomInventoryName(); + } + + final EnumSet possibleDirections = this.iHost.getTargets(); + for (final EnumFacing direction : possibleDirections) { + final BlockPos targ = hostTile.getPos().offset(direction); + final TileEntity directedTile = hostWorld.getTileEntity(targ); + + if (directedTile == null) { + continue; + } + + if (directedTile instanceof IFluidInterfaceHost) { + try { + if (((IFluidInterfaceHost) directedTile).getDualityFluidInterface().sameGrid(this.gridProxy.getGrid())) { + continue; + } + } catch (final GridAccessException e) { + continue; + } + } + + final InventoryAdaptor adaptor = InventoryAdaptor.getAdaptor(directedTile, direction.getOpposite()); + if (directedTile instanceof ICraftingMachine || adaptor != null) { + if (adaptor != null && !adaptor.hasSlots()) { + continue; + } + + final IBlockState directedBlockState = hostWorld.getBlockState(targ); + final Block directedBlock = directedBlockState.getBlock(); + ItemStack what = new ItemStack(directedBlock, 1, directedBlock.getMetaFromState(directedBlockState)); + + if (Loader.isModLoaded("gregtech") && directedBlock instanceof BlockMachine) { + MetaTileEntity metaTileEntity = Platform.getMetaTileEntity(directedTile.getWorld(), directedTile.getPos()); + if (metaTileEntity != null) { + return metaTileEntity.getMetaFullName(); + } + } + + try { + Vec3d from = new Vec3d(hostTile.getPos().getX() + 0.5, hostTile.getPos().getY() + 0.5, hostTile.getPos().getZ() + 0.5); + from = from.addVector(direction.getFrontOffsetX() * 0.501, direction.getFrontOffsetY() * 0.501, direction.getFrontOffsetZ() * 0.501); + final Vec3d to = from.addVector(direction.getFrontOffsetX(), direction.getFrontOffsetY(), direction.getFrontOffsetZ()); + final RayTraceResult mop = hostWorld.rayTraceBlocks(from, to, true); + if (mop != null && !BAD_BLOCKS.contains(directedBlock)) { + if (mop.getBlockPos().equals(directedTile.getPos())) { + final ItemStack g = directedBlock.getPickBlock(directedBlockState, mop, hostWorld, directedTile.getPos(), null); + if (!g.isEmpty()) { + what = g; + } + } + } + } catch (final Throwable t) { + BAD_BLOCKS.add(directedBlock); // nope! + } + + if (what.getItem() != Items.AIR) { + return what.getItem().getItemStackDisplayName(what); + } + + final Item item = Item.getItemFromBlock(directedBlock); + if (item == Items.AIR) { + return directedBlock.getUnlocalizedName(); + } + } + } + + return "Nothing"; + } + + public long getSortValue() { + final TileEntity te = this.iHost.getTileEntity(); + return (te.getPos().getZ() << 24) ^ (te.getPos().getX() << 8) ^ te.getPos().getY(); + } + public boolean hasCapability(Capability capabilityClass, EnumFacing facing) { return capabilityClass == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY || capabilityClass == Capabilities.STORAGE_MONITORABLE_ACCESSOR; } diff --git a/src/main/java/appeng/items/parts/PartType.java b/src/main/java/appeng/items/parts/PartType.java index 4645103c6..3e54527fe 100644 --- a/src/main/java/appeng/items/parts/PartType.java +++ b/src/main/java/appeng/items/parts/PartType.java @@ -229,7 +229,9 @@ public enum PartType { INTERFACE_TERMINAL(480, "interface_terminal", EnumSet.of(AEFeature.INTERFACE_TERMINAL), EnumSet.noneOf(IntegrationType.class), PartInterfaceTerminal.class), FLUID_TERMINAL(520, "fluid_terminal", EnumSet.of(AEFeature.FLUID_TERMINAL), EnumSet.noneOf(IntegrationType.class), PartFluidTerminal.class), - INTERFACE_CONFIGURATION_TERMINAL(521, "interface_configuration_terminal", EnumSet.of(AEFeature.INTERFACE_TERMINAL), EnumSet.noneOf(IntegrationType.class), PartInterfaceConfigurationTerminal.class); + INTERFACE_CONFIGURATION_TERMINAL(521, "interface_configuration_terminal", EnumSet.of(AEFeature.INTERFACE_TERMINAL), EnumSet.noneOf(IntegrationType.class), PartInterfaceConfigurationTerminal.class), + FLUID_INTERFACE_CONFIGURATION_TERMINAL(522, "interface_configuration_terminal", EnumSet.of(AEFeature.INTERFACE_TERMINAL), EnumSet.noneOf(IntegrationType.class), PartFluidInterfaceConfigurationTerminal.class); + private final int baseDamage; private final Set features; diff --git a/src/main/java/appeng/parts/reporting/PartFluidInterfaceConfigurationTerminal.java b/src/main/java/appeng/parts/reporting/PartFluidInterfaceConfigurationTerminal.java new file mode 100644 index 000000000..3c081cc5d --- /dev/null +++ b/src/main/java/appeng/parts/reporting/PartFluidInterfaceConfigurationTerminal.java @@ -0,0 +1,69 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved. + * + * Applied Energistics 2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Applied Energistics 2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Applied Energistics 2. If not, see . + */ + +package appeng.parts.reporting; + + +import appeng.api.parts.IPartModel; +import appeng.core.AppEng; +import appeng.core.sync.GuiBridge; +import appeng.items.parts.PartModels; +import appeng.parts.PartModel; +import appeng.util.Platform; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumHand; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.Vec3d; + + +public class PartFluidInterfaceConfigurationTerminal extends AbstractPartDisplay { + + @PartModels + public static final ResourceLocation MODEL_OFF = new ResourceLocation(AppEng.MOD_ID, "part/interface_configuration_terminal_off"); + @PartModels + public static final ResourceLocation MODEL_ON = new ResourceLocation(AppEng.MOD_ID, "part/interface_configuration_terminal_on"); + + public static final IPartModel MODELS_OFF = new PartModel(MODEL_BASE, MODEL_OFF, MODEL_STATUS_OFF); + public static final IPartModel MODELS_ON = new PartModel(MODEL_BASE, MODEL_ON, MODEL_STATUS_ON); + public static final IPartModel MODELS_HAS_CHANNEL = new PartModel(MODEL_BASE, MODEL_ON, MODEL_STATUS_HAS_CHANNEL); + public String in = ""; + + public PartFluidInterfaceConfigurationTerminal(final ItemStack is) { + super(is); + } + + @Override + public boolean onPartActivate(final EntityPlayer player, final EnumHand hand, final Vec3d pos) { + if (!super.onPartActivate(player, hand, pos)) { + if (Platform.isServer()) { + Platform.openGUI(player, this.getHost().getTile(), this.getSide(), GuiBridge.GUI_FLUID_INTERFACE_CONFIGURATION_TERMINAL); + } + } + return true; + } + + @Override + public IPartModel getStaticModels() { + return this.selectModel(MODELS_OFF, MODELS_ON, MODELS_HAS_CHANNEL); + } + + public void saveSearchStrings(String in) { + this.in = in; + } +}