package slimeknights.tconstruct.tools.common.inventory; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; import net.minecraft.world.WorldServer; import java.util.List; import java.util.Set; import slimeknights.mantle.inventory.BaseContainer; import slimeknights.tconstruct.TConstruct; import slimeknights.tconstruct.common.Sounds; import slimeknights.tconstruct.common.TinkerNetwork; import slimeknights.tconstruct.library.TinkerRegistry; import slimeknights.tconstruct.library.modifiers.TinkerGuiException; import slimeknights.tconstruct.library.tinkering.IModifyable; import slimeknights.tconstruct.library.tinkering.IRepairable; import slimeknights.tconstruct.library.tinkering.PartMaterialType; import slimeknights.tconstruct.library.tinkering.TinkersItem; import slimeknights.tconstruct.library.tools.ToolCore; import slimeknights.tconstruct.library.utils.ToolBuilder; import slimeknights.tconstruct.tools.common.client.GuiToolStation; import slimeknights.tconstruct.tools.common.network.ToolStationSelectionPacket; import slimeknights.tconstruct.tools.common.network.ToolStationTextPacket; import slimeknights.tconstruct.tools.common.tileentity.TileToolStation; // also tool forge public class ContainerToolStation extends ContainerTinkerStation<TileToolStation> { protected SlotToolStationOut out; protected ToolCore selectedTool; // needed for newly opened containers to sync protected int activeSlots; public String toolName; public ContainerToolStation(InventoryPlayer playerInventory, TileToolStation tile) { super(tile); // input slots int i; for(i = 0; i < tile.getSizeInventory(); i++) { addSlotToContainer(new SlotToolStationIn(tile, i, 0, 0, this)); } // output slot out = new SlotToolStationOut(i, 124, 38, this); addSlotToContainer(out); this.addPlayerInventory(playerInventory, 8, 84 + 8); onCraftMatrixChanged(null); } public ItemStack getResult() { return out.getStack(); } @Override protected void syncNewContainer(EntityPlayerMP player) { this.activeSlots = tile.getSizeInventory(); TinkerNetwork.sendTo(new ToolStationSelectionPacket(null, tile.getSizeInventory()), player); } @Override protected void syncWithOtherContainer(BaseContainer<TileToolStation> otherContainer, EntityPlayerMP player) { this.syncWithOtherContainer((ContainerToolStation) otherContainer, player); } protected void syncWithOtherContainer(ContainerToolStation otherContainer, EntityPlayerMP player) { // set same selection as other container this.setToolSelection(otherContainer.selectedTool, otherContainer.activeSlots); this.setToolName(otherContainer.toolName); // also send the data to the player TinkerNetwork.sendTo(new ToolStationSelectionPacket(otherContainer.selectedTool, otherContainer.activeSlots), player); if(otherContainer.toolName != null && !otherContainer.toolName.isEmpty()) { TinkerNetwork.sendTo(new ToolStationTextPacket(otherContainer.toolName), player); } } public void setToolSelection(ToolCore tool, int activeSlots) { if(activeSlots > tile.getSizeInventory()) { activeSlots = tile.getSizeInventory(); } this.activeSlots = activeSlots; this.selectedTool = tool; for(int i = 0; i < tile.getSizeInventory(); i++) { Slot slot = inventorySlots.get(i); // set part info for the slot if(slot instanceof SlotToolStationIn) { SlotToolStationIn slotToolPart = (SlotToolStationIn) slot; slotToolPart.setRestriction(null); // deactivate not needed slots if(i >= activeSlots) { slotToolPart.deactivate(); } // activate the other slots and set toolpart if possible else { slotToolPart.activate(); if(tool != null) { List<PartMaterialType> pmts = tool.getToolBuildComponents(); if(i < pmts.size()) { slotToolPart.setRestriction(pmts.get(i)); } } } if(world.isRemote) { slotToolPart.updateIcon(); } } } } public void setToolName(String name) { this.toolName = name; if(world.isRemote) { GuiScreen screen = Minecraft.getMinecraft().currentScreen; if(screen instanceof GuiToolStation) { ((GuiToolStation) screen).textField.setText(name); } } if(out.getHasStack()) { if(name != null && !name.isEmpty()) { out.inventory.getStackInSlot(0).setStackDisplayName(name); } else { out.inventory.getStackInSlot(0).clearCustomName(); } } } // update crafting - called whenever the content of an input slot changes @Override public void onCraftMatrixChanged(IInventory inventoryIn) { // reset gui state updateGUI(); try { ItemStack result; // 1. try repairing result = repairTool(false); // 2. try swapping tool parts if(result == null) { result = replaceToolParts(false); } // 3. try modifying if(result == null) { result = modifyTool(false); } // 4. try building a new tool if(result == null) { result = buildTool(); } out.inventory.setInventorySlotContents(0, result); updateGUI(); } catch(TinkerGuiException e) { // error ;( out.inventory.setInventorySlotContents(0, null); this.error(e.getMessage()); } // sync output with other open containers on the server if(!this.world.isRemote) { WorldServer server = (WorldServer) this.world; for(EntityPlayer player : server.playerEntities) { if(player.openContainer != this && player.openContainer instanceof ContainerToolStation && this.sameGui((ContainerToolStation) player.openContainer)) { ((ContainerToolStation) player.openContainer).out.inventory.setInventorySlotContents(0, out.getStack()); } } } } // Called when the crafting result is taken out of its slot public void onResultTaken(EntityPlayer playerIn, ItemStack stack) { boolean resultTaken = false; try { resultTaken = repairTool(true) != null || replaceToolParts(true) != null || modifyTool(true) != null; } catch(TinkerGuiException e) { // no error updating needed e.printStackTrace(); } if(resultTaken) { updateSlotsAfterToolAction(); } else { // calculate the result again (serverside) ItemStack tool = buildTool(); // we built a tool if(tool != null) { // remove 1 of each in the slots // it's guaranteed that each slot that has an item has used exactly 1 item to build the tool for(int i = 0; i < tile.getSizeInventory(); i++) { tile.decrStackSize(i, 1); } setToolName(""); } } onCraftMatrixChanged(null); this.playCraftSound(playerIn); } protected void playCraftSound(EntityPlayer player) { Sounds.playSoundForAll(player, Sounds.saw, 0.8f, 0.8f + 0.4f * TConstruct.random.nextFloat()); } private ItemStack repairTool(boolean remove) { ItemStack repairable = inventorySlots.get(0).getStack(); // modifying possible? if(repairable == null || !(repairable.getItem() instanceof IRepairable)) { return null; } return ToolBuilder.tryRepairTool(getInputs(), repairable, remove); } private ItemStack replaceToolParts(boolean remove) throws TinkerGuiException { ItemStack tool = inventorySlots.get(0).getStack(); if(tool == null || !(tool.getItem() instanceof TinkersItem)) { return null; } return ToolBuilder.tryReplaceToolParts(tool, getInputs(), remove); } private ItemStack modifyTool(boolean remove) throws TinkerGuiException { ItemStack modifyable = inventorySlots.get(0).getStack(); // modifying possible? if(modifyable == null || !(modifyable.getItem() instanceof IModifyable)) { return null; } return ToolBuilder.tryModifyTool(getInputs(), modifyable, remove); } private ItemStack buildTool() { ItemStack[] input = new ItemStack[tile.getSizeInventory()]; for(int i = 0; i < input.length; i++) { input[i] = tile.getStackInSlot(i); } return ToolBuilder.tryBuildTool(input, toolName, getBuildableTools()); } protected Set<ToolCore> getBuildableTools() { return TinkerRegistry.getToolStationCrafting(); } /** * Removes the tool in the input slot and fixes all stacks that have stacksize 0 after being used up. */ private void updateSlotsAfterToolAction() { // perfect, items already got removed but we still have to clean up 0-stacks and remove the tool tile.setInventorySlotContents(0, null); // slot where the tool was for(int i = 1; i < tile.getSizeInventory(); i++) { if(tile.getStackInSlot(i) != null && tile.getStackInSlot(i).stackSize == 0) { tile.setInventorySlotContents(i, null); } } } private ItemStack[] getInputs() { ItemStack[] input = new ItemStack[tile.getSizeInventory() - 1]; for(int i = 1; i < tile.getSizeInventory(); i++) { input[i - 1] = tile.getStackInSlot(i); } return input; } @Override public boolean canMergeSlot(ItemStack stack, Slot slot) { return slot != out && super.canMergeSlot(stack, slot); } }