2025-10-05 23:48:03 +02:00

444 lines
15 KiB
Java

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<String> 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; }
}
}