public class EntityMirrorVessel extends Entity implements IInventory {
final static byte VACUUM_TIMELIMIT = 20;
final static int VACUUM_RADIUS = 5;
private final NonNullList<ItemStack> mainInventory = NonNullList.withSize(200, ItemStack.EMPTY);
private final Deque<ItemStack> auxInventory = new LinkedList<>();
private byte vacuumTime = 0;
private static final DataParameter<ItemStack> ITEM = EntityDataManager.<ItemStack>createKey(EntityMirrorVessel.class, DataSerializers.ITEM_STACK);
private int age;
private int pickupDelay;
private int health = 5;
private String thrower;
private String owner;
public final float hoverStart = (float)(Math.random() * Math.PI * 2.0D);
public EntityMirrorVessel(World world) {
super(world);
this.setSize(0.9F, 0.9F);
}
public EntityMirrorVessel(World world, double x, double y, double z) {
super(world);
this.setPosition(x, y, z);
this.rotationYaw = this.rand.nextFloat() * 360.0F;
this.setSize(0.9F, 0.9F);
setNoGravity(true);
}
public EntityMirrorVessel(World world, double x, double y, double z, ItemStack stack) {
this(world, x, y, z);
this.setSize(0.9F, 0.9F);
this.setItem(stack);
this.markDirty();
}
protected boolean canTriggerWalking() { return false; }
protected void entityInit() { this.getDataManager().register(ITEM, ItemStack.EMPTY); }
protected boolean canDespawn() { return false; }
public void onUpdate() {
if (this.getItem().isEmpty()) {
this.dropAllItems();
this.setDead();
} else {
super.onUpdate();
if (this.pickupDelay > 0 && this.pickupDelay != 32767) --this.pickupDelay;
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
double d0 = this.motionX;
double d1 = this.motionY;
double d2 = this.motionZ;
if (!this.hasNoGravity()) this.motionY -= 0.04d;
if (this.world.isRemote) {
this.noClip = false;
world.spawnParticle(EnumParticleTypes.PORTAL, this.posX, this.posY+(this.getEyeHeight()/2), this.posZ, ((Math.random()-0.5)*2.0), ((Math.random()-0.5)*2.0), ((Math.random()-0.5)*2.0));
}
++this.age;
if (!this.world.isRemote) {
double d3 = this.motionX - d0;
double d4 = this.motionY - d1;
double d5 = this.motionZ - d2;
double d6 = d3 * d3 + d4 * d4 + d5 * d5;
if (d6 > 0.01D) this.isAirBorne = true;
}
ItemStack item = this.getItem();
if (item.isEmpty()) this.setDead();
}
//inventory--------------------
final boolean isClient = getEntityWorld().isRemote;
final boolean isServer = !isClient;
if (isServer && vacuumTime < VACUUM_TIMELIMIT) {
vacuumTime++;
List<EntityItem> items = getEntityWorld().getEntitiesWithinAABB(EntityItem.class, new AxisAlignedBB(
posX - VACUUM_RADIUS, posY - VACUUM_RADIUS, posZ - VACUUM_RADIUS,
posX + VACUUM_RADIUS, posY + VACUUM_RADIUS, posZ + VACUUM_RADIUS));
for (EntityItem item : items) { ItemStack stack = item.getItem(); this.addItem(stack); }
for (EntityItem item : items) getEntityWorld().removeEntity(item);
}
if (isServer && vacuumTime >= VACUUM_TIMELIMIT && (this.inWater || this.isInLava() || this.posY < 0)) {
this.motionY += 2.025D;
this.motionY *= 1.2;
}
if (isServer && isEmpty()) this.setDead();
}
protected void dealFireDamage(int amount) { this.attackEntityFrom(DamageSource.IN_FIRE, (float)amount); }
@Override
public boolean attackEntityFrom(DamageSource source, float amount) {
if (this.world.isRemote || !this.isEntityAlive()) return false;
if (source.isDamageAbsolute()) return false; else return false;
}
public static void registerFixesItem(DataFixer fixer) { fixer.registerWalker(FixTypes.ENTITY, new ItemStackData(EntityItem.class, new String[] {"Item"})); }
public void writeEntityToNBT(NBTTagCompound compound) {
compound.setShort("Health", (short)this.health);
compound.setShort("Age", (short)this.age);
compound.setShort("PickupDelay", (short)this.pickupDelay);
if (this.getThrower() != null) compound.setString("Thrower", this.thrower);
if (this.getOwner() != null) compound.setString("Owner", this.owner);
if (!this.getItem().isEmpty()) compound.setTag("Item", this.getItem().writeToNBT(new NBTTagCompound()));
//inventory---------------------------
final NBTTagList equipmentListTag = new NBTTagList();
for (int i = 0; i < this.getSizeInventory(); i++) {
ItemStack item = this.getStackInSlot(i);
if (!item.isEmpty()) {
NBTTagCompound slotTag = new NBTTagCompound();
slotTag.setByte("Slot", (byte)i);
item.writeToNBT(slotTag);
equipmentListTag.appendTag(slotTag);
}
}
compound.setTag("Equipment", equipmentListTag);
if (!this.auxInventory.isEmpty()) {
final NBTTagList nbtauxtaglist = new NBTTagList();
Iterator<ItemStack> iter = this.auxInventory.iterator();
while (iter.hasNext()) {
ItemStack i = iter.next();
if (i.isEmpty()) continue;
final NBTTagCompound nbttagcompound1 = new NBTTagCompound();
i.writeToNBT(nbttagcompound1);
nbtauxtaglist.appendTag(nbttagcompound1);
}
compound.setTag("Aux", nbtauxtaglist);
}
if (vacuumTime < VACUUM_TIMELIMIT) compound.setByte("Vac", vacuumTime);
}
public void readEntityFromNBT(NBTTagCompound compound) {
this.health = compound.getShort("Health");
this.age = compound.getShort("Age");
if (compound.hasKey("PickupDelay")) this.pickupDelay = compound.getShort("PickupDelay");
if (compound.hasKey("Owner")) this.owner = compound.getString("Owner");
if (compound.hasKey("Thrower")) this.thrower = compound.getString("Thrower");
NBTTagCompound nbttagcompound = compound.getCompoundTag("Item");
this.setItem(new ItemStack(nbttagcompound));
if (this.getItem().isEmpty()) this.setDead();
//inventory---------------------------
if (compound.hasKey("Equipment", 9)) {
final NBTTagList nbttaglist = compound.getTagList("Equipment", 10);
for (int i = 0; i < nbttaglist.tagCount(); ++i) {
NBTTagCompound slotTag = nbttaglist.getCompoundTagAt(i);
int slot = slotTag.getByte("Slot");
ItemStack item = new ItemStack(slotTag);
this.setInventorySlotContents(slot,item);
}
}
if (compound.hasKey("Aux")) {
final NBTTagList nbttaglist = compound.getTagList("Aux", 10);
for (int i = 0; i < nbttaglist.tagCount(); ++i) this.auxInventory.addLast(new ItemStack(nbttaglist.getCompoundTagAt(i)));
}
if (compound.hasKey("Vac")) this.vacuumTime = compound.getByte("Vac"); else this.vacuumTime = VACUUM_TIMELIMIT;
}
@SuppressWarnings("unlikely-arg-type")
public void onCollideWithPlayer(EntityPlayer player) {
if (!this.world.isRemote) {
if (this.pickupDelay > 0) return;
ItemStack itemstack = this.getItem();
Item item = itemstack.getItem();
int i = itemstack.getCount();
if (player.isSneaking()) if (this.pickupDelay == 0 && (this.owner == null || this.owner.equals(player.getUniqueID()))) {
this.dropAllItems();
this.setDead();
}
}
}
public String getName() { return this.hasCustomName() ? this.getCustomNameTag() : I18n.translateToLocal("item." + this.getItem().getUnlocalizedName()); }
public boolean canBeAttackedWithItem() { return false; }
@Nullable
public Entity changeDimension(int dimensionIn, net.minecraftforge.common.util.ITeleporter teleporter) {
Entity entity = super.changeDimension(dimensionIn, teleporter);
return entity;
}
public ItemStack getItem() { return (ItemStack)this.getDataManager().get(ITEM); }
public void setItem(ItemStack stack) { this.getDataManager().set(ITEM, stack); }
public String getOwner() { return this.owner; }
public void setOwner(String owner) { this.owner = owner; }
public String getThrower() { return this.thrower; }
public void setThrower(String thrower) { this.thrower = thrower; }
@SideOnly(Side.CLIENT) public int getAge() { return this.age; }
public void setDefaultPickupDelay() { this.pickupDelay = 10; }
public void setNoPickupDelay() { this.pickupDelay = 0; }
public void setInfinitePickupDelay() { this.pickupDelay = 32767; }
public void setPickupDelay(int ticks) { this.pickupDelay = ticks; }
public boolean cannotPickup() { return this.pickupDelay > 0; }
public void makeFakeItem() { this.setInfinitePickupDelay(); }
//inventory---------------------------
public void addItem(ItemStack stack) {
for (int slot = 0; slot < this.getSizeInventory(); slot++) {
stack = mergeItem(slot,stack);
if (stack.isEmpty()) return;
}
auxInventory.addLast(stack);
}
public void initializeItems(NonNullList<ItemStack> inv) {
for (int i = 0; i < inv.size(); i++) {
if (i < mainInventory.size()) mainInventory.set(i,inv.get(i));
else auxInventory.addLast(inv.get(i));
}
}
public ItemStack mergeItem(int slot, ItemStack stack) {
if (stack.isEmpty()) return ItemStack.EMPTY;
ItemStack current = this.getStackInSlot(slot);
final int inventorySizeLimit = Math.min(stack.getMaxStackSize(), this.getInventoryStackLimit());
if (current.isEmpty()) {
this.setInventorySlotContents(slot, stack);
return ItemStack.EMPTY;
} else if(current.getCount() < inventorySizeLimit && ItemStack.areItemsEqual(stack,current) && ItemStack.areItemStackTagsEqual(stack,current)) {
int delta = Math.min(stack.getCount(),inventorySizeLimit - current.getCount());
current.grow(delta);
stack.shrink(delta);
this.setInventorySlotContents(slot,current);
if (stack.getCount() <= 0) return ItemStack.EMPTY;
return stack;
}
return stack;
}
@Override public int getSizeInventory() { return mainInventory.size(); }
public boolean isEmpty() {
if (!auxInventory.isEmpty()) return false;
for (int slot = 0; slot < this.getSizeInventory(); slot++) if (!this.getStackInSlot(slot).isEmpty()) return false;
return true;
}
private void dropAllItems() {
for (ItemStack i : mainInventory) if (!i.isEmpty()) this.getEntityWorld().spawnEntity(new EntityItem(this.getEntityWorld(), posX, posY, posZ, i));
for (ItemStack i : auxInventory) if (!i.isEmpty()) this.getEntityWorld().spawnEntity(new EntityItem(this.getEntityWorld(), posX, posY, posZ, i));
this.clear();
}
@Override public ItemStack getStackInSlot(int index) { return mainInventory.get(index); }
@Override public ItemStack decrStackSize(int index, int count) {
ItemStack i = this.getStackInSlot(index);
ItemStack result = i.splitStack(count);
if (i.getCount() <= 0) i = ItemStack.EMPTY;
this.setInventorySlotContents(index, i);
return result;
}
@Override public ItemStack removeStackFromSlot(int index) { ItemStack i = this.getStackInSlot(index); this.setInventorySlotContents(index,ItemStack.EMPTY); return i; }
@Override public void setInventorySlotContents(int index, ItemStack stack) { mainInventory.set(index, stack); }
@Override public int getInventoryStackLimit() { return 64; }
@Override public void markDirty() {}
@Override public boolean isUsableByPlayer(EntityPlayer player) { return false; }
@Override public void openInventory(EntityPlayer player) {}
@Override public void closeInventory(EntityPlayer player) {}
@Override public boolean isItemValidForSlot(int index, ItemStack stack) { return true; }
@Override public int getField(int id) { return 0; }
@Override public void setField(int id, int value) { }
@Override public int getFieldCount() { return 0; }
@Override public void clear() { mainInventory.clear(); auxInventory.clear(); }
}