2020-04-16 04:52:39 +02:00
|
|
|
/*
|
|
|
|
* _____ _ _ _____ _
|
|
|
|
* | __ \| | | | / ____| | |
|
|
|
|
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
|
|
|
|
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
|
|
|
|
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
|
|
|
|
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
|
|
|
|
* | |
|
|
|
|
* |_|
|
|
|
|
* PlotSquared plot management system for Minecraft
|
2022-01-02 22:22:19 +01:00
|
|
|
* Copyright (C) 2014 - 2022 IntellectualSites
|
2020-04-16 04:52:39 +02:00
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
2020-08-15 14:59:29 +02:00
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
2020-04-16 04:52:39 +02:00
|
|
|
*/
|
2020-04-10 20:19:18 -04:00
|
|
|
package com.plotsquared.bukkit.entity;
|
2018-08-19 22:18:58 +02:00
|
|
|
|
2020-07-13 22:51:57 +02:00
|
|
|
import com.plotsquared.core.configuration.Settings;
|
2021-08-18 11:58:18 +02:00
|
|
|
import org.apache.logging.log4j.LogManager;
|
|
|
|
import org.apache.logging.log4j.Logger;
|
2019-05-17 18:49:09 -04:00
|
|
|
import org.bukkit.Art;
|
|
|
|
import org.bukkit.DyeColor;
|
|
|
|
import org.bukkit.Location;
|
|
|
|
import org.bukkit.Rotation;
|
|
|
|
import org.bukkit.TreeSpecies;
|
|
|
|
import org.bukkit.World;
|
2018-08-19 22:18:58 +02:00
|
|
|
import org.bukkit.block.BlockFace;
|
2019-11-04 17:44:23 +00:00
|
|
|
import org.bukkit.entity.AbstractHorse;
|
|
|
|
import org.bukkit.entity.Ageable;
|
|
|
|
import org.bukkit.entity.ArmorStand;
|
|
|
|
import org.bukkit.entity.Bat;
|
|
|
|
import org.bukkit.entity.Boat;
|
|
|
|
import org.bukkit.entity.ChestedHorse;
|
|
|
|
import org.bukkit.entity.EnderDragon;
|
|
|
|
import org.bukkit.entity.Entity;
|
|
|
|
import org.bukkit.entity.IronGolem;
|
|
|
|
import org.bukkit.entity.Item;
|
|
|
|
import org.bukkit.entity.ItemFrame;
|
|
|
|
import org.bukkit.entity.LivingEntity;
|
|
|
|
import org.bukkit.entity.Painting;
|
|
|
|
import org.bukkit.entity.Rabbit;
|
|
|
|
import org.bukkit.entity.Sheep;
|
|
|
|
import org.bukkit.entity.Slime;
|
|
|
|
import org.bukkit.entity.Tameable;
|
2018-08-19 22:18:58 +02:00
|
|
|
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;
|
|
|
|
|
2019-03-08 23:04:38 +00:00
|
|
|
import java.util.List;
|
|
|
|
|
2018-08-19 22:18:58 +02:00
|
|
|
public final class ReplicatingEntityWrapper extends EntityWrapper {
|
|
|
|
|
2021-06-03 12:40:27 +02:00
|
|
|
private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + ReplicatingEntityWrapper.class.getSimpleName());
|
2020-07-12 21:49:05 +02:00
|
|
|
|
2019-02-04 14:02:21 +00:00
|
|
|
private final short depth;
|
|
|
|
private final int hash;
|
|
|
|
private final EntityBaseStats base = new EntityBaseStats();
|
|
|
|
|
2019-02-15 12:50:43 -05:00
|
|
|
private ItemStack[] inventory;
|
2019-02-04 14:02:21 +00:00
|
|
|
// 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;
|
|
|
|
}
|
2019-03-08 23:04:38 +00:00
|
|
|
List<Entity> passengers = entity.getPassengers();
|
|
|
|
if (passengers.size() > 0) {
|
|
|
|
this.base.passenger = new ReplicatingEntityWrapper(passengers.get(0), depth);
|
2019-02-04 14:02:21 +00:00
|
|
|
}
|
|
|
|
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 (!entity.hasGravity()) {
|
|
|
|
this.noGravity = true;
|
|
|
|
}
|
2020-06-29 22:05:32 -04:00
|
|
|
switch (entity.getType().toString()) {
|
|
|
|
case "BOAT":
|
2019-02-04 14:02:21 +00:00
|
|
|
Boat boat = (Boat) entity;
|
|
|
|
this.dataByte = getOrdinal(TreeSpecies.values(), boat.getWoodType());
|
|
|
|
return;
|
2020-06-29 22:05:32 -04:00
|
|
|
case "ARROW":
|
|
|
|
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 "WITHER_SKULL":
|
|
|
|
case "UNKNOWN":
|
|
|
|
case "SPECTRAL_ARROW":
|
|
|
|
case "SHULKER_BULLET":
|
|
|
|
case "DRAGON_FIREBALL":
|
|
|
|
case "AREA_EFFECT_CLOUD":
|
|
|
|
case "TRIDENT":
|
|
|
|
case "LLAMA_SPIT":
|
2019-02-04 14:02:21 +00:00
|
|
|
// Do this stuff later
|
|
|
|
return;
|
|
|
|
// MISC //
|
2020-06-29 22:05:32 -04:00
|
|
|
case "DROPPED_ITEM":
|
2019-02-04 14:02:21 +00:00
|
|
|
Item item = (Item) entity;
|
|
|
|
this.stack = item.getItemStack();
|
|
|
|
return;
|
2020-06-29 22:05:32 -04:00
|
|
|
case "ITEM_FRAME":
|
2020-07-18 11:05:16 +02:00
|
|
|
this.x = Math.floor(this.getX());
|
|
|
|
this.y = Math.floor(this.getY());
|
2020-07-18 16:08:37 +02:00
|
|
|
this.z = Math.floor(this.getZ());
|
2019-02-04 14:02:21 +00:00
|
|
|
ItemFrame itemFrame = (ItemFrame) entity;
|
|
|
|
this.dataByte = getOrdinal(Rotation.values(), itemFrame.getRotation());
|
|
|
|
this.stack = itemFrame.getItem().clone();
|
|
|
|
return;
|
2020-06-29 22:05:32 -04:00
|
|
|
case "PAINTING":
|
2020-07-18 11:05:16 +02:00
|
|
|
this.x = Math.floor(this.getX());
|
|
|
|
this.y = Math.floor(this.getY());
|
2020-07-18 16:08:37 +02:00
|
|
|
this.z = Math.floor(this.getZ());
|
2019-02-04 14:02:21 +00:00
|
|
|
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 //
|
2020-06-29 22:05:32 -04:00
|
|
|
case "MINECART_CHEST":
|
|
|
|
case "MINECART_HOPPER":
|
2019-02-04 14:02:21 +00:00
|
|
|
storeInventory((InventoryHolder) entity);
|
|
|
|
return;
|
|
|
|
// START LIVING ENTITY //
|
|
|
|
// START AGEABLE //
|
|
|
|
// START TAMEABLE //
|
2020-06-29 22:05:32 -04:00
|
|
|
case "HORSE":
|
|
|
|
case "DONKEY":
|
|
|
|
case "LLAMA":
|
|
|
|
case "MULE":
|
|
|
|
case "SKELETON_HORSE":
|
2019-02-15 12:50:43 -05:00
|
|
|
AbstractHorse horse = (AbstractHorse) entity;
|
2019-02-04 14:02:21 +00:00
|
|
|
this.horse = new HorseStats();
|
|
|
|
this.horse.jump = horse.getJumpStrength();
|
2021-05-15 20:39:16 +02:00
|
|
|
if (horse instanceof ChestedHorse horse1) {
|
2019-02-15 12:50:43 -05:00
|
|
|
this.horse.chest = horse1.isCarryingChest();
|
|
|
|
}
|
2019-02-21 21:14:48 -05:00
|
|
|
//todo these horse features need fixing
|
2019-02-15 12:50:43 -05:00
|
|
|
//this.horse.variant = horse.getVariant();
|
|
|
|
//this.horse.style = horse.getStyle();
|
|
|
|
//this.horse.color = horse.getColor();
|
2019-02-04 14:02:21 +00:00
|
|
|
storeTameable(horse);
|
|
|
|
storeAgeable(horse);
|
|
|
|
storeLiving(horse);
|
|
|
|
storeInventory(horse);
|
|
|
|
return;
|
|
|
|
// END INVENTORY HOLDER //
|
2020-06-29 22:05:32 -04:00
|
|
|
case "WOLF":
|
|
|
|
case "OCELOT":
|
2019-02-04 14:02:21 +00:00
|
|
|
storeTameable((Tameable) entity);
|
|
|
|
storeAgeable((Ageable) entity);
|
|
|
|
storeLiving((LivingEntity) entity);
|
|
|
|
return;
|
|
|
|
// END TAMEABLE //
|
2019-04-23 13:45:24 -04:00
|
|
|
//todo fix sheep
|
2020-06-29 22:05:32 -04:00
|
|
|
case "SHEEP":
|
2019-02-04 14:02:21 +00:00
|
|
|
Sheep sheep = (Sheep) entity;
|
2019-04-23 13:45:24 -04:00
|
|
|
if (sheep.isSheared()) {
|
|
|
|
this.dataByte = (byte) 1;
|
|
|
|
} else {
|
|
|
|
this.dataByte = (byte) 0;
|
|
|
|
}
|
2019-02-04 14:02:21 +00:00
|
|
|
this.dataByte2 = sheep.getColor().getDyeData();
|
|
|
|
storeAgeable(sheep);
|
|
|
|
storeLiving(sheep);
|
|
|
|
return;
|
2020-06-29 22:05:32 -04:00
|
|
|
case "VILLAGER":
|
|
|
|
case "CHICKEN":
|
|
|
|
case "COW":
|
|
|
|
case "MUSHROOM_COW":
|
|
|
|
case "PIG":
|
|
|
|
case "TURTLE":
|
|
|
|
case "POLAR_BEAR":
|
2019-02-04 14:02:21 +00:00
|
|
|
storeAgeable((Ageable) entity);
|
|
|
|
storeLiving((LivingEntity) entity);
|
|
|
|
return;
|
2020-06-29 22:05:32 -04:00
|
|
|
case "RABBIT":
|
2019-02-04 14:02:21 +00:00
|
|
|
this.dataByte = getOrdinal(Rabbit.Type.values(), ((Rabbit) entity).getRabbitType());
|
|
|
|
storeAgeable((Ageable) entity);
|
|
|
|
storeLiving((LivingEntity) entity);
|
|
|
|
return;
|
|
|
|
// END AGEABLE //
|
2020-06-29 22:05:32 -04:00
|
|
|
case "ARMOR_STAND":
|
2019-02-04 14:02:21 +00:00
|
|
|
ArmorStand stand = (ArmorStand) entity;
|
|
|
|
this.inventory =
|
2021-01-09 22:28:41 +01:00
|
|
|
new ItemStack[]{stand.getItemInHand().clone(), stand.getHelmet().clone(),
|
|
|
|
stand.getChestplate().clone(), stand.getLeggings().clone(),
|
|
|
|
stand.getBoots().clone()};
|
2019-02-04 14:02:21 +00:00
|
|
|
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;
|
2020-06-29 22:05:32 -04:00
|
|
|
case "ENDERMITE":
|
2019-02-04 14:02:21 +00:00
|
|
|
return;
|
2020-06-29 22:05:32 -04:00
|
|
|
case "BAT":
|
2019-02-04 14:02:21 +00:00
|
|
|
if (((Bat) entity).isAwake()) {
|
|
|
|
this.dataByte = (byte) 1;
|
|
|
|
} else {
|
|
|
|
this.dataByte = (byte) 0;
|
|
|
|
}
|
|
|
|
return;
|
2020-06-29 22:05:32 -04:00
|
|
|
case "ENDER_DRAGON":
|
2019-02-04 14:02:21 +00:00
|
|
|
EnderDragon entity1 = (EnderDragon) entity;
|
|
|
|
this.dataByte = (byte) entity1.getPhase().ordinal();
|
|
|
|
return;
|
2020-06-29 22:05:32 -04:00
|
|
|
case "SKELETON":
|
|
|
|
case "WITHER_SKELETON":
|
|
|
|
case "GUARDIAN":
|
|
|
|
case "ELDER_GUARDIAN":
|
|
|
|
case "GHAST":
|
|
|
|
case "MAGMA_CUBE":
|
|
|
|
case "SQUID":
|
|
|
|
case "PIG_ZOMBIE":
|
|
|
|
case "HOGLIN":
|
|
|
|
case "ZOMBIFIED_PIGLIN":
|
|
|
|
case "PIGLIN":
|
2020-08-11 16:20:33 +02:00
|
|
|
case "PIGLIN_BRUTE":
|
2020-06-29 22:05:32 -04:00
|
|
|
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":
|
2019-02-04 14:02:21 +00:00
|
|
|
storeLiving((LivingEntity) entity);
|
|
|
|
return;
|
2020-06-29 22:05:32 -04:00
|
|
|
case "IRON_GOLEM":
|
2019-02-04 14:02:21 +00:00
|
|
|
if (((IronGolem) entity).isPlayerCreated()) {
|
|
|
|
this.dataByte = (byte) 1;
|
|
|
|
} else {
|
|
|
|
this.dataByte = (byte) 0;
|
|
|
|
}
|
|
|
|
storeLiving((LivingEntity) entity);
|
2021-01-09 22:28:41 +01:00
|
|
|
// END LIVING //
|
2019-02-04 14:02:21 +00:00
|
|
|
}
|
2018-08-19 22:18:58 +02:00
|
|
|
}
|
2019-02-04 14:02:21 +00:00
|
|
|
|
2021-01-09 22:28:41 +01:00
|
|
|
@Override
|
|
|
|
public boolean equals(Object obj) {
|
2019-02-04 14:02:21 +00:00
|
|
|
return this.hash == obj.hashCode();
|
2019-01-31 14:20:48 -05:00
|
|
|
}
|
2019-02-04 14:02:21 +00:00
|
|
|
|
2021-01-09 22:28:41 +01:00
|
|
|
@Override
|
|
|
|
public int hashCode() {
|
2019-02-04 14:02:21 +00:00
|
|
|
return this.hash;
|
2019-01-31 14:20:48 -05:00
|
|
|
}
|
2019-02-04 14:02:21 +00:00
|
|
|
|
|
|
|
public void storeInventory(InventoryHolder held) {
|
|
|
|
this.inventory = held.getInventory().getContents().clone();
|
2019-01-31 14:20:48 -05:00
|
|
|
}
|
2019-02-04 14:02:21 +00:00
|
|
|
|
|
|
|
void restoreLiving(LivingEntity entity) {
|
|
|
|
entity.setCanPickupItems(this.lived.loot);
|
|
|
|
if (this.lived.name != null) {
|
|
|
|
entity.setCustomName(this.lived.name);
|
|
|
|
entity.setCustomNameVisible(this.lived.visible);
|
2018-08-19 22:18:58 +02:00
|
|
|
}
|
2019-02-04 14:02:21 +00:00
|
|
|
if (this.lived.potions != null && !this.lived.potions.isEmpty()) {
|
|
|
|
entity.addPotionEffects(this.lived.potions);
|
2018-08-19 22:18:58 +02:00
|
|
|
}
|
2019-02-04 14:02:21 +00:00
|
|
|
entity.setRemainingAir(this.lived.air);
|
|
|
|
entity.setRemoveWhenFarAway(this.lived.persistent);
|
|
|
|
if (this.lived.equipped) {
|
|
|
|
this.restoreEquipment(entity);
|
2018-08-19 22:18:58 +02:00
|
|
|
}
|
2019-02-04 14:02:21 +00:00
|
|
|
if (this.lived.leashed) {
|
|
|
|
// TODO leashes
|
|
|
|
// World world = entity.getWorld();
|
2019-04-24 16:11:24 -04:00
|
|
|
// 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);
|
2019-02-04 14:02:21 +00:00
|
|
|
// entity.setLeashHolder(leash);
|
2019-01-31 14:20:48 -05:00
|
|
|
}
|
2018-08-19 22:18:58 +02:00
|
|
|
}
|
|
|
|
|
2019-02-04 14:02:21 +00:00
|
|
|
void restoreEquipment(LivingEntity entity) {
|
|
|
|
EntityEquipment equipment = entity.getEquipment();
|
2019-04-23 13:45:24 -04:00
|
|
|
if (equipment != null) {
|
|
|
|
equipment.setItemInMainHand(this.lived.mainHand);
|
|
|
|
equipment.setItemInOffHand(this.lived.offHand);
|
|
|
|
equipment.setHelmet(this.lived.helmet);
|
|
|
|
equipment.setChestplate(this.lived.chestplate);
|
|
|
|
equipment.setLeggings(this.lived.leggings);
|
|
|
|
equipment.setBoots(this.lived.boots);
|
|
|
|
}
|
2019-01-31 14:20:48 -05:00
|
|
|
}
|
2019-02-04 14:02:21 +00:00
|
|
|
|
|
|
|
private void restoreInventory(InventoryHolder entity) {
|
|
|
|
try {
|
|
|
|
entity.getInventory().setContents(this.inventory);
|
|
|
|
} catch (IllegalArgumentException e) {
|
2021-06-03 12:40:27 +02:00
|
|
|
LOGGER.error("Failed to restore inventory", e);
|
2019-02-04 14:02:21 +00:00
|
|
|
}
|
2019-01-31 14:20:48 -05:00
|
|
|
}
|
2019-02-04 14:02:21 +00:00
|
|
|
|
2019-04-24 16:11:24 -04:00
|
|
|
private void storeLiving(LivingEntity lived) {
|
2019-02-04 14:02:21 +00:00
|
|
|
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();
|
2020-07-18 11:05:16 +02:00
|
|
|
this.lived.leashX = (short) (this.getX() - location.getBlockX());
|
|
|
|
this.lived.leashY = (short) (this.getY() - location.getBlockY());
|
2020-07-18 16:08:37 +02:00
|
|
|
this.lived.leashZ = (short) (this.getZ() - location.getBlockZ());
|
2019-02-04 14:02:21 +00:00
|
|
|
}
|
|
|
|
EntityEquipment equipment = lived.getEquipment();
|
|
|
|
this.lived.equipped = equipment != null;
|
|
|
|
if (this.lived.equipped) {
|
|
|
|
storeEquipment(equipment);
|
|
|
|
}
|
2019-01-31 14:20:48 -05:00
|
|
|
}
|
2019-02-04 14:02:21 +00:00
|
|
|
|
|
|
|
void storeEquipment(EntityEquipment equipment) {
|
|
|
|
this.lived.mainHand = equipment.getItemInMainHand().clone();
|
|
|
|
this.lived.offHand = equipment.getItemInOffHand().clone();
|
|
|
|
this.lived.boots = equipment.getBoots().clone();
|
|
|
|
this.lived.leggings = equipment.getLeggings().clone();
|
|
|
|
this.lived.chestplate = equipment.getChestplate().clone();
|
|
|
|
this.lived.helmet = equipment.getHelmet().clone();
|
2019-01-31 14:20:48 -05:00
|
|
|
}
|
2019-02-04 14:02:21 +00:00
|
|
|
|
|
|
|
private void restoreTameable(Tameable entity) {
|
|
|
|
if (this.tamed.tamed) {
|
|
|
|
if (this.tamed.owner != null) {
|
|
|
|
entity.setTamed(true);
|
|
|
|
entity.setOwner(this.tamed.owner);
|
|
|
|
}
|
|
|
|
}
|
2019-01-31 14:20:48 -05:00
|
|
|
}
|
2019-02-04 14:02:21 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2019-01-31 14:20:48 -05:00
|
|
|
}
|
2019-02-04 14:02:21 +00:00
|
|
|
|
|
|
|
public void storeAgeable(Ageable aged) {
|
|
|
|
this.aged = new AgeableStats();
|
|
|
|
this.aged.age = aged.getAge();
|
|
|
|
this.aged.locked = aged.getAgeLock();
|
|
|
|
this.aged.adult = aged.isAdult();
|
2019-01-31 14:20:48 -05:00
|
|
|
}
|
2019-02-04 14:02:21 +00:00
|
|
|
|
|
|
|
public void storeTameable(Tameable tamed) {
|
|
|
|
this.tamed = new TameableStats();
|
|
|
|
this.tamed.owner = tamed.getOwner();
|
|
|
|
this.tamed.tamed = tamed.isTamed();
|
2018-08-19 22:18:58 +02:00
|
|
|
}
|
2019-02-04 14:02:21 +00:00
|
|
|
|
2021-01-09 22:28:41 +01:00
|
|
|
@Override
|
|
|
|
public Entity spawn(World world, int xOffset, int zOffset) {
|
2020-07-18 11:05:16 +02:00
|
|
|
Location location = new Location(world, this.getX() + xOffset, this.getY(), this.z + zOffset);
|
2019-02-04 14:02:21 +00:00
|
|
|
location.setYaw(this.yaw);
|
|
|
|
location.setPitch(this.pitch);
|
|
|
|
if (!this.getType().isSpawnable()) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
Entity entity;
|
2020-06-29 22:05:32 -04:00
|
|
|
switch (this.getType().toString()) {
|
|
|
|
case "DROPPED_ITEM":
|
2019-02-04 14:02:21 +00:00
|
|
|
return world.dropItem(location, this.stack);
|
2020-06-29 22:05:32 -04:00
|
|
|
case "PLAYER":
|
|
|
|
case "LEASH_HITCH":
|
2019-02-04 14:02:21 +00:00
|
|
|
return null;
|
2020-06-29 22:05:32 -04:00
|
|
|
case "ITEM_FRAME":
|
2019-02-04 14:02:21 +00:00
|
|
|
entity = world.spawn(location, ItemFrame.class);
|
|
|
|
break;
|
2020-06-29 22:05:32 -04:00
|
|
|
case "PAINTING":
|
2019-02-04 14:02:21 +00:00
|
|
|
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) {
|
2019-02-04 15:18:50 +00:00
|
|
|
try {
|
2019-02-13 12:05:28 -05:00
|
|
|
entity.addPassenger(this.base.passenger.spawn(world, xOffset, zOffset));
|
2019-02-04 15:18:50 +00:00
|
|
|
} catch (Exception ignored) {
|
|
|
|
}
|
2019-02-04 14:02:21 +00:00
|
|
|
}
|
|
|
|
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 (this.noGravity) {
|
|
|
|
entity.setGravity(false);
|
|
|
|
}
|
2020-06-29 22:05:32 -04:00
|
|
|
switch (entity.getType().toString()) {
|
|
|
|
case "BOAT":
|
2019-02-04 14:02:21 +00:00
|
|
|
Boat boat = (Boat) entity;
|
|
|
|
boat.setWoodType(TreeSpecies.values()[dataByte]);
|
|
|
|
return entity;
|
2020-06-29 22:05:32 -04:00
|
|
|
case "SLIME":
|
2019-02-04 14:02:21 +00:00
|
|
|
((Slime) entity).setSize(this.dataByte);
|
|
|
|
return entity;
|
2020-06-29 22:05:32 -04:00
|
|
|
case "ARROW":
|
|
|
|
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":
|
|
|
|
case "SMALL_FIREBALL":
|
|
|
|
case "SNOWBALL":
|
|
|
|
case "SPLASH_POTION":
|
|
|
|
case "THROWN_EXP_BOTTLE":
|
|
|
|
case "SPECTRAL_ARROW":
|
|
|
|
case "SHULKER_BULLET":
|
|
|
|
case "AREA_EFFECT_CLOUD":
|
|
|
|
case "DRAGON_FIREBALL":
|
|
|
|
case "WITHER_SKULL":
|
|
|
|
case "MINECART_FURNACE":
|
|
|
|
case "LLAMA_SPIT":
|
|
|
|
case "TRIDENT":
|
|
|
|
case "UNKNOWN":
|
2019-02-04 14:02:21 +00:00
|
|
|
// Do this stuff later
|
|
|
|
return entity;
|
|
|
|
// MISC //
|
2020-06-29 22:05:32 -04:00
|
|
|
case "ITEM_FRAME":
|
2019-02-04 14:02:21 +00:00
|
|
|
ItemFrame itemframe = (ItemFrame) entity;
|
|
|
|
itemframe.setRotation(Rotation.values()[this.dataByte]);
|
|
|
|
itemframe.setItem(this.stack);
|
|
|
|
return entity;
|
2020-06-29 22:05:32 -04:00
|
|
|
case "PAINTING":
|
2019-02-04 14:02:21 +00:00
|
|
|
Painting painting = (Painting) entity;
|
|
|
|
painting.setFacingDirection(BlockFace.values()[this.dataByte], true);
|
|
|
|
painting.setArt(Art.getByName(this.dataString), true);
|
|
|
|
return entity;
|
|
|
|
// END MISC //
|
|
|
|
// INVENTORY HOLDER //
|
2020-06-29 22:05:32 -04:00
|
|
|
case "MINECART_CHEST":
|
|
|
|
case "MINECART_HOPPER":
|
2019-02-04 14:02:21 +00:00
|
|
|
restoreInventory((InventoryHolder) entity);
|
|
|
|
return entity;
|
|
|
|
// START LIVING ENTITY //
|
|
|
|
// START AGEABLE //
|
|
|
|
// START TAMEABLE //
|
2020-06-29 22:05:32 -04:00
|
|
|
case "HORSE":
|
|
|
|
case "LLAMA":
|
|
|
|
case "SKELETON_HORSE":
|
|
|
|
case "DONKEY":
|
|
|
|
case "MULE":
|
2019-02-15 12:50:43 -05:00
|
|
|
AbstractHorse horse = (AbstractHorse) entity;
|
2019-02-04 14:02:21 +00:00
|
|
|
horse.setJumpStrength(this.horse.jump);
|
2019-02-15 12:50:43 -05:00
|
|
|
if (horse instanceof ChestedHorse) {
|
|
|
|
((ChestedHorse) horse).setCarryingChest(this.horse.chest);
|
|
|
|
}
|
|
|
|
//todo broken as of 1.13
|
|
|
|
//horse.setVariant(this.horse.variant);
|
|
|
|
//horse.setStyle(this.horse.style);
|
|
|
|
//horse.setColor(this.horse.color);
|
2019-02-04 14:02:21 +00:00
|
|
|
restoreTameable(horse);
|
|
|
|
restoreAgeable(horse);
|
|
|
|
restoreLiving(horse);
|
|
|
|
restoreInventory(horse);
|
|
|
|
return entity;
|
|
|
|
// END INVENTORY HOLDER //
|
2020-06-29 22:05:32 -04:00
|
|
|
case "WOLF":
|
|
|
|
case "OCELOT":
|
2019-02-04 14:02:21 +00:00
|
|
|
restoreTameable((Tameable) entity);
|
|
|
|
restoreAgeable((Ageable) entity);
|
|
|
|
restoreLiving((LivingEntity) entity);
|
|
|
|
return entity;
|
|
|
|
// END AGEABLE //
|
2020-06-29 22:05:32 -04:00
|
|
|
case "SHEEP":
|
2019-02-04 14:02:21 +00:00
|
|
|
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;
|
2020-06-29 22:05:32 -04:00
|
|
|
case "VILLAGER":
|
|
|
|
case "CHICKEN":
|
|
|
|
case "COW":
|
|
|
|
case "TURTLE":
|
|
|
|
case "POLAR_BEAR":
|
|
|
|
case "MUSHROOM_COW":
|
|
|
|
case "PIG":
|
2019-02-04 14:02:21 +00:00
|
|
|
restoreAgeable((Ageable) entity);
|
|
|
|
restoreLiving((LivingEntity) entity);
|
|
|
|
return entity;
|
|
|
|
// END AGEABLE //
|
2020-06-29 22:05:32 -04:00
|
|
|
case "RABBIT":
|
2019-02-04 14:02:21 +00:00
|
|
|
if (this.dataByte != 0) {
|
|
|
|
((Rabbit) entity).setRabbitType(Rabbit.Type.values()[this.dataByte]);
|
|
|
|
}
|
|
|
|
restoreAgeable((Ageable) entity);
|
|
|
|
restoreLiving((LivingEntity) entity);
|
|
|
|
return entity;
|
2020-06-29 22:05:32 -04:00
|
|
|
case "ARMOR_STAND":
|
2019-02-04 14:02:21 +00:00
|
|
|
// 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 =
|
2021-01-09 22:28:41 +01:00
|
|
|
new EulerAngle(this.stand.head[0], this.stand.head[1], this.stand.head[2]);
|
2019-02-04 14:02:21 +00:00
|
|
|
stand.setHeadPose(pose);
|
|
|
|
}
|
|
|
|
if (this.stand.body[0] != 0 || this.stand.body[1] != 0 || this.stand.body[2] != 0) {
|
|
|
|
EulerAngle pose =
|
2021-01-09 22:28:41 +01:00
|
|
|
new EulerAngle(this.stand.body[0], this.stand.body[1], this.stand.body[2]);
|
2019-02-04 14:02:21 +00:00
|
|
|
stand.setBodyPose(pose);
|
|
|
|
}
|
|
|
|
if (this.stand.leftLeg[0] != 0 || this.stand.leftLeg[1] != 0
|
2021-01-09 22:28:41 +01:00
|
|
|
|| this.stand.leftLeg[2] != 0) {
|
2019-02-04 14:02:21 +00:00
|
|
|
EulerAngle pose = new EulerAngle(this.stand.leftLeg[0], this.stand.leftLeg[1],
|
2021-01-09 22:28:41 +01:00
|
|
|
this.stand.leftLeg[2]
|
|
|
|
);
|
2019-02-04 14:02:21 +00:00
|
|
|
stand.setLeftLegPose(pose);
|
|
|
|
}
|
|
|
|
if (this.stand.rightLeg[0] != 0 || this.stand.rightLeg[1] != 0
|
2021-01-09 22:28:41 +01:00
|
|
|
|| this.stand.rightLeg[2] != 0) {
|
2019-02-04 14:02:21 +00:00
|
|
|
EulerAngle pose = new EulerAngle(this.stand.rightLeg[0], this.stand.rightLeg[1],
|
2021-01-09 22:28:41 +01:00
|
|
|
this.stand.rightLeg[2]
|
|
|
|
);
|
2019-02-04 14:02:21 +00:00
|
|
|
stand.setRightLegPose(pose);
|
|
|
|
}
|
|
|
|
if (this.stand.leftArm[0] != 0 || this.stand.leftArm[1] != 0
|
2021-01-09 22:28:41 +01:00
|
|
|
|| this.stand.leftArm[2] != 0) {
|
2019-02-04 14:02:21 +00:00
|
|
|
EulerAngle pose = new EulerAngle(this.stand.leftArm[0], this.stand.leftArm[1],
|
2021-01-09 22:28:41 +01:00
|
|
|
this.stand.leftArm[2]
|
|
|
|
);
|
2019-02-04 14:02:21 +00:00
|
|
|
stand.setLeftArmPose(pose);
|
|
|
|
}
|
|
|
|
if (this.stand.rightArm[0] != 0 || this.stand.rightArm[1] != 0
|
2021-01-09 22:28:41 +01:00
|
|
|
|| this.stand.rightArm[2] != 0) {
|
2019-02-04 14:02:21 +00:00
|
|
|
EulerAngle pose = new EulerAngle(this.stand.rightArm[0], this.stand.rightArm[1],
|
2021-01-09 22:28:41 +01:00
|
|
|
this.stand.rightArm[2]
|
|
|
|
);
|
2019-02-04 14:02:21 +00:00
|
|
|
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;
|
2020-06-29 22:05:32 -04:00
|
|
|
case "BAT":
|
2019-02-04 14:02:21 +00:00
|
|
|
if (this.dataByte != 0) {
|
|
|
|
((Bat) entity).setAwake(true);
|
|
|
|
}
|
|
|
|
restoreLiving((LivingEntity) entity);
|
|
|
|
return entity;
|
2020-06-29 22:05:32 -04:00
|
|
|
case "ENDER_DRAGON":
|
2019-02-04 14:02:21 +00:00
|
|
|
if (this.dataByte != 0) {
|
|
|
|
((EnderDragon) entity).setPhase(EnderDragon.Phase.values()[this.dataByte]);
|
|
|
|
}
|
|
|
|
restoreLiving((LivingEntity) entity);
|
|
|
|
return entity;
|
2020-06-29 22:05:32 -04:00
|
|
|
case "ENDERMITE":
|
|
|
|
case "GHAST":
|
|
|
|
case "MAGMA_CUBE":
|
|
|
|
case "SQUID":
|
|
|
|
case "PIG_ZOMBIE":
|
|
|
|
case "HOGLIN":
|
|
|
|
case "PIGLIN":
|
|
|
|
case "ZOMBIFIED_PIGLIN":
|
2020-08-11 16:20:33 +02:00
|
|
|
case "PIGLIN_BRUTE":
|
2020-06-29 22:05:32 -04:00
|
|
|
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":
|
|
|
|
case "GUARDIAN":
|
|
|
|
case "ELDER_GUARDIAN":
|
|
|
|
case "SKELETON":
|
|
|
|
case "WITHER_SKELETON":
|
2019-02-04 14:02:21 +00:00
|
|
|
restoreLiving((LivingEntity) entity);
|
|
|
|
return entity;
|
2020-06-29 22:05:32 -04:00
|
|
|
case "IRON_GOLEM":
|
2019-02-04 14:02:21 +00:00
|
|
|
if (this.dataByte != 0) {
|
|
|
|
((IronGolem) entity).setPlayerCreated(true);
|
|
|
|
}
|
|
|
|
restoreLiving((LivingEntity) entity);
|
|
|
|
return entity;
|
|
|
|
default:
|
2020-07-13 22:51:57 +02:00
|
|
|
if (Settings.DEBUG) {
|
2021-06-03 12:40:27 +02:00
|
|
|
LOGGER.info("Could not identify entity: {}", entity.getType());
|
2020-07-13 22:51:57 +02:00
|
|
|
}
|
2019-02-04 14:02:21 +00:00
|
|
|
return entity;
|
|
|
|
// END LIVING
|
2019-01-31 14:20:48 -05:00
|
|
|
}
|
2018-08-19 22:18:58 +02:00
|
|
|
}
|
|
|
|
|
2019-02-04 14:02:21 +00:00
|
|
|
public void saveEntity() {
|
|
|
|
}
|
2018-08-19 22:18:58 +02:00
|
|
|
|
2019-02-04 14:02:21 +00:00
|
|
|
private byte getOrdinal(Object[] list, Object value) {
|
|
|
|
for (byte i = 0; i < list.length; i++) {
|
|
|
|
if (list[i].equals(value)) {
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
2018-08-19 22:18:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|