package com.hbm.blocks.network; import java.util.ArrayList; import java.util.List; import com.hbm.handler.CompatHandler; import cpw.mods.fml.common.Optional; 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.SimpleComponent; import org.lwjgl.input.Keyboard; import com.hbm.blocks.ILookOverlay; import com.hbm.interfaces.IControlReceiver; import com.hbm.inventory.fluid.FluidType; import com.hbm.inventory.fluid.Fluids; import com.hbm.inventory.fluid.tank.FluidTank; import com.hbm.items.machine.IItemFluidIdentifier; import com.hbm.main.MainRegistry; import com.hbm.packet.PacketDispatcher; import com.hbm.packet.toserver.NBTControlPacket; import com.hbm.tileentity.IGUIProvider; import com.hbm.tileentity.TileEntityLoadedBase; import com.hbm.util.BobMathUtil; import com.hbm.util.EnumUtil; import com.hbm.util.i18n.I18nUtil; import com.hbm.world.gen.nbt.INBTBlockTransformable; import api.hbm.energymk2.IEnergyReceiverMK2.ConnectionPriority; import api.hbm.fluidmk2.IFluidStandardTransceiverMK2; import cpw.mods.fml.common.network.internal.FMLNetworkHandler; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import io.netty.buffer.ByteBuf; import net.minecraft.block.BlockContainer; import net.minecraft.block.material.Material; import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiTextField; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.Container; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ChatComponentText; import net.minecraft.util.ChatComponentTranslation; import net.minecraft.util.ChatStyle; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.MathHelper; import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import net.minecraftforge.client.event.RenderGameOverlayEvent.Pre; import net.minecraftforge.common.util.ForgeDirection; public class FluidPump extends BlockContainer implements INBTBlockTransformable, ILookOverlay, IGUIProvider { public FluidPump(Material mat) { super(mat); } @Override public TileEntity createNewTileEntity(World world, int meta) { return new TileEntityFluidPump(); } @Override public int getRenderType() { return -1; } @Override public boolean isOpaqueCube() { return false; } @Override public boolean renderAsNormalBlock() { return false; } @Override public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase player, ItemStack itemStack) { int i = MathHelper.floor_double(player.rotationYaw * 4.0F / 360.0F + 0.5D) & 3; if(i == 0) world.setBlockMetadataWithNotify(x, y, z, 2, 2); if(i == 1) world.setBlockMetadataWithNotify(x, y, z, 5, 2); if(i == 2) world.setBlockMetadataWithNotify(x, y, z, 3, 2); if(i == 3) world.setBlockMetadataWithNotify(x, y, z, 4, 2); } @Override public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int side, float fX, float fY, float fZ) { if(!player.isSneaking()) { if(player.getHeldItem() != null && player.getHeldItem().getItem() instanceof IItemFluidIdentifier) { IItemFluidIdentifier id = (IItemFluidIdentifier) player.getHeldItem().getItem(); FluidType type = id.getType(world, x, y, z, player.getHeldItem()); TileEntity tile = world.getTileEntity(x, y, z); if(tile instanceof TileEntityFluidPump) { if(!world.isRemote) { TileEntityFluidPump pump = (TileEntityFluidPump) tile; pump.tank[0].setTankType(type); pump.markDirty(); player.addChatComponentMessage(new ChatComponentText("Changed type to ").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.YELLOW)).appendSibling(new ChatComponentTranslation(type.getConditionalName())).appendSibling(new ChatComponentText("!"))); } return true; } } if(world.isRemote) FMLNetworkHandler.openGui(player, MainRegistry.instance, 0, world, x, y, z); return true; } return false; } @Override @SideOnly(Side.CLIENT) public Object provideGUI(int ID, EntityPlayer player, World world, int x, int y, int z) { return new GUIPump((TileEntityFluidPump) world.getTileEntity(x, y, z)); } @Override public Container provideContainer(int ID, EntityPlayer player, World world, int x, int y, int z) { return null; } @Override public void printHook(Pre event, World world, int x, int y, int z) { TileEntity tile = world.getTileEntity(x, y, z); if(!(tile instanceof TileEntityFluidPump)) return; TileEntityFluidPump pump = (TileEntityFluidPump) tile; List text = new ArrayList(); text.add(EnumChatFormatting.GREEN + "-> " + EnumChatFormatting.RESET + pump.tank[0].getTankType().getLocalizedName() + " (" + pump.tank[0].getPressure() + " PU): " + BobMathUtil.format(pump.bufferSize) + "mB/t" + EnumChatFormatting.RED + " ->"); text.add("Priority: " + EnumChatFormatting.YELLOW + pump.priority.name()); if(pump.tank[0].getFill() > 0) text.add(BobMathUtil.format(pump.tank[0].getFill()) + "mB buffered"); ILookOverlay.printGeneric(event, I18nUtil.resolveKey(getUnlocalizedName() + ".name"), 0xffff00, 0x404000, text); } @Override public int transformMeta(int meta, int coordBaseMode) { return INBTBlockTransformable.transformMetaDeco(meta, coordBaseMode); } @SideOnly(Side.CLIENT) @Optional.InterfaceList({@Optional.Interface(iface = "li.cil.oc.api.network.SimpleComponent", modid = "OpenComputers")}) public static class TileEntityFluidPump extends TileEntityLoadedBase implements IFluidStandardTransceiverMK2, IControlReceiver, SimpleComponent, CompatHandler.OCComponent { public int bufferSize = 100; public FluidTank[] tank; public ConnectionPriority priority = ConnectionPriority.NORMAL; public boolean redstone = false; public TileEntityFluidPump() { this.tank = new FluidTank[1]; this.tank[0] = new FluidTank(Fluids.NONE, bufferSize); } @Override public void updateEntity() { if(!worldObj.isRemote) { // if the capacity were changed directly, any excess buffered fluid would be destroyed // when running a closed loop or handling hard to get fluids, that's quite bad if(this.bufferSize != this.tank[0].getMaxFill()) { int nextBuffer = Math.max(this.tank[0].getFill(), this.bufferSize); this.tank[0].changeTankSize(nextBuffer); } this.redstone = worldObj.isBlockIndirectlyGettingPowered(xCoord, yCoord, zCoord); ForgeDirection dir = ForgeDirection.getOrientation(this.getBlockMetadata()); ForgeDirection in = dir.getRotation(ForgeDirection.UP); ForgeDirection out = in.getOpposite(); this.trySubscribe(tank[0].getTankType(), worldObj, xCoord + in.offsetX, yCoord, zCoord + in.offsetZ, in); if(!redstone) this.tryProvide(tank[0], worldObj, xCoord + out.offsetX, yCoord, zCoord + out.offsetZ, out); this.networkPackNT(15); } } @Override public void writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); tank[0].writeToNBT(nbt, "t"); nbt.setByte("p", (byte) priority.ordinal()); nbt.setInteger("buffer", bufferSize); } @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); tank[0].readFromNBT(nbt, "t"); priority = EnumUtil.grabEnumSafely(ConnectionPriority.class, nbt.getByte("p")); bufferSize = nbt.getInteger("buffer"); } @Override public void serialize(ByteBuf buf) { super.serialize(buf); tank[0].serialize(buf); buf.writeByte((byte) priority.ordinal()); buf.writeInt(bufferSize); } @Override public void deserialize(ByteBuf buf) { super.deserialize(buf); tank[0].deserialize(buf); priority = EnumUtil.grabEnumSafely(ConnectionPriority.class, buf.readByte()); bufferSize = buf.readInt(); } @Override public ConnectionPriority getFluidPriority() { return priority; } @Override public FluidTank[] getSendingTanks() { return redstone ? new FluidTank[0] : tank; } @Override public FluidTank[] getReceivingTanks() { return this.bufferSize < this.tank[0].getFill() ? new FluidTank[0] : tank; } @Override public FluidTank[] getAllTanks() { return tank; } @Override public boolean hasPermission(EntityPlayer player) { return player.getDistanceSq(xCoord + 0.5D, yCoord + 0.5D, zCoord + 0.5D) <= 128; } @Override public void receiveControl(NBTTagCompound data) { if(data.hasKey("capacity")) { this.bufferSize = MathHelper.clamp_int(data.getInteger("capacity"), 0, 10_000); } if(data.hasKey("pressure")) { this.tank[0].withPressure(MathHelper.clamp_int(data.getByte("pressure"), 0, 5)); } if(data.hasKey("priority")) { priority = EnumUtil.grabEnumSafely(ConnectionPriority.class, data.getByte("priority")); } this.markDirty(); } @Override @Optional.Method(modid = "OpenComputers") public String getComponentName() { return "ntm_fluid_pump"; } @Callback(direct = true, limit = 4) @Optional.Method(modid = "OpenComputers") public Object[] getFluid(Context context, Arguments args) { return new Object[] { tank[0].getTankType().getUnlocalizedName() }; } @Callback(direct = true, limit = 4) @Optional.Method(modid = "OpenComputers") public Object[] getPressure(Context context, Arguments args) { return new Object[] { tank[0].getPressure() }; } @Callback(direct = true, limit = 4) @Optional.Method(modid = "OpenComputers") public Object[] getFlow(Context context, Arguments args) { return new Object[] { bufferSize }; } @Callback(direct = true, limit = 4) @Optional.Method(modid = "OpenComputers") public Object[] getPriority(Context context, Arguments args) { return new Object[] { getFluidPriority() }; } @Callback(direct = true, limit = 4) @Optional.Method(modid = "OpenComputers") public Object[] getInfo(Context context, Arguments args) { return new Object[] { tank[0].getTankType().getUnlocalizedName(), tank[0].getPressure(), bufferSize, getFluidPriority() }; } @Callback(direct = true, limit = 4) @Optional.Method(modid = "OpenComputers") public Object[] setPriority(Context context, Arguments args) { int num = args.checkInteger(0); switch (num) { case 0: priority = ConnectionPriority.LOWEST; break; case 1: priority = ConnectionPriority.LOW; break; case 2: priority = ConnectionPriority.NORMAL; break; case 3: priority = ConnectionPriority.HIGH; break; case 4: priority = ConnectionPriority.HIGHEST; break; default: return new Object[] {null, "Not a valid Priority."}; } return new Object[] {true}; } @Callback(direct = true, limit = 4) @Optional.Method(modid = "OpenComputers") public Object[] setFlow(Context context, Arguments args) { int input = args.checkInteger(0); if (input > 10000 || input < 0) return new Object[] {null, "Number outside of bounds."}; bufferSize = input; return new Object[] {true}; } @Override @Optional.Method(modid = "OpenComputers") public String[] methods() { return new String[] { "getPriority", "getPressure", "getFluid", "getFlow", "getInfo", "setPriority", "setFlow" }; } @Override @Optional.Method(modid = "OpenComputers") public Object[] invoke(String method, Context context, Arguments args) throws Exception { switch (method) { case ("getPriority"): return getPriority(context, args); case ("getPressure"): return getPressure(context, args); case ("getFluid"): return getFluid(context, args); case ("getFlow"): return getFlow(context, args); case ("getInfo"): return getInfo(context, args); case ("setPriority"): return setPriority(context, args); case ("setFlow"): return setFlow(context, args); } throw new NoSuchMethodException(); } } public static class GUIPump extends GuiScreen { protected final TileEntityFluidPump pump; private GuiTextField textPlacementPriority; private GuiButton buttonPressure; private GuiButton buttonPriority; private int pressure; private int priority; public GUIPump(TileEntityFluidPump pump) { this.pump = pump; this.pressure = pump.tank[0].getPressure(); this.priority = pump.priority.ordinal(); } @Override public void initGui() { Keyboard.enableRepeatEvents(true); textPlacementPriority = new GuiTextField(fontRendererObj, this.width / 2 - 150, 100, 90, 20); textPlacementPriority.setText("" + pump.bufferSize); textPlacementPriority.setMaxStringLength(5); buttonPressure = new GuiButton(0, this.width / 2 - 50, 100, 90, 20, pressure + " PU"); buttonPriority = new GuiButton(1, this.width / 2 + 50, 100, 90, 20, pump.priority.name()); } @Override public void drawScreen(int mouseX, int mouseY, float partialTicks) { drawDefaultBackground(); drawString(fontRendererObj, "Throughput:", this.width / 2 - 150, 80, 0xA0A0A0); drawString(fontRendererObj, "(max. 10,000mB)", this.width / 2 - 150, 90, 0xA0A0A0); textPlacementPriority.drawTextBox(); drawString(fontRendererObj, "Pressure:", this.width / 2 - 50, 80, 0xA0A0A0); buttonPressure.drawButton(mc, mouseX, mouseY); drawString(fontRendererObj, "Priority:", this.width / 2 + 50, 80, 0xA0A0A0); buttonPriority.drawButton(mc, mouseX, mouseY); super.drawScreen(mouseX, mouseY, partialTicks); } @Override public void onGuiClosed() { Keyboard.enableRepeatEvents(false); NBTTagCompound data = new NBTTagCompound(); data.setByte("pressure", (byte) pressure); data.setByte("priority", (byte) priority); try { data.setInteger("capacity", Integer.parseInt(textPlacementPriority.getText())); } catch(Exception ex) {} PacketDispatcher.wrapper.sendToServer(new NBTControlPacket(data, pump.xCoord, pump.yCoord, pump.zCoord)); } @Override protected void keyTyped(char typedChar, int keyCode) { super.keyTyped(typedChar, keyCode); if(textPlacementPriority.textboxKeyTyped(typedChar, keyCode)) return; if(keyCode == 1 || keyCode == this.mc.gameSettings.keyBindInventory.getKeyCode()) { this.mc.thePlayer.closeScreen(); } } @Override protected void mouseClicked(int mouseX, int mouseY, int mouseButton) { super.mouseClicked(mouseX, mouseY, mouseButton); textPlacementPriority.mouseClicked(mouseX, mouseY, mouseButton); if(buttonPressure.mousePressed(mc, mouseX, mouseY)) { this.pressure++; if(pressure > 5) pressure = 0; buttonPressure.displayString = pressure + " PU"; mc.getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F)); } if(buttonPriority.mousePressed(mc, mouseX, mouseY)) { this.priority++; if(priority >= ConnectionPriority.values().length) priority = 0; buttonPriority.displayString = EnumUtil.grabEnumSafely(ConnectionPriority.class, priority).name(); mc.getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F)); } } @Override public boolean doesGuiPauseGame() { return false; } } }