diff --git a/dependencies.gradle b/dependencies.gradle index e086ce83e2a..83f3a24cc05 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -5,7 +5,7 @@ dependencies { compile('com.github.GTNewHorizons:NotEnoughItems:2.2.33-GTNH:dev') compile('curse.maven:cofh-core-69162:2388751') - compileOnly('com.github.GTNewHorizons:BuildCraft:7.1.27:dev') {transitive = false} + compile('com.github.GTNewHorizons:BuildCraft:7.1.27:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:ForgeMultipart:1.2.8:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:GT5-Unofficial:5.09.41.18:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:Jabba:1.2.21:dev') {transitive = false} diff --git a/src/main/java/appeng/api/config/TunnelType.java b/src/main/java/appeng/api/config/TunnelType.java index 116b3e5242c..dfd6df0eb80 100644 --- a/src/main/java/appeng/api/config/TunnelType.java +++ b/src/main/java/appeng/api/config/TunnelType.java @@ -34,5 +34,6 @@ public enum TunnelType { BUNDLED_REDSTONE, // Bundled Redstone Tunnel COMPUTER_MESSAGE, // Computer Message Tunnel PRESSURE, // PneumaticCraft Tunnel - GT_POWER // GregTech EU Tunnel + GT_POWER, // GregTech EU Tunnel + ME_INTERFACE } diff --git a/src/main/java/appeng/api/definitions/IParts.java b/src/main/java/appeng/api/definitions/IParts.java index 673b8652de2..a7ca2328c66 100644 --- a/src/main/java/appeng/api/definitions/IParts.java +++ b/src/main/java/appeng/api/definitions/IParts.java @@ -114,4 +114,6 @@ public interface IParts { IItemDefinition patternTerminalEx(); IItemDefinition p2PTunnelGregtech(); + + IItemDefinition p2PTunnelMEInterface(); } diff --git a/src/main/java/appeng/client/gui/implementations/GuiInterface.java b/src/main/java/appeng/client/gui/implementations/GuiInterface.java index 4d69c2476f9..09de8d7456f 100644 --- a/src/main/java/appeng/client/gui/implementations/GuiInterface.java +++ b/src/main/java/appeng/client/gui/implementations/GuiInterface.java @@ -92,6 +92,8 @@ public void drawFG(final int offsetX, final int offsetY, final int mouseX, final @Override protected String getBackground() { switch (((ContainerInterface) this.cvb).getPatternCapacityCardsInstalled()) { + case -1: + return "guis/interfacenone.png"; case 1: return "guis/interface2.png"; case 2: diff --git a/src/main/java/appeng/container/implementations/ContainerInterface.java b/src/main/java/appeng/container/implementations/ContainerInterface.java index 88c36a7c6c2..56f73048c6c 100644 --- a/src/main/java/appeng/container/implementations/ContainerInterface.java +++ b/src/main/java/appeng/container/implementations/ContainerInterface.java @@ -46,6 +46,9 @@ public class ContainerInterface extends ContainerUpgradeable implements IOptiona @GuiSync(7) public int patternRows; + @GuiSync(9) + public boolean isEmpty; + public ContainerInterface(final InventoryPlayer ip, final IInterfaceHost te) { super(ip, te.getInterfaceDuality().getHost()); @@ -102,6 +105,7 @@ public void detectAndSendChanges() { this.verifyPermissions(SecurityPermissions.BUILD, false); if (patternRows != getPatternCapacityCardsInstalled()) patternRows = getPatternCapacityCardsInstalled(); + isEmpty = patternRows == -1; final ArrayList drops = getRemovedPatterns(); if (!drops.isEmpty()) { @@ -161,12 +165,14 @@ private void setInsertionMode(final InsertionMode insertionMode) { } public int getPatternCapacityCardsInstalled() { + if (Platform.isClient() && isEmpty) return -1; if (myDuality == null) return 0; return myDuality.getInstalledUpgrades(Upgrades.PATTERN_CAPACITY); } @Override public boolean isSlotEnabled(final int idx) { + if (Platform.isClient() && isEmpty) return false; return myDuality.getInstalledUpgrades(Upgrades.PATTERN_CAPACITY) >= idx; } } diff --git a/src/main/java/appeng/core/api/definitions/ApiParts.java b/src/main/java/appeng/core/api/definitions/ApiParts.java index d356bafb53e..3e4304f7a29 100644 --- a/src/main/java/appeng/core/api/definitions/ApiParts.java +++ b/src/main/java/appeng/core/api/definitions/ApiParts.java @@ -63,6 +63,7 @@ public final class ApiParts implements IParts { private final IItemDefinition p2PTunnelOpenComputers; private final IItemDefinition p2PTunnelPneumaticCraft; private final IItemDefinition p2PTunnelGregtech; + private final IItemDefinition p2PTunnelInterface; private final IItemDefinition cableAnchor; private final IItemDefinition monitor; private final IItemDefinition semiDarkMonitor; @@ -115,6 +116,7 @@ public ApiParts(final DefinitionConstructor constructor, final IPartHelper partH new DamagedItemDefinition(itemMultiPart.createPart(PartType.P2PTunnelOpenComputers)); this.p2PTunnelPneumaticCraft = new DamagedItemDefinition(itemMultiPart.createPart(PartType.P2PTunnelPressure)); this.p2PTunnelGregtech = new DamagedItemDefinition(itemMultiPart.createPart(PartType.P2PTunnelGT)); + this.p2PTunnelInterface = new DamagedItemDefinition(itemMultiPart.createPart(PartType.P2PTunnelInterface)); this.cableAnchor = new DamagedItemDefinition(itemMultiPart.createPart(PartType.CableAnchor)); this.monitor = new DamagedItemDefinition(itemMultiPart.createPart(PartType.Monitor)); this.semiDarkMonitor = new DamagedItemDefinition(itemMultiPart.createPart(PartType.SemiDarkMonitor)); @@ -292,6 +294,11 @@ public IItemDefinition p2PTunnelGregtech() { return this.p2PTunnelGregtech; } + @Override + public IItemDefinition p2PTunnelMEInterface() { + return this.p2PTunnelInterface; + } + @Override public IItemDefinition cableAnchor() { return this.cableAnchor; diff --git a/src/main/java/appeng/core/features/registries/P2PTunnelRegistry.java b/src/main/java/appeng/core/features/registries/P2PTunnelRegistry.java index b234cf37328..8edcdf84a9b 100644 --- a/src/main/java/appeng/core/features/registries/P2PTunnelRegistry.java +++ b/src/main/java/appeng/core/features/registries/P2PTunnelRegistry.java @@ -73,8 +73,6 @@ public void configure() { final IBlocks blocks = definitions.blocks(); final IParts parts = definitions.parts(); - this.addNewAttunement(blocks.iface(), TunnelType.ITEM); - this.addNewAttunement(parts.iface(), TunnelType.ITEM); this.addNewAttunement(parts.storageBus(), TunnelType.ITEM); this.addNewAttunement(parts.importBus(), TunnelType.ITEM); this.addNewAttunement(parts.exportBus(), TunnelType.ITEM); @@ -113,6 +111,10 @@ public void configure() { this.addNewAttunement(parts.cableUltraDenseCovered().stack(c, 1), TunnelType.ME); this.addNewAttunement(parts.cableUltraDenseSmart().stack(c, 1), TunnelType.ME); } + + this.addNewAttunement(blocks.iface(), TunnelType.ME_INTERFACE); + this.addNewAttunement(parts.iface(), TunnelType.ME_INTERFACE); + this.addNewAttunement(definitions.items().encodedPattern(), TunnelType.ME_INTERFACE); } @Override diff --git a/src/main/java/appeng/core/localization/GuiText.java b/src/main/java/appeng/core/localization/GuiText.java index 99ca8bffc02..bb3c846d47f 100644 --- a/src/main/java/appeng/core/localization/GuiText.java +++ b/src/main/java/appeng/core/localization/GuiText.java @@ -89,6 +89,7 @@ public enum GuiText { RFTunnel, PressureTunnel, GTTunnel, + IFACETunnel, StoredSize, CopyMode, diff --git a/src/main/java/appeng/helpers/DualityInterface.java b/src/main/java/appeng/helpers/DualityInterface.java index f789d7d0774..9418acdcd6f 100644 --- a/src/main/java/appeng/helpers/DualityInterface.java +++ b/src/main/java/appeng/helpers/DualityInterface.java @@ -106,7 +106,7 @@ public class DualityInterface private final int[] sides = {0, 1, 2, 3, 4, 5, 6, 7, 8}; private final IAEItemStack[] requireWork = {null, null, null, null, null, null, null, null, null}; private final MultiCraftingTracker craftingTracker; - private final AENetworkProxy gridProxy; + protected final AENetworkProxy gridProxy; private final IInterfaceHost iHost; private final BaseActionSource mySource; private final BaseActionSource interfaceRequestSource; @@ -122,7 +122,7 @@ public class DualityInterface private final UpgradeInventory upgrades; private boolean hasConfig = false; private int priority; - private List craftingList = null; + public List craftingList = null; private List waitingToSend = null; private IMEInventory destination; private boolean isWorking = false; @@ -289,7 +289,7 @@ private void readConfig() { this.notifyNeighbors(); } - private void updateCraftingList() { + public void updateCraftingList() { final boolean[] accountedFor = new boolean[patterns.getSizeInventory()]; @@ -398,7 +398,7 @@ public void notifyNeighbors() { } } - private void addToCraftingList(final ItemStack is) { + protected void addToCraftingList(final ItemStack is) { if (is == null) { return; } diff --git a/src/main/java/appeng/items/parts/PartType.java b/src/main/java/appeng/items/parts/PartType.java index 48b98842037..295b0600bf9 100644 --- a/src/main/java/appeng/items/parts/PartType.java +++ b/src/main/java/appeng/items/parts/PartType.java @@ -223,6 +223,13 @@ public boolean isCable() { PartP2PGT5Power.class, GuiText.GTTunnel), + P2PTunnelInterface( + 471, + EnumSet.of(AEFeature.P2PTunnel), + EnumSet.noneOf(IntegrationType.class), + PartP2PInterface.class, + GuiText.IFACETunnel), + InterfaceTerminal( 480, EnumSet.of(AEFeature.InterfaceTerminal), diff --git a/src/main/java/appeng/parts/p2p/PartP2PInterface.java b/src/main/java/appeng/parts/p2p/PartP2PInterface.java new file mode 100644 index 00000000000..8aca01cede3 --- /dev/null +++ b/src/main/java/appeng/parts/p2p/PartP2PInterface.java @@ -0,0 +1,411 @@ +package appeng.parts.p2p; + +import appeng.api.AEApi; +import appeng.api.config.Actionable; +import appeng.api.config.Upgrades; +import appeng.api.implementations.tiles.ITileStorageMonitorable; +import appeng.api.networking.IGridNode; +import appeng.api.networking.crafting.ICraftingLink; +import appeng.api.networking.crafting.ICraftingPatternDetails; +import appeng.api.networking.crafting.ICraftingProviderHelper; +import appeng.api.networking.events.MENetworkChannelsChanged; +import appeng.api.networking.events.MENetworkCraftingPatternChange; +import appeng.api.networking.events.MENetworkEventSubscribe; +import appeng.api.networking.events.MENetworkPowerStatusChange; +import appeng.api.networking.security.BaseActionSource; +import appeng.api.networking.ticking.IGridTickable; +import appeng.api.networking.ticking.TickRateModulation; +import appeng.api.networking.ticking.TickingRequest; +import appeng.api.storage.IMEMonitor; +import appeng.api.storage.IStorageMonitorable; +import appeng.api.storage.data.IAEFluidStack; +import appeng.api.storage.data.IAEItemStack; +import appeng.api.util.IConfigManager; +import appeng.core.sync.GuiBridge; +import appeng.helpers.DualityInterface; +import appeng.helpers.IInterfaceHost; +import appeng.helpers.IPriorityHost; +import appeng.helpers.Reflected; +import appeng.me.GridAccessException; +import appeng.tile.inventory.AppEngInternalInventory; +import appeng.tile.inventory.IAEAppEngInventory; +import appeng.tile.inventory.InvOperation; +import appeng.util.Platform; +import appeng.util.inv.IInventoryDestination; +import com.google.common.collect.ImmutableSet; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.List; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.ISidedInventory; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.IIcon; +import net.minecraft.util.Vec3; +import net.minecraftforge.common.util.ForgeDirection; + +public class PartP2PInterface extends PartP2PTunnel + implements IGridTickable, + IStorageMonitorable, + IInventoryDestination, + IInterfaceHost, + ISidedInventory, + IAEAppEngInventory, + ITileStorageMonitorable, + IPriorityHost { + + @Reflected + public PartP2PInterface(ItemStack is) { + super(is); + } + + private final DualityInterface duality = new DualityInterface(this.getProxy(), this) { + @Override + public void updateCraftingList() { + if (!isOutput()) { + super.updateCraftingList(); + try { + for (PartP2PInterface p2p : getOutputs()) p2p.duality.updateCraftingList(); + } catch (GridAccessException e) { + // ? + } + } else { + PartP2PInterface p2p = getInput(); + if (p2p != null) { + final boolean[] accountedFor = + new boolean[p2p.duality.getPatterns().getSizeInventory()]; + + if (!this.gridProxy.isReady()) { + return; + } + + if (this.craftingList != null) { + final Iterator i = this.craftingList.iterator(); + while (i.hasNext()) { + final ICraftingPatternDetails details = i.next(); + boolean found = false; + + for (int x = 0; x < accountedFor.length; x++) { + final ItemStack is = p2p.duality.getPatterns().getStackInSlot(x); + if (details.getPattern() == is) { + accountedFor[x] = found = true; + } + } + + if (!found) { + i.remove(); + } + } + } + + for (int x = 0; x < accountedFor.length; x++) { + if (!accountedFor[x]) { + this.addToCraftingList(p2p.duality.getPatterns().getStackInSlot(x)); + } + } + + try { + this.gridProxy + .getGrid() + .postEvent(new MENetworkCraftingPatternChange(this, this.gridProxy.getNode())); + } catch (final GridAccessException e) { + // :P + } + } + } + } + + @Override + public int getInstalledUpgrades(Upgrades u) { + if (isOutput() && u == Upgrades.PATTERN_CAPACITY) return -1; + return super.getInstalledUpgrades(u); + } + }; + + @MENetworkEventSubscribe + public void stateChange(final MENetworkChannelsChanged c) { + this.duality.notifyNeighbors(); + } + + @MENetworkEventSubscribe + public void stateChange(final MENetworkPowerStatusChange c) { + this.duality.notifyNeighbors(); + } + + @Override + public int getInstalledUpgrades(final Upgrades u) { + return this.duality.getInstalledUpgrades(u); + } + + @Override + @SideOnly(Side.CLIENT) + protected IIcon getTypeTexture() { + return AEApi.instance() + .definitions() + .blocks() + .iface() + .maybeBlock() + .get() + .getBlockTextureFromSide(0); + } + + @Override + public void gridChanged() { + this.duality.gridChanged(); + } + + @Override + public void readFromNBT(final NBTTagCompound data) { + super.readFromNBT(data); + this.duality.readFromNBT(data); + } + + @Override + public void writeToNBT(final NBTTagCompound data) { + super.writeToNBT(data); + this.duality.writeToNBT(data); + } + + @Override + public void addToWorld() { + super.addToWorld(); + this.duality.initialize(); + } + + @Override + public void getDrops(final List drops, final boolean wrenched) { + this.duality.addDrops(drops); + } + + @Override + public int cableConnectionRenderTo() { + return 4; + } + + @Override + public IConfigManager getConfigManager() { + return this.duality.getConfigManager(); + } + + @Override + public IInventory getInventoryByName(final String name) { + return this.duality.getInventoryByName(name); + } + + @Override + public boolean onPartActivate(final EntityPlayer p, final Vec3 pos) { + AppEngInternalInventory patterns = (AppEngInternalInventory) this.duality.getPatterns(); + if (super.onPartActivate(p, pos)) { + ArrayList drops = new ArrayList<>(); + for (int i = 0; i < patterns.getSizeInventory(); i++) { + if (patterns.getStackInSlot(i) == null) continue; + drops.add(patterns.getStackInSlot(i)); + } + TileEntity te = getTileEntity(); + Platform.spawnDrops(te.getWorldObj(), te.xCoord, te.yCoord, te.zCoord, drops); + + return true; + } + + if (p.isSneaking()) { + return false; + } + + if (Platform.isServer()) { + Platform.openGUI(p, this.getTileEntity(), this.getSide(), GuiBridge.GUI_INTERFACE); + } + + return true; + } + + @Override + public IIcon getBreakingTexture() { + return this.getItemStack().getIconIndex(); + } + + @Override + public boolean canInsert(final ItemStack stack) { + return this.duality.canInsert(stack); + } + + @Override + public IMEMonitor getItemInventory() { + return this.duality.getItemInventory(); + } + + @Override + public IMEMonitor getFluidInventory() { + return this.duality.getFluidInventory(); + } + + @Override + public TickingRequest getTickingRequest(final IGridNode node) { + return this.duality.getTickingRequest(node); + } + + @Override + public TickRateModulation tickingRequest(final IGridNode node, final int ticksSinceLastCall) { + return this.duality.tickingRequest(node, ticksSinceLastCall); + } + + @Override + public int getSizeInventory() { + return this.duality.getStorage().getSizeInventory(); + } + + @Override + public ItemStack getStackInSlot(final int i) { + return this.duality.getStorage().getStackInSlot(i); + } + + @Override + public ItemStack decrStackSize(final int i, final int j) { + return this.duality.getStorage().decrStackSize(i, j); + } + + @Override + public ItemStack getStackInSlotOnClosing(final int i) { + return this.duality.getStorage().getStackInSlotOnClosing(i); + } + + @Override + public void setInventorySlotContents(final int i, final ItemStack itemstack) { + this.duality.getStorage().setInventorySlotContents(i, itemstack); + } + + @Override + public String getInventoryName() { + return this.duality.getStorage().getInventoryName(); + } + + @Override + public boolean hasCustomInventoryName() { + return this.duality.getStorage().hasCustomInventoryName(); + } + + @Override + public int getInventoryStackLimit() { + return this.duality.getStorage().getInventoryStackLimit(); + } + + @Override + public void markDirty() { + this.duality.getStorage().markDirty(); + } + + @Override + public boolean isUseableByPlayer(final EntityPlayer entityplayer) { + return this.duality.getStorage().isUseableByPlayer(entityplayer); + } + + @Override + public void openInventory() { + this.duality.getStorage().openInventory(); + } + + @Override + public void closeInventory() { + this.duality.getStorage().closeInventory(); + } + + @Override + public boolean isItemValidForSlot(final int i, final ItemStack itemstack) { + return this.duality.getStorage().isItemValidForSlot(i, itemstack); + } + + @Override + public int[] getAccessibleSlotsFromSide(final int s) { + return this.duality.getAccessibleSlotsFromSide(s); + } + + @Override + public boolean canInsertItem(final int i, final ItemStack itemstack, final int j) { + return true; + } + + @Override + public boolean canExtractItem(final int i, final ItemStack itemstack, final int j) { + return true; + } + + @Override + public void onChangeInventory( + final IInventory inv, + final int slot, + final InvOperation mc, + final ItemStack removedStack, + final ItemStack newStack) { + this.duality.onChangeInventory(inv, slot, mc, removedStack, newStack); + } + + @Override + public DualityInterface getInterfaceDuality() { + return this.duality; + } + + @Override + public EnumSet getTargets() { + return EnumSet.of(this.getSide()); + } + + @Override + public TileEntity getTileEntity() { + return super.getHost().getTile(); + } + + @Override + public IStorageMonitorable getMonitorable(final ForgeDirection side, final BaseActionSource src) { + return this.duality.getMonitorable(side, src, this); + } + + @Override + public boolean pushPattern(final ICraftingPatternDetails patternDetails, final InventoryCrafting table) { + return this.duality.pushPattern(patternDetails, table); + } + + @Override + public boolean isBusy() { + return this.duality.isBusy(); + } + + @Override + public void provideCrafting(final ICraftingProviderHelper craftingTracker) { + this.duality.provideCrafting(craftingTracker); + } + + @Override + public ImmutableSet getRequestedJobs() { + return this.duality.getRequestedJobs(); + } + + @Override + public IAEItemStack injectCraftedItems(final ICraftingLink link, final IAEItemStack items, final Actionable mode) { + return this.duality.injectCraftedItems(link, items, mode); + } + + @Override + public void jobStateChange(final ICraftingLink link) { + this.duality.jobStateChange(link); + } + + @Override + public int getPriority() { + return this.duality.getPriority(); + } + + @Override + public void setPriority(final int newValue) { + this.duality.setPriority(newValue); + } + + @Override + public void onTunnelNetworkChange() { + this.duality.updateCraftingList(); + } +} diff --git a/src/main/java/appeng/parts/p2p/PartP2PTunnel.java b/src/main/java/appeng/parts/p2p/PartP2PTunnel.java index a7c3c0a4762..8606574f341 100644 --- a/src/main/java/appeng/parts/p2p/PartP2PTunnel.java +++ b/src/main/java/appeng/parts/p2p/PartP2PTunnel.java @@ -341,11 +341,19 @@ public boolean onPartActivate(final EntityPlayer player, final Vec3 pos) { } break; + case ME_INTERFACE: + for (final ItemStack stack : + parts.p2PTunnelMEInterface().maybeStack(1).asSet()) { + newType = stack; + } + break; + default: break; } if (newType != null && !Platform.isSameItem(newType, this.getItemStack())) { + if (new Throwable().getStackTrace()[2].getMethodName().equals("place")) return true; final boolean oldOutput = this.isOutput(); final long myFreq = this.getFrequency(); diff --git a/src/main/java/appeng/tile/inventory/AppEngInternalInventory.java b/src/main/java/appeng/tile/inventory/AppEngInternalInventory.java index c7c40ed2eb1..407ea26e912 100644 --- a/src/main/java/appeng/tile/inventory/AppEngInternalInventory.java +++ b/src/main/java/appeng/tile/inventory/AppEngInternalInventory.java @@ -113,7 +113,7 @@ public void setInventorySlotContents(final int slot, final ItemStack newItemStac ItemStack removed = oldStack; ItemStack added = newItemStack; - if (oldStack != null && newItemStack != null && Platform.isSameItem(oldStack, newItemStack)) { + if (oldStack != null && newItemStack != null && Platform.isSameItemPrecise(oldStack, newItemStack)) { if (oldStack.stackSize > newItemStack.stackSize) { removed = removed.copy(); removed.stackSize -= newItemStack.stackSize; diff --git a/src/main/resources/assets/appliedenergistics2/lang/en_US.lang b/src/main/resources/assets/appliedenergistics2/lang/en_US.lang index 1c0f06ab8ec..e88353c64ad 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/en_US.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/en_US.lang @@ -111,6 +111,7 @@ gui.appliedenergistics2.LightTunnel=Light gui.appliedenergistics2.OCTunnel=OpenComputers gui.appliedenergistics2.PressureTunnel=Pressure gui.appliedenergistics2.GTTunnel=GT EU +gui.appliedenergistics2.IFACETunnel=ME Interface gui.appliedenergistics2.security.extract.name=Withdraw gui.appliedenergistics2.security.inject.name=Deposit diff --git a/src/main/resources/assets/appliedenergistics2/textures/guis/interfacenone.png b/src/main/resources/assets/appliedenergistics2/textures/guis/interfacenone.png new file mode 100644 index 00000000000..04c219a1cf6 Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/guis/interfacenone.png differ