Implements PlayerHeadMeta, FireworkMeta and FireworkEffectMeta

This commit is contained in:
R0bbyYT 2020-12-23 02:24:41 +01:00
parent 6e0ad54d5e
commit 58c7ad9e02
7 changed files with 530 additions and 38 deletions

View File

@ -9,6 +9,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.io.IOException; import java.io.IOException;
import java.util.Objects;
/** /**
* Contains all the data required to store a skin. * Contains all the data required to store a skin.
@ -26,24 +27,6 @@ public class PlayerSkin {
this.signature = signature; this.signature = signature;
} }
/**
* Gets the skin textures value.
*
* @return the textures value
*/
public String getTextures() {
return textures;
}
/**
* Gets the skin signature.
*
* @return the skin signature
*/
public String getSignature() {
return signature;
}
/** /**
* Gets a skin from a Mojang UUID. * Gets a skin from a Mojang UUID.
* *
@ -98,4 +81,42 @@ public class PlayerSkin {
} }
} }
/**
* Gets the skin textures value.
*
* @return the textures value
*/
public String getTextures() {
return textures;
}
/**
* Gets the skin signature.
*
* @return the skin signature
*/
public String getSignature() {
return signature;
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object object) {
if (this == object) return true;
if (object == null || getClass() != object.getClass()) return false;
PlayerSkin that = (PlayerSkin) object;
return Objects.equals(textures, that.textures) &&
Objects.equals(signature, that.signature);
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return Objects.hash(textures, signature);
}
} }

View File

@ -690,6 +690,9 @@ public class ItemStack implements DataContainer, PublicCloneable<ItemStack> {
if (material == Material.WRITTEN_BOOK) if (material == Material.WRITTEN_BOOK)
return new WrittenBookMeta(); return new WrittenBookMeta();
if(material == Material.FIREWORK_STAR)
return new FireworkEffectMeta();
if (material == Material.FIREWORK_ROCKET) if (material == Material.FIREWORK_ROCKET)
return new FireworkMeta(); return new FireworkMeta();

View File

@ -0,0 +1,126 @@
package net.minestom.server.item.firework;
import net.minestom.server.chat.ChatColor;
import net.minestom.server.item.metadata.FireworkMeta;
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
public class FireworkEffect {
private final boolean flicker;
private final boolean trail;
private final FireworkEffectType type;
private final ChatColor color;
private final ChatColor fadeColor;
/**
* Initializes a new firework effect.
*
* @param flicker {@code true} if this explosion has the Twinkle effect (glowstone dust), otherwise {@code false}.
* @param trail {@code true} if this explosion hsa the Trail effect (diamond), otherwise {@code false}.
* @param type The shape of this firework's explosion.
* @param color
* @param fadeColor
*/
public FireworkEffect(boolean flicker, boolean trail, FireworkEffectType type, ChatColor color, ChatColor fadeColor) {
this.flicker = flicker;
this.trail = trail;
this.type = type;
this.color = color;
this.fadeColor = fadeColor;
}
public static FireworkEffect fromCompound(NBTCompound compound) {
ChatColor primaryColor = null;
ChatColor secondaryColor = null;
if (compound.containsKey("Colors")) {
int[] color = compound.getIntArray("Colors");
primaryColor = ChatColor.fromRGB((byte) color[0], (byte) color[1], (byte) color[2]);
}
if (compound.containsKey("FadeColors")) {
int[] fadeColor = compound.getIntArray("FadeColors");
secondaryColor = ChatColor.fromRGB((byte) fadeColor[0], (byte) fadeColor[1], (byte) fadeColor[2]);
}
boolean flicker = compound.containsKey("Flicker") && compound.getByte("Flicker") == 1;
boolean trail = compound.containsKey("Trail") && compound.getByte("Trail") == 1;
FireworkEffectType type = compound.containsKey("Type") ? FireworkEffectType.byId(compound.getByte("Type")) : FireworkEffectType.SMALL_BALL;
return new FireworkEffect(
flicker,
trail,
type,
primaryColor,
secondaryColor);
}
public byte getFlicker() {
return (byte) (this.flicker ? 1 : 0);
}
public byte getTrail() {
return (byte) (this.trail ? 1 : 0);
}
/**
* Retrieves type of the firework effect.
*
* @return The firework type as a byte.
*/
public byte getType() {
return this.type.getType();
}
/**
* Retrieves array of integer values corresponding to the primary colors of this firework's explosion.
* <p>
* If custom color codes are used, the game renders is as "Custom" in the tooltip, but the proper color is used
* in the explosion.
*
* @return An array of integer values corresponding to the primary colors of this firework's explosion.
*/
public int[] getColors() {
return new int[]{
this.color.getRed(),
this.color.getGreen(),
this.color.getBlue()
};
}
/**
* Retrieves array of integer values corresponding to the fading colors of this firework's explosion.
* <p>
* Same handling of custom colors as Colors.
*
* @return An array of integer values corresponding to the fading colors of this firework's explosion.
*/
public int[] getFadeColors() {
return new int[]{
this.fadeColor.getRed(),
this.fadeColor.getGreen(),
this.fadeColor.getBlue()
};
}
/**
* Retrieves the {@link FireworkEffect} as a {@link NBTCompound}.
*
* @return The firework effect as a nbt compound.
*/
public NBTCompound asCompound() {
NBTCompound explosionCompound = new NBTCompound();
explosionCompound.setByte("Flicker", this.getFlicker());
explosionCompound.setByte("Trail", this.getTrail());
explosionCompound.setByte("Type", this.getType());
explosionCompound.setIntArray("Colors", this.getColors());
explosionCompound.setIntArray("FadeColors", this.getFadeColors());
return explosionCompound;
}
}

View File

@ -0,0 +1,41 @@
package net.minestom.server.item.firework;
import java.util.HashMap;
import java.util.Map;
/**
* An enumeration that representing all available firework types.
*/
public enum FireworkEffectType {
SMALL_BALL((byte) 0),
LARGE_BAR((byte) 1),
STAR_SHAPED((byte) 2),
CREEPER_SHAPED((byte) 3),
BURST((byte) 4),
;
private static final Map<Byte, FireworkEffectType> BY_ID = new HashMap<>();
static {
for (FireworkEffectType value : values()) {
BY_ID.put(value.type, value);
}
}
private final byte type;
FireworkEffectType(byte type) {
this.type = type;
}
public static FireworkEffectType byId(byte id) {
return BY_ID.get(id);
}
public byte getType() {
return type;
}
}

View File

@ -0,0 +1,92 @@
package net.minestom.server.item.metadata;
import net.minestom.server.item.firework.FireworkEffect;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
public class FireworkEffectMeta extends ItemMeta {
private FireworkEffect fireworkEffect;
/**
* Retrieves the firework effect for this meta.
*
* @return The current firework effect, or {@code null} if none.
*/
@Nullable
public FireworkEffect getFireworkEffect() {
return fireworkEffect;
}
/**
* Changes the {@link FireworkEffect} for this item meta.
*
* @param fireworkEffect The new firework effect, or {@code null}.
*/
public void setFireworkEffect(@Nullable FireworkEffect fireworkEffect) {
this.fireworkEffect = fireworkEffect;
}
/**
* Whether if this item meta has an effect.
*
* @return {@code true} if this item meta has an effect, otherwise {@code false}.
*/
public boolean hasFireworkEffect() {
return this.fireworkEffect != null;
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasNbt() {
return this.hasFireworkEffect();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isSimilar(@NotNull ItemMeta itemMeta) {
if (!(itemMeta instanceof FireworkEffectMeta)) {
return false;
}
FireworkEffectMeta fireworkEffectMeta = (FireworkEffectMeta) itemMeta;
return fireworkEffectMeta.fireworkEffect == this.fireworkEffect;
}
/**
* {@inheritDoc}
*/
@Override
public void read(@NotNull NBTCompound compound) {
if (compound.containsKey("Explosion")) {
this.fireworkEffect = FireworkEffect.fromCompound(compound.getCompound("Explosion"));
}
}
/**
* {@inheritDoc}
*/
@Override
public void write(@NotNull NBTCompound compound) {
if (this.fireworkEffect != null) {
compound.set("Explosion", this.fireworkEffect.asCompound());
}
}
/**
* {@inheritDoc}
*/
@NotNull
@Override
public ItemMeta clone() {
FireworkEffectMeta fireworkEffectMeta = (FireworkEffectMeta) super.clone();
fireworkEffectMeta.fireworkEffect = this.fireworkEffect;
return fireworkEffectMeta;
}
}

View File

@ -1,47 +1,127 @@
package net.minestom.server.item.metadata; package net.minestom.server.item.metadata;
import net.minestom.server.item.firework.FireworkEffect;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.NBTList;
import org.jglrxavpok.hephaistos.nbt.NBTTypes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Represents a firework rocket meta data and its effects.
*/
public class FireworkMeta extends ItemMeta { public class FireworkMeta extends ItemMeta {
private boolean flicker; private List<FireworkEffect> effects = new ArrayList<>();
private boolean trail;
private FireworkType type;
private int[] colors;
private int[] fadeColors;
private byte flightDuration; private byte flightDuration;
// TODO Explosions list
@Override public void addFireworkEffect(FireworkEffect effect) {
public boolean hasNbt() { this.effects.add(effect);
return false;
} }
public void addFireworkEffects(FireworkEffect... effects) {
this.effects.addAll(Arrays.asList(effects));
}
public void removeFireworkEffect(int index) throws IndexOutOfBoundsException {
this.effects.remove(index);
}
public void removeFireworkEffect(FireworkEffect effect) {
this.effects.remove(effect);
}
public List<FireworkEffect> getEffects() {
return effects;
}
public int getEffectSize() {
return this.effects.size();
}
public void clearEffects() {
this.effects.clear();
}
public boolean hasEffects() {
return this.effects.isEmpty();
}
public void setFlightDuration(byte flightDuration) {
this.flightDuration = flightDuration;
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasNbt() {
return this.flightDuration == 0 || !this.effects.isEmpty();
}
/**
* {@inheritDoc}
*/
@Override @Override
public boolean isSimilar(@NotNull ItemMeta itemMeta) { public boolean isSimilar(@NotNull ItemMeta itemMeta) {
return false; return false;
} }
/**
* {@inheritDoc}
*/
@Override @Override
public void read(@NotNull NBTCompound compound) { public void read(@NotNull NBTCompound compound) {
this.effects.clear();
if (compound.containsKey("Fireworks")) {
NBTCompound fireworksCompound = compound.getCompound("Fireworks");
if (fireworksCompound.containsKey("Flight")) {
this.flightDuration = fireworksCompound.getAsByte("Flight");
}
if (fireworksCompound.containsKey("Explosions")) {
NBTList<NBTCompound> explosions = fireworksCompound.getList("Explosions");
for (NBTCompound explosion : explosions) {
this.effects.add(FireworkEffect.fromCompound(explosion));
}
}
}
} }
/**
* {@inheritDoc}
*/
@Override @Override
public void write(@NotNull NBTCompound compound) { public void write(@NotNull NBTCompound compound) {
NBTCompound fireworksCompound = new NBTCompound();
fireworksCompound.setByte("Flight", this.flightDuration);
NBTList<NBTCompound> explosions = new NBTList<>(NBTTypes.TAG_Compound);
for (FireworkEffect effect : this.effects) {
explosions.add(effect.asCompound());
}
fireworksCompound.set("Explosions", explosions);
compound.set("Fireworks", fireworksCompound);
} }
/**
* {@inheritDoc}
*/
@NotNull @NotNull
@Override @Override
public ItemMeta clone() { public ItemMeta clone() {
return null; FireworkMeta fireworkMeta = (FireworkMeta) super.clone();
} fireworkMeta.effects = this.effects;
fireworkMeta.flightDuration = this.flightDuration;
public enum FireworkType { return fireworkMeta;
SMALL_BALL, LARGE_BALL, STAR_SHAPED, CREEPER_SHAPED, BURST
} }
} }

View File

@ -1,19 +1,100 @@
package net.minestom.server.item.metadata; package net.minestom.server.item.metadata;
import net.minestom.server.MinecraftServer;
import net.minestom.server.entity.Player;
import net.minestom.server.entity.PlayerSkin; import net.minestom.server.entity.PlayerSkin;
import net.minestom.server.utils.Utils;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.NBTList;
import org.jglrxavpok.hephaistos.nbt.NBTTypes;
import java.util.UUID;
/**
* Represents a skull that can have an owner.
*/
public class PlayerHeadMeta extends ItemMeta { public class PlayerHeadMeta extends ItemMeta {
private String playerName; private UUID skullOwner;
private PlayerSkin playerSkin; private PlayerSkin playerSkin;
@Override /**
public boolean hasNbt() { * Sets the owner of the skull.
return playerSkin != null; *
* @param player The new owner of the skull.
* @return {@code true} if the owner was successfully set, otherwise {@code false}.
*/
public boolean setOwningPlayer(@NotNull Player player) {
if (player.getSkin() != null) {
this.skullOwner = player.getUuid();
this.playerSkin = player.getSkin();
return true;
}
return false;
} }
/**
* Retrieves the owner of the skull.
*
* @return The owner if the skull or {@code null}.
*/
@Nullable
public Player getOwningPlayer() {
return MinecraftServer.getConnectionManager().getPlayer(this.skullOwner);
}
/**
* Retrieves the owner of the head.
*
* @return The head's owner.
*/
@Nullable
public UUID getSkullOwner() {
return skullOwner;
}
/**
* Changes the owner of the head.
*
* @param skullOwner The new head owner.
*/
public void setSkullOwner(@NotNull UUID skullOwner) {
this.skullOwner = skullOwner;
}
/**
* Retrieves the skin of the head.
*
* @return The head's skin.
*/
@Nullable
public PlayerSkin getPlayerSkin() {
return playerSkin;
}
/**
* Changes the skin of the head.
*
* @param playerSkin The new skin for the head.
*/
public void setPlayerSkin(@NotNull PlayerSkin playerSkin) {
this.playerSkin = playerSkin;
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasNbt() {
return this.skullOwner != null || playerSkin != null;
}
/**
* {@inheritDoc}
*/
@Override @Override
public boolean isSimilar(@NotNull ItemMeta itemMeta) { public boolean isSimilar(@NotNull ItemMeta itemMeta) {
if (!(itemMeta instanceof PlayerHeadMeta)) if (!(itemMeta instanceof PlayerHeadMeta))
@ -22,19 +103,67 @@ public class PlayerHeadMeta extends ItemMeta {
return playerHeadMeta.playerSkin == playerSkin; return playerHeadMeta.playerSkin == playerSkin;
} }
/**
* {@inheritDoc}
*/
@Override @Override
public void read(@NotNull NBTCompound compound) { public void read(@NotNull NBTCompound compound) {
if (compound.containsKey("SkullOwner")) {
NBTCompound skullOwnerCompound = compound.getCompound("SkullOwner");
if (skullOwnerCompound.containsKey("Id")) {
this.skullOwner = Utils.intArrayToUuid(skullOwnerCompound.getIntArray("Id"));
}
if (skullOwnerCompound.containsKey("Properties")) {
NBTCompound propertyCompound = skullOwnerCompound.getCompound("Properties");
if (propertyCompound.containsKey("textures")) {
NBTList<NBTCompound> textures = propertyCompound.getList("textures");
if (textures != null) {
NBTCompound nbt = textures.get(0);
this.playerSkin = new PlayerSkin(nbt.getString("Value"), nbt.getString("Signature"));
}
}
}
}
} }
/**
* {@inheritDoc}
*/
@Override @Override
public void write(@NotNull NBTCompound compound) { public void write(@NotNull NBTCompound compound) {
NBTCompound skullOwnerCompound = new NBTCompound();
// Sets the identifier for the skull
skullOwnerCompound.setIntArray("Id", Utils.uuidToIntArray(this.skullOwner));
if (this.playerSkin == null) {
this.playerSkin = PlayerSkin.fromUuid(this.skullOwner.toString());
}
NBTList<NBTCompound> textures = new NBTList<>(NBTTypes.TAG_Compound);
textures.add(new NBTCompound().setString("Value", this.playerSkin.getTextures()).setString("Signature", this.playerSkin.getSignature()));
skullOwnerCompound.set("Properties", new NBTCompound().set("textures", textures));
compound.set("SkullOwner", skullOwnerCompound);
} }
/**
* {@inheritDoc}
*/
@NotNull @NotNull
@Override @Override
public ItemMeta clone() { public ItemMeta clone() {
return null; PlayerHeadMeta playerHeadMeta = (PlayerHeadMeta) super.clone();
playerHeadMeta.skullOwner = this.skullOwner;
playerHeadMeta.playerSkin = this.playerSkin;
return playerHeadMeta;
} }
} }