/* * This file is part of NucleusFramework for Bukkit, licensed under the MIT License (MIT). * * Copyright (c) JCThePants (www.jcwhatever.com) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.jcwhatever.nucleus.utils.file; import com.jcwhatever.nucleus.utils.PreCon; import org.bukkit.Art; import org.bukkit.Location; import org.bukkit.Rotation; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.entity.ArmorStand; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.ItemFrame; import org.bukkit.entity.Painting; import org.bukkit.inventory.ItemStack; import org.bukkit.material.Directional; import org.bukkit.util.EulerAngle; import java.io.IOException; /** * Used to serialize entities that are considered part of structures, much like blocks. * * <p>Cannot create a {@link org.bukkit.entity.Entity} instance but instead retains * the information necessary to apply the data to the original block location.</p> * * <p>Supported Entity Interfaces:</p> * * <ul> * <li>{@link org.bukkit.material.Directional}</li> * <li>{@link org.bukkit.entity.Painting}</li> * <li>{@link org.bukkit.entity.ItemFrame}</li> * <li>{@link org.bukkit.entity.ArmorStand}</li> * </ul> */ public class SerializableFurnitureEntity implements IAppliedSerializable { /** * Determine if an entity is a furniture entity * * @param entity The entity to check. */ public static boolean isFurnitureEntity(Entity entity) { return entity instanceof Painting || entity instanceof ItemFrame || entity instanceof ArmorStand; } /** * Get classes used to detect a furniture entity. */ public static Class<?>[] getFurnitureClasses() { return new Class<?>[] { Painting.class, ItemFrame.class, ArmorStand.class }; } boolean _canSerialize; private Location _location; private EntityType _type; // Directional private BlockFace _facing; // Painting private Art _art; // ItemFrame private ItemStack _frameItem; private Rotation _frameRotation; // ArmorStand private boolean _hasArmorStand; private ItemStack _itemInHand; private ItemStack _helmet; private ItemStack _chestplate; private ItemStack _leggings; private ItemStack _boots; private EulerAngle _headPose; private EulerAngle _bodyPose; private EulerAngle _leftArmPose; private EulerAngle _rightArmPose; private EulerAngle _leftLegPose; private EulerAngle _rightLegPose; private boolean _hasArmorBasePlate; private boolean _hasArmorGravity; private boolean _isArmorVisible; private boolean _hasArmorArms; private boolean _isArmorSmall; /** * Constructor. * * <p>Required by {@link BasicByteReader} to deserialize.</p> */ private SerializableFurnitureEntity() {} /** * Constructor. * * @param entity The {@link org.bukkit.entity.Entity} that needs to be serialized. */ public SerializableFurnitureEntity(Entity entity) { PreCon.notNull(entity); _location = entity.getLocation(); _type = entity.getType(); if (entity instanceof Directional) { Directional directional = (Directional)entity; _facing = directional.getFacing(); _canSerialize = true; } if (entity instanceof Painting) { Painting painting = (Painting)entity; _art = painting.getArt(); _canSerialize = true; } if (entity instanceof ItemFrame) { ItemFrame frame = (ItemFrame)entity; _frameItem = frame.getItem(); _frameRotation = frame.getRotation(); } if (entity instanceof ArmorStand) { ArmorStand stand = (ArmorStand)entity; _hasArmorStand = true; _itemInHand = stand.getItemInHand(); _helmet = stand.getHelmet(); _chestplate = stand.getChestplate(); _leggings = stand.getLeggings(); _boots = stand.getBoots(); _headPose = stand.getHeadPose(); _bodyPose = stand.getBodyPose(); _leftArmPose = stand.getLeftArmPose(); _rightArmPose = stand.getRightArmPose(); _leftLegPose = stand.getLeftLegPose(); _rightLegPose = stand.getRightLegPose(); _hasArmorBasePlate = stand.hasBasePlate(); _hasArmorGravity = stand.hasGravity(); _isArmorVisible = stand.isVisible(); _hasArmorArms = stand.hasArms(); _isArmorSmall = stand.isSmall(); } } /** * Get the stored entity location. */ public Location getLocation() { return _location; } /** * Get the type of the stored entity. */ public EntityType getType() { return _type; } /** * Apply the stored {@link Entity} data to the * supplied {@link Entity} object. */ @Override public boolean apply() { Block block = getLocation().getBlock(); Entity entity; try { entity = getLocation().getWorld().spawnEntity(block.getLocation(), getType()); } catch (Exception e) { Location opposite = block.getRelative(_facing.getOppositeFace()).getLocation(); entity = getLocation().getWorld().spawnEntity(opposite, getType()); } applyToEntity(entity); return true; } /** * True if the Entity represented can be serialized. */ public boolean canSerialize() { return _canSerialize; } @Override public void serialize(IByteWriter writer) throws IOException { writer.write(_location); writer.write(_type); boolean hasDirection = _facing != null; boolean hasArt = _art != null; boolean hasItemFrame = _frameItem != null; writer.write(hasDirection); writer.write(hasArt); writer.write(hasItemFrame); writer.write(_hasArmorStand); if (hasDirection) { writer.write(_facing); } if (hasArt) { writer.write(_art); } if (hasItemFrame) { writer.write(_frameItem); writer.write(_frameRotation); } if (_hasArmorStand) { writer.write(_hasArmorBasePlate); writer.write(_hasArmorGravity); writer.write(_isArmorVisible); writer.write(_hasArmorArms); writer.write(_isArmorSmall); writer.write(_itemInHand); writer.write(_helmet); writer.write(_chestplate); writer.write(_leggings); writer.write(_boots); writer.write(_headPose); writer.write(_bodyPose); writer.write(_leftArmPose); writer.write(_rightArmPose); writer.write(_leftLegPose); writer.write(_rightLegPose); } } @Override public void deserialize(IByteReader reader) throws IOException, ClassNotFoundException { _location = reader.getLocation(); _type = reader.getEnum(EntityType.class); boolean hasDirection = reader.getBoolean(); boolean hasArt = reader.getBoolean(); boolean hasItemFrame = reader.getBoolean(); _hasArmorStand = reader.getBoolean(); if (hasDirection) { _facing = reader.getEnum(BlockFace.class); } if (hasArt) { _art = reader.getEnum(Art.class); } if (hasItemFrame) { _frameItem = reader.getItemStack(); _frameRotation = reader.getEnum(Rotation.class); } if (_hasArmorStand) { _hasArmorBasePlate = reader.getBoolean(); _hasArmorGravity = reader.getBoolean(); _isArmorVisible = reader.getBoolean(); _hasArmorArms = reader.getBoolean(); _isArmorSmall = reader.getBoolean(); _itemInHand = reader.getItemStack(); _helmet = reader.getItemStack(); _chestplate = reader.getItemStack(); _leggings = reader.getItemStack(); _boots = reader.getItemStack(); _headPose = reader.getEulerAngle(); _bodyPose = reader.getEulerAngle(); _leftArmPose = reader.getEulerAngle(); _rightArmPose = reader.getEulerAngle(); _leftLegPose = reader.getEulerAngle(); _rightLegPose = reader.getEulerAngle(); } } private boolean applyToEntity(Entity entity) { entity.teleport(_location); if (entity instanceof Directional && _facing != null) { Directional directional = (Directional)entity; directional.setFacingDirection(_facing); } if (entity instanceof Painting && _art != null) { Painting painting = (Painting)entity; painting.setArt(_art); } if (entity instanceof ItemFrame && _frameItem != null) { ItemFrame frame = (ItemFrame)entity; frame.setItem(_frameItem); frame.setRotation(_frameRotation); } if (entity instanceof ArmorStand && _hasArmorStand) { ArmorStand stand = (ArmorStand)entity; stand.setItemInHand(_itemInHand); stand.setHelmet(_helmet); stand.setChestplate(_chestplate); stand.setLeggings(_leggings); stand.setBoots(_boots); stand.setHeadPose(_headPose); stand.setBodyPose(_bodyPose); stand.setLeftArmPose(_leftArmPose); stand.setRightArmPose(_rightArmPose); stand.setLeftLegPose(_leftLegPose); stand.setRightLegPose(_rightLegPose); stand.setBasePlate(_hasArmorBasePlate); stand.setGravity(_hasArmorGravity); stand.setVisible(_isArmorVisible); stand.setArms(_hasArmorArms); stand.setSmall(_isArmorSmall); } if (_facing == null) return false; return true; } }