Make a start on the boiler.

It's currently causing odd issues with the heat simulator and has various issues such as balance not existing yet.
Also improve the specification of a load of the multiblock generics to reduce needless casting.
This commit is contained in:
Ben Spiers 2015-01-08 05:26:53 +00:00
parent ccf7a37b22
commit 385a1d29f6
25 changed files with 1236 additions and 38 deletions

View file

@ -62,6 +62,8 @@ import mekanism.common.recipe.inputs.ItemStackInput;
import mekanism.common.recipe.machines.SmeltingRecipe;
import mekanism.common.recipe.outputs.ItemStackOutput;
import mekanism.common.tile.TileEntityAdvancedBoundingBlock;
import mekanism.common.tile.TileEntityBoiler;
import mekanism.common.tile.TileEntityBoilerValve;
import mekanism.common.tile.TileEntityBoundingBlock;
import mekanism.common.tile.TileEntityCardboardBox;
import mekanism.common.tile.TileEntityElectricBlock;
@ -950,6 +952,8 @@ public class Mekanism
GameRegistry.registerTileEntity(TileEntitySalinationValve.class, "SalinationValve");
GameRegistry.registerTileEntity(TileEntitySalinationBlock.class, "SalinationTank");
GameRegistry.registerTileEntity(TileEntityEntangledBlock.class, "EntangledBlock");
GameRegistry.registerTileEntity(TileEntityBoiler.class, "SteamBoiler");
GameRegistry.registerTileEntity(TileEntityBoilerValve.class, "BoilerValve");
//Load tile entities that have special renderers.
proxy.registerSpecialTileEntities();

View file

@ -20,6 +20,8 @@ import mekanism.common.inventory.InventoryBin;
import mekanism.common.network.PacketTileEntity.TileEntityMessage;
import mekanism.common.tile.TileEntityBasicBlock;
import mekanism.common.tile.TileEntityBin;
import mekanism.common.tile.TileEntityBoiler;
import mekanism.common.tile.TileEntityBoilerValve;
import mekanism.common.tile.TileEntityDynamicTank;
import mekanism.common.tile.TileEntityDynamicValve;
import mekanism.common.tile.TileEntitySalinationBlock;
@ -71,6 +73,8 @@ import cpw.mods.fml.relauncher.SideOnly;
* 0:14: Salination Controller
* 0:15: Salination Valve
* 1:0: Salination Block
* 1:1: Steam Boiler
* 1:2: Boiler Valve
* @author AidanBrady
*
*/
@ -150,8 +154,12 @@ public class BlockBasic extends Block implements IBlockCTM
break;
case BASIC_BLOCK_2:
ctms[0][0] = new CTMData("ctm/SalinationBlock", this, Arrays.asList(0)).addOtherBlockConnectivities(MekanismBlocks.BasicBlock, Arrays.asList(14, 15)).registerIcons(register);
ctms[1][0] = new CTMData("ctm/SteamBoiler", this, Arrays.asList(1, 2)).registerIcons(register);
ctms[2][0] = new CTMData("ctm/BoilerValve", this, Arrays.asList(2, 1)).registerIcons(register);
icons[0][0] = ctms[0][0].mainTextureData.icon;
icons[1][0] = ctms[1][0].mainTextureData.icon;
icons[2][0] = ctms[2][0].mainTextureData.icon;
break;
}
}
@ -265,7 +273,7 @@ public class BlockBasic extends Block implements IBlockCTM
}
break;
case BASIC_BLOCK_2:
for(int i = 0; i < 1; i++)
for(int i = 0; i < 3; i++)
{
list.add(new ItemStack(item, 1, i));
}
@ -642,6 +650,8 @@ public class BlockBasic extends Block implements IBlockCTM
switch(metadata)
{
case 0:
case 1:
case 2:
return true;
default:
return false;
@ -679,6 +689,10 @@ public class BlockBasic extends Block implements IBlockCTM
{
case 0:
return new TileEntitySalinationBlock();
case 1:
return new TileEntityBoiler();
case 2:
return new TileEntityBoilerValve();
default:
return null;
}
@ -745,7 +759,7 @@ public class BlockBasic extends Block implements IBlockCTM
}
@Override
public ItemStack getPickBlock(MovingObjectPosition target, World world, int x, int y, int z)
public ItemStack getPickBlock(MovingObjectPosition target, World world, int x, int y, int z, EntityPlayer player)
{
ItemStack ret = new ItemStack(this, 1, world.getBlockMetadata(x, y, z));

View file

@ -1,32 +1,98 @@
package mekanism.common.content.boiler;
import mekanism.common.content.tank.SynchronizedTankData;
import mekanism.common.multiblock.MultiblockCache;
import mekanism.common.util.FluidContainerUtils.ContainerEditMode;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraftforge.common.util.Constants.NBT;
import net.minecraftforge.fluids.FluidStack;
public class BoilerCache extends MultiblockCache<SynchronizedBoilerData>
{
public ItemStack[] inventory = new ItemStack[2];
public FluidStack water;
public FluidStack steam;
public ContainerEditMode editMode = ContainerEditMode.BOTH;
@Override
public void apply(SynchronizedBoilerData data)
public void apply(SynchronizedBoilerData data)
{
data.inventory = inventory;
data.waterStored = water;
data.steamStored = steam;
data.editMode = editMode;
}
@Override
public void sync(SynchronizedBoilerData data)
public void sync(SynchronizedBoilerData data)
{
inventory = data.inventory;
water = data.waterStored;
steam = data.steamStored;
editMode = data.editMode;
}
@Override
public void load(NBTTagCompound nbtTags)
{
editMode = ContainerEditMode.values()[nbtTags.getInteger("editMode")];
NBTTagList tagList = nbtTags.getTagList("Items", NBT.TAG_COMPOUND);
inventory = new ItemStack[2];
for(int tagCount = 0; tagCount < tagList.tagCount(); tagCount++)
{
NBTTagCompound tagCompound = (NBTTagCompound)tagList.getCompoundTagAt(tagCount);
byte slotID = tagCompound.getByte("Slot");
if(slotID >= 0 && slotID < 2)
{
inventory[slotID] = ItemStack.loadItemStackFromNBT(tagCompound);
}
}
if(nbtTags.hasKey("cachedWater"))
{
water = FluidStack.loadFluidStackFromNBT(nbtTags.getCompoundTag("cachedWater"));
}
if(nbtTags.hasKey("cachedSteam"))
{
steam = FluidStack.loadFluidStackFromNBT(nbtTags.getCompoundTag("cachedSteam"));
}
}
@Override
public void save(NBTTagCompound nbtTags)
public void save(NBTTagCompound nbtTags)
{
nbtTags.setInteger("editMode", editMode.ordinal());
NBTTagList tagList = new NBTTagList();
for(int slotCount = 0; slotCount < 2; slotCount++)
{
if(inventory[slotCount] != null)
{
NBTTagCompound tagCompound = new NBTTagCompound();
tagCompound.setByte("Slot", (byte)slotCount);
inventory[slotCount].writeToNBT(tagCompound);
tagList.appendTag(tagCompound);
}
}
nbtTags.setTag("Items", tagList);
if(water != null)
{
nbtTags.setTag("cachedWater", water.writeToNBT(new NBTTagCompound()));
}
if(steam != null)
{
nbtTags.setTag("cachedSteam", steam.writeToNBT(new NBTTagCompound()));
}
}
}

View file

@ -0,0 +1,25 @@
package mekanism.common.content.boiler;
import mekanism.common.tile.TileEntityBoiler;
import net.minecraftforge.fluids.FluidStack;
public class BoilerSteamTank extends BoilerTank
{
public BoilerSteamTank(TileEntityBoiler tileEntity)
{
super(tileEntity);
}
@Override
public FluidStack getFluid()
{
return steamBoiler.structure != null ? steamBoiler.structure.steamStored : null;
}
public void setFluid(FluidStack stack)
{
steamBoiler.structure.steamStored = stack;
}
}

View file

@ -0,0 +1,198 @@
package mekanism.common.content.boiler;
import mekanism.api.Coord4D;
import mekanism.common.content.boiler.SynchronizedBoilerData.ValveData;
import mekanism.common.tile.TileEntityBoiler;
import mekanism.common.util.MekanismUtils;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidTankInfo;
import net.minecraftforge.fluids.IFluidTank;
public abstract class BoilerTank implements IFluidTank
{
public TileEntityBoiler steamBoiler;
public BoilerTank(TileEntityBoiler tileEntity)
{
steamBoiler = tileEntity;
}
public abstract void setFluid(FluidStack stack);
@Override
public int getCapacity()
{
return steamBoiler.structure != null ? steamBoiler.structure.volume * BoilerUpdateProtocol.WATER_PER_TANK : 0;
}
@Override
public int fill(FluidStack resource, boolean doFill)
{
if(steamBoiler.structure != null && !steamBoiler.getWorldObj().isRemote)
{
if(resource == null || resource.fluidID <= 0)
{
return 0;
}
if(getFluid() == null || getFluid().fluidID <= 0)
{
if(resource.amount <= getCapacity())
{
if(doFill)
{
setFluid(resource.copy());
}
if(resource.amount > 0 && doFill)
{
MekanismUtils.saveChunk(steamBoiler);
updateValveData(true);
steamBoiler.sendPacketToRenderer();
updateValveData(false);
}
return resource.amount;
}
else {
if(doFill)
{
setFluid(resource.copy());
getFluid().amount = getCapacity();
}
if(getCapacity() > 0 && doFill)
{
MekanismUtils.saveChunk(steamBoiler);
updateValveData(true);
steamBoiler.sendPacketToRenderer();
updateValveData(false);
}
return getCapacity();
}
}
if(!getFluid().isFluidEqual(resource))
{
return 0;
}
int space = getCapacity() - getFluid().amount;
if(resource.amount <= space)
{
if(doFill)
{
getFluid().amount += resource.amount;
}
if(resource.amount > 0 && doFill)
{
MekanismUtils.saveChunk(steamBoiler);
updateValveData(true);
steamBoiler.sendPacketToRenderer();
updateValveData(false);
}
return resource.amount;
}
else {
if(doFill)
{
getFluid().amount = getCapacity();
}
if(space > 0 && doFill)
{
MekanismUtils.saveChunk(steamBoiler);
updateValveData(true);
steamBoiler.sendPacketToRenderer();
updateValveData(false);
}
return space;
}
}
return 0;
}
public void updateValveData(boolean value)
{
if(steamBoiler.structure != null)
{
for(ValveData data : steamBoiler.structure.valves)
{
if(data.location.equals(Coord4D.get(steamBoiler)))
{
data.serverFluid = value;
}
}
}
}
@Override
public FluidStack drain(int maxDrain, boolean doDrain)
{
if(steamBoiler.structure != null && !steamBoiler.getWorldObj().isRemote)
{
if(getFluid() == null || getFluid().fluidID <= 0)
{
return null;
}
if(getFluid().amount <= 0)
{
return null;
}
int used = maxDrain;
if(getFluid().amount < used)
{
used = getFluid().amount;
}
if(doDrain)
{
getFluid().amount -= used;
}
FluidStack drained = new FluidStack(getFluid().fluidID, used);
if(getFluid().amount <= 0)
{
setFluid(null);
}
if(drained.amount > 0 && doDrain)
{
MekanismUtils.saveChunk(steamBoiler);
steamBoiler.sendPacketToRenderer();
}
return drained;
}
return null;
}
@Override
public int getFluidAmount()
{
if(steamBoiler.structure != null)
{
return getFluid().amount;
}
return 0;
}
@Override
public FluidTankInfo getInfo()
{
return new FluidTankInfo(this);
}
}

View file

@ -1,6 +1,111 @@
package mekanism.common.content.boiler;
public class BoilerUpdateProtocol
{
import java.util.List;
import mekanism.api.Coord4D;
import mekanism.api.util.StackUtils;
import mekanism.common.Mekanism;
import mekanism.common.MekanismBlocks;
import mekanism.common.content.boiler.SynchronizedBoilerData.ValveData;
import mekanism.common.multiblock.MultiblockCache;
import mekanism.common.multiblock.MultiblockManager;
import mekanism.common.multiblock.UpdateProtocol;
import mekanism.common.tile.TileEntityBoiler;
import mekanism.common.tile.TileEntityBoilerValve;
import net.minecraft.item.ItemStack;
public class BoilerUpdateProtocol extends UpdateProtocol<SynchronizedBoilerData>
{
public static final int WATER_PER_TANK = 16000;
public static final int STEAM_PER_TANK = 160000;
public BoilerUpdateProtocol(TileEntityBoiler tileEntity)
{
super(tileEntity);
}
@Override
protected boolean isValidFrame(int x, int y, int z)
{
return pointer.getWorldObj().getBlock(x, y, z) == MekanismBlocks.BasicBlock2 && pointer.getWorldObj().getBlockMetadata(x, y, z) == 1;
}
@Override
protected BoilerCache getNewCache()
{
return new BoilerCache();
}
@Override
protected SynchronizedBoilerData getNewStructure()
{
return new SynchronizedBoilerData();
}
@Override
protected MultiblockManager<SynchronizedBoilerData> getManager()
{
return Mekanism.boilerManager;
}
@Override
protected void mergeCaches(List<ItemStack> rejectedItems, MultiblockCache<SynchronizedBoilerData> cache, MultiblockCache<SynchronizedBoilerData> merge)
{
if(((BoilerCache)cache).water == null)
{
((BoilerCache)cache).water = ((BoilerCache)merge).water;
}
else if(((BoilerCache)merge).water != null && ((BoilerCache)cache).water.isFluidEqual(((BoilerCache)merge).water))
{
((BoilerCache)cache).water.amount += ((BoilerCache)merge).water.amount;
}
if(((BoilerCache)cache).steam == null)
{
((BoilerCache)cache).steam = ((BoilerCache)merge).steam;
}
else if(((BoilerCache)merge).steam != null && ((BoilerCache)cache).steam.isFluidEqual(((BoilerCache)merge).steam))
{
((BoilerCache)cache).steam.amount += ((BoilerCache)merge).steam.amount;
}
List<ItemStack> rejects = StackUtils.getMergeRejects(((BoilerCache)cache).inventory, ((BoilerCache)merge).inventory);
if(!rejects.isEmpty())
{
rejectedItems.addAll(rejects);
}
StackUtils.merge(((BoilerCache)cache).inventory, ((BoilerCache)merge).inventory);
}
@Override
protected void onFormed()
{
if((structureFound).waterStored != null)
{
(structureFound).waterStored.amount = Math.min((structureFound).waterStored.amount, structureFound.volume*WATER_PER_TANK);
}
if((structureFound).steamStored != null)
{
(structureFound).steamStored.amount = Math.min((structureFound).waterStored.amount, structureFound.volume*STEAM_PER_TANK);
}
}
@Override
protected void onStructureCreated(SynchronizedBoilerData structure, int origX, int origY, int origZ, int xmin, int xmax, int ymin, int ymax, int zmin, int zmax)
{
for(Coord4D obj : structure.locations)
{
if(obj.getTileEntity(pointer.getWorldObj()) instanceof TileEntityBoilerValve)
{
ValveData data = new ValveData();
data.location = obj;
data.side = getSide(obj, origX+xmin, origX+xmax, origY+ymin, origY+ymax, origZ+zmin, origZ+zmax);
((SynchronizedBoilerData)structure).valves.add(data);
}
}
}
}

View file

@ -0,0 +1,25 @@
package mekanism.common.content.boiler;
import mekanism.common.tile.TileEntityBoiler;
import net.minecraftforge.fluids.FluidStack;
public class BoilerWaterTank extends BoilerTank
{
public BoilerWaterTank(TileEntityBoiler tileEntity)
{
super(tileEntity);
}
@Override
public FluidStack getFluid()
{
return steamBoiler.structure != null ? steamBoiler.structure.waterStored : null;
}
public void setFluid(FluidStack stack)
{
steamBoiler.structure.waterStored = stack;
}
}

View file

@ -1,8 +1,137 @@
package mekanism.common.content.boiler;
import java.util.HashSet;
import java.util.Set;
import mekanism.api.Coord4D;
import mekanism.api.IHeatTransfer;
import mekanism.common.multiblock.SynchronizedData;
import mekanism.common.util.FluidContainerUtils.ContainerEditMode;
public class SynchronizedBoilerData extends SynchronizedData<SynchronizedBoilerData>
import net.minecraft.item.ItemStack;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
public class SynchronizedBoilerData extends SynchronizedData<SynchronizedBoilerData> implements IHeatTransfer
{
public FluidStack waterStored;
public FluidStack steamStored;
public double temperature;
public double heatToAbsorb;
public double heatCapacity = 100;
public double enthalpyOfVaporization = 10;
public ContainerEditMode editMode = ContainerEditMode.BOTH;
public ItemStack[] inventory = new ItemStack[2];
public Set<ValveData> valves = new HashSet<ValveData>();
@Override
public ItemStack[] getInventory()
{
return inventory;
}
@Override
public double getTemp()
{
return temperature;
}
@Override
public double getInverseConductionCoefficient()
{
return 100;
}
@Override
public double getInsulationCoefficient(ForgeDirection side)
{
return 100;
}
@Override
public void transferHeatTo(double heat)
{
heatToAbsorb = heat;
}
@Override
public double[] simulateHeat()
{
return new double[0];
}
@Override
public double applyTemperatureChange()
{
if(temperature < 100 + IHeatTransfer.AMBIENT_TEMP)
{
double temperatureDeficit = 100 + IHeatTransfer.AMBIENT_TEMP - temperature;
double heatNeeded = temperatureDeficit * volume * heatCapacity * 16;
double heatProvided = Math.min(heatToAbsorb, heatNeeded);
heatToAbsorb -= heatProvided;
temperature += heatProvided / (volume * heatCapacity * 16);
}
if(temperature >= 100 + IHeatTransfer.AMBIENT_TEMP && waterStored != null)
{
int amountToBoil = (int)Math.floor(heatToAbsorb / enthalpyOfVaporization);
amountToBoil = Math.min(amountToBoil, waterStored.amount);
waterStored.amount -= amountToBoil;
if(steamStored == null)
{
steamStored = new FluidStack(FluidRegistry.getFluid("steam"), amountToBoil);
}
else
{
steamStored.amount += amountToBoil;
}
heatToAbsorb -= amountToBoil * enthalpyOfVaporization;
}
heatToAbsorb *= 0.2;
return temperature;
}
@Override
public boolean canConnectHeat(ForgeDirection side)
{
return false;
}
@Override
public IHeatTransfer getAdjacent(ForgeDirection side)
{
return null;
}
public static class ValveData
{
public ForgeDirection side;
public Coord4D location;
public boolean serverFluid;
@Override
public int hashCode()
{
int code = 1;
code = 31 * code + side.ordinal();
code = 31 * code + location.hashCode();
return code;
}
@Override
public boolean equals(Object obj)
{
return obj instanceof ValveData && ((ValveData)obj).side == side && ((ValveData)obj).location.equals(location);
}
}
}

View file

@ -5,7 +5,7 @@ import mekanism.common.multiblock.SynchronizedData;
import net.minecraft.item.ItemStack;
public class SynchronizedMatrixData extends SynchronizedData<SynchronizedTankData>
public class SynchronizedMatrixData extends SynchronizedData<SynchronizedMatrixData>
{
public ItemStack[] inventory = new ItemStack[2];

View file

@ -1,6 +1,6 @@
package mekanism.common.multiblock;
public interface IMultiblock<T>
public interface IMultiblock<T extends SynchronizedData<T>>
{
public SynchronizedData<T> getSynchronizedData();
public T getSynchronizedData();
}

View file

@ -6,7 +6,7 @@ import mekanism.api.Coord4D;
import net.minecraft.nbt.NBTTagCompound;
public abstract class MultiblockCache<T>
public abstract class MultiblockCache<T extends SynchronizedData<T>>
{
public HashSet<Coord4D> locations = new HashSet<Coord4D>();

View file

@ -16,7 +16,7 @@ import net.minecraft.world.World;
import net.minecraft.world.WorldSavedData;
import net.minecraftforge.common.util.Constants.NBT;
public class MultiblockManager<T>
public class MultiblockManager<T extends SynchronizedData<T>>
{
private static Set<MultiblockManager> managers = new HashSet<MultiblockManager>();
@ -80,8 +80,6 @@ public class MultiblockManager<T>
/**
* Updates a dynamic tank cache with the defined inventory ID with the parameterized values.
* @param inventoryID - inventory ID of the dynamic tank
* @param cache - cache of the dynamic tank
* @param multiblock - dynamic tank TileEntity
*/
public void updateCache(IMultiblock<T> multiblock)

View file

@ -7,7 +7,7 @@ import mekanism.api.Coord4D;
import net.minecraft.item.ItemStack;
public abstract class SynchronizedData<T>
public abstract class SynchronizedData<T extends SynchronizedData<T>>
{
public Set<Coord4D> locations = new HashSet<Coord4D>();
@ -26,6 +26,9 @@ public abstract class SynchronizedData<T>
public boolean hasRenderer;
public Coord4D renderLocation;
public Coord4D minLocation;
public Coord4D maxLocation;
public ItemStack[] getInventory()
{

View file

@ -14,13 +14,13 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
public abstract class UpdateProtocol<T>
public abstract class UpdateProtocol<T extends SynchronizedData<T>>
{
/** The multiblock nodes that have already been iterated over. */
public Set<TileEntityMultiblock<T>> iteratedNodes = new HashSet<TileEntityMultiblock<T>>();
/** The structures found, all connected by some nodes to the pointer. */
public SynchronizedData<T> structureFound = null;
public T structureFound = null;
/** The original block the calculation is getting run from. */
public TileEntityMultiblock<T> pointer;
@ -178,13 +178,15 @@ public abstract class UpdateProtocol<T>
{
if(rightBlocks && rightFrame && isHollow && isCorner)
{
SynchronizedData<T> structure = getNewStructure();
T structure = getNewStructure();
structure.locations = locations;
structure.volLength = Math.abs(xmax-xmin)+1;
structure.volHeight = Math.abs(ymax-ymin)+1;
structure.volWidth = Math.abs(zmax-zmin)+1;
structure.volume = volume;
structure.renderLocation = Coord4D.get(tile).translate(0, 1, 0);
structure.minLocation = Coord4D.get(tile).translate(xmin, ymin, zmin);
structure.maxLocation = Coord4D.get(tile).translate(xmax, ymax, zmax);
onStructureCreated(structure, origX, origY, origZ, xmin, xmax, ymin, ymax, zmin, zmax);
@ -346,7 +348,7 @@ public abstract class UpdateProtocol<T>
protected abstract MultiblockCache<T> getNewCache();
protected abstract SynchronizedData<T> getNewStructure();
protected abstract T getNewStructure();
protected abstract MultiblockManager<T> getManager();
@ -354,7 +356,7 @@ public abstract class UpdateProtocol<T>
protected void onFormed() {}
protected void onStructureCreated(SynchronizedData<T> structure, int origX, int origY, int origZ, int xmin, int xmax, int ymin, int ymax, int zmin, int zmax) {}
protected void onStructureCreated(T structure, int origX, int origY, int origZ, int xmin, int xmax, int ymin, int ymax, int zmin, int zmax) {}
/**
* Runs the protocol and updates all tanks that make a part of the dynamic tank.
@ -371,7 +373,7 @@ public abstract class UpdateProtocol<T>
{
for(TileEntity tile : iteratedNodes)
{
((TileEntityMultiblock<T>)tileEntity).structure = null;
((TileEntityMultiblock<T>)tile).structure = null;
}
return;
@ -406,7 +408,7 @@ public abstract class UpdateProtocol<T>
cache = (MultiblockCache<T>)Mekanism.tankManager.pullInventory(pointer.getWorldObj(), id);
}
else {
mergeCaches(rejectedItems, cache, (MultiblockCache<T>)getManager().pullInventory(pointer.getWorldObj(), id));
mergeCaches(rejectedItems, cache, getManager().pullInventory(pointer.getWorldObj(), id));
}
idToUse = id;

View file

@ -0,0 +1,554 @@
package mekanism.common.tile;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import mekanism.api.Coord4D;
import mekanism.api.IHeatTransfer;
import mekanism.api.Range4D;
import mekanism.common.Mekanism;
import mekanism.common.base.IFluidContainerManager;
import mekanism.common.content.boiler.BoilerUpdateProtocol;
import mekanism.common.content.boiler.SynchronizedBoilerData;
import mekanism.common.content.boiler.SynchronizedBoilerData.ValveData;
import mekanism.common.multiblock.MultiblockManager;
import mekanism.common.network.PacketTileEntity.TileEntityMessage;
import mekanism.common.util.FluidContainerUtils;
import mekanism.common.util.FluidContainerUtils.ContainerEditMode;
import mekanism.common.util.HeatUtils;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.FluidContainerRegistry;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.IFluidContainerItem;
import io.netty.buffer.ByteBuf;
public class TileEntityBoiler extends TileEntityMultiblock<SynchronizedBoilerData> implements IFluidContainerManager, IHeatTransfer
{
/** A client-sided and server-sided map of valves on this tank's structure, used on the client for rendering fluids. */
public Map<ValveData, Integer> valveViewing = new HashMap<ValveData, Integer>();
/** The capacity this tank has on the client-side. */
public int clientWaterCapacity;
public int clientSteamCapacity;
public float prevWaterScale;
public float prevSteamScale;
public ForgeDirection innerSide;
public double temperature;
public double heatToAbsorb;
public double invHeatCapacity = 10;
public TileEntityBoiler()
{
this("SteamBoiler");
}
public TileEntityBoiler(String name)
{
super(name);
inventory = new ItemStack[2];
}
@Override
public void onUpdate()
{
super.onUpdate();
if(worldObj.isRemote)
{
if(structure != null && clientHasStructure && isRendering)
{
for(ValveData data : valveViewing.keySet())
{
if(valveViewing.get(data) > 0)
{
valveViewing.put(data, valveViewing.get(data)-1);
}
}
float targetScale = (float)(structure.waterStored != null ? structure.waterStored.amount : 0)/clientWaterCapacity;
if(Math.abs(prevWaterScale - targetScale) > 0.01)
{
prevWaterScale = (9*prevWaterScale + targetScale)/10;
}
targetScale = (float)(structure.steamStored != null ? structure.steamStored.amount : 0)/clientSteamCapacity;
if(Math.abs(prevSteamScale - targetScale) > 0.01)
{
prevSteamScale = (9*prevSteamScale+ targetScale)/10;
}
}
if(!clientHasStructure || !isRendering)
{
for(ValveData data : valveViewing.keySet())
{
TileEntityDynamicTank tileEntity = (TileEntityDynamicTank)data.location.getTileEntity(worldObj);
if(tileEntity != null)
{
tileEntity.clientHasStructure = false;
}
}
valveViewing.clear();
}
}
if(!worldObj.isRemote)
{
if(structure != null)
{
manageInventory();
}
simulateHeat();
applyTemperatureChange();
if(structure != null)
{
structure.applyTemperatureChange();
}
}
}
public void manageInventory()
{
int max = structure.volume * BoilerUpdateProtocol.WATER_PER_TANK;
if(structure.inventory[0] != null)
{
if(structure.inventory[0].getItem() instanceof IFluidContainerItem)
{
if(structure.editMode == ContainerEditMode.FILL && structure.waterStored != null)
{
int prev = structure.waterStored.amount;
structure.waterStored.amount -= FluidContainerUtils.insertFluid(structure.waterStored, structure.inventory[0]);
if(prev == structure.waterStored.amount || structure.waterStored.amount == 0)
{
if(structure.inventory[1] == null)
{
structure.inventory[1] = structure.inventory[0].copy();
structure.inventory[0] = null;
markDirty();
}
}
if(structure.waterStored.amount == 0)
{
structure.waterStored = null;
}
}
else if(structure.editMode == ContainerEditMode.EMPTY)
{
if(structure.waterStored != null)
{
FluidStack received = FluidContainerUtils.extractFluid(max-structure.waterStored.amount, structure.inventory[0], structure.waterStored.getFluid());
if(received != null)
{
structure.waterStored.amount += received.amount;
}
}
else {
structure.waterStored = FluidContainerUtils.extractFluid(max, structure.inventory[0], null);
}
int newStored = structure.waterStored != null ? structure.waterStored.amount : 0;
if(((IFluidContainerItem)structure.inventory[0].getItem()).getFluid(structure.inventory[0]) == null || newStored == max)
{
if(structure.inventory[1] == null)
{
structure.inventory[1] = structure.inventory[0].copy();
structure.inventory[0] = null;
markDirty();
}
}
}
}
else if(FluidContainerRegistry.isEmptyContainer(structure.inventory[0]) && (structure.editMode == ContainerEditMode.BOTH || structure.editMode == ContainerEditMode.FILL))
{
if(structure.waterStored != null && structure.waterStored.amount >= FluidContainerRegistry.BUCKET_VOLUME)
{
ItemStack filled = FluidContainerRegistry.fillFluidContainer(structure.waterStored, structure.inventory[0]);
if(filled != null)
{
if(structure.inventory[1] == null || (structure.inventory[1].isItemEqual(filled) && structure.inventory[1].stackSize+1 <= filled.getMaxStackSize()))
{
structure.inventory[0].stackSize--;
if(structure.inventory[0].stackSize <= 0)
{
structure.inventory[0] = null;
}
if(structure.inventory[1] == null)
{
structure.inventory[1] = filled;
}
else {
structure.inventory[1].stackSize++;
}
markDirty();
structure.waterStored.amount -= FluidContainerRegistry.getFluidForFilledItem(filled).amount;
if(structure.waterStored.amount == 0)
{
structure.waterStored = null;
}
Mekanism.packetHandler.sendToReceivers(new TileEntityMessage(Coord4D.get(this), getNetworkedData(new ArrayList())), new Range4D(Coord4D.get(this)));
}
}
}
}
else if(FluidContainerRegistry.isFilledContainer(structure.inventory[0]) && (structure.editMode == ContainerEditMode.BOTH || structure.editMode == ContainerEditMode.EMPTY))
{
FluidStack itemFluid = FluidContainerRegistry.getFluidForFilledItem(structure.inventory[0]);
if((structure.waterStored == null && itemFluid.amount <= max) || structure.waterStored.amount+itemFluid.amount <= max)
{
if(structure.waterStored != null && !structure.waterStored.isFluidEqual(itemFluid))
{
return;
}
ItemStack containerItem = structure.inventory[0].getItem().getContainerItem(structure.inventory[0]);
boolean filled = false;
if(containerItem != null)
{
if(structure.inventory[1] == null || (structure.inventory[1].isItemEqual(containerItem) && structure.inventory[1].stackSize+1 <= containerItem.getMaxStackSize()))
{
structure.inventory[0] = null;
if(structure.inventory[1] == null)
{
structure.inventory[1] = containerItem;
}
else {
structure.inventory[1].stackSize++;
}
filled = true;
}
}
else {
structure.inventory[0].stackSize--;
if(structure.inventory[0].stackSize == 0)
{
structure.inventory[0] = null;
}
filled = true;
}
if(filled)
{
if(structure.waterStored == null)
{
structure.waterStored = itemFluid.copy();
}
else {
structure.waterStored.amount += itemFluid.amount;
}
markDirty();
}
Mekanism.packetHandler.sendToReceivers(new TileEntityMessage(Coord4D.get(this), getNetworkedData(new ArrayList())), new Range4D(Coord4D.get(this)));
}
}
}
}
@Override
protected SynchronizedBoilerData getNewStructure()
{
return new SynchronizedBoilerData();
}
@Override
protected BoilerUpdateProtocol getProtocol()
{
return new BoilerUpdateProtocol(this);
}
@Override
public MultiblockManager<SynchronizedBoilerData> getManager()
{
return Mekanism.boilerManager;
}
@Override
public ArrayList getNetworkedData(ArrayList data)
{
super.getNetworkedData(data);
if(structure != null)
{
data.add(structure.volume*BoilerUpdateProtocol.WATER_PER_TANK);
data.add(structure.volume*BoilerUpdateProtocol.STEAM_PER_TANK);
data.add(structure.editMode.ordinal());
}
if(structure != null && structure.waterStored != null)
{
data.add(1);
data.add(structure.waterStored.fluidID);
data.add(structure.waterStored.amount);
}
else {
data.add(0);
}
if(structure != null && structure.steamStored != null)
{
data.add(1);
data.add(structure.steamStored.fluidID);
data.add(structure.steamStored.amount);
}
else {
data.add(0);
}
if(structure != null && isRendering)
{
data.add(structure.valves.size());
for(ValveData valveData : structure.valves)
{
valveData.location.write(data);
data.add(valveData.side.ordinal());
data.add(valveData.serverFluid);
}
}
return data;
}
@Override
public void handlePacketData(ByteBuf dataStream)
{
super.handlePacketData(dataStream);
if(clientHasStructure)
{
clientWaterCapacity = dataStream.readInt();
clientSteamCapacity = dataStream.readInt();
structure.editMode = ContainerEditMode.values()[dataStream.readInt()];
}
if(dataStream.readInt() == 1)
{
structure.waterStored = new FluidStack(dataStream.readInt(), dataStream.readInt());
}
else {
structure.waterStored = null;
}
if(dataStream.readInt() == 1)
{
structure.steamStored = new FluidStack(dataStream.readInt(), dataStream.readInt());
}
else {
structure.steamStored = null;
}
if(clientHasStructure && isRendering)
{
int size = dataStream.readInt();
for(int i = 0; i < size; i++)
{
ValveData data = new ValveData();
data.location = Coord4D.read(dataStream);
data.side = ForgeDirection.getOrientation(dataStream.readInt());
int viewingTicks = 0;
if(dataStream.readBoolean())
{
viewingTicks = 30;
}
if(viewingTicks == 0)
{
if(valveViewing.containsKey(data) && valveViewing.get(data) > 0)
{
continue;
}
}
valveViewing.put(data, viewingTicks);
TileEntityBoiler tileEntity = (TileEntityBoiler)data.location.getTileEntity(worldObj);
if(tileEntity != null)
{
tileEntity.clientHasStructure = true;
}
}
}
}
public int getScaledWaterLevel(int i)
{
if(clientWaterCapacity == 0 || structure.waterStored == null)
{
return 0;
}
return structure.waterStored.amount*i / clientWaterCapacity;
}
public int getScaledSteamLevel(int i)
{
if(clientSteamCapacity == 0 || structure.steamStored == null)
{
return 0;
}
return structure.steamStored.amount*i / clientSteamCapacity;
}
@Override
public ContainerEditMode getContainerEditMode()
{
if(structure != null)
{
return structure.editMode;
}
return ContainerEditMode.BOTH;
}
@Override
public void setContainerEditMode(ContainerEditMode mode)
{
if(structure == null)
{
return;
}
structure.editMode = mode;
}
@Override
public double getTemp()
{
return temperature;
}
@Override
public double getInverseConductionCoefficient()
{
return 10;
}
@Override
public double getInsulationCoefficient(ForgeDirection side)
{
return 10;
}
@Override
public void transferHeatTo(double heat)
{
heatToAbsorb += heat;
}
@Override
public double[] simulateHeat()
{
innerSide = null;
return HeatUtils.simulate(this);
}
@Override
public double applyTemperatureChange()
{
temperature += invHeatCapacity * heatToAbsorb;
heatToAbsorb = 0;
return temperature;
}
@Override
public boolean canConnectHeat(ForgeDirection side)
{
return structure == null || !isInnerSide(side);
}
@Override
public IHeatTransfer getAdjacent(ForgeDirection side)
{
if(structure != null && isInnerSide(side))
{
return structure;
}
else
{
TileEntity adj = Coord4D.get(this).getFromSide(side).getTileEntity(worldObj);
if(adj instanceof IHeatTransfer)
{
return (IHeatTransfer)adj;
}
}
return null;
}
public boolean isInnerSide(ForgeDirection side)
{
if(innerSide != null)
{
return side == innerSide;
}
if(!Coord4D.get(this).getFromSide(side).getBlock(worldObj).isAir(worldObj, xCoord, yCoord, zCoord))
{
return false;
}
if(structure == null || structure.minLocation == null || structure.maxLocation == null)
{
return false;
}
switch(side)
{
case DOWN:
return yCoord == structure.maxLocation.yCoord;
case UP:
return yCoord == structure.minLocation.yCoord;
case NORTH:
return zCoord == structure.maxLocation.zCoord;
case SOUTH:
return zCoord == structure.minLocation.zCoord;
case WEST:
return xCoord == structure.maxLocation.xCoord;
case EAST:
return xCoord == structure.minLocation.xCoord;
default:
return false;
}
}
}

View file

@ -0,0 +1,74 @@
package mekanism.common.tile;
import mekanism.common.content.boiler.BoilerSteamTank;
import mekanism.common.content.boiler.BoilerTank;
import mekanism.common.content.boiler.BoilerWaterTank;
import mekanism.common.util.PipeUtils;
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 TileEntityBoilerValve extends TileEntityBoiler implements IFluidHandler
{
public BoilerTank waterTank;
public BoilerTank steamTank;
public TileEntityBoilerValve()
{
super("Boiler Valve");
waterTank = new BoilerWaterTank(this);
steamTank = new BoilerSteamTank(this);
}
@Override
public FluidTankInfo[] getTankInfo(ForgeDirection from)
{
return ((!worldObj.isRemote && structure != null) || (worldObj.isRemote && clientHasStructure)) ? new FluidTankInfo[] {waterTank.getInfo(), steamTank.getInfo()} : PipeUtils.EMPTY;
}
@Override
public int fill(ForgeDirection from, FluidStack resource, boolean doFill)
{
return waterTank.fill(resource, doFill);
}
@Override
public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain)
{
if(structure != null && structure.steamStored != null)
{
if(resource.getFluid() == structure.steamStored.getFluid())
{
return steamTank.drain(resource.amount, doDrain);
}
}
return null;
}
@Override
public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain)
{
if(structure != null)
{
return steamTank.drain(maxDrain, doDrain);
}
return null;
}
@Override
public boolean canFill(ForgeDirection from, Fluid fluid)
{
return true;
}
@Override
public boolean canDrain(ForgeDirection from, Fluid fluid)
{
return true;
}
}

View file

@ -25,7 +25,7 @@ import net.minecraftforge.fluids.IFluidContainerItem;
import io.netty.buffer.ByteBuf;
public class TileEntityDynamicTank extends TileEntityMultiblock<SynchronizedTankData> implements IFluidContainerManager, IMultiblock<SynchronizedTankData>
public class TileEntityDynamicTank extends TileEntityMultiblock<SynchronizedTankData> implements IFluidContainerManager
{
/** A client-sided and server-sided map of valves on this tank's structure, used on the client for rendering fluids. */
public Map<ValveData, Integer> valveViewing = new HashMap<ValveData, Integer>();
@ -98,7 +98,7 @@ public class TileEntityDynamicTank extends TileEntityMultiblock<SynchronizedTank
public void manageInventory()
{
int max = structure.volume*TankUpdateProtocol.FLUID_PER_TANK;
int max = structure.volume * TankUpdateProtocol.FLUID_PER_TANK;
if(structure.inventory[0] != null)
{

View file

@ -34,9 +34,9 @@ public class TileEntityDynamicValve extends TileEntityDynamicTank implements IFl
@Override
public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain)
{
if(fluidTank.dynamicTank.structure != null && fluidTank.dynamicTank.structure.fluidStored != null)
if(structure != null && structure.fluidStored != null)
{
if(resource.getFluid() == fluidTank.dynamicTank.structure.fluidStored.getFluid())
if(resource.getFluid() == structure.fluidStored.getFluid())
{
return fluidTank.drain(resource.amount, doDrain);
}
@ -48,7 +48,7 @@ public class TileEntityDynamicValve extends TileEntityDynamicTank implements IFl
@Override
public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain)
{
if(fluidTank.dynamicTank.structure != null)
if(structure != null)
{
return fluidTank.drain(maxDrain, doDrain);
}

View file

@ -20,7 +20,7 @@ import cpw.mods.fml.relauncher.SideOnly;
import io.netty.buffer.ByteBuf;
public abstract class TileEntityMultiblock<T> extends TileEntityContainerBlock implements IMultiblock<T>
public abstract class TileEntityMultiblock<T extends SynchronizedData<T>> extends TileEntityContainerBlock implements IMultiblock<T>
{
/** The tank data for this structure. */
public T structure;
@ -138,7 +138,7 @@ public abstract class TileEntityMultiblock<T> extends TileEntityContainerBlock i
{
for(Coord4D obj : getSynchronizedData().locations)
{
TileEntityDynamicTank tileEntity = (TileEntityDynamicTank)obj.getTileEntity(worldObj);
TileEntityMultiblock<T> tileEntity = (TileEntityMultiblock<T>)obj.getTileEntity(worldObj);
if(tileEntity != null && tileEntity.isRendering)
{
@ -244,8 +244,8 @@ public abstract class TileEntityMultiblock<T> extends TileEntityContainerBlock i
}
@Override
public SynchronizedData<T> getSynchronizedData()
public T getSynchronizedData()
{
return (SynchronizedData<T>)structure;
return structure;
}
}

View file

@ -26,7 +26,8 @@ public class HeatUtils
continue;
}
//Transfer to air otherwise
double heatToTransfer = source.getTemp() / (IHeatTransfer.AIR_INVERSE_COEFFICIENT+source.getInsulationCoefficient(side)+source.getInverseConductionCoefficient());
double invConduction = IHeatTransfer.AIR_INVERSE_COEFFICIENT + source.getInsulationCoefficient(side) + source.getInverseConductionCoefficient();
double heatToTransfer = source.getTemp() / invConduction;
source.transferHeatTo(-heatToTransfer);
heatTransferred[1] += heatToTransfer;
}

View file

@ -432,7 +432,7 @@ public class TileEntityHeatGenerator extends TileEntityGenerator implements IFlu
@Override
public IHeatTransfer getAdjacent(ForgeDirection side)
{
if(side == ForgeDirection.DOWN)
if(canConnectHeat(side))
{
TileEntity adj = Coord4D.get(this).getFromSide(side).getTileEntity(worldObj);
if(adj instanceof IHeatTransfer)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB