#1266: Add support for virtual entities
By: Jishuna <joshl5324@gmail.com>
This commit is contained in:
@@ -24,6 +24,7 @@ import net.minecraft.world.entity.EntityFlying;
|
||||
import net.minecraft.world.entity.EntityLightning;
|
||||
import net.minecraft.world.entity.EntityLiving;
|
||||
import net.minecraft.world.entity.EntityTameableAnimal;
|
||||
import net.minecraft.world.entity.EntityTypes;
|
||||
import net.minecraft.world.entity.GlowSquid;
|
||||
import net.minecraft.world.entity.Interaction;
|
||||
import net.minecraft.world.entity.Marker;
|
||||
@@ -164,6 +165,7 @@ import net.minecraft.world.entity.vehicle.EntityMinecartTNT;
|
||||
import net.minecraft.world.phys.AxisAlignedBB;
|
||||
import org.bukkit.EntityEffect;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.World;
|
||||
@@ -177,8 +179,10 @@ 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.CraftNamespacedKey;
|
||||
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;
|
||||
@@ -641,7 +645,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return entity.isAlive() && entity.valid && entity.isChunkLoaded();
|
||||
return entity.isAlive() && entity.valid && entity.isChunkLoaded() && isInWorld();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1114,6 +1118,42 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
||||
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());
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
package org.bukkit.craftbukkit.entity;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import java.util.function.Function;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.world.entity.EntityTypes;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntitySnapshot;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
public class CraftEntitySnapshot implements EntitySnapshot {
|
||||
private final NBTTagCompound data;
|
||||
private final EntityType type;
|
||||
|
||||
private CraftEntitySnapshot(NBTTagCompound data, EntityType type) {
|
||||
this.data = data;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityType getEntityType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity createEntity(World world) {
|
||||
net.minecraft.world.entity.Entity internal = createInternal(world);
|
||||
|
||||
return internal.getBukkitEntity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity createEntity(Location location) {
|
||||
Preconditions.checkArgument(location.getWorld() != null, "Location has no world");
|
||||
|
||||
net.minecraft.world.entity.Entity internal = createInternal(location.getWorld());
|
||||
|
||||
internal.setPos(location.getX(), location.getY(), location.getZ());
|
||||
return location.getWorld().addEntity(internal.getBukkitEntity());
|
||||
}
|
||||
|
||||
private net.minecraft.world.entity.Entity createInternal(World world) {
|
||||
net.minecraft.world.level.World nms = ((CraftWorld) world).getHandle();
|
||||
net.minecraft.world.entity.Entity internal = EntityTypes.loadEntityRecursive(data, nms, Function.identity());
|
||||
if (internal == null) { // Try creating by type
|
||||
internal = CraftEntityType.bukkitToMinecraft(type).create(nms);
|
||||
}
|
||||
|
||||
Preconditions.checkArgument(internal != null, "Error creating new entity."); // This should only fail if the stored NBTTagCompound is malformed.
|
||||
internal.load(data);
|
||||
|
||||
return internal;
|
||||
}
|
||||
|
||||
public NBTTagCompound getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public static CraftEntitySnapshot create(CraftEntity entity) {
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
if (!entity.getHandle().saveAsPassenger(tag, false)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new CraftEntitySnapshot(tag, entity.getType());
|
||||
}
|
||||
|
||||
public static CraftEntitySnapshot create(NBTTagCompound tag, EntityType type) {
|
||||
if (tag == null || tag.isEmpty() || type == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new CraftEntitySnapshot(tag, type);
|
||||
}
|
||||
|
||||
public static CraftEntitySnapshot create(NBTTagCompound tag) {
|
||||
EntityType type = EntityTypes.by(tag).map(CraftEntityType::minecraftToBukkit).orElse(null);
|
||||
return create(tag, type);
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,7 @@ import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.craftbukkit.CraftServer;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
import org.bukkit.craftbukkit.entity.memory.CraftMemoryMapper;
|
||||
import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
import org.bukkit.craftbukkit.inventory.CraftContainer;
|
||||
@@ -684,4 +685,14 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
|
||||
boolean success = getHandle().level().addFreshEntity(fireworks, SpawnReason.CUSTOM);
|
||||
return success ? (Firework) fireworks.getBukkitEntity() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.bukkit.entity.Entity copy() {
|
||||
throw new UnsupportedOperationException("Cannot copy human entities");
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.bukkit.entity.Entity copy(Location location) {
|
||||
throw new UnsupportedOperationException("Cannot copy human entities");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user