--- title: PlayerRef type: docs weight: 4 --- PlayerRef fournit un moyen thread-safe de référencer les joueurs à travers les mondes et les threads. ## Pourquoi PlayerRef ? {{< callout type="warning" >}} Les références directes à Player ne doivent jamais être stockées ou utilisées à travers les threads. Utilisez toujours PlayerRef pour : - Les opérations asynchrones - Le stockage de références de joueurs - Le suivi des joueurs entre mondes {{< /callout >}} ## Obtenir un PlayerRef ```java import com.hypixel.hytale.server.core.entity.entities.Player; import com.hypixel.hytale.server.core.universe.PlayerRef; import java.util.UUID; Player player = ...; PlayerRef ref = player.getPlayerRef(); // PlayerRef contient les données essentielles du joueur UUID uuid = ref.getUuid(); String name = ref.getUsername(); // Note : getUsername(), PAS getName() ``` ## Utiliser PlayerRef dans le Code Async ```java import com.hypixel.hytale.server.core.event.events.player.PlayerConnectEvent; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.hypixel.hytale.server.core.Message; import com.hypixel.hytale.component.Ref; import java.util.concurrent.CompletableFuture; getEventRegistry().register(PlayerConnectEvent.class, event -> { PlayerRef ref = event.getPlayerRef(); World world = event.getWorld(); // Utiliser ref dans les opérations async CompletableFuture.runAsync(() -> { // Sûr d'utiliser ref ici PlayerData data = loadPlayerData(ref.getUuid()); // Retourner au thread du monde pour interagir avec le joueur if (world != null) { world.execute(() -> { Ref entityRef = ref.getReference(); if (entityRef != null && entityRef.isValid()) { applyData(entityRef, data); } // sendMessage est directement sur PlayerRef ref.sendMessage(Message.raw("Vos données ont été chargées !")); }); } }); }); ``` ## Méthodes de PlayerRef ```java PlayerRef ref = player.getPlayerRef(); // Obtenir l'UUID du joueur (toujours disponible) UUID uuid = ref.getUuid(); // Obtenir le nom d'utilisateur du joueur (toujours disponible) // Note : C'est getUsername(), PAS getName() String name = ref.getUsername(); // Obtenir la référence d'entité Ref entityRef = ref.getReference(); // Vérifier si la référence est valide boolean isValid = ref.isValid(); // Envoyer un message directement au joueur ref.sendMessage(Message.raw("Bonjour !")); // Obtenir le transform (position/rotation) Transform transform = ref.getTransform(); ``` {{< callout type="warning" >}} **Note :** `PlayerRef.getPlayer()` n'existe PAS. PlayerRef stocke les données essentielles qui survivent aux changements de monde, mais ne détient pas de référence Player directe. {{< /callout >}} ## PlayerRefs du Monde Les mondes fournissent l'accès aux PlayerRefs : ```java import com.hypixel.hytale.server.core.universe.Universe; import java.util.Collection; import java.util.List; World world = Universe.get().getWorld("default"); // Obtenir tous les refs de joueurs dans ce monde Collection playerRefs = world.getPlayerRefs(); // Obtenir tous les joueurs actifs (retourne List) List players = world.getPlayers(); ``` ## Stocker les Références de Joueurs ```java import com.hypixel.hytale.server.core.event.events.player.PlayerDisconnectEvent; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public class MyPlugin extends JavaPlugin { // Stocker les PlayerRefs, PAS les Players private final Map playerData = new ConcurrentHashMap<>(); public MyPlugin(JavaPluginInit init) { super(init); } @Override public void setup() { getEventRegistry().register(PlayerConnectEvent.class, event -> { PlayerRef ref = event.getPlayerRef(); playerData.put(ref.getUuid(), new PlayerData(ref)); }); getEventRegistry().register(PlayerDisconnectEvent.class, event -> { playerData.remove(event.getPlayerRef().getUuid()); }); } } class PlayerData { private final PlayerRef playerRef; private int score; public PlayerData(PlayerRef ref) { this.playerRef = ref; } public void addScore(int amount) { this.score += amount; playerRef.sendMessage(Message.raw("Score : " + score)); } } ``` ## Messagerie Inter-Mondes ```java // Envoyer un message au joueur peu importe son monde actuel public void sendGlobalMessage(PlayerRef ref, String message) { // PlayerRef.sendMessage gère la messagerie inter-mondes directement ref.sendMessage(Message.raw(message)); } // Diffuser à tous les joueurs dans tous les mondes public void broadcastAll(String message) { Message msg = Message.raw(message); for (World world : Universe.get().getWorlds().values()) { for (PlayerRef ref : world.getPlayerRefs()) { ref.sendMessage(msg); } } } ``` ## PlayerRef vs Player | Fonctionnalité | Player | PlayerRef | |----------------|--------|-----------| | Thread-safe | Non | Oui | | Stockable | Non | Oui | | Inter-mondes | Non | Oui | | Obtenir UUID | Oui | Oui | | Obtenir Nom | Oui (`getDisplayName()`) | Oui (`getUsername()`) | | Envoyer Message | Oui | Oui (directement) | | Obtenir Position | Via TransformComponent | Via `getTransform()` | ## Bonnes Pratiques {{< callout type="info" >}} **Utilisez toujours PlayerRef quand :** - Vous stockez des références de joueurs au-delà de la méthode actuelle - Vous passez à des tâches asynchrones - Vous suivez les joueurs à travers les changements de monde - Vous construisez des structures de données liées aux joueurs {{< /callout >}} ```java // Bien : Stocker PlayerRef private final Map trackedPlayers = new ConcurrentHashMap<>(); // Mauvais : Stocker Player directement // private final Map players = new HashMap<>(); // NE FAITES PAS ÇA // Bien : Utiliser ref en async CompletableFuture.runAsync(() -> { PlayerRef ref = ...; // ref est sûr ici }); // Mauvais : Utiliser Player en async // CompletableFuture.runAsync(() -> { // Player player = ...; // PAS SÛR // }); ```