package net.glowstone.io.entity;
import net.glowstone.entity.GlowEntity;
import net.glowstone.io.nbt.NbtSerialization;
import net.glowstone.util.nbt.CompoundTag;
import net.glowstone.util.nbt.TagType;
import org.bukkit.Location;
import org.bukkit.entity.EntityType;
import java.util.UUID;
/**
* The base for entity store classes.
*
* @param <T> The type of entity being stored.
*/
public abstract class EntityStore<T extends GlowEntity> {
protected final Class<T> clazz;
protected final String type;
public EntityStore(Class<T> clazz, EntityType type) {
this.clazz = clazz;
this.type = type.getName();
}
public EntityStore(Class<T> clazz, String name) {
this.type = name;
this.clazz = clazz;
}
public final String getEntityType() {
return type;
}
public final Class<T> getType() {
return clazz;
}
/**
* Create a new entity of this store's type at the given location. The
* load method will be called separately.
*
* @param location The location.
* @param compound The entity's tag, if extra data is needed.
* @return The new entity.
*/
public abstract T createEntity(Location location, CompoundTag compound);
// For information on the NBT tags loaded here and elsewhere:
// http://minecraft.gamepedia.com/Chunk_format#Entity_Format
// todo: the following tags
// - bool "Invulnerable"
// - int "PortalCooldown"
// - compound "Riding"
/**
* Load data into an existing entity of the appropriate type from the
* given compound tag.
*
* @param entity The target entity.
* @param tag The entity's tag.
*/
public void load(T entity, CompoundTag tag) {
// id, world, and location are handled by EntityStore
// base stuff for all entities is here:
if (tag.isList("Motion", TagType.DOUBLE)) {
entity.setVelocity(NbtSerialization.listToVector(tag.getList("Motion", TagType.DOUBLE)));
}
if (tag.isFloat("FallDistance")) {
entity.setFallDistance(tag.getFloat("FallDistance"));
}
if (tag.isShort("Fire")) {
entity.setFireTicks(tag.getShort("Fire"));
}
if (tag.isByte("OnGround")) {
entity.setOnGround(tag.getBool("OnGround"));
}
if (tag.isByte("NoGravity")) {
entity.setGravity(!tag.getBool("NoGravity"));
}
if (tag.isByte("Silent")) {
entity.setSilent(tag.getBool("Silent"));
}
if (tag.isByte("Glowing")) {
entity.setGlowing(tag.getBool("Glowing"));
}
if (tag.isByte("Invulnerable")) {
entity.setInvulnerable(tag.getBool("Invulnerable"));
}
if (tag.isLong("UUIDMost") && tag.isLong("UUIDLeast")) {
UUID uuid = new UUID(tag.getLong("UUIDMost"), tag.getLong("UUIDLeast"));
entity.setUniqueId(uuid);
} else if (tag.isString("UUID")) {
// deprecated string format
UUID uuid = UUID.fromString(tag.getString("UUID"));
entity.setUniqueId(uuid);
}
}
/**
* Save information about this entity to the given tag.
*
* @param entity The entity to save.
* @param tag The target tag.
*/
public void save(T entity, CompoundTag tag) {
tag.putString("id", "minecraft:" + type);
// write world info, Pos, Rotation, and Motion
Location loc = entity.getLocation();
NbtSerialization.writeWorld(loc.getWorld(), tag);
NbtSerialization.locationToListTags(loc, tag);
tag.putList("Motion", TagType.DOUBLE, NbtSerialization.vectorToList(entity.getVelocity()));
tag.putFloat("FallDistance", entity.getFallDistance());
tag.putShort("Fire", entity.getFireTicks());
tag.putBool("OnGround", entity.isOnGround());
tag.putLong("UUIDMost", entity.getUniqueId().getMostSignificantBits());
tag.putLong("UUIDLeast", entity.getUniqueId().getLeastSignificantBits());
tag.putBool("NoGravity", !entity.hasGravity());
tag.putBool("Silent", entity.isSilent());
tag.putBool("Invulnerable", entity.isInvulnerable());
tag.putBool("Glowing", entity.isGlowing());
// in case Vanilla or CraftBukkit expects non-living entities to have this tag
tag.putInt("Air", 300);
}
}