package openmods.tileentity;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
import openmods.api.IInventoryCallback;
import openmods.block.OpenBlock;
import openmods.geometry.Orientation;
import openmods.inventory.GenericInventory;
import openmods.network.DimCoord;
import openmods.network.rpc.IRpcTarget;
import openmods.network.rpc.IRpcTargetProvider;
import openmods.network.rpc.RpcCallDispatcher;
import openmods.network.rpc.targets.TileEntityRpcTarget;
import openmods.network.senders.IPacketSender;
import openmods.reflection.TypeUtils;
import openmods.utils.Coord;
public abstract class OpenTileEntity extends TileEntity implements IRpcTargetProvider {
private boolean isUsedForClientInventoryRendering = false;
/** Place for TE specific setup. Called once upon creation */
public void setup() {}
public Coord getPosition() {
return new Coord(xCoord, yCoord, zCoord);
}
public DimCoord getDimCoords() {
return new DimCoord(worldObj.provider.dimensionId, xCoord, yCoord, zCoord);
}
public Orientation getOrientation() {
final Block block = getBlockType();
if (!(block instanceof OpenBlock)) return Orientation.XP_YP;
final OpenBlock openBlock = (OpenBlock)block;
if (isUsedForClientInventoryRendering) return openBlock.getInventoryRenderOrientation();
return openBlock.getOrientation(getBlockMetadata());
}
@SideOnly(Side.CLIENT)
public void prepareForInventoryRender(Block block, int metadata) {
if (this.worldObj != null) {
System.out.println("SEVERE PROGRAMMER ERROR! Inventory Render on World TileEntity. Expect hell!");
} // But of course, we continue, because YOLO.
isUsedForClientInventoryRendering = true;
this.blockType = block;
this.blockMetadata = metadata;
}
public boolean isAddedToWorld() {
return worldObj != null;
}
private TileEntity getTileEntity(int x, int y, int z) {
return (worldObj != null && worldObj.blockExists(x, y, z))? worldObj.getTileEntity(x, y, z) : null;
}
public TileEntity getTileInDirection(ForgeDirection direction) {
return getNeighbour(direction.offsetX, direction.offsetY, direction.offsetZ);
}
public TileEntity getNeighbour(int dx, int dy, int dz) {
return getTileEntity(xCoord + dx, yCoord + dy, zCoord + dz);
}
@Override
public String toString() {
return String.format("%s,%s,%s", xCoord, yCoord, zCoord);
}
public boolean isAirBlock(ForgeDirection direction) {
return worldObj != null
&& worldObj.isAirBlock(xCoord + direction.offsetX, yCoord
+ direction.offsetY, zCoord + direction.offsetZ);
}
public void sendBlockEvent(int event, int param) {
worldObj.addBlockEvent(xCoord, yCoord, zCoord, getBlockType(), event, param);
}
@Override
public boolean shouldRefresh(Block oldBlock, Block newBlock, int oldMeta, int newMeta, World world, int x, int y, int z) {
return oldBlock != newBlock;
}
public void openGui(Object instance, EntityPlayer player) {
player.openGui(instance, -1, worldObj, xCoord, yCoord, zCoord);
}
public AxisAlignedBB getBB() {
return AxisAlignedBB.getBoundingBox(xCoord, yCoord, zCoord, xCoord + 1, yCoord + 1, zCoord + 1);
}
public boolean isRenderedInInventory() {
return isUsedForClientInventoryRendering;
}
@Override
public IRpcTarget createRpcTarget() {
return new TileEntityRpcTarget(this);
}
public <T> T createProxy(final IPacketSender sender, Class<? extends T> mainIntf, Class<?>... extraIntf) {
TypeUtils.isInstance(this, mainIntf, extraIntf);
return RpcCallDispatcher.INSTANCE.createProxy(createRpcTarget(), sender, mainIntf, extraIntf);
}
public <T> T createClientRpcProxy(Class<? extends T> mainIntf, Class<?>... extraIntf) {
final IPacketSender sender = RpcCallDispatcher.INSTANCE.senders.client;
return createProxy(sender, mainIntf, extraIntf);
}
public <T> T createServerRpcProxy(Class<? extends T> mainIntf, Class<?>... extraIntf) {
final IPacketSender sender = RpcCallDispatcher.INSTANCE.senders.block.bind(getDimCoords());
return createProxy(sender, mainIntf, extraIntf);
}
public void markUpdated() {
worldObj.markTileEntityChunkModified(xCoord, yCoord, zCoord, this);
}
protected IInventoryCallback createInventoryCallback() {
return new IInventoryCallback() {
@Override
public void onInventoryChanged(IInventory inventory, int slotNumber) {
markUpdated();
}
};
}
protected GenericInventory registerInventoryCallback(GenericInventory inventory) {
return inventory.addCallback(createInventoryCallback());
}
public boolean isValid(EntityPlayer player) {
return (worldObj.getTileEntity(xCoord, yCoord, zCoord) == this) && (player.getDistanceSq(xCoord + 0.5, yCoord + 0.5, zCoord + 0.5) <= 64.0D);
}
}