Update TileAutoWorkbench.java

This commit is contained in:
Alex 2013-04-26 21:03:53 -03:00
parent bda4de6024
commit 903dd33568

View file

@ -9,393 +9,235 @@
package buildcraft.factory;
import java.util.LinkedList;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.InventoryCraftResult;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.item.crafting.CraftingManager;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.ForgeDirection;
import net.minecraftforge.common.ISidedInventory;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent;
import buildcraft.api.core.Position;
import buildcraft.api.inventory.ISpecialInventory;
import buildcraft.core.inventory.TransactorRoundRobin;
import buildcraft.core.proxy.CoreProxy;
import buildcraft.core.utils.CraftingHelper;
import buildcraft.core.utils.SidedInventoryAdapter;
import buildcraft.core.utils.Utils;
public class TileAutoWorkbench extends TileEntity implements ISpecialInventory {
private ItemStack stackList[] = new ItemStack[9];
private IRecipe currentRecipe = null;
class LocalInventoryCrafting extends InventoryCrafting {
public LocalInventoryCrafting() {
super(new Container() {
@SuppressWarnings("all")
public boolean isUsableByPlayer(EntityPlayer entityplayer) {
return false;
}
@SuppressWarnings("all")
public boolean canInteractWith(EntityPlayer entityplayer) {
// TODO Auto-generated method stub
return false;
}
}, 3, 3);
// TODO Auto-generated constructor stub
private IInventory craftResult = new InventoryCraftResult();
private InventoryCrafting crafting = new InventoryCrafting(new Container() {
@Override
public boolean canInteractWith(EntityPlayer entityplayer) {
return false;
}
@Override
public void onCraftMatrixChanged(IInventory inventory) {}
}, 3, 3);
@Override
public void onInventoryChanged() {
craftResult.setInventorySlotContents(0, CraftingManager.getInstance().findMatchingRecipe(crafting, this.worldObj));
super.onInventoryChanged();
}
public IRecipe getCurrentRecipe() {
return currentRecipe ;
public IInventory getCraftResult() {
return this.craftResult;
}
@Override
public int getSizeInventory() {
return stackList.length;
return this.crafting.getSizeInventory();
}
@Override
public ItemStack getStackInSlot(int i) {
return stackList[i];
public ItemStack getStackInSlot(int slot) {
return this.crafting.getStackInSlot(slot);
}
@Override
public ItemStack decrStackSize(int slotId, int count) {
if (stackList[slotId] == null)
return null;
if (stackList[slotId].stackSize > count)
return stackList[slotId].splitStack(count);
ItemStack stack = stackList[slotId];
stackList[slotId] = null;
return stack;
public ItemStack decrStackSize(int slot, int amount) {
ItemStack item = this.crafting.decrStackSize(slot, amount);
this.onInventoryChanged();
return item;
}
@Override
public void setInventorySlotContents(int i, ItemStack itemstack) {
stackList[i] = itemstack;
public void setInventorySlotContents(int slot, ItemStack stack) {
this.crafting.setInventorySlotContents(slot, stack);
this.onInventoryChanged();
}
@Override
public ItemStack getStackInSlotOnClosing(int slot) {
if (this.stackList[slot] == null)
return null;
ItemStack stackToTake = this.stackList[slot];
this.stackList[slot] = null;
return stackToTake;
return this.crafting.getStackInSlotOnClosing(slot);
}
@Override
public String getInvName() {
return "";
return "AutoCrafting";
}
@Override
public int getInventoryStackLimit() {
return 64;
}
@Override
public boolean isUseableByPlayer(EntityPlayer entityplayer) {
return worldObj.getBlockTileEntity(xCoord, yCoord, zCoord) == this;
public boolean isUseableByPlayer(EntityPlayer player) {
return this.worldObj.getBlockTileEntity(this.xCoord, this.yCoord, this.zCoord) == this;
}
@Override
public void readFromNBT(NBTTagCompound nbttagcompound) {
super.readFromNBT(nbttagcompound);
Utils.readStacksFromNBT(nbttagcompound, "stackList", stackList);
}
@Override
public void writeToNBT(NBTTagCompound nbttagcompound) {
super.writeToNBT(nbttagcompound);
Utils.writeStacksToNBT(nbttagcompound, "stackList", stackList);
}
class StackPointer {
IInventory inventory;
int index;
ItemStack item;
}
public ItemStack findRecipe() {
InventoryCrafting craftMatrix = new LocalInventoryCrafting();
for (int i = 0; i < getSizeInventory(); ++i) {
ItemStack stack = getStackInSlot(i);
craftMatrix.setInventorySlotContents(i, stack);
}
if(this.currentRecipe == null || !this.currentRecipe.matches(craftMatrix, worldObj))
currentRecipe = CraftingHelper.findMatchingRecipe(craftMatrix, worldObj);
if(currentRecipe!=null)
return currentRecipe.getCraftingResult(craftMatrix);
return null;
}
public ItemStack extractItem(boolean doRemove, boolean removeRecipe) {
InventoryCrafting craftMatrix = new LocalInventoryCrafting();
LinkedList<StackPointer> pointerList = new LinkedList<StackPointer>();
int itemsToLeave = (removeRecipe ? 0 : 1);
for (int i = 0; i < getSizeInventory(); ++i) {
ItemStack stack = getStackInSlot(i);
if (stack != null) {
if (stack.stackSize <= itemsToLeave) {
StackPointer pointer = getNearbyItem(stack);
if (pointer == null) {
resetPointers(pointerList);
return null;
} else {
pointerList.add(pointer);
}
} else {
StackPointer pointer = new StackPointer();
pointer.inventory = this;
pointer.item = this.decrStackSize(i, 1);
pointer.index = i;
stack = pointer.item;
pointerList.add(pointer);
public void refilFromNeibour(){
//pre-compute to see if there are enough items
{
ItemStack[] required = new ItemStack[this.getSizeInventory()];
for (int slot = 0; slot < this.getSizeInventory(); slot++){
ItemStack item = this.getStackInSlot(slot);
if (item != null && item.stackSize == 1){
required[slot] = item.copy();
}
}
craftMatrix.setInventorySlotContents(i, stack);
}
if(this.currentRecipe == null || !this.currentRecipe.matches(craftMatrix, worldObj))
currentRecipe = buildcraft.core.utils.CraftingHelper.findMatchingRecipe(craftMatrix, worldObj);
ItemStack resultStack = null;
if(currentRecipe != null) {
resultStack = currentRecipe.getCraftingResult(craftMatrix);
}
if (resultStack == null || !doRemove) {
resetPointers(pointerList);
} else {
for (StackPointer p : pointerList) {
// replace with the container where appropriate
if (p.item.getItem().getContainerItem() != null) {
ItemStack newStack = p.item.getItem().getContainerItemStack(p.item);
if (p.item.isItemStackDamageable()) {
if (newStack.getItemDamage() >= p.item.getMaxDamage()) {
MinecraftForge.EVENT_BUS.post(new PlayerDestroyItemEvent(CoreProxy.proxy.getBuildCraftPlayer(worldObj, xCoord, yCoord, zCoord),
newStack));
this.worldObj.playSoundAtEntity(CoreProxy.proxy.getBuildCraftPlayer(worldObj, xCoord, yCoord, zCoord), "random.break", 0.8F,
0.8F + this.worldObj.rand.nextFloat() * 0.4F);
newStack = null;
}
}
p.inventory.setInventorySlotContents(p.index, newStack);
}
}
}
return resultStack;
}
public void resetPointers(LinkedList<StackPointer> pointers) {
for (StackPointer p : pointers) {
ItemStack item = p.inventory.getStackInSlot(p.index);
if (item == null) {
p.inventory.setInventorySlotContents(p.index, p.item);
} else {
p.inventory.getStackInSlot(p.index).stackSize++;
}
}
}
public StackPointer getNearbyItem(ItemStack stack) {
StackPointer pointer = null;
if (pointer == null) {
pointer = getNearbyItemFromOrientation(stack, ForgeDirection.WEST);
}
if (pointer == null) {
pointer = getNearbyItemFromOrientation(stack, ForgeDirection.EAST);
}
if (pointer == null) {
pointer = getNearbyItemFromOrientation(stack, ForgeDirection.DOWN);
}
if (pointer == null) {
pointer = getNearbyItemFromOrientation(stack, ForgeDirection.UP);
}
if (pointer == null) {
pointer = getNearbyItemFromOrientation(stack, ForgeDirection.NORTH);
}
if (pointer == null) {
pointer = getNearbyItemFromOrientation(stack, ForgeDirection.SOUTH);
}
if (pointer == null) {
pointer = getNearbyItemFromOrientation(stack, ForgeDirection.UNKNOWN);
}
return pointer;
}
public StackPointer getNearbyItemFromOrientation(ItemStack itemStack, ForgeDirection direction) {
TileEntity tile = worldObj.getBlockTileEntity(xCoord + direction.offsetX, yCoord + direction.offsetY, zCoord + direction.offsetZ);
if (tile instanceof ISpecialInventory) {
// Don't get stuff out of ISpecialInventory for now / we wouldn't
// know how to put it back... And it's not clear if we want to
// have workbenches automatically getting things from one another.
return null;
}
IInventory inventory = null;
if (tile instanceof ISidedInventory){
inventory = new SidedInventoryAdapter((ISidedInventory) tile, direction.getOpposite());
} else if (tile instanceof IInventory) {
inventory = Utils.getInventory((IInventory) tile);
}
if (inventory == null) return null;
for (int j = 0; j < inventory.getSizeInventory(); ++j) {
ItemStack stack = inventory.getStackInSlot(j);
if (stack != null) {
if (stack.stackSize > 0) {
if (stack.itemID == itemStack.itemID) {
if (!stack.isItemStackDamageable()) {
if (stack.itemID == itemStack.itemID && stack.getItemDamage() == itemStack.getItemDamage()) {
inventory.decrStackSize(j, 1);
StackPointer result = new StackPointer();
result.inventory = inventory;
result.index = j;
result.item = stack;
return result;
}
} else {
if (stack.itemID == itemStack.itemID) {
inventory.decrStackSize(j, 1);
StackPointer result = new StackPointer();
result.inventory = inventory;
result.index = j;
result.item = stack;
return result;
for (ForgeDirection side : ForgeDirection.VALID_DIRECTIONS){
TileEntity tileEntity = this.worldObj.getBlockTileEntity(side.offsetX + this.xCoord, side.offsetY + this.yCoord, side.offsetZ + this.zCoord);
if (tileEntity instanceof IInventory){
IInventory inventory = (IInventory) tileEntity;
ItemStack remaining = null;
for (int slot = 0; slot < inventory.getSizeInventory(); slot++){
ItemStack item = inventory.getStackInSlot(slot);
if (item != null){
remaining = item.copy();
for (int index = 0; index < required.length; index++){
if (required[index] != null && item.isItemEqual(required[index])){
required[index] = null;
if (remaining.stackSize == 1){
remaining = null;
break;
}else{
remaining.stackSize--;
}
}
}
}
}
}
}
for (int index = 0; index < required.length; index++){
if (required[index] != null) return;
}
}
return null;
}
public StackPointer getNearbyItem(int itemId, int damage) {
StackPointer pointer = null;
pointer = getNearbyItemFromOrientation(itemId, damage, ForgeDirection.WEST);
if (pointer == null) {
pointer = getNearbyItemFromOrientation(itemId, damage, ForgeDirection.EAST);
}
if (pointer == null) {
pointer = getNearbyItemFromOrientation(itemId, damage, ForgeDirection.DOWN);
}
if (pointer == null) {
pointer = getNearbyItemFromOrientation(itemId, damage, ForgeDirection.UP);
}
if (pointer == null) {
pointer = getNearbyItemFromOrientation(itemId, damage, ForgeDirection.NORTH);
}
if (pointer == null) {
pointer = getNearbyItemFromOrientation(itemId, damage, ForgeDirection.SOUTH);
}
return pointer;
}
public StackPointer getNearbyItemFromOrientation(int itemId, int damage, ForgeDirection orientation) {
Position p = new Position(xCoord, yCoord, zCoord, orientation);
p.moveForwards(1.0);
TileEntity tile = worldObj.getBlockTileEntity((int) p.x, (int) p.y, (int) p.z);
if (tile instanceof ISpecialInventory) {
// Don't get stuff out of ISpecialInventory for now / we wouldn't
// know how to put it back... And it's not clear if we want to
// have workbenches automatically getting things from one another.
} else if (tile instanceof IInventory) {
IInventory inventory = Utils.getInventory((IInventory) tile);
for (int j = 0; j < inventory.getSizeInventory(); ++j) {
ItemStack stack = inventory.getStackInSlot(j);
if (stack != null && stack.stackSize > 0 && stack.itemID == itemId && stack.getItemDamage() == damage) {
inventory.decrStackSize(j, 1);
StackPointer result = new StackPointer();
result.inventory = inventory;
result.index = j;
result.item = stack;
return result;
for (ForgeDirection side : ForgeDirection.VALID_DIRECTIONS){
TileEntity tileEntity = this.worldObj.getBlockTileEntity(side.offsetX + this.xCoord, side.offsetY + this.yCoord, side.offsetZ + this.zCoord);
/*
* FIXME: make this support ISidedInvontory. That means forge's and vanilla's implementation
* perhaps have this work with ISpecialInvenotry?
*/
if (tileEntity instanceof IInventory){
IInventory inventory = (IInventory) tileEntity;
for (int slot = 0; slot < inventory.getSizeInventory(); slot++){
ItemStack item = inventory.getStackInSlot(slot);
if (item != null){
boolean refilAll = false;
for (int slot1 = 0; slot1 < this.getSizeInventory(); slot1++){
ItemStack item1 = this.getStackInSlot(slot1);
if (item1 != null && item1.stackSize == 1 && item.isItemEqual(item1)){
item1.stackSize++;
inventory.decrStackSize(slot, 1);
if (slot1 == this.getSizeInventory() - 1) refilAll = true;
}else{
refilAll = false;
}
}
if (refilAll) return;
}
}
}
}
}
private void craft(){
for (int slot = 0; slot < this.getSizeInventory(); slot++){
ItemStack item = this.getStackInSlot(slot);
if (item != null){
this.decrStackSize(slot, 1);
if (item.getItem().hasContainerItem()){
ItemStack item2 = item.getItem().getContainerItemStack(item);
return null;
if (item2.isItemStackDamageable() && item2.getItemDamage() > item2.getMaxDamage()){
this.worldObj.playSoundAtEntity(CoreProxy.proxy.getBuildCraftPlayer(worldObj, xCoord, yCoord, zCoord), "random.break", 0.8F,
0.8F + this.worldObj.rand.nextFloat() * 0.4F);
item2 = null;
}
this.crafting.setInventorySlotContents(slot, item2);
}
}
}
}
private boolean canCraft() {
if (this.craftResult.getStackInSlot(0) == null){
return false;
}
for (int slot = 0; slot < this.getSizeInventory(); slot++){
ItemStack stack = this.getStackInSlot(slot);
if (stack != null && stack.stackSize <= 1){
if (!stack.getItem().hasContainerItem()){
ItemStack item = stack.getItem().getContainerItemStack(stack);
if (item == null || item.stackSize <= 0){
return false;
}
}
}
}
return true;
}
@Override
public void openChest() {
public void readFromNBT(NBTTagCompound nbt) {
super.readFromNBT(nbt);
Utils.readStacksFromNBT(nbt, "stackList", this);
this.onInventoryChanged();
}
@Override
public void closeChest() {
public void writeToNBT(NBTTagCompound nbt) {
super.writeToNBT(nbt);
Utils.writeStacksToNBT(nbt, "stackList", this);
}
/* ISPECIALINVENTORY */
public void openChest() {}
public void closeChest() {}
@Override
public int addItem(ItemStack stack, boolean doAdd, ForgeDirection from) {
return new TransactorRoundRobin(this).add(stack, from, doAdd).stackSize;
@ -403,21 +245,34 @@ public class TileAutoWorkbench extends TileEntity implements ISpecialInventory {
@Override
public ItemStack[] extractItem(boolean doRemove, ForgeDirection from, int maxItemCount) {
return new ItemStack[] { extractItem(doRemove, false) };
ItemStack item = null;
ItemStack result = this.craftResult.getStackInSlot(0);
if (result != null){
if (!this.canCraft()){
this.refilFromNeibour();
if (!this.canCraft()){
return new ItemStack[0];
}
}
this.craft();
item = result.copy();
}else{
return new ItemStack[0];
}
return new ItemStack[] { item };
}
@Override
public boolean isInvNameLocalized()
{
// TODO Auto-generated method stub
public boolean isInvNameLocalized(){
return false;
}
@Override
public boolean isStackValidForSlot(int i, ItemStack itemstack)
{
// TODO Auto-generated method stub
public boolean isStackValidForSlot(int slot, ItemStack stack){
return false;
}
}