From 847ce7f20dde4f752769d8f607b3bbcc7e9a56f8 Mon Sep 17 00:00:00 2001 From: sauilitired Date: Sun, 19 Aug 2018 22:18:58 +0200 Subject: [PATCH] (W.I.P) TeleportEntityWrapper as alternative to replicating entity wrapper --- .../plotsquared/bukkit/BukkitMain.java | 15 + .../bukkit/object/entity/EntityWrapper.java | 733 +----------------- .../entity/ReplicatingEntityWrapper.java | 716 +++++++++++++++++ .../object/entity/TeleportEntityWrapper.java | 92 +++ .../bukkit/util/BukkitChunkManager.java | 10 +- Bukkit/src/main/resources/plugin.yml | 2 +- 6 files changed, 857 insertions(+), 711 deletions(-) create mode 100644 Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/object/entity/ReplicatingEntityWrapper.java create mode 100644 Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/object/entity/TeleportEntityWrapper.java diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/BukkitMain.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/BukkitMain.java index 8d570685c..22ecb54aa 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/BukkitMain.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/BukkitMain.java @@ -355,6 +355,9 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain Plot plot = location.getPlot(); if (plot == null) { if (location.isPlotArea()) { + if (entity.hasMetadata("ps-tmp-teleport")) { + continue; + } iterator.remove(); entity.remove(); } @@ -366,6 +369,9 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain } Plot origin = (Plot) meta.get(0).value(); if (!plot.equals(origin.getBasePlot(false))) { + if (entity.hasMetadata("ps-tmp-teleport")) { + continue; + } iterator.remove(); entity.remove(); } @@ -445,6 +451,9 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain Entity passenger = entity.getPassenger(); if (!(passenger instanceof Player) && entity .getMetadata("keep").isEmpty()) { + if (entity.hasMetadata("ps-tmp-teleport")) { + continue; + } iterator.remove(); entity.remove(); continue; @@ -454,6 +463,9 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain Entity passenger = entity.getPassenger(); if (!(passenger instanceof Player) && entity .getMetadata("keep").isEmpty()) { + if (entity.hasMetadata("ps-tmp-teleport")) { + continue; + } iterator.remove(); entity.remove(); continue; @@ -490,6 +502,9 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain && (currentPlotId == null || !area .getPlot(originalPlotId) .equals(area.getPlot(currentPlotId)))) { + if (entity.hasMetadata("ps-tmp-teleport")) { + continue; + } iterator.remove(); entity.remove(); } diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/object/entity/EntityWrapper.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/object/entity/EntityWrapper.java index 71dd22191..bc1561217 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/object/entity/EntityWrapper.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/object/entity/EntityWrapper.java @@ -1,726 +1,43 @@ package com.github.intellectualsites.plotsquared.bukkit.object.entity; -import com.github.intellectualsites.plotsquared.bukkit.util.BukkitVersion; -import com.github.intellectualsites.plotsquared.plot.PS; -import org.bukkit.*; -import org.bukkit.block.BlockFace; -import org.bukkit.entity.*; -import org.bukkit.entity.Rabbit.Type; -import org.bukkit.entity.Skeleton.SkeletonType; -import org.bukkit.inventory.EntityEquipment; -import org.bukkit.inventory.InventoryHolder; -import org.bukkit.inventory.ItemStack; -import org.bukkit.util.EulerAngle; -import org.bukkit.util.Vector; +import lombok.Getter; +import lombok.NonNull; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; -public class EntityWrapper { +@Getter +public abstract class EntityWrapper { + private final Entity entity; private final EntityType type; - private final float yaw; - private final float pitch; - private final short depth; - private final int hash; - private final EntityBaseStats base = new EntityBaseStats(); + public double x; public double y; public double z; - public ItemStack[] inventory; - // Extended - private ItemStack stack; - private byte dataByte; - private byte dataByte2; - private String dataString; - private LivingEntityStats lived; - private AgeableStats aged; - private TameableStats tamed; - private ArmorStandStats stand; - private HorseStats horse; - private boolean noGravity; - public EntityWrapper(Entity entity, short depth) { - this.hash = entity.getEntityId(); - this.depth = depth; - Location location = entity.getLocation(); - this.yaw = location.getYaw(); - this.pitch = location.getPitch(); + protected final float yaw; + protected final float pitch; + + EntityWrapper(@NonNull final Entity entity) { + this.entity = entity; + this.type = entity.getType(); + + final Location location = entity.getLocation(); this.x = location.getX(); this.y = location.getY(); this.z = location.getZ(); - this.type = entity.getType(); - if (depth == 0) { - return; - } - Entity passenger = entity.getPassenger(); - if (passenger != null) { - this.base.passenger = new EntityWrapper(passenger, depth); - } - this.base.fall = entity.getFallDistance(); - this.base.fire = (short) entity.getFireTicks(); - this.base.age = entity.getTicksLived(); - Vector velocity = entity.getVelocity(); - this.base.vX = velocity.getX(); - this.base.vY = velocity.getY(); - this.base.vZ = velocity.getZ(); - if (depth == 1) { - return; - } - if (PS.get().checkVersion(PS.get().IMP.getServerVersion(), BukkitVersion.v1_10_0) - || entity instanceof ArmorStand) { - if (!entity.hasGravity()) { - this.noGravity = true; - } - } - switch (entity.getType()) { - case ARROW: - case BOAT: - if (PS.get().checkVersion(PS.get().IMP.getServerVersion(), BukkitVersion.v1_9_0)) { - Boat boat = (Boat) entity; - this.dataByte = getOrdinal(TreeSpecies.values(), boat.getWoodType()); - } - case COMPLEX_PART: - case EGG: - case ENDER_CRYSTAL: - case ENDER_PEARL: - case ENDER_SIGNAL: - case EXPERIENCE_ORB: - case FALLING_BLOCK: - case FIREBALL: - case FIREWORK: - case FISHING_HOOK: - case LEASH_HITCH: - case LIGHTNING: - case MINECART: - case MINECART_COMMAND: - case MINECART_MOB_SPAWNER: - case MINECART_TNT: - case PLAYER: - case PRIMED_TNT: - case SLIME: - case SMALL_FIREBALL: - case SNOWBALL: - case MINECART_FURNACE: - case SPLASH_POTION: - case THROWN_EXP_BOTTLE: - case WEATHER: - case WITHER_SKULL: - case UNKNOWN: - case TIPPED_ARROW: - case SPECTRAL_ARROW: - case SHULKER_BULLET: - case DRAGON_FIREBALL: - case LINGERING_POTION: - case AREA_EFFECT_CLOUD: - // Do this stuff later - return; - default: - PS.debug("&cCOULD NOT IDENTIFY ENTITY: " + entity.getType()); - return; - // MISC // - case DROPPED_ITEM: - Item item = (Item) entity; - this.stack = item.getItemStack(); - return; - case ITEM_FRAME: - this.x = Math.floor(this.x); - this.y = Math.floor(this.y); - this.z = Math.floor(this.z); - ItemFrame itemFrame = (ItemFrame) entity; - this.dataByte = getOrdinal(Rotation.values(), itemFrame.getRotation()); - this.stack = itemFrame.getItem().clone(); - return; - case PAINTING: - this.x = Math.floor(this.x); - this.y = Math.floor(this.y); - this.z = Math.floor(this.z); - Painting painting = (Painting) entity; - Art art = painting.getArt(); - this.dataByte = getOrdinal(BlockFace.values(), painting.getFacing()); - int h = art.getBlockHeight(); - if (h % 2 == 0) { - this.y -= 1; - } - this.dataString = art.name(); - return; - // END MISC // - // INVENTORY HOLDER // - case MINECART_CHEST: - case MINECART_HOPPER: - storeInventory((InventoryHolder) entity); - return; - // START LIVING ENTITY // - // START AGEABLE // - // START TAMEABLE // - case HORSE: - Horse horse = (Horse) entity; - this.horse = new HorseStats(); - this.horse.jump = horse.getJumpStrength(); - this.horse.chest = horse.isCarryingChest(); - this.horse.variant = horse.getVariant(); - this.horse.style = horse.getStyle(); - this.horse.color = horse.getColor(); - storeTameable(horse); - storeAgeable(horse); - storeLiving(horse); - storeInventory(horse); - return; - // END INVENTORY HOLDER // - case WOLF: - case OCELOT: - storeTameable((Tameable) entity); - storeAgeable((Ageable) entity); - storeLiving((LivingEntity) entity); - return; - // END TAMEABLE // - case SHEEP: - Sheep sheep = (Sheep) entity; - this.dataByte = (byte) (sheep.isSheared() ? 1 : 0); - this.dataByte2 = sheep.getColor().getDyeData(); - storeAgeable(sheep); - storeLiving(sheep); - return; - case VILLAGER: - case CHICKEN: - case COW: - case MUSHROOM_COW: - case PIG: - case POLAR_BEAR: - storeAgeable((Ageable) entity); - storeLiving((LivingEntity) entity); - return; - case RABBIT: - this.dataByte = getOrdinal(Type.values(), ((Rabbit) entity).getRabbitType()); - storeAgeable((Ageable) entity); - storeLiving((LivingEntity) entity); - return; - // END AGEABLE // - case GUARDIAN: - this.dataByte = (byte) (((Guardian) entity).isElder() ? 1 : 0); - storeLiving((LivingEntity) entity); - return; - case SKELETON: - this.dataByte = - getOrdinal(SkeletonType.values(), ((Skeleton) entity).getSkeletonType()); - storeLiving((LivingEntity) entity); - return; - case ARMOR_STAND: - ArmorStand stand = (ArmorStand) entity; - this.inventory = - new ItemStack[] {stand.getItemInHand().clone(), stand.getHelmet().clone(), - stand.getChestplate().clone(), stand.getLeggings().clone(), - stand.getBoots().clone()}; - storeLiving(stand); - this.stand = new ArmorStandStats(); - - EulerAngle head = stand.getHeadPose(); - this.stand.head[0] = (float) head.getX(); - this.stand.head[1] = (float) head.getY(); - this.stand.head[2] = (float) head.getZ(); - - EulerAngle body = stand.getBodyPose(); - this.stand.body[0] = (float) body.getX(); - this.stand.body[1] = (float) body.getY(); - this.stand.body[2] = (float) body.getZ(); - - EulerAngle leftLeg = stand.getLeftLegPose(); - this.stand.leftLeg[0] = (float) leftLeg.getX(); - this.stand.leftLeg[1] = (float) leftLeg.getY(); - this.stand.leftLeg[2] = (float) leftLeg.getZ(); - - EulerAngle rightLeg = stand.getRightLegPose(); - this.stand.rightLeg[0] = (float) rightLeg.getX(); - this.stand.rightLeg[1] = (float) rightLeg.getY(); - this.stand.rightLeg[2] = (float) rightLeg.getZ(); - - EulerAngle leftArm = stand.getLeftArmPose(); - this.stand.leftArm[0] = (float) leftArm.getX(); - this.stand.leftArm[1] = (float) leftArm.getY(); - this.stand.leftArm[2] = (float) leftArm.getZ(); - - EulerAngle rightArm = stand.getRightArmPose(); - this.stand.rightArm[0] = (float) rightArm.getX(); - this.stand.rightArm[1] = (float) rightArm.getY(); - this.stand.rightArm[2] = (float) rightArm.getZ(); - - if (stand.hasArms()) { - this.stand.arms = true; - } - if (!stand.hasBasePlate()) { - this.stand.noPlate = true; - } - if (!stand.isVisible()) { - this.stand.invisible = true; - } - if (stand.isSmall()) { - this.stand.small = true; - } - return; - case ENDERMITE: - return; - case BAT: - if (((Bat) entity).isAwake()) { - this.dataByte = (byte) 1; - } else { - this.dataByte = (byte) 0; - } - return; - case ENDER_DRAGON: - EnderDragon entity1 = (EnderDragon) entity; - this.dataByte = (byte) entity1.getPhase().ordinal(); - return; - case GHAST: - case MAGMA_CUBE: - case SQUID: - case PIG_ZOMBIE: - case ZOMBIE: - case WITHER: - case WITCH: - case SPIDER: - case CAVE_SPIDER: - case SILVERFISH: - case GIANT: - case ENDERMAN: - case CREEPER: - case BLAZE: - case SHULKER: - case SNOWMAN: - storeLiving((LivingEntity) entity); - return; - case IRON_GOLEM: - if (((IronGolem) entity).isPlayerCreated()) { - this.dataByte = (byte) 1; - } else { - this.dataByte = (byte) 0; - } - storeLiving((LivingEntity) entity); - // END LIVING // - } - } - - @Override public boolean equals(Object obj) { - return this.hash == obj.hashCode(); - } - - @Override public int hashCode() { - return this.hash; - } - - public void storeInventory(InventoryHolder held) { - this.inventory = held.getInventory().getContents().clone(); - } - - void restoreLiving(LivingEntity entity) { - entity.setCanPickupItems(this.lived.loot); - if (this.lived.name != null) { - entity.setCustomName(this.lived.name); - entity.setCustomNameVisible(this.lived.visible); - } - if (this.lived.potions != null && !this.lived.potions.isEmpty()) { - entity.addPotionEffects(this.lived.potions); - } - entity.setRemainingAir(this.lived.air); - entity.setRemoveWhenFarAway(this.lived.persistent); - if (this.lived.equipped) { - this.restoreEquipment(entity); - } - if (this.lived.leashed) { - // TODO leashes - // World world = entity.getWorld(); - // Entity leash = world.spawnEntity(new Location(world, Math.floor(x) + lived.leashX, Math.floor(y) + lived.leashY, Math - // .floor(z) + lived.leashZ), EntityType.LEASH_HITCH); - // entity.setLeashHolder(leash); - } - } - - void restoreEquipment(LivingEntity entity) { - EntityEquipment equipment = entity.getEquipment(); - if (PS.get().checkVersion(PS.get().IMP.getServerVersion(), BukkitVersion.v1_9_0)) { - equipment.setItemInMainHand(this.lived.mainHand); - equipment.setItemInOffHand(this.lived.offHand); - } else { - equipment.setItemInHand(this.lived.mainHand); - } - equipment.setHelmet(this.lived.helmet); - equipment.setChestplate(this.lived.chestplate); - equipment.setLeggings(this.lived.leggings); - equipment.setBoots(this.lived.boots); - } - - private void restoreInventory(InventoryHolder entity) { - try { - entity.getInventory().setContents(this.inventory); - } catch (IllegalArgumentException e) { - PS.debug("&c[WARN] Failed to restore inventory.\n Reason: " + e.getMessage()); - } - } - - public void storeLiving(LivingEntity lived) { - this.lived = new LivingEntityStats(); - this.lived.potions = lived.getActivePotionEffects(); - this.lived.loot = lived.getCanPickupItems(); - this.lived.name = lived.getCustomName(); - this.lived.visible = lived.isCustomNameVisible(); - this.lived.health = (float) lived.getHealth(); - this.lived.air = (short) lived.getRemainingAir(); - this.lived.persistent = lived.getRemoveWhenFarAway(); - this.lived.leashed = lived.isLeashed(); - if (this.lived.leashed) { - Location location = lived.getLeashHolder().getLocation(); - this.lived.leashX = (short) (this.x - location.getBlockX()); - this.lived.leashY = (short) (this.y - location.getBlockY()); - this.lived.leashZ = (short) (this.z - location.getBlockZ()); - } - EntityEquipment equipment = lived.getEquipment(); - this.lived.equipped = equipment != null; - if (this.lived.equipped) { - storeEquipment(equipment); - } - } - - void storeEquipment(EntityEquipment equipment) { - if (PS.get().checkVersion(PS.get().IMP.getServerVersion(), BukkitVersion.v1_9_0)) { - this.lived.mainHand = equipment.getItemInMainHand().clone(); - this.lived.offHand = equipment.getItemInOffHand().clone(); - } else { - this.lived.mainHand = equipment.getItemInHand().clone(); - this.lived.offHand = null; - } - this.lived.boots = equipment.getBoots().clone(); - this.lived.leggings = equipment.getLeggings().clone(); - this.lived.chestplate = equipment.getChestplate().clone(); - this.lived.helmet = equipment.getHelmet().clone(); - } - - private void restoreTameable(Tameable entity) { - if (this.tamed.tamed) { - if (this.tamed.owner != null) { - entity.setTamed(true); - entity.setOwner(this.tamed.owner); - } - } - } - - private void restoreAgeable(Ageable entity) { - if (!this.aged.adult) { - entity.setBaby(); - } - entity.setAgeLock(this.aged.locked); - if (this.aged.age > 0) { - entity.setAge(this.aged.age); - } - } - - public void storeAgeable(Ageable aged) { - this.aged = new AgeableStats(); - this.aged.age = aged.getAge(); - this.aged.locked = aged.getAgeLock(); - this.aged.adult = aged.isAdult(); - } - - public void storeTameable(Tameable tamed) { - this.tamed = new TameableStats(); - this.tamed.owner = tamed.getOwner(); - this.tamed.tamed = tamed.isTamed(); - } - - public Entity spawn(World world, int xOffset, int zOffset) { - Location location = new Location(world, this.x + xOffset, this.y, this.z + zOffset); - location.setYaw(this.yaw); - location.setPitch(this.pitch); - if (!this.type.isSpawnable()) { - return null; - } - Entity entity; - switch (this.type) { - case DROPPED_ITEM: - return world.dropItem(location, this.stack); - case PLAYER: - case LEASH_HITCH: - return null; - case ITEM_FRAME: - entity = world.spawn(location, ItemFrame.class); - break; - case PAINTING: - entity = world.spawn(location, Painting.class); - break; - default: - entity = world.spawnEntity(location, this.type); - break; - } - if (this.depth == 0) { - return entity; - } - if (this.base.passenger != null) { - try { - entity.setPassenger(this.base.passenger.spawn(world, xOffset, zOffset)); - } catch (Exception ignored) { - } - } - if (this.base.fall != 0) { - entity.setFallDistance(this.base.fall); - } - if (this.base.fire != 0) { - entity.setFireTicks(this.base.fire); - } - if (this.base.age != 0) { - entity.setTicksLived(this.base.age); - } - entity.setVelocity(new Vector(this.base.vX, this.base.vY, this.base.vZ)); - if (this.depth == 1) { - return entity; - } - if (PS.get().checkVersion(PS.get().IMP.getServerVersion(), BukkitVersion.v1_10_0) - || entity instanceof ArmorStand) { - if (this.noGravity) { - entity.setGravity(false); - } - } - switch (entity.getType()) { - case ARROW: - case BOAT: - if (PS.get().checkVersion(PS.get().IMP.getServerVersion(), BukkitVersion.v1_9_0)) { - Boat boat = (Boat) entity; - boat.setWoodType(TreeSpecies.values()[dataByte]); - } - - case COMPLEX_PART: - case EGG: - case ENDER_CRYSTAL: - case ENDER_PEARL: - case ENDER_SIGNAL: - case DROPPED_ITEM: - case EXPERIENCE_ORB: - case FALLING_BLOCK: - case FIREBALL: - case FIREWORK: - case FISHING_HOOK: - case LEASH_HITCH: - case LIGHTNING: - case MINECART: - case MINECART_COMMAND: - case MINECART_MOB_SPAWNER: - case MINECART_TNT: - case PLAYER: - case PRIMED_TNT: - return entity; - case SLIME: - ((Slime) entity).setSize(this.dataByte); - return entity; - case SMALL_FIREBALL: - case SNOWBALL: - case SPLASH_POTION: - case THROWN_EXP_BOTTLE: - case WEATHER: - case TIPPED_ARROW: - case SPECTRAL_ARROW: - case SHULKER_BULLET: - case LINGERING_POTION: - case AREA_EFFECT_CLOUD: - case DRAGON_FIREBALL: - case WITHER_SKULL: - case MINECART_FURNACE: - case UNKNOWN: - // Do this stuff later - return entity; - default: - PS.debug("&cCOULD NOT IDENTIFY ENTITY: " + entity.getType()); - return entity; - // MISC // - case ITEM_FRAME: - ItemFrame itemframe = (ItemFrame) entity; - itemframe.setRotation(Rotation.values()[this.dataByte]); - itemframe.setItem(this.stack); - return entity; - case PAINTING: - Painting painting = (Painting) entity; - painting.setFacingDirection(BlockFace.values()[this.dataByte], true); - painting.setArt(Art.getByName(this.dataString), true); - return entity; - // END MISC // - // INVENTORY HOLDER // - case MINECART_CHEST: - case MINECART_HOPPER: - restoreInventory((InventoryHolder) entity); - return entity; - // START LIVING ENTITY // - // START AGEABLE // - // START TAMEABLE // - case HORSE: - Horse horse = (Horse) entity; - horse.setJumpStrength(this.horse.jump); - horse.setCarryingChest(this.horse.chest); - horse.setVariant(this.horse.variant); - horse.setStyle(this.horse.style); - horse.setColor(this.horse.color); - restoreTameable(horse); - restoreAgeable(horse); - restoreLiving(horse); - restoreInventory(horse); - return entity; - // END INVENTORY HOLDER // - case WOLF: - case OCELOT: - restoreTameable((Tameable) entity); - restoreAgeable((Ageable) entity); - restoreLiving((LivingEntity) entity); - return entity; - // END AGEABLE // - case SHEEP: - Sheep sheep = (Sheep) entity; - if (this.dataByte == 1) { - sheep.setSheared(true); - } - if (this.dataByte2 != 0) { - sheep.setColor(DyeColor.getByDyeData(this.dataByte2)); - } - restoreAgeable(sheep); - restoreLiving(sheep); - return sheep; - case VILLAGER: - case CHICKEN: - case COW: - case POLAR_BEAR: - case MUSHROOM_COW: - case PIG: - restoreAgeable((Ageable) entity); - restoreLiving((LivingEntity) entity); - return entity; - // END AGEABLE // - case RABBIT: - if (this.dataByte != 0) { - ((Rabbit) entity).setRabbitType(Type.values()[this.dataByte]); - } - restoreAgeable((Ageable) entity); - restoreLiving((LivingEntity) entity); - return entity; - case GUARDIAN: - if (this.dataByte != 0) { - ((Guardian) entity).setElder(true); - } - restoreLiving((LivingEntity) entity); - return entity; - case SKELETON: - if (this.dataByte != 0) { - ((Skeleton) entity).setSkeletonType(SkeletonType.values()[this.dataByte]); - } - storeLiving((LivingEntity) entity); - return entity; - case ARMOR_STAND: - // CHECK positions - ArmorStand stand = (ArmorStand) entity; - if (this.inventory[0] != null) { - stand.setItemInHand(this.inventory[0]); - } - if (this.inventory[1] != null) { - stand.setHelmet(this.inventory[1]); - } - if (this.inventory[2] != null) { - stand.setChestplate(this.inventory[2]); - } - if (this.inventory[3] != null) { - stand.setLeggings(this.inventory[3]); - } - if (this.inventory[4] != null) { - stand.setBoots(this.inventory[4]); - } - if (this.stand.head[0] != 0 || this.stand.head[1] != 0 || this.stand.head[2] != 0) { - EulerAngle pose = - new EulerAngle(this.stand.head[0], this.stand.head[1], this.stand.head[2]); - stand.setHeadPose(pose); - } - if (this.stand.body[0] != 0 || this.stand.body[1] != 0 || this.stand.body[2] != 0) { - EulerAngle pose = - new EulerAngle(this.stand.body[0], this.stand.body[1], this.stand.body[2]); - stand.setBodyPose(pose); - } - if (this.stand.leftLeg[0] != 0 || this.stand.leftLeg[1] != 0 - || this.stand.leftLeg[2] != 0) { - EulerAngle pose = new EulerAngle(this.stand.leftLeg[0], this.stand.leftLeg[1], - this.stand.leftLeg[2]); - stand.setLeftLegPose(pose); - } - if (this.stand.rightLeg[0] != 0 || this.stand.rightLeg[1] != 0 - || this.stand.rightLeg[2] != 0) { - EulerAngle pose = new EulerAngle(this.stand.rightLeg[0], this.stand.rightLeg[1], - this.stand.rightLeg[2]); - stand.setRightLegPose(pose); - } - if (this.stand.leftArm[0] != 0 || this.stand.leftArm[1] != 0 - || this.stand.leftArm[2] != 0) { - EulerAngle pose = new EulerAngle(this.stand.leftArm[0], this.stand.leftArm[1], - this.stand.leftArm[2]); - stand.setLeftArmPose(pose); - } - if (this.stand.rightArm[0] != 0 || this.stand.rightArm[1] != 0 - || this.stand.rightArm[2] != 0) { - EulerAngle pose = new EulerAngle(this.stand.rightArm[0], this.stand.rightArm[1], - this.stand.rightArm[2]); - stand.setRightArmPose(pose); - } - if (this.stand.invisible) { - stand.setVisible(false); - } - if (this.stand.arms) { - stand.setArms(true); - } - if (this.stand.noPlate) { - stand.setBasePlate(false); - } - if (this.stand.small) { - stand.setSmall(true); - } - restoreLiving(stand); - return stand; - case BAT: - if (this.dataByte != 0) { - ((Bat) entity).setAwake(true); - } - restoreLiving((LivingEntity) entity); - return entity; - case ENDER_DRAGON: - if (this.dataByte != 0) { - ((EnderDragon) entity).setPhase(EnderDragon.Phase.values()[this.dataByte]); - } - restoreLiving((LivingEntity) entity); - return entity; - case ENDERMITE: - case GHAST: - case MAGMA_CUBE: - case SQUID: - case PIG_ZOMBIE: - case ZOMBIE: - case WITHER: - case WITCH: - case SPIDER: - case CAVE_SPIDER: - case SILVERFISH: - case GIANT: - case ENDERMAN: - case CREEPER: - case BLAZE: - case SNOWMAN: - case SHULKER: - restoreLiving((LivingEntity) entity); - return entity; - case IRON_GOLEM: - if (this.dataByte != 0) { - ((IronGolem) entity).setPlayerCreated(true); - } - restoreLiving((LivingEntity) entity); - return entity; - // END LIVING - } - } - - private byte getOrdinal(Object[] list, Object value) { - for (byte i = 0; i < list.length; i++) { - if (list[i].equals(value)) { - return i; - } - } - return 0; + this.yaw = location.getYaw(); + this.pitch = location.getPitch(); } @SuppressWarnings("deprecation") @Override public String toString() { return String.format("[%s, x=%s, y=%s, z=%s]", type.getName(), x, y, z); } + + public abstract Entity spawn(World world, int xOffset, int zOffset); + + public abstract void saveEntity(); + } diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/object/entity/ReplicatingEntityWrapper.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/object/entity/ReplicatingEntityWrapper.java new file mode 100644 index 000000000..a9de09619 --- /dev/null +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/object/entity/ReplicatingEntityWrapper.java @@ -0,0 +1,716 @@ +package com.github.intellectualsites.plotsquared.bukkit.object.entity; + +import com.github.intellectualsites.plotsquared.bukkit.util.BukkitVersion; +import com.github.intellectualsites.plotsquared.plot.PS; +import org.bukkit.*; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.*; +import org.bukkit.inventory.EntityEquipment; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.EulerAngle; +import org.bukkit.util.Vector; + +public final class ReplicatingEntityWrapper extends EntityWrapper { + + private final short depth; + private final int hash; + private final EntityBaseStats base = new EntityBaseStats(); + + public ItemStack[] inventory; + // Extended + private ItemStack stack; + private byte dataByte; + private byte dataByte2; + private String dataString; + private LivingEntityStats lived; + private AgeableStats aged; + private TameableStats tamed; + private ArmorStandStats stand; + private HorseStats horse; + private boolean noGravity; + + public ReplicatingEntityWrapper(Entity entity, short depth) { + super(entity); + + this.hash = entity.getEntityId(); + this.depth = depth; + + if (depth == 0) { + return; + } + Entity passenger = entity.getPassenger(); + if (passenger != null) { + this.base.passenger = new ReplicatingEntityWrapper(passenger, depth); + } + this.base.fall = entity.getFallDistance(); + this.base.fire = (short) entity.getFireTicks(); + this.base.age = entity.getTicksLived(); + Vector velocity = entity.getVelocity(); + this.base.vX = velocity.getX(); + this.base.vY = velocity.getY(); + this.base.vZ = velocity.getZ(); + if (depth == 1) { + return; + } + if (PS.get().checkVersion(PS.get().IMP.getServerVersion(), BukkitVersion.v1_10_0) + || entity instanceof ArmorStand) { + if (!entity.hasGravity()) { + this.noGravity = true; + } + } + switch (entity.getType()) { + case ARROW: + case BOAT: + if (PS.get().checkVersion(PS.get().IMP.getServerVersion(), BukkitVersion.v1_9_0)) { + Boat boat = (Boat) entity; + this.dataByte = getOrdinal(TreeSpecies.values(), boat.getWoodType()); + } + case COMPLEX_PART: + case EGG: + case ENDER_CRYSTAL: + case ENDER_PEARL: + case ENDER_SIGNAL: + case EXPERIENCE_ORB: + case FALLING_BLOCK: + case FIREBALL: + case FIREWORK: + case FISHING_HOOK: + case LEASH_HITCH: + case LIGHTNING: + case MINECART: + case MINECART_COMMAND: + case MINECART_MOB_SPAWNER: + case MINECART_TNT: + case PLAYER: + case PRIMED_TNT: + case SLIME: + case SMALL_FIREBALL: + case SNOWBALL: + case MINECART_FURNACE: + case SPLASH_POTION: + case THROWN_EXP_BOTTLE: + case WEATHER: + case WITHER_SKULL: + case UNKNOWN: + case TIPPED_ARROW: + case SPECTRAL_ARROW: + case SHULKER_BULLET: + case DRAGON_FIREBALL: + case LINGERING_POTION: + case AREA_EFFECT_CLOUD: + // Do this stuff later + return; + default: + PS.debug("&cCOULD NOT IDENTIFY ENTITY: " + entity.getType()); + return; + // MISC // + case DROPPED_ITEM: + Item item = (Item) entity; + this.stack = item.getItemStack(); + return; + case ITEM_FRAME: + this.x = Math.floor(this.x); + this.y = Math.floor(this.y); + this.z = Math.floor(this.z); + ItemFrame itemFrame = (ItemFrame) entity; + this.dataByte = getOrdinal(Rotation.values(), itemFrame.getRotation()); + this.stack = itemFrame.getItem().clone(); + return; + case PAINTING: + this.x = Math.floor(this.x); + this.y = Math.floor(this.y); + this.z = Math.floor(this.z); + Painting painting = (Painting) entity; + Art art = painting.getArt(); + this.dataByte = getOrdinal(BlockFace.values(), painting.getFacing()); + int h = art.getBlockHeight(); + if (h % 2 == 0) { + this.y -= 1; + } + this.dataString = art.name(); + return; + // END MISC // + // INVENTORY HOLDER // + case MINECART_CHEST: + case MINECART_HOPPER: + storeInventory((InventoryHolder) entity); + return; + // START LIVING ENTITY // + // START AGEABLE // + // START TAMEABLE // + case HORSE: + Horse horse = (Horse) entity; + this.horse = new HorseStats(); + this.horse.jump = horse.getJumpStrength(); + this.horse.chest = horse.isCarryingChest(); + this.horse.variant = horse.getVariant(); + this.horse.style = horse.getStyle(); + this.horse.color = horse.getColor(); + storeTameable(horse); + storeAgeable(horse); + storeLiving(horse); + storeInventory(horse); + return; + // END INVENTORY HOLDER // + case WOLF: + case OCELOT: + storeTameable((Tameable) entity); + storeAgeable((Ageable) entity); + storeLiving((LivingEntity) entity); + return; + // END TAMEABLE // + case SHEEP: + Sheep sheep = (Sheep) entity; + this.dataByte = (byte) (sheep.isSheared() ? 1 : 0); + this.dataByte2 = sheep.getColor().getDyeData(); + storeAgeable(sheep); + storeLiving(sheep); + return; + case VILLAGER: + case CHICKEN: + case COW: + case MUSHROOM_COW: + case PIG: + case POLAR_BEAR: + storeAgeable((Ageable) entity); + storeLiving((LivingEntity) entity); + return; + case RABBIT: + this.dataByte = getOrdinal(Rabbit.Type.values(), ((Rabbit) entity).getRabbitType()); + storeAgeable((Ageable) entity); + storeLiving((LivingEntity) entity); + return; + // END AGEABLE // + case GUARDIAN: + this.dataByte = (byte) (((Guardian) entity).isElder() ? 1 : 0); + storeLiving((LivingEntity) entity); + return; + case SKELETON: + this.dataByte = + getOrdinal(Skeleton.SkeletonType.values(), ((Skeleton) entity).getSkeletonType()); + storeLiving((LivingEntity) entity); + return; + case ARMOR_STAND: + ArmorStand stand = (ArmorStand) entity; + this.inventory = + new ItemStack[] {stand.getItemInHand().clone(), stand.getHelmet().clone(), + stand.getChestplate().clone(), stand.getLeggings().clone(), + stand.getBoots().clone()}; + storeLiving(stand); + this.stand = new ArmorStandStats(); + + EulerAngle head = stand.getHeadPose(); + this.stand.head[0] = (float) head.getX(); + this.stand.head[1] = (float) head.getY(); + this.stand.head[2] = (float) head.getZ(); + + EulerAngle body = stand.getBodyPose(); + this.stand.body[0] = (float) body.getX(); + this.stand.body[1] = (float) body.getY(); + this.stand.body[2] = (float) body.getZ(); + + EulerAngle leftLeg = stand.getLeftLegPose(); + this.stand.leftLeg[0] = (float) leftLeg.getX(); + this.stand.leftLeg[1] = (float) leftLeg.getY(); + this.stand.leftLeg[2] = (float) leftLeg.getZ(); + + EulerAngle rightLeg = stand.getRightLegPose(); + this.stand.rightLeg[0] = (float) rightLeg.getX(); + this.stand.rightLeg[1] = (float) rightLeg.getY(); + this.stand.rightLeg[2] = (float) rightLeg.getZ(); + + EulerAngle leftArm = stand.getLeftArmPose(); + this.stand.leftArm[0] = (float) leftArm.getX(); + this.stand.leftArm[1] = (float) leftArm.getY(); + this.stand.leftArm[2] = (float) leftArm.getZ(); + + EulerAngle rightArm = stand.getRightArmPose(); + this.stand.rightArm[0] = (float) rightArm.getX(); + this.stand.rightArm[1] = (float) rightArm.getY(); + this.stand.rightArm[2] = (float) rightArm.getZ(); + + if (stand.hasArms()) { + this.stand.arms = true; + } + if (!stand.hasBasePlate()) { + this.stand.noPlate = true; + } + if (!stand.isVisible()) { + this.stand.invisible = true; + } + if (stand.isSmall()) { + this.stand.small = true; + } + return; + case ENDERMITE: + return; + case BAT: + if (((Bat) entity).isAwake()) { + this.dataByte = (byte) 1; + } else { + this.dataByte = (byte) 0; + } + return; + case ENDER_DRAGON: + EnderDragon entity1 = (EnderDragon) entity; + this.dataByte = (byte) entity1.getPhase().ordinal(); + return; + case GHAST: + case MAGMA_CUBE: + case SQUID: + case PIG_ZOMBIE: + case ZOMBIE: + case WITHER: + case WITCH: + case SPIDER: + case CAVE_SPIDER: + case SILVERFISH: + case GIANT: + case ENDERMAN: + case CREEPER: + case BLAZE: + case SHULKER: + case SNOWMAN: + storeLiving((LivingEntity) entity); + return; + case IRON_GOLEM: + if (((IronGolem) entity).isPlayerCreated()) { + this.dataByte = (byte) 1; + } else { + this.dataByte = (byte) 0; + } + storeLiving((LivingEntity) entity); + // END LIVING // + } + } + + @Override public boolean equals(Object obj) { + return this.hash == obj.hashCode(); + } + + @Override public int hashCode() { + return this.hash; + } + + public void storeInventory(InventoryHolder held) { + this.inventory = held.getInventory().getContents().clone(); + } + + void restoreLiving(LivingEntity entity) { + entity.setCanPickupItems(this.lived.loot); + if (this.lived.name != null) { + entity.setCustomName(this.lived.name); + entity.setCustomNameVisible(this.lived.visible); + } + if (this.lived.potions != null && !this.lived.potions.isEmpty()) { + entity.addPotionEffects(this.lived.potions); + } + entity.setRemainingAir(this.lived.air); + entity.setRemoveWhenFarAway(this.lived.persistent); + if (this.lived.equipped) { + this.restoreEquipment(entity); + } + if (this.lived.leashed) { + // TODO leashes + // World world = entity.getWorld(); + // Entity leash = world.spawnEntity(new Location(world, Math.floor(x) + lived.leashX, Math.floor(y) + lived.leashY, Math + // .floor(z) + lived.leashZ), EntityType.LEASH_HITCH); + // entity.setLeashHolder(leash); + } + } + + void restoreEquipment(LivingEntity entity) { + EntityEquipment equipment = entity.getEquipment(); + if (PS.get().checkVersion(PS.get().IMP.getServerVersion(), BukkitVersion.v1_9_0)) { + equipment.setItemInMainHand(this.lived.mainHand); + equipment.setItemInOffHand(this.lived.offHand); + } else { + equipment.setItemInHand(this.lived.mainHand); + } + equipment.setHelmet(this.lived.helmet); + equipment.setChestplate(this.lived.chestplate); + equipment.setLeggings(this.lived.leggings); + equipment.setBoots(this.lived.boots); + } + + private void restoreInventory(InventoryHolder entity) { + try { + entity.getInventory().setContents(this.inventory); + } catch (IllegalArgumentException e) { + PS.debug("&c[WARN] Failed to restore inventory.\n Reason: " + e.getMessage()); + } + } + + public void storeLiving(LivingEntity lived) { + this.lived = new LivingEntityStats(); + this.lived.potions = lived.getActivePotionEffects(); + this.lived.loot = lived.getCanPickupItems(); + this.lived.name = lived.getCustomName(); + this.lived.visible = lived.isCustomNameVisible(); + this.lived.health = (float) lived.getHealth(); + this.lived.air = (short) lived.getRemainingAir(); + this.lived.persistent = lived.getRemoveWhenFarAway(); + this.lived.leashed = lived.isLeashed(); + if (this.lived.leashed) { + Location location = lived.getLeashHolder().getLocation(); + this.lived.leashX = (short) (this.x - location.getBlockX()); + this.lived.leashY = (short) (this.y - location.getBlockY()); + this.lived.leashZ = (short) (this.z - location.getBlockZ()); + } + EntityEquipment equipment = lived.getEquipment(); + this.lived.equipped = equipment != null; + if (this.lived.equipped) { + storeEquipment(equipment); + } + } + + void storeEquipment(EntityEquipment equipment) { + if (PS.get().checkVersion(PS.get().IMP.getServerVersion(), BukkitVersion.v1_9_0)) { + this.lived.mainHand = equipment.getItemInMainHand().clone(); + this.lived.offHand = equipment.getItemInOffHand().clone(); + } else { + this.lived.mainHand = equipment.getItemInHand().clone(); + this.lived.offHand = null; + } + this.lived.boots = equipment.getBoots().clone(); + this.lived.leggings = equipment.getLeggings().clone(); + this.lived.chestplate = equipment.getChestplate().clone(); + this.lived.helmet = equipment.getHelmet().clone(); + } + + private void restoreTameable(Tameable entity) { + if (this.tamed.tamed) { + if (this.tamed.owner != null) { + entity.setTamed(true); + entity.setOwner(this.tamed.owner); + } + } + } + + private void restoreAgeable(Ageable entity) { + if (!this.aged.adult) { + entity.setBaby(); + } + entity.setAgeLock(this.aged.locked); + if (this.aged.age > 0) { + entity.setAge(this.aged.age); + } + } + + public void storeAgeable(Ageable aged) { + this.aged = new AgeableStats(); + this.aged.age = aged.getAge(); + this.aged.locked = aged.getAgeLock(); + this.aged.adult = aged.isAdult(); + } + + public void storeTameable(Tameable tamed) { + this.tamed = new TameableStats(); + this.tamed.owner = tamed.getOwner(); + this.tamed.tamed = tamed.isTamed(); + } + + @Override + public Entity spawn(World world, int xOffset, int zOffset) { + Location location = new Location(world, this.x + xOffset, this.y, this.z + zOffset); + location.setYaw(this.yaw); + location.setPitch(this.pitch); + if (!this.getType().isSpawnable()) { + return null; + } + Entity entity; + switch (this.getType()) { + case DROPPED_ITEM: + return world.dropItem(location, this.stack); + case PLAYER: + case LEASH_HITCH: + return null; + case ITEM_FRAME: + entity = world.spawn(location, ItemFrame.class); + break; + case PAINTING: + entity = world.spawn(location, Painting.class); + break; + default: + entity = world.spawnEntity(location, this.getType()); + break; + } + if (this.depth == 0) { + return entity; + } + if (this.base.passenger != null) { + try { + entity.setPassenger(this.base.passenger.spawn(world, xOffset, zOffset)); + } catch (Exception ignored) { + } + } + if (this.base.fall != 0) { + entity.setFallDistance(this.base.fall); + } + if (this.base.fire != 0) { + entity.setFireTicks(this.base.fire); + } + if (this.base.age != 0) { + entity.setTicksLived(this.base.age); + } + entity.setVelocity(new Vector(this.base.vX, this.base.vY, this.base.vZ)); + if (this.depth == 1) { + return entity; + } + if (PS.get().checkVersion(PS.get().IMP.getServerVersion(), BukkitVersion.v1_10_0) + || entity instanceof ArmorStand) { + if (this.noGravity) { + entity.setGravity(false); + } + } + switch (entity.getType()) { + case ARROW: + case BOAT: + if (PS.get().checkVersion(PS.get().IMP.getServerVersion(), BukkitVersion.v1_9_0)) { + Boat boat = (Boat) entity; + boat.setWoodType(TreeSpecies.values()[dataByte]); + } + + case COMPLEX_PART: + case EGG: + case ENDER_CRYSTAL: + case ENDER_PEARL: + case ENDER_SIGNAL: + case DROPPED_ITEM: + case EXPERIENCE_ORB: + case FALLING_BLOCK: + case FIREBALL: + case FIREWORK: + case FISHING_HOOK: + case LEASH_HITCH: + case LIGHTNING: + case MINECART: + case MINECART_COMMAND: + case MINECART_MOB_SPAWNER: + case MINECART_TNT: + case PLAYER: + case PRIMED_TNT: + return entity; + case SLIME: + ((Slime) entity).setSize(this.dataByte); + return entity; + case SMALL_FIREBALL: + case SNOWBALL: + case SPLASH_POTION: + case THROWN_EXP_BOTTLE: + case WEATHER: + case TIPPED_ARROW: + case SPECTRAL_ARROW: + case SHULKER_BULLET: + case LINGERING_POTION: + case AREA_EFFECT_CLOUD: + case DRAGON_FIREBALL: + case WITHER_SKULL: + case MINECART_FURNACE: + case UNKNOWN: + // Do this stuff later + return entity; + default: + PS.debug("&cCOULD NOT IDENTIFY ENTITY: " + entity.getType()); + return entity; + // MISC // + case ITEM_FRAME: + ItemFrame itemframe = (ItemFrame) entity; + itemframe.setRotation(Rotation.values()[this.dataByte]); + itemframe.setItem(this.stack); + return entity; + case PAINTING: + Painting painting = (Painting) entity; + painting.setFacingDirection(BlockFace.values()[this.dataByte], true); + painting.setArt(Art.getByName(this.dataString), true); + return entity; + // END MISC // + // INVENTORY HOLDER // + case MINECART_CHEST: + case MINECART_HOPPER: + restoreInventory((InventoryHolder) entity); + return entity; + // START LIVING ENTITY // + // START AGEABLE // + // START TAMEABLE // + case HORSE: + Horse horse = (Horse) entity; + horse.setJumpStrength(this.horse.jump); + horse.setCarryingChest(this.horse.chest); + horse.setVariant(this.horse.variant); + horse.setStyle(this.horse.style); + horse.setColor(this.horse.color); + restoreTameable(horse); + restoreAgeable(horse); + restoreLiving(horse); + restoreInventory(horse); + return entity; + // END INVENTORY HOLDER // + case WOLF: + case OCELOT: + restoreTameable((Tameable) entity); + restoreAgeable((Ageable) entity); + restoreLiving((LivingEntity) entity); + return entity; + // END AGEABLE // + case SHEEP: + Sheep sheep = (Sheep) entity; + if (this.dataByte == 1) { + sheep.setSheared(true); + } + if (this.dataByte2 != 0) { + sheep.setColor(DyeColor.getByDyeData(this.dataByte2)); + } + restoreAgeable(sheep); + restoreLiving(sheep); + return sheep; + case VILLAGER: + case CHICKEN: + case COW: + case POLAR_BEAR: + case MUSHROOM_COW: + case PIG: + restoreAgeable((Ageable) entity); + restoreLiving((LivingEntity) entity); + return entity; + // END AGEABLE // + case RABBIT: + if (this.dataByte != 0) { + ((Rabbit) entity).setRabbitType(Rabbit.Type.values()[this.dataByte]); + } + restoreAgeable((Ageable) entity); + restoreLiving((LivingEntity) entity); + return entity; + case GUARDIAN: + if (this.dataByte != 0) { + ((Guardian) entity).setElder(true); + } + restoreLiving((LivingEntity) entity); + return entity; + case SKELETON: + if (this.dataByte != 0) { + ((Skeleton) entity).setSkeletonType(Skeleton.SkeletonType.values()[this.dataByte]); + } + storeLiving((LivingEntity) entity); + return entity; + case ARMOR_STAND: + // CHECK positions + ArmorStand stand = (ArmorStand) entity; + if (this.inventory[0] != null) { + stand.setItemInHand(this.inventory[0]); + } + if (this.inventory[1] != null) { + stand.setHelmet(this.inventory[1]); + } + if (this.inventory[2] != null) { + stand.setChestplate(this.inventory[2]); + } + if (this.inventory[3] != null) { + stand.setLeggings(this.inventory[3]); + } + if (this.inventory[4] != null) { + stand.setBoots(this.inventory[4]); + } + if (this.stand.head[0] != 0 || this.stand.head[1] != 0 || this.stand.head[2] != 0) { + EulerAngle pose = + new EulerAngle(this.stand.head[0], this.stand.head[1], this.stand.head[2]); + stand.setHeadPose(pose); + } + if (this.stand.body[0] != 0 || this.stand.body[1] != 0 || this.stand.body[2] != 0) { + EulerAngle pose = + new EulerAngle(this.stand.body[0], this.stand.body[1], this.stand.body[2]); + stand.setBodyPose(pose); + } + if (this.stand.leftLeg[0] != 0 || this.stand.leftLeg[1] != 0 + || this.stand.leftLeg[2] != 0) { + EulerAngle pose = new EulerAngle(this.stand.leftLeg[0], this.stand.leftLeg[1], + this.stand.leftLeg[2]); + stand.setLeftLegPose(pose); + } + if (this.stand.rightLeg[0] != 0 || this.stand.rightLeg[1] != 0 + || this.stand.rightLeg[2] != 0) { + EulerAngle pose = new EulerAngle(this.stand.rightLeg[0], this.stand.rightLeg[1], + this.stand.rightLeg[2]); + stand.setRightLegPose(pose); + } + if (this.stand.leftArm[0] != 0 || this.stand.leftArm[1] != 0 + || this.stand.leftArm[2] != 0) { + EulerAngle pose = new EulerAngle(this.stand.leftArm[0], this.stand.leftArm[1], + this.stand.leftArm[2]); + stand.setLeftArmPose(pose); + } + if (this.stand.rightArm[0] != 0 || this.stand.rightArm[1] != 0 + || this.stand.rightArm[2] != 0) { + EulerAngle pose = new EulerAngle(this.stand.rightArm[0], this.stand.rightArm[1], + this.stand.rightArm[2]); + stand.setRightArmPose(pose); + } + if (this.stand.invisible) { + stand.setVisible(false); + } + if (this.stand.arms) { + stand.setArms(true); + } + if (this.stand.noPlate) { + stand.setBasePlate(false); + } + if (this.stand.small) { + stand.setSmall(true); + } + restoreLiving(stand); + return stand; + case BAT: + if (this.dataByte != 0) { + ((Bat) entity).setAwake(true); + } + restoreLiving((LivingEntity) entity); + return entity; + case ENDER_DRAGON: + if (this.dataByte != 0) { + ((EnderDragon) entity).setPhase(EnderDragon.Phase.values()[this.dataByte]); + } + restoreLiving((LivingEntity) entity); + return entity; + case ENDERMITE: + case GHAST: + case MAGMA_CUBE: + case SQUID: + case PIG_ZOMBIE: + case ZOMBIE: + case WITHER: + case WITCH: + case SPIDER: + case CAVE_SPIDER: + case SILVERFISH: + case GIANT: + case ENDERMAN: + case CREEPER: + case BLAZE: + case SNOWMAN: + case SHULKER: + restoreLiving((LivingEntity) entity); + return entity; + case IRON_GOLEM: + if (this.dataByte != 0) { + ((IronGolem) entity).setPlayerCreated(true); + } + restoreLiving((LivingEntity) entity); + return entity; + // END LIVING + } + } + + public void saveEntity() {} + + private byte getOrdinal(Object[] list, Object value) { + for (byte i = 0; i < list.length; i++) { + if (list[i].equals(value)) { + return i; + } + } + return 0; + } + + +} diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/object/entity/TeleportEntityWrapper.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/object/entity/TeleportEntityWrapper.java new file mode 100644 index 000000000..a5084a1c8 --- /dev/null +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/object/entity/TeleportEntityWrapper.java @@ -0,0 +1,92 @@ +package com.github.intellectualsites.plotsquared.bukkit.object.entity; + +import com.github.intellectualsites.plotsquared.bukkit.BukkitMain; +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Entity; +import org.bukkit.metadata.FixedMetadataValue; + +public class TeleportEntityWrapper extends EntityWrapper { + + private Location oldLocation; + private boolean gravityOld; + private boolean invulnerableOld; + private int fireTicksOld; + private int livingTicksOld; + + public TeleportEntityWrapper(final Entity entity) { + super(entity); + } + + @Override public Entity spawn(final World world, final int xOffset, final int zOffset) { + if (!getEntity().getLocation().getChunk().equals(oldLocation.getChunk())) { + final Location oldLocation = this.oldLocation.clone(); + oldLocation.add(xOffset, 0, xOffset); + getEntity().teleport(oldLocation); + getEntity().setGravity(gravityOld); + getEntity().setInvulnerable(invulnerableOld); + getEntity().setFireTicks(fireTicksOld); + getEntity().setTicksLived(livingTicksOld); + getEntity().removeMetadata("ps-tmp-teleport", BukkitMain.getPlugin(BukkitMain.class)); + } + return getEntity(); + } + + @Override public void saveEntity() { + if (getEntity().hasMetadata("ps-tmp-teleport")) { + this.oldLocation = (Location) this.getEntity().getMetadata("ps-tmp-teleport").get(0); + } else { + this.oldLocation = this.getEntity().getLocation(); + } + + // To account for offsets in the chunk manager + this.oldLocation = oldLocation.clone(); + this.oldLocation.setX(this.x); + this.oldLocation.setY(this.y); + this.oldLocation.setZ(this.z); + + this.gravityOld = this.getEntity().hasGravity(); + this.getEntity().setGravity(false); + this.invulnerableOld = this.getEntity().isInvulnerable(); + this.getEntity().setInvulnerable(true); + this.fireTicksOld = this.getEntity().getFireTicks(); + this.livingTicksOld = this.getEntity().getTicksLived(); + this.getEntity().setMetadata("ps-tmp-teleport", new FixedMetadataValue( + BukkitMain.getPlugin(BukkitMain.class), oldLocation)); + final Chunk newChunk = getNewChunk(); + this.getEntity().teleport(new Location(newChunk.getWorld(), newChunk.getX() >> 4, 5000, newChunk.getZ() >> 4)); + } + + private Chunk getNewChunk() { + final Chunk oldChunk = oldLocation.getChunk(); + Chunk chunk = null; + + for (Chunk lChunk : oldChunk.getWorld().getLoadedChunks()) { + if (!lChunk.equals(oldChunk) && lChunk.isLoaded()) { + chunk = lChunk; + break; + } + } + if (chunk == null) { + for (int dx = 1; dx < Integer.MAX_VALUE; dx++) { + for (int dz = 0; dz < Integer.MAX_VALUE; dz++) { + if ((chunk = getChunkRelative(oldChunk, dx, dz)).isLoaded()) { + break; + } else if ((chunk = getChunkRelative(oldChunk, -dx, dz)).isLoaded()) { + break; + } else if ((chunk = getChunkRelative(oldChunk, dx, -dz)).isLoaded()) { + break; + } else if ((chunk = getChunkRelative(oldChunk, -dx, -dz)).isLoaded()) { + break; + } + } + } + } + return chunk; + } + + private Chunk getChunkRelative(final Chunk chunk, final int dx, final int dz) { + return chunk.getWorld().getChunkAt(chunk.getX() + dx, chunk.getZ() + dz); + } +} diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/BukkitChunkManager.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/BukkitChunkManager.java index c5d9c37a9..31b7f84ce 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/BukkitChunkManager.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/BukkitChunkManager.java @@ -1,6 +1,7 @@ package com.github.intellectualsites.plotsquared.bukkit.util; import com.github.intellectualsites.plotsquared.bukkit.object.entity.EntityWrapper; +import com.github.intellectualsites.plotsquared.bukkit.object.entity.ReplicatingEntityWrapper; import com.github.intellectualsites.plotsquared.plot.PS; import com.github.intellectualsites.plotsquared.plot.generator.AugmentedUtils; import com.github.intellectualsites.plotsquared.plot.object.*; @@ -327,6 +328,9 @@ public class BukkitChunkManager extends ChunkManager { org.bukkit.Location location = entity.getLocation(); if (location.getX() >= bx && location.getX() <= tx && location.getZ() >= bz && location.getZ() <= tz) { + if (entity.hasMetadata("ps-tmp-teleport")) { + continue; + } entity.remove(); } } @@ -660,7 +664,8 @@ public class BukkitChunkManager extends ChunkManager { if (entity.getVehicle() != null) { continue; } - EntityWrapper wrap = new EntityWrapper(entity, (short) 2); + EntityWrapper wrap = new ReplicatingEntityWrapper(entity, (short) 2); + wrap.saveEntity(); this.entities.add(wrap); } } @@ -677,9 +682,10 @@ public class BukkitChunkManager extends ChunkManager { if (entity.getVehicle() != null) { continue; } - EntityWrapper wrap = new EntityWrapper(entity, (short) 2); + EntityWrapper wrap = new ReplicatingEntityWrapper(entity, (short) 2); wrap.x += offsetX; wrap.z += offsetZ; + wrap.saveEntity(); this.entities.add(wrap); if (delete) { if (!(entity instanceof Player)) { diff --git a/Bukkit/src/main/resources/plugin.yml b/Bukkit/src/main/resources/plugin.yml index 655f1d355..fd2f4bd95 100644 --- a/Bukkit/src/main/resources/plugin.yml +++ b/Bukkit/src/main/resources/plugin.yml @@ -1,5 +1,5 @@ name: ${name} -main: BukkitMain +main: com.github.intellectualsites.plotsquared.bukkit.BukkitMain version: ${version} load: STARTUP description: >