Fix incorrect functionality of ClientSpectatePacket (#1402)

This commit is contained in:
Koding 2022-09-14 21:44:43 +10:00 committed by GitHub
parent fc90fe8852
commit 18c46481f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 62 additions and 3 deletions

View File

@ -0,0 +1,29 @@
package net.minestom.server.event.player;
import net.minestom.server.entity.Entity;
import net.minestom.server.entity.Player;
import net.minestom.server.event.trait.PlayerEvent;
import org.jetbrains.annotations.NotNull;
/**
* Called by the SpectateListener when a player starts spectating an entity.
*/
@SuppressWarnings("ClassCanBeRecord")
public class PlayerSpectateEvent implements PlayerEvent {
private final Player player;
private final Entity target;
public PlayerSpectateEvent(Player player, Entity target) {
this.player = player;
this.target = target;
}
public Entity getTarget() {
return target;
}
@Override
public @NotNull Player getPlayer() {
return player;
}
}

View File

@ -1,7 +1,11 @@
package net.minestom.server.listener;
import net.minestom.server.entity.Entity;
import net.minestom.server.entity.GameMode;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.player.PlayerSpectateEvent;
import net.minestom.server.instance.Instance;
import net.minestom.server.network.packet.client.play.ClientSpectatePacket;
import java.util.UUID;
@ -9,15 +13,36 @@ import java.util.UUID;
public class SpectateListener {
public static void listener(ClientSpectatePacket packet, Player player) {
// Ignore if the player is not in spectator mode
if (player.getGameMode() != GameMode.SPECTATOR) {
return;
}
final UUID targetUuid = packet.target();
final Entity target = Entity.getEntity(targetUuid);
// Check if the target is valid
if (target == null || target == player)
if (target == null || target == player) {
return;
}
// TODO check if 'target' is in a different instance
player.spectate(target);
// Ignore if they're not attached to any instances
Instance targetInstance = target.getInstance();
Instance playerInstance = player.getInstance();
if (targetInstance == null || playerInstance == null) {
return;
}
// Ignore if they're not in the same instance. Vanilla actually allows for
// cross-instance spectating, but it's not really a good idea for Minestom.
if (targetInstance.getUniqueId() != playerInstance.getUniqueId()) {
return;
}
// Despite the name of this packet being spectate, it is sent when the player
// uses their hotbar to switch between entities, which actually performs a teleport
// instead of a spectate.
EventDispatcher.call(new PlayerSpectateEvent(player, target));
}
}

View File

@ -7,6 +7,11 @@ import org.jetbrains.annotations.NotNull;
import java.util.UUID;
/**
* The ClientSpectatePacket is sent when the client interacts with their hotbar to switch between entities.
* Contrary to its name, it is actually used to teleport the player to the entity they are switching to,
* rather than spectating them.
*/
public record ClientSpectatePacket(@NotNull UUID target) implements ClientPacket {
public ClientSpectatePacket(BinaryReader reader) {
this(reader.readUuid());