package mods.ocminecart.common.inventory; import cpw.mods.fml.common.FMLCommonHandler; import li.cil.oc.api.API; import li.cil.oc.api.driver.EnvironmentProvider; import li.cil.oc.api.driver.Item; import li.cil.oc.api.driver.item.Container; import li.cil.oc.api.driver.item.Slot; import li.cil.oc.api.machine.MachineHost; import li.cil.oc.api.network.Environment; import li.cil.oc.api.network.ManagedEnvironment; import li.cil.oc.api.network.Message; import li.cil.oc.api.network.Node; import li.cil.oc.common.Tier; import li.cil.oc.common.component.Screen; import mods.ocminecart.OCMinecart; import mods.ocminecart.Settings; import mods.ocminecart.common.driver.CustomDriver; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import java.util.ArrayList; import java.util.Iterator; import java.util.Set; // This Class is just a Java rewrite of li.cil.oc.common.inventory.ComponentInventory and Inventory (Credits to Sangar) public abstract class ComponetInventory implements IInventory, Environment { protected MachineHost host; private ItemStack[] slots; private ArrayList<ManagedEnvironment> updatingCompoents = new ArrayList<ManagedEnvironment>(); private ManagedEnvironment[] components = new ManagedEnvironment[this.getSizeInventory()]; public ComponetInventory(MachineHost host){ this.host = host; this.slots = new ItemStack[this.getSizeInventory()]; } @Override public ItemStack getStackInSlot(int slot) { if(slot<this.getSizeInventory()) return this.slots[slot]; return null; } @Override public ItemStack decrStackSize(int slot, int number) { if(slot>=0 && slot<this.getSizeInventory()){ if(number >= slots[slot].stackSize){ ItemStack get = slots[slot]; slots[slot]=null; this.onItemRemoved(slot, get); return get; } else{ ItemStack ret = slots[slot].splitStack(number); if(slots[slot].stackSize<1){ slots[slot] = null; this.onItemRemoved(slot, ret); } return ret; } } return null; } @Override public ItemStack getStackInSlotOnClosing(int p_70304_1_) { return null; } @Override public void setInventorySlotContents(int slot, ItemStack stack) { if(slot>=0 && slot<this.getSizeInventory()){ if(stack==null && slots[slot]==null) return; if(slots[slot]!=null && stack !=null && slots[slot]==stack) return; ItemStack oldStack = slots[slot]; this.updateSlot(slot, null); if(oldStack!=null) this.onItemRemoved(slot, oldStack); if(stack!=null && stack.stackSize>=1){ if(stack.stackSize>=this.getInventoryStackLimit()){ stack.stackSize=this.getInventoryStackLimit(); } this.updateSlot(slot, stack); } if(slots[slot]!=null){ this.onItemAdded(slot, stack); } this.markDirty(); } } @Override public String getInventoryName() { return "Component Inventory"; } @Override public int getInventoryStackLimit() { return 1; } @Override public void markDirty() {} @Override public boolean isUseableByPlayer(EntityPlayer player) { return true; } public void updateSlot(int slot, ItemStack stack){ slots[slot] = stack; } @Override public void openInventory() {} @Override public void closeInventory() {} @Override public boolean isItemValidForSlot(int slot, ItemStack stack) { Item driver = CustomDriver.driverFor(stack,host.getClass()); if(driver!=null && (driver.slot(stack)==this.getSlotType(slot) || this.getSlotType(slot) == Slot.Any) && driver.tier(stack) <= this.getSlotTier(slot)) return true; return false; } @Override public boolean hasCustomInventoryName() { return false; } public String getSlotType(int slot){ if(slot>=20 && slot<=22){ Item drv = CustomDriver.driverFor(this.getContainer(slot-20)); if(drv instanceof Container){ return ((Container)drv).providedSlot(this.getContainer(slot-20)); } else return Slot.None; } return Slot.Any; } public int getSlotTier(int slot){ if(slot>=20 && slot<=22){ Item drv = CustomDriver.driverFor(this.getContainer(slot-20)); if(drv instanceof Container){ return ((Container)drv).providedTier(this.getContainer(slot-20)); } else return Tier.None(); } return Tier.Any(); } public Node node(){ return this.host.machine().node(); } public void updateComponents() { if(!this.updatingCompoents.isEmpty()){ Iterator<ManagedEnvironment> list = this.updatingCompoents.iterator(); while(list.hasNext()){ list.next().update(); } } } public ManagedEnvironment getSlotComponent(int slot) { if(slot < this.getSizeInventory()) return this.components[slot]; return null; } public void connectComponents(){ for(int slot=0;slot<this.getSizeInventory();slot+=1){ ItemStack stack = this.getStackInSlot(slot); if(stack!=null && this.components[slot]==null && this.isComponentSlot(slot, stack)){ Item drv = CustomDriver.driverFor(stack,host.getClass()); if(drv!=null){ ManagedEnvironment env = drv.createEnvironment(stack, host); if(env!=null){ try{ env.load(dataTag(drv,stack)); } catch(Throwable e){ OCMinecart.logger.warn("An item component of type"+env.getClass().getName()+" (provided by driver "+drv.getClass().getName()+") threw an error while loading.",e); } this.components[slot] = env; if(env.canUpdate() && !this.updatingCompoents.contains(env)){ this.updatingCompoents.add(env); } } } } } API.network.joinNewNetwork(this.node()); for(int i=0;i<this.components.length;i+=1){ if(this.components[i]!=null && this.components[i].node()!=null){ this.connectItemNode(this.components[i].node()); } } } public void disconnectComponents(){ for(int i=0;i<this.components.length;i+=1){ if(this.components[i]!=null) this.components[i].node().remove(); } } public void connectItemNode(Node node){ if(this.node()!=null && node!=null && this.node().network()!=null){ this.node().connect(node); } } public void removeTagsForDrop(){ for(int i=0;i<this.getSizeInventory();i+=1){ if(this.getStackInSlot(i)!=null){ Item drv = CustomDriver.driverFor(this.getStackInSlot(i), this.host.getClass()); //Unfortunately it's not possible to make 'instanceof' with a Scala class and I'am lazy. So I check the Environment class. if((drv instanceof EnvironmentProvider) && ((EnvironmentProvider)drv).getEnvironment(this.getStackInSlot(i)) == Screen.class){ NBTTagCompound tag = this.dataTag(drv, this.getStackInSlot(i)); Set<String> tags = tag.func_150296_c(); String[] list = tags.toArray(new String[tags.size()]); for(int j=0; j<list.length; j+=1){ tag.removeTag(list[j]); } } } } } synchronized protected void onItemAdded(int slot, ItemStack stack){ Item drv = CustomDriver.driverFor(stack,host.getClass()); if(drv!=null){ ManagedEnvironment env = drv.createEnvironment(stack, host); if(env!=null){ try{ env.load(this.dataTag(drv, stack)); } catch(Throwable e){ OCMinecart.logger.warn("An item component of type"+env.getClass().getName()+" (provided by driver "+drv.getClass().getName()+") threw an error while loading.",e); } this.components[slot] = env; this.connectItemNode(env.node()); if(env.canUpdate() && !this.updatingCompoents.contains(env)){ this.updatingCompoents.add(env); } this.save(env, drv, stack); } } } synchronized protected void onItemRemoved(int slot, ItemStack stack){ if(this.components[slot]!=null && FMLCommonHandler.instance().getEffectiveSide().isServer()){ ManagedEnvironment component = this.components[slot]; this.components[slot]=null; if(this.updatingCompoents!=null && this.updatingCompoents.contains(component)) this.updatingCompoents.remove(component); component.node().remove(); this.save(component, CustomDriver.driverFor(stack), stack); component.node().remove(); } } private NBTTagCompound dataTag(Item driver, ItemStack stack){ NBTTagCompound tag = null; if(driver!=null) driver.dataTag(stack); if(tag==null){ if (!stack.hasTagCompound()) { stack.setTagCompound(new NBTTagCompound()); } NBTTagCompound nbt = stack.getTagCompound(); if (!nbt.hasKey(Settings.OC_Namespace + "data")) { nbt.setTag(Settings.OC_Namespace + "data", new NBTTagCompound()); } tag = nbt.getCompoundTag(Settings.OC_Namespace + "data"); } return tag; } public boolean isComponentSlot(int slot, ItemStack stack){return true;} public void save(ManagedEnvironment component, Item driver, ItemStack stack){ try{ NBTTagCompound tag = this.dataTag(driver, stack); Set<String> tags = tag.func_150296_c(); String[] list = tags.toArray(new String[tags.size()]); for(int i=0; i<list.length; i+=1){ tag.removeTag(list[i]); } component.save(tag); } catch(Throwable e){ OCMinecart.logger.warn("An item component of type "+component.getClass().getName()+" (provided by driver "+driver.getClass().getName()+") threw an error while loading.",e); } } public NBTTagList writeNTB(){ NBTTagList nbt = new NBTTagList(); for(byte slot=0;slot < this.getSizeInventory(); slot+=1){ NBTTagCompound invslot = new NBTTagCompound(); NBTTagCompound item = new NBTTagCompound(); invslot.setByte("slot", slot); if(this.getStackInSlot(slot)!=null){ this.getStackInSlot(slot).writeToNBT(item); invslot.setTag("item", item); } nbt.appendTag(invslot); } return nbt; } public void readNBT(NBTTagList nbt){ for(int i=0;i < nbt.tagCount(); i+=1){ NBTTagCompound invslot = nbt.getCompoundTagAt(i); ItemStack stack = ItemStack.loadItemStackFromNBT(invslot.getCompoundTag("item")); byte slot = invslot.getByte("slot"); if(slot>=0 && slot<this.getSizeInventory()) this.updateSlot(slot, stack); } } public Iterable<ManagedEnvironment> getComponents(){ ArrayList<ManagedEnvironment> list = new ArrayList<ManagedEnvironment>(); for(int i=0;i<this.getSizeInventory();i+=1){ if(this.components[i]!=null){ list.add(this.components[i]); } } return list; } public void saveComponents() { for (int slot=0; slot< this.getSizeInventory(); slot+=1) { ItemStack stack = this.getStackInSlot(slot); if (stack != null && this.components[slot]!=null) { this.save(this.components[slot], CustomDriver.driverFor(stack,host.getClass()), stack); } } } public ItemStack getContainer(int index){ if(index >= 0 && index <= 2 && this.getStackInSlot(index)!=null){ Item it = CustomDriver.driverFor(this.getStackInSlot(index)); if(it instanceof Container) return this.getStackInSlot(index); } return null; } @Override public void onConnect(Node node) {} @Override public void onDisconnect(Node node) {} @Override public void onMessage(Message message) {} }