package crazypants.enderio.machine.invpanel; import java.util.ArrayList; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.tileentity.TileEntity; import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidTank; import net.minecraftforge.fluids.FluidTankInfo; import net.minecraftforge.fluids.IFluidHandler; import com.enderio.core.api.common.util.ITankAccess; import crazypants.enderio.EnderIO; import crazypants.enderio.ModObject; import crazypants.enderio.conduit.TileConduitBundle; import crazypants.enderio.conduit.item.FilterRegister; import crazypants.enderio.conduit.item.ItemConduit; import crazypants.enderio.conduit.item.ItemConduitNetwork; import crazypants.enderio.conduit.item.filter.IItemFilter; import crazypants.enderio.config.Config; import crazypants.enderio.machine.AbstractMachineEntity; import crazypants.enderio.machine.IoMode; import crazypants.enderio.machine.SlotDefinition; import crazypants.enderio.machine.generator.zombie.IHasNutrientTank; import crazypants.enderio.machine.generator.zombie.PacketNutrientTank; import crazypants.enderio.machine.invpanel.client.ClientDatabaseManager; import crazypants.enderio.machine.invpanel.client.InventoryDatabaseClient; import crazypants.enderio.machine.invpanel.server.InventoryDatabaseServer; import crazypants.enderio.network.PacketHandler; import crazypants.enderio.tool.SmartTank; public class TileInventoryPanel extends AbstractMachineEntity implements IFluidHandler, ITankAccess, IHasNutrientTank { public static final int SLOT_CRAFTING_START = 0; public static final int SLOT_CRAFTING_RESULT = 9; public static final int SLOT_VIEW_FILTER = 10; public static final int SLOT_RETURN_START = 11; public static final int MAX_STORED_CRAFTING_RECIPES = 6; protected final SmartTank fuelTank; protected boolean tanksDirty; private InventoryDatabaseServer dbServer; private InventoryDatabaseClient dbClient; private boolean active; private boolean extractionDisabled; public InventoryPanelContainer eventHandler; private IItemFilter itemFilter; private int guiSortMode; private String guiFilterString = ""; private boolean guiSync; private final ArrayList<StoredCraftingRecipe> storedCraftingRecipes; public TileInventoryPanel() { super(new SlotDefinition(0, 8, 11, 20, 21, 20)); this.fuelTank = new SmartTank(EnderIO.fluidNutrientDistillation, Config.inventoryPanelFree ? 0 : 2000); this.storedCraftingRecipes = new ArrayList<StoredCraftingRecipe>(); } public InventoryDatabaseServer getDatabaseServer() { return dbServer; } public InventoryDatabaseClient getDatabaseClient(int generation) { if(dbClient != null && dbClient.getGeneration() != generation) { ClientDatabaseManager.INSTANCE.destroyDatabase(dbClient.getGeneration()); dbClient = null; } if(dbClient == null) { dbClient = ClientDatabaseManager.INSTANCE.getOrCreateDatabase(generation); } return dbClient; } public InventoryDatabaseClient getDatabaseClient() { return dbClient; } @Override public boolean canInsertItem(int slot, ItemStack var2, int side) { return false; } @Override protected boolean canExtractItem(int slot, ItemStack itemstack) { return !extractionDisabled && super.canExtractItem(slot, itemstack); } @Override protected boolean isMachineItemValidForSlot(int slot, ItemStack stack) { if(slot == SLOT_VIEW_FILTER && stack != null) { return FilterRegister.isItemFilter(stack) && FilterRegister.isFilterSet(stack); } return true; } @Override public ItemStack decrStackSize(int fromSlot, int amount) { ItemStack res = super.decrStackSize(fromSlot, amount); if(res != null && fromSlot < SLOT_CRAFTING_RESULT && eventHandler != null) { eventHandler.onCraftMatrixChanged(this); } if(res != null && fromSlot == SLOT_VIEW_FILTER) { updateItemFilter(); } return res; } @Override public void setInventorySlotContents(int slot, ItemStack contents) { super.setInventorySlotContents(slot, contents); if(slot < SLOT_CRAFTING_RESULT && eventHandler != null) { eventHandler.onCraftMatrixChanged(this); } if(slot == SLOT_VIEW_FILTER) { updateItemFilter(); } } private void updateItemFilter() { itemFilter = FilterRegister.getFilterForUpgrade(inventory[SLOT_VIEW_FILTER]); } public IItemFilter getItemFilter() { return itemFilter; } @Override public boolean isActive() { return Config.inventoryPanelFree || active; } @Override public void doUpdate() { if(worldObj.isRemote) { updateEntityClient(); return; } if(shouldDoWorkThisTick(20)) { scanNetwork(); } if(forceClientUpdate) { worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); markDirty(); } if(tanksDirty) { tanksDirty = false; PacketHandler.sendToAllAround(new PacketNutrientTank(this), this); } } private void scanNetwork() { ForgeDirection facingDir = getFacingDir(); ForgeDirection backside = facingDir.getOpposite(); ItemConduitNetwork icn = null; TileEntity te = worldObj.getTileEntity(xCoord + backside.offsetX, yCoord + backside.offsetY, zCoord + backside.offsetZ); if(te instanceof TileConduitBundle) { TileConduitBundle teCB = (TileConduitBundle) te; ItemConduit conduit = teCB.getConduit(ItemConduit.class); if(conduit != null) { icn = (ItemConduitNetwork) conduit.getNetwork(); } } if(icn != null) { dbServer = icn.getDatabase(); dbServer.sendChangeLogs(); refuelPower(dbServer); if(active != dbServer.isOperational()) { active = dbServer.isOperational(); forceClientUpdate = true; } } else { if(active) { forceClientUpdate = true; } dbServer = null; active = false; } } public float getAvailablePower() { return getPower() * Config.inventoryPanelPowerPerMB; } public void refuelPower(InventoryDatabaseServer db) { float missingPower = Config.inventoryPanelPowerPerMB * 0.5f - db.getPower(); if(missingPower > 0) { int amount = (int) Math.ceil(missingPower / Config.inventoryPanelPowerPerMB); amount = Math.min(amount, getPower()); if(amount > 0) { useNutrient(amount); dbServer.addPower(amount * Config.inventoryPanelPowerPerMB); } } } public void useNutrient(int amount) { fuelTank.drain(amount, true); tanksDirty = true; } private int getPower() { return Config.inventoryPanelFree ? 100 : fuelTank.getFluidAmount(); } @Override protected boolean processTasks(boolean redstoneCheckPassed) { return false; } public int getGuiSortMode() { return guiSortMode; } public String getGuiFilterString() { return guiFilterString; } public boolean getGuiSync() { return guiSync; } public void setGuiParameter(int sortMode, String filterString, boolean sync) { this.guiSortMode = sortMode; this.guiFilterString = filterString; this.guiSync = sync; if(worldObj != null && worldObj.isRemote) { PacketHandler.INSTANCE.sendToServer(new PacketGuiSettings(this, sortMode, filterString, sync)); } else { markDirty(); } } public int getStoredCraftingRecipes() { return storedCraftingRecipes.size(); } public StoredCraftingRecipe getStoredCraftingRecipe(int index) { if(index < 0 || index >= storedCraftingRecipes.size()) { return null; } return storedCraftingRecipes.get(index); } public void addStoredCraftingRecipe(StoredCraftingRecipe recipe) { if(worldObj != null && worldObj.isRemote) { PacketHandler.INSTANCE.sendToServer(new PacketStoredCraftingRecipe(PacketStoredCraftingRecipe.ACTION_ADD, 0, recipe)); } else { storedCraftingRecipes.add(recipe); markDirty(); updateBlock(); } } public void removeStoredCraftingRecipe(int index) { if(worldObj != null && worldObj.isRemote) { PacketHandler.INSTANCE.sendToServer(new PacketStoredCraftingRecipe(PacketStoredCraftingRecipe.ACTION_DELETE, index, null)); } else if(index >= 0 && index < storedCraftingRecipes.size()) { storedCraftingRecipes.remove(index); markDirty(); updateBlock(); } } public boolean isExtractionDisabled() { return extractionDisabled; } public void setExtractionDisabled(boolean extractionDisabled) { if(worldObj != null) { if(worldObj.isRemote) { PacketHandler.INSTANCE.sendToServer(new PacketSetExtractionDisabled(this, extractionDisabled)); } else if(this.extractionDisabled != extractionDisabled) { this.extractionDisabled = extractionDisabled; PacketHandler.INSTANCE.sendToDimension(new PacketUpdateExtractionDisabled(this, extractionDisabled), worldObj.provider.dimensionId); } } } /** * This is called by PacketUpdateExtractionDisabled on the client side * @param extractionDisabled if extraction is disabled */ void updateExtractionDisabled(boolean extractionDisabled) { this.extractionDisabled = extractionDisabled; } @Override public void writeCommon(NBTTagCompound nbtRoot) { super.writeCommon(nbtRoot); fuelTank.writeCommon("fuelTank", nbtRoot); nbtRoot.setInteger("guiSortMode", guiSortMode); nbtRoot.setString("guiFilterString", guiFilterString); nbtRoot.setBoolean("guiSync", guiSync); nbtRoot.setBoolean("extractionDisabled", extractionDisabled); if(!storedCraftingRecipes.isEmpty()) { NBTTagList recipesNBT = new NBTTagList(); for(StoredCraftingRecipe recipe : storedCraftingRecipes) { NBTTagCompound recipeNBT = new NBTTagCompound(); recipe.writeToNBT(recipeNBT); recipesNBT.appendTag(recipeNBT); } nbtRoot.setTag("craftingRecipes", recipesNBT); } } @Override public void readCommon(NBTTagCompound nbtRoot) { super.readCommon(nbtRoot); fuelTank.readCommon("fuelTank", nbtRoot); guiSortMode = nbtRoot.getInteger("guiSortMode"); guiFilterString = nbtRoot.getString("guiFilterString"); guiSync = nbtRoot.getBoolean("guiSync"); extractionDisabled = nbtRoot.getBoolean("extractionDisabled"); faceModes = null; storedCraftingRecipes.clear(); NBTTagList recipesNBT = (NBTTagList) nbtRoot.getTag("craftingRecipes"); if(recipesNBT != null) { for (int idx = 0; idx < recipesNBT.tagCount() && storedCraftingRecipes.size() < MAX_STORED_CRAFTING_RECIPES; idx++) { NBTTagCompound recipeNBT = recipesNBT.getCompoundTagAt(idx); StoredCraftingRecipe recipe = new StoredCraftingRecipe(); if(recipe.readFromNBT(recipeNBT)) { storedCraftingRecipes.add(recipe); } } } if(eventHandler != null) { eventHandler.checkCraftingRecipes(); } } @Override public void readCustomNBT(NBTTagCompound nbtRoot) { super.readCustomNBT(nbtRoot); active = nbtRoot.getBoolean("active"); updateItemFilter(); } @Override public void writeCustomNBT(NBTTagCompound nbtRoot) { super.writeCustomNBT(nbtRoot); nbtRoot.setBoolean("active", active); } @Override public String getMachineName() { return ModObject.blockInventoryPanel.unlocalisedName; } @Override public IoMode getIoMode(ForgeDirection face) { return face == getIODirection() ? IoMode.NONE : IoMode.DISABLED; } @Override public void setIoMode(ForgeDirection faceHit, IoMode mode) { } @Override public IoMode toggleIoModeForFace(ForgeDirection faceHit) { return getIoMode(faceHit); } private ForgeDirection getIODirection() { return getFacingDir().getOpposite(); } @Override public int fill(ForgeDirection from, FluidStack resource, boolean doFill) { if(from != getIODirection()) { return 0; } int res = fuelTank.fill(resource, doFill); if(res > 0 && doFill) { tanksDirty = true; } return res; } @Override public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain) { return null; } @Override public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) { return null; } @Override public boolean canFill(ForgeDirection from, Fluid fluid) { return from == getIODirection() && fuelTank.canFill(fluid); } @Override public boolean canDrain(ForgeDirection from, Fluid fluid) { return false; } @Override public FluidTankInfo[] getTankInfo(ForgeDirection from) { if(from == getIODirection()) { return new FluidTankInfo[] { fuelTank.getInfo() }; } else { return new FluidTankInfo[0]; } } @Override public FluidTank getInputTank(FluidStack forFluidType) { if(forFluidType != null && fuelTank.canFill(forFluidType.getFluid())) { return fuelTank; } return null; } @Override public FluidTank[] getOutputTanks() { return new FluidTank[0]; } @Override public void setTanksDirty() { tanksDirty = true; } @Override public SmartTank getNutrientTank() { return fuelTank; } }