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