package mcjty.rftools.blocks.dimletconstruction;
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.dimlets.DimletSetup;
import mcjty.rftools.items.dimlets.*;
import mcjty.rftools.items.dimlets.types.DimletCraftingTools;
import mcjty.rftools.items.dimlets.types.IDimletType;
import mcjty.rftools.network.RFToolsMessages;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.inventory.ISidedInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraftforge.common.util.Constants;
import net.minecraftforge.common.util.ForgeDirection;
import java.util.Map;
public class DimletWorkbenchTileEntity extends GenericEnergyReceiverTileEntity implements ISidedInventory {
public static final String CMD_STARTEXTRACT = "startExtract";
public static final String CMD_GETEXTRACTING = "getExtracting";
public static final String CLIENTCMD_GETEXTRACTING = "getExtracting";
public static final String CMD_SETAUTOEXTRACT = "setAutoExtract";
private InventoryHelper inventoryHelper = new InventoryHelper(this, DimletWorkbenchContainer.factory, DimletWorkbenchContainer.SIZE_BUFFER + 9);
private int extracting = 0;
private DimletKey idToExtract = null;
private int inhibitCrafting = 0;
private boolean autoExtract = false;
public int getExtracting() {
return extracting;
}
public boolean isAutoExtract() {return autoExtract;
}
public DimletWorkbenchTileEntity() {
super(DimletConstructionConfiguration.WORKBENCH_MAXENERGY, DimletConstructionConfiguration.WORKBENCH_RECEIVEPERTICK);
}
@Override
public int[] getAccessibleSlotsFromSide(int side) {
return DimletWorkbenchContainer.factory.getAccessibleSlots();
}
@Override
public boolean canInsertItem(int index, ItemStack item, int side) {
return index == DimletWorkbenchContainer.SLOT_INPUT;
}
@Override
public boolean canExtractItem(int index, ItemStack item, int side) {
return index == DimletWorkbenchContainer.SLOT_OUTPUT;
}
@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) {
ItemStack s = inventoryHelper.decrStackSize(index, amount);
checkCrafting();
return s;
}
@Override
public ItemStack getStackInSlotOnClosing(int index) {
return null;
}
@Override
public void setInventorySlotContents(int index, ItemStack stack) {
inventoryHelper.setInventorySlotContents(getInventoryStackLimit(), index, stack);
if (index < DimletWorkbenchContainer.SLOT_BASE || index > DimletWorkbenchContainer.SLOT_ESSENCE) {
return;
}
checkCrafting();
}
private void checkCrafting() {
if (inhibitCrafting == 0) {
if (!checkDimletCrafting()) {
if (inventoryHelper.getStackInSlot(DimletWorkbenchContainer.SLOT_OUTPUT) != null) {
inventoryHelper.setInventorySlotContents(0, DimletWorkbenchContainer.SLOT_OUTPUT, null);
}
}
}
}
@Override
public String getInventoryName() {
return "Workbench Inventory";
}
@Override
public boolean hasCustomInventoryName() {
return false;
}
@Override
public int getInventoryStackLimit() {
return 64;
}
@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;
}
@Override
protected void checkStateServer() {
if (extracting > 0) {
extracting--;
if (extracting == 0) {
if (!doExtract()) {
// We failed due to not enough power. Try again later.
extracting = 10;
}
}
markDirty();
} else if (autoExtract) {
startExtracting();
}
}
private boolean checkDimletCrafting() {
ItemStack stackBase = inventoryHelper.getStackInSlot(DimletWorkbenchContainer.SLOT_BASE);
if (stackBase == null) {
return false;
}
ItemStack stackController = inventoryHelper.getStackInSlot(DimletWorkbenchContainer.SLOT_CONTROLLER);
if (stackController == null) {
return false;
}
ItemStack stackTypeController = inventoryHelper.getStackInSlot(DimletWorkbenchContainer.SLOT_TYPE_CONTROLLER);
if (stackTypeController == null) {
return false;
}
ItemStack stackMemory = inventoryHelper.getStackInSlot(DimletWorkbenchContainer.SLOT_MEMORY);
if (stackMemory == null) {
return false;
}
ItemStack stackEnergy = inventoryHelper.getStackInSlot(DimletWorkbenchContainer.SLOT_ENERGY);
if (stackEnergy == null) {
return false;
}
ItemStack stackEssence = inventoryHelper.getStackInSlot(DimletWorkbenchContainer.SLOT_ESSENCE);
if (stackEssence == null) {
return false;
}
DimletType type = DimletType.values()[stackTypeController.getItemDamage()];
IDimletType itype = type.dimletType;
DimletKey key = itype.attemptDimletCrafting(stackController, stackMemory, stackEnergy, stackEssence);
if (key != null) {
inventoryHelper.setInventorySlotContents(1, DimletWorkbenchContainer.SLOT_OUTPUT, KnownDimletConfiguration.makeKnownDimlet(key, worldObj));
return true;
}
return false;
}
public void craftDimlet() {
inhibitCrafting++;
inventoryHelper.decrStackSize(DimletWorkbenchContainer.SLOT_BASE, 1);
inventoryHelper.decrStackSize(DimletWorkbenchContainer.SLOT_CONTROLLER, 1);
inventoryHelper.decrStackSize(DimletWorkbenchContainer.SLOT_TYPE_CONTROLLER, 1);
inventoryHelper.decrStackSize(DimletWorkbenchContainer.SLOT_ENERGY, 1);
inventoryHelper.decrStackSize(DimletWorkbenchContainer.SLOT_MEMORY, 1);
inventoryHelper.decrStackSize(DimletWorkbenchContainer.SLOT_ESSENCE, 1);
inhibitCrafting--;
checkCrafting();
}
private void startExtracting() {
if (extracting > 0) {
// Already extracting
return;
}
ItemStack stack = inventoryHelper.getStackInSlot(DimletWorkbenchContainer.SLOT_INPUT);
if (stack != null) {
if (DimletSetup.knownDimlet.equals(stack.getItem())) {
DimletKey key = KnownDimletConfiguration.getDimletKey(stack, worldObj);
DimletEntry entry = KnownDimletConfiguration.getEntry(key);
if (entry != null) {
if (!KnownDimletConfiguration.craftableDimlets.contains(key)) {
extracting = 64;
idToExtract = key;
inventoryHelper.decrStackSize(DimletWorkbenchContainer.SLOT_INPUT, 1);
markDirty();
}
}
}
}
}
private boolean doExtract() {
int rf = DimletConstructionConfiguration.rfExtractOperation;
if (getEnergyStored(ForgeDirection.DOWN) < rf) {
// Not enough energy.
return false;
}
consumeEnergy(rf);
float factor = getInfusedFactor();
DimletEntry entry = KnownDimletConfiguration.getEntry(idToExtract);
if (extractSuccess(factor)) {
mergeItemOrThrowInWorld(new ItemStack(DimletConstructionSetup.dimletBaseItem));
}
int rarity = entry.getRarity();
if (extractSuccess(factor)) {
mergeItemOrThrowInWorld(new ItemStack(DimletConstructionSetup.dimletTypeControllerItem, 1, entry.getKey().getType().ordinal()));
}
int level = DimletCraftingTools.calculateItemLevelFromRarity(rarity);
if (extractSuccess(factor)) {
mergeItemOrThrowInWorld(new ItemStack(DimletConstructionSetup.dimletMemoryUnitItem, 1, level));
} else {
factor += 0.1f; // If this failed we increase our chances a bit
}
if (extractSuccess(factor)) {
mergeItemOrThrowInWorld(new ItemStack(DimletConstructionSetup.dimletEnergyModuleItem, 1, level));
} else {
factor += 0.1f; // If this failed we increase our chances a bit
}
if (extractSuccess(factor)) {
mergeItemOrThrowInWorld(new ItemStack(DimletConstructionSetup.dimletControlCircuitItem, 1, rarity));
}
idToExtract = null;
markDirty();
return true;
}
private boolean extractSuccess(float factor) {
return worldObj.rand.nextFloat() <= (0.61f + factor * 0.4f);
}
private void mergeItemOrThrowInWorld(ItemStack stack) {
int notInserted = inventoryHelper.mergeItemStack(this, false, stack, DimletWorkbenchContainer.SLOT_BUFFER, DimletWorkbenchContainer.SLOT_BUFFER + DimletWorkbenchContainer.SIZE_BUFFER, null);
if (notInserted > 0) {
BlockTools.spawnItemStack(worldObj, xCoord, yCoord, zCoord, stack);
}
}
@Override
public void readFromNBT(NBTTagCompound tagCompound) {
super.readFromNBT(tagCompound);
}
@Override
public void readRestorableFromNBT(NBTTagCompound tagCompound) {
super.readRestorableFromNBT(tagCompound);
readBufferFromNBT(tagCompound);
extracting = tagCompound.getInteger("extracting");
idToExtract = null;
if (tagCompound.hasKey("extDkey")) {
DimletType type = DimletType.getTypeByOpcode(tagCompound.getString("extKtype"));
idToExtract = new DimletKey(type, tagCompound.getString("extDkey"));
} else {
if (tagCompound.hasKey("idToExtract")) {
// Compatibility with old system.
int id = tagCompound.getInteger("idToExtract");
if (id != -1) {
DimletMapping mapping = DimletMapping.getDimletMapping(worldObj);
idToExtract = mapping.getKey(id);
}
}
}
autoExtract = tagCompound.getBoolean("autoExtract");
}
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("extracting", extracting);
if (idToExtract != null) {
tagCompound.setString("extKtype", idToExtract.getType().dimletType.getOpcode());
tagCompound.setString("extDkey", idToExtract.getName());
}
tagCompound.setBoolean("autoExtract", autoExtract);
}
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);
}
@Override
public boolean execute(EntityPlayerMP playerMP, String command, Map<String, Argument> args) {
boolean rc = super.execute(playerMP, command, args);
if (rc) {
return true;
}
if (CMD_STARTEXTRACT.equals(command)) {
startExtracting();
return true;
} else if (CMD_SETAUTOEXTRACT.equals(command)) {
autoExtract = args.get("auto").getBoolean();
markDirty();
return true;
}
return false;
}
// Request the extracting amount from the server. This has to be called on the client side.
public void requestExtractingFromServer() {
RFToolsMessages.INSTANCE.sendToServer(new PacketRequestIntegerFromServer(xCoord, yCoord, zCoord,
CMD_GETEXTRACTING,
CLIENTCMD_GETEXTRACTING));
}
@Override
public Integer executeWithResultInteger(String command, Map<String, Argument> args) {
Integer rc = super.executeWithResultInteger(command, args);
if (rc != null) {
return rc;
}
if (CMD_GETEXTRACTING.equals(command)) {
return extracting;
}
return null;
}
@Override
public boolean execute(String command, Integer result) {
boolean rc = super.execute(command, result);
if (rc) {
return true;
}
if (CLIENTCMD_GETEXTRACTING.equals(command)) {
extracting = result;
return true;
}
return false;
}
}