package mcjty.rftools.blocks.dimlets; import mcjty.lib.container.InventoryHelper; import mcjty.lib.entity.GenericEnergyReceiverTileEntity; import mcjty.lib.network.Argument; import mcjty.lib.network.PacketRequestIntegerFromServer; import mcjty.lib.varia.BlockTools; import mcjty.rftools.blocks.teleporter.TeleportDestinations; import mcjty.rftools.blocks.teleporter.TeleporterSetup; import mcjty.rftools.dimension.DimensionInformation; import mcjty.rftools.dimension.DimensionStorage; import mcjty.rftools.dimension.RfToolsDimensionManager; import mcjty.rftools.dimension.world.WorldGenerationTools; import mcjty.rftools.items.dimlets.*; import mcjty.rftools.items.dimlets.types.IDimletType; import mcjty.rftools.network.RFToolsMessages; import mcjty.rftools.varia.Broadcaster; import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.inventory.ISidedInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.world.World; import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.util.Constants; import net.minecraftforge.common.util.ForgeDirection; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.util.Map; public class DimensionEditorTileEntity extends GenericEnergyReceiverTileEntity implements ISidedInventory { public static final String CMD_GETEDITING = "getEditing"; public static final String CLIENTCMD_GETEDITING = "getEditing"; private static int editPercentage = 0; private int ticksLeft = -1; private int ticksCost = -1; private int rfPerTick = -1; private InventoryHelper inventoryHelper = new InventoryHelper(this, DimensionEditorContainer.factory, 2); public DimensionEditorTileEntity() { super(DimletConfiguration.EDITOR_MAXENERGY, DimletConfiguration.EDITOR_RECEIVEPERTICK); } @Override protected void checkStateServer() { ItemStack injectableItemStack = validateInjectableItemStack(); if (injectableItemStack == null) { return; } ItemStack dimensionItemStack = validateDimensionItemStack(); if (dimensionItemStack == null) { return; } if (ticksLeft == -1) { // We were not injecting. Start now. if (isMatterReceiver(injectableItemStack)) { ticksCost = DimletCosts.baseDimensionTickCost + 1000; ticksLeft = ticksCost; rfPerTick = DimletCosts.baseDimensionCreationCost + 200; } else if (isTNT(injectableItemStack)) { ticksCost = 600; ticksLeft = ticksCost; rfPerTick = 10; } else { DimletKey key = KnownDimletConfiguration.getDimletKey(injectableItemStack, worldObj); DimletEntry dimletEntry = KnownDimletConfiguration.getEntry(key); ticksCost = DimletCosts.baseDimensionTickCost + dimletEntry.getTickCost(); ticksLeft = ticksCost; rfPerTick = DimletCosts.baseDimensionCreationCost + dimletEntry.getRfCreateCost(); } } else { int rf = getEnergyStored(ForgeDirection.DOWN); int rfpt = rfPerTick; rfpt = (int) (rfpt * (2.0f - getInfusedFactor()) / 2.0f); if (rf >= rfpt) { // Enough energy. consumeEnergy(rfpt); ticksLeft--; if (ticksLeft <= 0) { RfToolsDimensionManager dimensionManager = RfToolsDimensionManager.getDimensionManager(worldObj); ItemStack dimensionTab = validateDimensionItemStack(); NBTTagCompound tagCompound = dimensionTab.getTagCompound(); int id = tagCompound.getInteger("id"); injectableItemStack = validateInjectableItemStack(); if (isMatterReceiver(injectableItemStack)) { World dimWorld = dimensionManager.getWorldForDimension(id); int y = findGoodReceiverLocation(dimWorld); if (y == -1) { y = dimWorld.getHeight() / 2; } dimWorld.setBlock(8, y, 8, TeleporterSetup.matterReceiverBlock, 0, 2); TeleporterSetup.matterReceiverBlock.onBlockPlaced(dimWorld, 8, y, 8, 0, 0, 0, 0, 0); TeleporterSetup.matterReceiverBlock.onBlockPlacedBy(dimWorld, 8, y, 8, null, injectableItemStack); dimWorld.setBlockToAir(8, y + 1, 8); dimWorld.setBlockToAir(8, y + 2, 8); } else if (isTNT(injectableItemStack)) { safeDeleteDimension(id, dimensionTab); } else { DimletKey key = KnownDimletConfiguration.getDimletKey(injectableItemStack, worldObj); DimensionInformation information = dimensionManager.getDimensionInformation(id); information.injectDimlet(key); dimensionManager.save(worldObj); } inventoryHelper.decrStackSize(DimensionEditorContainer.SLOT_INJECTINPUT, 1); stopInjecting(); } } } markDirty(); setState(); } private void safeDeleteDimension(int id, ItemStack dimensionTab) { World w = DimensionManager.getWorld(id); if (w != null) { // Dimension is still loaded. Do nothing. Broadcaster.broadcast(worldObj, xCoord, yCoord, zCoord, "Dimension cannot be deleted. It is still in use!", 10); return; } RfToolsDimensionManager dimensionManager = RfToolsDimensionManager.getDimensionManager(worldObj); DimensionInformation information = dimensionManager.getDimensionInformation(id); if (information.getOwner() == null) { Broadcaster.broadcast(worldObj, xCoord, yCoord, zCoord, "You cannot delete a dimension without an owner!", 10); return; } if (getOwnerUUID() == null) { Broadcaster.broadcast(worldObj, xCoord, yCoord, zCoord, "This machine has no proper owner and cannot delete dimensions!", 10); return; } if (!getOwnerUUID().equals(information.getOwner())) { Broadcaster.broadcast(worldObj, xCoord, yCoord, zCoord, "This machine's owner differs from the dimensions owner!", 10); return; } TeleportDestinations destinations = TeleportDestinations.getDestinations(worldObj); destinations.removeDestinationsInDimension(id); destinations.save(worldObj); dimensionManager.removeDimension(id); dimensionManager.reclaimId(id); dimensionManager.save(worldObj); DimensionStorage dimensionStorage = DimensionStorage.getDimensionStorage(worldObj); dimensionStorage.removeDimension(id); dimensionStorage.save(worldObj); if (DimletConfiguration.dimensionFolderIsDeletedWithSafeDel) { File rootDirectory = DimensionManager.getCurrentSaveRootDirectory(); try { FileUtils.deleteDirectory(new File(rootDirectory.getPath() + File.separator + "DIM" + id)); Broadcaster.broadcast(worldObj, xCoord, yCoord, zCoord, "Dimension deleted and dimension folder succesfully wiped!", 10); } catch (IOException e) { Broadcaster.broadcast(worldObj, xCoord, yCoord, zCoord, "Dimension deleted but dimension folder could not be completely wiped!", 10); } } else { Broadcaster.broadcast(worldObj, xCoord, yCoord, zCoord, "Dimension deleted. Please remove the dimension folder from disk!", 10); } dimensionTab.getTagCompound().removeTag("id"); int tickCost = dimensionTab.getTagCompound().getInteger("tickCost"); dimensionTab.getTagCompound().setInteger("ticksLeft", tickCost); } private int findGoodReceiverLocation(World dimWorld) { int y = WorldGenerationTools.findSuitableEmptySpot(dimWorld, 8, 8); y++; return y; } private ItemStack validateInjectableItemStack() { ItemStack itemStack = inventoryHelper.getStackInSlot(DimensionEditorContainer.SLOT_INJECTINPUT); if (itemStack == null || itemStack.stackSize == 0) { stopInjecting(); return null; } if (isMatterReceiver(itemStack)) { return itemStack; } if (isTNT(itemStack)) { return canDeleteDimension(itemStack); } DimletKey key = KnownDimletConfiguration.getDimletKey(itemStack, worldObj); DimletType type = key.getType(); IDimletType itype = type.dimletType; if (itype.isInjectable()) { return itemStack; } else { return null; } } private ItemStack canDeleteDimension(ItemStack itemStack) { if (!DimletConfiguration.playersCanDeleteDimensions) { Broadcaster.broadcast(worldObj, xCoord, yCoord, zCoord, "Players cannot delete dimensions!", 10); return null; } if (!DimletConfiguration.editorCanDeleteDimensions) { Broadcaster.broadcast(worldObj, xCoord, yCoord, zCoord, "Dimension deletion with the editor is not enabled!", 10); return null; } ItemStack dimensionStack = inventoryHelper.getStackInSlot(DimensionEditorContainer.SLOT_DIMENSIONTARGET); if (dimensionStack == null || dimensionStack.stackSize == 0) { return null; } NBTTagCompound tagCompound = dimensionStack.getTagCompound(); int id = tagCompound.getInteger("id"); if (id == 0) { return null; } DimensionInformation information = RfToolsDimensionManager.getDimensionManager(worldObj).getDimensionInformation(id); if (getOwnerUUID() != null && getOwnerUUID().equals(information.getOwner())) { return itemStack; } Broadcaster.broadcast(worldObj, xCoord, yCoord, zCoord, "This machine's owner differs from the dimensions owner!", 10); return null; } private boolean isMatterReceiver(ItemStack itemStack) { Block block = BlockTools.getBlock(itemStack); if (block == TeleporterSetup.matterReceiverBlock) { // We can inject matter receivers too. return true; } return false; } private boolean isTNT(ItemStack itemStack) { Block block = BlockTools.getBlock(itemStack); if (block == Blocks.tnt) { // We can inject TNT to destroy a dimension. return true; } return false; } private ItemStack validateDimensionItemStack() { ItemStack itemStack = inventoryHelper.getStackInSlot(DimensionEditorContainer.SLOT_DIMENSIONTARGET); if (itemStack == null || itemStack.stackSize == 0) { stopInjecting(); return null; } NBTTagCompound tagCompound = itemStack.getTagCompound(); int id = tagCompound.getInteger("id"); if (id == 0) { // Not a valid dimension. stopInjecting(); return null; } return itemStack; } private void stopInjecting() { setState(); ticksLeft = -1; ticksCost = -1; rfPerTick = -1; markDirty(); } private void setState() { int state = 0; if (ticksLeft == 0) { state = 0; } else if (ticksLeft == -1) { state = 1; } else if (((ticksLeft >> 2) & 1) == 0) { state = 2; } else { state = 3; } int metadata = worldObj.getBlockMetadata(xCoord, yCoord, zCoord); int newmeta = BlockTools.setState(metadata, state); if (newmeta != metadata) { worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, newmeta, 2); } } @Override public int[] getAccessibleSlotsFromSide(int side) { return DimletResearcherContainer.factory.getAccessibleSlots(); } @Override public boolean canInsertItem(int index, ItemStack item, int side) { return DimletResearcherContainer.factory.isInputSlot(index); } @Override public boolean canExtractItem(int index, ItemStack item, int side) { return DimletResearcherContainer.factory.isOutputSlot(index); } @Override public int getSizeInventory() { return inventoryHelper.getCount(); } @Override public ItemStack getStackInSlot(int index) { return inventoryHelper.getStackInSlot(index); } @Override public ItemStack decrStackSize(int index, int amount) { return inventoryHelper.decrStackSize(index, amount); } @Override public ItemStack getStackInSlotOnClosing(int index) { return null; } @Override public void setInventorySlotContents(int index, ItemStack stack) { inventoryHelper.setInventorySlotContents(getInventoryStackLimit(), index, stack); } @Override public String getInventoryName() { return "Editor Inventory"; } @Override public boolean hasCustomInventoryName() { return false; } @Override public int getInventoryStackLimit() { return DimletConfiguration.dimletStackSize; } @Override public boolean isUseableByPlayer(EntityPlayer player) { return canPlayerAccess(player); } @Override public void openInventory() { } @Override public void closeInventory() { } @Override public boolean isItemValidForSlot(int index, ItemStack stack) { return true; } // Request the building percentage from the server. This has to be called on the client side. public void requestBuildingPercentage() { RFToolsMessages.INSTANCE.sendToServer(new PacketRequestIntegerFromServer(xCoord, yCoord, zCoord, CMD_GETEDITING, CLIENTCMD_GETEDITING)); } @Override public Integer executeWithResultInteger(String command, Map<String, Argument> args) { Integer rc = super.executeWithResultInteger(command, args); if (rc != null) { return rc; } if (CMD_GETEDITING.equals(command)) { if (ticksLeft == -1) { return 0; } else { return (ticksCost - ticksLeft) * 100 / ticksCost; } } return null; } @Override public boolean execute(String command, Integer result) { boolean rc = super.execute(command, result); if (rc) { return true; } if (CLIENTCMD_GETEDITING.equals(command)) { editPercentage = result; return true; } return false; } public static int getEditPercentage() { return editPercentage; } @Override public void readFromNBT(NBTTagCompound tagCompound) { super.readFromNBT(tagCompound); } @Override public void readRestorableFromNBT(NBTTagCompound tagCompound) { super.readRestorableFromNBT(tagCompound); readBufferFromNBT(tagCompound); ticksLeft = tagCompound.getInteger("ticksLeft"); ticksCost = tagCompound.getInteger("ticksCost"); rfPerTick = tagCompound.getInteger("rfPerTick"); } private void readBufferFromNBT(NBTTagCompound tagCompound) { NBTTagList bufferTagList = tagCompound.getTagList("Items", Constants.NBT.TAG_COMPOUND); for (int i = 0 ; i < bufferTagList.tagCount() ; i++) { NBTTagCompound nbtTagCompound = bufferTagList.getCompoundTagAt(i); inventoryHelper.setStackInSlot(i, ItemStack.loadItemStackFromNBT(nbtTagCompound)); } } @Override public void writeToNBT(NBTTagCompound tagCompound) { super.writeToNBT(tagCompound); } @Override public void writeRestorableToNBT(NBTTagCompound tagCompound) { super.writeRestorableToNBT(tagCompound); writeBufferToNBT(tagCompound); tagCompound.setInteger("ticksLeft", ticksLeft); tagCompound.setInteger("ticksCost", ticksCost); tagCompound.setInteger("rfPerTick", rfPerTick); } private void writeBufferToNBT(NBTTagCompound tagCompound) { NBTTagList bufferTagList = new NBTTagList(); for (int i = 0 ; i < inventoryHelper.getCount() ; i++) { ItemStack stack = inventoryHelper.getStackInSlot(i); NBTTagCompound nbtTagCompound = new NBTTagCompound(); if (stack != null) { stack.writeToNBT(nbtTagCompound); } bufferTagList.appendTag(nbtTagCompound); } tagCompound.setTag("Items", bufferTagList); } }