package advancedsystemsmanager.tileentities; import advancedsystemsmanager.api.network.IPacketBlock; import advancedsystemsmanager.api.tileentities.IActivateListener; import advancedsystemsmanager.helpers.BlockHelper; import advancedsystemsmanager.network.ASMPacket; import advancedsystemsmanager.network.PacketHandler; import advancedsystemsmanager.registry.ClusterRegistry; import com.mojang.authlib.GameProfile; import net.minecraft.block.Block; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.init.Blocks; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.Packet; import net.minecraft.util.IIcon; import net.minecraft.util.StatCollector; import net.minecraft.world.WorldServer; import net.minecraftforge.common.util.FakePlayerFactory; import net.minecraftforge.common.util.ForgeDirection; import java.util.ArrayList; import java.util.List; import java.util.UUID; public class TileEntityBlockGate extends TileEntityElementRotation implements IInventory, IPacketBlock, IActivateListener { protected static final int[] ROTATION_SIDE_MAPPING = {0, 0, 0, 2, 3, 1}; protected static final String NBT_DIRECTION = "Direction"; private static final String FAKE_PLAYER_NAME = "[ASM_PLAYER]"; private static final UUID FAKE_PLAYER_ID = null; private static final GameProfile FAKE_PLAYER_PROFILE = new GameProfile(FAKE_PLAYER_ID, FAKE_PLAYER_NAME); protected boolean blocked; protected int placeDirection; private List<ItemStack> inventory; private List<ItemStack> inventoryCache; private boolean broken; @Override public IIcon getIcon(int side) { if (getFacing() != null) { if (side == placeDirection && side == getFacing().ordinal()) { return getTileFactory().getIcons(subtype)[0]; } else if (side == placeDirection) { return getTileFactory().getIcons(subtype)[3]; } else if (side == getFacing().ordinal()) { return getTileFactory().getIcons(subtype)[2]; } } return getTileFactory().getIcons(subtype)[1]; } @Override public boolean onBlockActivated(EntityPlayer player, int side, float xSide, float ySide, float zSide) { int direction = player.isSneaking() ? BlockHelper.getReverseDirection(side) : side; setPlaceDirection(direction); sendPacketToClient(); return true; } @Override public void onBlockPlacedBy(EntityLivingBase entity, ItemStack item) { super.onBlockPlacedBy(entity, item); setPlaceDirection(getFacing().ordinal()); } public void setPlaceDirection(int placeDirection) { if (this.placeDirection != placeDirection) { this.placeDirection = placeDirection; setMessageType(CLIENT_SYNC); } } @Override public void writeClientSyncData(ASMPacket packet) { super.writeClientSyncData(packet); packet.writeByte(placeDirection); } @Override public void readClientSyncData(ASMPacket packet) { super.readClientSyncData(packet); placeDirection = packet.readByte(); } @Override public void writeToTileNBT(NBTTagCompound tag) { super.writeToTileNBT(tag); tag.setByte(NBT_DIRECTION, (byte) placeDirection); } @Override public void readFromTileNBT(NBTTagCompound tag) { super.readFromTileNBT(tag); setPlaceDirection(tag.getByte(NBT_DIRECTION)); } @Override public void updateEntity() { super.updateEntity(); if (inventory != null) { ForgeDirection direction = getFacing(); for (ItemStack itemStack : getInventoryForDrop()) { List<ItemStack> items = placeItem(itemStack); if (items != null && !items.isEmpty()) { for (ItemStack item : items) { double x = xCoord + 0.5 + direction.offsetX * 0.75; double y = yCoord + 0.5 + direction.offsetY * 0.75; double z = zCoord + 0.5 + direction.offsetZ * 0.75; if (direction.offsetY == 0) { y -= 0.1; } EntityItem entityitem = new EntityItem(worldObj, x, y, z, item); entityitem.motionX = direction.offsetX * 0.1; entityitem.motionY = direction.offsetY * 0.1; entityitem.motionZ = direction.offsetZ * 0.1; entityitem.delayBeforeCanPickup = 40; worldObj.spawnEntityInWorld(entityitem); } } } } inventory = null; inventoryCache = null; broken = false; } private List<ItemStack> getInventoryForDrop() { List<ItemStack> ret = new ArrayList<ItemStack>(); for (ItemStack itemStack : inventory) { if (itemStack != null) { ItemStack newStack = itemStack.copy(); if (!broken) { for (int i = 0; i < inventoryCache.size(); i++) { ItemStack copyStack = inventoryCache.get(i); if (copyStack != null && newStack.isItemEqual(copyStack) && ItemStack.areItemStackTagsEqual(newStack, copyStack)) { int max = Math.min(copyStack.stackSize, newStack.stackSize); copyStack.stackSize -= max; if (copyStack.stackSize == 0) { inventoryCache.set(0, null); } newStack.stackSize -= max; if (newStack.stackSize == 0) { newStack = null; break; } } } } if (newStack != null) { ret.add(newStack); } } } return ret; } private List<ItemStack> placeItem(ItemStack itemstack) { List<ItemStack> items = new ArrayList<ItemStack>(); if (itemstack != null && itemstack.getItem() != null && itemstack.stackSize > 0) { ForgeDirection facing = getFacing(); ForgeDirection side = ForgeDirection.getOrientation(placeDirection); float hitX = 0.5F + side.offsetX * 0.5F; float hitY = 0.5F + side.offsetY * 0.5F; float hitZ = 0.5F + side.offsetZ * 0.5F; if (facing == side) { facing = ForgeDirection.UNKNOWN; } side = side.getOpposite(); EntityPlayerMP player = FakePlayerFactory.get((WorldServer)worldObj, FAKE_PLAYER_PROFILE); int rotationSide = ROTATION_SIDE_MAPPING[side.ordinal()]; player.prevRotationYaw = player.rotationYaw = rotationSide * 90; player.prevRotationPitch = player.rotationPitch = side == ForgeDirection.UP ? 90 : side == ForgeDirection.DOWN ? -90 : 0; player.prevPosX = player.posX = xCoord + facing.offsetX + 0.5D; player.prevPosY = player.posY = yCoord + facing.offsetY + 0.5D; player.prevPosZ = player.posZ = zCoord + facing.offsetZ + 0.5D; player.eyeHeight = 0; player.yOffset = 1.82F; player.theItemInWorldManager.setBlockReachDistance(1); blocked = true; try { player.inventory.clearInventory(null, -1); player.inventory.currentItem = 0; player.inventory.setInventorySlotContents(0, itemstack); ItemStack result = itemstack.useItemRightClick(worldObj, player); if (ItemStack.areItemStacksEqual(result, itemstack)) { int x = xCoord + facing.offsetX - side.offsetX; int y = yCoord + facing.offsetY - side.offsetY; int z = zCoord + facing.offsetZ - side.offsetZ; player.theItemInWorldManager.activateBlockOrUseItem(player, worldObj, itemstack, x, y, z, side.ordinal(), hitX, hitY, hitZ); } else { player.inventory.setInventorySlotContents(0, result); } } catch (Exception ignored) { } finally { for (ItemStack itemStack : player.inventory.mainInventory) { if (itemStack != null && itemStack.stackSize > 0) { items.add(itemStack); } } blocked = false; } } return items; } @Override public void markDirty() { super.markDirty(); if (inventory != null && !broken) { boolean match = true; for (int i = 0; i < inventory.size(); i++) { ItemStack itemStack = inventory.get(i); ItemStack itemStackCopy = inventoryCache.get(i); if (!ItemStack.areItemStacksEqual(itemStack, itemStackCopy) || itemStack.stackSize < itemStackCopy.stackSize) { match = false; break; } } if (!match) { ForgeDirection direction = getFacing(); int x = xCoord + direction.offsetX; int y = yCoord + direction.offsetY; int z = zCoord + direction.offsetZ; Block block = worldObj.getBlock(x, y, z); if (canBreakBlock(block, x, y, z)) { broken = true; int meta = worldObj.getBlockMetadata(x, y, z); block.breakBlock(worldObj, x, y, z, block, meta); worldObj.playAuxSFX(2001, x, y, z, Block.getIdFromBlock(block) + (meta << 12)); worldObj.setBlockToAir(x, y, z); } } } } @Override public Packet getDescriptionPacket() { PacketHandler.sendBlockPacket(this, null, CLIENT_SYNC); return null; } private boolean canBreakBlock(Block block, int x, int y, int z) { return block != null && block != Blocks.bedrock && block.getBlockHardness(worldObj, x, y, z) >= 0; } @Override public int getSizeInventory() { return getInventory().size() + 1; } private List<ItemStack> getInventory() { if (inventory == null) { ForgeDirection direction = getFacing(); int x = xCoord + direction.offsetX; int y = yCoord + direction.offsetY; int z = zCoord + direction.offsetZ; Block block = worldObj.getBlock(x, y, z); if (canBreakBlock(block, x, y, z)) { inventory = block.getDrops(worldObj, x, y, z, worldObj.getBlockMetadata(x, y, z), 0); } if (inventory == null) { inventory = new ArrayList<ItemStack>(); } inventoryCache = new ArrayList<ItemStack>(); for (ItemStack itemStack : inventory) { inventoryCache.add(itemStack.copy()); } } return inventory; } @Override public ItemStack getStackInSlot(int id) { if (id < getInventory().size()) { return getInventory().get(id); } else { return null; } } @Override public ItemStack decrStackSize(int id, int count) { ItemStack item = getStackInSlot(id); if (item != null) { if (item.stackSize <= count) { getInventory().set(id, null); return item; } ItemStack ret = item.splitStack(count); if (item.stackSize == 0) { getInventory().set(id, null); } return ret; } else { return null; } } @Override public ItemStack getStackInSlotOnClosing(int i) { return null; } @Override public void setInventorySlotContents(int id, ItemStack itemstack) { if (id < getInventory().size()) { getInventory().set(id, itemstack); } else { getInventory().add(itemstack); inventoryCache.add(null); } } @Override public String getInventoryName() { return StatCollector.translateToLocal(ClusterRegistry.BLOCK_GATE.getUnlocalizedName(subtype)); } @Override public boolean hasCustomInventoryName() { return true; } @Override public int getInventoryStackLimit() { return 64; } @Override public boolean isUseableByPlayer(EntityPlayer entityplayer) { return false; } @Override public void openInventory() { } @Override public void closeInventory() { } @Override public boolean isItemValidForSlot(int i, ItemStack itemstack) { return true; } public boolean isBlocked() { return blocked; } }