package openblocks.common.tileentity; import com.google.common.base.Preconditions; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import java.util.List; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.AxisAlignedBB; import net.minecraftforge.common.util.ForgeDirection; import openblocks.common.item.ItemImaginary; import openblocks.common.item.ItemImaginationGlasses; import openmods.OpenMods; import openmods.api.ICustomPickItem; import openmods.tileentity.SimpleNetTileEntity; public class TileEntityImaginary extends SimpleNetTileEntity implements ICustomPickItem { public static final double PANEL_HEIGHT = 0.1; public enum Property { VISIBLE, SELECTABLE, SOLID } private enum CollisionType { BLOCK { @Override public ICollisionData createData() { return DUMMY; } }, PANEL { @Override public ICollisionData createData() { return new PanelData(); } }, STAIRS { @Override public ICollisionData createData() { return new StairsData(); } }; public abstract ICollisionData createData(); public final static CollisionType[] VALUES = values(); } public interface ICollisionData { public CollisionType getType(); public void readFromNBT(NBTTagCompound tag); public void writeToNBT(NBTTagCompound tag); public void addCollisions(int x, int y, int z, AxisAlignedBB region, List<AxisAlignedBB> result); public AxisAlignedBB getBlockBounds(); } public final static ICollisionData DUMMY = new ICollisionData() { @Override public void readFromNBT(NBTTagCompound tag) {} @Override public void writeToNBT(NBTTagCompound tag) {} @Override public CollisionType getType() { return CollisionType.BLOCK; } @Override public void addCollisions(int x, int y, int z, AxisAlignedBB region, List<AxisAlignedBB> result) { AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(x, y, z, x + 1, y + 1, z + 1); if (aabb != null && aabb.intersectsWith(region)) result.add(aabb); } @Override public AxisAlignedBB getBlockBounds() { return AxisAlignedBB.getBoundingBox(0, 0, 0, 1, 1, 1); } }; public static class PanelData implements ICollisionData { public float height; public PanelData() {} public PanelData(float height) { this.height = height; } @Override public void readFromNBT(NBTTagCompound tag) { height = tag.getFloat("PanelHeight"); } @Override public void writeToNBT(NBTTagCompound tag) { tag.setFloat("PanelHeight", height); } @Override public CollisionType getType() { return CollisionType.PANEL; } @Override public void addCollisions(int x, int y, int z, AxisAlignedBB region, List<AxisAlignedBB> result) { AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(x, y + height - PANEL_HEIGHT, z, x + 1, y + height, z + 1); if (aabb != null && aabb.intersectsWith(region)) result.add(aabb); } @Override public AxisAlignedBB getBlockBounds() { return AxisAlignedBB.getBoundingBox(0, height - PANEL_HEIGHT, 0, 1, height, 1); } } public static class StairsData implements ICollisionData { public float lowerPanelHeight; public float upperPanelHeight; public ForgeDirection orientation; public StairsData() {} public StairsData(float lowerPanelHeight, float upperPanelHeight, ForgeDirection orientation) { this.lowerPanelHeight = lowerPanelHeight; this.upperPanelHeight = upperPanelHeight; this.orientation = orientation; } @Override public void readFromNBT(NBTTagCompound tag) { lowerPanelHeight = tag.getFloat("LowerPanelHeight"); upperPanelHeight = tag.getFloat("UpperPanelHeight"); orientation = ForgeDirection.getOrientation(tag.getByte("Orientation")); } @Override public void writeToNBT(NBTTagCompound tag) { tag.setFloat("LowerPanelHeight", lowerPanelHeight); tag.setFloat("UpperPanelHeight", upperPanelHeight); tag.setByte("Orientation", (byte)orientation.ordinal()); } @Override public CollisionType getType() { return CollisionType.STAIRS; } @Override public void addCollisions(int x, int y, int z, AxisAlignedBB region, List<AxisAlignedBB> result) { AxisAlignedBB lower; AxisAlignedBB upper; final double lowerTop = y + lowerPanelHeight; final double lowerBottom = lowerTop - PANEL_HEIGHT; final double upperTop = y + upperPanelHeight; final double upperBottom = upperTop - PANEL_HEIGHT; switch (orientation) { case NORTH: lower = AxisAlignedBB.getBoundingBox(x, lowerBottom, z + 0.5, x + 1, lowerTop, z + 1.0); upper = AxisAlignedBB.getBoundingBox(x, upperBottom, z + 0.0, x + 1, upperTop, z + 0.5); break; case SOUTH: lower = AxisAlignedBB.getBoundingBox(x, lowerBottom, z + 0.0, x + 1, lowerTop, z + 0.5); upper = AxisAlignedBB.getBoundingBox(x, upperBottom, z + 0.5, x + 1, upperTop, z + 1.0); break; case WEST: lower = AxisAlignedBB.getBoundingBox(x + 0.5, lowerBottom, z, x + 1.0, lowerTop, z + 1); upper = AxisAlignedBB.getBoundingBox(x + 0.0, upperBottom, z, x + 0.5, upperTop, z + 1); break; case EAST: lower = AxisAlignedBB.getBoundingBox(x + 0.0, lowerBottom, z, x + 0.5, lowerTop, z + 1); upper = AxisAlignedBB.getBoundingBox(x + 0.5, upperBottom, z, x + 1.0, upperTop, z + 1); break; default: lower = upper = null; break; } if (lower != null && lower.intersectsWith(region)) result.add(lower); if (upper != null && upper.intersectsWith(region)) result.add(upper); } @Override public AxisAlignedBB getBlockBounds() { return AxisAlignedBB.getBoundingBox(0, lowerPanelHeight, 0, 1, upperPanelHeight, 1); } } @SideOnly(Side.CLIENT) public float visibility; public TileEntityImaginary() { collisionData = DUMMY; } public TileEntityImaginary(Integer color, boolean isInverted, ICollisionData collisionData) { Preconditions.checkNotNull(collisionData, "Bad idea! Rejected!"); this.color = color; this.isInverted = isInverted; this.collisionData = collisionData; } public Integer color; public boolean isInverted; public ICollisionData collisionData; @Override public void readFromNBT(NBTTagCompound tag) { super.readFromNBT(tag); color = tag.hasKey("Color")? tag.getInteger("Color") : null; isInverted = tag.getBoolean("IsInverted"); CollisionType type = CollisionType.VALUES[tag.getByte("Type")]; collisionData = type.createData(); collisionData.readFromNBT(tag); } @Override public void writeToNBT(NBTTagCompound tag) { super.writeToNBT(tag); if (color != null) tag.setInteger("Color", color); tag.setBoolean("IsInverted", isInverted); tag.setByte("Type", (byte)collisionData.getType().ordinal()); collisionData.writeToNBT(tag); } @Override public boolean canUpdate() { return false; } @Override public boolean shouldRenderInPass(int pass) { return pass == 1; } public boolean isPencil() { return color == null; } public boolean isInverted() { return isInverted; } public boolean is(Property what, EntityPlayer player) { if (what == Property.SOLID && isPencil()) return true; ItemStack helmet = player.inventory.armorItemInSlot(3); if (helmet == null) return isInverted(); Item item = helmet.getItem(); if (item instanceof ItemImaginationGlasses) return ((ItemImaginationGlasses)item).checkBlock(what, helmet, this); return isInverted(); } public boolean is(EntityPlayer player) { return player.getHeldItem() != null; } public boolean is(Property what, Entity e) { return (e instanceof EntityPlayer) && is(what, (EntityPlayer)e); } public boolean is(Property what) { EntityPlayer player = OpenMods.proxy.getThePlayer(); return player != null && is(what, player); } public void addCollisions(AxisAlignedBB region, List<AxisAlignedBB> result) { collisionData.addCollisions(xCoord, yCoord, zCoord, region, result); } public AxisAlignedBB getSelectionBox() { return collisionData.getBlockBounds().offset(xCoord, yCoord, zCoord); } public AxisAlignedBB getBlockBounds() { return collisionData.getBlockBounds(); } @Override public ItemStack getPickBlock() { int dmg = isPencil()? ItemImaginary.DAMAGE_PENCIL : ItemImaginary.DAMAGE_CRAYON; return ItemImaginary.setupValues(color, new ItemStack(getBlockType(), 1, dmg)); } }