Jugadores
Un registro de reservas, cooldowns, teletransportes, snapshots, clanes, combate y cabezas.
Un jugador, una actividad
El problema que resuelve: tres minijuegos en un servidor, cada uno con su método isInGame(player),
cada uno preguntando a los otros dos por reflexión, cada uno respondiendo sobre un momento que ya había
pasado para cuando se ejecutaba la entrada.
PluginSessions sessions = Sessions.of(this);
if (!Sessions.isFree(player)) {
Sessions.holder(player).ifPresent(claim ->
Text.of("Ocupado en " + claim.kind()).send(player));
return;
}
sessions.claim(player, "Event", () -> leaveEvent(player))
.ifPresent(claim -> join(player));| Llamada | Qué hace |
|---|---|
Sessions.isFree(player) | Si algo lo tiene. Una pregunta, no una reserva. |
Sessions.holder(player) | Quién lo tiene, y cómo lo llamó. |
sessions.claim(player, kind, onRelease) | Tomarlo. Atómico — esto es lo que decide de verdad. |
sessions.mine(player) | La reserva, si es nuestra. |
sessions.release(player) | Devolverlo. |
Entre preguntar y actuar, otro puede haberse llevado al jugador. claim es lo que decide, y devuelve
vacío cuando perdió la carrera. El callback de liberación es cómo se le dice a quien lo tiene que lo
suelte.
La reserva es reentrante para su dueño: un jugador que pasa del lobby de un evento a la partida, o de jugar a espectar, mantiene una única reserva continua en vez de soltarla y competir por recuperarla.
Nada del registro sabe qué modos existen, así que un modo añadido más tarde queda cubierto sin tocarlo.
Cooldowns
La base sobre la que se apoya cada cooldown del ecosistema, para que una barra pueda mostrar uno sin ser su dueña:
PluginCooldowns cooldowns = Cooldowns.of(this);
cooldowns.startSeconds(player, "pearl", 16);
cooldowns.isActive(player, "pearl");
cooldowns.remainingSeconds(player, "pearl");CooldownScope amplía la clave más allá de un jugador — un cooldown por arena, por clan o de servidor
entero. ItemCooldowns pone además el barrido de cooldown de vanilla sobre un item, para que el cliente
lo apague visualmente.
Un efecto puede leer un cooldown en marcha en vez de contar por su cuenta — ver Efectos · Temporizadores.
Teletransportes
Mover a un jugador rara vez es solo player.teleport(...):
PluginTeleports teleports = Teleports.of(this);
teleports.to(player, spawn)
.warmup(Duration.ofSeconds(3))
.cancelOnMove()
.cancelOnDamage()
.go();| Llamada | Qué hace |
|---|---|
to(player, location) | Una petición, configurada y luego enviada. |
toAll(players, location) | Un grupo a la vez. |
back(player) | Donde estaba antes del último teletransporte. |
lastLocationOf(player) | Esa ubicación, sin moverlo. |
request(from, to, …) | Una petición estilo /tpa. |
accept(target, from) / deny(…) | Responderla. |
Los calentamientos, los aterrizajes seguros, el historial de /back y los traspasos entre servidores
viven aquí, y todos corren en el hilo del propio jugador.
Snapshots
El estado de un jugador guardado para después — en memoria mientras un menú está abierto, o almacenado para que sobreviva a un reinicio:
PluginSnapshots snapshots = Snapshots.of(this);
Snapshot held = snapshots.capture(player); // en memoria, ahora mismo
snapshots.saveAndClear(player, "event:lms1"); // guardado, y el jugador vaciado
snapshots.restore(player, "event:lms1"); // devueltocapture es el de memoria, para un menú que va a devolver el estado en un momento. save lo escribe
bajo un id de contexto para que sobreviva a un reinicio, y saveAndClear hace las dos mitades de
"guarda esto y dale el kit" en una llamada.
Clanes
Una API sobre ocho plugins de clanes, detectados automáticamente al arrancar:
if (Clans.isSupported()) {
Optional<String> tag = Clans.clanTag(player.getUniqueId());
Optional<Clan> clan = Clans.clanOf(player.getUniqueId());
}Orden de detección — gana el primero presente y accesible:
- FactionsUUID / Factions
- HuskTowns
- ZelTeams
- RunithClans
- UltimateClans
- Kingdoms / KingdomsX
- SimpleClans
- ExyliaClans
Cada proveedor llega a su plugin por reflexión, de modo que uno instalado cuya API no se pueda alcanzar
se salta con un aviso en vez de ocupar el hueco en silencio. Un plugin que no esté en la lista registra
un ClanBridge, y un puente registrado gana a la detección automática.
Las alianzas y rivalidades forman parte de la API, y los proveedores que no tienen ese concepto responden vacío en vez de inventárselo.
Combate
Si un jugador está peleando, sobre DeluxeCombat, PvPManager o un puente que escribas:
if (Combat.isTagged(player)) {
return;
}La idea es la misma que en clanes: tu plugin hace una pregunta y no le importa qué plugin responde.
Cabezas
Skulls.player("Notch").build();
Skulls.texture(base64).build();
Skulls.url(url).build();Cacheadas, compartidas entre plugins, y sin bloquear nunca: una cabeza que aún no se ha descargado vuelve en plano y se reemplaza cuando llega. Por eso un menú lleno de cabezas de jugador se abre al instante en vez de congelar el servidor en una consulta a Mojang.
¿Falta algo en esta página? Dínoslo en Discord