PublicCloneable and support for ItemMeta#clone

This commit is contained in:
Felix Cravic 2020-12-09 21:15:02 +01:00
parent cea3b8b593
commit f39f6444d7
17 changed files with 284 additions and 229 deletions

View File

@ -1,5 +1,6 @@
package net.minestom.server.data; package net.minestom.server.data;
import net.minestom.server.utils.clone.PublicCloneable;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -11,7 +12,7 @@ import java.util.Set;
* <p> * <p>
* See {@link DataImpl} for the default implementation. * See {@link DataImpl} for the default implementation.
*/ */
public abstract class Data implements Cloneable { public abstract class Data implements PublicCloneable<Data> {
public static final Data EMPTY = new Data() { public static final Data EMPTY = new Data() {
@Override @Override

View File

@ -16,6 +16,7 @@ import net.minestom.server.registry.Registries;
import net.minestom.server.utils.BlockPosition; import net.minestom.server.utils.BlockPosition;
import net.minestom.server.utils.Direction; import net.minestom.server.utils.Direction;
import net.minestom.server.utils.NBTUtils; import net.minestom.server.utils.NBTUtils;
import net.minestom.server.utils.clone.PublicCloneable;
import net.minestom.server.utils.ownership.OwnershipHandler; import net.minestom.server.utils.ownership.OwnershipHandler;
import net.minestom.server.utils.validate.Check; import net.minestom.server.utils.validate.Check;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -35,7 +36,7 @@ import java.util.*;
* Here a non-exhaustive list of what you can do to update the item: * Here a non-exhaustive list of what you can do to update the item:
* {@link PlayerInventory#refreshSlot(short)}, {@link Inventory#refreshSlot(short)} or a raw {@link SetSlotPacket}. * {@link PlayerInventory#refreshSlot(short)}, {@link Inventory#refreshSlot(short)} or a raw {@link SetSlotPacket}.
*/ */
public class ItemStack implements DataContainer { public class ItemStack implements DataContainer, PublicCloneable<ItemStack> {
public static final OwnershipHandler<Data> DATA_OWNERSHIP = new OwnershipHandler(); public static final OwnershipHandler<Data> DATA_OWNERSHIP = new OwnershipHandler();
public static final String OWNERSHIP_DATA_KEY = "ownership_identifier"; public static final String OWNERSHIP_DATA_KEY = "ownership_identifier";
@ -551,15 +552,25 @@ public class ItemStack implements DataContainer {
} }
/** /**
* Copies this item stack. * @deprecated use {@link #clone()}
*/
@Deprecated
@NotNull
public synchronized ItemStack copy() {
return clone();
}
/**
* Clones this item stack.
* <p> * <p>
* Be aware that the identifier ({@link #getIdentifier()}) will change. * Be aware that the identifier ({@link #getIdentifier()}) will change.
* *
* @return a cloned item stack with a different identifier * @return a cloned item stack with a different identifier
*/ */
@NotNull @Override
public synchronized ItemStack copy() { public ItemStack clone() {
ItemStack itemStack = new ItemStack(material, amount, damage); try {
ItemStack itemStack = (ItemStack) super.clone();
itemStack.setDisplayName(displayName); itemStack.setDisplayName(displayName);
itemStack.setUnbreakable(unbreakable); itemStack.setUnbreakable(unbreakable);
if (lore != null) { if (lore != null) {
@ -576,13 +587,17 @@ public class ItemStack implements DataContainer {
itemStack.customModelData = customModelData; itemStack.customModelData = customModelData;
if (itemMeta != null) if (itemMeta != null)
itemStack.itemMeta = itemMeta.copy(); itemStack.itemMeta = itemMeta.clone();
final Data data = getData(); final Data data = getData();
if (data != null) if (data != null)
itemStack.setData(data.clone()); itemStack.setData(data.clone());
return itemStack; return itemStack;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
} }
@Nullable @Nullable

View File

@ -3,7 +3,7 @@ package net.minestom.server.item.metadata;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
public class CompassMeta implements ItemMeta { public class CompassMeta extends ItemMeta {
private boolean lodestoneTracked; private boolean lodestoneTracked;
private String lodestoneDimension; private String lodestoneDimension;
@ -84,7 +84,7 @@ public class CompassMeta implements ItemMeta {
@Override @Override
public void write(@NotNull NBTCompound compound) { public void write(@NotNull NBTCompound compound) {
compound.setByte("LodestoneTracked", (byte) (lodestoneTracked ? 1 : 0)); compound.setByte("LodestoneTracked", (byte) (lodestoneTracked ? 1 : 0));
if(lodestoneDimension != null) { if (lodestoneDimension != null) {
compound.setString("LodestoneDimension", lodestoneDimension); compound.setString("LodestoneDimension", lodestoneDimension);
} }
@ -99,8 +99,8 @@ public class CompassMeta implements ItemMeta {
@NotNull @NotNull
@Override @Override
public ItemMeta copy() { public ItemMeta clone() {
CompassMeta compassMeta = new CompassMeta(); CompassMeta compassMeta = (CompassMeta) super.clone();
compassMeta.lodestoneTracked = lodestoneTracked; compassMeta.lodestoneTracked = lodestoneTracked;
compassMeta.lodestoneDimension = lodestoneDimension; compassMeta.lodestoneDimension = lodestoneDimension;
compassMeta.x = x; compassMeta.x = x;

View File

@ -10,7 +10,7 @@ import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.NBTList; import org.jglrxavpok.hephaistos.nbt.NBTList;
import org.jglrxavpok.hephaistos.nbt.NBTTypes; import org.jglrxavpok.hephaistos.nbt.NBTTypes;
public class CrossbowMeta implements ItemMeta { public class CrossbowMeta extends ItemMeta {
private boolean triple; private boolean triple;
private ItemStack projectile1, projectile2, projectile3; private ItemStack projectile1, projectile2, projectile3;
@ -180,12 +180,12 @@ public class CrossbowMeta implements ItemMeta {
@NotNull @NotNull
@Override @Override
public ItemMeta copy() { public ItemMeta clone() {
CrossbowMeta crossbowMeta = new CrossbowMeta(); CrossbowMeta crossbowMeta = (CrossbowMeta) super.clone();
crossbowMeta.triple = triple; crossbowMeta.triple = triple;
crossbowMeta.projectile1 = projectile1 == null ? null : projectile1.copy(); crossbowMeta.projectile1 = projectile1 == null ? null : projectile1.clone();
crossbowMeta.projectile2 = projectile2 == null ? null : projectile2.copy(); crossbowMeta.projectile2 = projectile2 == null ? null : projectile2.clone();
crossbowMeta.projectile3 = projectile3 == null ? null : projectile3.copy(); crossbowMeta.projectile3 = projectile3 == null ? null : projectile3.clone();
crossbowMeta.charged = charged; crossbowMeta.charged = charged;

View File

@ -9,7 +9,7 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
public class EnchantedBookMeta implements ItemMeta { public class EnchantedBookMeta extends ItemMeta {
private final Map<Enchantment, Short> storedEnchantmentMap = new HashMap<>(); private final Map<Enchantment, Short> storedEnchantmentMap = new HashMap<>();
@ -85,8 +85,8 @@ public class EnchantedBookMeta implements ItemMeta {
@NotNull @NotNull
@Override @Override
public ItemMeta copy() { public ItemMeta clone() {
EnchantedBookMeta enchantedBookMeta = new EnchantedBookMeta(); EnchantedBookMeta enchantedBookMeta = (EnchantedBookMeta) super.clone();
enchantedBookMeta.storedEnchantmentMap.putAll(storedEnchantmentMap); enchantedBookMeta.storedEnchantmentMap.putAll(storedEnchantmentMap);
return enchantedBookMeta; return enchantedBookMeta;

View File

@ -3,7 +3,7 @@ package net.minestom.server.item.metadata;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
public class FireworkMeta implements ItemMeta { public class FireworkMeta extends ItemMeta {
private boolean flicker; private boolean flicker;
private boolean trail; private boolean trail;
@ -36,7 +36,7 @@ public class FireworkMeta implements ItemMeta {
@NotNull @NotNull
@Override @Override
public ItemMeta copy() { public ItemMeta clone() {
return null; return null;
} }

View File

@ -1,20 +1,21 @@
package net.minestom.server.item.metadata; package net.minestom.server.item.metadata;
import net.minestom.server.item.ItemStack; import net.minestom.server.item.ItemStack;
import net.minestom.server.utils.clone.PublicCloneable;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
/** /**
* Represents nbt data only available for a type of item. * Represents nbt data only available for a type of item.
*/ */
public interface ItemMeta { public abstract class ItemMeta implements PublicCloneable<ItemMeta> {
/** /**
* Gets if this meta object contains any useful data to send to the client. * Gets if this meta object contains any useful data to send to the client.
* *
* @return true if this item has nbt data, false otherwise * @return true if this item has nbt data, false otherwise
*/ */
boolean hasNbt(); public abstract boolean hasNbt();
/** /**
* Gets if the two ItemMeta are similar. * Gets if the two ItemMeta are similar.
@ -24,7 +25,7 @@ public interface ItemMeta {
* @param itemMeta the second item meta to check * @param itemMeta the second item meta to check
* @return true if the two meta are similar, false otherwise * @return true if the two meta are similar, false otherwise
*/ */
boolean isSimilar(@NotNull ItemMeta itemMeta); public abstract boolean isSimilar(@NotNull ItemMeta itemMeta);
/** /**
* Reads nbt data from a compound. * Reads nbt data from a compound.
@ -34,23 +35,23 @@ public interface ItemMeta {
* *
* @param compound the compound containing the data * @param compound the compound containing the data
*/ */
void read(@NotNull NBTCompound compound); public abstract void read(@NotNull NBTCompound compound);
/** /**
* Writes nbt data to a compound. * Writes nbt data to a compound.
* *
* @param compound the compound receiving the item meta data * @param compound the compound receiving the item meta data
*/ */
void write(@NotNull NBTCompound compound); public abstract void write(@NotNull NBTCompound compound);
/**
* Copies this item meta.
* <p>
* Used by {@link ItemStack#copy()}.
*
* @return the cloned item meta
*/
@NotNull @NotNull
ItemMeta copy(); @Override
public ItemMeta clone() {
try {
return (ItemMeta) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
throw new IllegalStateException("Weird thing happened");
}
}
} }

View File

@ -4,8 +4,10 @@ import net.minestom.server.chat.ChatColor;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
/** Represents the item meat for leather armor parts. */ /**
public class LeatherArmorMeta implements ItemMeta { * Represents the item meta for leather armor parts.
*/
public class LeatherArmorMeta extends ItemMeta {
private static final int BIT_MASK = 0xFF; private static final int BIT_MASK = 0xFF;
@ -41,7 +43,9 @@ public class LeatherArmorMeta implements ItemMeta {
this.modified = true; this.modified = true;
} }
/** Resets the color to the default leather one. */ /**
* Resets the color to the default leather one.
*/
public void reset() { public void reset() {
this.red = 0; this.red = 0;
this.green = 0; this.green = 0;
@ -85,13 +89,17 @@ public class LeatherArmorMeta implements ItemMeta {
return modified; return modified;
} }
/** {@inheritDoc} */ /**
* {@inheritDoc}
*/
@Override @Override
public boolean hasNbt() { public boolean hasNbt() {
return modified; return modified;
} }
/** {@inheritDoc} */ /**
* {@inheritDoc}
*/
@Override @Override
public boolean isSimilar(@NotNull ItemMeta itemMeta) { public boolean isSimilar(@NotNull ItemMeta itemMeta) {
if (!(itemMeta instanceof LeatherArmorMeta)) return false; if (!(itemMeta instanceof LeatherArmorMeta)) return false;
@ -102,7 +110,9 @@ public class LeatherArmorMeta implements ItemMeta {
&& leatherArmorMeta.getBlue() == getBlue(); && leatherArmorMeta.getBlue() == getBlue();
} }
/** {@inheritDoc} */ /**
* {@inheritDoc}
*/
@Override @Override
public void read(@NotNull NBTCompound compound) { public void read(@NotNull NBTCompound compound) {
if (compound.containsKey("display")) { if (compound.containsKey("display")) {
@ -121,7 +131,9 @@ public class LeatherArmorMeta implements ItemMeta {
} }
} }
/** {@inheritDoc} */ /**
* {@inheritDoc}
*/
@Override @Override
public void write(@NotNull NBTCompound compound) { public void write(@NotNull NBTCompound compound) {
if (modified) { if (modified) {
@ -139,11 +151,13 @@ public class LeatherArmorMeta implements ItemMeta {
} }
} }
/** {@inheritDoc} */ /**
* {@inheritDoc}
*/
@NotNull @NotNull
@Override @Override
public ItemMeta copy() { public ItemMeta clone() {
LeatherArmorMeta leatherArmorMeta = new LeatherArmorMeta(); LeatherArmorMeta leatherArmorMeta = (LeatherArmorMeta) super.clone();
leatherArmorMeta.modified = this.isModified(); leatherArmorMeta.modified = this.isModified();
leatherArmorMeta.red = (byte) this.getRed(); leatherArmorMeta.red = (byte) this.getRed();
leatherArmorMeta.green = (byte) this.getGreen(); leatherArmorMeta.green = (byte) this.getGreen();

View File

@ -9,7 +9,7 @@ import org.jglrxavpok.hephaistos.nbt.NBTTypes;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class MapMeta implements ItemMeta { public class MapMeta extends ItemMeta {
private int mapId; private int mapId;
private int mapScaleDirection = 1; private int mapScaleDirection = 1;
@ -132,17 +132,17 @@ public class MapMeta implements ItemMeta {
final byte type = decorationCompound.getAsByte("type"); final byte type = decorationCompound.getAsByte("type");
byte x = 0; byte x = 0;
if(decorationCompound.containsKey("x")) { if (decorationCompound.containsKey("x")) {
x = decorationCompound.getAsByte("x"); x = decorationCompound.getAsByte("x");
} }
byte z = 0; byte z = 0;
if(decorationCompound.containsKey("z")) { if (decorationCompound.containsKey("z")) {
z = decorationCompound.getAsByte("z"); z = decorationCompound.getAsByte("z");
} }
double rotation = 0.0; double rotation = 0.0;
if(decorationCompound.containsKey("rot")) { if (decorationCompound.containsKey("rot")) {
rotation = decorationCompound.getAsDouble("rot"); rotation = decorationCompound.getAsDouble("rot");
} }
@ -194,8 +194,8 @@ public class MapMeta implements ItemMeta {
@NotNull @NotNull
@Override @Override
public ItemMeta copy() { public ItemMeta clone() {
MapMeta mapMeta = new MapMeta(); MapMeta mapMeta = (MapMeta) super.clone();
mapMeta.setMapId(mapId); mapMeta.setMapId(mapId);
mapMeta.setMapScaleDirection(mapScaleDirection); mapMeta.setMapScaleDirection(mapScaleDirection);
mapMeta.decorations.addAll(decorations); mapMeta.decorations.addAll(decorations);

View File

@ -4,7 +4,7 @@ import net.minestom.server.entity.PlayerSkin;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
public class PlayerHeadMeta implements ItemMeta { public class PlayerHeadMeta extends ItemMeta {
private String playerName; private String playerName;
private PlayerSkin playerSkin; private PlayerSkin playerSkin;
@ -34,7 +34,7 @@ public class PlayerHeadMeta implements ItemMeta {
@NotNull @NotNull
@Override @Override
public ItemMeta copy() { public ItemMeta clone() {
return null; return null;
} }
} }

View File

@ -19,7 +19,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
* {@link net.minestom.server.item.Material#SPLASH_POTION}, * {@link net.minestom.server.item.Material#SPLASH_POTION},
* {@link net.minestom.server.item.Material#TIPPED_ARROW}. * {@link net.minestom.server.item.Material#TIPPED_ARROW}.
*/ */
public class PotionMeta implements ItemMeta { public class PotionMeta extends ItemMeta {
private PotionType potionType; private PotionType potionType;
private final List<CustomPotionEffect> customPotionEffects = new CopyOnWriteArrayList<>(); private final List<CustomPotionEffect> customPotionEffects = new CopyOnWriteArrayList<>();
@ -152,8 +152,8 @@ public class PotionMeta implements ItemMeta {
@NotNull @NotNull
@Override @Override
public ItemMeta copy() { public ItemMeta clone() {
PotionMeta potionMeta = new PotionMeta(); PotionMeta potionMeta = (PotionMeta) super.clone();
potionMeta.potionType = potionType; potionMeta.potionType = potionType;
potionMeta.customPotionEffects.addAll(customPotionEffects); potionMeta.customPotionEffects.addAll(customPotionEffects);

View File

@ -5,7 +5,7 @@ import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
// TODO for which item // TODO for which item
public class SpawnEggMeta implements ItemMeta { public class SpawnEggMeta extends ItemMeta {
private EntityType entityType; private EntityType entityType;
@ -42,8 +42,8 @@ public class SpawnEggMeta implements ItemMeta {
@NotNull @NotNull
@Override @Override
public ItemMeta copy() { public ItemMeta clone() {
SpawnEggMeta spawnEggMeta = new SpawnEggMeta(); SpawnEggMeta spawnEggMeta = (SpawnEggMeta) super.clone();
spawnEggMeta.entityType = entityType; spawnEggMeta.entityType = entityType;
return spawnEggMeta; return spawnEggMeta;
} }

View File

@ -8,7 +8,7 @@ import org.jglrxavpok.hephaistos.nbt.NBTTypes;
import java.util.ArrayList; import java.util.ArrayList;
public class WritableBookMeta implements ItemMeta { public class WritableBookMeta extends ItemMeta {
private ArrayList<String> pages = new ArrayList<>(); private ArrayList<String> pages = new ArrayList<>();
@ -68,8 +68,8 @@ public class WritableBookMeta implements ItemMeta {
@NotNull @NotNull
@Override @Override
public ItemMeta copy() { public ItemMeta clone() {
WritableBookMeta writableBookMeta = new WritableBookMeta(); WritableBookMeta writableBookMeta = (WritableBookMeta) super.clone();
writableBookMeta.pages.addAll(pages); writableBookMeta.pages.addAll(pages);
return writableBookMeta; return writableBookMeta;

View File

@ -11,7 +11,7 @@ import org.jglrxavpok.hephaistos.nbt.NBTTypes;
import java.util.ArrayList; import java.util.ArrayList;
public class WrittenBookMeta implements ItemMeta { public class WrittenBookMeta extends ItemMeta {
private boolean resolved; private boolean resolved;
private WrittenBookGeneration generation; private WrittenBookGeneration generation;
@ -180,8 +180,8 @@ public class WrittenBookMeta implements ItemMeta {
@NotNull @NotNull
@Override @Override
public ItemMeta copy() { public ItemMeta clone() {
WrittenBookMeta writtenBookMeta = new WrittenBookMeta(); WrittenBookMeta writtenBookMeta = (WrittenBookMeta) super.clone();
writtenBookMeta.resolved = resolved; writtenBookMeta.resolved = resolved;
writtenBookMeta.generation = generation; writtenBookMeta.generation = generation;
writtenBookMeta.author = author; writtenBookMeta.author = author;

View File

@ -1,5 +1,6 @@
package net.minestom.server.utils; package net.minestom.server.utils;
import net.minestom.server.utils.clone.PublicCloneable;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Objects; import java.util.Objects;
@ -9,7 +10,7 @@ import java.util.Objects;
/** /**
* Represents the position of a block, so with integers instead of floating numbers. * Represents the position of a block, so with integers instead of floating numbers.
*/ */
public class BlockPosition { public class BlockPosition implements PublicCloneable<BlockPosition> {
private int x, y, z; private int x, y, z;
@ -213,10 +214,22 @@ public class BlockPosition {
* Copies this block position. * Copies this block position.
* *
* @return the cloned block position * @return the cloned block position
* @deprecated use {@link #clone()}
*/ */
@Deprecated
@NotNull @NotNull
public BlockPosition copy() { public BlockPosition copy() {
return new BlockPosition(x, y, z); return clone();
}
@Override
public BlockPosition clone() {
try {
return (BlockPosition) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
} }
/** /**

View File

@ -1,6 +1,7 @@
package net.minestom.server.utils; package net.minestom.server.utils;
import net.minestom.server.utils.chunk.ChunkUtils; import net.minestom.server.utils.chunk.ChunkUtils;
import net.minestom.server.utils.clone.PublicCloneable;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Objects; import java.util.Objects;
@ -9,7 +10,7 @@ import java.util.Objects;
* Represents a position. * Represents a position.
* The instance is not contained. * The instance is not contained.
*/ */
public class Position implements Cloneable { public class Position implements PublicCloneable<Position> {
private float x, y, z; private float x, y, z;
private float yaw, pitch; private float yaw, pitch;

View File

@ -0,0 +1,10 @@
package net.minestom.server.utils.clone;
/**
* Convenient interface to expose {@link Object#clone()} publicly with a generic.
*
* @param <T> the type to clone
*/
public interface PublicCloneable<T> extends Cloneable {
T clone();
}