package buildcraft.api.core;
import java.util.Map;
import java.util.UUID;
import com.google.common.base.Supplier;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.server.MinecraftServer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
/** Identifies an in world tile entity or movable entity. Feel free to extend this class if your tile entity contains
* multiple identifiable {@link IPowerConnection}. Just make sure to register it with
* {@link #registerType(String, Supplier)} to make loading work.
* <p>
* Created on 1 Jan 2016 by AlexIIL */
public abstract class Identifier {
private static Map<String, Supplier<Identifier>> registeredIdentifiers;
static {
registeredIdentifiers.put("mincraft:tile", new Supplier<Identifier>() {
@Override
public Identifier get() {
return new Tile(0, null);
}
});
registeredIdentifiers.put("mincraft:entity", new Supplier<Identifier>() {
@Override
public Identifier get() {
return new MovableEntity(0, null);
}
});
}
protected final int dimId;
public static void registerType(String type, Supplier<Identifier> constructor) {
if (constructor == null) throw new NullPointerException("constructor");
if (constructor.get() == null) throw new NullPointerException("constructor.get()");
registeredIdentifiers.put(type, constructor);
}
public static Identifier getFor(Object obj) {
if (obj == null) throw new NullPointerException("obj");
if (obj instanceof TileEntity) {
return Tile.create((TileEntity) obj);
}
if (obj instanceof Entity) {
return MovableEntity.create((Entity) obj);
}
if (obj instanceof NBTTagCompound) {
NBTTagCompound nbt = (NBTTagCompound) obj;
String type = nbt.getString("type");
if (!registeredIdentifiers.containsKey(type)) return null;
return registeredIdentifiers.get(type).get().load(nbt.getCompoundTag("data"));
}
throw new IllegalArgumentException("Unknown type " + obj.getClass());
}
public static NBTTagCompound save(Identifier ident) {
NBTTagCompound tag = new NBTTagCompound();
tag.setString("type", ident.typeId());
tag.setTag("data", ident.save());
return tag;
}
private Identifier(int dimId) {
this.dimId = dimId;
}
public abstract Object getByIdentifier(MinecraftServer server);
public abstract boolean isLoaded(MinecraftServer server);
protected abstract Identifier load(NBTTagCompound tag);
protected abstract NBTTagCompound save();
public abstract String typeId();
@SideOnly(Side.CLIENT)
public abstract Object getByIdentifierClient();
@SideOnly(Side.CLIENT)
public abstract boolean isLoadedClient();
public static class Tile extends Identifier {
private final BlockPos pos;
public static Tile create(TileEntity tile) {
if (tile.getWorld() == null) throw new NullPointerException("tile.getWorld() for the tile " + tile.getClass());
if (tile.getPos() == null) throw new NullPointerException("tile.getPos() for the tile " + tile.getClass());
return new Tile(tile.getWorld().provider.getDimensionId(), tile.getPos());
}
private Tile(int dimId, BlockPos pos) {
super(dimId);
this.pos = pos;
}
@Override
public Tile load(NBTTagCompound tag) {
int dimId = tag.getInteger("dimId");
int[] arr = tag.getIntArray("pos");
if (arr.length == 0) return null;
return new Tile(dimId, new BlockPos(arr[0], arr[1], arr[2]));
}
@Override
protected NBTTagCompound save() {
NBTTagCompound tag = new NBTTagCompound();
tag.setInteger("dimId", dimId);
tag.setIntArray("pos", new int[] { pos.getX(), pos.getY(), pos.getZ() });
return tag;
}
@Override
public String typeId() {
return "minecraft:tile";
}
@Override
public TileEntity getByIdentifier(MinecraftServer server) {
World world = server.worldServerForDimension(dimId);
if (world == null) return null;
return world.getTileEntity(pos);
}
@Override
public boolean isLoaded(MinecraftServer server) {
World world = server.worldServerForDimension(dimId);
if (world == null) return false;
return world.getTileEntity(pos) != null;
}
@Override
@SideOnly(Side.CLIENT)
public TileEntity getByIdentifierClient() {
World world = Minecraft.getMinecraft().theWorld;
if (world == null || world.provider.getDimensionId() != dimId) return null;
return world.getTileEntity(pos);
}
@Override
@SideOnly(Side.CLIENT)
public boolean isLoadedClient() {
World world = Minecraft.getMinecraft().theWorld;
if (world == null || world.provider.getDimensionId() != dimId) return false;
return world.getTileEntity(pos) != null;
}
}
public static class MovableEntity extends Identifier {
private final UUID uniqueId;
public static MovableEntity create(Entity ent) {
if (ent.getEntityWorld() == null) throw new NullPointerException("ent.getEntityWorld() for the entity " + ent.getClass());
if (ent.getPersistentID() == null) throw new NullPointerException("ent.getPersistentID() for the entity " + ent.getClass());
return new MovableEntity(ent.getEntityWorld().provider.getDimensionId(), ent.getPersistentID());
}
private MovableEntity(int dimId, UUID uniqueId) {
super(dimId);
this.uniqueId = uniqueId;
}
private Entity get(World world) {
for (Entity entity : world.loadedEntityList) {
if (entity.getPersistentID().equals(uniqueId)) {
return entity;
}
}
return null;
}
@Override
public Entity getByIdentifier(MinecraftServer server) {
World world = server.worldServerForDimension(dimId);
if (world == null || world.provider.getDimensionId() != dimId) return null;
return get(world);
}
@Override
public boolean isLoaded(MinecraftServer server) {
World world = server.worldServerForDimension(dimId);
if (world == null || world.provider.getDimensionId() != dimId) return false;
return get(world) != null;
}
@Override
@SideOnly(Side.CLIENT)
public Entity getByIdentifierClient() {
World world = Minecraft.getMinecraft().theWorld;
if (world == null || world.provider.getDimensionId() != dimId) return null;
return get(world);
}
@Override
@SideOnly(Side.CLIENT)
public boolean isLoadedClient() {
World world = Minecraft.getMinecraft().theWorld;
if (world == null || world.provider.getDimensionId() != dimId) return false;
return get(world) != null;
}
@Override
protected MovableEntity load(NBTTagCompound tag) {
int dimId = tag.getInteger("dimId");
UUID uuid = UUID.fromString(tag.getString("uuid"));
return new MovableEntity(dimId, uuid);
}
@Override
protected NBTTagCompound save() {
NBTTagCompound tag = new NBTTagCompound();
tag.setInteger("dimId", dimId);
tag.setString("uuid", uniqueId.toString());
return tag;
}
@Override
public String typeId() {
return "minecraft:entity";
}
}
}