Implement HoverSource for ItemStack, Entity and Player

This commit is contained in:
Kieran Wallbanks 2021-03-11 17:07:04 +00:00
parent 4ef62a1017
commit 6dd3eb8044
4 changed files with 52 additions and 7 deletions

View File

@ -2,6 +2,9 @@ package net.minestom.server.entity;
import com.google.common.collect.Queues;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.event.HoverEvent.ShowEntity;
import net.kyori.adventure.text.event.HoverEventSource;
import net.minestom.server.MinecraftServer;
import net.minestom.server.Viewable;
import net.minestom.server.chat.JsonMessage;
@ -47,13 +50,14 @@ import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.UnaryOperator;
/**
* Could be a player, a monster, or an object.
* <p>
* To create your own entity you probably want to extends {@link LivingEntity} or {@link EntityCreature} instead.
*/
public class Entity implements Viewable, EventHandler, DataContainer, PermissionHandler {
public class Entity implements Viewable, EventHandler, DataContainer, PermissionHandler, HoverEventSource<ShowEntity> {
private static final Map<Integer, Entity> entityById = new ConcurrentHashMap<>();
private static final Map<UUID, Entity> entityByUuid = new ConcurrentHashMap<>();
@ -1528,6 +1532,11 @@ public class Entity implements Viewable, EventHandler, DataContainer, Permission
this.customSynchronizationCooldown = cooldown;
}
@Override
public @NotNull HoverEvent<ShowEntity> asHoverEvent(@NotNull UnaryOperator<ShowEntity> op) {
return HoverEvent.showEntity(ShowEntity.of(this.entityType, this.uuid));
}
private UpdateOption getSynchronizationCooldown() {
if (this.customSynchronizationCooldown != null) {
return this.customSynchronizationCooldown;

View File

@ -7,6 +7,9 @@ import net.kyori.adventure.identity.Identity;
import net.kyori.adventure.inventory.Book;
import net.kyori.adventure.sound.SoundStop;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.event.HoverEvent.ShowEntity;
import net.kyori.adventure.text.event.HoverEventSource;
import net.kyori.adventure.title.Title;
import net.minestom.server.MinecraftServer;
import net.minestom.server.advancements.AdvancementTab;
@ -77,6 +80,7 @@ import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.UnaryOperator;
/**
* Those are the major actors of the server,
@ -84,7 +88,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* <p>
* You can easily create your own implementation of this and use it with {@link ConnectionManager#setPlayerProvider(PlayerProvider)}.
*/
public class Player extends LivingEntity implements CommandSender, Localizable {
public class Player extends LivingEntity implements CommandSender, Localizable, HoverEventSource<ShowEntity> {
private long lastKeepAlive;
private boolean answerKeepAlive;
@ -2536,6 +2540,11 @@ public class Player extends LivingEntity implements CommandSender, Localizable {
return lastKeepAlive;
}
@Override
public @NotNull HoverEvent<ShowEntity> asHoverEvent(@NotNull UnaryOperator<ShowEntity> op) {
return HoverEvent.showEntity(ShowEntity.of(EntityType.PLAYER, this.uuid, this.displayName));
}
/**
* Gets the packet to add the player from the tab-list.
*

View File

@ -3,6 +3,9 @@ package net.minestom.server.item;
import it.unimi.dsi.fastutil.objects.Object2ShortMap;
import it.unimi.dsi.fastutil.objects.Object2ShortOpenHashMap;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.event.HoverEvent.ShowItem;
import net.kyori.adventure.text.event.HoverEventSource;
import net.minestom.server.MinecraftServer;
import net.minestom.server.chat.JsonMessage;
import net.minestom.server.data.Data;
@ -27,6 +30,7 @@ import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import java.util.*;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
// TODO should we cache a ByteBuf of this item for faster packet write
@ -40,7 +44,7 @@ import java.util.stream.Collectors;
* 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}.
*/
public class ItemStack implements DataContainer, PublicCloneable<ItemStack> {
public class ItemStack implements DataContainer, PublicCloneable<ItemStack>, HoverEventSource<ShowItem> {
public static final OwnershipHandler<Data> DATA_OWNERSHIP = new OwnershipHandler<>();
public static final String OWNERSHIP_DATA_KEY = "ownership_identifier";
@ -850,6 +854,11 @@ public class ItemStack implements DataContainer, PublicCloneable<ItemStack> {
throw new UnsupportedOperationException("Not implemented yet");
}
@Override
public @NotNull HoverEvent<ShowItem> asHoverEvent(@NotNull UnaryOperator<ShowItem> op) {
return HoverEvent.showItem(op.apply(ShowItem.of(this.material, this.amount, NBTUtils.asBinaryTagHolder(this.toNBT().getCompound("tag")))));
}
// Callback events
/**

View File

@ -1,13 +1,12 @@
package net.minestom.server.utils;
import net.kyori.adventure.nbt.api.BinaryTagHolder;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.kyori.adventure.util.Codec;
import net.minestom.server.MinecraftServer;
import net.minestom.server.attribute.Attribute;
import net.minestom.server.attribute.AttributeOperation;
import net.minestom.server.chat.ChatParser;
import net.minestom.server.chat.ColoredText;
import net.minestom.server.chat.JsonMessage;
import net.minestom.server.data.Data;
import net.minestom.server.data.DataType;
import net.minestom.server.inventory.Inventory;
@ -28,17 +27,36 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.StringReader;
import java.util.*;
// for lack of a better name
public final class NBTUtils {
private final static Logger LOGGER = LoggerFactory.getLogger(NBTUtils.class);
/**
* An Adventure codec to convert between NBT and SNBT.
*/
public static final Codec<NBT, String, NBTException, RuntimeException> SNBT_CODEC
= Codec.of(encoded -> new SNBTParser(new StringReader(encoded)).parse(), NBT::toSNBT);
private NBTUtils() {
}
/**
* Turns an {@link NBTCompound} into an Adventure {@link BinaryTagHolder}.
* @param tag the tag, if any
* @return the binary tag holder, or {@code null} if the tag was null
*/
public static @Nullable BinaryTagHolder asBinaryTagHolder(@Nullable NBTCompound tag) {
if (tag == null) {
return null;
}
return BinaryTagHolder.encode(tag, SNBT_CODEC);
}
/**
* Loads all the items from the 'items' list into the given inventory
*