diff --git a/src/main/java/net/minestom/server/entity/Entity.java b/src/main/java/net/minestom/server/entity/Entity.java index 7f093d589..68b60692a 100644 --- a/src/main/java/net/minestom/server/entity/Entity.java +++ b/src/main/java/net/minestom/server/entity/Entity.java @@ -53,6 +53,7 @@ import java.util.function.Consumer; public abstract class Entity implements Viewable, EventHandler, DataContainer, PermissionHandler { private static final Map entityById = new ConcurrentHashMap<>(); + private static final Map entityByUuid = new ConcurrentHashMap<>(); private static final AtomicInteger lastEntityId = new AtomicInteger(); // Metadata @@ -137,10 +138,10 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P private long ticks; private final EntityTickEvent tickEvent = new EntityTickEvent(this); - public Entity(@NotNull EntityType entityType, @NotNull Position spawnPosition) { + public Entity(@NotNull EntityType entityType, @NotNull UUID uuid, @NotNull Position spawnPosition) { this.id = generateId(); this.entityType = entityType; - this.uuid = UUID.randomUUID(); + this.uuid = uuid; this.position = spawnPosition.clone(); setBoundingBox(0, 0, 0); @@ -148,6 +149,11 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P setAutoViewable(true); entityById.put(id, this); + entityByUuid.put(uuid, this); + } + + public Entity(@NotNull EntityType entityType, @NotNull Position spawnPosition) { + this(entityType, UUID.randomUUID(), spawnPosition); } public Entity(@NotNull EntityType entityType) { @@ -177,6 +183,18 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P return entityById.getOrDefault(id, null); } + /** + * Gets an entity based on its UUID (from {@link #getUuid()}). + * + * @param uuid the entity UUID + * @return the entity having the specified uuid, null if not found + */ + @Nullable + public static Entity getEntity(@NotNull UUID uuid) { + return entityByUuid.getOrDefault(uuid, null); + } + + /** * Generate and return a new unique entity id. *

diff --git a/src/main/java/net/minestom/server/listener/SettingsListener.java b/src/main/java/net/minestom/server/listener/SettingsListener.java index 4a0a618ee..7f23840be 100644 --- a/src/main/java/net/minestom/server/listener/SettingsListener.java +++ b/src/main/java/net/minestom/server/listener/SettingsListener.java @@ -12,7 +12,6 @@ public class SettingsListener { PlayerSettingsChangeEvent playerSettingsChangeEvent = new PlayerSettingsChangeEvent(player); player.callEvent(PlayerSettingsChangeEvent.class, playerSettingsChangeEvent); - } } diff --git a/src/main/java/net/minestom/server/listener/SpectateListener.java b/src/main/java/net/minestom/server/listener/SpectateListener.java new file mode 100644 index 000000000..18098adbf --- /dev/null +++ b/src/main/java/net/minestom/server/listener/SpectateListener.java @@ -0,0 +1,23 @@ +package net.minestom.server.listener; + +import net.minestom.server.entity.Entity; +import net.minestom.server.entity.Player; +import net.minestom.server.network.packet.client.play.ClientSpectatePacket; + +import java.util.UUID; + +public class SpectateListener { + + public static void listener(ClientSpectatePacket packet, Player player) { + final UUID targetUuid = packet.targetUuid; + final Entity target = Entity.getEntity(targetUuid); + + // Check if the target is valid + if (target == null || target == player) + return; + + // TODO check if 'target' is in a different instance + player.spectate(target); + } + +} diff --git a/src/main/java/net/minestom/server/listener/manager/PacketListenerManager.java b/src/main/java/net/minestom/server/listener/manager/PacketListenerManager.java index 09594d762..e9f3ba158 100644 --- a/src/main/java/net/minestom/server/listener/manager/PacketListenerManager.java +++ b/src/main/java/net/minestom/server/listener/manager/PacketListenerManager.java @@ -53,6 +53,7 @@ public final class PacketListenerManager { setListener(ClientTeleportConfirmPacket.class, TeleportListener::listener); setListener(ClientResourcePackStatusPacket.class, ResourcePackListener::listener); setListener(ClientAdvancementTabPacket.class, AdvancementTabListener::listener); + setListener(ClientSpectatePacket.class, SpectateListener::listener); } /**