869 lines
25 KiB
Java
869 lines
25 KiB
Java
package org.bukkit.craftbukkit.entity;
|
|
|
|
import com.google.common.base.Function;
|
|
import com.google.common.base.Preconditions;
|
|
import com.google.common.base.Predicates;
|
|
import com.google.common.collect.ImmutableSet;
|
|
import com.google.common.collect.Lists;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
import java.util.UUID;
|
|
import net.minecraft.nbt.NBTBase;
|
|
import net.minecraft.nbt.NBTTagCompound;
|
|
import net.minecraft.network.chat.IChatBaseComponent;
|
|
import net.minecraft.server.level.EntityPlayer;
|
|
import net.minecraft.server.level.PlayerChunkMap;
|
|
import net.minecraft.server.level.WorldServer;
|
|
import net.minecraft.server.network.ServerPlayerConnection;
|
|
import net.minecraft.world.entity.Entity;
|
|
import net.minecraft.world.entity.EntityTypes;
|
|
import net.minecraft.world.entity.boss.EntityComplexPart;
|
|
import net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon;
|
|
import net.minecraft.world.entity.player.EntityHuman;
|
|
import net.minecraft.world.entity.projectile.EntityArrow;
|
|
import net.minecraft.world.phys.AxisAlignedBB;
|
|
import org.bukkit.EntityEffect;
|
|
import org.bukkit.Location;
|
|
import org.bukkit.Server;
|
|
import org.bukkit.Sound;
|
|
import org.bukkit.World;
|
|
import org.bukkit.block.BlockFace;
|
|
import org.bukkit.block.PistonMoveReaction;
|
|
import org.bukkit.craftbukkit.CraftServer;
|
|
import org.bukkit.craftbukkit.CraftSound;
|
|
import org.bukkit.craftbukkit.CraftWorld;
|
|
import org.bukkit.craftbukkit.block.CraftBlock;
|
|
import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer;
|
|
import org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry;
|
|
import org.bukkit.craftbukkit.util.CraftChatMessage;
|
|
import org.bukkit.craftbukkit.util.CraftLocation;
|
|
import org.bukkit.craftbukkit.util.CraftSpawnCategory;
|
|
import org.bukkit.craftbukkit.util.CraftVector;
|
|
import org.bukkit.entity.EntitySnapshot;
|
|
import org.bukkit.entity.EntityType;
|
|
import org.bukkit.entity.Player;
|
|
import org.bukkit.entity.Pose;
|
|
import org.bukkit.entity.SpawnCategory;
|
|
import org.bukkit.event.entity.EntityDamageEvent;
|
|
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
|
import org.bukkit.metadata.MetadataValue;
|
|
import org.bukkit.permissions.PermissibleBase;
|
|
import org.bukkit.permissions.Permission;
|
|
import org.bukkit.permissions.PermissionAttachment;
|
|
import org.bukkit.permissions.PermissionAttachmentInfo;
|
|
import org.bukkit.permissions.ServerOperator;
|
|
import org.bukkit.plugin.Plugin;
|
|
import org.bukkit.util.BoundingBox;
|
|
import org.bukkit.util.NumberConversions;
|
|
import org.bukkit.util.Vector;
|
|
|
|
public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
|
private static PermissibleBase perm;
|
|
private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry();
|
|
|
|
protected final CraftServer server;
|
|
protected Entity entity;
|
|
private final EntityType entityType;
|
|
private EntityDamageEvent lastDamageEvent;
|
|
private final CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY);
|
|
|
|
public CraftEntity(final CraftServer server, final Entity entity) {
|
|
this.server = server;
|
|
this.entity = entity;
|
|
this.entityType = CraftEntityType.minecraftToBukkit(entity.getType());
|
|
}
|
|
|
|
public static <T extends Entity> CraftEntity getEntity(CraftServer server, T entity) {
|
|
Preconditions.checkArgument(entity != null, "Unknown entity");
|
|
|
|
// Special case human, since bukkit use Player interface for ...
|
|
if (entity instanceof EntityHuman && !(entity instanceof EntityPlayer)) {
|
|
return new CraftHumanEntity(server, (EntityHuman) entity);
|
|
}
|
|
|
|
// Special case complex part, since there is no extra entity type for them
|
|
if (entity instanceof EntityComplexPart complexPart) {
|
|
if (complexPart.parentMob instanceof EntityEnderDragon) {
|
|
return new CraftEnderDragonPart(server, complexPart);
|
|
} else {
|
|
return new CraftComplexPart(server, complexPart);
|
|
}
|
|
}
|
|
|
|
CraftEntityTypes.EntityTypeData<?, T> entityTypeData = CraftEntityTypes.getEntityTypeData(CraftEntityType.minecraftToBukkit(entity.getType()));
|
|
|
|
if (entityTypeData != null) {
|
|
return entityTypeData.convertFunction().apply(server, entity);
|
|
}
|
|
|
|
throw new AssertionError("Unknown entity " + (entity == null ? null : entity.getClass()));
|
|
}
|
|
|
|
@Override
|
|
public Location getLocation() {
|
|
return CraftLocation.toBukkit(entity.position(), getWorld(), entity.getBukkitYaw(), entity.getXRot());
|
|
}
|
|
|
|
@Override
|
|
public Location getLocation(Location loc) {
|
|
if (loc != null) {
|
|
loc.setWorld(getWorld());
|
|
loc.setX(entity.getX());
|
|
loc.setY(entity.getY());
|
|
loc.setZ(entity.getZ());
|
|
loc.setYaw(entity.getBukkitYaw());
|
|
loc.setPitch(entity.getXRot());
|
|
}
|
|
|
|
return loc;
|
|
}
|
|
|
|
@Override
|
|
public Vector getVelocity() {
|
|
return CraftVector.toBukkit(entity.getDeltaMovement());
|
|
}
|
|
|
|
@Override
|
|
public void setVelocity(Vector velocity) {
|
|
Preconditions.checkArgument(velocity != null, "velocity");
|
|
velocity.checkFinite();
|
|
entity.setDeltaMovement(CraftVector.toNMS(velocity));
|
|
entity.hurtMarked = true;
|
|
}
|
|
|
|
@Override
|
|
public double getHeight() {
|
|
return getHandle().getBbHeight();
|
|
}
|
|
|
|
@Override
|
|
public double getWidth() {
|
|
return getHandle().getBbWidth();
|
|
}
|
|
|
|
@Override
|
|
public BoundingBox getBoundingBox() {
|
|
AxisAlignedBB bb = getHandle().getBoundingBox();
|
|
return new BoundingBox(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ);
|
|
}
|
|
|
|
@Override
|
|
public boolean isOnGround() {
|
|
if (entity instanceof EntityArrow) {
|
|
return ((EntityArrow) entity).inGround;
|
|
}
|
|
return entity.onGround();
|
|
}
|
|
|
|
@Override
|
|
public boolean isInWater() {
|
|
return entity.isInWater();
|
|
}
|
|
|
|
@Override
|
|
public World getWorld() {
|
|
return entity.level().getWorld();
|
|
}
|
|
|
|
@Override
|
|
public void setRotation(float yaw, float pitch) {
|
|
NumberConversions.checkFinite(pitch, "pitch not finite");
|
|
NumberConversions.checkFinite(yaw, "yaw not finite");
|
|
|
|
yaw = Location.normalizeYaw(yaw);
|
|
pitch = Location.normalizePitch(pitch);
|
|
|
|
entity.setYRot(yaw);
|
|
entity.setXRot(pitch);
|
|
entity.yRotO = yaw;
|
|
entity.xRotO = pitch;
|
|
entity.setYHeadRot(yaw);
|
|
}
|
|
|
|
@Override
|
|
public boolean teleport(Location location) {
|
|
return teleport(location, TeleportCause.PLUGIN);
|
|
}
|
|
|
|
@Override
|
|
public boolean teleport(Location location, TeleportCause cause) {
|
|
Preconditions.checkArgument(location != null, "location cannot be null");
|
|
location.checkFinite();
|
|
|
|
if (entity.isVehicle() || entity.isRemoved()) {
|
|
return false;
|
|
}
|
|
|
|
// If this entity is riding another entity, we must dismount before teleporting.
|
|
entity.stopRiding();
|
|
|
|
// Let the server handle cross world teleports
|
|
if (location.getWorld() != null && !location.getWorld().equals(getWorld())) {
|
|
// Prevent teleportation to an other world during world generation
|
|
Preconditions.checkState(!entity.generation, "Cannot teleport entity to an other world during world generation");
|
|
entity.teleportTo(((CraftWorld) location.getWorld()).getHandle(), CraftLocation.toVec3D(location));
|
|
return true;
|
|
}
|
|
|
|
// entity.setLocation() throws no event, and so cannot be cancelled
|
|
entity.absMoveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
|
// SPIGOT-619: Force sync head rotation also
|
|
entity.setYHeadRot(location.getYaw());
|
|
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean teleport(org.bukkit.entity.Entity destination) {
|
|
return teleport(destination.getLocation());
|
|
}
|
|
|
|
@Override
|
|
public boolean teleport(org.bukkit.entity.Entity destination, TeleportCause cause) {
|
|
return teleport(destination.getLocation(), cause);
|
|
}
|
|
|
|
@Override
|
|
public List<org.bukkit.entity.Entity> getNearbyEntities(double x, double y, double z) {
|
|
Preconditions.checkState(!entity.generation, "Cannot get nearby entities during world generation");
|
|
|
|
List<Entity> notchEntityList = entity.level().getEntities(entity, entity.getBoundingBox().inflate(x, y, z), Predicates.alwaysTrue());
|
|
List<org.bukkit.entity.Entity> bukkitEntityList = new java.util.ArrayList<org.bukkit.entity.Entity>(notchEntityList.size());
|
|
|
|
for (Entity e : notchEntityList) {
|
|
bukkitEntityList.add(e.getBukkitEntity());
|
|
}
|
|
return bukkitEntityList;
|
|
}
|
|
|
|
@Override
|
|
public int getEntityId() {
|
|
return entity.getId();
|
|
}
|
|
|
|
@Override
|
|
public int getFireTicks() {
|
|
return entity.getRemainingFireTicks();
|
|
}
|
|
|
|
@Override
|
|
public int getMaxFireTicks() {
|
|
return entity.getFireImmuneTicks();
|
|
}
|
|
|
|
@Override
|
|
public void setFireTicks(int ticks) {
|
|
entity.setRemainingFireTicks(ticks);
|
|
}
|
|
|
|
@Override
|
|
public void setVisualFire(boolean fire) {
|
|
getHandle().hasVisualFire = fire;
|
|
}
|
|
|
|
@Override
|
|
public boolean isVisualFire() {
|
|
return getHandle().hasVisualFire;
|
|
}
|
|
|
|
@Override
|
|
public int getFreezeTicks() {
|
|
return getHandle().getTicksFrozen();
|
|
}
|
|
|
|
@Override
|
|
public int getMaxFreezeTicks() {
|
|
return getHandle().getTicksRequiredToFreeze();
|
|
}
|
|
|
|
@Override
|
|
public void setFreezeTicks(int ticks) {
|
|
Preconditions.checkArgument(0 <= ticks, "Ticks (%s) cannot be less than 0", ticks);
|
|
|
|
getHandle().setTicksFrozen(ticks);
|
|
}
|
|
|
|
@Override
|
|
public boolean isFrozen() {
|
|
return getHandle().isFullyFrozen();
|
|
}
|
|
|
|
@Override
|
|
public void remove() {
|
|
entity.pluginRemoved = true;
|
|
entity.discard();
|
|
}
|
|
|
|
@Override
|
|
public boolean isDead() {
|
|
return !entity.isAlive();
|
|
}
|
|
|
|
@Override
|
|
public boolean isValid() {
|
|
return entity.isAlive() && entity.valid && entity.isChunkLoaded() && isInWorld();
|
|
}
|
|
|
|
@Override
|
|
public Server getServer() {
|
|
return server;
|
|
}
|
|
|
|
@Override
|
|
public boolean isPersistent() {
|
|
return entity.persist;
|
|
}
|
|
|
|
@Override
|
|
public void setPersistent(boolean persistent) {
|
|
entity.persist = persistent;
|
|
}
|
|
|
|
public Vector getMomentum() {
|
|
return getVelocity();
|
|
}
|
|
|
|
public void setMomentum(Vector value) {
|
|
setVelocity(value);
|
|
}
|
|
|
|
@Override
|
|
public org.bukkit.entity.Entity getPassenger() {
|
|
return isEmpty() ? null : getHandle().passengers.get(0).getBukkitEntity();
|
|
}
|
|
|
|
@Override
|
|
public boolean setPassenger(org.bukkit.entity.Entity passenger) {
|
|
Preconditions.checkArgument(!this.equals(passenger), "Entity cannot ride itself.");
|
|
if (passenger instanceof CraftEntity) {
|
|
eject();
|
|
return ((CraftEntity) passenger).getHandle().startRiding(getHandle());
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public List<org.bukkit.entity.Entity> getPassengers() {
|
|
return Lists.newArrayList(Lists.transform(getHandle().passengers, (Function<Entity, org.bukkit.entity.Entity>) input -> input.getBukkitEntity()));
|
|
}
|
|
|
|
@Override
|
|
public boolean addPassenger(org.bukkit.entity.Entity passenger) {
|
|
Preconditions.checkArgument(passenger != null, "Entity passenger cannot be null");
|
|
Preconditions.checkArgument(!this.equals(passenger), "Entity cannot ride itself.");
|
|
|
|
return ((CraftEntity) passenger).getHandle().startRiding(getHandle(), true);
|
|
}
|
|
|
|
@Override
|
|
public boolean removePassenger(org.bukkit.entity.Entity passenger) {
|
|
Preconditions.checkArgument(passenger != null, "Entity passenger cannot be null");
|
|
|
|
((CraftEntity) passenger).getHandle().stopRiding();
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean isEmpty() {
|
|
return !getHandle().isVehicle();
|
|
}
|
|
|
|
@Override
|
|
public boolean eject() {
|
|
if (isEmpty()) {
|
|
return false;
|
|
}
|
|
|
|
getHandle().ejectPassengers();
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public float getFallDistance() {
|
|
return getHandle().fallDistance;
|
|
}
|
|
|
|
@Override
|
|
public void setFallDistance(float distance) {
|
|
getHandle().fallDistance = distance;
|
|
}
|
|
|
|
@Override
|
|
public void setLastDamageCause(EntityDamageEvent event) {
|
|
lastDamageEvent = event;
|
|
}
|
|
|
|
@Override
|
|
public EntityDamageEvent getLastDamageCause() {
|
|
return lastDamageEvent;
|
|
}
|
|
|
|
@Override
|
|
public UUID getUniqueId() {
|
|
return getHandle().getUUID();
|
|
}
|
|
|
|
@Override
|
|
public int getTicksLived() {
|
|
return getHandle().tickCount;
|
|
}
|
|
|
|
@Override
|
|
public void setTicksLived(int value) {
|
|
Preconditions.checkArgument(value > 0, "Age value (%s) must be greater than 0", value);
|
|
getHandle().tickCount = value;
|
|
}
|
|
|
|
public Entity getHandle() {
|
|
return entity;
|
|
}
|
|
|
|
@Override
|
|
public final EntityType getType() {
|
|
return entityType;
|
|
}
|
|
|
|
@Override
|
|
public void playEffect(EntityEffect type) {
|
|
Preconditions.checkArgument(type != null, "Type cannot be null");
|
|
Preconditions.checkState(!entity.generation, "Cannot play effect during world generation");
|
|
|
|
if (type.getApplicable().isInstance(this)) {
|
|
this.getHandle().level().broadcastEntityEvent(getHandle(), type.getData());
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public Sound getSwimSound() {
|
|
return CraftSound.minecraftToBukkit(getHandle().getSwimSound0());
|
|
}
|
|
|
|
@Override
|
|
public Sound getSwimSplashSound() {
|
|
return CraftSound.minecraftToBukkit(getHandle().getSwimSplashSound0());
|
|
}
|
|
|
|
@Override
|
|
public Sound getSwimHighSpeedSplashSound() {
|
|
return CraftSound.minecraftToBukkit(getHandle().getSwimHighSpeedSplashSound0());
|
|
}
|
|
|
|
public void setHandle(final Entity entity) {
|
|
this.entity = entity;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return "CraftEntity{" + "id=" + getEntityId() + '}';
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object obj) {
|
|
if (obj == null) {
|
|
return false;
|
|
}
|
|
if (getClass() != obj.getClass()) {
|
|
return false;
|
|
}
|
|
final CraftEntity other = (CraftEntity) obj;
|
|
return (this.getEntityId() == other.getEntityId());
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
int hash = 7;
|
|
hash = 29 * hash + this.getEntityId();
|
|
return hash;
|
|
}
|
|
|
|
@Override
|
|
public void setMetadata(String metadataKey, MetadataValue newMetadataValue) {
|
|
server.getEntityMetadata().setMetadata(this, metadataKey, newMetadataValue);
|
|
}
|
|
|
|
@Override
|
|
public List<MetadataValue> getMetadata(String metadataKey) {
|
|
return server.getEntityMetadata().getMetadata(this, metadataKey);
|
|
}
|
|
|
|
@Override
|
|
public boolean hasMetadata(String metadataKey) {
|
|
return server.getEntityMetadata().hasMetadata(this, metadataKey);
|
|
}
|
|
|
|
@Override
|
|
public void removeMetadata(String metadataKey, Plugin owningPlugin) {
|
|
server.getEntityMetadata().removeMetadata(this, metadataKey, owningPlugin);
|
|
}
|
|
|
|
@Override
|
|
public boolean isInsideVehicle() {
|
|
return getHandle().isPassenger();
|
|
}
|
|
|
|
@Override
|
|
public boolean leaveVehicle() {
|
|
if (!isInsideVehicle()) {
|
|
return false;
|
|
}
|
|
|
|
getHandle().stopRiding();
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public org.bukkit.entity.Entity getVehicle() {
|
|
if (!isInsideVehicle()) {
|
|
return null;
|
|
}
|
|
|
|
return getHandle().getVehicle().getBukkitEntity();
|
|
}
|
|
|
|
@Override
|
|
public void setCustomName(String name) {
|
|
// sane limit for name length
|
|
if (name != null && name.length() > 256) {
|
|
name = name.substring(0, 256);
|
|
}
|
|
|
|
getHandle().setCustomName(CraftChatMessage.fromStringOrNull(name));
|
|
}
|
|
|
|
@Override
|
|
public String getCustomName() {
|
|
IChatBaseComponent name = getHandle().getCustomName();
|
|
|
|
if (name == null) {
|
|
return null;
|
|
}
|
|
|
|
return CraftChatMessage.fromComponent(name);
|
|
}
|
|
|
|
@Override
|
|
public void setCustomNameVisible(boolean flag) {
|
|
getHandle().setCustomNameVisible(flag);
|
|
}
|
|
|
|
@Override
|
|
public boolean isCustomNameVisible() {
|
|
return getHandle().isCustomNameVisible();
|
|
}
|
|
|
|
@Override
|
|
public void setVisibleByDefault(boolean visible) {
|
|
if (getHandle().visibleByDefault != visible) {
|
|
if (visible) {
|
|
// Making visible by default, reset and show to all players
|
|
for (Player player : server.getOnlinePlayers()) {
|
|
((CraftPlayer) player).resetAndShowEntity(this);
|
|
}
|
|
} else {
|
|
// Hiding by default, reset and hide from all players
|
|
for (Player player : server.getOnlinePlayers()) {
|
|
((CraftPlayer) player).resetAndHideEntity(this);
|
|
}
|
|
}
|
|
|
|
getHandle().visibleByDefault = visible;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean isVisibleByDefault() {
|
|
return getHandle().visibleByDefault;
|
|
}
|
|
|
|
@Override
|
|
public Set<Player> getTrackedBy() {
|
|
Preconditions.checkState(!entity.generation, "Cannot get tracking players during world generation");
|
|
ImmutableSet.Builder<Player> players = ImmutableSet.builder();
|
|
|
|
WorldServer world = ((CraftWorld) getWorld()).getHandle();
|
|
PlayerChunkMap.EntityTracker entityTracker = world.getChunkSource().chunkMap.entityMap.get(getEntityId());
|
|
|
|
if (entityTracker != null) {
|
|
for (ServerPlayerConnection connection : entityTracker.seenBy) {
|
|
players.add(connection.getPlayer().getBukkitEntity());
|
|
}
|
|
}
|
|
|
|
return players.build();
|
|
}
|
|
|
|
@Override
|
|
public void sendMessage(String message) {
|
|
|
|
}
|
|
|
|
@Override
|
|
public void sendMessage(String... messages) {
|
|
|
|
}
|
|
|
|
@Override
|
|
public void sendMessage(UUID sender, String message) {
|
|
this.sendMessage(message); // Most entities don't know about senders
|
|
}
|
|
|
|
@Override
|
|
public void sendMessage(UUID sender, String... messages) {
|
|
this.sendMessage(messages); // Most entities don't know about senders
|
|
}
|
|
|
|
@Override
|
|
public String getName() {
|
|
return CraftChatMessage.fromComponent(getHandle().getName());
|
|
}
|
|
|
|
@Override
|
|
public boolean isPermissionSet(String name) {
|
|
return getPermissibleBase().isPermissionSet(name);
|
|
}
|
|
|
|
@Override
|
|
public boolean isPermissionSet(Permission perm) {
|
|
return CraftEntity.getPermissibleBase().isPermissionSet(perm);
|
|
}
|
|
|
|
@Override
|
|
public boolean hasPermission(String name) {
|
|
return getPermissibleBase().hasPermission(name);
|
|
}
|
|
|
|
@Override
|
|
public boolean hasPermission(Permission perm) {
|
|
return getPermissibleBase().hasPermission(perm);
|
|
}
|
|
|
|
@Override
|
|
public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value) {
|
|
return getPermissibleBase().addAttachment(plugin, name, value);
|
|
}
|
|
|
|
@Override
|
|
public PermissionAttachment addAttachment(Plugin plugin) {
|
|
return getPermissibleBase().addAttachment(plugin);
|
|
}
|
|
|
|
@Override
|
|
public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks) {
|
|
return getPermissibleBase().addAttachment(plugin, name, value, ticks);
|
|
}
|
|
|
|
@Override
|
|
public PermissionAttachment addAttachment(Plugin plugin, int ticks) {
|
|
return getPermissibleBase().addAttachment(plugin, ticks);
|
|
}
|
|
|
|
@Override
|
|
public void removeAttachment(PermissionAttachment attachment) {
|
|
getPermissibleBase().removeAttachment(attachment);
|
|
}
|
|
|
|
@Override
|
|
public void recalculatePermissions() {
|
|
getPermissibleBase().recalculatePermissions();
|
|
}
|
|
|
|
@Override
|
|
public Set<PermissionAttachmentInfo> getEffectivePermissions() {
|
|
return getPermissibleBase().getEffectivePermissions();
|
|
}
|
|
|
|
@Override
|
|
public boolean isOp() {
|
|
return getPermissibleBase().isOp();
|
|
}
|
|
|
|
@Override
|
|
public void setOp(boolean value) {
|
|
getPermissibleBase().setOp(value);
|
|
}
|
|
|
|
@Override
|
|
public void setGlowing(boolean flag) {
|
|
getHandle().setGlowingTag(flag);
|
|
}
|
|
|
|
@Override
|
|
public boolean isGlowing() {
|
|
return getHandle().isCurrentlyGlowing();
|
|
}
|
|
|
|
@Override
|
|
public void setInvulnerable(boolean flag) {
|
|
getHandle().setInvulnerable(flag);
|
|
}
|
|
|
|
@Override
|
|
public boolean isInvulnerable() {
|
|
return getHandle().isInvulnerableTo(getHandle().damageSources().generic());
|
|
}
|
|
|
|
@Override
|
|
public boolean isSilent() {
|
|
return getHandle().isSilent();
|
|
}
|
|
|
|
@Override
|
|
public void setSilent(boolean flag) {
|
|
getHandle().setSilent(flag);
|
|
}
|
|
|
|
@Override
|
|
public boolean hasGravity() {
|
|
return !getHandle().isNoGravity();
|
|
}
|
|
|
|
@Override
|
|
public void setGravity(boolean gravity) {
|
|
getHandle().setNoGravity(!gravity);
|
|
}
|
|
|
|
@Override
|
|
public int getPortalCooldown() {
|
|
return getHandle().portalCooldown;
|
|
}
|
|
|
|
@Override
|
|
public void setPortalCooldown(int cooldown) {
|
|
getHandle().portalCooldown = cooldown;
|
|
}
|
|
|
|
@Override
|
|
public Set<String> getScoreboardTags() {
|
|
return getHandle().getTags();
|
|
}
|
|
|
|
@Override
|
|
public boolean addScoreboardTag(String tag) {
|
|
return getHandle().addTag(tag);
|
|
}
|
|
|
|
@Override
|
|
public boolean removeScoreboardTag(String tag) {
|
|
return getHandle().removeTag(tag);
|
|
}
|
|
|
|
@Override
|
|
public PistonMoveReaction getPistonMoveReaction() {
|
|
return PistonMoveReaction.getById(getHandle().getPistonPushReaction().ordinal());
|
|
}
|
|
|
|
@Override
|
|
public BlockFace getFacing() {
|
|
// Use this method over getDirection because it handles boats and minecarts.
|
|
return CraftBlock.notchToBlockFace(getHandle().getMotionDirection());
|
|
}
|
|
|
|
@Override
|
|
public CraftPersistentDataContainer getPersistentDataContainer() {
|
|
return persistentDataContainer;
|
|
}
|
|
|
|
@Override
|
|
public Pose getPose() {
|
|
return Pose.values()[getHandle().getPose().ordinal()];
|
|
}
|
|
|
|
@Override
|
|
public SpawnCategory getSpawnCategory() {
|
|
return CraftSpawnCategory.toBukkit(getHandle().getType().getCategory());
|
|
}
|
|
|
|
@Override
|
|
public boolean isInWorld() {
|
|
return getHandle().inWorld;
|
|
}
|
|
|
|
@Override
|
|
public EntitySnapshot createSnapshot() {
|
|
return CraftEntitySnapshot.create(this);
|
|
}
|
|
|
|
@Override
|
|
public org.bukkit.entity.Entity copy() {
|
|
Entity copy = copy(getHandle().level());
|
|
Preconditions.checkArgument(copy != null, "Error creating new entity.");
|
|
|
|
return copy.getBukkitEntity();
|
|
}
|
|
|
|
@Override
|
|
public org.bukkit.entity.Entity copy(Location location) {
|
|
Preconditions.checkArgument(location.getWorld() != null, "Location has no world");
|
|
|
|
Entity copy = copy(((CraftWorld) location.getWorld()).getHandle());
|
|
Preconditions.checkArgument(copy != null, "Error creating new entity.");
|
|
|
|
copy.setPos(location.getX(), location.getY(), location.getZ());
|
|
return location.getWorld().addEntity(copy.getBukkitEntity());
|
|
}
|
|
|
|
private Entity copy(net.minecraft.world.level.World level) {
|
|
NBTTagCompound compoundTag = new NBTTagCompound();
|
|
getHandle().saveAsPassenger(compoundTag, false);
|
|
|
|
return EntityTypes.loadEntityRecursive(compoundTag, level, java.util.function.Function.identity());
|
|
}
|
|
|
|
public void storeBukkitValues(NBTTagCompound c) {
|
|
if (!this.persistentDataContainer.isEmpty()) {
|
|
c.put("BukkitValues", this.persistentDataContainer.toTagCompound());
|
|
}
|
|
}
|
|
|
|
public void readBukkitValues(NBTTagCompound c) {
|
|
NBTBase base = c.get("BukkitValues");
|
|
if (base instanceof NBTTagCompound) {
|
|
this.persistentDataContainer.putAll((NBTTagCompound) base);
|
|
}
|
|
}
|
|
|
|
protected NBTTagCompound save() {
|
|
NBTTagCompound nbttagcompound = new NBTTagCompound();
|
|
|
|
nbttagcompound.putString("id", getHandle().getEncodeId());
|
|
getHandle().saveWithoutId(nbttagcompound);
|
|
|
|
return nbttagcompound;
|
|
}
|
|
|
|
// re-sends the spawn entity packet to updated values which cannot be updated otherwise
|
|
protected void update() {
|
|
if (!getHandle().isAlive()) {
|
|
return;
|
|
}
|
|
|
|
WorldServer world = ((CraftWorld) getWorld()).getHandle();
|
|
PlayerChunkMap.EntityTracker entityTracker = world.getChunkSource().chunkMap.entityMap.get(getEntityId());
|
|
|
|
if (entityTracker == null) {
|
|
return;
|
|
}
|
|
|
|
entityTracker.broadcast(getHandle().getAddEntityPacket());
|
|
}
|
|
|
|
private static PermissibleBase getPermissibleBase() {
|
|
if (perm == null) {
|
|
perm = new PermissibleBase(new ServerOperator() {
|
|
|
|
@Override
|
|
public boolean isOp() {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void setOp(boolean value) {
|
|
|
|
}
|
|
});
|
|
}
|
|
return perm;
|
|
}
|
|
}
|