assemblyline/src/main/java/assemblyline/common/machine/TileEntityManipulator.java
2023-02-10 17:51:10 +01:00

398 lines
15 KiB
Java

package assemblyline.common.machine;
import java.util.List;
import assemblyline.api.IManipulator;
import assemblyline.common.block.BlockCrate;
import assemblyline.common.block.TileEntityCrate;
import assemblyline.common.machine.imprinter.TileEntityFilterable;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.ISidedInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityChest;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.world.IBlockAccess;
import net.minecraftforge.common.util.ForgeDirection;
import universalelectricity.core.vector.Vector3;
import universalelectricity.prefab.implement.IRedstoneReceptor;
import universalelectricity.prefab.implement.IRotatable;
import universalelectricity.prefab.multiblock.TileEntityMulti;
public class TileEntityManipulator
extends TileEntityFilterable implements IRotatable, IRedstoneReceptor, IManipulator {
public boolean selfPulse = false;
private boolean isOutput = false;
private boolean isRedstonePowered = false;
public boolean isOutput() {
return this.isOutput;
}
public void setOutput(boolean isOutput) {
this.isOutput = isOutput;
if (!this.worldObj.isRemote) {
this.worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
}
}
public void toggleOutput() {
this.setOutput(!this.isOutput());
}
@Override
protected void onUpdate() {
if (!this.worldObj.isRemote) {
if (this.ticks % 20L == 0L) {
this.worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
}
if (!this.isDisabled() && this.isRunning()) {
if (!this.isOutput) {
this.inject();
} else {
if (this.selfPulse && this.ticks % 10L == 0L) {
this.isRedstonePowered = true;
}
if (this.isRedstonePowered) {
this.eject();
}
}
}
}
}
@Override
public void inject() {
Vector3 inputPosition = new Vector3(this);
Vector3 outputUp = new Vector3(this);
outputUp.modifyPositionFromSide(ForgeDirection.UP);
Vector3 outputDown = new Vector3(this);
outputDown.modifyPositionFromSide(ForgeDirection.DOWN);
Vector3 outputPosition = new Vector3(this);
outputPosition.modifyPositionFromSide(this.getDirection().getOpposite());
if (outputPosition.getTileEntity((IBlockAccess) this.worldObj)
instanceof TileEntityManipulator
&& ((TileEntityManipulator
) outputPosition.getTileEntity((IBlockAccess) this.worldObj))
.getDirection()
== this.getDirection().getOpposite()) {
return;
}
AxisAlignedBB bounds = AxisAlignedBB.getBoundingBox(
(double) inputPosition.x,
(double) inputPosition.y,
(double) inputPosition.z,
(double) (inputPosition.x + 1.0),
(double) (inputPosition.y + 1.0),
(double) (inputPosition.z + 1.0)
);
List<EntityItem> itemsInBound
= this.worldObj.getEntitiesWithinAABB(EntityItem.class, bounds);
for (EntityItem entity : itemsInBound) {
if (entity.isDead)
continue;
ItemStack remainingStack = entity.getEntityItem().copy();
if (this.getFilter() != null && !this.isFiltering(remainingStack))
continue;
if ((remainingStack
= this.tryPlaceInPosition(remainingStack, outputUp, ForgeDirection.DOWN))
!= null) {
remainingStack = this.tryPlaceInPosition(
remainingStack, outputDown, ForgeDirection.UP
);
}
if (remainingStack != null) {
remainingStack = this.tryPlaceInPosition(
remainingStack, outputPosition, this.getDirection().getOpposite()
);
}
if (remainingStack != null && remainingStack.stackSize > 0) {
this.throwItem(outputPosition, remainingStack);
}
entity.setDead();
}
}
@Override
public void eject() {
this.onPowerOff();
Vector3 inputUp = new Vector3(this);
inputUp.modifyPositionFromSide(ForgeDirection.UP);
Vector3 inputDown = new Vector3(this);
inputDown.modifyPositionFromSide(ForgeDirection.DOWN);
Vector3 inputPosition = new Vector3(this);
inputPosition.modifyPositionFromSide(this.getDirection().getOpposite());
Vector3 outputPosition = new Vector3(this);
outputPosition.modifyPositionFromSide(this.getDirection());
ItemStack itemStack = this.tryGrabFromPosition(inputUp, ForgeDirection.DOWN);
if (itemStack == null) {
itemStack = this.tryGrabFromPosition(inputDown, ForgeDirection.UP);
}
if (itemStack == null) {
itemStack = this.tryGrabFromPosition(
inputPosition, this.getDirection().getOpposite()
);
}
if (itemStack != null && itemStack.stackSize > 0) {
this.throwItem(outputPosition, itemStack);
}
}
public void throwItem(Vector3 outputPosition, ItemStack items) {
if (!this.worldObj.isRemote) {
EntityItem entityItem = new EntityItem(
this.worldObj,
outputPosition.x + 0.5,
outputPosition.y + 0.8,
outputPosition.z + 0.5,
items
);
entityItem.motionX = 0.0;
entityItem.motionZ = 0.0;
entityItem.motionY /= 5.0;
entityItem.delayBeforeCanPickup = 20;
this.worldObj.spawnEntityInWorld((Entity) entityItem);
}
}
private ItemStack
tryPlaceInPosition(ItemStack itemStack, Vector3 position, ForgeDirection direction) {
TileEntity tileEntity = position.getTileEntity((IBlockAccess) this.worldObj);
if (tileEntity != null && itemStack != null) {
if (tileEntity instanceof TileEntityMulti) {
Vector3 mainBlockPosition
= ((TileEntityMulti) tileEntity).mainBlockPosition;
if (mainBlockPosition != null
&& !(
mainBlockPosition.getTileEntity((IBlockAccess) this.worldObj)
instanceof TileEntityMulti
)) {
return this.tryPlaceInPosition(
itemStack, mainBlockPosition, direction
);
}
} else if (tileEntity instanceof TileEntityChest) {
TileEntityChest[] chests
= new TileEntityChest[] { (TileEntityChest) tileEntity, null };
for (int i = 2; i < 6; ++i) {
ForgeDirection searchDirection
= ForgeDirection.getOrientation((int) i);
Vector3 searchPosition = position.clone();
searchPosition.modifyPositionFromSide(searchDirection);
if (searchPosition.getTileEntity((IBlockAccess) this.worldObj) == null
|| searchPosition.getTileEntity((IBlockAccess) this.worldObj)
.getClass()
!= chests[0].getClass())
continue;
chests[1] = (TileEntityChest
) searchPosition.getTileEntity((IBlockAccess) this.worldObj);
break;
}
for (TileEntityChest chest : chests) {
if (chest == null)
continue;
for (int i = 0; i < chest.getSizeInventory(); ++i) {
if ((itemStack
= this.addStackToInventory(i, (IInventory) chest, itemStack))
!= null)
continue;
return null;
}
}
} else {
if (tileEntity instanceof TileEntityCrate) {
return BlockCrate.putIn((TileEntityCrate) tileEntity, itemStack);
}
if (tileEntity instanceof ISidedInventory) {
int startIndex;
ISidedInventory inventory = (ISidedInventory) tileEntity;
for (int i :
inventory.getAccessibleSlotsFromSide(direction.ordinal())) {
if ((itemStack = this.addStackToInventory(
i, (IInventory) inventory, itemStack
))
!= null)
continue;
return null;
}
} else if (tileEntity instanceof IInventory) {
IInventory inventory = (IInventory) tileEntity;
for (int i = 0; i < inventory.getSizeInventory(); ++i) {
if ((itemStack
= this.addStackToInventory(i, inventory, itemStack))
!= null)
continue;
return null;
}
}
}
}
if (itemStack.stackSize <= 0) {
return null;
}
return itemStack;
}
public ItemStack
addStackToInventory(int slotIndex, IInventory inventory, ItemStack itemStack) {
if (inventory.getSizeInventory() > slotIndex) {
ItemStack stackInInventory = inventory.getStackInSlot(slotIndex);
if (stackInInventory == null) {
inventory.setInventorySlotContents(slotIndex, itemStack);
if (inventory.getStackInSlot(slotIndex) == null) {
return itemStack;
}
return null;
}
if (stackInInventory.isItemEqual(itemStack)
&& stackInInventory.isStackable()) {
stackInInventory = stackInInventory.copy();
int stackLim = Math.min(
inventory.getInventoryStackLimit(), itemStack.getMaxStackSize()
);
int rejectedAmount = Math.max(
stackInInventory.stackSize + itemStack.stackSize - stackLim, 0
);
stackInInventory.stackSize = Math.min(
Math.max(
stackInInventory.stackSize + itemStack.stackSize - rejectedAmount,
0
),
inventory.getInventoryStackLimit()
);
itemStack.stackSize = rejectedAmount;
inventory.setInventorySlotContents(slotIndex, stackInInventory);
}
}
if (itemStack.stackSize <= 0) {
return null;
}
return itemStack;
}
private ItemStack tryGrabFromPosition(Vector3 position, ForgeDirection direction) {
ItemStack returnStack;
block6: {
TileEntity tileEntity;
block9: {
int startIndex;
block8: {
block7: {
returnStack = null;
tileEntity = position.getTileEntity((IBlockAccess) this.worldObj);
if (tileEntity == null)
break block6;
if (!(tileEntity instanceof TileEntityMulti))
break block7;
Vector3 mainBlockPosition = ((TileEntityMulti) tileEntity).mainBlockPosition;
if (mainBlockPosition != null
&& !(
mainBlockPosition.getTileEntity((IBlockAccess) this.worldObj)
instanceof TileEntityMulti
)) {
return this.tryGrabFromPosition(mainBlockPosition, direction);
}
break block6;
}
if (!(tileEntity instanceof TileEntityChest))
break block8;
TileEntityChest[] chests
= new TileEntityChest[] { (TileEntityChest) tileEntity, null };
for (int i = 2; i < 6; ++i) {
ForgeDirection searchDirection = ForgeDirection.getOrientation((int) i);
Vector3 searchPosition = position.clone();
searchPosition.modifyPositionFromSide(searchDirection);
if (searchPosition.getTileEntity((IBlockAccess) this.worldObj) == null
|| searchPosition.getTileEntity((IBlockAccess) this.worldObj).getClass()
!= chests[0].getClass())
continue;
chests[1] = (TileEntityChest
) searchPosition.getTileEntity((IBlockAccess) this.worldObj);
break;
}
for (TileEntityChest chest : chests) {
if (chest == null)
continue;
for (int i = 0; i < chest.getSizeInventory(); ++i) {
ItemStack itemStack
= this.removeStackFromInventory(i, (IInventory) chest);
if (itemStack == null)
continue;
returnStack = itemStack;
break block6;
}
}
break block6;
}
if (!(tileEntity instanceof ISidedInventory))
break block9;
ISidedInventory inventory = (ISidedInventory) tileEntity;
for (int i : inventory.getAccessibleSlotsFromSide(direction.ordinal())) {
ItemStack itemStack
= this.removeStackFromInventory(i, (IInventory) inventory);
if (itemStack == null)
continue;
returnStack = itemStack;
break block6;
}
break block6;
}
if (!(tileEntity instanceof IInventory))
break block6;
IInventory inventory = (IInventory) tileEntity;
for (int i = 0; i < inventory.getSizeInventory(); ++i) {
ItemStack itemStack = this.removeStackFromInventory(i, inventory);
if (itemStack == null)
continue;
returnStack = itemStack;
break;
}
}
return returnStack;
}
public ItemStack removeStackFromInventory(int slotIndex, IInventory inventory) {
if (inventory.getStackInSlot(slotIndex) != null) {
ItemStack itemStack = inventory.getStackInSlot(slotIndex).copy();
if (this.getFilter() == null || this.isFiltering(itemStack)) {
itemStack.stackSize = 1;
inventory.decrStackSize(slotIndex, 1);
return itemStack;
}
}
return null;
}
@Override
public void readFromNBT(NBTTagCompound nbt) {
super.readFromNBT(nbt);
this.isOutput = nbt.getBoolean("isOutput");
this.selfPulse = nbt.getBoolean("selfpulse");
}
@Override
public void writeToNBT(NBTTagCompound nbt) {
super.writeToNBT(nbt);
nbt.setBoolean("isOutput", this.isOutput);
nbt.setBoolean("selfpulse", this.selfPulse);
}
@Override
public void onPowerOn() {
this.isRedstonePowered = true;
}
@Override
public void onPowerOff() {
this.isRedstonePowered = false;
}
@Override
public boolean canConnect(ForgeDirection dir) {
return dir != this.getDirection();
}
}