package crazypants.enderio.machine.vacuum;
import java.util.List;
import net.minecraft.block.Block;
import net.minecraft.command.IEntitySelector;
import net.minecraft.entity.Entity;
import net.minecraft.entity.IProjectile;
import net.minecraft.entity.item.EntityItem;
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 net.minecraft.util.AxisAlignedBB;
import com.enderio.core.client.render.BoundingBox;
import com.enderio.core.common.util.ItemUtil;
import crazypants.enderio.EnderIO;
import crazypants.enderio.ModObject;
import crazypants.enderio.TileEntityEio;
import crazypants.enderio.conduit.item.FilterRegister;
import crazypants.enderio.conduit.item.filter.IItemFilter;
import crazypants.enderio.conduit.item.filter.ItemFilter;
import crazypants.enderio.config.Config;
import crazypants.enderio.machine.IRedstoneModeControlable;
import crazypants.enderio.machine.RedstoneControlMode;
public class TileVacuumChest extends TileEntityEio implements IEntitySelector, IInventory, IRedstoneModeControlable {
public static final int ITEM_ROWS = 3;
public static final int ITEM_SLOTS = 9*ITEM_ROWS;
public static final int FILTER_SLOTS = 5;
private final ItemStack[] inv = new ItemStack[ITEM_SLOTS];
private int range = Config.vacuumChestRange;
private ItemFilter filter;
private ItemStack filterItem;
protected RedstoneControlMode redstoneControlMode = RedstoneControlMode.IGNORE;
protected boolean redstoneCheckPassed;
private boolean redstoneStateDirty = true;
@Override
public void doUpdate() {
if(redstoneStateDirty) {
updateRedstoneStatus();
}
if(redstoneCheckPassed && !isFull()) {
doHoover();
}
}
private void updateRedstoneStatus() {
boolean prevRedstoneCheckPassed = redstoneCheckPassed;
redstoneCheckPassed = RedstoneControlMode.isConditionMet(redstoneControlMode, this);
redstoneStateDirty = false;
if(redstoneCheckPassed != prevRedstoneCheckPassed) {
updateBlock();
}
}
public void onNeighborBlockChange(Block blockId) {
redstoneStateDirty = true;
}
@Override
public boolean isEntityApplicable(Entity entity) {
if(entity.isDead) {
return false;
}
if(entity instanceof IProjectile) {
return entity.motionY < 0.01;
}
if(entity instanceof EntityItem) {
return true;
}
return false;
}
@SuppressWarnings("unchecked")
private void doHoover() {
int rangeSqr = range*range;
BoundingBox bb = new BoundingBox(getLocation());
AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ);
aabb = aabb.expand(range, range, range);
List<EntityItem> interestingItems = worldObj.selectEntitiesWithinAABB(EntityItem.class, aabb, this);
for (EntityItem entity : interestingItems) {
if(filter == null || filter.doesItemPassFilter(entity.getEntityItem())) {
double x = (xCoord + 0.5D - entity.posX);
double y = (yCoord + 0.5D - entity.posY);
double z = (zCoord + 0.5D - entity.posZ);
double distance = Math.sqrt(x * x + y * y + z * z);
if(distance < 1.25) {
hooverEntity(entity);
} else {
double speed = 0.06;
double distScale = 1.0 - Math.min(0.9, distance / rangeSqr);
distScale *= distScale;
entity.motionX += x / distance * distScale * speed;
entity.motionY += y / distance * distScale * 0.2;
entity.motionZ += z / distance * distScale * speed;
}
}
}
}
private void hooverEntity(Entity entity) {
if(!worldObj.isRemote) {
if(entity instanceof EntityItem && !entity.isDead) {
EntityItem item = (EntityItem) entity;
ItemStack stack = item.getEntityItem().copy();
int numInserted = ItemUtil.doInsertItem(this, stack, null);
stack.stackSize -= numInserted;
item.setEntityItemStack(stack);
if(stack.stackSize == 0) {
item.setDead();
}
}
}
}
private boolean isFull() {
for (ItemStack stack : inv) {
if(stack == null || stack.stackSize < stack.getMaxStackSize()) {
return false;
}
}
return true;
}
@Override
public boolean isUseableByPlayer(EntityPlayer player) {
return canPlayerAccess(player);
}
@Override
public int getSizeInventory() {
return inv.length;
}
@Override
public int getInventoryStackLimit() {
return 64;
}
@Override
public ItemStack getStackInSlot(int slot) {
if(slot < 0 || slot >= inv.length) {
return null;
}
return inv[slot];
}
@Override
public ItemStack decrStackSize(int fromSlot, int amount) {
ItemStack fromStack = inv[fromSlot];
if(fromStack == null) {
return null;
}
if(fromStack.stackSize <= amount) {
inv[fromSlot] = null;
return fromStack;
}
ItemStack result = new ItemStack(fromStack.getItem(), amount, fromStack.getItemDamage());
if(fromStack.stackTagCompound != null) {
result.stackTagCompound = (NBTTagCompound) fromStack.stackTagCompound.copy();
}
fromStack.stackSize -= amount;
return result;
}
@Override
public void setInventorySlotContents(int slot, ItemStack contents) {
if(slot < 0 || slot >= inv.length) {
System.out.println("TileVacumChest.setInventorySlotContents: " + slot);
return;
}
if(contents == null) {
inv[slot] = contents;
} else {
inv[slot] = contents.copy();
}
if(contents != null && contents.stackSize > getInventoryStackLimit()) {
contents.stackSize = getInventoryStackLimit();
}
}
@Override
public ItemStack getStackInSlotOnClosing(int var1) {
return null;
}
@Override
public String getInventoryName() {
return ModObject.blockVacuumChest.unlocalisedName;
}
@Override
public boolean hasCustomInventoryName() {
return false;
}
@Override
public void openInventory() {
}
@Override
public void closeInventory() {
}
@Override
public boolean isItemValidForSlot(int var1, ItemStack var2) {
return true;
}
public boolean isItemValidForFilter(ItemStack itemstack) {
return itemstack != null && itemstack.getItem() == EnderIO.itemBasicFilterUpgrade && itemstack.getItemDamage() == 0;
}
public int getRange() {
return range;
}
private int limitRange(int range) {
return Math.max(1, Math.min(Config.vacuumChestRange, range));
}
public void setRange(int range) {
this.range = limitRange(range);
updateBlock();
}
public ItemStack getFilterItem() {
return filterItem;
}
public void setFilterItem(ItemStack filterItem) {
IItemFilter newFilter = FilterRegister.getFilterForUpgrade(filterItem);
if(newFilter == null || newFilter instanceof ItemFilter) {
this.filterItem = filterItem;
this.filter = (ItemFilter)newFilter;
updateBlock();
}
}
public void setFilterBlacklist(boolean isBlacklist) {
if(filter != null) {
filter.setBlacklist(isBlacklist);
updateFilterItem();
}
}
public void setFilterMatchMeta(boolean matchMeta) {
if(filter != null) {
filter.setMatchMeta(matchMeta);
updateFilterItem();
}
}
public boolean hasItemFilter() {
return filter != null;
}
public ItemFilter getItemFilter() {
return filter;
}
public void setItemFilterSlot(int slot, ItemStack stack) {
if(slot >= 0 && slot < FILTER_SLOTS && filter != null) {
filter.setInventorySlotContents(slot, stack);
updateFilterItem();
}
}
private void updateFilterItem() {
FilterRegister.writeFilterToStack(filter, filterItem);
updateBlock();
}
@Override
public RedstoneControlMode getRedstoneControlMode() {
return redstoneControlMode;
}
@Override
public void setRedstoneControlMode(RedstoneControlMode redstoneControlMode) {
this.redstoneControlMode = redstoneControlMode;
redstoneStateDirty = true;
updateBlock();
}
@Override
public void readCustomNBT(NBTTagCompound nbtRoot) {
readContentsFromNBT(nbtRoot);
redstoneCheckPassed = nbtRoot.getBoolean("redstoneCheckPassed");
}
public void readContentsFromNBT(NBTTagCompound nbtRoot) {
NBTTagList itemList = (NBTTagList) nbtRoot.getTag("Items");
if(itemList != null) {
for (int i = 0; i < itemList.tagCount(); i++) {
NBTTagCompound itemStack = itemList.getCompoundTagAt(i);
byte slot = itemStack.getByte("Slot");
if(slot >= 0 && slot < inv.length) {
inv[slot] = ItemStack.loadItemStackFromNBT(itemStack);
}
}
}
if(nbtRoot.hasKey("range")) {
range = limitRange(nbtRoot.getInteger("range"));
} else {
range = Config.vacuumChestRange;
}
if(nbtRoot.hasKey("filter")) {
NBTTagCompound filterTag = (NBTTagCompound) nbtRoot.getTag("filter");
filterItem = ItemStack.loadItemStackFromNBT(filterTag);
IItemFilter flt = FilterRegister.getFilterForUpgrade(filterItem);
if(flt instanceof ItemFilter) {
filter = (ItemFilter)flt;
} else {
filterItem = null;
}
} else {
filterItem = null;
filter = null;
}
int rsContr = nbtRoot.getInteger("redstoneControlMode");
if(rsContr < 0 || rsContr >= RedstoneControlMode.values().length) {
rsContr = 0;
}
redstoneControlMode = RedstoneControlMode.values()[rsContr];
}
@Override
public void writeCustomNBT(NBTTagCompound nbtRoot) {
writeContentsToNBT(nbtRoot);
nbtRoot.setBoolean("redstoneCheckPassed", redstoneCheckPassed);
}
public void writeContentsToNBT(NBTTagCompound nbtRoot) {
NBTTagList itemList = new NBTTagList();
for (int i = 0; i < inv.length; i++) {
if(inv[i] != null) {
NBTTagCompound itemStackNBT = new NBTTagCompound();
itemStackNBT.setByte("Slot", (byte) i);
inv[i].writeToNBT(itemStackNBT);
itemList.appendTag(itemStackNBT);
}
}
nbtRoot.setTag("Items", itemList);
nbtRoot.setInteger("range", range);
if(filterItem != null) {
NBTTagCompound filterNBT = new NBTTagCompound();
filterItem.writeToNBT(filterNBT);
nbtRoot.setTag("filter", filterNBT);
}
nbtRoot.setInteger("redstoneControlMode", redstoneControlMode.ordinal());
}
}