9577c53313
Added a new concept of NetworkId, allowing to transfer ids over the network instead of strings. RPCs are now all handled the same way (except RPC Pipes, to be completed when actually used).
825 lines
19 KiB
Java
825 lines
19 KiB
Java
/**
|
|
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
|
|
* http://www.mod-buildcraft.com
|
|
*
|
|
* BuildCraft is distributed under the terms of the Minecraft Mod Public
|
|
* License 1.0, or MMPL. Please check the contents of the license located in
|
|
* http://www.mod-buildcraft.com/MMPL-1.0.txt
|
|
*/
|
|
package buildcraft.builders;
|
|
|
|
import java.util.Collection;
|
|
import java.util.Iterator;
|
|
import java.util.LinkedList;
|
|
|
|
import net.minecraft.entity.player.EntityPlayer;
|
|
import net.minecraft.item.ItemStack;
|
|
import net.minecraft.nbt.NBTTagCompound;
|
|
import net.minecraft.nbt.NBTTagList;
|
|
import net.minecraft.tileentity.TileEntity;
|
|
import net.minecraft.util.AxisAlignedBB;
|
|
import net.minecraft.world.WorldSettings.GameType;
|
|
|
|
import net.minecraftforge.common.util.Constants;
|
|
import net.minecraftforge.common.util.ForgeDirection;
|
|
import net.minecraftforge.fluids.Fluid;
|
|
import net.minecraftforge.fluids.FluidContainerRegistry;
|
|
import net.minecraftforge.fluids.FluidStack;
|
|
import net.minecraftforge.fluids.FluidTankInfo;
|
|
import net.minecraftforge.fluids.IFluidHandler;
|
|
|
|
import buildcraft.BuildCraftBuilders;
|
|
import buildcraft.api.blueprints.BuildingPermission;
|
|
import buildcraft.api.blueprints.Translation;
|
|
import buildcraft.api.core.BlockIndex;
|
|
import buildcraft.api.core.NetworkData;
|
|
import buildcraft.api.core.Position;
|
|
import buildcraft.api.gates.IAction;
|
|
import buildcraft.core.Box;
|
|
import buildcraft.core.Box.Kind;
|
|
import buildcraft.core.IMachine;
|
|
import buildcraft.core.LaserData;
|
|
import buildcraft.core.blueprints.Blueprint;
|
|
import buildcraft.core.blueprints.BlueprintBase;
|
|
import buildcraft.core.blueprints.BptBuilderBase;
|
|
import buildcraft.core.blueprints.BptBuilderBlueprint;
|
|
import buildcraft.core.blueprints.BptBuilderTemplate;
|
|
import buildcraft.core.blueprints.BptContext;
|
|
import buildcraft.core.fluids.Tank;
|
|
import buildcraft.core.fluids.TankManager;
|
|
import buildcraft.core.inventory.InvUtils;
|
|
import buildcraft.core.inventory.SimpleInventory;
|
|
import buildcraft.core.network.RPC;
|
|
import buildcraft.core.network.RPCHandler;
|
|
import buildcraft.core.network.RPCMessageInfo;
|
|
import buildcraft.core.network.RPCSide;
|
|
|
|
public class TileBuilder extends TileAbstractBuilder implements IMachine, IFluidHandler {
|
|
|
|
private static int POWER_ACTIVATION = 50;
|
|
|
|
@NetworkData
|
|
public Box box = new Box();
|
|
public PathIterator currentPathIterator;
|
|
public Tank[] fluidTanks = new Tank[] {
|
|
new Tank("fluid1", FluidContainerRegistry.BUCKET_VOLUME * 8, this),
|
|
new Tank("fluid2", FluidContainerRegistry.BUCKET_VOLUME * 8, this),
|
|
new Tank("fluid3", FluidContainerRegistry.BUCKET_VOLUME * 8, this),
|
|
new Tank("fluid4", FluidContainerRegistry.BUCKET_VOLUME * 8, this)
|
|
};
|
|
@NetworkData
|
|
public TankManager<Tank> fluidTank = new TankManager<Tank>(fluidTanks);
|
|
|
|
private SimpleInventory inv = new SimpleInventory(28, "Builder", 64);
|
|
private BptBuilderBase bluePrintBuilder;
|
|
private LinkedList<BlockIndex> path;
|
|
private LinkedList<ItemStack> requiredToBuild;
|
|
private NBTTagCompound initNBT = null;
|
|
private boolean done = true;
|
|
|
|
private class PathIterator {
|
|
|
|
public Iterator<BlockIndex> currentIterator;
|
|
public double cx, cy, cz;
|
|
public float ix, iy, iz;
|
|
public BlockIndex to;
|
|
public double lastDistance;
|
|
AxisAlignedBB oldBoundingBox = null;
|
|
ForgeDirection o = null;
|
|
|
|
public PathIterator(BlockIndex from, Iterator<BlockIndex> it, ForgeDirection initialDir) {
|
|
this.to = it.next();
|
|
|
|
currentIterator = it;
|
|
|
|
double dx = to.x - from.x;
|
|
double dy = to.y - from.y;
|
|
double dz = to.z - from.z;
|
|
|
|
double size = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
|
|
cx = dx / size / 10;
|
|
cy = dy / size / 10;
|
|
cz = dz / size / 10;
|
|
|
|
ix = from.x;
|
|
iy = from.y;
|
|
iz = from.z;
|
|
|
|
lastDistance = (ix - to.x) * (ix - to.x) + (iy - to.y)
|
|
* (iy - to.y) + (iz - to.z) * (iz - to.z);
|
|
|
|
if (dx == 0 && dz == 0) {
|
|
o = initialDir;
|
|
} else if (Math.abs(dx) > Math.abs(dz)) {
|
|
if (dx > 0) {
|
|
o = ForgeDirection.EAST;
|
|
} else {
|
|
o = ForgeDirection.WEST;
|
|
}
|
|
} else {
|
|
if (dz > 0) {
|
|
o = ForgeDirection.SOUTH;
|
|
} else {
|
|
o = ForgeDirection.NORTH;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return false when reached the end of the iteration
|
|
*/
|
|
public BptBuilderBase next() {
|
|
while (true) {
|
|
BptBuilderBase bpt;
|
|
|
|
int newX = Math.round(ix);
|
|
int newY = Math.round(iy);
|
|
int newZ = Math.round(iz);
|
|
|
|
bpt = instanciateBluePrint(newX, newY, newZ, o);
|
|
|
|
if (bpt == null) {
|
|
return null;
|
|
}
|
|
|
|
AxisAlignedBB boundingBox = bpt.getBoundingBox();
|
|
|
|
if (oldBoundingBox == null || !collision(oldBoundingBox, boundingBox)) {
|
|
|
|
oldBoundingBox = boundingBox;
|
|
|
|
if (bpt != null) {
|
|
return bpt;
|
|
}
|
|
}
|
|
|
|
ix += cx;
|
|
iy += cy;
|
|
iz += cz;
|
|
|
|
double distance = (ix - to.x) * (ix - to.x) + (iy - to.y)
|
|
* (iy - to.y) + (iz - to.z) * (iz - to.z);
|
|
|
|
if (distance > lastDistance) {
|
|
return null;
|
|
} else {
|
|
lastDistance = distance;
|
|
}
|
|
}
|
|
}
|
|
|
|
public PathIterator iterate() {
|
|
if (currentIterator.hasNext()) {
|
|
PathIterator next = new PathIterator(to, currentIterator, o);
|
|
next.oldBoundingBox = oldBoundingBox;
|
|
|
|
return next;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public boolean collision(AxisAlignedBB left, AxisAlignedBB right) {
|
|
if (left.maxX < right.minX || left.minX > right.maxX) {
|
|
return false;
|
|
}
|
|
if (left.maxY < right.minY || left.minY > right.maxY) {
|
|
return false;
|
|
}
|
|
if (left.maxZ < right.minZ || left.minZ > right.maxZ) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public TileBuilder() {
|
|
super();
|
|
|
|
box.kind = Kind.STRIPES;
|
|
}
|
|
|
|
@Override
|
|
public void initialize() {
|
|
super.initialize();
|
|
|
|
if (worldObj.isRemote) {
|
|
return;
|
|
}
|
|
|
|
|
|
if (initNBT != null) {
|
|
iterateBpt(true);
|
|
|
|
if (initNBT.hasKey("iterator")) {
|
|
BlockIndex expectedTo = new BlockIndex(initNBT.getCompoundTag("iterator"));
|
|
|
|
while (!done && bluePrintBuilder != null && currentPathIterator != null) {
|
|
BlockIndex bi = new BlockIndex((int) currentPathIterator.ix,
|
|
(int) currentPathIterator.iy, (int) currentPathIterator.iz);
|
|
|
|
if (bi.equals(expectedTo)) {
|
|
break;
|
|
}
|
|
|
|
iterateBpt(true);
|
|
}
|
|
}
|
|
|
|
if (bluePrintBuilder != null) {
|
|
bluePrintBuilder.loadBuildStateToNBT(
|
|
initNBT.getCompoundTag("builderState"), this);
|
|
}
|
|
|
|
initNBT = null;
|
|
}
|
|
|
|
box.kind = Kind.STRIPES;
|
|
|
|
for (int x = xCoord - 1; x <= xCoord + 1; ++x) {
|
|
for (int y = yCoord - 1; y <= yCoord + 1; ++y) {
|
|
for (int z = zCoord - 1; z <= zCoord + 1; ++z) {
|
|
TileEntity tile = worldObj.getTileEntity(x, y, z);
|
|
|
|
if (tile instanceof TilePathMarker) {
|
|
path = ((TilePathMarker) tile).getPath();
|
|
|
|
for (BlockIndex b : path) {
|
|
worldObj.setBlockToAir(b.x, b.y, b.z);
|
|
|
|
BuildCraftBuilders.pathMarkerBlock.dropBlockAsItem(
|
|
worldObj, b.x, b.y, b.z,
|
|
0, 0);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (path != null && pathLasers.size() == 0) {
|
|
createLasersForPath();
|
|
|
|
sendNetworkUpdate();
|
|
}
|
|
|
|
iterateBpt(false);
|
|
}
|
|
|
|
public void createLasersForPath() {
|
|
pathLasers = new LinkedList<LaserData>();
|
|
BlockIndex previous = null;
|
|
|
|
for (BlockIndex b : path) {
|
|
if (previous != null) {
|
|
LaserData laser = new LaserData(new Position(previous.x + 0.5,
|
|
previous.y + 0.5, previous.z + 0.5), new Position(
|
|
b.x + 0.5, b.y + 0.5, b.z + 0.5));
|
|
|
|
pathLasers.add(laser);
|
|
}
|
|
|
|
previous = b;
|
|
}
|
|
}
|
|
|
|
public BptBuilderBase instanciateBluePrint(int x, int y, int z, ForgeDirection o) {
|
|
BlueprintBase bpt = null;
|
|
|
|
try {
|
|
bpt = ItemBlueprint.loadBlueprint(getStackInSlot(0));
|
|
} catch (Throwable t) {
|
|
setInventorySlotContents(0, null);
|
|
t.printStackTrace();
|
|
return null;
|
|
}
|
|
|
|
if (bpt == null) {
|
|
return null;
|
|
}
|
|
|
|
if (bpt.buildingPermission == BuildingPermission.NONE
|
|
|| (bpt.buildingPermission == BuildingPermission.CREATIVE_ONLY && worldObj
|
|
.getWorldInfo().getGameType() != GameType.CREATIVE)) {
|
|
return null;
|
|
}
|
|
|
|
BptContext context = bpt.getContext(worldObj, bpt.getBoxForPos(x, y, z));
|
|
|
|
if (bpt.rotate) {
|
|
if (o == ForgeDirection.EAST) {
|
|
// Do nothing
|
|
} else if (o == ForgeDirection.SOUTH) {
|
|
bpt.rotateLeft(context);
|
|
} else if (o == ForgeDirection.WEST) {
|
|
bpt.rotateLeft(context);
|
|
bpt.rotateLeft(context);
|
|
} else if (o == ForgeDirection.NORTH) {
|
|
bpt.rotateLeft(context);
|
|
bpt.rotateLeft(context);
|
|
bpt.rotateLeft(context);
|
|
}
|
|
}
|
|
|
|
Translation transform = new Translation();
|
|
|
|
transform.x = x - bpt.anchorX;
|
|
transform.y = y - bpt.anchorY;
|
|
transform.z = z - bpt.anchorZ;
|
|
|
|
bpt.translateToWorld(transform);
|
|
|
|
if (getStackInSlot(0).getItem() instanceof ItemBlueprintStandard) {
|
|
return new BptBuilderBlueprint((Blueprint) bpt, worldObj, x, y, z);
|
|
} else if (getStackInSlot(0).getItem() instanceof ItemBlueprintTemplate) {
|
|
return new BptBuilderTemplate(bpt, worldObj, x, y, z);
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public void iterateBpt(boolean forceIterate) {
|
|
if (getStackInSlot(0) == null || !(getStackInSlot(0).getItem() instanceof ItemBlueprint)) {
|
|
if (bluePrintBuilder != null) {
|
|
bluePrintBuilder = null;
|
|
}
|
|
|
|
if (box.isInitialized()) {
|
|
box.reset();
|
|
}
|
|
|
|
if (currentPathIterator != null) {
|
|
currentPathIterator = null;
|
|
}
|
|
|
|
updateRequirements();
|
|
|
|
sendNetworkUpdate();
|
|
|
|
return;
|
|
}
|
|
|
|
if (bluePrintBuilder == null || (bluePrintBuilder.isDone(this) || forceIterate)) {
|
|
if (path != null && path.size() > 1) {
|
|
if (currentPathIterator == null) {
|
|
Iterator<BlockIndex> it = path.iterator();
|
|
BlockIndex start = it.next();
|
|
currentPathIterator = new PathIterator(start, it,
|
|
ForgeDirection.values()[worldObj.getBlockMetadata(
|
|
xCoord, yCoord, zCoord)].getOpposite());
|
|
}
|
|
|
|
if (bluePrintBuilder != null && bluePrintBuilder.isDone(this)) {
|
|
bluePrintBuilder.postProcessing(worldObj);
|
|
}
|
|
|
|
bluePrintBuilder = currentPathIterator.next();
|
|
|
|
if (bluePrintBuilder != null) {
|
|
box.reset();
|
|
box.initialize(bluePrintBuilder);
|
|
sendNetworkUpdate();
|
|
}
|
|
|
|
if (bluePrintBuilder == null) {
|
|
currentPathIterator = currentPathIterator.iterate();
|
|
}
|
|
|
|
if (currentPathIterator == null) {
|
|
done = true;
|
|
} else {
|
|
done = false;
|
|
}
|
|
} else {
|
|
if (bluePrintBuilder != null && bluePrintBuilder.isDone(this)) {
|
|
bluePrintBuilder.postProcessing(worldObj);
|
|
|
|
done = true;
|
|
bluePrintBuilder = null;
|
|
} else {
|
|
bluePrintBuilder = instanciateBluePrint(xCoord, yCoord, zCoord,
|
|
ForgeDirection.values()[worldObj.getBlockMetadata(xCoord, yCoord, zCoord)].getOpposite());
|
|
|
|
if (bluePrintBuilder != null) {
|
|
box.initialize(bluePrintBuilder);
|
|
sendNetworkUpdate();
|
|
done = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
updateRequirements();
|
|
}
|
|
|
|
if (done) {
|
|
boolean dropBlueprint = true;
|
|
for (int i = 1; i < getSizeInventory(); ++i) {
|
|
if (getStackInSlot(i) == null) {
|
|
setInventorySlotContents(i, getStackInSlot(0));
|
|
dropBlueprint = false;
|
|
break;
|
|
}
|
|
}
|
|
if (dropBlueprint) {
|
|
InvUtils.dropItems(getWorld(), getStackInSlot(0), xCoord, yCoord, zCoord);
|
|
}
|
|
|
|
setInventorySlotContents(0, null);
|
|
box.reset();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public int getSizeInventory() {
|
|
return inv.getSizeInventory();
|
|
}
|
|
|
|
@Override
|
|
public ItemStack getStackInSlot(int i) {
|
|
return inv.getStackInSlot(i);
|
|
}
|
|
|
|
@Override
|
|
public ItemStack decrStackSize(int i, int j) {
|
|
ItemStack result = inv.decrStackSize(i, j);
|
|
|
|
if (!worldObj.isRemote) {
|
|
if (i == 0) {
|
|
RPCHandler.rpcBroadcastWorldPlayers(worldObj, this, "setItemRequirements",
|
|
null, null);
|
|
iterateBpt(false);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
@Override
|
|
public void setInventorySlotContents(int i, ItemStack itemstack) {
|
|
inv.setInventorySlotContents(i, itemstack);
|
|
|
|
if (!worldObj.isRemote) {
|
|
if (i == 0) {
|
|
iterateBpt(false);
|
|
done = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public ItemStack getStackInSlotOnClosing(int slot) {
|
|
return inv.getStackInSlotOnClosing(slot);
|
|
}
|
|
|
|
@Override
|
|
public String getInventoryName() {
|
|
return "Builder";
|
|
}
|
|
|
|
@Override
|
|
public int getInventoryStackLimit() {
|
|
return 64;
|
|
}
|
|
|
|
@Override
|
|
public boolean isUseableByPlayer(EntityPlayer entityplayer) {
|
|
return worldObj.getTileEntity(xCoord, yCoord, zCoord) == this;
|
|
}
|
|
|
|
@Override
|
|
public void readFromNBT(NBTTagCompound nbttagcompound) {
|
|
super.readFromNBT(nbttagcompound);
|
|
|
|
inv.readFromNBT(nbttagcompound);
|
|
|
|
if (nbttagcompound.hasKey("box")) {
|
|
box.initialize(nbttagcompound.getCompoundTag("box"));
|
|
}
|
|
|
|
if (nbttagcompound.hasKey("path")) {
|
|
path = new LinkedList<BlockIndex>();
|
|
NBTTagList list = nbttagcompound.getTagList("path",
|
|
Constants.NBT.TAG_COMPOUND);
|
|
|
|
for (int i = 0; i < list.tagCount(); ++i) {
|
|
path.add(new BlockIndex(list.getCompoundTagAt(i)));
|
|
}
|
|
}
|
|
|
|
done = nbttagcompound.getBoolean("done");
|
|
fluidTank.readFromNBT(nbttagcompound);
|
|
|
|
// The rest of load has to be done upon initialize.
|
|
initNBT = (NBTTagCompound) nbttagcompound.getCompoundTag("bptBuilder").copy();
|
|
}
|
|
|
|
@Override
|
|
public void writeToNBT(NBTTagCompound nbttagcompound) {
|
|
super.writeToNBT(nbttagcompound);
|
|
|
|
inv.writeToNBT(nbttagcompound);
|
|
|
|
if (box.isInitialized()) {
|
|
NBTTagCompound boxStore = new NBTTagCompound();
|
|
box.writeToNBT(boxStore);
|
|
nbttagcompound.setTag("box", boxStore);
|
|
}
|
|
|
|
if (path != null) {
|
|
NBTTagList list = new NBTTagList();
|
|
|
|
for (BlockIndex i : path) {
|
|
NBTTagCompound c = new NBTTagCompound();
|
|
i.writeTo(c);
|
|
list.appendTag(c);
|
|
}
|
|
|
|
nbttagcompound.setTag("path", list);
|
|
}
|
|
|
|
nbttagcompound.setBoolean("done", done);
|
|
fluidTank.writeToNBT(nbttagcompound);
|
|
|
|
NBTTagCompound bptNBT = new NBTTagCompound();
|
|
|
|
if (bluePrintBuilder != null) {
|
|
NBTTagCompound builderCpt = new NBTTagCompound();
|
|
bluePrintBuilder.saveBuildStateToNBT(builderCpt, this);
|
|
bptNBT.setTag("builderState", builderCpt);
|
|
}
|
|
|
|
if (currentPathIterator != null) {
|
|
NBTTagCompound iteratorNBT = new NBTTagCompound();
|
|
new BlockIndex((int) currentPathIterator.ix,
|
|
(int) currentPathIterator.iy, (int) currentPathIterator.iz)
|
|
.writeTo(iteratorNBT);
|
|
bptNBT.setTag ("iterator", iteratorNBT);
|
|
}
|
|
|
|
nbttagcompound.setTag("bptBuilder", bptNBT);
|
|
}
|
|
|
|
@Override
|
|
public void invalidate() {
|
|
super.invalidate();
|
|
destroy();
|
|
}
|
|
|
|
@Override
|
|
public void openInventory() {
|
|
}
|
|
|
|
@Override
|
|
public void closeInventory() {
|
|
}
|
|
|
|
@Override
|
|
public void updateEntity() {
|
|
super.updateEntity();
|
|
|
|
if (worldObj.isRemote) {
|
|
return;
|
|
}
|
|
|
|
if (bluePrintBuilder != null) {
|
|
bluePrintBuilder.removeDoneBuilders(this);
|
|
}
|
|
|
|
if ((bluePrintBuilder == null || bluePrintBuilder.isDone(this))
|
|
&& box.isInitialized()) {
|
|
box.reset();
|
|
|
|
sendNetworkUpdate();
|
|
|
|
return;
|
|
}
|
|
|
|
iterateBpt(false);
|
|
|
|
if (getWorld().getWorldInfo().getGameType() == GameType.CREATIVE) {
|
|
build();
|
|
} else {
|
|
if (mjStored > POWER_ACTIVATION) {
|
|
build();
|
|
}
|
|
}
|
|
|
|
|
|
if (done) {
|
|
return;
|
|
} else if (mjStored < 25) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean isActive() {
|
|
return !done;
|
|
}
|
|
|
|
@Override
|
|
public boolean manageFluids() {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean manageSolids() {
|
|
return true;
|
|
}
|
|
|
|
public boolean isBuildingBlueprint() {
|
|
return getStackInSlot(0) != null && getStackInSlot(0).getItem() instanceof ItemBlueprint;
|
|
}
|
|
|
|
public Collection<ItemStack> getNeededItems() {
|
|
return requiredToBuild;
|
|
}
|
|
|
|
@RPC (RPCSide.CLIENT)
|
|
public void setItemRequirements(LinkedList<ItemStack> rq, LinkedList<Integer> realSizes) {
|
|
// Item stack serialized are represented through bytes, so 0-255. In
|
|
// order to get the real amounts, we need to pass the real sizes of the
|
|
// stacks as a separate list.
|
|
|
|
requiredToBuild = rq;
|
|
|
|
if (rq != null && rq.size() > 0) {
|
|
Iterator<ItemStack> itStack = rq.iterator();
|
|
Iterator<Integer> size = realSizes.iterator();
|
|
|
|
while (true) {
|
|
ItemStack stack = itStack.next();
|
|
stack.stackSize = size.next();
|
|
|
|
if (stack.stackSize > 999) {
|
|
stack.stackSize = 999;
|
|
}
|
|
|
|
if (!itStack.hasNext()) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean isBuildingMaterialSlot(int i) {
|
|
return i != 0;
|
|
}
|
|
|
|
@Override
|
|
public boolean allowAction(IAction action) {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean hasCustomInventoryName() {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean isItemValidForSlot(int slot, ItemStack stack) {
|
|
if (slot == 0) {
|
|
return stack.getItem() instanceof ItemBlueprint;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public Box getBox() {
|
|
return box;
|
|
}
|
|
|
|
@Override
|
|
public AxisAlignedBB getRenderBoundingBox() {
|
|
Box renderBox = new Box (this).extendToEncompass(box);
|
|
|
|
for (LaserData l : pathLasers) {
|
|
renderBox = renderBox.extendToEncompass(l.head);
|
|
renderBox = renderBox.extendToEncompass(l.tail);
|
|
}
|
|
|
|
return renderBox.expand(50).getBoundingBox();
|
|
}
|
|
|
|
public void build () {
|
|
if (!buildTracker.markTimeIfDelay(worldObj)) {
|
|
return;
|
|
}
|
|
|
|
if (bluePrintBuilder != null) {
|
|
bluePrintBuilder.buildNextSlot(worldObj, this, xCoord, yCoord, zCoord);
|
|
|
|
updateRequirements();
|
|
}
|
|
}
|
|
|
|
public void updateRequirements () {
|
|
if (bluePrintBuilder instanceof BptBuilderBlueprint) {
|
|
LinkedList<Integer> realSize = new LinkedList<Integer>();
|
|
|
|
for (ItemStack stack : ((BptBuilderBlueprint) bluePrintBuilder).neededItems) {
|
|
realSize.add(stack.stackSize);
|
|
stack.stackSize = 0;
|
|
}
|
|
|
|
RPCHandler.rpcBroadcastWorldPlayers(worldObj, this, "setItemRequirements",
|
|
((BptBuilderBlueprint) bluePrintBuilder).neededItems, realSize);
|
|
} else {
|
|
RPCHandler.rpcBroadcastWorldPlayers(worldObj, this, "setItemRequirements", null, null);
|
|
}
|
|
|
|
}
|
|
|
|
public BptBuilderBase getBlueprint () {
|
|
if (bluePrintBuilder != null) {
|
|
return bluePrintBuilder;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean canDrain(ForgeDirection from, Fluid fluid) {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain) {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) {
|
|
return null;
|
|
}
|
|
|
|
public boolean drainBuild(FluidStack fluidStack, boolean realDrain) {
|
|
for (Tank tank : fluidTanks) {
|
|
if (tank.getFluidType() == fluidStack.getFluid()) {
|
|
return tank.getFluidAmount() >= fluidStack.amount && tank.drain(fluidStack.amount, realDrain).amount > 0;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public int fill(ForgeDirection from, FluidStack resource, boolean doFill) {
|
|
Fluid fluid = resource.getFluid();
|
|
Tank emptyTank = null;
|
|
for (Tank tank : fluidTanks) {
|
|
Fluid type = tank.getFluidType();
|
|
if (type == fluid) {
|
|
int used = tank.fill(resource, doFill);
|
|
if (used > 0 && doFill) {
|
|
sendNetworkUpdate();
|
|
}
|
|
return used;
|
|
} else if (emptyTank == null && tank.isEmpty()) {
|
|
emptyTank = tank;
|
|
}
|
|
}
|
|
if (emptyTank != null) {
|
|
int used = emptyTank.fill(resource, doFill);
|
|
if (used > 0 && doFill) {
|
|
sendNetworkUpdate();
|
|
}
|
|
return used;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public boolean canFill(ForgeDirection from, Fluid fluid) {
|
|
boolean emptyAvailable = false;
|
|
for (Tank tank : fluidTanks) {
|
|
Fluid type = tank.getFluidType();
|
|
if (type == fluid) {
|
|
return !tank.isFull();
|
|
} else if (!emptyAvailable) {
|
|
emptyAvailable = tank.isEmpty();
|
|
}
|
|
}
|
|
return emptyAvailable;
|
|
}
|
|
|
|
@Override
|
|
public FluidTankInfo[] getTankInfo(ForgeDirection from) {
|
|
return fluidTank.getTankInfo(from);
|
|
}
|
|
|
|
@RPC(RPCSide.SERVER)
|
|
public void eraseFluidTank(int id, RPCMessageInfo info) {
|
|
if (id < 0 || id >= fluidTanks.length) {
|
|
return;
|
|
}
|
|
if (isUseableByPlayer(info.sender) && info.sender.getDistanceSq(xCoord, yCoord, zCoord) <= 64) {
|
|
fluidTanks[id].setFluid(null);
|
|
sendNetworkUpdate();
|
|
}
|
|
}
|
|
}
|