package com.arkcraft.module.blocks.common.container; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.inventory.Container; import net.minecraft.inventory.ICrafting; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import com.arkcraft.lib.LogHelper; import com.arkcraft.module.blocks.common.tile.TileInventoryCropPlot; /** * @author wildbill22 */ public class ContainerInventoryCropPlot extends Container { private TileInventoryCropPlot tileInventoryCropPlot; private final int CROP_SLOT_COUNT = 9; public static final int FERTILIZER_SLOT_YPOS = 53; // These store cache values, used by the server to only update the client // side tile entity when values have changed private int[] cachedFields; public ContainerInventoryCropPlot(InventoryPlayer invPlayer, TileInventoryCropPlot tileInventoryCropPlot) { LogHelper.info("TileInventoryCropPlot: constructor called."); this.tileInventoryCropPlot = tileInventoryCropPlot; /* Hotbar inventory */ final int HOTBAR_YPOS = 142; for (int col = 0; col < 9; col++) { addSlotToContainer(new Slot(invPlayer, col, 8 + col * 18, HOTBAR_YPOS)); } /* Player inventory */ final int PLAYER_INVENTORY_YPOS = 84; for (int row = 0; row < 3; row++) { for (int col = 0; col < 9; col++) { int slotIndex = col + row * 9 + 9; addSlotToContainer(new Slot(invPlayer, slotIndex, 8 + col * 18, PLAYER_INVENTORY_YPOS + row * 18)); } } /* Crop inventory */ if (CROP_SLOT_COUNT != tileInventoryCropPlot.getSizeInventory()) { LogHelper .error("Mismatched slot count in container(" + CROP_SLOT_COUNT + ") and CropInventory (" + tileInventoryCropPlot .getSizeInventory() + ")"); } // Water and Seed slot are first two this.addSlotToContainer(new SlotWater(tileInventoryCropPlot, TileInventoryCropPlot.WATER_SLOT, 8, 53)); // Water input slot this.addSlotToContainer(new SlotSeed(tileInventoryCropPlot, TileInventoryCropPlot.SEED_SLOT, 44, 17)); // Seed input slot // Fertilizer slots for (int col = TileInventoryCropPlot.FIRST_FERTILIZER_SLOT; col < CROP_SLOT_COUNT - 1; col++) { addSlotToContainer(new SlotFertilizer(tileInventoryCropPlot, col, 8 + col * 18, FERTILIZER_SLOT_YPOS)); } // Berry output slot (berry is centered in 24 x 24 box (berry is 16 x // 16) this.addSlotToContainer(new Slot(tileInventoryCropPlot, TileInventoryCropPlot.BERRY_SLOT, 104, 17)); } /* Nothing to do, this is a furnace type container */ public void onContainerClosed(EntityPlayer playerIn) { super.onContainerClosed(playerIn); } public ItemStack transferStackInSlot(EntityPlayer playerIn, int sourceSlotIndex) { LogHelper.info("ARKContainerCropPlot: transferStackInSlot called."); Slot sourceSlot = (Slot) inventorySlots.get(sourceSlotIndex); if (sourceSlot == null || !sourceSlot.getHasStack()) { return null; } ItemStack sourceStack = sourceSlot.getStack(); ItemStack copyOfSourceStack = sourceStack.copy(); // Check if the slot clicked is one of the vanilla container slots if (sourceSlotIndex >= 0 && sourceSlotIndex < 36) { if (tileInventoryCropPlot.isItemValidForWaterSlot(sourceStack)) { // This is a vanilla container slot so merge the stack into the // crop plot inventory if (!mergeItemStack( sourceStack, 36, 36 + TileInventoryCropPlot.WATER_SLOT + TileInventoryCropPlot.WATER_SLOTS_COUNT, false)) { return null; } } else if (tileInventoryCropPlot.isItemValidForSeedSlot(sourceStack)) { // This is a vanilla container slot so merge the stack into the // crop plot inventory if (!mergeItemStack( sourceStack, 36, 36 + TileInventoryCropPlot.SEED_SLOT + TileInventoryCropPlot.SEED_SLOTS_COUNT, false)) { return null; } } else if (tileInventoryCropPlot.isItemValidForFertilizerSlot(sourceStack)) { // This is a vanilla container slot so merge the stack into the // crop plot inventory if (!mergeItemStack( sourceStack, 36, 36 + TileInventoryCropPlot.FIRST_FERTILIZER_SLOT + TileInventoryCropPlot.FERTILIZER_SLOTS_COUNT, false)) { return null; } } else { return null; } } // Check if the slot clicked is a crop plot container slot else if (sourceSlotIndex >= 36 && sourceSlotIndex < 36 + CROP_SLOT_COUNT) { // This is a crop plot slot so merge the stack into the players // inventory if (!mergeItemStack(sourceStack, 0, 36, false)) { return null; } } else { LogHelper.error("Invalid slotIndex:" + sourceSlotIndex); return null; } // If stack size == 0 (the entire stack was moved) set slot contents to // null if (sourceStack.stackSize == 0) { sourceSlot.putStack(null); } else { sourceSlot.onSlotChanged(); } sourceSlot.onPickupFromSlot(playerIn, sourceStack); return copyOfSourceStack; } @Override public boolean canInteractWith(EntityPlayer playerIn) { return tileInventoryCropPlot.isUseableByPlayer(playerIn); } // This is where you check if any values have changed and if so send an // update to any clients accessing this container // The container itemstacks are tested in Container.detectAndSendChanges, so // we don't need to do that // We iterate through all of the TileEntity Fields to find any which have // changed, and send them. // You don't have to use fields if you don't wish to; just manually match // the ID in sendProgressBarUpdate with the value in // updateProgressBar() // The progress bar values are restricted to shorts. If you have a larger // value (eg int), it's not a good idea to try and split it // up into two shorts because the progress bar values are sent // independently, and unless you add synchronisation logic at the // receiving side, your int value will be wrong until the second short // arrives. Use a custom packet instead. @Override public void detectAndSendChanges() { super.detectAndSendChanges(); boolean allFieldsHaveChanged = false; boolean fieldHasChanged[] = new boolean[tileInventoryCropPlot.getFieldCount()]; if (cachedFields == null) { cachedFields = new int[tileInventoryCropPlot.getFieldCount()]; allFieldsHaveChanged = true; } for (int i = 0; i < cachedFields.length; ++i) { if (allFieldsHaveChanged || cachedFields[i] != tileInventoryCropPlot.getField(i)) { cachedFields[i] = tileInventoryCropPlot.getField(i); fieldHasChanged[i] = true; } } // go through the list of crafters (players using this container) and // update them if necessary for (int i = 0; i < this.crafters.size(); ++i) { ICrafting icrafting = (ICrafting) this.crafters.get(i); for (int fieldID = 0; fieldID < tileInventoryCropPlot.getFieldCount(); ++fieldID) { if (fieldHasChanged[fieldID]) { // Note that although sendProgressBarUpdate takes 2 ints on // a server these are truncated to shorts icrafting.sendProgressBarUpdate(this, fieldID, cachedFields[fieldID]); } } } } // Called when a progress bar update is received from the server. The two // values (id and data) are the same two // values given to sendProgressBarUpdate. In this case we are using fields // so we just pass them to the tileEntity. @SideOnly(Side.CLIENT) @Override public void updateProgressBar(int id, int data) { tileInventoryCropPlot.setField(id, data); } // SlotFertilizer is a slot for fertilizer items public class SlotFertilizer extends Slot { public SlotFertilizer(IInventory inventoryIn, int index, int xPosition, int yPosition) { super(inventoryIn, index, xPosition, yPosition); } // if this function returns false, the player won't be able to insert // the given item into this slot @Override public boolean isItemValid(ItemStack stack) { return tileInventoryCropPlot.isItemValidForFertilizerSlot(stack); } } // SlotWater is a slot for water public class SlotWater extends Slot { public SlotWater(IInventory inventoryIn, int index, int xPosition, int yPosition) { super(inventoryIn, index, xPosition, yPosition); } // if this function returns false, the player won't be able to insert // the given item into this slot @Override public boolean isItemValid(ItemStack stack) { return tileInventoryCropPlot.isItemValidForWaterSlot(stack); } } // SlotSeed is a slot for seeds public class SlotSeed extends Slot { public SlotSeed(IInventory inventoryIn, int index, int xPosition, int yPosition) { super(inventoryIn, index, xPosition, yPosition); } // if this function returns false, the player won't be able to insert // the given item into this slot @Override public boolean isItemValid(ItemStack stack) { return tileInventoryCropPlot.isItemValidForSeedSlot(stack); } } }