feat(stealth): conceal identity for prepared sessions
CI / build (push) Successful in 5m4s
Release / release (push) Successful in 6m13s

This commit is contained in:
dmg
2026-08-15 00:16:09 -04:00
parent 90851a0d87
commit 6071bfbdce
16 changed files with 510 additions and 18 deletions
@@ -2,7 +2,7 @@
type: User Story
title: "US-002: Rejoin without a visible identity"
description: Let an unlocked player turn a qualifying invisible disconnect into one identity-concealed session.
status: backlog
status: done
---
# US-002: Rejoin without a visible identity
@@ -11,18 +11,22 @@ As an **unlocked player**, I want to disconnect while invisibility from a potion
## Acceptance criteria
- [ ] An unlocked player becomes eligible for a concealed login only by disconnecting while an invisibility effect from a potion they directly drank remains active.
- [ ] A player who has not unlocked stealth cannot prepare a concealed login.
- [ ] An ordinary disconnect without an active qualifying effect clears any preparation for the next login.
- [ ] On a prepared login, no public join announcement is shown.
- [ ] Throughout the concealed session, the player is absent from every other player's tab list, including administrators' tab lists.
- [ ] Throughout the concealed session, no overhead name tag identifies the player to any other player, including administrators.
- [ ] The concealed player's physical character remains visible in the world and retains ordinary movement, interaction, combat, and permission behavior.
- [ ] The concealed player receives a private message explaining that stealth is active for the session.
- [ ] Concealment lasts until the player disconnects and is handled predictably across death and plugin reload or disable events.
- [ ] Disconnecting consumes the current concealed session; another concealed login requires another qualifying potion and qualifying disconnect.
- [ ] Merely owning the unlock never conceals an ordinary login or carries concealment automatically into a later session.
- [ ] Prepared-login state survives a server restart between the qualifying disconnect and the next login.
- [x] An unlocked player becomes eligible for a concealed login only by disconnecting while an invisibility effect from a potion they directly drank remains active.
- [x] A player who has not unlocked stealth cannot prepare a concealed login.
- [x] An ordinary disconnect without an active qualifying effect clears any preparation for the next login.
- [x] On a prepared login, no public join announcement is shown.
- [x] Throughout the concealed session, the player is absent from every other player's tab list, including administrators' tab lists.
- [x] Throughout the concealed session, no overhead name tag identifies the player to any other player, including administrators.
- [x] The concealed player's physical character remains visible in the world and retains ordinary movement, interaction, combat, and permission behavior.
- [x] The concealed player receives a private message explaining that stealth is active for the session.
- [x] Concealment lasts until the player disconnects and is handled predictably across death and plugin reload or disable events.
- [x] Disconnecting consumes the current concealed session; another concealed login requires another qualifying potion and qualifying disconnect.
- [x] Merely owning the unlock never conceals an ordinary login or carries concealment automatically into a later session.
- [x] Prepared-login state survives a server restart between the qualifying disconnect and the next login.
## Validation
Automated tests verify unlocked and locked disconnect transitions, ordinary-disconnect clearing, one-login consumption, announcement suppression, private activation messaging, ordinary-login presentation, tab removal for existing and new observers, overhead-name suppression, and the absence of entity-hiding calls. ProtocolLib is declared as a required dependency, prepared state round trips through YAML, and `./gradlew clean check jar` passes.
## Related