fluid tank handling updated to match energy storage blocks, allowing for more consistent tank leveling behaviour

This commit is contained in:
George Paton 2025-03-24 15:05:56 +11:00
parent f00f2c7ca3
commit 62485c6854
4 changed files with 179 additions and 69 deletions

View File

@ -0,0 +1,5 @@
package api.hbm.fluidmk2;
public interface IFluidBufferTransceiverMK2 extends IFluidStandardTransceiverMK2 {
}

View File

@ -24,29 +24,29 @@ public interface IFluidStandardSenderMK2 extends IFluidProviderMK2 {
public default void tryProvide(FluidTank tank, World world, DirPos pos) { tryProvide(tank.getTankType(), tank.getPressure(), world, pos.getX(), pos.getY(), pos.getZ(), pos.getDir()); }
public default void tryProvide(FluidType type, World world, DirPos pos) { tryProvide(type, 0, world, pos.getX(), pos.getY(), pos.getZ(), pos.getDir()); }
public default void tryProvide(FluidType type, int pressure, World world, DirPos pos) { tryProvide(type, pressure, world, pos.getX(), pos.getY(), pos.getZ(), pos.getDir()); }
public default void tryProvide(FluidTank tank, World world, int x, int y, int z, ForgeDirection dir) { tryProvide(tank.getTankType(), tank.getPressure(), world, x, y, z, dir); }
public default void tryProvide(FluidType type, World world, int x, int y, int z, ForgeDirection dir) { tryProvide(type, 0, world, x, y, z, dir); }
public default void tryProvide(FluidType type, int pressure, World world, int x, int y, int z, ForgeDirection dir) {
TileEntity te = Compat.getTileStandard(world, x, y, z);
boolean red = false;
if(te instanceof IFluidConnectorMK2) {
IFluidConnectorMK2 con = (IFluidConnectorMK2) te;
if(con.canConnect(type, dir.getOpposite())) {
GenNode<FluidNetMK2> node = UniNodespace.getNode(world, x, y, z, type.getNetworkProvider());
if(node != null && node.net != null) {
node.net.addProvider(this);
red = true;
}
}
}
if(te instanceof IFluidReceiverMK2 && te != this) {
if(te != this && te instanceof IFluidReceiverMK2 && !(te instanceof IFluidBufferTransceiverMK2)) {
IFluidReceiverMK2 rec = (IFluidReceiverMK2) te;
if(rec.canConnect(type, dir.getOpposite())) {
long provides = Math.min(this.getFluidAvailable(type, pressure), this.getProviderSpeed(type, pressure));
@ -56,7 +56,7 @@ public interface IFluidStandardSenderMK2 extends IFluidProviderMK2 {
this.useUpFluid(type, pressure, toTransfer);
}
}
if(particleDebug) {
NBTTagCompound data = new NBTTagCompound();
data.setString("type", "network");
@ -71,9 +71,9 @@ public interface IFluidStandardSenderMK2 extends IFluidProviderMK2 {
PacketDispatcher.wrapper.sendToAllAround(new AuxParticlePacketNT(data, posX, posY, posZ), new TargetPoint(world.provider.dimensionId, posX, posY, posZ, 25));
}
}
public FluidTank[] getSendingTanks();
@Override
public default long getFluidAvailable(FluidType type, int pressure) {
long amount = 0;
@ -112,14 +112,14 @@ public interface IFluidStandardSenderMK2 extends IFluidProviderMK2 {
public default int[] getProvidingPressureRange(FluidType type) {
int lowest = HIGHEST_VALID_PRESSURE;
int highest = 0;
for(FluidTank tank : getSendingTanks()) {
if(tank.getTankType() == type) {
if(tank.getPressure() < lowest) lowest = tank.getPressure();
if(tank.getPressure() > highest) highest = tank.getPressure();
}
}
return lowest <= highest ? new int[] {lowest, highest} : DEFAULT_PRESSURE_RANGE;
}

View File

@ -1,7 +1,10 @@
package com.hbm.tileentity.machine.storage;
import api.hbm.energymk2.IEnergyReceiverMK2.ConnectionPriority;
import api.hbm.fluidmk2.IFluidStandardTransceiverMK2;
import api.hbm.fluidmk2.FluidNode;
import api.hbm.fluidmk2.IFluidBufferTransceiverMK2;
import java.util.HashSet;
import com.hbm.blocks.ModBlocks;
import com.hbm.handler.CompatHandler;
@ -20,6 +23,8 @@ import com.hbm.tileentity.IFluidCopiable;
import com.hbm.tileentity.IGUIProvider;
import com.hbm.tileentity.IPersistentNBT;
import com.hbm.tileentity.TileEntityMachineBase;
import com.hbm.uninos.UniNodespace;
import com.hbm.util.fauxpointtwelve.BlockPos;
import com.hbm.util.fauxpointtwelve.DirPos;
import cpw.mods.fml.common.Optional;
import cpw.mods.fml.relauncher.Side;
@ -37,9 +42,13 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.MathHelper;
import net.minecraft.world.EnumSkyBlock;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
@Optional.InterfaceList({@Optional.Interface(iface = "li.cil.oc.api.network.SimpleComponent", modid = "opencomputers")})
public class TileEntityBarrel extends TileEntityMachineBase implements SimpleComponent, IFluidStandardTransceiverMK2, IPersistentNBT, IGUIProvider, CompatHandler.OCComponent, IFluidCopiable {
public class TileEntityBarrel extends TileEntityMachineBase implements SimpleComponent, IFluidBufferTransceiverMK2, IPersistentNBT, IGUIProvider, CompatHandler.OCComponent, IFluidCopiable {
protected FluidNode node;
protected FluidType lastType;
public FluidTank tank;
public short mode = 0;
@ -90,10 +99,28 @@ public class TileEntityBarrel extends TileEntityMachineBase implements SimpleCom
tank.setType(0, 1, slots);
tank.loadTank(2, 3, slots);
tank.unloadTank(4, 5, slots);
for(DirPos pos : getConPos()) {
if(mode == 0 || mode == 1) this.trySubscribe(tank.getTankType(), worldObj, pos);
if(mode == 1 || mode == 2) this.tryProvide(tank, worldObj, pos);
if(this.node == null || this.node.expired || tank.getTankType() != lastType) {
this.node = (FluidNode) UniNodespace.getNode(worldObj, xCoord, yCoord, zCoord, tank.getTankType().getNetworkProvider());
if(this.node == null || this.node.expired || tank.getTankType() != lastType) {
this.node = this.createNode(tank.getTankType());
UniNodespace.createNode(worldObj, this.node);
lastType = tank.getTankType();
}
}
if(mode == 2 || mode == 1) {
this.tryProvide(tank, worldObj, xCoord, yCoord, zCoord, ForgeDirection.UNKNOWN);
} else {
if(node != null && node.hasValidNet()) node.net.removeProvider(this);
}
if(mode == 0 || mode == 1) {
if(node != null && node.hasValidNet()) node.net.addReceiver(this);
} else {
if(node != null && node.hasValidNet()) node.net.removeReceiver(this);
}
if(tank.getFill() > 0) {
@ -104,6 +131,30 @@ public class TileEntityBarrel extends TileEntityMachineBase implements SimpleCom
}
}
protected FluidNode createNode(FluidType type) {
DirPos[] conPos = getConPos();
HashSet<BlockPos> posSet = new HashSet<>();
posSet.add(new BlockPos(this));
for(DirPos pos : conPos) {
ForgeDirection dir = pos.getDir();
posSet.add(new BlockPos(pos.getX() - dir.offsetX, pos.getY() - dir.offsetY, pos.getZ() - dir.offsetZ));
}
return new FluidNode(type.getNetworkProvider(), posSet.toArray(new BlockPos[posSet.size()])).setConnections(conPos);
}
@Override
public void invalidate() {
super.invalidate();
if(!worldObj.isRemote) {
if(this.node != null) {
UniNodespace.destroyNode(worldObj, xCoord, yCoord, zCoord, tank.getTankType().getNetworkProvider());
}
}
}
@Override
public void serialize(ByteBuf buf) {
super.serialize(buf);
@ -220,6 +271,8 @@ public class TileEntityBarrel extends TileEntityMachineBase implements SimpleCom
tank.writeToNBT(nbt, "tank");
}
@Override public boolean canConnect(FluidType fluid, ForgeDirection dir) { return true; }
@Override
public FluidTank[] getSendingTanks() {
return (mode == 1 || mode == 2) ? new FluidTank[] {tank} : new FluidTank[0];

View File

@ -1,7 +1,9 @@
package com.hbm.tileentity.machine.storage;
import api.hbm.energymk2.IEnergyReceiverMK2.ConnectionPriority;
import api.hbm.fluid.IFluidStandardTransceiver;
import api.hbm.fluidmk2.FluidNode;
import api.hbm.fluidmk2.IFluidBufferTransceiverMK2;
import com.hbm.blocks.BlockDummyable;
import com.hbm.blocks.ModBlocks;
import com.hbm.explosion.vanillant.ExplosionVNT;
@ -22,8 +24,10 @@ import com.hbm.inventory.fluid.tank.FluidTank;
import com.hbm.lib.Library;
import com.hbm.packet.PacketDispatcher;
import com.hbm.tileentity.*;
import com.hbm.uninos.UniNodespace;
import com.hbm.packet.toclient.AuxParticlePacketNT;
import com.hbm.util.ParticleUtil;
import com.hbm.util.fauxpointtwelve.BlockPos;
import com.hbm.util.fauxpointtwelve.DirPos;
import cpw.mods.fml.common.Optional;
import cpw.mods.fml.common.network.NetworkRegistry.TargetPoint;
@ -45,23 +49,26 @@ import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
@Optional.InterfaceList({@Optional.Interface(iface = "li.cil.oc.api.network.SimpleComponent", modid = "opencomputers")})
public class TileEntityMachineFluidTank extends TileEntityMachineBase implements SimpleComponent, OCComponent, IFluidStandardTransceiver, IPersistentNBT, IOverpressurable, IGUIProvider, IRepairable, IFluidCopiable {
public class TileEntityMachineFluidTank extends TileEntityMachineBase implements SimpleComponent, OCComponent, IFluidBufferTransceiverMK2, IPersistentNBT, IOverpressurable, IGUIProvider, IRepairable, IFluidCopiable {
protected FluidNode node;
protected FluidType lastType;
public FluidTank tank;
public short mode = 0;
public static final short modes = 4;
public boolean hasExploded = false;
protected boolean sendingBrake = false;
public boolean onFire = false;
public byte lastRedstone = 0;
public Explosion lastExplosion = null;
public int age = 0;
public TileEntityMachineFluidTank() {
super(6);
tank = new FluidTank(Fluids.NONE, 256000);
@ -82,7 +89,7 @@ public class TileEntityMachineFluidTank extends TileEntityMachineBase implements
public void updateEntity() {
if(!worldObj.isRemote) {
//meta below 12 means that it's an old multiblock configuration
if(this.getBlockMetadata() < 12) {
//get old direction
@ -98,24 +105,43 @@ public class TileEntityMachineFluidTank extends TileEntityMachineBase implements
worldObj.getTileEntity(xCoord, yCoord, zCoord).readFromNBT(data);
return;
}
if(!hasExploded) {
age++;
if(age >= 20) {
age = 0;
this.markChanged();
}
for(DirPos pos : getConPos()) {
if(mode == 0 || mode == 1) this.trySubscribe(tank.getTankType(), worldObj, pos);
if(mode == 1 || mode == 2) this.tryProvide(tank, worldObj, pos);
if(this.node == null || this.node.expired || tank.getTankType() != lastType) {
this.node = (FluidNode) UniNodespace.getNode(worldObj, xCoord, yCoord, zCoord, tank.getTankType().getNetworkProvider());
if(this.node == null || this.node.expired || tank.getTankType() != lastType) {
this.node = this.createNode(tank.getTankType());
UniNodespace.createNode(worldObj, this.node);
lastType = tank.getTankType();
}
}
if(mode == 2 || mode == 1) {
this.tryProvide(tank, worldObj, xCoord, yCoord, zCoord, ForgeDirection.UNKNOWN);
} else {
if(node != null && node.hasValidNet()) node.net.removeProvider(this);
}
if(mode == 0 || mode == 1) {
if(node != null && node.hasValidNet()) node.net.addReceiver(this);
} else {
if(node != null && node.hasValidNet()) node.net.removeReceiver(this);
}
tank.loadTank(2, 3, slots);
tank.setType(0, 1, slots);
} else {
for(DirPos pos : getConPos()) this.tryUnsubscribe(tank.getTankType(), worldObj, pos.getX(), pos.getY(), pos.getZ());
} else if(this.node != null) {
UniNodespace.destroyNode(worldObj, xCoord, yCoord, zCoord, tank.getTankType().getNetworkProvider());
this.node = null;
}
byte comp = this.getComparatorPower(); //comparator shit
@ -131,11 +157,11 @@ public class TileEntityMachineFluidTank extends TileEntityMachineBase implements
this.explode();
this.tank.setFill(0);
}
if(tank.getTankType().hasTrait(FT_Corrosive.class) && tank.getTankType().getTrait(FT_Corrosive.class).isHighlyCorrosive()) {
this.explode();
}
if(this.hasExploded) {
int leaking = 0;
@ -146,26 +172,50 @@ public class TileEntityMachineFluidTank extends TileEntityMachineBase implements
} else {
leaking = Math.min(tank.getFill(), tank.getMaxFill() / 10000);
}
updateLeak(leaking);
}
}
tank.unloadTank(4, 5, slots);
this.networkPackNT(150);
}
ForgeDirection dir = ForgeDirection.getOrientation(this.getBlockMetadata() - 10);
ForgeDirection rot = dir.getRotation(ForgeDirection.UP);
List<EntityPlayer> players = worldObj.getEntitiesWithinAABB(EntityPlayer.class, AxisAlignedBB.getBoundingBox(xCoord, yCoord, zCoord, xCoord + 1, yCoord + 2.875, zCoord + 1).offset(dir.offsetX * 0.5 - rot.offsetX * 2.25, 0, dir.offsetZ * 0.5 - rot.offsetZ * 2.25));
for(EntityPlayer player : players) {
HbmPlayerProps props = HbmPlayerProps.getData(player);
props.isOnLadder = true;
}
}
protected FluidNode createNode(FluidType type) {
DirPos[] conPos = getConPos();
HashSet<BlockPos> posSet = new HashSet<>();
posSet.add(new BlockPos(this));
for(DirPos pos : conPos) {
ForgeDirection dir = pos.getDir();
posSet.add(new BlockPos(pos.getX() - dir.offsetX, pos.getY() - dir.offsetY, pos.getZ() - dir.offsetZ));
}
return new FluidNode(type.getNetworkProvider(), posSet.toArray(new BlockPos[posSet.size()])).setConnections(conPos);
}
@Override
public void invalidate() {
super.invalidate();
if(!worldObj.isRemote) {
if(this.node != null) {
UniNodespace.destroyNode(worldObj, xCoord, yCoord, zCoord, tank.getTankType().getNetworkProvider());
}
}
}
@Override
public void serialize(ByteBuf buf) {
super.serialize(buf);
@ -173,7 +223,7 @@ public class TileEntityMachineFluidTank extends TileEntityMachineBase implements
buf.writeBoolean(hasExploded);
tank.serialize(buf);
}
@Override
public void deserialize(ByteBuf buf) {
super.deserialize(buf);
@ -181,39 +231,39 @@ public class TileEntityMachineFluidTank extends TileEntityMachineBase implements
hasExploded = buf.readBoolean();
tank.deserialize(buf);
}
/** called when the tank breaks due to hazardous materials or external force, can be used to quickly void part of the tank or spawn a mushroom cloud */
public void explode() {
this.hasExploded = true;
this.onFire = tank.getTankType().hasTrait(FT_Flammable.class);
this.markChanged();
}
/** called every tick post explosion, used for leaking fluid and spawning particles */
public void updateLeak(int amount) {
if(!hasExploded) return;
if(amount <= 0) return;
this.tank.getTankType().onFluidRelease(this, tank, amount);
this.tank.setFill(Math.max(0, this.tank.getFill() - amount));
FluidType type = tank.getTankType();
if(type.hasTrait(FT_Amat.class)) {
new ExplosionVNT(worldObj, xCoord + 0.5, yCoord + 1.5, zCoord + 0.5, 5F).makeAmat().setBlockAllocator(null).setBlockProcessor(null).explode();
} else if(type.hasTrait(FT_Flammable.class) && onFire) {
List<Entity> affected = worldObj.getEntitiesWithinAABB(Entity.class, AxisAlignedBB.getBoundingBox(xCoord - 1.5, yCoord, zCoord - 1.5, xCoord + 2.5, yCoord + 5, zCoord + 2.5));
for(Entity e : affected) e.setFire(5);
Random rand = worldObj.rand;
ParticleUtil.spawnGasFlame(worldObj, xCoord + rand.nextDouble(), yCoord + 0.5 + rand.nextDouble(), zCoord + rand.nextDouble(), rand.nextGaussian() * 0.2, 0.1, rand.nextGaussian() * 0.2);
if(worldObj.getTotalWorldTime() % 5 == 0) {
FT_Polluting.pollute(worldObj, xCoord, yCoord, zCoord, tank.getTankType(), FluidReleaseType.BURN, amount * 5);
}
} else if(type.hasTrait(FT_Gaseous.class) || type.hasTrait(FT_Gaseous_ART.class)) {
if(worldObj.getTotalWorldTime() % 5 == 0) {
NBTTagCompound data = new NBTTagCompound();
data.setString("type", "tower");
@ -233,7 +283,7 @@ public class TileEntityMachineFluidTank extends TileEntityMachineBase implements
@Override
public void explode(World world, int x, int y, int z) {
if(this.hasExploded) return;
this.onFire = tank.getTankType().hasTrait(FT_Flammable.class);
this.hasExploded = true;
@ -243,7 +293,7 @@ public class TileEntityMachineFluidTank extends TileEntityMachineBase implements
@Override
public void tryExtinguish(World world, int x, int y, int z, EnumExtinguishType type) {
if(!this.hasExploded || !this.onFire) return;
if(type == EnumExtinguishType.WATER) {
if(tank.getTankType().hasTrait(FT_Liquid.class)) { // extinguishing oil with water is a terrible idea!
worldObj.newExplosion(null, xCoord + 0.5, yCoord + 1.5, zCoord + 0.5, 5F, true, true);
@ -253,13 +303,13 @@ public class TileEntityMachineFluidTank extends TileEntityMachineBase implements
return;
}
}
if(type == EnumExtinguishType.FOAM || type == EnumExtinguishType.CO2) {
this.onFire = false;
this.markChanged();
}
}
protected DirPos[] getConPos() {
return new DirPos[] {
new DirPos(xCoord + 2, yCoord, zCoord - 1, Library.POS_X),
@ -272,17 +322,17 @@ public class TileEntityMachineFluidTank extends TileEntityMachineBase implements
new DirPos(xCoord + 1, yCoord, zCoord - 2, Library.NEG_Z)
};
}
public void handleButtonPacket(int value, int meta) {
mode = (short) ((mode + 1) % modes);
this.markChanged();
}
AxisAlignedBB bb = null;
@Override
public AxisAlignedBB getRenderBoundingBox() {
if(bb == null) {
bb = AxisAlignedBB.getBoundingBox(
xCoord - 2,
@ -293,30 +343,30 @@ public class TileEntityMachineFluidTank extends TileEntityMachineBase implements
zCoord + 3
);
}
return bb;
}
@Override
@SideOnly(Side.CLIENT)
public double getMaxRenderDistanceSquared() {
return 65536.0D;
}
@Override
public void readFromNBT(NBTTagCompound nbt) {
super.readFromNBT(nbt);
mode = nbt.getShort("mode");
tank.readFromNBT(nbt, "tank");
hasExploded = nbt.getBoolean("exploded");
onFire = nbt.getBoolean("onFire");
}
@Override
public void writeToNBT(NBTTagCompound nbt) {
super.writeToNBT(nbt);
nbt.setShort("mode", mode);
tank.writeToNBT(nbt, "tank");
nbt.setBoolean("exploded", hasExploded);
@ -362,6 +412,8 @@ public class TileEntityMachineFluidTank extends TileEntityMachineBase implements
this.onFire = data.getBoolean("onFire");
}
@Override public boolean canConnect(FluidType fluid, ForgeDirection dir) { return true; }
@Override
public FluidTank[] getSendingTanks() {
if(this.hasExploded) return new FluidTank[0];
@ -370,7 +422,7 @@ public class TileEntityMachineFluidTank extends TileEntityMachineBase implements
@Override
public FluidTank[] getReceivingTanks() {
if(this.hasExploded || this.sendingBrake) return new FluidTank[0];
if(this.hasExploded) return new FluidTank[0];
return (mode == 0 || mode == 1) ? new FluidTank[] {tank} : new FluidTank[0];
}
@ -404,14 +456,14 @@ public class TileEntityMachineFluidTank extends TileEntityMachineBase implements
public boolean isDamaged() {
return this.hasExploded;
}
List<AStack> repair = new ArrayList<>();
@Override
public List<AStack> getRepairMaterials() {
if(!repair.isEmpty())
return repair;
repair.add(new OreDictStack(OreDictManager.STEEL.plate(), 6));
return repair;
}