@Mod(modid=RealFilingCabinet.MOD_ID, name=RealFilingCabinet.MOD_NAME, version=RealFilingCabinet.VERSION, dependencies = "after:forge@[" + RealFilingCabinet.FORGE_VER + ",);")
public class RealFilingCabinet {

	public static final String MOD_ID = "realfilingcabinet";
	public static final String MOD_NAME = "Real Filing Cabinet";
	public static final String VERSION = "@VERSION@";
	public static final String FORGE_VER = "14.21.0.2363";
	
	// intentional typo in order to disable integration with storage drawers for now
	public static final String STORAGEDRAWERS = "storageDrawers";
	
	@SidedProxy(clientSide="com.bafomdad.realfilingcabinet.proxies.ClientProxy", serverSide="com.bafomdad.realfilingcabinet.proxies.CommonProxy")
	public static CommonProxy proxy;
	
	@Mod.Instance(MOD_ID)
	public static RealFilingCabinet instance;
	
	public static Logger logger;
	
	public static boolean botaniaLoaded = Loader.isModLoaded("botania");
	public static boolean topLoaded = Loader.isModLoaded("theoneprobe");
	public static boolean wailaLoaded = Loader.isModLoaded("waila");
	public static boolean tcLoaded = Loader.isModLoaded("thaumcraft");
	public static boolean crtLoaded = Loader.isModLoaded("crafttweaker");
	
	@Mod.EventHandler
	public void preInit(FMLPreInitializationEvent event) {
		
		NetworkRegistry.INSTANCE.registerGuiHandler(this, new GuiHandlerRFC());
		NewConfigRFC.preInit(event);
		logger = event.getModLog();
		
		proxy.preInit(event);
		proxy.initAllModels();
	}
	
	@Mod.EventHandler
	public void init(FMLInitializationEvent event) {

		proxy.init(event);
	}
	
	@Mod.EventHandler
	public void postInit(FMLPostInitializationEvent event) {
		
		proxy.postInit(event);
		MinecraftForge.EVENT_BUS.register(new EventHandlerServer());
		CapabilityProviderFolder.register();
	}
	
	@Mod.EventHandler
	public void serverLoad(FMLServerStartingEvent event) {
		
		event.registerServerCommand(new CommandRFC());
	}
} public interface IUpgrades {

	public boolean canApply(TileEntityRFC tile, ItemStack upgrade, EntityPlayer player);
} @Optional.Interface(iface = "com.jaquadro.minecraft.storagedrawers.api.storage.INetworked", modid = RealFilingCabinet.STORAGEDRAWERS, striprefs = true)
public class BlockRFC extends Block implements IFilingCabinet, INetworked {
	
	static float f = 0.0625F;
	protected static final AxisAlignedBB BASE_AABB = new AxisAlignedBB(0.0D + f, 0.0D, 0.0D + f, 1.0D - f, 1.0D - f, 1.0D - f);

	public static final PropertyDirection FACING = BlockHorizontal.FACING;
	
	public BlockRFC() {
		
		super(Material.IRON);
		setRegistryName("modelcabinet");
		setTranslationKey(RealFilingCabinet.MOD_ID + ".filingcabinet");
		setHardness(5.0F);
		setResistance(1000.0F);
		setCreativeTab(TabRFC.instance);
		
		setDefaultState(blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH));
	}
	
	@Override
	protected BlockStateContainer createBlockState() {
		
		return new BlockStateContainer(this, FACING);
	}
	
	@Override
	public void addCollisionBoxToList(IBlockState state, World worldIn, BlockPos pos, AxisAlignedBB aabb, List<AxisAlignedBB> collidingBoxes, @Nullable Entity entityIn, boolean wat) {
        
    	addCollisionBoxToList(pos, aabb, collidingBoxes, BASE_AABB);
    }
	
    @Override
    public void onEntityCollision(World world, BlockPos pos, IBlockState state, Entity entity) {
    	
    	TileEntityRFC tileRFC = (TileEntityRFC)world.getTileEntity(pos);
    	if (UpgradeHelper.getUpgrade(tileRFC, StringLibs.TAG_MOB) == null)
    		return;
    	
    	if (!(entity instanceof EntityLivingBase) || entity instanceof EntityPlayer)
    		return;
    	
    	EntityLivingBase elb = (EntityLivingBase)entity;
    	if (!elb.isNonBoss() || (elb.isChild() && !(elb instanceof EntityZombie)))
    		return;
    	
//    	ResourceLocation res = EntityList.getKey(elb);
    	for (int i = 0; i < tileRFC.getInventory().getSlots(); i++) {
    		ItemStack folder = tileRFC.getInventory().getTrueStackInSlot(i);
    		if (!folder.isEmpty() && folder.getItem() == RFCItems.folder) {
    			Object obj = ItemFolder.getObject(folder);
    			if (folder.getItemDamage() == 3 && obj != null) {
    				if (obj.equals(entity.getClass())) {
    					MobUtils.dropMobEquips(world, elb);
    					elb.setDead();
    					ItemFolder.add(folder, 1);
    					break;
    				}
    			}
    		}
    	}
    }
	
    @Override
	public void onBlockClicked(World world, BlockPos pos, EntityPlayer player) {
		
		TileEntity tile = world.getTileEntity(pos);
		if (!world.isRemote && !player.capabilities.isCreativeMode) {
			if (tile instanceof TileEntityRFC)
				leftClick(tile, player);
		}
	}
	
	@Override
	public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
    	
		if (hand == EnumHand.MAIN_HAND) {
			TileEntity tile = world.getTileEntity(pos);
	    	if (tile instanceof TileEntityRFC)
	    		rightClick(tile, player, facing, hitX, hitY, hitZ);
	    	
	    	return true;
		}
        return false;
    }
	
	@Override
	public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase entity, ItemStack stack) {
		
		world.setBlockState(pos, state.withProperty(FACING, entity.getHorizontalFacing().getOpposite()), 2);
		TileEntity tile = world.getTileEntity(pos);
		if (tile != null && tile instanceof TileEntityRFC) {
			if (stack.hasTagCompound())
				((TileEntityRFC)tile).readInv(stack.getTagCompound());
		}
	}
	
	@Override
	public IBlockState getStateFromMeta(int meta) {
		
		return getDefaultState().withProperty(FACING, EnumFacing.byHorizontalIndex(meta));
	}
	
	@Override
	public int getMetaFromState(IBlockState state) {
		
		return state.getValue(FACING).getHorizontalIndex();
	}
	
	@Override
    public boolean removedByPlayer(IBlockState state, World world, BlockPos pos, EntityPlayer player, boolean willHarvest) {
    	
    	if (player.capabilities.isCreativeMode && !world.isRemote)
    		this.harvestBlock(world, player, pos, state, world.getTileEntity(pos), player.getActiveItemStack());

    	return willHarvest || super.removedByPlayer(state, world, pos, player, false);
    }
	
	@Override
	public void harvestBlock(World world, EntityPlayer player, BlockPos pos, IBlockState state, TileEntity tile, ItemStack stack) {

		super.harvestBlock(world, player, pos, state, tile, stack);
		world.setBlockToAir(pos);
	}
	
	@Override
	public void breakBlock(World world, BlockPos pos, IBlockState state) {
		
		TileEntity tile = world.getTileEntity(pos);
		if (tile instanceof TileEntityRFC) {
			ItemStack upgrade = UpgradeHelper.stackTest((TileEntityRFC)tile);
			if (!upgrade.isEmpty() && upgrade.getItemDamage() != ItemUpgrades.UpgradeType.LIFE.ordinal()) {
				if (upgrade.getCount() == 0)
					upgrade.setCount(1);
				InventoryHelper.spawnItemStack(world, pos.getX(), pos.getY(), pos.getZ(), upgrade);
			}
		}
		super.breakBlock(world, pos, state);
	}
	
	@Override
	public void getDrops(NonNullList<ItemStack> drops, IBlockAccess world, BlockPos pos, IBlockState state, int fortune) {
		
		ItemStack s = new ItemStack(this);
		TileEntity tile = world.getTileEntity(pos);
		if (!(tile instanceof TileEntityRFC)) return;
		
		NBTTagCompound tag = new NBTTagCompound();
		((TileEntityRFC)tile).writeInv(tag, true);
		if (!tag.isEmpty()) {
			s.setTagCompound(tag);
		}
		drops.add(s);
		return;
	}

	@Override
	public TileEntity createNewTileEntity(World world, int meta) {

		return new TileEntityRFC();
	}

	@Override
	public void leftClick(TileEntity tile, EntityPlayer player) {
		
		if (player.capabilities.isCreativeMode)
			return;
		
		TileEntityRFC tileRFC = (TileEntityRFC)tile;
		
		if (tileRFC.isCabinetLocked()) {
			if (!tileRFC.getCabinetOwner().equals(player.getUniqueID())) {
				if (!tileRFC.hasKeyCopy(player, tileRFC.getCabinetOwner()))
					return;
			}
		}
		if (player.isSneaking() && !player.getHeldItem(EnumHand.MAIN_HAND).isEmpty() && player.getHeldItem(EnumHand.MAIN_HAND).getItem() == RFCItems.magnifyingGlass) {
			if (!tileRFC.getWorld().isRemote) {
				UpgradeHelper.removeUpgrade(player, tileRFC);
			}
			tileRFC.markBlockForUpdate();
			return;
		}
		if (UpgradeHelper.getUpgrade(tileRFC, StringLibs.TAG_CRAFT) == null) {
			StorageUtils.extractStackManually(tileRFC, player, player.isSneaking());
			return;
		} else {
			ItemStack toCraft = tileRFC.getFilter().copy();
			if (!tileRFC.getFilter().isEmpty() && toCraft.isItemDamaged())
				toCraft.setItemDamage(0);
				
			if (AutocraftingUtils.canCraft(tileRFC.getFilter(), tileRFC)) {
				ItemStack stack = toCraft;
				stack.setCount(AutocraftingUtils.getOutputSize());
				if (!UpgradeHelper.isCreative(tileRFC))
					AutocraftingUtils.doCraft(tileRFC.getFilter(), tileRFC.getInventory());
				ItemHandlerHelper.giveItemToPlayer(player, stack);
			}
		}
	}

	@Override
	public void rightClick(TileEntity tile, EntityPlayer player, EnumFacing side, float hitX, float hitY, float hitZ) {

		TileEntityRFC tileRFC = (TileEntityRFC)tile;
		ItemStack stack = player.getHeldItemMainhand();
		
		if (tileRFC.isCabinetLocked()) {
			if (!tileRFC.getCabinetOwner().equals(player.getUniqueID())) {
				if (!tileRFC.hasKeyCopy(player, tileRFC.getCabinetOwner()))
					return;
			}
		}
		if (tileRFC.calcLastClick(player))
			StorageUtils.addAllStacksManually(tileRFC, player);

		if (!player.isSneaking() && !stack.isEmpty()) {
			if (stack.getItem() instanceof ItemKeys) {
				if (!tileRFC.isCabinetLocked()) {
					if (stack.getItemDamage() == 0)
						tileRFC.setOwner(player.getUniqueID());
				}
				else {
					if (tileRFC.getCabinetOwner().equals(player.getUniqueID()) && stack.getItemDamage() == 0) {
						tileRFC.setOwner(null);
						return;
					}
					if (tileRFC.getCabinetOwner().equals(player.getUniqueID()) && stack.getItemDamage() == 1) {
						if (!stack.hasTagCompound() || (stack.hasTagCompound() && !stack.getTagCompound().hasKey(StringLibs.RFC_COPY))) {
							NBTUtils.setString(stack, StringLibs.RFC_COPY, player.getUniqueID().toString());
							NBTUtils.setString(stack, StringLibs.RFC_FALLBACK, player.getDisplayNameString());
						}
					}
				}
				return;
			}
			if (stack.getItem() instanceof IFolder && tileRFC.isOpen) {
				if (UpgradeHelper.getUpgrade(tileRFC, StringLibs.TAG_ENDER) != null) {
					if (stack.getItem() == RFCItems.folder && stack.getItemDamage() == FolderType.ENDER.ordinal())
						player.setHeldItem(EnumHand.MAIN_HAND, ItemStack.EMPTY);
					return;
				}
				if (stack.getItemDamage() == FolderType.FLUID.ordinal() && UpgradeHelper.getUpgrade(tileRFC, StringLibs.TAG_FLUID) != null) {
					for (int i = 0; i < tileRFC.getInventory().getSlots(); i++) {
						ItemStack tileStack = tileRFC.getInventory().getTrueStackInSlot(i);
						if (tileStack.isEmpty()) {
							tileRFC.getInventory().setStackInSlot(i, stack);
							player.setHeldItem(EnumHand.MAIN_HAND, ItemStack.EMPTY);
							tileRFC.markBlockForUpdate();
							break;
						}
					}
					return;
				}
				else if (!(stack.getItem() == RFCItems.folder && stack.getItemDamage() == 1) && !tileRFC.getWorld().isRemote) {
					if (UpgradeHelper.getUpgrade(tileRFC, StringLibs.TAG_FLUID) != null && !FluidUtils.canAcceptFluidContainer(stack))
						return;

					for (int i = 0; i < tileRFC.getInventory().getSlots(); i++) {
						ItemStack tileStack = tileRFC.getInventory().getTrueStackInSlot(i);
						if (tileStack.isEmpty()) {
							tileRFC.getInventory().setStackInSlot(i, stack);
							player.setHeldItem(EnumHand.MAIN_HAND, ItemStack.EMPTY);
							tileRFC.markBlockForUpdate();
							break;
						}
					}
				}
				return;
			}
			if (stack.getItem() instanceof IUpgrades) {
				if (!tileRFC.getWorld().isRemote) {
					UpgradeHelper.setUpgrade(player, tileRFC, stack);
				}
				tileRFC.markBlockForUpdate();
				return;
			} else {
				StorageUtils.addStackManually(tileRFC, player, stack);
				return;
			}
		}
		if (!player.isSneaking() && stack.isEmpty()) {	
			if (!tileRFC.getWorld().isRemote) {
				tileRFC.isOpen = !tileRFC.isOpen;
				tileRFC.markDirty();
			}
			tileRFC.markBlockForUpdate();
		}
		if (player.isSneaking() && stack.isEmpty() && tileRFC.isOpen) {		
			if (UpgradeHelper.getUpgrade(tileRFC, StringLibs.TAG_ENDER) != null) {
				EnderUtils.extractEnderFolder(tileRFC, player);
				return;
			}
			StorageUtils.folderExtract(tileRFC, player, side, hitX, hitY, hitZ);
		}
	}
	
	@Override
	@SideOnly(Side.CLIENT)
	public boolean shouldSideBeRendered(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing side) {
		
		return false;
	}
	
	@Override
	public boolean isBlockNormalCube(IBlockState state) {
		
		return false;
	}
	
	@Override
	public boolean isOpaqueCube(IBlockState state) {
		
		return false;
	}
	
	@Override
    public boolean isFullCube(IBlockState state) {
		
        return false;
    }
	
	@Override
    public EnumBlockRenderType getRenderType(IBlockState state) {
		
        return EnumBlockRenderType.ENTITYBLOCK_ANIMATED;
    }
	
	@Override
    public float getPlayerRelativeBlockHardness(IBlockState state, EntityPlayer player, World world, BlockPos pos) {
		
		TileEntityRFC tileRFC = (TileEntityRFC)world.getTileEntity(pos);
		if (tileRFC != null && tileRFC.isCabinetLocked()) {
			if (!tileRFC.getCabinetOwner().equals(player.getUniqueID()))
				return -1.0F;
		}
		return ForgeHooks.blockStrength(state, player, world, pos);
	}
	
	// copied from vanilla furnace
	@Override
    @SuppressWarnings("incomplete-switch")
    public void randomDisplayTick(IBlockState stateIn, World worldIn, BlockPos pos, Random rand) {
    	
		TileEntity tile = worldIn.getTileEntity(pos);
		if (!(tile instanceof TileEntityRFC)) return;
		
        if (SmeltingUtils.isSmelting((TileEntityRFC)tile)) {
            EnumFacing enumfacing = (EnumFacing)stateIn.getValue(FACING);
            double d0 = (double)pos.getX() + 0.5D;
            double d1 = (double)pos.getY() + rand.nextDouble() * 6.0D / 16.0D;
            double d2 = (double)pos.getZ() + 0.5D;
            double d3 = 0.52D;
            double d4 = rand.nextDouble() * 0.6D - 0.3D;

            if (rand.nextDouble() < 0.1D)
                worldIn.playSound((double)pos.getX() + 0.5D, (double)pos.getY(), (double)pos.getZ() + 0.5D, SoundEvents.BLOCK_FURNACE_FIRE_CRACKLE, SoundCategory.BLOCKS, 1.0F, 1.0F, false);

            switch (enumfacing) {
                case WEST:
                    worldIn.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, d0 - 0.52D, d1, d2 + d4, 0.0D, 0.0D, 0.0D);
                    worldIn.spawnParticle(EnumParticleTypes.FLAME, d0 - 0.52D, d1, d2 + d4, 0.0D, 0.0D, 0.0D);
                    break;
                case EAST:
                    worldIn.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, d0 + 0.52D, d1, d2 + d4, 0.0D, 0.0D, 0.0D);
                    worldIn.spawnParticle(EnumParticleTypes.FLAME, d0 + 0.52D, d1, d2 + d4, 0.0D, 0.0D, 0.0D);
                    break;
                case NORTH:
                    worldIn.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, d0 + d4, d1, d2 - 0.52D, 0.0D, 0.0D, 0.0D);
                    worldIn.spawnParticle(EnumParticleTypes.FLAME, d0 + d4, d1, d2 - 0.52D, 0.0D, 0.0D, 0.0D);
                    break;
                case SOUTH:
                    worldIn.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, d0 + d4, d1, d2 + 0.52D, 0.0D, 0.0D, 0.0D);
                    worldIn.spawnParticle(EnumParticleTypes.FLAME, d0 + d4, d1, d2 + 0.52D, 0.0D, 0.0D, 0.0D);
            }
        }
    }
} @Optional.Interface(iface = "com.jaquadro.minecraft.storagedrawers.api.storage.IDrawerGroup", modid = RealFilingCabinet.STORAGEDRAWERS, striprefs = true)
public class TileEntityRFC extends TileFilingCabinet implements ITickable, ILockableCabinet, IDrawerGroup {

	private InventoryRFC inv = new InventoryRFC(this, 8);
	private FluidRFC fluidinv = new FluidRFC(this);
	
	private UUID owner;
	
	// MISC variables
	private long lastClickTime;
	private UUID lastClickUUID;
	
	// NBT variables
	private int rfcHash = -1;
	public boolean isCreative = false;
	public String upgrades = "";
	public List<int[]> smeltingJobs = Lists.newArrayList();
	public int fuelTime = 0;
	public ItemStack uncraftableItem = ItemStack.EMPTY;
	
	// Rendering variables
	public static final float offsetSpeed = 0.1F;
	public boolean isOpen = false;

	@Override
	public void update() {
		
		if (isOpen) {
			offset -= offsetSpeed;
			if (offset <= -0.75F)
				offset = -0.75F;
		} else {
			offset += offsetSpeed;
			if (offset >= 0.05F)
				offset = 0.05F;
		}
		if (SmeltingUtils.canSmelt(this)) {
//			if (!world.isRemote) {
				SmeltingUtils.incrementSmeltTime(this);
				if (getWorld().getTotalWorldTime() % 40 == 0) {
					SmeltingUtils.createSmeltingJob(this);
					this.markBlockForUpdate();
				}
//			}
			return;
		}
		if (UpgradeHelper.getUpgrade(this, StringLibs.TAG_LIFE) != null) {
			if (!world.isRemote) {
				EntityCabinet cabinet = new EntityCabinet(world);
				IBlockState state = world.getBlockState(getPos());
				float angle = state.getActualState(world, pos).getValue(BlockHorizontal.FACING).getHorizontalAngle();
				cabinet.setPosition(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5);
				cabinet.setRotationYawHead(angle);
				
				for (int i = 0; i < this.getInventory().getSlots(); i++) {
					ItemStack folder = this.getInventory().getTrueStackInSlot(i);
					if (folder != null) {
						cabinet.setInventory(i, folder.copy());
					}
				}
				if (this.isCabinetLocked()) {
					UUID uuid = this.getCabinetOwner();
					cabinet.setOwnerId(uuid);
				} else
					cabinet.homePos = getPos().toLong();
				
				if (!cabinet.isLegit())
					cabinet.setLegit();
				
				world.spawnEntity(cabinet);
			}
			world.setBlockToAir(getPos());
		}
	}
	
	@Override
    public NBTTagCompound getUpdateTag() {
		
		return writeToNBT(new NBTTagCompound());
    }
	
	@Nullable
	@Override
	public SPacketUpdateTileEntity getUpdatePacket() {
		
		NBTTagCompound nbtTag = new NBTTagCompound();
		this.writeCustomNBT(nbtTag);
		
		return new SPacketUpdateTileEntity(getPos(), 1, nbtTag);
	}

	@Override
	public void writeCustomNBT(NBTTagCompound tag) {
		
		tag.setTag("inventory", inv.serializeNBT());
		tag.setBoolean("isOpen", this.isOpen);
		tag.setBoolean(StringLibs.TAG_CREATIVE, this.isCreative);
		tag.setTag(StringLibs.RFC_CRAFTABLE, uncraftableItem.serializeNBT());
		
		if (owner != null)
			tag.setString("Own", owner.toString());
		if (rfcHash != -1)
			tag.setInteger(StringLibs.RFC_HASH, rfcHash);
		
		tag.setString(StringLibs.RFC_UPGRADE, upgrades);
		
		SmeltingUtils.writeSmeltNBT(this, tag);
	}
	
	@Override
	public void readCustomNBT(NBTTagCompound tag) {
		
		inv.deserializeNBT(tag.getCompoundTag("inventory"));
		this.isOpen = tag.getBoolean("isOpen");
		this.isCreative = tag.getBoolean(StringLibs.TAG_CREATIVE);
		if (tag.hasKey(StringLibs.RFC_CRAFTABLE))
			this.uncraftableItem = new ItemStack((NBTTagCompound) tag.getTag(StringLibs.RFC_CRAFTABLE));
		
		this.owner = null;
		if (tag.hasKey("Own"))
			owner = UUID.fromString(tag.getString("Own"));
		if (tag.hasKey(StringLibs.RFC_HASH))
			rfcHash = tag.getInteger(StringLibs.RFC_HASH);
		upgrades = tag.getString(StringLibs.RFC_UPGRADE);
		
		SmeltingUtils.readSmeltNBT(this, tag);
	}
	
	public void readInv(NBTTagCompound nbt) {
		
		NBTTagList invList = nbt.getTagList("inventory", 10);
		for (int i = 0; i < invList.tagCount(); i++) {
			NBTTagCompound itemTag = invList.getCompoundTagAt(i);
			int slot = itemTag.getByte("Slot");
			if (slot >= 0 && slot < inv.getSlots())
				inv.getStacks().set(slot, new ItemStack(itemTag));
		}
	}
	
	public void writeInv(NBTTagCompound nbt, boolean toItem) {
		
		boolean write = false;
		NBTTagList invList = new NBTTagList();
		for (int i = 0; i < inv.getSlots(); i++) {
			if (!inv.getTrueStackInSlot(i).isEmpty()) {
				if (toItem)
					write = true;
				NBTTagCompound itemTag = new NBTTagCompound();
				itemTag.setByte("Slot", (byte)i);
				inv.getTrueStackInSlot(i).writeToNBT(itemTag);
				invList.appendTag(itemTag);
			}
		}
		if (!toItem || write)
			nbt.setTag("inventory", invList);
	}
	
	public InventoryRFC getInventory() {
		
		return inv;
	}
	
	public IFluidHandler getFluidInventory() {
		
		return fluidinv;
	}
	
	public boolean calcLastClick(EntityPlayer player) {
		
		boolean bool = false;
		
		if (getWorld().getTotalWorldTime() - lastClickTime < 10 && player.getPersistentID().equals(lastClickUUID)) {
			bool = true;
		}
		lastClickTime = getWorld().getTotalWorldTime();
		lastClickUUID = player.getPersistentID();
		
		return bool;
	}
	
	public boolean hasItemFrame() {
		
		AxisAlignedBB aabb = new AxisAlignedBB(pos.add(0, 1, 0), pos.add(1, 2, 1));
		List<EntityItemFrame> frames = this.getWorld().getEntitiesWithinAABB(EntityItemFrame.class, aabb);
		for (EntityItemFrame frame : frames) {
			EnumFacing orientation = frame.getAdjustedHorizontalFacing();
			IBlockState state = getWorld().getBlockState(getPos());
			EnumFacing rfcOrientation = (EnumFacing)state.getValue(BlockRFC.FACING);
			
			return frame != null && orientation == rfcOrientation;
		}
		return false;
	}
	
	public ItemStack getFilter() {
		
		AxisAlignedBB aabb = new AxisAlignedBB(pos.add(0, 1, 0), pos.add(1, 2, 1));
		List<EntityItemFrame> frames = this.getWorld().getEntitiesWithinAABB(EntityItemFrame.class, aabb);
		for (EntityItemFrame frame : frames) {
			EnumFacing orientation = frame.getAdjustedHorizontalFacing();
			IBlockState state = getWorld().getBlockState(getPos());
			EnumFacing rfcOrientation = (EnumFacing)state.getValue(BlockRFC.FACING);
			if (frame != null && !frame.getDisplayedItem().isEmpty() && (orientation == rfcOrientation)) {
				if (frame.getDisplayedItem().getItem() == RFCItems.filter) {
					int rotation = frame.getRotation();
					return inv.getStackFromFolder(rotation);
				}
				return frame.getDisplayedItem();
			}
		}
		return ItemStack.EMPTY;
	}
	
	@Override
	public boolean hasCapability(@Nonnull Capability<?> cap, EnumFacing side) {
		
		if (cap == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY && UpgradeHelper.getUpgrade(this, StringLibs.TAG_FLUID) != null)
			return cap == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY;
		if (cap == DRAWER_GROUP_CAPABILITY && !UpgradeHelper.hasUpgrade(this))
			return cap == DRAWER_GROUP_CAPABILITY;
		
		return cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY;
	}
	
	@Override
	public <T> T getCapability(@Nonnull Capability<T> cap, EnumFacing side) {
		
		if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
			return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.cast(inv);
		}
		if (cap == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)
			return CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY.cast(fluidinv);
		if (cap == DRAWER_GROUP_CAPABILITY)
			return (T) this;
		
		return super.getCapability(cap, side);
	}

	@Override
	public UUID getCabinetOwner() {

		return owner;
	}

	@Override
	public boolean setOwner(UUID owner) {

		if ((this.owner != null && !this.owner.equals(owner)) || (owner != null && !owner.equals(this.owner))) {
			this.owner = owner;
			
			if (getWorld() != null && !getWorld().isRemote) {
				markDirty();
				this.markBlockForUpdate();
			}
		}
		return true;
	}

	@Override
	public boolean isCabinetLocked() {

		return getCabinetOwner() != null;
	}
	
	public boolean hasKeyCopy(EntityPlayer player, UUID uuid) {
		
		for (int i = 0; i < player.inventory.mainInventory.size(); i++) {
			ItemStack keyCopy = player.inventory.mainInventory.get(i);
			if (keyCopy.isEmpty())
				continue;
			if (keyCopy.getItem() == RFCItems.keys && keyCopy.getItemDamage() == 1) {
				if (keyCopy.hasTagCompound() && keyCopy.getTagCompound().hasKey(StringLibs.RFC_COPY)) {
					return uuid.equals(UUID.fromString(NBTUtils.getString(keyCopy, StringLibs.RFC_COPY, "")));
				}
			}
		}
		return false;
	}
	
	public void setHash(TileEntity tile) {
		
		this.rfcHash = EnderUtils.createHash(this);
	}
	
	public int getHash(TileEntityRFC tile) {
		
		return this.rfcHash;
	}

/**
 * Storage Drawers Integration begins here
 */
	@CapabilityInject(IDrawerGroup.class)
	static Capability<IDrawerGroup> DRAWER_GROUP_CAPABILITY = null;
	
	@Override
	public int getDrawerCount() {

		return this.inv.getSlots();
	}

	@Optional.Method(modid = RealFilingCabinet.STORAGEDRAWERS)
	@Override
	public IDrawer getDrawer(int slot) {

		return new CabinetData(this, slot);
	}

	@Override
	public int[] getAccessibleDrawerSlots() {

		return new int[this.inv.getSlots()];
	}
} public class MobUpgradeHelper {

	private static Map<ItemStack, String> mobUpgrades = new HashMap<ItemStack, String>();
	
	/**
	 * Entity cabinet version of upgrades
	 * @param stack
	 * @param tag
	 */
	public static void registerMobUpgrade(ItemStack stack, String tag) {
		
		if (stack.getItem() instanceof IUpgrades && !tag.isEmpty())
			mobUpgrades.put(stack, tag);
		else throw new IllegalArgumentException("[RealFilingCabinet]: Register mob upgrades: ItemStack is not an instance of IUpgrades, or the string tag is empty");
	}
	
	public static boolean hasMobUpgrade(EntityCabinet entity) {
		
		return !entity.upgrades.isEmpty();
	}
	
	public static String getMobUpgrade(EntityCabinet entity, String str) {
		
		if (entity.upgrades.isEmpty())
			return null;
		
		String tag = entity.upgrades;
		if (tag.equals(str))
			return tag;
		
		return null;
	}
	
	public static void setUpgrade(EntityPlayer player, EntityCabinet cabinet, ItemStack upgrade) {
		
		if (cabinet.world.isRemote || !(upgrade.getItem() instanceof IUpgrades))
			return;
		
		if (hasMobUpgrade(cabinet))
			return;
		
		String key = stringTest(upgrade);
		if (key != null)
		{
			cabinet.upgrades = key;
			if (!player.capabilities.isCreativeMode)
				upgrade.shrink(1);
			if (key.equals(StringLibs.TAG_MOB))
				cabinet.setTextureState(1);
			else if (key.equals(StringLibs.TAG_FLUID))
				cabinet.setTextureState(2);
		}
	}
	
	public static void removeUpgrade(EntityPlayer player, EntityCabinet cabinet) {
		
		if (!hasMobUpgrade(cabinet))
			return;
		
		ItemStack upgrade = stackTest(cabinet);
		if (upgrade != null) {
			ItemStack newStack = new ItemStack(upgrade.getItem(), 1, upgrade.getItemDamage());
			ItemHandlerHelper.giveItemToPlayer(player, newStack);
		}
		cabinet.setTextureState(0);
		cabinet.upgrades = "";
	}
	
	private static String stringTest(ItemStack upgrade) {
		
		List<ItemStack> keys = new ArrayList(mobUpgrades.keySet());
		for (ItemStack is : keys) {
			if (ItemStack.areItemsEqual(upgrade, is)) {
				String str = mobUpgrades.get(is);
				return str;
			}
		}
		return null;
	}
	
	public static ItemStack stackTest(EntityCabinet cabinet) {
		
		String str = cabinet.upgrades;
		if (str.isEmpty())
			return null;
		
		for (Map.Entry<ItemStack, String> entry : mobUpgrades.entrySet())
		{
			String value = entry.getValue();
			if (value.equals(str))
				return entry.getKey();
		}
		return null;
	}
} public class ResourceUpgradeHelper {

	private static final Map<ResourceLocation, String> upgradeTextures = new HashMap<ResourceLocation, String>();
	private static final Map<ResourceLocation, String> upgradeMobTextures = new HashMap<ResourceLocation, String>();
	
	private static final ResourceLocation MOB_DEFAULT = new ResourceLocation(RealFilingCabinet.MOD_ID, "textures/entity/cabinettexture.png");
	private static final ResourceLocation DEFAULT = new ResourceLocation(RealFilingCabinet.MOD_ID, "textures/model/filingcabinet.png");
	private static final ResourceLocation HALLOWEEN = new ResourceLocation(RealFilingCabinet.MOD_ID, "textures/model/pumpkincabinet.png");
	private static final ResourceLocation CHRISTMAS = new ResourceLocation(RealFilingCabinet.MOD_ID, "textures/model/candycanecabinet.png");
	
	public static final ResourceLocation SMELTING = new ResourceLocation(RealFilingCabinet.MOD_ID, "textures/model/litfurnacecabinet.png");
	
	/**
	 * Put this in preinit phase before you've registered all your items/blocks. Registers your custom model texture for filing cabinet, along with the NBT tag you've mapped it to.
	 * Of course, if you don't use this method, it'll just use the default texture look when your upgrade has been applied to it.
	 * @param resourcelocation
	 * @param string
	 */
	public static void registerUpgradeResource(ResourceLocation resource, String str) {
		
		if (resource != null && !str.isEmpty())
			upgradeTextures.put(resource, str);
		else throw new IllegalArgumentException("[RealFilingCabinet]: Register upgrade resource: ResourceLocation is null, or the string tag is empty");
	}
	
	/**
	 * Entity version of resource registration for blocks.
	 * @param resource
	 * @param str
	 */
	public static void registerMobUpgradeResource(ResourceLocation resource, String str) {
		
		if (resource != null && !str.isEmpty())
			upgradeMobTextures.put(resource, str);
		else throw new IllegalArgumentException("[RealFilingCabinet]: Register upgrade mob resource: ResourceLocation is null, or the string tag is empty");
	}
	
	public static ResourceLocation getTexture(TileEntityRFC tile, String tag) {
		
		if (tag != null) {
			for (Map.Entry<ResourceLocation, String> entry : upgradeTextures.entrySet()) {
				String value = entry.getValue();
				if (value.equals(tag))
					return entry.getKey();
			}
		}
		return DEFAULT;
	}
	
	public static ResourceLocation getMobTexture(EntityCabinet cabinet, String tag) {
		
		if (tag != null) {
			for (Map.Entry<ResourceLocation, String> entry : upgradeMobTextures.entrySet()) {
				String value = entry.getValue();
				if (value.equals(tag))
					return entry.getKey();
			}
		}
		return MOB_DEFAULT;
	}
	
	public static ResourceLocation getDefault() {
		
		if (ConfigRFC.seasonalCabinets) {
			LocalDateTime current = LocalDateTime.now();
			if (current.getMonth() == Month.OCTOBER)
				return HALLOWEEN;
			if (current.getMonth() == Month.DECEMBER)
				return CHRISTMAS;
		}
		return DEFAULT;
	}
	
	public static ResourceLocation getMobDefault() {
		
		return MOB_DEFAULT;
	}
} public class StringLibs {

	// UPGRADES
	public static String RFC_UPGRADE = "RFC_upgrade";
	public static String TAG_CREATIVE = "TAG_creativeUpgrade";
	public static String TAG_ENDER = "TAG_enderUpgrade";
	public static String TAG_CRAFT = "TAG_craftingUpgrade";
	public static String TAG_OREDICT = "TAG_oredictUpgrade";
	public static String TAG_MOB = "TAG_mobUpgrade";
	public static String TAG_FLUID = "TAG_fluidUpgrade";
	public static String TAG_LIFE = "TAG_lifeUpgrade";
	public static String TAG_SMELT = "TAG_smeltingUpgrade";
	
	// ENDER FOLDER
	public static String RFC_SLOTINDEX = "RFC_slotindex";
	public static String RFC_TILEPOS = "RFC_tilepos";
	public static String RFC_DIM = "RFC_dim";
	public static String RFC_HASH = "RFC_enderhash";
	
	// UUID
	public static String RFC_OWNER = "Own";
	public static String RFC_COPY = "OwnCopy";
	public static String RFC_FALLBACK = "RFC_playername";
	
	// MISC
	public static String RFC_TAPED = "RFC_whiteoutTaped";
	public static String RFC_PLACEMODE = "RFC_placeMode";
	public static String RFC_IGNORENBT = "RFC_ignoreNBT";
	public static String RFC_CRAFTABLE = "RFC_isCraftable";
	
	// ENTITY
	public static String RFC_MOBUPGRADE = "RFC_mobUpgrade";
} public class TextHelper {

	private static final NavigableMap<Long, String> suffixes = new TreeMap();
	
	static {
		suffixes.put(1000L, "k");
		suffixes.put(1000000L, "M");
		suffixes.put(1000000000L, "b");
		suffixes.put(1000000000000L, "T");
		suffixes.put(1000000000000000L, "q");
	}
	
	public static String format(long value) {
		
		if (value == Long.MIN_VALUE) return format(Long.MIN_VALUE + 1);
		if (value < 0) return "-" + format(-value);
		if (value < 1000) return Long.toString(value);
		
		Entry<Long, String> e = suffixes.floorEntry(value);
		Long divideBy = e.getKey();
		String suffix = e.getValue();
		
		long truncated = value / (divideBy / 10);
		boolean hasDecimal = truncated < 100 && (truncated / 10d) != (truncated / 10);
		
		return hasDecimal ? (truncated / 10d) + suffix : (truncated / 10) + suffix;
	}
	
	// client only
	public static String localize(String str) {
		
		return I18n.format(str);
	}
	
	// server only
	public static String localizeCommands(String str) {
		
		return net.minecraft.util.text.translation.I18n.translateToLocalFormatted("commands." + RealFilingCabinet.MOD_ID + "." + str);
	}
	
	public static String folderStr(ItemStack folder) {
		
		if (!(folder.getItem() instanceof IFolder))
			return null;
		
		Object obj = ItemFolder.getObject(folder);
		if (obj != null) {
			return folder.getCapability(CapabilityProviderFolder.FOLDER_CAP, null).getDisplayName();
		}
		return null;
	}
} public class RFCBlocks {

	public static BlockRFC blockRFC;
	public static BlockAC blockAC;
	
	public static void init() {
		
		blockRFC = new BlockRFC();
		if (RealFilingCabinet.tcLoaded && ConfigRFC.tcIntegration)
			blockAC = new BlockAC();
	}
	
	@SideOnly(Side.CLIENT)
	public static void initModels() {

		ClientRegistry.bindTileEntitySpecialRenderer(TileEntityRFC.class, new RenderFilingCabinet());
		if (RealFilingCabinet.botaniaLoaded && ConfigRFC.botaniaIntegration)
			ClientRegistry.bindTileEntitySpecialRenderer(TileManaCabinet.class, new RenderManaCabinet());
		if (RealFilingCabinet.tcLoaded && ConfigRFC.tcIntegration)
			ClientRegistry.bindTileEntitySpecialRenderer(TileEntityAC.class, new RenderAspectCabinet());
	}
} public class RFCItems {

	public static ItemEmptyFolder emptyFolder;
	public static ItemFolder folder;
	public static ItemMagnifyingGlass magnifyingGlass;
	public static ItemWhiteoutTape whiteoutTape;
	public static ItemUpgrades upgrades;
	public static ItemFilter filter;
	public static ItemKeys keys;
	public static ItemDebugger debugger;
	public static ItemMysteryFolder mysteryFolder;
	public static ItemSuitcase suitcase;
	public static ItemEmptyDyedFolder emptyDyedFolder;
	public static ItemDyedFolder dyedFolder;
	public static ItemAutoFolder autoFolder;
	
	// Thaumcraft integration
	public static ItemAspectFolder aspectFolder;
	
	public static void init() {
		
		if (RealFilingCabinet.botaniaLoaded && ConfigRFC.botaniaIntegration)
			BotaniaRFC.initItem();
		
		emptyFolder = new ItemEmptyFolder();
		folder = new ItemFolder();
		magnifyingGlass = new ItemMagnifyingGlass();
		whiteoutTape = new ItemWhiteoutTape();
		upgrades = new ItemUpgrades();
		filter = new ItemFilter();
		keys = new ItemKeys();
		debugger = new ItemDebugger();
		mysteryFolder = new ItemMysteryFolder();
		suitcase = new ItemSuitcase();
		emptyDyedFolder = new ItemEmptyDyedFolder();
		dyedFolder = new ItemDyedFolder();
//		autoFolder = new ItemAutoFolder();
		
		if (RealFilingCabinet.tcLoaded && ConfigRFC.tcIntegration)
			aspectFolder = new ItemAspectFolder();
	}
} public class InventoryEntity extends ItemStackHandler {

	final EntityCabinet cabinet;
	
	public InventoryEntity(EntityCabinet cabinet, int size) {
		
		this.cabinet = cabinet;
		setSize(size);
	}
	
	@Override
	public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
		
        if (stack == null || stack.getCount() == 0)
            return null;

        validateSlotIndex(slot);

        if (simpleFolderMatch(stack) != -1) {
        	slot = simpleFolderMatch(stack);
        	if (!simulate) {
        		if (getStacks().get(slot).getItem() == RFCItems.folder && getStacks().get(slot).getItemDamage() == 2) {
        			int remSize = stack.getItemDamage();
        			int storedRem = ItemFolder.getRemSize(getStacks().get(slot));
        			
        			if (remSize == 0)
        				ItemFolder.insert(getStacks().get(slot), stack, simulate);
 //       				ItemFolder.add(getStacks().get(slot), 1);
        			
        			ItemFolder.addRem(getStacks().get(slot), stack.getMaxDamage() - stack.getItemDamage());
        			int newRem = ItemFolder.getRemSize(getStacks().get(slot));
        			
        			if (newRem >= stack.getMaxDamage()) {
        				ItemFolder.insert(getStacks().get(slot), stack, simulate);
 //       				ItemFolder.add(getStacks().get(slot), 1);
        				int newStoredRem = newRem - stack.getMaxDamage();
        				ItemFolder.setRemSize(getStacks().get(slot), newStoredRem);
        			}
        		}
        		else
        			ItemFolder.insert(stacks.get(slot), stack, simulate);
//        			ItemFolder.add(stacks.get(slot), stack.getCount());
        	}
        	return null;
        }
        return stack;
	}
	
	public ItemStack getStackFromFolder(int slot) {
		
		ItemStack folder = getStackInSlot(slot);
		if (ItemFolder.getObject(folder) == null)
			return ItemStack.EMPTY;
		
		if (folder != null && folder.getItem() instanceof IFolder) {
			if (ItemFolder.getObject(folder) instanceof ItemStack) {
				ItemStack stack = (ItemStack)ItemFolder.getObject(folder);
				if (!stack.isEmpty())
					return stack.copy();
			}
		}
		return ItemStack.EMPTY;
	}
	
	public boolean canInsertItem(ItemStack stack) {
		
		return simpleFolderMatch(stack) != -1;
	}
	
	public boolean canInsertMob(EntityLivingBase elb, boolean doThing) {
		
		if (elb instanceof EntityPlayer)
			return false;
		
		if (!elb.isNonBoss() || elb.isChild())
			return false;
		
		if (elb instanceof EntityCabinet)
			return false;
		
		if (elb instanceof IEntityOwnable && ((IEntityOwnable)elb).getOwner() != null)
			return false;
		
		String entityblacklist = elb.getClass().getSimpleName();
		for (String toBlacklist : ConfigRFC.mobFolderBlacklist) {
			if (toBlacklist.contains(entityblacklist))
				return false;
		}
		
		String entityName = EntityList.getKey(elb).toString();
    	for (int i = 0; i < getSlots(); i++) {
    		ItemStack folder = getStackInSlot(i);
    		if (folder != null && folder.getItem() == RFCItems.folder) {
    			if (folder.getItemDamage() == 3 && ItemFolder.getObject(folder) != null) {
    				if (ItemFolder.getObject(folder).equals(entityName)) {
    					if (doThing)
    						ItemFolder.add(folder, 1);

    					return true;
    				}
    			}
    		}
    	}
		return false;
	}
	
	public int simpleFolderMatch(ItemStack stack) {
		
		if (stack.isEmpty())
			return -1;
		
		for (int i = 0; i < getSlots(); i++) {
			ItemStack loopinv = getStackFromFolder(i);
			if (!loopinv.isEmpty() && getStackInSlot(i).getItemDamage() == 2 && stack.getItem() == loopinv.getItem()) {
				if (stack.hasTagCompound() && NBTUtils.getBoolean(getStackInSlot(i), StringLibs.RFC_IGNORENBT, false))
					return i;
				else if (!stack.hasTagCompound())
					return i;
			}
			if (!loopinv.isEmpty() && (getStackInSlot(i).getItemDamage() == 5 && ItemStack.areItemStackTagsEqual(stack, loopinv)))
				return i;
			if (!loopinv.isEmpty() && ((getStackInSlot(i).getItemDamage() != 5 && getStackInSlot(i).getItemDamage() != 2) && StorageUtils.simpleMatch(stack, loopinv)))
				return i;
		}
		return -1;
	}
	
	public NonNullList<ItemStack> getStacks() {
		
		return stacks;
	}
}
import javax.annotation.Nullable;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.EntityAgeable;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIFollowOwner;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAISwimming;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.passive.EntityTameable;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.network.datasync.DataParameter;
import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.network.datasync.EntityDataManager;
import net.minecraft.pathfinding.PathNavigate;
import net.minecraft.pathfinding.PathNodeType;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.items.ItemHandlerHelper;
import com.bafomdad.realfilingcabinet.RealFilingCabinet;
import com.bafomdad.realfilingcabinet.api.IUpgrades;
import com.bafomdad.realfilingcabinet.blocks.BlockRFC;
import com.bafomdad.realfilingcabinet.blocks.tiles.TileEntityRFC;
import com.bafomdad.realfilingcabinet.entity.ai.*;
import com.bafomdad.realfilingcabinet.helpers.MobUpgradeHelper;
import com.bafomdad.realfilingcabinet.helpers.ResourceUpgradeHelper;
import com.bafomdad.realfilingcabinet.helpers.StringLibs;
import com.bafomdad.realfilingcabinet.helpers.TextHelper;
import com.bafomdad.realfilingcabinet.init.RFCBlocks;
import com.bafomdad.realfilingcabinet.init.RFCItems;
import com.bafomdad.realfilingcabinet.inventory.InventoryEntity;
		if (source.getTrueSource() == null) {
			setDead();
			return true;
		}
		if (getPosition().getY() < 0) {
			BlockPos toHome = BlockPos.fromLong(homePos);
			if (!world.isRemote)
				this.setPosition(toHome.getX(), toHome.getY(), toHome.getZ());
			return false;
		}
		this.setTile(source);
		return true;
	}
	
	@Override
	public boolean processInteract(EntityPlayer player, EnumHand hand) {
		
		ItemStack stack = player.getHeldItemMainhand();
		if (hand == EnumHand.MAIN_HAND && !this.world.isRemote) {
			if (!stack.isEmpty() && stack.getItem() instanceof IUpgrades) {
				MobUpgradeHelper.setUpgrade(player, this, stack);
				return true;
			}
		}
		return false;
	}
	
	@Override
	public void readEntityFromNBT(NBTTagCompound tag) {
		
		super.readEntityFromNBT(tag);
		
        NBTTagList nbttaglist = tag.getTagList("Inventory", 10);
        for (int i = 0; i < nbttaglist.tagCount(); ++i){
        	ItemStack itemstack = new ItemStack(nbttaglist.getCompoundTagAt(i));
            if (!itemstack.isEmpty())
                this.inventory.setStackInSlot(i, itemstack.copy());
        }
        isRealEntity = tag.getBoolean("legitEntity");
        upgrades = tag.getString(StringLibs.RFC_MOBUPGRADE);
        homePos = tag.getLong("homePos");
        this.setTextureState(tag.getInteger("varTex"));
	}
	
	@Override
	public void writeEntityToNBT(NBTTagCompound tag) {
		
		super.writeEntityToNBT(tag);
		
		NBTTagList tagList = new NBTTagList();
        for (int i = 0; i < this.inventory.getSlots(); ++i){
            ItemStack itemstack = this.inventory.getStackInSlot(i);
            if (!itemstack.isEmpty())
                tagList.appendTag(itemstack.writeToNBT(new NBTTagCompound()));
        }
        tag.setTag("Inventory", tagList);
        tag.setBoolean("legitEntity", isRealEntity);
        tag.setString(StringLibs.RFC_MOBUPGRADE, upgrades);
        tag.setLong("homePos", homePos);
        tag.setInteger("varTex", this.getTextureState());
	}

	@Override
	public EntityAgeable createChild(EntityAgeable ageable) {

		return null;
	}
	
	public InventoryEntity getInventory() {
		
		return inventory;
	}
	
	public void setInventory(int slot, ItemStack stack) {
		
		if (inventory == null)
			return;
		
		this.inventory.setStackInSlot(slot, stack);
	}
	
	public void setInventory(TileEntityRFC tile, int slot, ItemStack stack) {
		
		tile.getInventory().setStackInSlot(slot, stack);
	}
	
	public void setYay(boolean bool) {
		
		this.dataManager.set(YAY, Boolean.valueOf(bool));
	}
	
	public boolean isYaying() {
		
		return (Boolean)this.dataManager.get(YAY).booleanValue();
	}
	
	public void setTextureState(int val) {
		
		this.dataManager.set(STATE, Integer.valueOf(val));
	}
	
	public int getTextureState() {
		
		return (Integer)this.dataManager.get(STATE).intValue();
	}
	
	public boolean isLegit() {
		
		return this.isRealEntity;
	}
	
	public void setLegit() {
		
		this.isRealEntity = true;
	}
	
	private void setTile(DamageSource source) {
		
		if (source.getTrueSource() instanceof EntityPlayer) {
			EntityPlayer player = (EntityPlayer)source.getTrueSource();
			IBlockState state = RFCBlocks.blockRFC.getDefaultState().withProperty(BlockRFC.FACING, this.getHorizontalFacing().getOpposite());