001/* 002 * PlotSquared, a land and world management plugin for Minecraft. 003 * Copyright (C) IntellectualSites <https://intellectualsites.com> 004 * Copyright (C) IntellectualSites team and contributors 005 * 006 * This program is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with this program. If not, see <https://www.gnu.org/licenses/>. 018 */ 019package com.plotsquared.bukkit.entity; 020 021import com.plotsquared.core.configuration.Settings; 022import org.apache.logging.log4j.LogManager; 023import org.apache.logging.log4j.Logger; 024import org.bukkit.Art; 025import org.bukkit.DyeColor; 026import org.bukkit.Location; 027import org.bukkit.Rotation; 028import org.bukkit.TreeSpecies; 029import org.bukkit.World; 030import org.bukkit.block.BlockFace; 031import org.bukkit.entity.AbstractHorse; 032import org.bukkit.entity.Ageable; 033import org.bukkit.entity.ArmorStand; 034import org.bukkit.entity.Bat; 035import org.bukkit.entity.Boat; 036import org.bukkit.entity.Breedable; 037import org.bukkit.entity.ChestedHorse; 038import org.bukkit.entity.EnderDragon; 039import org.bukkit.entity.Entity; 040import org.bukkit.entity.IronGolem; 041import org.bukkit.entity.Item; 042import org.bukkit.entity.ItemFrame; 043import org.bukkit.entity.LivingEntity; 044import org.bukkit.entity.Painting; 045import org.bukkit.entity.Rabbit; 046import org.bukkit.entity.Sheep; 047import org.bukkit.entity.Slime; 048import org.bukkit.entity.Tameable; 049import org.bukkit.inventory.EntityEquipment; 050import org.bukkit.inventory.InventoryHolder; 051import org.bukkit.inventory.ItemStack; 052import org.bukkit.util.EulerAngle; 053import org.bukkit.util.Vector; 054 055import java.util.List; 056 057public final class ReplicatingEntityWrapper extends EntityWrapper { 058 059 private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + ReplicatingEntityWrapper.class.getSimpleName()); 060 061 private final short depth; 062 private final int hash; 063 private final EntityBaseStats base = new EntityBaseStats(); 064 065 private ItemStack[] inventory; 066 // Extended 067 private ItemStack stack; 068 private byte dataByte; 069 private byte dataByte2; 070 private String dataString; 071 private LivingEntityStats lived; 072 private AgeableStats aged; 073 private TameableStats tamed; 074 private ArmorStandStats stand; 075 private HorseStats horse; 076 private boolean noGravity; 077 078 @SuppressWarnings("deprecation") // Deprecation exists since 1.20, while we support 1.16 onwards 079 public ReplicatingEntityWrapper(Entity entity, short depth) { 080 super(entity); 081 082 this.hash = entity.getEntityId(); 083 this.depth = depth; 084 085 if (depth == 0) { 086 return; 087 } 088 List<Entity> passengers = entity.getPassengers(); 089 if (passengers.size() > 0) { 090 this.base.passenger = new ReplicatingEntityWrapper(passengers.get(0), depth); 091 } 092 this.base.fall = entity.getFallDistance(); 093 this.base.fire = (short) entity.getFireTicks(); 094 this.base.age = entity.getTicksLived(); 095 Vector velocity = entity.getVelocity(); 096 this.base.vX = velocity.getX(); 097 this.base.vY = velocity.getY(); 098 this.base.vZ = velocity.getZ(); 099 if (depth == 1) { 100 return; 101 } 102 if (!entity.hasGravity()) { 103 this.noGravity = true; 104 } 105 switch (entity.getType().toString()) { 106 case "BOAT" -> { 107 Boat boat = (Boat) entity; 108 this.dataByte = getOrdinal(TreeSpecies.values(), boat.getWoodType()); 109 return; 110 } 111 case "ARROW", "EGG", "ENDER_CRYSTAL", "ENDER_PEARL", "ENDER_SIGNAL", "EXPERIENCE_ORB", "FALLING_BLOCK", "FIREBALL", 112 "FIREWORK", "FISHING_HOOK", "LEASH_HITCH", "LIGHTNING", "MINECART", "MINECART_COMMAND", "MINECART_MOB_SPAWNER", 113 "MINECART_TNT", "PLAYER", "PRIMED_TNT", "SLIME", "SMALL_FIREBALL", "SNOWBALL", "MINECART_FURNACE", "SPLASH_POTION", 114 "THROWN_EXP_BOTTLE", "WITHER_SKULL", "UNKNOWN", "SPECTRAL_ARROW", "SHULKER_BULLET", "DRAGON_FIREBALL", "AREA_EFFECT_CLOUD", 115 "TRIDENT", "LLAMA_SPIT" -> { 116 // Do this stuff later 117 return; 118 } 119 // MISC // 120 case "DROPPED_ITEM" -> { 121 Item item = (Item) entity; 122 this.stack = item.getItemStack(); 123 return; 124 } 125 case "ITEM_FRAME" -> { 126 this.x = Math.floor(this.getX()); 127 this.y = Math.floor(this.getY()); 128 this.z = Math.floor(this.getZ()); 129 ItemFrame itemFrame = (ItemFrame) entity; 130 this.dataByte = getOrdinal(Rotation.values(), itemFrame.getRotation()); 131 this.stack = itemFrame.getItem().clone(); 132 return; 133 } 134 case "PAINTING" -> { 135 this.x = Math.floor(this.getX()); 136 this.y = Math.floor(this.getY()); 137 this.z = Math.floor(this.getZ()); 138 Painting painting = (Painting) entity; 139 Art art = painting.getArt(); 140 this.dataByte = getOrdinal(BlockFace.values(), painting.getFacing()); 141 int h = art.getBlockHeight(); 142 if (h % 2 == 0) { 143 this.y -= 1; 144 } 145 this.dataString = art.name(); 146 return; 147 } 148 // END MISC // 149 // INVENTORY HOLDER // 150 case "MINECART_CHEST", "MINECART_HOPPER" -> { 151 storeInventory((InventoryHolder) entity); 152 return; 153 } 154 // START LIVING ENTITY // 155 // START AGEABLE // 156 // START TAMEABLE // 157 case "HORSE", "DONKEY", "LLAMA", "MULE", "SKELETON_HORSE" -> { 158 AbstractHorse horse = (AbstractHorse) entity; 159 this.horse = new HorseStats(); 160 this.horse.jump = horse.getJumpStrength(); 161 if (horse instanceof ChestedHorse horse1) { 162 this.horse.chest = horse1.isCarryingChest(); 163 } 164 //todo these horse features need fixing 165 //this.horse.variant = horse.getVariant(); 166 //this.horse.style = horse.getStyle(); 167 //this.horse.color = horse.getColor(); 168 storeTameable(horse); 169 storeBreedable(horse); 170 storeLiving(horse); 171 storeInventory(horse); 172 return; 173 } 174 // END INVENTORY HOLDER // 175 case "WOLF", "OCELOT" -> { 176 storeTameable((Tameable) entity); 177 storeBreedable((Breedable) entity); 178 storeLiving((LivingEntity) entity); 179 return; 180 } 181 // END TAMEABLE // 182 //todo fix sheep 183 case "SHEEP" -> { 184 Sheep sheep = (Sheep) entity; 185 if (sheep.isSheared()) { 186 this.dataByte = (byte) 1; 187 } else { 188 this.dataByte = (byte) 0; 189 } 190 this.dataByte2 = sheep.getColor().getDyeData(); 191 storeBreedable(sheep); 192 storeLiving(sheep); 193 return; 194 } 195 case "VILLAGER", "CHICKEN", "COW", "MUSHROOM_COW", "PIG", "TURTLE", "POLAR_BEAR" -> { 196 storeBreedable((Breedable) entity); 197 storeLiving((LivingEntity) entity); 198 return; 199 } 200 case "RABBIT" -> { 201 this.dataByte = getOrdinal(Rabbit.Type.values(), ((Rabbit) entity).getRabbitType()); 202 storeBreedable((Breedable) entity); 203 storeLiving((LivingEntity) entity); 204 return; 205 } 206 // END AGEABLE // 207 case "ARMOR_STAND" -> { 208 ArmorStand stand = (ArmorStand) entity; 209 this.inventory = 210 new ItemStack[]{stand.getItemInHand().clone(), stand.getHelmet().clone(), 211 stand.getChestplate().clone(), stand.getLeggings().clone(), 212 stand.getBoots().clone()}; 213 storeLiving(stand); 214 this.stand = new ArmorStandStats(); 215 EulerAngle head = stand.getHeadPose(); 216 this.stand.head[0] = (float) head.getX(); 217 this.stand.head[1] = (float) head.getY(); 218 this.stand.head[2] = (float) head.getZ(); 219 EulerAngle body = stand.getBodyPose(); 220 this.stand.body[0] = (float) body.getX(); 221 this.stand.body[1] = (float) body.getY(); 222 this.stand.body[2] = (float) body.getZ(); 223 EulerAngle leftLeg = stand.getLeftLegPose(); 224 this.stand.leftLeg[0] = (float) leftLeg.getX(); 225 this.stand.leftLeg[1] = (float) leftLeg.getY(); 226 this.stand.leftLeg[2] = (float) leftLeg.getZ(); 227 EulerAngle rightLeg = stand.getRightLegPose(); 228 this.stand.rightLeg[0] = (float) rightLeg.getX(); 229 this.stand.rightLeg[1] = (float) rightLeg.getY(); 230 this.stand.rightLeg[2] = (float) rightLeg.getZ(); 231 EulerAngle leftArm = stand.getLeftArmPose(); 232 this.stand.leftArm[0] = (float) leftArm.getX(); 233 this.stand.leftArm[1] = (float) leftArm.getY(); 234 this.stand.leftArm[2] = (float) leftArm.getZ(); 235 EulerAngle rightArm = stand.getRightArmPose(); 236 this.stand.rightArm[0] = (float) rightArm.getX(); 237 this.stand.rightArm[1] = (float) rightArm.getY(); 238 this.stand.rightArm[2] = (float) rightArm.getZ(); 239 if (stand.hasArms()) { 240 this.stand.arms = true; 241 } 242 if (!stand.hasBasePlate()) { 243 this.stand.noPlate = true; 244 } 245 if (!stand.isVisible()) { 246 this.stand.invisible = true; 247 } 248 if (stand.isSmall()) { 249 this.stand.small = true; 250 } 251 return; 252 } 253 case "ENDERMITE" -> { 254 return; 255 } 256 case "BAT" -> { 257 if (((Bat) entity).isAwake()) { 258 this.dataByte = (byte) 1; 259 } else { 260 this.dataByte = (byte) 0; 261 } 262 return; 263 } 264 case "ENDER_DRAGON" -> { 265 EnderDragon entity1 = (EnderDragon) entity; 266 this.dataByte = (byte) entity1.getPhase().ordinal(); 267 return; 268 } 269 case "SKELETON", "WITHER_SKELETON", "GUARDIAN", "ELDER_GUARDIAN", "GHAST", "MAGMA_CUBE", "SQUID", "PIG_ZOMBIE", "HOGLIN", 270 "ZOMBIFIED_PIGLIN", "PIGLIN", "PIGLIN_BRUTE", "ZOMBIE", "WITHER", "WITCH", "SPIDER", "CAVE_SPIDER", "SILVERFISH", 271 "GIANT", "ENDERMAN", "CREEPER", "BLAZE", "SHULKER", "SNOWMAN" -> { 272 storeLiving((LivingEntity) entity); 273 return; 274 } 275 case "IRON_GOLEM" -> { 276 if (((IronGolem) entity).isPlayerCreated()) { 277 this.dataByte = (byte) 1; 278 } else { 279 this.dataByte = (byte) 0; 280 } 281 storeLiving((LivingEntity) entity); 282 } 283 // END LIVING // 284 } 285 } 286 287 @Override 288 public boolean equals(Object obj) { 289 return this.hash == obj.hashCode(); 290 } 291 292 @Override 293 public int hashCode() { 294 return this.hash; 295 } 296 297 public void storeInventory(InventoryHolder held) { 298 this.inventory = held.getInventory().getContents().clone(); 299 } 300 301 void restoreLiving(LivingEntity entity) { 302 entity.setCanPickupItems(this.lived.loot); 303 if (this.lived.name != null) { 304 entity.setCustomName(this.lived.name); 305 entity.setCustomNameVisible(this.lived.visible); 306 } 307 if (this.lived.potions != null && !this.lived.potions.isEmpty()) { 308 entity.addPotionEffects(this.lived.potions); 309 } 310 entity.setRemainingAir(this.lived.air); 311 entity.setRemoveWhenFarAway(this.lived.persistent); 312 if (this.lived.equipped) { 313 this.restoreEquipment(entity); 314 } 315 if (this.lived.leashed) { 316 // TODO leashes 317 // World world = entity.getWorld(); 318 // Entity leash = world.spawnEntity(new Location(world, Math.floor(x) + 319 // lived.leashX, Math.floor(y) + lived.leashY, Math.floor(z) + lived.leashZ), 320 // EntityType.LEASH_HITCH); 321 // entity.setLeashHolder(leash); 322 } 323 } 324 325 void restoreEquipment(LivingEntity entity) { 326 EntityEquipment equipment = entity.getEquipment(); 327 if (equipment != null) { 328 equipment.setItemInMainHand(this.lived.mainHand); 329 equipment.setItemInOffHand(this.lived.offHand); 330 equipment.setHelmet(this.lived.helmet); 331 equipment.setChestplate(this.lived.chestplate); 332 equipment.setLeggings(this.lived.leggings); 333 equipment.setBoots(this.lived.boots); 334 } 335 } 336 337 private void restoreInventory(InventoryHolder entity) { 338 try { 339 entity.getInventory().setContents(this.inventory); 340 } catch (IllegalArgumentException e) { 341 LOGGER.error("Failed to restore inventory", e); 342 } 343 } 344 345 private void storeLiving(LivingEntity lived) { 346 this.lived = new LivingEntityStats(); 347 this.lived.potions = lived.getActivePotionEffects(); 348 this.lived.loot = lived.getCanPickupItems(); 349 this.lived.name = lived.getCustomName(); 350 this.lived.visible = lived.isCustomNameVisible(); 351 this.lived.health = (float) lived.getHealth(); 352 this.lived.air = (short) lived.getRemainingAir(); 353 this.lived.persistent = lived.getRemoveWhenFarAway(); 354 this.lived.leashed = lived.isLeashed(); 355 if (this.lived.leashed) { 356 Location location = lived.getLeashHolder().getLocation(); 357 this.lived.leashX = (short) (this.getX() - location.getBlockX()); 358 this.lived.leashY = (short) (this.getY() - location.getBlockY()); 359 this.lived.leashZ = (short) (this.getZ() - location.getBlockZ()); 360 } 361 EntityEquipment equipment = lived.getEquipment(); 362 this.lived.equipped = equipment != null; 363 if (this.lived.equipped) { 364 storeEquipment(equipment); 365 } 366 } 367 368 void storeEquipment(EntityEquipment equipment) { 369 this.lived.mainHand = equipment.getItemInMainHand().clone(); 370 this.lived.offHand = equipment.getItemInOffHand().clone(); 371 this.lived.boots = equipment.getBoots().clone(); 372 this.lived.leggings = equipment.getLeggings().clone(); 373 this.lived.chestplate = equipment.getChestplate().clone(); 374 this.lived.helmet = equipment.getHelmet().clone(); 375 } 376 377 private void restoreTameable(Tameable entity) { 378 if (this.tamed.tamed) { 379 if (this.tamed.owner != null) { 380 entity.setTamed(true); 381 entity.setOwner(this.tamed.owner); 382 } 383 } 384 } 385 386 /** 387 * @deprecated Use {@link #restoreBreedable(Breedable)} instead 388 * @since 7.1.0 389 */ 390 @Deprecated(forRemoval = true, since = "7.1.0") 391 private void restoreAgeable(Ageable entity) { 392 if (!this.aged.adult) { 393 entity.setBaby(); 394 } 395 entity.setAgeLock(this.aged.locked); 396 if (this.aged.age > 0) { 397 entity.setAge(this.aged.age); 398 } 399 } 400 401 /** 402 * @deprecated Use {@link #storeBreedable(Breedable)} instead 403 * @since 7.1.0 404 */ 405 @Deprecated(forRemoval = true, since = "7.1.0") 406 public void storeAgeable(Ageable aged) { 407 this.aged = new AgeableStats(); 408 this.aged.age = aged.getAge(); 409 this.aged.locked = aged.getAgeLock(); 410 this.aged.adult = aged.isAdult(); 411 } 412 413 /** 414 * @since 7.1.0 415 */ 416 private void restoreBreedable(Breedable entity) { 417 if (!this.aged.adult) { 418 entity.setBaby(); 419 } 420 entity.setAgeLock(this.aged.locked); 421 if (this.aged.age > 0) { 422 entity.setAge(this.aged.age); 423 } 424 } 425 426 /** 427 * @since 7.1.0 428 */ 429 private void storeBreedable(Breedable breedable) { 430 this.aged = new AgeableStats(); 431 this.aged.age = breedable.getAge(); 432 this.aged.locked = breedable.getAgeLock(); 433 this.aged.adult = breedable.isAdult(); 434 } 435 436 public void storeTameable(Tameable tamed) { 437 this.tamed = new TameableStats(); 438 this.tamed.owner = tamed.getOwner(); 439 this.tamed.tamed = tamed.isTamed(); 440 } 441 442 @SuppressWarnings("deprecation") // Paper deprecation 443 @Override 444 public Entity spawn(World world, int xOffset, int zOffset) { 445 Location location = new Location(world, this.getX() + xOffset, this.getY(), this.z + zOffset); 446 location.setYaw(this.yaw); 447 location.setPitch(this.pitch); 448 if (!this.getType().isSpawnable()) { 449 return null; 450 } 451 Entity entity; 452 switch (this.getType().toString()) { 453 case "DROPPED_ITEM" -> { 454 return world.dropItem(location, this.stack); 455 } 456 case "PLAYER", "LEASH_HITCH" -> { 457 return null; 458 } 459 case "ITEM_FRAME" -> entity = world.spawn(location, ItemFrame.class); 460 case "PAINTING" -> entity = world.spawn(location, Painting.class); 461 default -> entity = world.spawnEntity(location, this.getType()); 462 } 463 if (this.depth == 0) { 464 return entity; 465 } 466 if (this.base.passenger != null) { 467 try { 468 entity.addPassenger(this.base.passenger.spawn(world, xOffset, zOffset)); 469 } catch (Exception ignored) { 470 } 471 } 472 if (this.base.fall != 0) { 473 entity.setFallDistance(this.base.fall); 474 } 475 if (this.base.fire != 0) { 476 entity.setFireTicks(this.base.fire); 477 } 478 if (this.base.age != 0) { 479 entity.setTicksLived(this.base.age); 480 } 481 entity.setVelocity(new Vector(this.base.vX, this.base.vY, this.base.vZ)); 482 if (this.depth == 1) { 483 return entity; 484 } 485 if (this.noGravity) { 486 entity.setGravity(false); 487 } 488 switch (entity.getType().toString()) { 489 case "BOAT" -> { 490 Boat boat = (Boat) entity; 491 boat.setWoodType(TreeSpecies.values()[dataByte]); 492 return entity; 493 } 494 case "SLIME" -> { 495 ((Slime) entity).setSize(this.dataByte); 496 return entity; 497 } 498 case "ARROW", "EGG", "ENDER_CRYSTAL", "ENDER_PEARL", "ENDER_SIGNAL", "DROPPED_ITEM", "EXPERIENCE_ORB", "FALLING_BLOCK", 499 "FIREBALL", "FIREWORK", "FISHING_HOOK", "LEASH_HITCH", "LIGHTNING", "MINECART", "MINECART_COMMAND", 500 "MINECART_MOB_SPAWNER", "MINECART_TNT", "PLAYER", "PRIMED_TNT", "SMALL_FIREBALL", "SNOWBALL", 501 "SPLASH_POTION", "THROWN_EXP_BOTTLE", "SPECTRAL_ARROW", "SHULKER_BULLET", "AREA_EFFECT_CLOUD", 502 "DRAGON_FIREBALL", "WITHER_SKULL", "MINECART_FURNACE", "LLAMA_SPIT", "TRIDENT", "UNKNOWN" -> { 503 // Do this stuff later 504 return entity; 505 } 506 // MISC // 507 case "ITEM_FRAME" -> { 508 ItemFrame itemframe = (ItemFrame) entity; 509 itemframe.setRotation(Rotation.values()[this.dataByte]); 510 itemframe.setItem(this.stack); 511 return entity; 512 } 513 case "PAINTING" -> { 514 Painting painting = (Painting) entity; 515 painting.setFacingDirection(BlockFace.values()[this.dataByte], true); 516 painting.setArt(Art.getByName(this.dataString), true); 517 return entity; 518 } 519 // END MISC // 520 // INVENTORY HOLDER // 521 case "MINECART_CHEST", "MINECART_HOPPER" -> { 522 restoreInventory((InventoryHolder) entity); 523 return entity; 524 } 525 // START LIVING ENTITY // 526 // START AGEABLE // 527 // START TAMEABLE // 528 case "HORSE", "LLAMA", "SKELETON_HORSE", "DONKEY", "MULE" -> { 529 AbstractHorse horse = (AbstractHorse) entity; 530 horse.setJumpStrength(this.horse.jump); 531 if (horse instanceof ChestedHorse) { 532 ((ChestedHorse) horse).setCarryingChest(this.horse.chest); 533 } 534 //todo broken as of 1.13 535 //horse.setVariant(this.horse.variant); 536 //horse.setStyle(this.horse.style); 537 //horse.setColor(this.horse.color); 538 restoreTameable(horse); 539 restoreBreedable(horse); 540 restoreLiving(horse); 541 restoreInventory(horse); 542 return entity; 543 } 544 // END INVENTORY HOLDER // 545 case "WOLF", "OCELOT" -> { 546 restoreTameable((Tameable) entity); 547 restoreBreedable((Breedable) entity); 548 restoreLiving((LivingEntity) entity); 549 return entity; 550 } 551 // END AGEABLE // 552 case "SHEEP" -> { 553 Sheep sheep = (Sheep) entity; 554 if (this.dataByte == 1) { 555 sheep.setSheared(true); 556 } 557 if (this.dataByte2 != 0) { 558 sheep.setColor(DyeColor.getByDyeData(this.dataByte2)); 559 } 560 restoreBreedable(sheep); 561 restoreLiving(sheep); 562 return sheep; 563 } 564 case "VILLAGER", "CHICKEN", "COW", "TURTLE", "POLAR_BEAR", "MUSHROOM_COW", "PIG" -> { 565 restoreBreedable((Breedable) entity); 566 restoreLiving((LivingEntity) entity); 567 return entity; 568 } 569 // END AGEABLE // 570 case "RABBIT" -> { 571 if (this.dataByte != 0) { 572 ((Rabbit) entity).setRabbitType(Rabbit.Type.values()[this.dataByte]); 573 } 574 restoreBreedable((Breedable) entity); 575 restoreLiving((LivingEntity) entity); 576 return entity; 577 } 578 case "ARMOR_STAND" -> { 579 // CHECK positions 580 ArmorStand stand = (ArmorStand) entity; 581 if (this.inventory[0] != null) { 582 stand.setItemInHand(this.inventory[0]); 583 } 584 if (this.inventory[1] != null) { 585 stand.setHelmet(this.inventory[1]); 586 } 587 if (this.inventory[2] != null) { 588 stand.setChestplate(this.inventory[2]); 589 } 590 if (this.inventory[3] != null) { 591 stand.setLeggings(this.inventory[3]); 592 } 593 if (this.inventory[4] != null) { 594 stand.setBoots(this.inventory[4]); 595 } 596 if (this.stand.head[0] != 0 || this.stand.head[1] != 0 || this.stand.head[2] != 0) { 597 EulerAngle pose = 598 new EulerAngle(this.stand.head[0], this.stand.head[1], this.stand.head[2]); 599 stand.setHeadPose(pose); 600 } 601 if (this.stand.body[0] != 0 || this.stand.body[1] != 0 || this.stand.body[2] != 0) { 602 EulerAngle pose = 603 new EulerAngle(this.stand.body[0], this.stand.body[1], this.stand.body[2]); 604 stand.setBodyPose(pose); 605 } 606 if (this.stand.leftLeg[0] != 0 || this.stand.leftLeg[1] != 0 607 || this.stand.leftLeg[2] != 0) { 608 EulerAngle pose = new EulerAngle(this.stand.leftLeg[0], this.stand.leftLeg[1], 609 this.stand.leftLeg[2] 610 ); 611 stand.setLeftLegPose(pose); 612 } 613 if (this.stand.rightLeg[0] != 0 || this.stand.rightLeg[1] != 0 614 || this.stand.rightLeg[2] != 0) { 615 EulerAngle pose = new EulerAngle(this.stand.rightLeg[0], this.stand.rightLeg[1], 616 this.stand.rightLeg[2] 617 ); 618 stand.setRightLegPose(pose); 619 } 620 if (this.stand.leftArm[0] != 0 || this.stand.leftArm[1] != 0 621 || this.stand.leftArm[2] != 0) { 622 EulerAngle pose = new EulerAngle(this.stand.leftArm[0], this.stand.leftArm[1], 623 this.stand.leftArm[2] 624 ); 625 stand.setLeftArmPose(pose); 626 } 627 if (this.stand.rightArm[0] != 0 || this.stand.rightArm[1] != 0 628 || this.stand.rightArm[2] != 0) { 629 EulerAngle pose = new EulerAngle(this.stand.rightArm[0], this.stand.rightArm[1], 630 this.stand.rightArm[2] 631 ); 632 stand.setRightArmPose(pose); 633 } 634 if (this.stand.invisible) { 635 stand.setVisible(false); 636 } 637 if (this.stand.arms) { 638 stand.setArms(true); 639 } 640 if (this.stand.noPlate) { 641 stand.setBasePlate(false); 642 } 643 if (this.stand.small) { 644 stand.setSmall(true); 645 } 646 restoreLiving(stand); 647 return stand; 648 } 649 case "BAT" -> { 650 if (this.dataByte != 0) { 651 ((Bat) entity).setAwake(true); 652 } 653 restoreLiving((LivingEntity) entity); 654 return entity; 655 } 656 case "ENDER_DRAGON" -> { 657 if (this.dataByte != 0) { 658 ((EnderDragon) entity).setPhase(EnderDragon.Phase.values()[this.dataByte]); 659 } 660 restoreLiving((LivingEntity) entity); 661 return entity; 662 } 663 case "ENDERMITE", "GHAST", "MAGMA_CUBE", "SQUID", "PIG_ZOMBIE", "HOGLIN", "PIGLIN", "ZOMBIFIED_PIGLIN", "PIGLIN_BRUTE", "ZOMBIE", "WITHER", "WITCH", "SPIDER", "CAVE_SPIDER", "SILVERFISH", "GIANT", "ENDERMAN", "CREEPER", "BLAZE", "SNOWMAN", "SHULKER", "GUARDIAN", "ELDER_GUARDIAN", "SKELETON", "WITHER_SKELETON" -> { 664 restoreLiving((LivingEntity) entity); 665 return entity; 666 } 667 case "IRON_GOLEM" -> { 668 if (this.dataByte != 0) { 669 ((IronGolem) entity).setPlayerCreated(true); 670 } 671 restoreLiving((LivingEntity) entity); 672 return entity; 673 } 674 default -> { 675 if (Settings.DEBUG) { 676 LOGGER.info("Could not identify entity: {}", entity.getType()); 677 } 678 return entity; 679 } 680 // END LIVING 681 } 682 } 683 684 public void saveEntity() { 685 } 686 687 private byte getOrdinal(Object[] list, Object value) { 688 for (byte i = 0; i < list.length; i++) { 689 if (list[i].equals(value)) { 690 return i; 691 } 692 } 693 return 0; 694 } 695 696 697}