package com.infinityraider.agricraft.container; import com.infinityraider.agricraft.api.seed.AgriSeed; import com.infinityraider.agricraft.apiimpl.SeedRegistry; import com.infinityraider.agricraft.network.MessageContainerSeedStorage; import com.infinityraider.agricraft.tiles.storage.ISeedStorageControllable; import com.infinityraider.agricraft.tiles.storage.ISeedStorageController; import com.infinityraider.agricraft.tiles.storage.SeedStorageSlot; import com.infinityraider.infinitylib.container.ContainerBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.relauncher.Side; import java.util.List; import java.util.Optional; public abstract class ContainerSeedStorageBase<T extends TileEntity> extends ContainerBase<T> { public ContainerSeedStorageBase(T tile, InventoryPlayer inventory, int xOffset, int yOffset) { super(tile, inventory, xOffset, yOffset); } /** * tries to add a stack to the storage, return true on success */ public abstract boolean addSeedToStorage(ItemStack stack); /** * Gets a list off all the different kinds of seeds in the storage */ public abstract List<ItemStack> getSeedEntries(); /** * Gets a list off all the slots corresponding to this seed and meta */ public abstract List<SeedStorageSlot> getSeedSlots(AgriSeed seed); public Optional<ISeedStorageControllable> getControllable(ItemStack stack) { if (this.tile instanceof ISeedStorageController) { return ((ISeedStorageController) this.tile).getControllable(stack); } else if (this.tile instanceof ISeedStorageControllable) { return Optional.of((ISeedStorageControllable) tile); } else { return Optional.empty(); } } /** * returns a list if itemStacks, for each slot. */ @Override public List<ItemStack> getInventory() { return super.getInventory(); } /** * Tries to move an item stack form the correct tile entity to the player's * inventory */ public void moveStackFromTileEntityToPlayer(int slotId, ItemStack stack) { ISeedStorageControllable controllable = this.getControllable(stack).orElse(null); if (controllable == null) { return; } ItemStack stackToMove = controllable.getStackForSlotId(slotId); if (stack == null) { return; } if (stackToMove == null || stackToMove.getItem() == null) { return; } stackToMove.stackSize = stack.stackSize > stackToMove.stackSize ? stackToMove.stackSize : stack.stackSize; stackToMove.setTagCompound(controllable.getStackForSlotId(slotId).getTagCompound()); if (this.mergeItemStack(stackToMove, 0, PLAYER_INVENTORY_SIZE, false)) { if (FMLCommonHandler.instance().getEffectiveSide() == Side.CLIENT) { //this method is only called form the gui client side, so we need to manually tell the server to execute it there new MessageContainerSeedStorage(stack, slotId).sendToServer(); } else { //on the server decrease the size of the stack, where it is synced to the client controllable.decreaseStackSizeInSlot(slotId, stack.stackSize - stackToMove.stackSize); } } } /** * Handles shift clicking in the inventory, return the stack that was * transferred */ @Override public ItemStack transferStackInSlot(EntityPlayer player, int clickedSlot) { ItemStack originalStackInSlot = null; Slot slot = this.inventorySlots.get(clickedSlot); if (slot != null && slot.getHasStack()) { ItemStack notMergedStack = slot.getStack(); originalStackInSlot = notMergedStack.copy(); //try to move item from the player's inventory into the container AgriSeed seed = SeedRegistry.getInstance().valueOf(notMergedStack).orElse(null); if (seed != null && seed.getStat().isAnalyzed()) { ISeedStorageControllable controllable = this.getControllable(notMergedStack).orElse(null); if (controllable != null && controllable.hasLockedSeed()) { ItemStack locked = controllable.getLockedSeed().map(s -> s.toStack()).orElse(null); if (notMergedStack.getItem() != locked.getItem() || notMergedStack.getItemDamage() != locked.getItemDamage()) { return null; } } if (this.addSeedToStorage(notMergedStack)) { notMergedStack.stackSize = 0; } else { return null; } } if (notMergedStack.stackSize == 0) { slot.putStack(null); } else { slot.onSlotChanged(); } if (notMergedStack.stackSize == originalStackInSlot.stackSize) { return null; } slot.onPickupFromSlot(player, notMergedStack); } return originalStackInSlot; } /** * Tries to merge an itemstack into a range of slots, return true if the * stack was (partly) merged */ @Override protected boolean mergeItemStack(ItemStack stack, int startSlot, int endSlot, boolean iterateBackwards) { boolean flag = false; int k = iterateBackwards ? endSlot - 1 : startSlot; Slot currentSlot; ItemStack currentStack; //look for identical stacks to merge with while (stack.stackSize > 0 && (!iterateBackwards && k < endSlot || iterateBackwards && k >= startSlot)) { currentSlot = this.inventorySlots.get(k); currentStack = currentSlot.getStack(); if (currentStack != null && currentStack.getItem() == stack.getItem() && (!stack.getHasSubtypes() || stack.getItemDamage() == currentStack.getItemDamage()) && ItemStack.areItemStackTagsEqual(stack, currentStack)) { int l = currentStack.stackSize + stack.stackSize; //total stacksize is smaller than the limit: merge entire stack into this stack if (l <= stack.getMaxStackSize()) { stack.stackSize = 0; currentStack.stackSize = l; currentSlot.onSlotChanged(); flag = true; } //total stacksize exceeds the limit: merge part of the stack into this stack else if (currentStack.stackSize < stack.getMaxStackSize()) { stack.stackSize -= stack.getMaxStackSize() - currentStack.stackSize; currentStack.stackSize = stack.getMaxStackSize(); currentSlot.onSlotChanged(); flag = true; } } k = iterateBackwards ? k - 1 : k + 1; } //couldn't completely merge stack with an existing slot, find the first empty slot to put the rest of the stack in if (stack.stackSize > 0) { k = iterateBackwards ? endSlot - 1 : startSlot; while (!iterateBackwards && k < endSlot || iterateBackwards && k >= startSlot) { currentSlot = this.inventorySlots.get(k); currentStack = currentSlot.getStack(); if (currentStack == null) { currentSlot.putStack(stack.copy()); currentSlot.onSlotChanged(); stack.stackSize = 0; flag = true; break; } k = iterateBackwards ? k - 1 : k + 1; } } return flag; } }