diff --git a/dependencies.gradle b/dependencies.gradle index f1c5f00a..636a2064 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -7,6 +7,7 @@ dependencies { compile('com.github.GTNewHorizons:ExtraCells2:2.5.9:dev') {transitive = false} compile("com.github.GTNewHorizons:ForestryMC:4.4.7:dev") + compileOnly("com.github.GTNewHorizons:ForestryMC:4.4.4:dev") compileOnly("com.github.GTNewHorizons:EnderIO:2.3.1.27:dev") compileOnly("com.github.GTNewHorizons:EnderCore:0.2.6:dev") compileOnly('com.github.GTNewHorizons:GT5-Unofficial:5.09.40.41:dev') @@ -15,5 +16,7 @@ dependencies { compileOnly('com.github.GTNewHorizons:AppleCore:3.1.9:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:BuildCraft:7.1.27:dev') {transitive = false} compileOnly("com.gregoriust.gregtech:gregtech_1.7.10:6.14.23:dev") {transitive = false} + compileOnly('com.github.GTNewHorizons:OpenComputers:1.7.5.23-GTNH:dev') {transitive = false} compileOnly("com.github.GTNewHorizons:GTplusplus:1.7.49:dev") {transitive = false} + } diff --git a/src/main/java/com/glodblock/github/client/gui/GuiDualInterface.java b/src/main/java/com/glodblock/github/client/gui/GuiDualInterface.java new file mode 100644 index 00000000..aba1bf4b --- /dev/null +++ b/src/main/java/com/glodblock/github/client/gui/GuiDualInterface.java @@ -0,0 +1,128 @@ +package com.glodblock.github.client.gui; + +import appeng.api.config.Settings; +import appeng.api.config.YesNo; +import appeng.client.gui.implementations.GuiUpgradeable; +import appeng.client.gui.widgets.GuiImgButton; +import appeng.client.gui.widgets.GuiTabButton; +import appeng.client.gui.widgets.GuiToggleButton; +import appeng.container.implementations.ContainerInterface; +import appeng.core.localization.GuiText; +import appeng.core.sync.network.NetworkHandler; +import appeng.core.sync.packets.PacketConfigButton; +import appeng.helpers.IInterfaceHost; +import com.glodblock.github.FluidCraft; +import com.glodblock.github.common.parts.PartFluidInterface; +import com.glodblock.github.common.tile.TileFluidInterface; +import com.glodblock.github.inventory.gui.GuiType; +import com.glodblock.github.loader.ItemAndBlockHolder; +import com.glodblock.github.network.CPacketSwitchGuis; +import com.glodblock.github.util.ModAndClassUtil; +import com.glodblock.github.util.NameConst; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.util.StatCollector; +import org.lwjgl.input.Mouse; + +public class GuiDualInterface extends GuiUpgradeable { + + private GuiTabButton priority; + private GuiTabButton switcher; + private GuiImgButton BlockMode; + private GuiToggleButton interfaceMode; + private final IInterfaceHost host; + + public GuiDualInterface(InventoryPlayer inventoryPlayer, IInterfaceHost te) { + super(new ContainerInterface(inventoryPlayer, te)); + this.host = te; + this.ySize = 211; + } + + @Override + @SuppressWarnings("unchecked") + protected void addButtons() + { + this.priority = new GuiTabButton( this.guiLeft + 154, this.guiTop, 2 + 4 * 16, GuiText.Priority.getLocal(), itemRender ); + this.buttonList.add( this.priority ); + + this.switcher = new GuiTabButton( this.guiLeft + 132, this.guiTop, host instanceof PartFluidInterface ? ItemAndBlockHolder.FLUID_INTERFACE.stack() : ItemAndBlockHolder.INTERFACE.stack(), StatCollector.translateToLocal("ae2fc.tooltip.switch_fluid_interface"), itemRender ); + this.buttonList.add( this.switcher ); + + this.BlockMode = new GuiImgButton( this.guiLeft - 18, this.guiTop + 8, Settings.BLOCK, YesNo.NO ); + this.buttonList.add( this.BlockMode ); + + this.interfaceMode = new GuiToggleButton( this.guiLeft - 18, this.guiTop + 26, 84, 85, GuiText.InterfaceTerminal.getLocal(), GuiText.InterfaceTerminalHint.getLocal() ); + this.buttonList.add( this.interfaceMode ); + } + + @Override + public void drawFG( final int offsetX, final int offsetY, final int mouseX, final int mouseY ) + { + if( this.BlockMode != null ) + { + this.BlockMode.set( ( (ContainerInterface) this.cvb ).getBlockingMode() ); + } + + if( this.interfaceMode != null ) + { + this.interfaceMode.setState( ( (ContainerInterface) this.cvb ).getInterfaceTerminalMode() == YesNo.YES ); + } + + this.fontRendererObj.drawString( StatCollector.translateToLocal(NameConst.GUI_FLUID_INTERFACE), 8, 6, 4210752 ); + } + + @Override + protected String getBackground() + { + if (!ModAndClassUtil.isBigInterface) + return "guis/interface.png"; + switch (((ContainerInterface) this.cvb).getPatternCapacityCardsInstalled()) + { + case 1: + return "guis/interface2.png"; + case 2: + return "guis/interface3.png"; + case 3: + return "guis/interface4.png"; + } + return "guis/interface.png"; + } + + @Override + protected void actionPerformed( final GuiButton btn ) + { + super.actionPerformed( btn ); + + final boolean backwards = Mouse.isButtonDown( 1 ); + + if( btn == this.priority ) + { + if (host instanceof TileFluidInterface) { + FluidCraft.proxy.netHandler.sendToServer(new CPacketSwitchGuis(GuiType.DUAL_INTERFACE_PRIORITY)); + } + else if(host instanceof PartFluidInterface) { + FluidCraft.proxy.netHandler.sendToServer(new CPacketSwitchGuis(GuiType.DUAL_INTERFACE_PRIORITY_PART)); + } + } + + if( btn == this.switcher ) + { + if (host instanceof TileFluidInterface) { + FluidCraft.proxy.netHandler.sendToServer(new CPacketSwitchGuis(GuiType.DUAL_INTERFACE_FLUID)); + } + else if (host instanceof PartFluidInterface) { + FluidCraft.proxy.netHandler.sendToServer(new CPacketSwitchGuis(GuiType.DUAL_INTERFACE_FLUID_PART)); + } + } + + if( btn == this.interfaceMode ) + { + NetworkHandler.instance.sendToServer( new PacketConfigButton( Settings.INTERFACE_TERMINAL, backwards ) ); + } + + if( btn == this.BlockMode ) + { + NetworkHandler.instance.sendToServer( new PacketConfigButton( this.BlockMode.getSetting(), backwards ) ); + } + } +} diff --git a/src/main/java/com/glodblock/github/client/gui/GuiFCPriority.java b/src/main/java/com/glodblock/github/client/gui/GuiFCPriority.java new file mode 100644 index 00000000..92468d59 --- /dev/null +++ b/src/main/java/com/glodblock/github/client/gui/GuiFCPriority.java @@ -0,0 +1,219 @@ +package com.glodblock.github.client.gui; + +import appeng.client.gui.AEBaseGui; +import appeng.client.gui.widgets.GuiNumberBox; +import appeng.client.gui.widgets.GuiTabButton; +import appeng.container.AEBaseContainer; +import appeng.container.implementations.ContainerPriority; +import appeng.core.AEConfig; +import appeng.core.AELog; +import appeng.core.localization.GuiText; +import appeng.core.sync.network.NetworkHandler; +import appeng.core.sync.packets.PacketValueConfig; +import appeng.helpers.IPriorityHost; +import com.glodblock.github.FluidCraft; +import com.glodblock.github.common.parts.PartFluidInterface; +import com.glodblock.github.common.tile.TileFluidInterface; +import com.glodblock.github.inventory.gui.GuiType; +import com.glodblock.github.loader.ItemAndBlockHolder; +import com.glodblock.github.network.CPacketSwitchGuis; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.item.ItemStack; + +import java.io.IOException; + +public class GuiFCPriority extends AEBaseGui +{ + + private GuiNumberBox priority; + private GuiTabButton originalGuiBtn; + + private GuiButton plus1; + private GuiButton plus10; + private GuiButton plus100; + private GuiButton plus1000; + private GuiButton minus1; + private GuiButton minus10; + private GuiButton minus100; + private GuiButton minus1000; + + private GuiType OriginalGui; + + public GuiFCPriority( final InventoryPlayer inventoryPlayer, final IPriorityHost te ) + { + super( new ContainerPriority( inventoryPlayer, te ) ); + } + + @Override + @SuppressWarnings("unchecked") + public void initGui() + { + super.initGui(); + + final int a = AEConfig.instance.priorityByStacksAmounts( 0 ); + final int b = AEConfig.instance.priorityByStacksAmounts( 1 ); + final int c = AEConfig.instance.priorityByStacksAmounts( 2 ); + final int d = AEConfig.instance.priorityByStacksAmounts( 3 ); + + this.buttonList.add( this.plus1 = new GuiButton( 0, this.guiLeft + 20, this.guiTop + 32, 22, 20, "+" + a ) ); + this.buttonList.add( this.plus10 = new GuiButton( 0, this.guiLeft + 48, this.guiTop + 32, 28, 20, "+" + b ) ); + this.buttonList.add( this.plus100 = new GuiButton( 0, this.guiLeft + 82, this.guiTop + 32, 32, 20, "+" + c ) ); + this.buttonList.add( this.plus1000 = new GuiButton( 0, this.guiLeft + 120, this.guiTop + 32, 38, 20, "+" + d ) ); + + this.buttonList.add( this.minus1 = new GuiButton( 0, this.guiLeft + 20, this.guiTop + 69, 22, 20, "-" + a ) ); + this.buttonList.add( this.minus10 = new GuiButton( 0, this.guiLeft + 48, this.guiTop + 69, 28, 20, "-" + b ) ); + this.buttonList.add( this.minus100 = new GuiButton( 0, this.guiLeft + 82, this.guiTop + 69, 32, 20, "-" + c ) ); + this.buttonList.add( this.minus1000 = new GuiButton( 0, this.guiLeft + 120, this.guiTop + 69, 38, 20, "-" + d ) ); + + ItemStack myIcon = null; + final Object target = ( (AEBaseContainer) this.inventorySlots ).getTarget(); + + if( target instanceof TileFluidInterface) + { + myIcon = ItemAndBlockHolder.INTERFACE.stack(); + this.OriginalGui = GuiType.DUAL_INTERFACE; + } + else if (target instanceof PartFluidInterface) + { + myIcon = ItemAndBlockHolder.FLUID_INTERFACE.stack(); + this.OriginalGui = GuiType.DUAL_INTERFACE_FLUID_PART; + } + + if( this.OriginalGui != null && myIcon != null ) + { + this.buttonList.add( this.originalGuiBtn = new GuiTabButton( this.guiLeft + 154, this.guiTop, myIcon, myIcon.getDisplayName(), itemRender ) ); + } + + this.priority = new GuiNumberBox( this.fontRendererObj, this.guiLeft + 62, this.guiTop + 57, 59, this.fontRendererObj.FONT_HEIGHT, Long.class ); + this.priority.setEnableBackgroundDrawing( false ); + this.priority.setMaxStringLength( 16 ); + this.priority.setTextColor( 0xFFFFFF ); + this.priority.setVisible( true ); + this.priority.setFocused( true ); + ( (ContainerPriority) this.inventorySlots ).setTextField( this.priority ); + } + + @Override + public void drawFG( final int offsetX, final int offsetY, final int mouseX, final int mouseY ) + { + this.fontRendererObj.drawString( GuiText.Priority.getLocal(), 8, 6, 4210752 ); + } + + @Override + public void drawBG( final int offsetX, final int offsetY, final int mouseX, final int mouseY ) + { + this.bindTexture( getBackground() ); + this.drawTexturedModalRect( offsetX, offsetY, 0, 0, this.xSize, this.ySize ); + + this.priority.drawTextBox(); + } + + @Override + protected void actionPerformed( final GuiButton btn ) + { + super.actionPerformed( btn ); + + if( btn == this.originalGuiBtn ) + { + FluidCraft.proxy.netHandler.sendToServer(new CPacketSwitchGuis(this.OriginalGui)); + } + + final boolean isPlus = btn == this.plus1 || btn == this.plus10 || btn == this.plus100 || btn == this.plus1000; + final boolean isMinus = btn == this.minus1 || btn == this.minus10 || btn == this.minus100 || btn == this.minus1000; + + if( isPlus || isMinus ) + { + this.addQty( this.getQty( btn ) ); + } + } + + private void addQty( final int i ) + { + try + { + String out = this.priority.getText(); + + boolean fixed = false; + while( out.startsWith( "0" ) && out.length() > 1 ) + { + out = out.substring( 1 ); + fixed = true; + } + + if( fixed ) + { + this.priority.setText( out ); + } + + if( out.isEmpty() ) + { + out = "0"; + } + + long result = Long.parseLong( out ); + result += i; + + this.priority.setText( out = Long.toString( result ) ); + + NetworkHandler.instance.sendToServer( new PacketValueConfig( "PriorityHost.Priority", out ) ); + } + catch( final NumberFormatException e ) + { + // nope.. + this.priority.setText( "0" ); + } + catch( final IOException e ) + { + AELog.debug( e ); + } + } + + @Override + protected void keyTyped( final char character, final int key ) + { + if( !this.checkHotbarKeys( key ) ) + { + if( ( key == 211 || key == 205 || key == 203 || key == 14 || character == '-' || Character.isDigit( character ) ) && this.priority.textboxKeyTyped( character, key ) ) + { + try + { + String out = this.priority.getText(); + + boolean fixed = false; + while( out.startsWith( "0" ) && out.length() > 1 ) + { + out = out.substring( 1 ); + fixed = true; + } + + if( fixed ) + { + this.priority.setText( out ); + } + + if( out.isEmpty() ) + { + out = "0"; + } + + NetworkHandler.instance.sendToServer( new PacketValueConfig( "PriorityHost.Priority", out ) ); + } + catch( final IOException e ) + { + AELog.debug( e ); + } + } + else + { + super.keyTyped( character, key ); + } + } + } + + protected String getBackground() + { + return "guis/priority.png"; + } +} diff --git a/src/main/java/com/glodblock/github/client/gui/GuiFluidInterface.java b/src/main/java/com/glodblock/github/client/gui/GuiFluidInterface.java new file mode 100644 index 00000000..13f84f6f --- /dev/null +++ b/src/main/java/com/glodblock/github/client/gui/GuiFluidInterface.java @@ -0,0 +1,145 @@ +package com.glodblock.github.client.gui; + +import appeng.api.storage.data.IAEFluidStack; +import appeng.client.gui.AEBaseGui; +import appeng.client.gui.widgets.GuiTabButton; +import appeng.core.localization.GuiText; +import com.glodblock.github.FluidCraft; +import com.glodblock.github.client.gui.container.ContainerFluidInterface; +import com.glodblock.github.common.parts.PartFluidInterface; +import com.glodblock.github.common.tile.TileFluidInterface; +import com.glodblock.github.inventory.IAEFluidTank; +import com.glodblock.github.inventory.gui.GuiType; +import com.glodblock.github.loader.ItemAndBlockHolder; +import com.glodblock.github.network.CPacketSwitchGuis; +import com.glodblock.github.util.NameConst; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.client.resources.I18n; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.util.IIcon; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.StatCollector; +import net.minecraftforge.common.util.ForgeDirection; +import org.lwjgl.opengl.GL11; + +import javax.annotation.Nullable; + +public class GuiFluidInterface extends AEBaseGui { + + private static final ResourceLocation TEX_BG = FluidCraft.resource("textures/gui/interface_fluid.png"); + private static final int TANK_X = 35, TANK_X_OFF = 18, TANK_Y = 53; + private static final int TANK_WIDTH = 16, TANK_HEIGHT = 68; + + private final ContainerFluidInterface cont; + + private GuiTabButton switcher; + + public GuiFluidInterface(InventoryPlayer ipl, TileFluidInterface tile) { + super(new ContainerFluidInterface(ipl, tile)); + this.cont = (ContainerFluidInterface) inventorySlots; + this.ySize = 231; + } + + public GuiFluidInterface(InventoryPlayer ipl, PartFluidInterface tile) { + super(new ContainerFluidInterface(ipl, tile)); + this.cont = (ContainerFluidInterface) inventorySlots; + this.ySize = 231; + } + + @Override + @SuppressWarnings("unchecked") + public void initGui() + { + super.initGui(); + this.switcher = new GuiTabButton( this.guiLeft + 154, this.guiTop, isPart() ? ItemAndBlockHolder.FLUID_INTERFACE.stack() : ItemAndBlockHolder.INTERFACE.stack(), StatCollector.translateToLocal("ae2fc.tooltip.switch_fluid_interface"), itemRender ); + this.buttonList.add( this.switcher ); + } + + @Override + public void drawFG(int offsetX, int offsetY, int mouseX, int mouseY) { + fontRendererObj.drawString(getGuiDisplayName(I18n.format(NameConst.GUI_FLUID_INTERFACE)), 8, 6, 0x404040); + fontRendererObj.drawString(GuiText.inventory.getLocal(), 8, ySize - 94, 0x404040); + GL11.glColor4f(1F, 1F, 1F, 1F); + + IAEFluidTank fluidInv; + if (isPart()) { + fluidInv = ((PartFluidInterface) cont.getTile()).getInternalFluid(); + } else { + fluidInv = ((TileFluidInterface) cont.getTile()).getInternalFluid(); + } + + mc.getTextureManager().bindTexture(TextureMap.locationBlocksTexture); + for (int i = 0; i < 6; i++) { + if (!isPart()) { + fontRendererObj.drawString(dirName(i), TANK_X + i * TANK_X_OFF + 5, 22, 0x404040); + } + renderFluidIntoGui(TANK_X + i * TANK_X_OFF, TANK_Y, TANK_WIDTH, TANK_HEIGHT, + fluidInv.getFluidInSlot(i), fluidInv.getTankInfo(ForgeDirection.UNKNOWN)[i].capacity); + } + GL11.glColor4f(1F, 1F, 1F, 1F); + } + + public String dirName(int face) { + return I18n.format(NameConst.GUI_FLUID_INTERFACE + "." + face); + } + + @Override + public void drawBG(int offsetX, int offsetY, int mouseX, int mouseY) { + mc.getTextureManager().bindTexture(TEX_BG); + drawTexturedModalRect(offsetX, offsetY, 0, 0, 176, ySize); + } + + public void renderFluidIntoGui(int x, int y, int width, int height, + @Nullable IAEFluidStack aeFluidStack, int capacity) { + if (aeFluidStack != null) { + GL11.glDisable(2896); + GL11.glColor3f(1.0F, 1.0F, 1.0F); + int hi = (int) (height * ((double) aeFluidStack.getStackSize() / capacity)); + if (aeFluidStack.getStackSize() > 0 && hi > 0) { + Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.locationBlocksTexture); + IIcon fluidIcon = aeFluidStack.getFluid().getStillIcon(); + GL11.glColor3f((float)(aeFluidStack.getFluid().getColor() >> 16 & 255) / 255.0F, (float)(aeFluidStack.getFluid().getColor() >> 8 & 255) / 255.0F, (float)(aeFluidStack.getFluid().getColor() & 255) / 255.0F); + for (int th = 0; th <= hi; th += 16) { + if (hi - th <= 0) break; + this.drawTexturedModelRectFromIcon(x, y + height - Math.min(16, hi - th) - th, fluidIcon, width, Math.min(16, hi - th)); + } + GL11.glColor3f(1.0F, 1.0F, 1.0F); + } + } + } + + @Override + protected void actionPerformed( final GuiButton btn ) + { + super.actionPerformed(btn); + if (btn == this.switcher) { + FluidCraft.proxy.netHandler.sendToServer(new CPacketSwitchGuis(isPart() ? GuiType.DUAL_INTERFACE_PART : GuiType.DUAL_INTERFACE)); + } + } + + public void update(int id, IAEFluidStack stack) { + if (id >= 100) { + id -= 100; + if (isPart()) { + ((PartFluidInterface) cont.getTile()).setConfig(id, stack); + } else { + ((TileFluidInterface) cont.getTile()).setConfig(id, stack); + } + } + else { + if(isPart()) { + ((PartFluidInterface) cont.getTile()).setFluidInv(id, stack); + } else { + ((TileFluidInterface) cont.getTile()).setFluidInv(id, stack); + } + } + } + + private boolean isPart() { + return this.cont.getTile() instanceof PartFluidInterface; + } + +} + diff --git a/src/main/java/com/glodblock/github/client/gui/GuiOCPatternEditor.java b/src/main/java/com/glodblock/github/client/gui/GuiOCPatternEditor.java new file mode 100644 index 00000000..26a75fbd --- /dev/null +++ b/src/main/java/com/glodblock/github/client/gui/GuiOCPatternEditor.java @@ -0,0 +1,33 @@ +package com.glodblock.github.client.gui; + +import appeng.client.gui.AEBaseGui; +import appeng.core.localization.GuiText; +import com.glodblock.github.FluidCraft; +import com.glodblock.github.client.gui.container.ContainerOCPatternEditor; +import com.glodblock.github.common.tile.TileOCPatternEditor; +import com.glodblock.github.util.NameConst; +import net.minecraft.client.resources.I18n; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.util.ResourceLocation; + +public class GuiOCPatternEditor extends AEBaseGui { + + private static final ResourceLocation TEX_BG = FluidCraft.resource("textures/gui/oc_pattern_editor.png"); + + public GuiOCPatternEditor(InventoryPlayer ipl, TileOCPatternEditor tile) { + super(new ContainerOCPatternEditor(ipl, tile)); + this.ySize = 186; + } + + @Override + public void drawBG(int offsetX, int offsetY, int mouseX, int mouseY) { + mc.getTextureManager().bindTexture(TEX_BG); + drawTexturedModalRect(offsetX, offsetY, 0, 0, 176, ySize); + } + + @Override + public void drawFG(int offsetX, int offsetY, int mouseX, int mouseY) { + fontRendererObj.drawString(getGuiDisplayName(I18n.format(NameConst.GUI_OC_PATTERN_EDITOR)), 8, 6, 0x404040); + fontRendererObj.drawString(GuiText.inventory.getLocal(), 8, ySize - 94, 0x404040); + } +} diff --git a/src/main/java/com/glodblock/github/client/gui/container/ContainerFluidConfigurable.java b/src/main/java/com/glodblock/github/client/gui/container/ContainerFluidConfigurable.java index b9739e6e..d4818dc6 100644 --- a/src/main/java/com/glodblock/github/client/gui/container/ContainerFluidConfigurable.java +++ b/src/main/java/com/glodblock/github/client/gui/container/ContainerFluidConfigurable.java @@ -69,18 +69,18 @@ public abstract class ContainerFluidConfigurable extends ContainerUpgradeable { final IInventory inv = Ae2Reflect.getUpgradeList(this).getInventoryByName( "config" ); final int y = 40; final int x = 80; - this.addSlotToContainer( new OptionalFluidSlotFakeTypeOnly( inv, this, 0, x, y, 0, 0, 0 ) ); + this.addSlotToContainer( new OptionalFluidSlotFakeTypeOnly( inv, null, this, 0, x, y, 0, 0, 0 ) ); if( this.supportCapacity() ) { - this.addSlotToContainer( new OptionalFluidSlotFakeTypeOnly( inv, this, 1, x, y, -1, 0, 1 ) ); - this.addSlotToContainer( new OptionalFluidSlotFakeTypeOnly( inv, this, 2, x, y, 1, 0, 1 ) ); - this.addSlotToContainer( new OptionalFluidSlotFakeTypeOnly( inv, this, 3, x, y, 0, -1, 1 ) ); - this.addSlotToContainer( new OptionalFluidSlotFakeTypeOnly( inv, this, 4, x, y, 0, 1, 1 ) ); + this.addSlotToContainer( new OptionalFluidSlotFakeTypeOnly( inv, null, this, 1, x, y, -1, 0, 1 ) ); + this.addSlotToContainer( new OptionalFluidSlotFakeTypeOnly( inv, null, this, 2, x, y, 1, 0, 1 ) ); + this.addSlotToContainer( new OptionalFluidSlotFakeTypeOnly( inv, null, this, 3, x, y, 0, -1, 1 ) ); + this.addSlotToContainer( new OptionalFluidSlotFakeTypeOnly( inv, null, this, 4, x, y, 0, 1, 1 ) ); - this.addSlotToContainer( new OptionalFluidSlotFakeTypeOnly( inv, this, 5, x, y, -1, -1, 2 ) ); - this.addSlotToContainer( new OptionalFluidSlotFakeTypeOnly( inv, this, 6, x, y, 1, -1, 2 ) ); - this.addSlotToContainer( new OptionalFluidSlotFakeTypeOnly( inv, this, 7, x, y, -1, 1, 2 ) ); - this.addSlotToContainer( new OptionalFluidSlotFakeTypeOnly( inv, this, 8, x, y, 1, 1, 2 ) ); + this.addSlotToContainer( new OptionalFluidSlotFakeTypeOnly( inv, null, this, 5, x, y, -1, -1, 2 ) ); + this.addSlotToContainer( new OptionalFluidSlotFakeTypeOnly( inv, null, this, 6, x, y, 1, -1, 2 ) ); + this.addSlotToContainer( new OptionalFluidSlotFakeTypeOnly( inv, null, this, 7, x, y, -1, 1, 2 ) ); + this.addSlotToContainer( new OptionalFluidSlotFakeTypeOnly( inv, null, this, 8, x, y, 1, 1, 2 ) ); } } @@ -128,11 +128,4 @@ public abstract class ContainerFluidConfigurable extends ContainerUpgradeable { super.standardDetectAndSendChanges(); } - public void setFluid(int id, IAEFluidStack fluidStack) { - final AppEngInternalAEInventory inv = this.getFakeFluidInv(); - if (inv != null && this.isValidForConfig(id, AEFluidStack.create(fluidStack))) { - ItemStack tmp = ItemFluidPacket.newDisplayStack(fluidStack.getFluidStack()); - inv.setInventorySlotContents(id, tmp); - } - } } diff --git a/src/main/java/com/glodblock/github/client/gui/container/ContainerFluidInterface.java b/src/main/java/com/glodblock/github/client/gui/container/ContainerFluidInterface.java new file mode 100644 index 00000000..34f0599e --- /dev/null +++ b/src/main/java/com/glodblock/github/client/gui/container/ContainerFluidInterface.java @@ -0,0 +1,88 @@ +package com.glodblock.github.client.gui.container; + +import appeng.api.storage.data.IAEFluidStack; +import appeng.container.AEBaseContainer; +import appeng.container.slot.IOptionalSlotHost; +import appeng.util.item.AEFluidStack; +import com.glodblock.github.FluidCraft; +import com.glodblock.github.common.item.ItemFluidPacket; +import com.glodblock.github.common.parts.PartFluidInterface; +import com.glodblock.github.common.tile.TileFluidInterface; +import com.glodblock.github.inventory.slot.OptionalFluidSlotFakeTypeOnly; +import com.glodblock.github.network.SPacketFluidUpdate; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.IInventory; + +import java.util.HashMap; +import java.util.Map; + +public class ContainerFluidInterface extends AEBaseContainer implements IOptionalSlotHost { + + private final Object tile; + + public ContainerFluidInterface(InventoryPlayer ipl, TileFluidInterface tile) { + super(ipl, tile); + this.tile = tile; + IInventory inv = tile.getConfig(); + final int y = 35; + final int x = 35; + for (int i = 0; i < 6; i++) { + addSlotToContainer(new OptionalFluidSlotFakeTypeOnly(inv, tile.getDualityFluid().getConfig(), this, i, x, y, i, 0, 0)); + } + bindPlayerInventory(ipl, 0, 149); + } + + public ContainerFluidInterface(InventoryPlayer ipl, PartFluidInterface tile) { + super(ipl, tile); + this.tile = tile; + IInventory inv = tile.getConfig(); + final int y = 35; + final int x = 35; + for (int i = 0; i < 6; i++) { + addSlotToContainer(new OptionalFluidSlotFakeTypeOnly(inv, tile.getDualityFluid().getConfig(), this, i, x, y, i, 0, 0)); + } + bindPlayerInventory(ipl, 0, 149); + } + + public Object getTile() { + return tile; + } + + @Override + public boolean isSlotEnabled(int idx) { + return idx >= 0 && idx < 6; + } + + @Override + public void detectAndSendChanges() { + super.detectAndSendChanges(); + Map tmp = new HashMap<>(); + if (tile instanceof TileFluidInterface) { + for (int i = 0; i < ((TileFluidInterface) tile).getInternalFluid().getSlots(); i ++) { + tmp.put(i, ((TileFluidInterface) tile).getInternalFluid().getFluidInSlot(i)); + } + for (int i = 0; i < ((TileFluidInterface) tile).getConfig().getSizeInventory(); i ++) { + tmp.put(i + 100, AEFluidStack.create(ItemFluidPacket.getFluidStack(((TileFluidInterface) tile).getConfig().getStackInSlot( i )))); + } + } + else { + for (int i = 0; i < ((PartFluidInterface) tile).getInternalFluid().getSlots(); i ++) { + tmp.put(i, ((PartFluidInterface) tile).getInternalFluid().getFluidInSlot(i)); + } + for (int i = 0; i < ((PartFluidInterface) tile).getConfig().getSizeInventory(); i ++) { + tmp.put(i + 100, AEFluidStack.create(ItemFluidPacket.getFluidStack(((PartFluidInterface) tile).getConfig().getStackInSlot( i )))); + } + } + + for( final Object g : this.crafters ) + { + if( g instanceof EntityPlayer) + { + FluidCraft.proxy.netHandler.sendTo(new SPacketFluidUpdate(tmp), (EntityPlayerMP) g); + } + } + } + +} diff --git a/src/main/java/com/glodblock/github/client/gui/container/ContainerOCPatternEditor.java b/src/main/java/com/glodblock/github/client/gui/container/ContainerOCPatternEditor.java new file mode 100644 index 00000000..e80af736 --- /dev/null +++ b/src/main/java/com/glodblock/github/client/gui/container/ContainerOCPatternEditor.java @@ -0,0 +1,23 @@ +package com.glodblock.github.client.gui.container; + +import appeng.container.AEBaseContainer; +import appeng.container.slot.SlotRestrictedInput; +import com.glodblock.github.common.tile.TileOCPatternEditor; +import net.minecraft.entity.player.InventoryPlayer; + +public class ContainerOCPatternEditor extends AEBaseContainer { + + public ContainerOCPatternEditor(InventoryPlayer ipl, TileOCPatternEditor tile) { + super(ipl, tile); + for (int i = 0; i < 4; i ++) { + for (int j = 0; j < 4; j ++) { + addSlotToContainer(new SlotRestrictedInput( + SlotRestrictedInput.PlacableItemType.PATTERN, tile.getInternalInventory(), + j * 4 + i, 55 + i * 18, 17 + j * 18, ipl + )); + } + } + bindPlayerInventory(ipl, 0, 104); + } + +} diff --git a/src/main/java/com/glodblock/github/common/block/BlockFluidInterface.java b/src/main/java/com/glodblock/github/common/block/BlockFluidInterface.java index 68aac600..608caa7c 100644 --- a/src/main/java/com/glodblock/github/common/block/BlockFluidInterface.java +++ b/src/main/java/com/glodblock/github/common/block/BlockFluidInterface.java @@ -8,6 +8,9 @@ import appeng.tile.misc.TileInterface; import appeng.util.Platform; import com.glodblock.github.client.render.RenderBlockFluidInterface; import com.glodblock.github.common.tile.TileFluidInterface; +import com.glodblock.github.inventory.InventoryHandler; +import com.glodblock.github.inventory.gui.GuiType; +import com.glodblock.github.util.BlockPos; import com.glodblock.github.util.NameConst; import cpw.mods.fml.common.registry.GameRegistry; import cpw.mods.fml.relauncher.Side; @@ -15,6 +18,7 @@ import cpw.mods.fml.relauncher.SideOnly; import net.minecraft.block.material.Material; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumFacing; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; @@ -38,19 +42,18 @@ public class BlockFluidInterface extends FCBaseBlock { } @Override - public boolean onActivated(final World w, final int x, final int y, final int z, final EntityPlayer p, final int side, final float hitX, final float hitY, final float hitZ ) + public boolean onActivated(final World world, final int x, final int y, final int z, final EntityPlayer player, final int facing, final float hitX, final float hitY, final float hitZ ) { - if( p.isSneaking() ) + if( player.isSneaking() ) { return false; } - - final TileInterface tg = this.getTileEntity( w, x, y, z ); + final TileInterface tg = this.getTileEntity( world, x, y, z ); if( tg != null ) { if( Platform.isServer() ) { - Platform.openGUI( p, tg, ForgeDirection.getOrientation( side ), GuiBridge.GUI_INTERFACE ); + InventoryHandler.openGui(player, world, new BlockPos(x, y, z), EnumFacing.getFront(facing), GuiType.DUAL_INTERFACE); } return true; } diff --git a/src/main/java/com/glodblock/github/common/block/BlockOCPatternEditor.java b/src/main/java/com/glodblock/github/common/block/BlockOCPatternEditor.java new file mode 100644 index 00000000..0a6c26ce --- /dev/null +++ b/src/main/java/com/glodblock/github/common/block/BlockOCPatternEditor.java @@ -0,0 +1,60 @@ +package com.glodblock.github.common.block; + +import appeng.block.AEBaseItemBlock; +import com.glodblock.github.common.tile.TileOCPatternEditor; +import com.glodblock.github.crossmod.opencomputers.OCDriverInit; +import com.glodblock.github.inventory.InventoryHandler; +import com.glodblock.github.inventory.gui.GuiType; +import com.glodblock.github.util.BlockPos; +import com.glodblock.github.util.ModAndClassUtil; +import com.glodblock.github.util.NameConst; +import cpw.mods.fml.common.registry.GameRegistry; +import net.minecraft.block.material.Material; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; + +public class BlockOCPatternEditor extends FCBaseBlock { + + public BlockOCPatternEditor() { + super(Material.iron, NameConst.BLOCK_OC_PATTERN_EDITOR); + setTileEntity(TileOCPatternEditor.class); + setFullBlock(true); + setOpaque(true); + } + + @Override + public boolean onActivated(World world, int x, int y, int z, EntityPlayer player, int facing, float hitX, float hitY, float hitZ) { + if (player.isSneaking()) { + return false; + } + TileOCPatternEditor tile = getTileEntity(world, x, y, z); + if (tile != null) { + if (!world.isRemote) { + InventoryHandler.openGui(player, world, new BlockPos(x, y, z), EnumFacing.getFront(facing), GuiType.OC_PATTERN_EDITOR); + } + return true; + } + return false; + } + + public BlockOCPatternEditor register() { + if (ModAndClassUtil.OC) { + GameRegistry.registerBlock(this, AEBaseItemBlock.class, NameConst.BLOCK_OC_PATTERN_EDITOR); + GameRegistry.registerTileEntity(TileOCPatternEditor.class, NameConst.BLOCK_OC_PATTERN_EDITOR); + OCDriverInit.run(); + return this; + } + return null; + } + + public ItemStack stack(int size) { + return new ItemStack(this, size); + } + + public ItemStack stack() { + return new ItemStack(this, 1); + } + +} diff --git a/src/main/java/com/glodblock/github/common/parts/PartFluidInterface.java b/src/main/java/com/glodblock/github/common/parts/PartFluidInterface.java index a821909e..2848ea2b 100644 --- a/src/main/java/com/glodblock/github/common/parts/PartFluidInterface.java +++ b/src/main/java/com/glodblock/github/common/parts/PartFluidInterface.java @@ -2,32 +2,59 @@ package com.glodblock.github.common.parts; import appeng.api.config.Actionable; import appeng.api.config.Upgrades; +import appeng.api.networking.IGridNode; import appeng.api.networking.energy.IEnergyGrid; +import appeng.api.networking.events.MENetworkChannelsChanged; +import appeng.api.networking.events.MENetworkEventSubscribe; +import appeng.api.networking.events.MENetworkPowerStatusChange; import appeng.api.networking.security.BaseActionSource; import appeng.api.networking.security.MachineSource; import appeng.api.networking.storage.IStorageGrid; +import appeng.api.networking.ticking.TickRateModulation; +import appeng.api.networking.ticking.TickingRequest; import appeng.api.parts.IPartRenderHelper; import appeng.api.storage.IMEMonitor; import appeng.api.storage.data.IAEFluidStack; import appeng.client.texture.CableBusTextures; +import appeng.core.settings.TickRates; import appeng.me.GridAccessException; import appeng.parts.misc.PartInterface; +import appeng.tile.inventory.AppEngInternalAEInventory; import appeng.util.Platform; import appeng.util.item.AEFluidStack; import com.glodblock.github.client.textures.FCPartsTexture; +import com.glodblock.github.common.item.ItemFluidPacket; +import com.glodblock.github.inventory.AEFluidInventory; +import com.glodblock.github.inventory.IAEFluidInventory; +import com.glodblock.github.inventory.IAEFluidTank; +import com.glodblock.github.inventory.InventoryHandler; +import com.glodblock.github.inventory.gui.GuiType; +import com.glodblock.github.util.BlockPos; +import com.glodblock.github.util.DualityFluidInterface; +import com.glodblock.github.util.Util; +import cpw.mods.fml.common.network.ByteBufUtils; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import io.netty.buffer.ByteBuf; import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.Vec3; import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidTankInfo; import net.minecraftforge.fluids.IFluidHandler; -public class PartFluidInterface extends PartInterface implements IFluidHandler { +import java.io.IOException; +import java.util.Objects; + +public class PartFluidInterface extends PartInterface implements IFluidHandler, IAEFluidInventory { private final BaseActionSource ownActionSource = new MachineSource(this); + private final AppEngInternalAEInventory config = new AppEngInternalAEInventory( this, 6 ); + private final DualityFluidInterface fluidDuality = new DualityFluidInterface(this.getProxy(), this); public PartFluidInterface(ItemStack is) { super(is); @@ -72,6 +99,120 @@ public class PartFluidInterface extends PartInterface implements IFluidHandler { rh.renderInventoryBox( renderer ); } + @MENetworkEventSubscribe + public void stateChange(final MENetworkChannelsChanged c) { + fluidDuality.onChannelStateChange(c); + } + + @MENetworkEventSubscribe + public void stateChange(final MENetworkPowerStatusChange c) { + fluidDuality.onPowerStateChange(c); + } + + @Override + public void gridChanged() { + super.gridChanged(); + fluidDuality.gridChanged(); + } + + public DualityFluidInterface getDualityFluid() { + return fluidDuality; + } + + public AEFluidInventory getInternalFluid() { + return fluidDuality.getTanks(); + } + + public AppEngInternalAEInventory getConfig() { + for (int i = 0; i < fluidDuality.getConfig().getSlots(); i ++) { + IAEFluidStack fluid = fluidDuality.getConfig().getFluidInSlot(i); + if (fluid == null) { + config.setInventorySlotContents(i, null); + } + else { + config.setInventorySlotContents(i, ItemFluidPacket.newDisplayStack(fluid.getFluidStack())); + } + } + return config; + } + + @Override + public void writeToStream(ByteBuf data) throws IOException { + super.writeToStream(data); + for (int i = 0; i < config.getSizeInventory(); i++) { + ByteBufUtils.writeItemStack(data, config.getStackInSlot(i)); + for (int j = 0; j < config.getSizeInventory(); j ++) { + FluidStack fluid = ItemFluidPacket.getFluidStack(config.getStackInSlot(j)); + fluidDuality.getConfig().setFluidInSlot(j, fluidDuality.getStandardFluid(fluid)); + } + } + int fluidMask = 0; + for (int i = 0; i < getInternalFluid().getSlots(); i++) { + if (getInternalFluid().getFluidInSlot(i) != null) { + fluidMask |= 1 << i; + } + } + data.writeByte(fluidMask); + for (int i = 0; i < getInternalFluid().getSlots(); i++) { + IAEFluidStack fluid = getInternalFluid().getFluidInSlot(i); + if (fluid != null) { + fluid.writeToPacket(data); + } + } + } + + @Override + public boolean readFromStream(ByteBuf data) throws IOException { + super.readFromStream(data); + boolean changed = false; + for (int i = 0; i < config.getSizeInventory(); i++) { + ItemStack stack = ByteBufUtils.readItemStack(data); + if (!ItemStack.areItemStacksEqual(stack, config.getStackInSlot(i))) { + config.setInventorySlotContents(i, stack); + changed = true; + } + for (int j = 0; j < config.getSizeInventory(); j ++) { + FluidStack fluid = ItemFluidPacket.getFluidStack(config.getStackInSlot(j)); + fluidDuality.getConfig().setFluidInSlot(j, fluidDuality.getStandardFluid(fluid)); + } + } + int fluidMask = data.readByte(); + for (int i = 0; i < getInternalFluid().getSlots(); i++) { + if ((fluidMask & (1 << i)) != 0) { + IAEFluidStack fluid = AEFluidStack.loadFluidStackFromPacket(data); + if (fluid != null) { // this shouldn't happen, but better safe than sorry + IAEFluidStack origFluid = getInternalFluid().getFluidInSlot(i); + if (!fluid.equals(origFluid) || fluid.getStackSize() != origFluid.getStackSize()) { + getInternalFluid().setFluidInSlot(i, fluid); + changed = true; + } + } + } else if (getInternalFluid().getFluidInSlot(i) != null) { + getInternalFluid().setFluidInSlot(i, null); + changed = true; + } + } + return changed; + } + + @Override + public void readFromNBT( NBTTagCompound data ) { + super.readFromNBT( data ); + config.readFromNBT(data, "ConfigInv"); + for (int i = 0; i < config.getSizeInventory(); i ++) { + FluidStack fluid = ItemFluidPacket.getFluidStack(config.getStackInSlot(i)); + fluidDuality.getConfig().setFluidInSlot(i, fluidDuality.getStandardFluid(fluid)); + } + getInternalFluid().readFromNBT(data, "FluidInv"); + } + + @Override + public void writeToNBT( NBTTagCompound data ) { + super.writeToNBT(data); + config.writeToNBT(data, "ConfigInv"); + getInternalFluid().writeToNBT(data, "FluidInv"); + } + @Override public int getInstalledUpgrades( final Upgrades u ) { @@ -103,7 +244,7 @@ public class PartFluidInterface extends PartInterface implements IFluidHandler { int ori = resource.amount; IAEFluidStack remove; if (doFill) { - remove = Platform.poweredInsert(energyGrid, fluidGrid, AEFluidStack.create(resource), ownActionSource); + remove = fluidGrid.injectItems(AEFluidStack.create(resource), Actionable.MODULATE, ownActionSource); } else { remove = fluidGrid.injectItems(AEFluidStack.create(resource), Actionable.SIMULATE, ownActionSource); } @@ -112,12 +253,12 @@ public class PartFluidInterface extends PartInterface implements IFluidHandler { @Override public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain) { - return null; + return fluidDuality.drain(from, resource, doDrain); } @Override public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) { - return null; + return fluidDuality.drain(from, maxDrain, doDrain); } @Override @@ -127,11 +268,69 @@ public class PartFluidInterface extends PartInterface implements IFluidHandler { @Override public boolean canDrain(ForgeDirection from, Fluid fluid) { - return false; + return true; } @Override public FluidTankInfo[] getTankInfo(ForgeDirection from) { - return new FluidTankInfo[]{new FluidTankInfo(null, 0)}; + return fluidDuality.getTankInfo(from); } + + @Override + public boolean onPartActivate(final EntityPlayer player, final Vec3 pos) + { + if( player.isSneaking() ) + { + return false; + } + if( Platform.isServer() ) + { + InventoryHandler.openGui(player, this.getHost().getTile().getWorldObj(), new BlockPos(this.getHost().getTile()), Objects.requireNonNull(Util.from(this.getSide())), GuiType.DUAL_INTERFACE_PART); + } + return true; + } + + @Override + public void onFluidInventoryChanged(IAEFluidTank inv, int slot) { + saveChanges(); + getTileEntity().markDirty(); + fluidDuality.onFluidInventoryChanged(inv, slot); + } + + public void setConfig(int id, IAEFluidStack fluid) { + if (id >= 0 && id < 6) { + config.setInventorySlotContents(id, ItemFluidPacket.newDisplayStack(fluid == null ? null : fluid.getFluidStack())); + fluidDuality.getConfig().setFluidInSlot(id, fluidDuality.getStandardFluid(fluid)); + } + } + + public void setFluidInv(int id, IAEFluidStack fluid) { + if (id >= 0 && id < 6) { + getInternalFluid().setFluidInSlot(id, fluid); + } + } + + @Override + public TickingRequest getTickingRequest( final IGridNode node ) + { + TickingRequest item = super.getTickingRequest(node); + TickingRequest fluid = fluidDuality.getTickingRequest(node); + return new TickingRequest( + Math.min(item.minTickRate, fluid.minTickRate), + Math.max(item.maxTickRate, fluid.maxTickRate), + item.isSleeping && fluid.isSleeping, + true); + } + + @Override + public TickRateModulation tickingRequest(IGridNode node, int TicksSinceLastCall) { + TickRateModulation item = super.tickingRequest(node, TicksSinceLastCall); + TickRateModulation fluid = fluidDuality.tickingRequest(node, TicksSinceLastCall); + if (item.ordinal() >= fluid.ordinal()) { + return item; + } else { + return fluid; + } + } + } diff --git a/src/main/java/com/glodblock/github/common/parts/PartSharedFluidBus.java b/src/main/java/com/glodblock/github/common/parts/PartSharedFluidBus.java index 281edde8..3c917dc4 100644 --- a/src/main/java/com/glodblock/github/common/parts/PartSharedFluidBus.java +++ b/src/main/java/com/glodblock/github/common/parts/PartSharedFluidBus.java @@ -87,6 +87,10 @@ public abstract class PartSharedFluidBus extends PartUpgradeable implements IGri @Override public boolean onPartActivate(final EntityPlayer player, final Vec3 pos) { + if( player.isSneaking() ) + { + return false; + } if( Platform.isServer() ) { InventoryHandler.openGui(player, this.getHost().getTile().getWorldObj(), new BlockPos(this.getHost().getTile()), Objects.requireNonNull(Util.from(this.getSide())), GuiType.FLUID_BUS_IO); diff --git a/src/main/java/com/glodblock/github/common/tile/TileFluidDiscretizer.java b/src/main/java/com/glodblock/github/common/tile/TileFluidDiscretizer.java index 68f3aab9..20b40225 100644 --- a/src/main/java/com/glodblock/github/common/tile/TileFluidDiscretizer.java +++ b/src/main/java/com/glodblock/github/common/tile/TileFluidDiscretizer.java @@ -131,11 +131,6 @@ public class TileFluidDiscretizer extends AENetworkTile implements IPriorityHost updateState(); } - private boolean checkDiscreatizer() { - int amount = getProxy().getNode().getGrid().getMachines(this.getClass()).size(); - return amount <= 1; - } - private class FluidDiscretizingInventory implements IMEInventory, IMEMonitorHandlerReceiver { private final MEInventoryHandler invHandler = new MEInventoryHandler<>(this, getChannel()); @@ -164,7 +159,7 @@ public class TileFluidDiscretizer extends AENetworkTile implements IPriorityHost return ItemFluidDrop.newAeStack(fluidGrid.injectItems(fluidStack.copy(), Actionable.SIMULATE, src)); } else { - return ItemFluidDrop.newAeStack(Platform.poweredInsert(energyGrid, fluidGrid, fluidStack, ownActionSource)); + return ItemFluidDrop.newAeStack(fluidGrid.injectItems(fluidStack.copy(), Actionable.MODULATE, src)); } } @@ -187,7 +182,7 @@ public class TileFluidDiscretizer extends AENetworkTile implements IPriorityHost return ItemFluidDrop.newAeStack(fluidGrid.extractItems(fluidStack.copy(), Actionable.SIMULATE, src)); } else { - return ItemFluidDrop.newAeStack(Platform.poweredExtraction(energyGrid, fluidGrid, fluidStack, ownActionSource)); + return ItemFluidDrop.newAeStack(fluidGrid.extractItems(fluidStack.copy(), Actionable.MODULATE, src)); } } diff --git a/src/main/java/com/glodblock/github/common/tile/TileFluidInterface.java b/src/main/java/com/glodblock/github/common/tile/TileFluidInterface.java index 7d22731b..8cb5268f 100644 --- a/src/main/java/com/glodblock/github/common/tile/TileFluidInterface.java +++ b/src/main/java/com/glodblock/github/common/tile/TileFluidInterface.java @@ -1,20 +1,34 @@ package com.glodblock.github.common.tile; -import appeng.api.config.Actionable; import appeng.api.config.Upgrades; +import appeng.api.networking.IGridNode; import appeng.api.networking.energy.IEnergyGrid; +import appeng.api.networking.events.MENetworkChannelsChanged; +import appeng.api.networking.events.MENetworkEventSubscribe; +import appeng.api.networking.events.MENetworkPowerStatusChange; import appeng.api.networking.security.BaseActionSource; import appeng.api.networking.security.MachineSource; import appeng.api.networking.storage.IStorageGrid; +import appeng.api.networking.ticking.TickRateModulation; +import appeng.api.networking.ticking.TickingRequest; import appeng.api.storage.IMEMonitor; import appeng.api.storage.data.IAEFluidStack; -import appeng.core.features.IStackSrc; import appeng.me.GridAccessException; +import appeng.tile.TileEvent; +import appeng.tile.events.TileEventType; +import appeng.tile.inventory.AppEngInternalAEInventory; import appeng.tile.misc.TileInterface; -import appeng.util.Platform; import appeng.util.item.AEFluidStack; +import com.glodblock.github.common.item.ItemFluidPacket; +import com.glodblock.github.inventory.AEFluidInventory; +import com.glodblock.github.inventory.IAEFluidInventory; +import com.glodblock.github.inventory.IAEFluidTank; import com.glodblock.github.loader.ItemAndBlockHolder; +import com.glodblock.github.util.DualityFluidInterface; +import cpw.mods.fml.common.network.ByteBufUtils; +import io.netty.buffer.ByteBuf; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; @@ -22,26 +36,150 @@ import net.minecraftforge.fluids.FluidTankInfo; import net.minecraftforge.fluids.IFluidHandler; import javax.annotation.Nullable; +import java.io.IOException; -public class TileFluidInterface extends TileInterface implements IFluidHandler +public class TileFluidInterface extends TileInterface implements IFluidHandler, IAEFluidInventory { - private final BaseActionSource ownActionSource = new MachineSource(this); + private final DualityFluidInterface fluidDuality = new DualityFluidInterface(this.getProxy(), this) { + @Override + public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) { + return this.getTanks().drain(from.ordinal(), maxDrain, doDrain); + } + }; + private final AppEngInternalAEInventory config = new AppEngInternalAEInventory(this, 6); - private IMEMonitor getFluidGrid() { - try { - return getProxy().getGrid().getCache(IStorageGrid.class).getFluidInventory(); - } catch (GridAccessException e) { - return null; + @MENetworkEventSubscribe + public void stateChange(final MENetworkChannelsChanged c) { + fluidDuality.onChannelStateChange(c); + } + + @MENetworkEventSubscribe + public void stateChange(final MENetworkPowerStatusChange c) { + fluidDuality.onPowerStateChange(c); + } + + @Override + public void gridChanged() { + super.gridChanged(); + fluidDuality.gridChanged(); + } + + public DualityFluidInterface getDualityFluid() { + return fluidDuality; + } + + public AEFluidInventory getInternalFluid() { + return fluidDuality.getTanks(); + } + + public AppEngInternalAEInventory getConfig() { + for (int i = 0; i < fluidDuality.getConfig().getSlots(); i ++) { + IAEFluidStack fluid = fluidDuality.getConfig().getFluidInSlot(i); + if (fluid == null) { + config.setInventorySlotContents(i, null); + } + else { + config.setInventorySlotContents(i, ItemFluidPacket.newDisplayStack(fluid.getFluidStack())); + } + } + return config; + } + + @Override + public TickingRequest getTickingRequest(IGridNode node) { + TickingRequest item = super.getTickingRequest(node); + TickingRequest fluid = fluidDuality.getTickingRequest(node); + return new TickingRequest( + Math.min(item.minTickRate, fluid.minTickRate), + Math.max(item.maxTickRate, fluid.maxTickRate), + item.isSleeping && fluid.isSleeping, + true); + } + + @Override + public TickRateModulation tickingRequest(IGridNode node, int ticksSinceLastCall) { + TickRateModulation item = super.tickingRequest(node, ticksSinceLastCall); + TickRateModulation fluid = fluidDuality.tickingRequest(node, ticksSinceLastCall); + if (item.ordinal() >= fluid.ordinal()) { + return item; + } else { + return fluid; } } - private IEnergyGrid getEnergyGrid() { - try { - return getProxy().getGrid().getCache(IEnergyGrid.class); - } catch (GridAccessException e) { - return null; + @TileEvent( TileEventType.NETWORK_WRITE ) + protected void writeToStream(ByteBuf data) throws IOException { + for (int i = 0; i < config.getSizeInventory(); i++) { + ByteBufUtils.writeItemStack(data, config.getStackInSlot(i)); + for (int j = 0; j < config.getSizeInventory(); j ++) { + FluidStack fluid = ItemFluidPacket.getFluidStack(config.getStackInSlot(j)); + fluidDuality.getConfig().setFluidInSlot(j, fluidDuality.getStandardFluid(fluid)); + } } + int fluidMask = 0; + for (int i = 0; i < getInternalFluid().getSlots(); i++) { + if (getInternalFluid().getFluidInSlot(i) != null) { + fluidMask |= 1 << i; + } + } + data.writeByte(fluidMask); + for (int i = 0; i < getInternalFluid().getSlots(); i++) { + IAEFluidStack fluid = getInternalFluid().getFluidInSlot(i); + if (fluid != null) { + fluid.writeToPacket(data); + } + } + } + + @TileEvent( TileEventType.NETWORK_READ ) + protected boolean readFromStream(ByteBuf data) throws IOException { + boolean changed = false; + for (int i = 0; i < config.getSizeInventory(); i++) { + ItemStack stack = ByteBufUtils.readItemStack(data); + if (!ItemStack.areItemStacksEqual(stack, config.getStackInSlot(i))) { + config.setInventorySlotContents(i, stack); + changed = true; + } + for (int j = 0; j < config.getSizeInventory(); j ++) { + FluidStack fluid = ItemFluidPacket.getFluidStack(config.getStackInSlot(j)); + fluidDuality.getConfig().setFluidInSlot(j, fluidDuality.getStandardFluid(fluid)); + } + } + int fluidMask = data.readByte(); + for (int i = 0; i < getInternalFluid().getSlots(); i++) { + if ((fluidMask & (1 << i)) != 0) { + IAEFluidStack fluid = AEFluidStack.loadFluidStackFromPacket(data); + if (fluid != null) { // this shouldn't happen, but better safe than sorry + IAEFluidStack origFluid = getInternalFluid().getFluidInSlot(i); + if (!fluid.equals(origFluid) || fluid.getStackSize() != origFluid.getStackSize()) { + getInternalFluid().setFluidInSlot(i, fluid); + changed = true; + } + } + } else if (getInternalFluid().getFluidInSlot(i) != null) { + getInternalFluid().setFluidInSlot(i, null); + changed = true; + } + } + return changed; + } + + @TileEvent( TileEventType.WORLD_NBT_READ ) + public void readFromNBTEvent(NBTTagCompound data) { + config.readFromNBT(data, "ConfigInv"); + for (int i = 0; i < config.getSizeInventory(); i ++) { + FluidStack fluid = ItemFluidPacket.getFluidStack(config.getStackInSlot(i)); + fluidDuality.getConfig().setFluidInSlot(i, fluidDuality.getStandardFluid(fluid)); + } + getInternalFluid().readFromNBT(data, "FluidInv"); + } + + @TileEvent( TileEventType.WORLD_NBT_WRITE ) + public NBTTagCompound writeToNBTEvent(NBTTagCompound data) { + config.writeToNBT(data, "ConfigInv"); + getInternalFluid().writeToNBT(data, "FluidInv"); + return data; } @Nullable @@ -61,42 +199,52 @@ public class TileFluidInterface extends TileInterface implements IFluidHandler @Override public int fill(ForgeDirection from, FluidStack resource, boolean doFill) { - IMEMonitor fluidGrid = getFluidGrid(); - IEnergyGrid energyGrid = getEnergyGrid(); - if (energyGrid == null || fluidGrid == null || resource == null) - return 0; - int ori = resource.amount; - IAEFluidStack remove; - if (doFill) { - remove = Platform.poweredInsert(energyGrid, fluidGrid, AEFluidStack.create(resource), ownActionSource); - } else { - remove = fluidGrid.injectItems(AEFluidStack.create(resource), Actionable.SIMULATE, ownActionSource); - } - return remove == null ? ori : (int) (ori - remove.getStackSize()); + return fluidDuality.fill(from, resource, doFill); } @Override public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain) { - return null; + return fluidDuality.drain(from, resource, doDrain); } @Override public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) { - return null; + return fluidDuality.drain(from, maxDrain, doDrain); } @Override public boolean canFill(ForgeDirection from, Fluid fluid) { - return true; + return fluidDuality.canFill(from, fluid); } @Override public boolean canDrain(ForgeDirection from, Fluid fluid) { - return false; + return true; } @Override public FluidTankInfo[] getTankInfo(ForgeDirection from) { - return new FluidTankInfo[]{new FluidTankInfo(null, 0)}; + return fluidDuality.getTankInfo(from); } + + @Override + public void onFluidInventoryChanged(IAEFluidTank inv, int slot) { + saveChanges(); + markForUpdate(); + fluidDuality.onFluidInventoryChanged(inv, slot); + } + + public void setConfig(int id, IAEFluidStack fluid) { + if (id >= 0 && id < 6) { + config.setInventorySlotContents(id, ItemFluidPacket.newDisplayStack(fluid == null ? null : fluid.getFluidStack())); + fluidDuality.getConfig().setFluidInSlot(id, fluidDuality.getStandardFluid(fluid)); + } + } + + public void setFluidInv(int id, IAEFluidStack fluid) { + if (id >= 0 && id < 6) { + getInternalFluid().setFluidInSlot(id, fluid); + } + } + } diff --git a/src/main/java/com/glodblock/github/common/tile/TileFluidPatternEncoder.java b/src/main/java/com/glodblock/github/common/tile/TileFluidPatternEncoder.java index a0f1cac5..315e6ed5 100644 --- a/src/main/java/com/glodblock/github/common/tile/TileFluidPatternEncoder.java +++ b/src/main/java/com/glodblock/github/common/tile/TileFluidPatternEncoder.java @@ -43,10 +43,6 @@ public class TileFluidPatternEncoder extends AEBaseTile implements IAEAppEngInve @Override public void getDrops(final World w, final int x, final int y, final int z, final List drops ) { - getDrops(w, new BlockPos(x, y, z), drops); - } - - public void getDrops(World world, BlockPos pos, List drops) { for (ItemStack stack : patternInv) { if (stack != null) { drops.add(stack); diff --git a/src/main/java/com/glodblock/github/common/tile/TileIngredientBuffer.java b/src/main/java/com/glodblock/github/common/tile/TileIngredientBuffer.java index 8a3817e5..37135e4d 100644 --- a/src/main/java/com/glodblock/github/common/tile/TileIngredientBuffer.java +++ b/src/main/java/com/glodblock/github/common/tile/TileIngredientBuffer.java @@ -149,6 +149,6 @@ public class TileIngredientBuffer extends AEBaseInvTile implements IAEFluidInven @Override public FluidTankInfo[] getTankInfo(ForgeDirection from) { - return invFluids.getTankInfo(ForgeDirection.UNKNOWN); + return invFluids.getTankInfo(from); } } diff --git a/src/main/java/com/glodblock/github/common/tile/TileOCPatternEditor.java b/src/main/java/com/glodblock/github/common/tile/TileOCPatternEditor.java new file mode 100644 index 00000000..2342aec8 --- /dev/null +++ b/src/main/java/com/glodblock/github/common/tile/TileOCPatternEditor.java @@ -0,0 +1,35 @@ +package com.glodblock.github.common.tile; + +import appeng.items.misc.ItemEncodedPattern; +import appeng.tile.AEBaseInvTile; +import appeng.tile.inventory.AppEngInternalInventory; +import appeng.tile.inventory.InvOperation; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.util.ForgeDirection; + +public class TileOCPatternEditor extends AEBaseInvTile { + + private final AppEngInternalInventory invItems = new AppEngInternalInventory(this, 16); + + @Override + public IInventory getInternalInventory() { + return invItems; + } + + @Override + public void onChangeInventory(IInventory inv, int slot, InvOperation mc, ItemStack removed, ItemStack added) { + markForUpdate(); + } + + @Override + public int[] getAccessibleSlotsBySide(ForgeDirection whichSide) { + return new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + } + + @Override + public boolean isItemValidForSlot( final int i, final ItemStack itemstack ) { + return itemstack == null || itemstack.getItem() instanceof ItemEncodedPattern; + } + +} diff --git a/src/main/java/com/glodblock/github/coremod/hooker/CoreModHooks.java b/src/main/java/com/glodblock/github/coremod/hooker/CoreModHooks.java index 21bae394..14d5ef56 100644 --- a/src/main/java/com/glodblock/github/coremod/hooker/CoreModHooks.java +++ b/src/main/java/com/glodblock/github/coremod/hooker/CoreModHooks.java @@ -98,4 +98,11 @@ public class CoreModHooks { else return aeStack.getItemStack(); } + public static long getFluidSize(IAEItemStack aeStack) { + if (aeStack.getItemStack() != null && aeStack.getItemStack().getItem() instanceof ItemFluidDrop) { + return (long) Math.max(aeStack.getStackSize() / 1000D, 1); + } + else return aeStack.getStackSize(); + } + } diff --git a/src/main/java/com/glodblock/github/coremod/transform/CraftingCpuTransformer.java b/src/main/java/com/glodblock/github/coremod/transform/CraftingCpuTransformer.java index f65a9e61..985ec9c3 100644 --- a/src/main/java/com/glodblock/github/coremod/transform/CraftingCpuTransformer.java +++ b/src/main/java/com/glodblock/github/coremod/transform/CraftingCpuTransformer.java @@ -6,7 +6,7 @@ import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; -public class CraftingCpuTransformer extends FCClassTransformer.ClassMapper { +public class CraftingCpuTransformer extends FCClassTransformer.ClassMapper { public static final CraftingCpuTransformer INSTANCE = new CraftingCpuTransformer(); @@ -38,6 +38,7 @@ public class CraftingCpuTransformer extends FCClassTransformer.ClassMapper { private static class TransformExecuteCrafting extends MethodVisitor { private boolean gotInventory = false; + private int reach_stack = 0; TransformExecuteCrafting(int api, MethodVisitor mv) { super(api, mv); @@ -58,8 +59,28 @@ public class CraftingCpuTransformer extends FCClassTransformer.ClassMapper { super.visitLineNumber(line, start); } + @Override + public void visitJumpInsn(int opcode, Label label) { + if (opcode == Opcodes.IFNULL && reach_stack == 0) { + reach_stack = 1; + } + super.visitJumpInsn(opcode, label); + } + @Override public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { + if (reach_stack == 1) { + if (opcode == Opcodes.INVOKEINTERFACE + && owner.equals("appeng/api/storage/data/IAEItemStack") && name.equals("getStackSize")) { + reach_stack = 2; + super.visitMethodInsn(Opcodes.INVOKESTATIC, + "com/glodblock/github/coremod/hooker/CoreModHooks", + "getFluidSize", + "(Lappeng/api/storage/data/IAEItemStack;)J", + false); + return; + } + } super.visitMethodInsn(opcode, owner, name, desc, itf); if (gotInventory) { if (opcode == Opcodes.INVOKESTATIC diff --git a/src/main/java/com/glodblock/github/crossmod/opencomputers/DriverOCPatternEditor.java b/src/main/java/com/glodblock/github/crossmod/opencomputers/DriverOCPatternEditor.java new file mode 100644 index 00000000..94e24055 --- /dev/null +++ b/src/main/java/com/glodblock/github/crossmod/opencomputers/DriverOCPatternEditor.java @@ -0,0 +1,275 @@ +package com.glodblock.github.crossmod.opencomputers; + +import appeng.items.misc.ItemEncodedPattern; +import appeng.util.item.AEItemStack; +import com.glodblock.github.common.item.ItemFluidDrop; +import com.glodblock.github.common.item.ItemFluidEncodedPattern; +import com.glodblock.github.common.tile.TileOCPatternEditor; +import com.glodblock.github.loader.ItemAndBlockHolder; +import com.glodblock.github.util.NameConst; +import com.glodblock.github.util.Util; +import li.cil.oc.api.driver.EnvironmentProvider; +import li.cil.oc.api.driver.NamedBlock; +import li.cil.oc.api.internal.Database; +import li.cil.oc.api.machine.Arguments; +import li.cil.oc.api.machine.Callback; +import li.cil.oc.api.machine.Context; +import li.cil.oc.api.network.Component; +import li.cil.oc.api.network.ManagedEnvironment; +import li.cil.oc.api.network.Node; +import li.cil.oc.api.prefab.DriverSidedTileEntity; +import li.cil.oc.integration.ManagedTileEntityEnvironment; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.world.World; +import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.fluids.FluidStack; + +public class DriverOCPatternEditor extends DriverSidedTileEntity { + + public DriverOCPatternEditor() { + } + + @Override + public Class getTileEntityClass() { + return TileOCPatternEditor.class; + } + + @Override + public ManagedEnvironment createEnvironment(World world, int x, int y, int z, ForgeDirection forgeDirection) { + return new DriverOCPatternEditor.Environment((TileOCPatternEditor) world.getTileEntity(x, y, z)); + } + + public static class Environment extends ManagedTileEntityEnvironment + implements NamedBlock { + + public Environment(TileOCPatternEditor tileEntity) { + super(tileEntity, NameConst.BLOCK_OC_PATTERN_EDITOR); + } + + private int optSlot(Arguments args, IInventory inv, int index, int def) { + if (index >= 0 && index < args.count()) { + int slot = args.checkInteger(index) - 1; + if (slot < 0 || slot >= inv.getSizeInventory()) { + throw new IllegalArgumentException("invalid slot"); + } + return slot; + } + else { + return def; + } + } + + private int checkSlot(Arguments args, IInventory inv, int index) { + if (index >= 0 && index < args.count()) { + int slot = args.checkInteger(index) - 1; + if (slot < 0 || slot >= inv.getSizeInventory()) { + throw new IllegalArgumentException("invalid slot"); + } + return slot; + } + else { + throw new IllegalArgumentException("invalid slot"); + } + } + + private boolean validPattern(ItemStack pattern) { + if (pattern == null) { + throw new IllegalArgumentException("No pattern here!"); + } + if (pattern.getItem() instanceof ItemEncodedPattern && !(pattern.getItem() instanceof ItemFluidEncodedPattern)) { + ItemEncodedPattern iep = (ItemEncodedPattern) pattern.getItem(); + return iep.getOutput(pattern) == null; + } + return true; + } + + private ItemStack getStack(Arguments args) { + if (args.count() > 1) { + String address; + int entry; + int size; + if (args.isString(0)) { + address = args.checkString(0); + entry = args.checkInteger(1); + size = args.optInteger(2, 1); + } + else { + address = args.checkString(1); + entry = args.checkInteger(2); + size = args.optInteger(3, 1); + } + Node node = node().network().node(address); + if (node instanceof Component) { + if (node.host() instanceof Database) { + ItemStack dbStack = ((Database) node.host()).getStackInSlot(entry - 1); + if (dbStack == null || size < 1) { + return null; + } + else { + dbStack.stackSize = Math.min(size, dbStack.getMaxStackSize()); + return dbStack; + } + } + else { + throw new IllegalArgumentException("not a database"); + } + } + else { + throw new IllegalArgumentException("no such component"); + } + } + else { + return null; + } + } + + private Object[] clearInterfacePattern(Context context, Arguments args, String tag) { + IInventory inv = tileEntity.getInternalInventory(); + ItemStack pattern = inv.getStackInSlot(checkSlot(args, inv, 0)); + if (validPattern(pattern)) { + NBTTagCompound encodedValue = pattern.getTagCompound(); + int slot = checkSlot(args, inv, 0); + if (encodedValue == null) + throw new IllegalArgumentException("No pattern here!"); + NBTTagList nbt = encodedValue.getTagList(tag, 10); + int index = args.checkInteger(1) - 1; + if (index < 0) + throw new IllegalArgumentException("Invalid index!"); + nbt.removeTag(index); + encodedValue.setTag(tag, nbt); + pattern.setTagCompound(encodedValue); + inv.setInventorySlotContents(slot, null); + inv.setInventorySlotContents(slot, pattern); + context.pause(0.1); + return new Object[] {true}; + } else { + throw new IllegalArgumentException("Not Fluid Encoded pattern!"); + } + } + + private Object[] setPatternSlot(Context context, Arguments args, String tag, boolean fluid) { + IInventory inv = tileEntity.getInternalInventory(); + int slot = args.isString(0) ? 0 : optSlot(args, inv, 0, 0); + ItemStack stack = getStack(args); + if (fluid) { + FluidStack fluids = Util.getFluidFromItem(stack); + stack = ItemFluidDrop.newStack(fluids); + } + int index = args.checkInteger(4) - 1; + if (index < 0 || index > 511) + throw new IllegalArgumentException("Invalid index!"); + ItemStack pattern = inv.getStackInSlot(slot); + if (validPattern(pattern)) { + NBTTagCompound encodedValue = pattern.getTagCompound(); + if (encodedValue == null) + throw new IllegalArgumentException("No pattern here!"); + + NBTTagList inTag = encodedValue.getTagList(tag, 10); + while (inTag.tagCount() <= index) + inTag.appendTag(new NBTTagCompound()); + if (stack != null) { + NBTTagCompound nbt = new NBTTagCompound(); + AEItemStack aeStack = AEItemStack.create(stack); + aeStack.writeToNBT(nbt); + inTag.func_150304_a(index, nbt); + } + else { + inTag.removeTag(index); + } + encodedValue.setTag(tag, inTag); + pattern.setTagCompound(encodedValue); + inv.setInventorySlotContents(slot, null); + inv.setInventorySlotContents(slot, pattern); + context.pause(0.1); + return new Object[] {true}; + } else { + throw new IllegalArgumentException("Not Fluid Encoded pattern!"); + } + } + + @Callback(doc = "function([slot:number]):table -- Get the configuration of the interface.") + public Object[] getInterfaceConfiguration(Context context, Arguments args) { + IInventory config = tileEntity.getInternalInventory(); + int slot = optSlot(args, config, 0, 0); + ItemStack stack = config.getStackInSlot(slot); + if (!validPattern(stack )) { + throw new IllegalArgumentException("Not Fluid Encoded pattern!"); + } + return new Object[]{stack}; + } + + @Callback(doc = "function([slot:number][, database:address, entry:number[, size:number]]):boolean -- Configure the interface.") + public Object[] setInterfaceConfiguration(Context context, Arguments args) { + IInventory config = tileEntity.getInternalInventory(); + int slot = args.isString(0) ? 0 : optSlot(args, config, 0, 0); + config.setInventorySlotContents(slot, getStack(args)); + context.pause(0.5); + return new Object[] {true}; + } + + @Callback(doc = "function([slot:number]):table -- Get the given pattern in the interface.") + public Object[] getInterfacePattern(Context context, Arguments args) { + IInventory inv = tileEntity.getInternalInventory(); + int slot = optSlot(args, inv, 0, 0); + ItemStack stack = inv.getStackInSlot(slot); + return new Object[] {stack}; + } + + @Callback(doc = "function(slot:number, database:address, entry:number, size:number, index:number):boolean -- Set the pattern item input at the given index.") + public Object[] setInterfacePatternItemInput(Context context, Arguments args) { + return setPatternSlot(context, args, "in", false); + } + + @Callback(doc = "function(slot:number, database:address, entry:number, size:number, index:number):boolean -- Set the pattern item output at the given index.") + public Object[] setInterfacePatternItemOutput(Context context, Arguments args) { + return setPatternSlot(context, args, "out", false); + } + + @Callback(doc = "function(slot:number, database:address, entry:number, size:number, index:number):boolean -- Set the pattern fluid input at the given index.") + public Object[] setInterfacePatternFluidInput(Context context, Arguments args) { + return setPatternSlot(context, args, "in", true); + } + + @Callback(doc = "function(slot:number, database:address, entry:number, size:number, index:number):boolean -- Set the pattern fluid output at the given index.") + public Object[] setInterfacePatternFluidOutput(Context context, Arguments args) { + return setPatternSlot(context, args, "out", true); + } + + @Callback(doc = "function(slot:number, index:number):boolean -- Clear pattern input at the given index.") + public Object[] clearInterfacePatternInput(Context context, Arguments args) { + return clearInterfacePattern(context, args, "in"); + } + + @Callback(doc = "function(slot:number, index:number):boolean -- Clear pattern output at the given index.") + public Object[] clearInterfacePatternOutput(Context context, Arguments args) { + return clearInterfacePattern(context, args, "out"); + } + + @Override + public String preferredName() { + return NameConst.BLOCK_OC_PATTERN_EDITOR; + } + + @Override + public int priority() { + return 5; + } + } + + public static class Provider implements EnvironmentProvider { + Provider() { + } + + @Override + public Class getEnvironment(ItemStack itemStack) { + if (itemStack != null && itemStack.isItemEqual(ItemAndBlockHolder.OC_EDITOR.stack())) { + return DriverOCPatternEditor.Environment.class; + } + return null; + } + } + +} diff --git a/src/main/java/com/glodblock/github/crossmod/opencomputers/OCDriverInit.java b/src/main/java/com/glodblock/github/crossmod/opencomputers/OCDriverInit.java new file mode 100644 index 00000000..35cd6554 --- /dev/null +++ b/src/main/java/com/glodblock/github/crossmod/opencomputers/OCDriverInit.java @@ -0,0 +1,12 @@ +package com.glodblock.github.crossmod.opencomputers; + +import li.cil.oc.api.Driver; + +public class OCDriverInit { + + public static void run() { + Driver.add(new DriverOCPatternEditor()); + Driver.add(new DriverOCPatternEditor.Provider()); + } + +} diff --git a/src/main/java/com/glodblock/github/inventory/AEFluidInventory.java b/src/main/java/com/glodblock/github/inventory/AEFluidInventory.java index acd3574e..5fac85b7 100644 --- a/src/main/java/com/glodblock/github/inventory/AEFluidInventory.java +++ b/src/main/java/com/glodblock/github/inventory/AEFluidInventory.java @@ -21,7 +21,6 @@ public class AEFluidInventory implements IAEFluidTank private final IAEFluidStack[] fluids; private final IAEFluidInventory handler; private final int capacity; - private FluidTankInfo[] props = null; public AEFluidInventory( final IAEFluidInventory handler, final int slots, final int capcity ) { @@ -40,9 +39,9 @@ public class AEFluidInventory implements IAEFluidTank { if( slot >= 0 && slot < this.getSlots() ) { - if( Objects.equals( this.fluids[slot], fluid ) ) + if( fluid != null && this.fluids[slot] != null && fluid.getFluidStack().isFluidEqual(this.fluids[slot].getFluidStack()) ) { - if( fluid != null && fluid.getStackSize() != this.fluids[slot].getStackSize() ) + if(fluid.getStackSize() != this.fluids[slot].getStackSize()) { this.fluids[slot].setStackSize( Math.min( fluid.getStackSize(), this.capacity ) ); this.onContentChanged( slot ); @@ -83,6 +82,15 @@ public class AEFluidInventory implements IAEFluidTank return null; } + public FluidStack getFluidStackInSlot( final int slot ) + { + if( getFluidInSlot(slot) != null ) + { + return getFluidInSlot(slot).getFluidStack(); + } + return null; + } + @Override public int getSlots() { @@ -92,16 +100,12 @@ public class AEFluidInventory implements IAEFluidTank @Override public FluidTankInfo[] getTankInfo(ForgeDirection from) { - if( this.props == null ) + FluidTankInfo[] props = new FluidTankInfo[this.getSlots()]; + for( int i = 0; i < this.getSlots(); ++i ) { - this.props = new FluidTankInfo[this.getSlots()]; - for( int i = 0; i < this.getSlots(); ++i ) - { - this.props[i] = new FluidTankInfo(new FluidTankPropertiesWrapper( i )); - } - + props[i] = new FluidTankInfo(new FluidTankPropertiesWrapper( i )); } - return this.props; + return props; } public int fill( final int slot, final FluidStack resource, final boolean doFill ) @@ -146,7 +150,7 @@ public class AEFluidInventory implements IAEFluidTank public FluidStack drain( final int slot, final FluidStack resource, final boolean doDrain ) { final IAEFluidStack fluid = this.fluids[slot]; - if(fluid == null || !fluid.getFluidStack().equals(resource)) + if(fluid == null || !fluid.getFluidStack().isFluidEqual(resource)) { return null; } @@ -217,6 +221,9 @@ public class AEFluidInventory implements IAEFluidTank FluidStack totalDrained = null; for( int slot = 0; slot < this.getSlots(); ++slot ) { + if (!fluid.isFluidEqual(getFluidStackInSlot(slot))) { + continue; + } FluidStack drain = this.drain( slot, resource, doDrain ); if( drain != null ) { @@ -252,6 +259,10 @@ public class AEFluidInventory implements IAEFluidTank for( int slot = 0; slot < this.getSlots(); ++slot ) { + if (this.getFluidInSlot(slot) == null) { + continue; + } + if( totalDrained == null ) { totalDrained = this.drain( slot, toDrain, doDrain ); @@ -380,7 +391,7 @@ public class AEFluidInventory implements IAEFluidTank @Override public int fill(FluidStack resource, boolean doFill) { - if (resource == null || (getFluid() != null && !resource.equals(getFluid()))) return 0; + if (resource == null || (getFluid() != null && !resource.isFluidEqual(getFluid()))) return 0; int acc = 0; if (getFluid() == null) { acc = Math.min(resource.amount, getCapacity()); diff --git a/src/main/java/com/glodblock/github/inventory/MEMonitorIFluidHandler.java b/src/main/java/com/glodblock/github/inventory/MEMonitorIFluidHandler.java new file mode 100644 index 00000000..4a260af6 --- /dev/null +++ b/src/main/java/com/glodblock/github/inventory/MEMonitorIFluidHandler.java @@ -0,0 +1,203 @@ +package com.glodblock.github.inventory; + +import appeng.api.AEApi; +import appeng.api.config.AccessRestriction; +import appeng.api.config.Actionable; +import appeng.api.config.StorageFilter; +import appeng.api.networking.security.BaseActionSource; +import appeng.api.networking.ticking.TickRateModulation; +import appeng.api.storage.IMEMonitor; +import appeng.api.storage.IMEMonitorHandlerReceiver; +import appeng.api.storage.StorageChannel; +import appeng.api.storage.data.IAEFluidStack; +import appeng.api.storage.data.IItemList; +import appeng.util.item.AEFluidStack; +import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidTankInfo; +import net.minecraftforge.fluids.IFluidHandler; + +import java.util.*; + +public class MEMonitorIFluidHandler implements IMEMonitor { + private final IFluidHandler handler; + private IItemList cache = AEApi.instance().storage().createFluidList(); + private final HashMap, Object> listeners = new HashMap<>(); + private BaseActionSource mySource; + private StorageFilter mode; + + public MEMonitorIFluidHandler(IFluidHandler handler) { + this.mode = StorageFilter.EXTRACTABLE_ONLY; + this.handler = handler; + } + + public void addListener(IMEMonitorHandlerReceiver l, Object verificationToken) { + this.listeners.put(l, verificationToken); + } + + public void removeListener(IMEMonitorHandlerReceiver l) { + this.listeners.remove(l); + } + + public IAEFluidStack injectItems(IAEFluidStack input, Actionable type, BaseActionSource src) { + int filled = this.handler.fill(ForgeDirection.UNKNOWN, input.getFluidStack(), type == Actionable.MODULATE); + if (filled == 0) { + return input.copy(); + } else if ((long)filled == input.getStackSize()) { + return null; + } else { + IAEFluidStack o = input.copy(); + o.setStackSize(input.getStackSize() - (long)filled); + if (type == Actionable.MODULATE) { + IAEFluidStack added = o.copy(); + this.cache.add(added); + this.postDifference(Collections.singletonList(added)); + this.onTick(); + } + return o; + } + } + + public IAEFluidStack extractItems(IAEFluidStack request, Actionable type, BaseActionSource src) { + FluidStack removed = this.handler.drain(ForgeDirection.UNKNOWN, request.getFluidStack(), type == Actionable.MODULATE); + if (removed != null && removed.amount != 0) { + IAEFluidStack o = request.copy(); + o.setStackSize(removed.amount); + if (type == Actionable.MODULATE) { + IAEFluidStack cachedStack = this.cache.findPrecise(request); + if (cachedStack != null) { + cachedStack.decStackSize(o.getStackSize()); + this.postDifference(Collections.singletonList(o.copy().setStackSize(-o.getStackSize()))); + } + } + return o; + } else { + return null; + } + } + + @Override + public StorageChannel getChannel() + { + return StorageChannel.FLUIDS; + } + + //*Decompiled Stuff*// + + public TickRateModulation onTick() { + boolean changed = false; + List changes = new ArrayList<>(); + FluidTankInfo[] tankProperties = this.handler.getTankInfo(ForgeDirection.UNKNOWN); + IItemList currentlyOnStorage = AEApi.instance().storage().createFluidList(); + + for (FluidTankInfo tankProperty : tankProperties) { + if (this.mode != StorageFilter.EXTRACTABLE_ONLY || this.handler.drain(ForgeDirection.UNKNOWN, 1, false) != null) { + currentlyOnStorage.add(AEFluidStack.create(tankProperty.fluid)); + } + } + + Iterator var9 = this.cache.iterator(); + + IAEFluidStack is; + while(var9.hasNext()) { + is = (IAEFluidStack)var9.next(); + is.setStackSize(-is.getStackSize()); + } + + var9 = currentlyOnStorage.iterator(); + + while(var9.hasNext()) { + is = (IAEFluidStack)var9.next(); + this.cache.add(is); + } + + var9 = this.cache.iterator(); + + while(var9.hasNext()) { + is = (IAEFluidStack)var9.next(); + if (is.getStackSize() != 0L) { + changes.add(is); + } + } + + this.cache = currentlyOnStorage; + if (!changes.isEmpty()) { + this.postDifference(changes); + changed = true; + } + + return changed ? TickRateModulation.URGENT : TickRateModulation.SLOWER; + } + + private void postDifference(Iterable a) { + if (a != null) { + Iterator i = this.listeners.entrySet().iterator(); + + while(i.hasNext()) { + Map.Entry, Object> l = (Map.Entry)i.next(); + IMEMonitorHandlerReceiver key = l.getKey(); + if (key.isValid(l.getValue())) { + key.postChange(this, a, this.getActionSource()); + } else { + i.remove(); + } + } + } + + } + + public AccessRestriction getAccess() { + return AccessRestriction.READ_WRITE; + } + + public boolean isPrioritized(IAEFluidStack input) { + return false; + } + + public boolean canAccept(IAEFluidStack input) { + return true; + } + + public int getPriority() { + return 0; + } + + public int getSlot() { + return 0; + } + + public boolean validForPass(int i) { + return true; + } + + public IItemList getAvailableItems(IItemList out) { + Iterator var2 = this.cache.iterator(); + + while(var2.hasNext()) { + IAEFluidStack fs = (IAEFluidStack)var2.next(); + out.addStorage(fs); + } + + return out; + } + + public IItemList getStorageList() { + return this.cache; + } + + private StorageFilter getMode() { + return this.mode; + } + + public void setMode(StorageFilter mode) { + this.mode = mode; + } + + private BaseActionSource getActionSource() { + return this.mySource; + } + + public void setActionSource(BaseActionSource mySource) { + this.mySource = mySource; + } +} diff --git a/src/main/java/com/glodblock/github/inventory/gui/GuiType.java b/src/main/java/com/glodblock/github/inventory/gui/GuiType.java index 19c0e124..37175c28 100644 --- a/src/main/java/com/glodblock/github/inventory/gui/GuiType.java +++ b/src/main/java/com/glodblock/github/inventory/gui/GuiType.java @@ -3,13 +3,15 @@ package com.glodblock.github.inventory.gui; import appeng.api.storage.ITerminalHost; import appeng.container.implementations.ContainerCraftAmount; import appeng.container.implementations.ContainerCraftingStatus; +import appeng.container.implementations.ContainerInterface; +import appeng.container.implementations.ContainerPriority; +import appeng.helpers.IPriorityHost; import com.glodblock.github.client.gui.*; import com.glodblock.github.client.gui.container.*; import com.glodblock.github.common.parts.FCBasePart; +import com.glodblock.github.common.parts.PartFluidInterface; import com.glodblock.github.common.parts.PartSharedFluidBus; -import com.glodblock.github.common.tile.TileFluidPacketDecoder; -import com.glodblock.github.common.tile.TileFluidPatternEncoder; -import com.glodblock.github.common.tile.TileIngredientBuffer; +import com.glodblock.github.common.tile.*; import com.google.common.collect.ImmutableList; import net.minecraft.entity.player.EntityPlayer; @@ -18,6 +20,90 @@ import java.util.List; public enum GuiType { + OC_PATTERN_EDITOR(new TileGuiFactory(TileOCPatternEditor.class) { + @Override + protected Object createServerGui(EntityPlayer player, TileOCPatternEditor inv) { + return new ContainerOCPatternEditor(player.inventory, inv); + } + + @Override + protected Object createClientGui(EntityPlayer player, TileOCPatternEditor inv) { + return new GuiOCPatternEditor(player.inventory, inv); + } + }), + + DUAL_INTERFACE_PART(new PartGuiFactory(PartFluidInterface.class) { + @Override + protected Object createServerGui(EntityPlayer player, PartFluidInterface inv) { + return new ContainerInterface(player.inventory, inv); + } + + @Override + protected Object createClientGui(EntityPlayer player, PartFluidInterface inv) { + return new GuiDualInterface(player.inventory, inv); + } + }), + + DUAL_INTERFACE_FLUID_PART(new PartGuiFactory(PartFluidInterface.class) { + @Override + protected Object createServerGui(EntityPlayer player, PartFluidInterface inv) { + return new ContainerFluidInterface(player.inventory, inv); + } + + @Override + protected Object createClientGui(EntityPlayer player, PartFluidInterface inv) { + return new GuiFluidInterface(player.inventory, inv); + } + }), + + DUAL_INTERFACE(new TileGuiFactory(TileFluidInterface.class) { + @Override + protected Object createServerGui(EntityPlayer player, TileFluidInterface inv) { + return new ContainerInterface(player.inventory, inv); + } + + @Override + protected Object createClientGui(EntityPlayer player, TileFluidInterface inv) { + return new GuiDualInterface(player.inventory, inv); + } + }), + + DUAL_INTERFACE_FLUID(new TileGuiFactory(TileFluidInterface.class) { + @Override + protected Object createServerGui(EntityPlayer player, TileFluidInterface inv) { + return new ContainerFluidInterface(player.inventory, inv); + } + + @Override + protected Object createClientGui(EntityPlayer player, TileFluidInterface inv) { + return new GuiFluidInterface(player.inventory, inv); + } + }), + + DUAL_INTERFACE_PRIORITY_PART(new PartGuiFactory(IPriorityHost.class) { + @Override + protected Object createServerGui(EntityPlayer player, IPriorityHost inv) { + return new ContainerPriority(player.inventory, inv); + } + + @Override + protected Object createClientGui(EntityPlayer player, IPriorityHost inv) { + return new GuiFCPriority(player.inventory, inv); + } + }), + + DUAL_INTERFACE_PRIORITY(new TileGuiFactory(IPriorityHost.class) { + @Override + protected Object createServerGui(EntityPlayer player, IPriorityHost inv) { + return new ContainerPriority(player.inventory, inv); + } + + @Override + protected Object createClientGui(EntityPlayer player, IPriorityHost inv) { + return new GuiFCPriority(player.inventory, inv); + } + }), + FLUID_BUS_IO(new PartGuiFactory(PartSharedFluidBus.class) { @Override protected Object createServerGui(EntityPlayer player, PartSharedFluidBus inv) { diff --git a/src/main/java/com/glodblock/github/inventory/gui/MouseRegionManager.java b/src/main/java/com/glodblock/github/inventory/gui/MouseRegionManager.java index 06107e85..313e2368 100644 --- a/src/main/java/com/glodblock/github/inventory/gui/MouseRegionManager.java +++ b/src/main/java/com/glodblock/github/inventory/gui/MouseRegionManager.java @@ -1,6 +1,5 @@ package com.glodblock.github.inventory.gui; -import com.glodblock.github.util.Ae2Reflect; import com.glodblock.github.util.Ae2ReflectClient; import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.client.gui.inventory.GuiContainer; diff --git a/src/main/java/com/glodblock/github/inventory/slot/OptionalFluidSlotFakeTypeOnly.java b/src/main/java/com/glodblock/github/inventory/slot/OptionalFluidSlotFakeTypeOnly.java index 6986f82a..9eeaa70b 100644 --- a/src/main/java/com/glodblock/github/inventory/slot/OptionalFluidSlotFakeTypeOnly.java +++ b/src/main/java/com/glodblock/github/inventory/slot/OptionalFluidSlotFakeTypeOnly.java @@ -2,7 +2,9 @@ package com.glodblock.github.inventory.slot; import appeng.container.slot.IOptionalSlotHost; import appeng.container.slot.OptionalSlotFakeTypeOnly; +import appeng.util.item.AEFluidStack; import com.glodblock.github.common.item.ItemFluidPacket; +import com.glodblock.github.inventory.AEFluidInventory; import com.glodblock.github.util.Util; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; @@ -10,8 +12,11 @@ import net.minecraftforge.fluids.FluidStack; public class OptionalFluidSlotFakeTypeOnly extends OptionalSlotFakeTypeOnly { - public OptionalFluidSlotFakeTypeOnly(IInventory inv, IOptionalSlotHost containerBus, int idx, int x, int y, int offX, int offY, int groupNum) { + AEFluidInventory fluidInv; + + public OptionalFluidSlotFakeTypeOnly(IInventory inv, AEFluidInventory fluidInv, IOptionalSlotHost containerBus, int idx, int x, int y, int offX, int offY, int groupNum) { super(inv, containerBus, idx, x, y, offX, offY, groupNum); + this.fluidInv = fluidInv; } @Override @@ -19,12 +24,19 @@ public class OptionalFluidSlotFakeTypeOnly extends OptionalSlotFakeTypeOnly { { FluidStack fluidStack = Util.getFluidFromItem(is); if (fluidStack != null) { - ItemStack tmp = ItemFluidPacket.newStack(fluidStack); - tmp.setStackDisplayName(fluidStack.getLocalizedName()); + ItemStack tmp = ItemFluidPacket.newDisplayStack(fluidStack); + if (fluidInv != null) { + FluidStack standard = fluidStack.copy(); + standard.amount = 8000; + fluidInv.setFluidInSlot(getSlotIndex(), AEFluidStack.create(standard)); + } super.putStack(tmp); } else { super.putStack(null); + if (fluidInv != null) { + fluidInv.setFluidInSlot(getSlotIndex(), null); + } } } diff --git a/src/main/java/com/glodblock/github/loader/ChannelLoader.java b/src/main/java/com/glodblock/github/loader/ChannelLoader.java index 9b7cee71..9073ec55 100644 --- a/src/main/java/com/glodblock/github/loader/ChannelLoader.java +++ b/src/main/java/com/glodblock/github/loader/ChannelLoader.java @@ -20,6 +20,5 @@ public class ChannelLoader implements Runnable { FluidCraft.proxy.netHandler.registerMessage(new CPacketTransferRecipe.Handler(), CPacketTransferRecipe.class, id ++, Side.SERVER); FluidCraft.proxy.netHandler.registerMessage(new CPacketDumpTank.Handler(), CPacketDumpTank.class, id ++, Side.SERVER); FluidCraft.proxy.netHandler.registerMessage(new SPacketFluidUpdate.Handler(), SPacketFluidUpdate.class, id ++, Side.CLIENT); - FluidCraft.proxy.netHandler.registerMessage(new CPacketFluidUpdate.Handler(), CPacketFluidUpdate.class, id ++, Side.SERVER); } } diff --git a/src/main/java/com/glodblock/github/loader/ItemAndBlockHolder.java b/src/main/java/com/glodblock/github/loader/ItemAndBlockHolder.java index 43758331..5fcef8d7 100644 --- a/src/main/java/com/glodblock/github/loader/ItemAndBlockHolder.java +++ b/src/main/java/com/glodblock/github/loader/ItemAndBlockHolder.java @@ -29,6 +29,7 @@ public class ItemAndBlockHolder { public static BlockFluidPacketDecoder DECODER = new BlockFluidPacketDecoder().register(); public static BlockFluidInterface INTERFACE = new BlockFluidInterface().register(); public static BlockIngredientBuffer BUFFER = new BlockIngredientBuffer().register(); + public static BlockOCPatternEditor OC_EDITOR = new BlockOCPatternEditor().register(); public static void loadSetting() { if (!Config.fluidCells) return; diff --git a/src/main/java/com/glodblock/github/loader/RecipeLoader.java b/src/main/java/com/glodblock/github/loader/RecipeLoader.java index 504cbed5..29d0e9cc 100644 --- a/src/main/java/com/glodblock/github/loader/RecipeLoader.java +++ b/src/main/java/com/glodblock/github/loader/RecipeLoader.java @@ -3,6 +3,7 @@ package com.glodblock.github.loader; import com.glodblock.github.common.Config; import com.glodblock.github.common.item.ItemBasicFluidStorageCell; import com.glodblock.github.common.storage.CellType; +import com.glodblock.github.util.ModAndClassUtil; import cpw.mods.fml.common.registry.GameRegistry; import net.minecraft.init.Blocks; import net.minecraft.init.Items; @@ -32,6 +33,9 @@ public class RecipeLoader implements Runnable { public final static ItemStack AE2_CORE_ANN = new ItemStack(GameRegistry.findItem("appliedenergistics2", "item.ItemMultiMaterial"), 1, 44); public final static ItemStack AE2_CORE_FOM = new ItemStack(GameRegistry.findItem("appliedenergistics2", "item.ItemMultiMaterial"), 1, 43); public final static ItemStack PISTON = new ItemStack(Blocks.piston, 1); + public final static ItemStack AE2_BLANK_PATTERN = new ItemStack(GameRegistry.findItem("appliedenergistics2", "item.ItemMultiMaterial"), 1, 52); + public final static ItemStack BUCKET = new ItemStack(Items.bucket, 1); + public final static ItemStack IRON_BAR = new ItemStack(Blocks.iron_bars, 1); @Override public void run() { @@ -43,7 +47,7 @@ public class RecipeLoader implements Runnable { GameRegistry.addRecipe(new ShapedOreRecipe(ENCODER.stack(), "LPL", "IWI", "III", 'I', "ingotIron", 'L', "blockLapis", 'P', AE2_PROCESS_ENG, 'W', AE2_WORK_BENCH)); GameRegistry.addShapelessRecipe(FLUID_TERMINAL.stack(), AE2_PATTERN_TERM, ENCODER); GameRegistry.addShapelessRecipe(FLUID_TERMINAL_EX.stack(), FLUID_TERMINAL.stack(), AE2_PROCESS_CAL, AE2_PROCESS_ENG, AE2_PROCESS_LOG); - GameRegistry.addRecipe(new ShapedOreRecipe(BUFFER.stack(), "ILI", "AGF", "IBI", 'I', "ingotIron", 'G', AE2_QUARTZ_GLASS, 'L', AE2_CELL_1K, 'A', AE2_CORE_ANN, 'F', AE2_CORE_FOM, 'B', Items.bucket)); + GameRegistry.addRecipe(new ShapedOreRecipe(BUFFER.stack(), "ILI", "AGF", "IBI", 'I', "ingotIron", 'G', AE2_QUARTZ_GLASS, 'L', AE2_CELL_1K, 'A', AE2_CORE_ANN, 'F', AE2_CORE_FOM, 'B', BUCKET)); if (Config.fluidCells) { OreDictionary.registerOre("anyCertusCrystal", AE2_PURE_CERTUS); @@ -73,5 +77,10 @@ public class RecipeLoader implements Runnable { GameRegistry.addRecipe(new ShapedOreRecipe(FLUID_IMPORT_BUS, "BCB", "IPI", 'B', "dyeBlue", 'I', "ingotIron", 'P', PISTON, 'C', AE2_CORE_ANN)); } + if (ModAndClassUtil.OC) { + ItemStack CHIP_T1 = new ItemStack(GameRegistry.findItem("OpenComputers", "item"), 1, 24); + GameRegistry.addRecipe(new ShapedOreRecipe(OC_EDITOR, "IMI", "CBC", "IPI", 'I', IRON_BAR, 'M', CHIP_T1, 'C', "oc:cable", 'B', BUCKET, 'P', AE2_BLANK_PATTERN)); + } + } } diff --git a/src/main/java/com/glodblock/github/network/CPacketFluidUpdate.java b/src/main/java/com/glodblock/github/network/CPacketFluidUpdate.java deleted file mode 100644 index 91766ff5..00000000 --- a/src/main/java/com/glodblock/github/network/CPacketFluidUpdate.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.glodblock.github.network; - -import appeng.api.storage.data.IAEFluidStack; -import appeng.util.item.AEFluidStack; -import com.glodblock.github.client.gui.container.ContainerFluidConfigurable; -import cpw.mods.fml.common.network.simpleimpl.IMessage; -import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; -import cpw.mods.fml.common.network.simpleimpl.MessageContext; -import io.netty.buffer.ByteBuf; -import net.minecraft.inventory.Container; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -public class CPacketFluidUpdate implements IMessage { - - private Map list; - - public CPacketFluidUpdate() { - } - - public CPacketFluidUpdate(Map data) { - this.list = data; - } - - @Override - public void fromBytes(ByteBuf buf) { - int size = buf.readInt(); - this.list = new HashMap<>(); - try { - for (int i = 0; i < size; i ++) { - int id = buf.readInt(); - boolean isNull = buf.readBoolean(); - if (!isNull) - list.put(id, null); - else { - IAEFluidStack fluid = AEFluidStack.loadFluidStackFromPacket(buf); - list.put(id, fluid); - } - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public void toBytes(ByteBuf buf) { - buf.writeInt(list.size()); - try { - for (Map.Entry fs : list.entrySet()) { - buf.writeInt(fs.getKey()); - if (fs.getValue() == null) - buf.writeBoolean(false); - else { - buf.writeBoolean(true); - fs.getValue().writeToPacket(buf); - } - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - public static class Handler implements IMessageHandler { - - @Override - public IMessage onMessage(CPacketFluidUpdate message, MessageContext ctx) { - final Container c = ctx.getServerHandler().playerEntity.openContainer; - if( c instanceof ContainerFluidConfigurable) - { - for (Map.Entry e : message.list.entrySet() ) { - ( (ContainerFluidConfigurable) c ).setFluid(e.getKey(), e.getValue()); - } - } - return null; - } - - } -} diff --git a/src/main/java/com/glodblock/github/network/SPacketFluidUpdate.java b/src/main/java/com/glodblock/github/network/SPacketFluidUpdate.java index 3316626b..bf371e7e 100644 --- a/src/main/java/com/glodblock/github/network/SPacketFluidUpdate.java +++ b/src/main/java/com/glodblock/github/network/SPacketFluidUpdate.java @@ -3,6 +3,7 @@ package com.glodblock.github.network; import appeng.api.storage.data.IAEFluidStack; import appeng.util.item.AEFluidStack; import com.glodblock.github.client.gui.GuiFluidIO; +import com.glodblock.github.client.gui.GuiFluidInterface; import com.glodblock.github.client.gui.GuiIngredientBuffer; import cpw.mods.fml.common.network.simpleimpl.IMessage; import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; @@ -79,6 +80,10 @@ public class SPacketFluidUpdate implements IMessage { for (Map.Entry e : message.list.entrySet() ) { ( (GuiFluidIO) gs ).update(e.getKey(), e.getValue()); } + } else if (gs instanceof GuiFluidInterface) { + for (Map.Entry e : message.list.entrySet() ) { + ( (GuiFluidInterface) gs ).update(e.getKey(), e.getValue()); + } } return null; } diff --git a/src/main/java/com/glodblock/github/util/DualityFluidInterface.java b/src/main/java/com/glodblock/github/util/DualityFluidInterface.java new file mode 100644 index 00000000..50febdf1 --- /dev/null +++ b/src/main/java/com/glodblock/github/util/DualityFluidInterface.java @@ -0,0 +1,434 @@ +package com.glodblock.github.util; + +import appeng.api.config.Actionable; +import appeng.api.config.Upgrades; +import appeng.api.implementations.IUpgradeableHost; +import appeng.api.networking.GridFlags; +import appeng.api.networking.IGridNode; +import appeng.api.networking.events.MENetworkChannelsChanged; +import appeng.api.networking.events.MENetworkPowerStatusChange; +import appeng.api.networking.security.BaseActionSource; +import appeng.api.networking.security.MachineSource; +import appeng.api.networking.storage.IStorageGrid; +import appeng.api.networking.ticking.IGridTickable; +import appeng.api.networking.ticking.TickRateModulation; +import appeng.api.networking.ticking.TickingRequest; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.IMEMonitor; +import appeng.api.storage.IStorageMonitorable; +import appeng.api.storage.StorageChannel; +import appeng.api.storage.data.IAEFluidStack; +import appeng.api.storage.data.IAEItemStack; +import appeng.api.util.IConfigManager; +import appeng.core.settings.TickRates; +import appeng.helpers.IInterfaceHost; +import appeng.me.GridAccessException; +import appeng.me.helpers.AENetworkProxy; +import appeng.me.storage.MEMonitorPassThrough; +import appeng.me.storage.NullInventory; +import appeng.util.ConfigManager; +import appeng.util.IConfigManagerHost; +import appeng.util.Platform; +import appeng.util.item.AEFluidStack; +import com.glodblock.github.inventory.AEFluidInventory; +import com.glodblock.github.inventory.IAEFluidInventory; +import com.glodblock.github.inventory.IAEFluidTank; +import com.glodblock.github.inventory.MEMonitorIFluidHandler; +import net.minecraft.inventory.IInventory; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidTankInfo; +import net.minecraftforge.fluids.IFluidHandler; + +import java.util.Objects; + +public class DualityFluidInterface implements IGridTickable, IStorageMonitorable, IAEFluidInventory, IUpgradeableHost, IConfigManagerHost, IFluidHandler { + + public static final int NUMBER_OF_TANKS = 6; + public static final long TANK_CAPACITY = 16000; + private final ConfigManager cm = new ConfigManager(this); + private final AENetworkProxy gridProxy; + private final IInterfaceHost iHost; + private final BaseActionSource mySource; + private boolean hasConfig = false; + private final AEFluidInventory tanks = new AEFluidInventory(this, NUMBER_OF_TANKS, (int) TANK_CAPACITY); + private final AEFluidInventory config = new AEFluidInventory( this, NUMBER_OF_TANKS, Integer.MAX_VALUE ); + private final IAEFluidStack[] requireWork; + private int isWorking = -1; + private final MEMonitorPassThrough items = new MEMonitorPassThrough( new NullInventory(), StorageChannel.ITEMS ); + private final MEMonitorPassThrough fluids = new MEMonitorPassThrough(new NullInventory<>(), StorageChannel.FLUIDS ); + private boolean resetConfigCache = true; + + public DualityFluidInterface(final AENetworkProxy networkProxy, final IInterfaceHost ih) { + this.gridProxy = networkProxy; + this.gridProxy.setFlags(GridFlags.REQUIRE_CHANNEL); + this.iHost = ih; + this.mySource = new MachineSource(this.iHost); + this.fluids.setChangeSource(this.mySource); + this.items.setChangeSource(this.mySource); + this.requireWork = new IAEFluidStack[6]; + + for(int i = 0; i < 6; ++i) { + this.requireWork[i] = null; + } + } + + public IAEFluidStack getStandardFluid(IAEFluidStack fluid) { + if (fluid == null) { + return null; + } + else { + return AEFluidStack.create(new FluidStack(fluid.getFluid(), 8000)); + } + } + + public IAEFluidStack getStandardFluid(FluidStack fluid) { + if (fluid == null) { + return null; + } + else { + return AEFluidStack.create(new FluidStack(fluid.getFluid(), 8000)); + } + } + + public void onChannelStateChange(final MENetworkChannelsChanged c) { + this.notifyNeighbors(); + } + + public void onPowerStateChange(final MENetworkPowerStatusChange c) { + this.notifyNeighbors(); + } + + public void gridChanged() { + try { + this.items.setInternal(this.gridProxy.getStorage().getItemInventory()); + this.fluids.setInternal(this.gridProxy.getStorage().getFluidInventory()); + } catch (GridAccessException var2) { + this.items.setInternal(new NullInventory<>()); + this.fluids.setInternal(new NullInventory<>()); + } + this.notifyNeighbors(); + } + + public void writeToNBT(NBTTagCompound data) { + this.tanks.writeToNBT(data, "storage"); + this.config.writeToNBT(data, "config"); + } + + public void readFromNBT(NBTTagCompound data) { + this.config.readFromNBT(data, "config"); + this.tanks.readFromNBT(data, "storage"); + this.readConfig(); + } + + public AEFluidInventory getConfig() { + return this.config; + } + + public AEFluidInventory getTanks() { + return this.tanks; + } + + private IMEMonitor getFluidGrid() { + try { + return gridProxy.getGrid().getCache(IStorageGrid.class).getFluidInventory(); + } catch (GridAccessException e) { + return null; + } + } + + @Override + public int getInstalledUpgrades(Upgrades u) { + return 0; + } + + @Override + public TileEntity getTile() { + return (TileEntity) (this.iHost instanceof TileEntity ? this.iHost : null); + } + + @Override + public IInventory getInventoryByName(String name) { + return null; + } + + public IFluidHandler getFluidInventoryByName(String name) { + return name.equals("config") ? this.config : null; + } + + @Override + public TickingRequest getTickingRequest(IGridNode node) { + return new TickingRequest(TickRates.Interface.getMin(), TickRates.Interface.getMax(), !this.hasWorkToDo(), true); + } + + @Override + public TickRateModulation tickingRequest(IGridNode node, int TicksSinceLastCall) { + if (!this.gridProxy.isActive()) { + return TickRateModulation.SLEEP; + } else { + boolean couldDoWork = this.updateStorage(); + return this.hasWorkToDo() ? (couldDoWork ? TickRateModulation.URGENT : TickRateModulation.SLOWER) : TickRateModulation.SLEEP; + } + } + + @Override + public IMEMonitor getItemInventory() { + if( this.hasConfig ) + { + return null; + } + return this.items; + } + + @Override + public IMEMonitor getFluidInventory() { + if( this.hasConfig ) + { + if (this.resetConfigCache) { + this.resetConfigCache = false; + return new InterfaceInventory(this); + } + } + return this.fluids; + } + + @Override + public IConfigManager getConfigManager() { + return this.cm; + } + + @Override + public void updateSetting(IConfigManager manager, Enum settingName, Enum newValue) { + + } + + @Override + public void onFluidInventoryChanged(IAEFluidTank inventory, int slot) { + if (this.isWorking != slot) { + boolean had; + if (inventory == this.config) { + had = this.hasConfig; + this.readConfig(); + if (had != this.hasConfig) { + this.resetConfigCache = true; + this.notifyNeighbors(); + } + } else if (inventory == this.tanks) { + this.saveChanges(); + had = this.hasWorkToDo(); + this.updatePlan(slot); + boolean now = this.hasWorkToDo(); + if (had != now) { + try { + if (now) { + this.gridProxy.getTick().alertDevice(this.gridProxy.getNode()); + } else { + this.gridProxy.getTick().sleepDevice(this.gridProxy.getNode()); + } + } catch (GridAccessException ignored) { + } + } + } + + } + } + + private boolean hasWorkToDo() { + for (IAEFluidStack requiredWork : this.requireWork) { + if (requiredWork != null) { + return true; + } + } + return false; + } + + private boolean updateStorage() { + boolean didSomething = false; + for(int x = 0; x < 6; ++x) { + if (this.requireWork[x] != null) { + didSomething = this.usePlan(x) || didSomething; + } + } + return didSomething; + } + + private boolean usePlan(int slot) { + IAEFluidStack work = this.requireWork[slot]; + this.isWorking = slot; + boolean changed = false; + + IMEInventory dest = getFluidGrid(); + if (dest == null) { + this.isWorking = -1; + return false; + } + IAEFluidStack toStore; + if (work.getStackSize() > 0L) { + if ((long)this.tanks.fill(slot, work.getFluidStack(), false) != work.getStackSize()) { + changed = true; + } else if (Objects.requireNonNull(getFluidGrid()).getStorageList().findPrecise(work) != null) { + toStore = dest.extractItems(work, Actionable.MODULATE, this.mySource); + if (toStore != null) { + changed = true; + int filled = this.tanks.fill(slot, toStore.getFluidStack(), true); + if ((long)filled != toStore.getStackSize()) { + throw new IllegalStateException("bad attempt at managing tanks. ( fill )"); + } + } + } + } else if (work.getStackSize() < 0L) { + toStore = work.copy(); + toStore.setStackSize(-toStore.getStackSize()); + FluidStack canExtract = this.tanks.drain(slot, toStore.getFluidStack(), false); + if (canExtract != null && (long)canExtract.amount == toStore.getStackSize()) { + IAEFluidStack notStored = dest.injectItems(toStore, Actionable.MODULATE, this.mySource);; + toStore.setStackSize(toStore.getStackSize() - (notStored == null ? 0L : notStored.getStackSize())); + if (toStore.getStackSize() > 0L) { + changed = true; + FluidStack removed = this.tanks.drain(slot, toStore.getFluidStack(), true); + if (removed == null || toStore.getStackSize() != (long)removed.amount) { + throw new IllegalStateException("bad attempt at managing tanks. ( drain )"); + } + } + } else { + changed = true; + } + } + + if (changed) { + this.updatePlan(slot); + } + + this.isWorking = -1; + return changed; + } + + private void updatePlan(int slot) { + IAEFluidStack req = this.config.getFluidInSlot(slot); + IAEFluidStack stored = this.tanks.getFluidInSlot(slot); + IAEFluidStack work; + if (req == null && stored != null && stored.getStackSize() > 0L) { + work = stored.copy(); + this.requireWork[slot] = work.setStackSize(-work.getStackSize()); + } else { + if (req != null) { + if (stored == null || stored.getStackSize() == 0L) { + this.requireWork[slot] = req.copy(); + this.requireWork[slot].setStackSize(TANK_CAPACITY); + return; + } + + if (!req.equals(stored)) { + work = stored.copy(); + this.requireWork[slot] = work.setStackSize(-work.getStackSize()); + return; + } + + if (stored.getStackSize() < TANK_CAPACITY) { + this.requireWork[slot] = req.copy(); + this.requireWork[slot].setStackSize(TANK_CAPACITY - stored.getStackSize()); + return; + } + } + this.requireWork[slot] = null; + } + } + + public void notifyNeighbors() { + if (this.gridProxy.isActive()) { + try { + this.gridProxy.getTick().wakeDevice(this.gridProxy.getNode()); + } catch (GridAccessException ignored) { + } + } + TileEntity te = this.iHost.getTileEntity(); + if (te != null && te.getWorldObj() != null) { + Platform.notifyBlocksOfNeighbors(te.getWorldObj(), te.xCoord, te.yCoord, te.zCoord); + } + } + + public void saveChanges() { + this.iHost.saveChanges(); + } + + private void readConfig() { + this.hasConfig = false; + + for(int i = 0; i < this.config.getSlots(); ++i) { + if (this.config.getFluidInSlot(i) != null) { + this.hasConfig = true; + break; + } + } + + boolean had = this.hasWorkToDo(); + + for(int x = 0; x < 6; ++x) { + this.updatePlan(x); + } + + boolean has = this.hasWorkToDo(); + if (had != has) { + try { + if (has) { + this.gridProxy.getTick().alertDevice(this.gridProxy.getNode()); + } else { + this.gridProxy.getTick().sleepDevice(this.gridProxy.getNode()); + } + } catch (GridAccessException ignored) { + } + } + + this.notifyNeighbors(); + } + + @Override + public int fill(ForgeDirection from, FluidStack resource, boolean doFill) { + IMEMonitor fluidGrid = getFluidGrid(); + if (fluidGrid == null || resource == null) + return 0; + int ori = resource.amount; + IAEFluidStack remove; + if (doFill) { + remove = fluidGrid.injectItems(AEFluidStack.create(resource), Actionable.MODULATE, this.mySource); + } else { + remove = fluidGrid.injectItems(AEFluidStack.create(resource), Actionable.SIMULATE, this.mySource); + } + return remove == null ? ori : (int) (ori - remove.getStackSize()); + } + + @Override + public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain) { + return this.tanks.drain(from, resource, doDrain); + } + + @Override + public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) { + return this.tanks.drain(from, maxDrain, doDrain); + } + + @Override + public boolean canFill(ForgeDirection from, Fluid fluid) { + return true; + } + + @Override + public boolean canDrain(ForgeDirection from, Fluid fluid) { + return true; + } + + @Override + public FluidTankInfo[] getTankInfo(ForgeDirection from) { + return this.tanks.getTankInfo(from); + } + + private static class InterfaceInventory extends MEMonitorIFluidHandler { + InterfaceInventory(DualityFluidInterface tileInterface) { + super(tileInterface.tanks); + } + } + +} diff --git a/src/main/java/com/glodblock/github/util/ModAndClassUtil.java b/src/main/java/com/glodblock/github/util/ModAndClassUtil.java index e985aab6..f48d6a59 100644 --- a/src/main/java/com/glodblock/github/util/ModAndClassUtil.java +++ b/src/main/java/com/glodblock/github/util/ModAndClassUtil.java @@ -17,6 +17,7 @@ public final class ModAndClassUtil { public static boolean EC2 = false; public static boolean EIO = false; public static boolean FTR = false; + public static boolean OC = false; public static boolean GTPP = false; public static boolean isDoubleButton; @@ -96,10 +97,9 @@ public final class ModAndClassUtil { EIO = true; if (Loader.isModLoaded("Forestry")) FTR = true; + if (Loader.isModLoaded("OpenComputers")) + OC = true; if (Loader.isModLoaded("miscutils")) GTPP = true; } - - - } diff --git a/src/main/java/com/glodblock/github/util/NameConst.java b/src/main/java/com/glodblock/github/util/NameConst.java index e0f01687..141e42d9 100644 --- a/src/main/java/com/glodblock/github/util/NameConst.java +++ b/src/main/java/com/glodblock/github/util/NameConst.java @@ -9,6 +9,7 @@ public class NameConst { public static final String BLOCK_FLUID_PACKET_DECODER = "fluid_packet_decoder"; public static final String BLOCK_FLUID_INTERFACE = "fluid_interface"; public static final String BLOCK_INGREDIENT_BUFFER = "ingredient_buffer"; + public static final String BLOCK_OC_PATTERN_EDITOR = "oc_pattern_editor"; public static final String ITEM_FLUID_DROP = "fluid_drop"; public static final String ITEM_FLUID_ENCODED_PATTERN = "fluid_encoded_pattern"; @@ -36,5 +37,7 @@ public class NameConst { public static final String GUI_FLUID_PATTERN_ENCODER = GUI_KEY + BLOCK_FLUID_PATTERN_ENCODER; public static final String GUI_FLUID_PACKET_DECODER = GUI_KEY + BLOCK_FLUID_PACKET_DECODER; public static final String GUI_INGREDIENT_BUFFER = GUI_KEY + BLOCK_INGREDIENT_BUFFER; + public static final String GUI_FLUID_INTERFACE = GUI_KEY + BLOCK_FLUID_INTERFACE; + public static final String GUI_OC_PATTERN_EDITOR = GUI_KEY + BLOCK_OC_PATTERN_EDITOR; } diff --git a/src/main/java/com/glodblock/github/util/Util.java b/src/main/java/com/glodblock/github/util/Util.java index 4596c795..b4b0d0cf 100644 --- a/src/main/java/com/glodblock/github/util/Util.java +++ b/src/main/java/com/glodblock/github/util/Util.java @@ -116,4 +116,9 @@ public final class Util { return fluid; } + public static boolean areFluidsEqual(FluidStack fluid1, FluidStack fluid2) { + if (fluid1 == null || fluid2 == null) return false; + return fluid1.isFluidEqual(fluid2); + } + } diff --git a/src/main/resources/assets/ae2fc/lang/en_US.lang b/src/main/resources/assets/ae2fc/lang/en_US.lang index 26f2ccae..fb6a1a20 100644 --- a/src/main/resources/assets/ae2fc/lang/en_US.lang +++ b/src/main/resources/assets/ae2fc/lang/en_US.lang @@ -2,7 +2,7 @@ item.fluid_drop.name=drop of %s item.fluid_encoded_pattern.name=Encode Pattern item.part_fluid_pattern_terminal.name=ME Fluid Pattern Terminal item.part_fluid_pattern_terminal_ex.name=ME Fluid Processing Pattern Terminal -item.part_fluid_interface.name=Fluid Interface +item.part_fluid_interface.name=ME Dual Interface item.part_fluid_import.name=ME Fluid Import Bus item.part_fluid_export.name=ME Fluid Export Bus item.fluid_packet.name=Fluid Packet @@ -24,17 +24,27 @@ item.fluid_part.6.name=4096k ME Fluid Storage Component tile.fluid_discretizer.name=Fluid Discretizer tile.fluid_pattern_encoder.name=Fluid Pattern Encoder tile.fluid_packet_decoder.name=ME Fluid Packet Decoder -tile.fluid_interface.name=Fluid Interface +tile.fluid_interface.name=ME Dual Interface tile.ingredient_buffer.name=Ingredient Buffer +tile.oc_pattern_editor.name=OC Pattern Editor ae2fc.tooltip.invalid_fluid=Invalid fluid! ae2fc.tooltip.encode_pattern=Encode Patter ae2fc.tooltip.fluid_packet=Use a Fluid Packet Decoder to\nconvert this back into fluid. ae2fc.tooltip.empty=Empty ae2fc.tooltip.dump_tank=Dump Tank Contents +ae2fc.tooltip.switch_fluid_interface=Switch ME Dual Interface GUI ae2fc.gui.part_fluid_pattern_terminal=Fluid Pattern Terminal ae2fc.gui.part_fluid_pattern_terminal_ex=Fluid Processing Pattern Terminal ae2fc.gui.fluid_pattern_encoder=Fluid Pattern Encoder ae2fc.gui.fluid_packet_decoder=ME Fluid Packet Decoder ae2fc.gui.ingredient_buffer=Ingredient Buffer +ae2fc.gui.fluid_interface=ME Dual Interface +ae2fc.gui.fluid_interface.0=D +ae2fc.gui.fluid_interface.1=U +ae2fc.gui.fluid_interface.2=N +ae2fc.gui.fluid_interface.3=S +ae2fc.gui.fluid_interface.4=W +ae2fc.gui.fluid_interface.5=E +ae2fc.gui.oc_pattern_editor=OC Pattern Editor diff --git a/src/main/resources/assets/ae2fc/textures/blocks/oc_pattern_editor.png b/src/main/resources/assets/ae2fc/textures/blocks/oc_pattern_editor.png new file mode 100644 index 00000000..b3ca3bdc Binary files /dev/null and b/src/main/resources/assets/ae2fc/textures/blocks/oc_pattern_editor.png differ diff --git a/src/main/resources/assets/ae2fc/textures/gui/interface_fluid.png b/src/main/resources/assets/ae2fc/textures/gui/interface_fluid.png new file mode 100644 index 00000000..41ed69fd Binary files /dev/null and b/src/main/resources/assets/ae2fc/textures/gui/interface_fluid.png differ diff --git a/src/main/resources/assets/ae2fc/textures/gui/oc_pattern_editor.png b/src/main/resources/assets/ae2fc/textures/gui/oc_pattern_editor.png new file mode 100644 index 00000000..0e2f39b9 Binary files /dev/null and b/src/main/resources/assets/ae2fc/textures/gui/oc_pattern_editor.png differ