package eiteam.esteemedinnovation.metalcasting.crucible; import eiteam.esteemedinnovation.api.crucible.CrucibleFormula; import eiteam.esteemedinnovation.api.crucible.CrucibleLiquid; import eiteam.esteemedinnovation.api.crucible.CrucibleRegistry; import eiteam.esteemedinnovation.api.mold.CrucibleMold; import eiteam.esteemedinnovation.api.tile.TileEntityTickableSafe; import eiteam.esteemedinnovation.metalcasting.mold.TileEntityMold; import net.minecraft.block.state.IBlockState; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.network.NetworkManager; import net.minecraft.network.play.server.SPacketUpdateTileEntity; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import org.apache.commons.lang3.tuple.Pair; import java.util.ArrayList; import java.util.HashMap; public class TileEntityCrucible extends TileEntityTickableSafe { public ArrayList<CrucibleLiquid> contents = new ArrayList<>(); public HashMap<CrucibleLiquid, Integer> number = new HashMap<>(); public boolean hasUpdated = true; public boolean needsUpdate = false; public int tipTicks = 0; private int targetFill = -1; private boolean tipping; public boolean isPowered; private int lastComparatorOutput = 0; public TileEntityCrucible() { isPowered = false; } @Override public NBTTagCompound getUpdateTag() { return writeToNBT(new NBTTagCompound()); } @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); NBTTagList nbttaglist = (NBTTagList) nbt.getTag("liquids"); for (int i = 0; i < nbttaglist.tagCount(); ++i) { NBTTagCompound nbttagcompound1 = nbttaglist.getCompoundTagAt(i); CrucibleLiquid liquid = CrucibleRegistry.getLiquidFromName(nbttagcompound1.getString("name")); if (liquid != null) { contents.add(liquid); number.put(liquid, (int) nbttagcompound1.getShort("amount")); } } } @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); NBTTagList nbttaglist = new NBTTagList(); for (CrucibleLiquid liquid : contents) { NBTTagCompound nbttagcompound1 = new NBTTagCompound(); nbttagcompound1.setShort("amount", (short) (int) number.get(liquid)); nbttagcompound1.setString("name", liquid.getName()); nbttaglist.appendTag(nbttagcompound1); } nbt.setTag("liquids", nbttaglist); return nbt; } @Override public SPacketUpdateTileEntity getUpdatePacket() { super.getUpdatePacket(); NBTTagCompound access = new NBTTagCompound(); NBTTagList nbttaglist = new NBTTagList(); access.setInteger("tipTicks", tipTicks); access.setBoolean("tipping", tipping); for (CrucibleLiquid liquid : contents) { if (liquid != null) { NBTTagCompound nbttagcompound1 = new NBTTagCompound(); nbttagcompound1.setShort("amount", (short) (int) number.get(liquid)); nbttagcompound1.setString("name", liquid.getName()); nbttaglist.appendTag(nbttagcompound1); } } access.setTag("liquids", nbttaglist); return new SPacketUpdateTileEntity(pos, 1, access); } @Override public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) { super.onDataPacket(net, pkt); NBTTagCompound access = pkt.getNbtCompound(); NBTTagList nbttaglist = (NBTTagList) access.getTag("liquids"); contents = new ArrayList<>(); number = new HashMap<>(); if (tipTicks == 0) { tipTicks = access.getInteger("tipTicks"); } tipping = access.getBoolean("tipping"); for (int i = 0; i < nbttaglist.tagCount(); ++i) { NBTTagCompound nbttagcompound1 = nbttaglist.getCompoundTagAt(i); CrucibleLiquid liquid = CrucibleRegistry.getLiquidFromName(nbttagcompound1.getString("name")); contents.add(liquid); number.put(liquid, (int) nbttagcompound1.getShort("amount")); } markForResync(); } @Override public boolean canUpdate(IBlockState target) { return target.getBlock() instanceof BlockCrucible; } @Override public void safeUpdate() { if (targetFill < 0) { targetFill = getFill(); } if (this.getFill() == targetFill) { hasUpdated = true; } IBlockState state = worldObj.getBlockState(pos); EnumFacing myDir = state.getValue(BlockCrucible.FACING); if (worldObj.isBlockIndirectlyGettingPowered(pos) > 0) { isPowered = true; } if (tipping || isPowered) { tipTicks++; if (tipTicks == 45 && !worldObj.isRemote) { int posX = pos.getX() + myDir.getFrontOffsetX(); int posY = pos.getY(); int posZ = pos.getZ() + myDir.getFrontOffsetZ(); BlockPos offsetPos = new BlockPos(posX, posY, posZ); TileEntity tile = worldObj.getTileEntity(offsetPos); if (tile != null && tile instanceof TileEntityMold) { TileEntityMold mold = (TileEntityMold) tile; if (mold.canPour() && contents.size() > 0) { ItemStack moldStack = mold.mold; CrucibleMold crucibleMold = (CrucibleMold) moldStack.getItem(); CrucibleLiquid liquid = getNextLiquid(crucibleMold, moldStack); if (liquid != null) { if (!worldObj.isRemote) { mold.pour(liquid); } int currNum = number.get(liquid); currNum -= crucibleMold.getCostToMold(liquid, moldStack); if (currNum == 0) { contents.remove(liquid); } number.remove(liquid); if (currNum > 0) { number.put(liquid, currNum); } needsUpdate = true; } } } } if (tipTicks > 140) { tipTicks = 0; tipping = false; isPowered = false; } } // Optimization: Don't iterate over all the liquids if we have nothing. if (!contents.isEmpty()) { for (CrucibleFormula formula : CrucibleRegistry.alloyFormulas) { if (formula.matches(contents, number)) { decreaseLiquid(formula.getLiquid1(), formula.getLiquid1Amount()); decreaseLiquid(formula.getLiquid2(), formula.getLiquid2Amount()); if (!number.containsKey(formula.getOutputLiquid())) { contents.add(formula.getOutputLiquid()); number.put(formula.getOutputLiquid(), 0); } int currNum = number.get(formula.getOutputLiquid()); currNum += formula.getOutputAmount(); number.remove(formula.getOutputLiquid()); number.put(formula.getOutputLiquid(), currNum); needsUpdate = true; } } } if (getComparatorOutput() != lastComparatorOutput){ lastComparatorOutput = getComparatorOutput(); markDirty(); } if (needsUpdate) { markForResync(state); needsUpdate = false; } } /** * Depletes the liquid contents of the crucible for the provided liquid and amount. * @param liquid The liquid to remove * @param amount The amount of said liquid to remove */ private void decreaseLiquid(CrucibleLiquid liquid, int amount) { int currNum = number.get(liquid); currNum -= amount; if (currNum == 0) { contents.remove(liquid); } number.remove(liquid); number.put(liquid, currNum); } public int getFill() { int fill = 0; for (CrucibleLiquid liquid : contents) { fill += number.get(liquid); } return fill; } public ItemStack fillWith(ItemStack stack, int amount, Pair<CrucibleLiquid, Integer> output) { int fill = getFill(); if (!worldObj.isRemote) { if (fill + amount <= 90 && hasUpdated) { CrucibleLiquid fluid = output.getLeft(); if (!contents.contains(fluid)) { contents.add(fluid); number.put(fluid, 0); } int currAmount = number.get(fluid); currAmount += amount; number.remove(fluid); number.put(fluid, currAmount); stack.stackSize--; hasUpdated = false; targetFill = fill + amount; needsUpdate = true; } } return stack; } public CrucibleLiquid getNextLiquid(CrucibleMold mold, ItemStack moldStack) { for (CrucibleLiquid liquid : CrucibleRegistry.liquids) { if (number.containsKey(liquid)) { if (mold.canUseOn(liquid, moldStack) && number.get(liquid) >= mold.getCostToMold(liquid, moldStack)) { return liquid; } } } return null; } public boolean isTipping() { return !(!tipping || tipTicks > 90); } public void setTipping() { tipping = true; tipTicks = 0; } public int getComparatorOutput() { return (int) ((double) 15 * (((double) getFill() / 90D))); } }