commit 470e372e474aa6bdb050b4ec14fea6fa6934c5b0 Author: Dylan Garvis Date: Fri Aug 14 22:08:35 2026 -0400 docs(design): define tyrant game stories diff --git a/design/concepts/game-state-machine.md b/design/concepts/game-state-machine.md new file mode 100644 index 0000000..3d9ac37 --- /dev/null +++ b/design/concepts/game-state-machine.md @@ -0,0 +1,35 @@ +--- +type: Design Concept +title: Tyrant Game State Machine +description: Defines lifecycle, succession, selection, and pause behavior for a Tyrant game. +--- + +# Tyrant Game State Machine + +## Lifecycle + +The game begins unstarted. An administrator starts it by assigning the first Tyrant; the administrator may explicitly assign the first Vigilante or allow selection from eligible recently active players. A running game may be paused without deleting its state and later resumed. + +Pausing freezes gameplay progression, role inactivity checks, pending-selection deadlines, ability cooldowns, and daily-use timers. Role and class effects are suppressed while paused and restored on resume. + +## Tyrant succession + +When a player directly kills the Tyrant, that killer becomes the new Tyrant. When no player is credited with the death, an eligible opted-in player active during the preceding 24 hours is selected randomly. The former Tyrant is excluded when another candidate exists. + +Every Tyrant death ends the reign, clears all role-side assignments, resets the former Tyrant's reign progression, and requires a new Vigilante. The new Tyrant receives one starting unlock choice. + +## Vigilante succession + +Every Vigilante death ends that assignment regardless of cause. A replacement is selected randomly from eligible opted-in players active during the preceding 24 hours. The Tyrant is never eligible. The previous Vigilante is excluded when another eligible non-Tyrant exists and may be selected again only as a fallback. Followers are cleared rather than transferred. + +A Tyrant earns progression from the death only when the Tyrant personally killed the Vigilante. + +## Pending selections + +An offline random selectee has 24 hours of unpaused time to log in and confirm the assignment. Failure causes another selection. When no eligible candidate exists, the position remains vacant and selection retries periodically without assigning the Tyrant to both roles. + +## Related stories + +- [Start, pause, and administer the game](../user-stories/us-001-start-pause-and-administer.md) +- [Transfer and reset the Tyrant role](../user-stories/us-002-transfer-and-reset-tyrant.md) +- [Handle inactivity and pending selections](../user-stories/us-010-handle-inactivity-and-selection.md) diff --git a/design/concepts/index.md b/design/concepts/index.md new file mode 100644 index 0000000..53c793d --- /dev/null +++ b/design/concepts/index.md @@ -0,0 +1,5 @@ +# Design Concepts + +- [Game state machine](game-state-machine.md) - Running, paused, succession, and pending-selection states. +- [Role and class model](role-and-class-model.md) - Role relationships, eligibility, assignments, and unlocks. +- [Persistence model](persistence-model.md) - Durable game and player state requirements. diff --git a/design/concepts/persistence-model.md b/design/concepts/persistence-model.md new file mode 100644 index 0000000..5153175 --- /dev/null +++ b/design/concepts/persistence-model.md @@ -0,0 +1,19 @@ +--- +type: Design Concept +title: Persistence Model +description: Defines the durable state and timekeeping needed to restore a Tyrant game safely. +--- + +# Persistence Model + +State is keyed by player UUID while retaining the latest known player name for display. Durable global state includes lifecycle status, current and pending role holders, selection deadlines, paused durations, and the current Tyrant reign. + +Durable player state includes participation status, opt-out deadline, login history, role or class, Tyrant level, purchased unlocks, unspent choices, Follower relationship, ability cooldowns, daily intelligence use, bound-item delivery state, and captured mobs. + +Elapsed-time rules use UTC instants. Paused time is excluded from timers. Saves use atomic replacement where supported, preserve unknown fields where practical, and reject corrupt records rather than granting powers, assignments, or duplicated entities. + +## Related stories + +- [Inform players and manage participation](../user-stories/us-011-inform-and-manage-participation.md) +- [Configure and persist game state](../user-stories/us-012-configure-and-persist-state.md) +- [Use class ability items](../user-stories/us-014-use-class-ability-items.md) diff --git a/design/concepts/role-and-class-model.md b/design/concepts/role-and-class-model.md new file mode 100644 index 0000000..b90c04d --- /dev/null +++ b/design/concepts/role-and-class-model.md @@ -0,0 +1,38 @@ +--- +type: Design Concept +title: Role and Class Model +description: Defines Tyrant-side classes, Vigilante-side membership, progression, and assignment constraints. +--- + +# Role and Class Model + +## Roles and affiliations + +A running game has one Tyrant and, when an eligible player is available, one Vigilante. The Vigilante may recruit Followers through invitations that require acceptance. The Tyrant may assign the Assassin, Fixer, and Tamer classes after unlocking them. + +Role alignment and Tyrant-side class are independent. A Vigilante or Follower may simultaneously hold one Tyrant-side class, allowing divided loyalties. A player cannot simultaneously be the Tyrant, Vigilante, and/or a Follower, and cannot hold more than one Tyrant-side class. Each Tyrant-side class may be assigned to only one player at a time. Opted-out players are ineligible for every assignment. + +## Tyrant progression + +The Tyrant starts each reign at level zero with one starting unlock choice. Personally killing the Vigilante grants one level and one additional choice. Each of these unlocks can be purchased once per reign: + +- Assassin class +- Fixer class +- Tamer class +- Vigilante roster intelligence +- Permanent Resistance +- Permanent Strength + +## Proximity + +Unless a more specific rule applies, "near the Tyrant" means in the same world and within a configurable 50-block three-dimensional distance. + +## Effect safety + +Vigilante Follower scaling is capped by default at Strength V and Resistance IV, with validated configurable caps. Permanent and conditional class effects are reapplied after ordinary Minecraft removal while the game is running and the assignment remains valid. + +## Related stories + +- [Progress and purchase Tyrant unlocks](../user-stories/us-003-progress-and-purchase-unlocks.md) +- [Assign unlocked classes](../user-stories/us-004-assign-unlocked-classes.md) +- [Support the Vigilante and Followers](../user-stories/us-008-support-vigilante-and-followers.md) diff --git a/design/index.md b/design/index.md new file mode 100644 index 0000000..cf94f7c --- /dev/null +++ b/design/index.md @@ -0,0 +1,18 @@ +--- +type: Index +title: Spigot Tyrant Design +description: Entry point for the Spigot Tyrant OKF knowledge bundle. +okf_version: "0.1" +--- + +# Spigot Tyrant Design + +This bundle documents the asymmetric Tyrant game, its role succession, class abilities, participation rules, persistence, administration, and delivery requirements. + +## Explore + +- [User stories](user-stories/index.md) +- [Game state machine](concepts/game-state-machine.md) +- [Role and class model](concepts/role-and-class-model.md) +- [Persistence model](concepts/persistence-model.md) +- [Design log](log.md) diff --git a/design/log.md b/design/log.md new file mode 100644 index 0000000..082b716 --- /dev/null +++ b/design/log.md @@ -0,0 +1,19 @@ +--- +type: Log +title: Spigot Tyrant Design Log +description: Chronological record of material decisions affecting the Spigot Tyrant design. +--- + +# Spigot Tyrant Design Log + +## 2026-08-14 — Initial game design + +- The game has one Tyrant and one Vigilante, with Followers aligned to the Vigilante and Assassin, Fixer, and Tamer classes assigned by the Tyrant. +- A player who kills the Tyrant becomes the next Tyrant; a Tyrant death without a player killer causes random succession among recently active eligible players. +- Every Tyrant death clears all class and Follower assignments and resets the former Tyrant's reign progression. +- Every Vigilante death rerolls the role among eligible players active in the preceding 24 hours. The previous Vigilante is reused only when no other eligible non-Tyrant player exists. +- A Tyrant levels and earns one unlock choice only by personally killing the Vigilante. +- Class abilities use named bound items where appropriate. Consumed cooldown items return when ready, and `/tyrant item` recovers missing ready items. +- The Tamer has no cooldown and uses a named fishing rod plus a separate captured-mob item. +- Game timers freeze while administratively paused. +- The project will follow the Java 17, Gradle, testing, Gitea CI, and semantic-release structure demonstrated by `../spigot-base/`. diff --git a/design/user-stories/index.md b/design/user-stories/index.md new file mode 100644 index 0000000..0dd8f75 --- /dev/null +++ b/design/user-stories/index.md @@ -0,0 +1,16 @@ +# Spigot Tyrant User Stories + +1. [US-001: Start, pause, and administer the game](us-001-start-pause-and-administer.md) +2. [US-002: Transfer and reset the Tyrant role](us-002-transfer-and-reset-tyrant.md) +3. [US-003: Progress and purchase Tyrant unlocks](us-003-progress-and-purchase-unlocks.md) +4. [US-004: Assign unlocked classes](us-004-assign-unlocked-classes.md) +5. [US-005: Use Assassin abilities](us-005-use-assassin-abilities.md) +6. [US-006: Use Fixer abilities](us-006-use-fixer-abilities.md) +7. [US-007: Capture and place mobs as a Tamer](us-007-capture-and-place-mobs.md) +8. [US-008: Support the Vigilante and Followers](us-008-support-vigilante-and-followers.md) +9. [US-009: Purchase and use Tyrant abilities](us-009-use-tyrant-abilities.md) +10. [US-010: Handle inactivity and pending selections](us-010-handle-inactivity-and-selection.md) +11. [US-011: Inform players and manage participation](us-011-inform-and-manage-participation.md) +12. [US-012: Configure and persist game state](us-012-configure-and-persist-state.md) +13. [US-013: Build, test, and release the plugin](us-013-build-test-and-release.md) +14. [US-014: Use class ability items](us-014-use-class-ability-items.md) diff --git a/design/user-stories/us-001-start-pause-and-administer.md b/design/user-stories/us-001-start-pause-and-administer.md new file mode 100644 index 0000000..e386d4d --- /dev/null +++ b/design/user-stories/us-001-start-pause-and-administer.md @@ -0,0 +1,26 @@ +--- +type: User Story +title: "US-001: Start, pause, and administer the game" +description: Give server operators safe control over the Tyrant game's lifecycle and state. +status: backlog +--- + +# US-001: Start, pause, and administer the game + +As a **server operator**, I want to start, pause, resume, and inspect the game so that it can coexist safely with maintenance and other server events. + +## Acceptance criteria + +- [ ] An administrator can start the first game by assigning the initial Tyrant. +- [ ] The administrator may assign the first Vigilante or allow random selection from eligible recently active players. +- [ ] An administrator can pause and resume the game without deleting game state. +- [ ] Pausing freezes progression, cooldowns, daily-use timers, inactivity checks, and pending-selection deadlines. +- [ ] Role and class effects are suppressed while paused and restored when play resumes. +- [ ] Administrative commands require the `spigottyrant.admin` permission, granted to server operators by default. +- [ ] Administrators can inspect lifecycle state, roles, classes, Followers, purchases, levels, cooldowns, participation, and pending selections. +- [ ] Destructive administrative operations require explicit confirmation. + +## Related + +- [Tyrant game state machine](../concepts/game-state-machine.md) +- [Configure and persist game state](us-012-configure-and-persist-state.md) diff --git a/design/user-stories/us-002-transfer-and-reset-tyrant.md b/design/user-stories/us-002-transfer-and-reset-tyrant.md new file mode 100644 index 0000000..134f7c1 --- /dev/null +++ b/design/user-stories/us-002-transfer-and-reset-tyrant.md @@ -0,0 +1,27 @@ +--- +type: User Story +title: "US-002: Transfer and reset the Tyrant role" +description: End a Tyrant's reign cleanly and establish a valid successor after death. +status: backlog +--- + +# US-002: Transfer and reset the Tyrant role + +As a **player**, I want defeating the Tyrant to transfer power predictably so that the central conflict always has meaningful consequences. + +## Acceptance criteria + +- [ ] A player directly credited with killing the Tyrant becomes the new Tyrant. +- [ ] A Tyrant death without a player killer selects an eligible opted-in player active within the preceding 24 hours at random. +- [ ] The former Tyrant is excluded from random succession when another eligible candidate exists. +- [ ] The former Tyrant's level, unlocks, unspent choices, and Tyrant ability cooldowns reset when the reign ends. +- [ ] Every Assassin, Fixer, Tamer, Vigilante, and Follower assignment is cleared when the Tyrant dies. +- [ ] A new Vigilante is selected under the normal candidate rules after succession. +- [ ] The new Tyrant receives exactly one starting unlock choice. +- [ ] The Tyrant's displayed name is red and the Tyrant has a red glowing outline while the game is running. +- [ ] Succession cannot assign the same player as both Tyrant and Vigilante. + +## Related + +- [Tyrant game state machine](../concepts/game-state-machine.md) +- [Progress and purchase Tyrant unlocks](us-003-progress-and-purchase-unlocks.md) diff --git a/design/user-stories/us-003-progress-and-purchase-unlocks.md b/design/user-stories/us-003-progress-and-purchase-unlocks.md new file mode 100644 index 0000000..4ed7b1f --- /dev/null +++ b/design/user-stories/us-003-progress-and-purchase-unlocks.md @@ -0,0 +1,27 @@ +--- +type: User Story +title: "US-003: Progress and purchase Tyrant unlocks" +description: Let the Tyrant earn and spend choices by personally defeating the Vigilante. +status: backlog +--- + +# US-003: Progress and purchase Tyrant unlocks + +As the **Tyrant**, I want to earn one meaningful choice for defeating the Vigilante so that each reign develops differently. + +## Acceptance criteria + +- [ ] The Tyrant gains one level and one unlock choice only when personally credited with killing the current Vigilante. +- [ ] A Vigilante death caused by another player, the environment, or the Vigilante does not level the Tyrant. +- [ ] Available purchases are Assassin, Fixer, Tamer, roster intelligence, permanent Resistance, and permanent Strength. +- [ ] Each class or ability can be purchased at most once during a reign. +- [ ] A menu or command clearly identifies purchased, available, and unavailable choices. +- [ ] A purchase consumes exactly one unspent choice and cannot be duplicated by retries or concurrent input. +- [ ] Progress cannot be earned or spent while the game is paused. +- [ ] Levels, purchases, and unspent choices survive logout and restart but reset when the reign ends. + +## Related + +- [Role and class model](../concepts/role-and-class-model.md) +- [Assign unlocked classes](us-004-assign-unlocked-classes.md) +- [Purchase and use Tyrant abilities](us-009-use-tyrant-abilities.md) diff --git a/design/user-stories/us-004-assign-unlocked-classes.md b/design/user-stories/us-004-assign-unlocked-classes.md new file mode 100644 index 0000000..b9dc5fa --- /dev/null +++ b/design/user-stories/us-004-assign-unlocked-classes.md @@ -0,0 +1,26 @@ +--- +type: User Story +title: "US-004: Assign unlocked classes" +description: Let the Tyrant assign each purchased class to one eligible participant. +status: backlog +--- + +# US-004: Assign unlocked classes + +As the **Tyrant**, I want to assign unlocked specialist classes so that I can build a small team suited to my reign. + +## Acceptance criteria + +- [ ] The Tyrant can assign only Assassin, Fixer, and Tamer classes purchased during the current reign. +- [ ] Each class can be assigned to at most one player at a time, and a player can hold at most one Tyrant-side class. +- [ ] Role alignment and Tyrant-side class are independent: the Vigilante or a Follower may simultaneously be the Assassin, Fixer, or Tamer. +- [ ] The Tyrant cannot assign a class to the Tyrant, an opted-out player, or another ineligible player. +- [ ] Reassignment removes the class and its bound items and effects from the previous holder before granting it to the new holder. +- [ ] Assignment and removal are stored by UUID and communicated clearly to affected players. +- [ ] A class holder is reminded of the assignment and its controls on login. +- [ ] All class assignments end when the Tyrant's reign ends. + +## Related + +- [Role and class model](../concepts/role-and-class-model.md) +- [Use class ability items](us-014-use-class-ability-items.md) diff --git a/design/user-stories/us-005-use-assassin-abilities.md b/design/user-stories/us-005-use-assassin-abilities.md new file mode 100644 index 0000000..21e52f7 --- /dev/null +++ b/design/user-stories/us-005-use-assassin-abilities.md @@ -0,0 +1,27 @@ +--- +type: User Story +title: "US-005: Use Assassin abilities" +description: Give the Assassin timed stealth and a risky burst-mobility ability. +status: backlog +--- + +# US-005: Use Assassin abilities + +As the **Assassin**, I want stealth and burst mobility so that I can ambush opponents while accepting a combat penalty afterward. + +## Acceptance criteria + +- [ ] The Assassin can activate ten minutes of invisibility once per rolling hour using the named Assassin ability item. +- [ ] Invisibility displays no potion particles. +- [ ] Activation while in the same world and within the configured Tyrant range grants twenty minutes instead. +- [ ] Proximity is evaluated when the ability is activated and does not alter the active duration afterward. +- [ ] The Assassin can double-jump once every 60 seconds without requiring an item. +- [ ] A successful double-jump grants Speed for 15 seconds and Weakness III for 20 seconds. +- [ ] Grounding and supported movement reset jump availability only after the 60-second cooldown has elapsed. +- [ ] Ability cooldowns use unpaused elapsed time and survive death, logout, and restart. +- [ ] The player can inspect remaining cooldowns and receives clear feedback when an activation is unavailable. + +## Related + +- [Use class ability items](us-014-use-class-ability-items.md) +- [Configure and persist game state](us-012-configure-and-persist-state.md) diff --git a/design/user-stories/us-006-use-fixer-abilities.md b/design/user-stories/us-006-use-fixer-abilities.md new file mode 100644 index 0000000..6d5e302 --- /dev/null +++ b/design/user-stories/us-006-use-fixer-abilities.md @@ -0,0 +1,25 @@ +--- +type: User Story +title: "US-006: Use Fixer abilities" +description: Give the Fixer a periodic offensive and health enhancement strengthened near the Tyrant. +status: backlog +--- + +# US-006: Use Fixer abilities + +As the **Fixer**, I want a substantial temporary combat boost so that I can protect the Tyrant during important fights. + +## Acceptance criteria + +- [ ] The Fixer can activate ten minutes of Strength and Health Boost once per rolling hour using the named Fixer ability item. +- [ ] Normal activation provides two total rows of hearts when combined with the player's normal maximum health. +- [ ] Activation in the same world and within the configured Tyrant range provides three total rows of hearts. +- [ ] Proximity is evaluated when the ability is activated and does not alter the active tier afterward. +- [ ] Health is safely clamped when the boost expires, is suppressed, or changes tier. +- [ ] The cooldown uses unpaused elapsed time and survives death, logout, and restart. +- [ ] The player can inspect the remaining cooldown and receives clear feedback when activation is unavailable. + +## Related + +- [Use class ability items](us-014-use-class-ability-items.md) +- [Configure and persist game state](us-012-configure-and-persist-state.md) diff --git a/design/user-stories/us-007-capture-and-place-mobs.md b/design/user-stories/us-007-capture-and-place-mobs.md new file mode 100644 index 0000000..532d885 --- /dev/null +++ b/design/user-stories/us-007-capture-and-place-mobs.md @@ -0,0 +1,28 @@ +--- +type: User Story +title: "US-007: Capture and place mobs as a Tamer" +description: Let the Tamer move supported mobs without losing or duplicating them. +status: backlog +--- + +# US-007: Capture and place mobs as a Tamer + +As the **Tamer**, I want to capture a mob and release it elsewhere so that I can relocate creatures safely. + +## Acceptance criteria + +- [ ] The Tamer can use a named fishing rod on a supported targeted mob to capture it with no cooldown. +- [ ] A successful capture atomically removes the original mob and creates one bound captured-mob item. +- [ ] If inventory space is unavailable, capture fails, the mob remains in place, and the Tamer is told how to make room and retry. +- [ ] Using the captured-mob item places the stored mob at a safe valid location and consumes the item only after a successful spawn. +- [ ] Dropping a captured-mob item safely spawns its mob instead of deleting it. +- [ ] Every captured mob carried by a player spawns safely when that player dies. +- [ ] Ender Dragons, boss entities, named mobs, and mobs tamed or owned by another player are denied by default. +- [ ] Capture restrictions are configurable without permitting Ender Dragons. +- [ ] Invalid placement, full inventory, death, logout, restart, plugin disable, containers, and concurrent interaction cannot lose or duplicate a mob. +- [ ] Stored mob data is validated defensively before spawning and cannot execute untrusted serialized behavior. + +## Related + +- [Use class ability items](us-014-use-class-ability-items.md) +- [Persistence model](../concepts/persistence-model.md) diff --git a/design/user-stories/us-008-support-vigilante-and-followers.md b/design/user-stories/us-008-support-vigilante-and-followers.md new file mode 100644 index 0000000..bed6c4c --- /dev/null +++ b/design/user-stories/us-008-support-vigilante-and-followers.md @@ -0,0 +1,30 @@ +--- +type: User Story +title: "US-008: Support the Vigilante and Followers" +description: Give the Vigilante a replaceable role and combat strength derived from nearby Followers. +status: backlog +--- + +# US-008: Support the Vigilante and Followers + +As the **Vigilante**, I want nearby living Followers to strengthen me against the Tyrant so that coordinated resistance is rewarded. + +## Acceptance criteria + +- [ ] Exactly one active Vigilante exists while the game is running whenever an eligible player is available. +- [ ] The Vigilante can invite eligible opted-in players to become Followers, and recruitment requires acceptance. +- [ ] The Vigilante can dismiss Followers and Followers can leave voluntarily. +- [ ] While actively fighting the Tyrant, the Vigilante gains one potion level each of Strength and Resistance per living Follower in the same world within 50 blocks. +- [ ] Offline, dead, opted-out, dismissed, or out-of-range Followers do not count. +- [ ] A Vigilante or Follower may simultaneously hold one Tyrant-side class without losing Vigilante-side membership. +- [ ] Effect levels update promptly as combat starts or ends and as Followers move, die, respawn, disconnect, or change assignment. +- [ ] Scaling is capped by validated configuration, defaulting to Strength V and Resistance IV. +- [ ] Every Vigilante death ends the assignment and triggers random replacement regardless of cause. +- [ ] The deceased Vigilante is excluded when another eligible non-Tyrant candidate exists and is reused only when no such candidate exists. +- [ ] Followers are cleared rather than transferred when their Vigilante dies or loses the position. +- [ ] The Tyrant is never eligible to be selected as Vigilante. + +## Related + +- [Role and class model](../concepts/role-and-class-model.md) +- [Handle inactivity and pending selections](us-010-handle-inactivity-and-selection.md) diff --git a/design/user-stories/us-009-use-tyrant-abilities.md b/design/user-stories/us-009-use-tyrant-abilities.md new file mode 100644 index 0000000..4afbff8 --- /dev/null +++ b/design/user-stories/us-009-use-tyrant-abilities.md @@ -0,0 +1,26 @@ +--- +type: User Story +title: "US-009: Purchase and use Tyrant abilities" +description: Give the Tyrant persistent combat upgrades and limited intelligence about the opposition. +status: backlog +--- + +# US-009: Purchase and use Tyrant abilities + +As the **Tyrant**, I want permanent upgrades and limited roster intelligence so that I can shape my reign and assess the resistance. + +## Acceptance criteria + +- [ ] Purchasing permanent Strength applies the configured Strength level throughout the current reign while the game is running. +- [ ] Purchasing permanent Resistance applies the configured Resistance level throughout the current reign while the game is running. +- [ ] Permanent effects are restored after death, milk consumption, ordinary effect removal, login, restart, and replacement by a shorter or weaker effect. +- [ ] Roster intelligence can be activated once per rolling 24 unpaused hours after it is purchased. +- [ ] Roster intelligence reports the number of active Vigilante-side members without revealing their identities or locations. +- [ ] Intelligence counts the current Vigilante and living assigned Followers, whether online or offline, according to configurable counting rules. +- [ ] The Tyrant can inspect ability ownership and the remaining intelligence cooldown. +- [ ] Purchases and cooldowns survive restart and end with the Tyrant's reign. + +## Related + +- [Progress and purchase Tyrant unlocks](us-003-progress-and-purchase-unlocks.md) +- [Configure and persist game state](us-012-configure-and-persist-state.md) diff --git a/design/user-stories/us-010-handle-inactivity-and-selection.md b/design/user-stories/us-010-handle-inactivity-and-selection.md new file mode 100644 index 0000000..e006e54 --- /dev/null +++ b/design/user-stories/us-010-handle-inactivity-and-selection.md @@ -0,0 +1,28 @@ +--- +type: User Story +title: "US-010: Handle inactivity and pending selections" +description: Replace absent or unconfirmed role holders using recently active eligible players. +status: backlog +--- + +# US-010: Handle inactivity and pending selections + +As a **participant**, I want inactive central roles to be replaced fairly so that the game does not stall around absent players. + +## Acceptance criteria + +- [ ] A Tyrant or Vigilante who has not logged in for 48 unpaused hours loses the position. +- [ ] Random candidates are drawn from eligible opted-in players who logged in during the preceding 24 hours. +- [ ] The Tyrant is always excluded from Vigilante selection. +- [ ] A previous role holder is excluded when another eligible candidate exists and may be reused only as a fallback. +- [ ] Tyrant inactivity ends the reign, clears all assignments, and invokes normal random Tyrant succession followed by Vigilante selection. +- [ ] Vigilante inactivity clears Followers and rerolls only the Vigilante position. +- [ ] An offline randomly selected candidate must log in within 24 unpaused hours to confirm the assignment. +- [ ] An unconfirmed selection expires and rerolls automatically under the same eligibility rules. +- [ ] Selection remains vacant and retries periodically when no valid candidate exists. +- [ ] Candidate selection cannot assign conflicting roles or choose an opted-out player, including during concurrent joins and deaths. + +## Related + +- [Tyrant game state machine](../concepts/game-state-machine.md) +- [Inform players and manage participation](us-011-inform-and-manage-participation.md) diff --git a/design/user-stories/us-011-inform-and-manage-participation.md b/design/user-stories/us-011-inform-and-manage-participation.md new file mode 100644 index 0000000..2f27a93 --- /dev/null +++ b/design/user-stories/us-011-inform-and-manage-participation.md @@ -0,0 +1,27 @@ +--- +type: User Story +title: "US-011: Inform players and manage participation" +description: Tell players their current place in the game and let unassigned players opt out. +status: backlog +--- + +# US-011: Inform players and manage participation + +As a **player**, I want to understand my status and control my eligibility so that participation is informed and voluntary. + +## Acceptance criteria + +- [ ] On join, a player is told the game status and their role, class, subclass, abilities, and relevant cooldowns. +- [ ] An unassigned opted-in player is told that they are eligible and shown the opt-out command. +- [ ] An opted-out player is told when they may opt back in. +- [ ] An unassigned player can opt out through a command. +- [ ] Opting out removes an ordinary class or Follower assignment immediately; the Tyrant and Vigilante must relinquish through a safe role command before opting out. +- [ ] Opted-out players cannot be randomly selected, recruited, or assigned a class. +- [ ] A player cannot opt back in until seven days have elapsed by default. +- [ ] The opt-out duration is configurable, uses unpaused elapsed time, and survives restart. +- [ ] Participation commands are idempotent and clearly report current status and remaining time. + +## Related + +- [Handle inactivity and pending selections](us-010-handle-inactivity-and-selection.md) +- [Persistence model](../concepts/persistence-model.md) diff --git a/design/user-stories/us-012-configure-and-persist-state.md b/design/user-stories/us-012-configure-and-persist-state.md new file mode 100644 index 0000000..08709df --- /dev/null +++ b/design/user-stories/us-012-configure-and-persist-state.md @@ -0,0 +1,27 @@ +--- +type: User Story +title: "US-012: Configure and persist game state" +description: Give operators validated configuration and durable defensive storage for all Tyrant behavior. +status: backlog +--- + +# US-012: Configure and persist game state + +As a **server operator**, I want configurable and durable game behavior so that the plugin remains predictable across restarts and balance changes. + +## Acceptance criteria + +- [ ] Configuration covers ranges, durations, cooldowns, inactivity periods, candidate windows, retry intervals, effect levels and caps, mob restrictions, item materials and names, messages, and timer behavior. +- [ ] Defaults match the approved user stories, including a 50-block Tyrant range and Follower range, seven-day opt-out, 48-hour inactivity, and 24-hour candidate windows. +- [ ] Invalid required configuration prevents partial plugin initialization and produces a clear server log message. +- [ ] UUID-keyed state stores lifecycle, current and pending roles, assignments, login history, participation, reign progression, purchases, choices, cooldowns, paused time, item delivery, and captured mobs. +- [ ] Cooldowns and deadlines use UTC instants and exclude administratively paused time. +- [ ] State is saved using atomic replacement where supported so failed writes do not replace valid state with partial data. +- [ ] Corrupt, unknown, or invalid records cannot silently grant progression, roles, powers, items, or duplicated mobs. +- [ ] Unknown forward-compatible configuration and state fields are preserved where practical. +- [ ] Plugin disable removes transient effects and presentation safely while preserving durable state. + +## Related + +- [Persistence model](../concepts/persistence-model.md) +- [Build, test, and release the plugin](us-013-build-test-and-release.md) diff --git a/design/user-stories/us-013-build-test-and-release.md b/design/user-stories/us-013-build-test-and-release.md new file mode 100644 index 0000000..1cd87ba --- /dev/null +++ b/design/user-stories/us-013-build-test-and-release.md @@ -0,0 +1,26 @@ +--- +type: User Story +title: "US-013: Build, test, and release the plugin" +description: Give maintainers repeatable builds, automated verification, and versioned Gitea releases. +status: backlog +--- + +# US-013: Build, test, and release the plugin + +As a **plugin maintainer**, I want automated builds and releases modeled on Spigot Base so that tested, correctly versioned artifacts can be distributed consistently. + +## Acceptance criteria + +- [ ] The Gradle Kotlin DSL project compiles against Spigot API `26.2-R0.1-SNAPSHOT` using a Java 17 toolchain. +- [ ] Compiler lint warnings fail the build. +- [ ] Automated JUnit 5 and Mockito tests run as part of the Gradle check lifecycle. +- [ ] Pushes and pull requests build and test the plugin in Gitea Actions. +- [ ] Pull requests validate conventional commit messages. +- [ ] CI stores a `spigot-tyrant` development JAR as a workflow artifact. +- [ ] Main-branch conventional commits drive semantic versioning. +- [ ] A successful release builds a versioned JAR and attaches it to the corresponding Gitea release. +- [ ] Build files, Gradle wrapper, workflows, and release behavior follow `../spigot-base/` where applicable while using Spigot Tyrant names and identifiers. + +## Related + +- [Configure and persist game state](us-012-configure-and-persist-state.md) diff --git a/design/user-stories/us-014-use-class-ability-items.md b/design/user-stories/us-014-use-class-ability-items.md new file mode 100644 index 0000000..9088716 --- /dev/null +++ b/design/user-stories/us-014-use-class-ability-items.md @@ -0,0 +1,30 @@ +--- +type: User Story +title: "US-014: Use class ability items" +description: Give class holders named bound items that activate abilities without enabling transfer or cooldown bypasses. +status: backlog +--- + +# US-014: Use class ability items + +As a **class holder**, I want a recognizable inventory item for my ability so that activation is fast and understandable during play. + +## Acceptance criteria + +- [ ] Each item-triggered class ability uses a uniquely named standard Minecraft item with hidden persistent ownership and ability metadata. +- [ ] Right-clicking or swinging the appropriate item activates the ability without also performing an unsafe vanilla action. +- [ ] Another player cannot activate, retain, craft with, place, store, frame, dispense, or otherwise transfer a bound ability item. +- [ ] A cooldown ability item disappears only after successful activation and is restored when the cooldown finishes. +- [ ] The Tamer's named fishing rod has no cooldown and remains available after successful capture or placement. +- [ ] A dropped class ability item vanishes immediately; a dropped captured-mob item instead attempts to spawn its mob safely. +- [ ] `/tyrant item` restores currently available missing class items but cannot bypass cooldowns or create duplicates. +- [ ] Missing ready items are restored on login and cooldown completion when inventory space is available. +- [ ] When delivery fails because the inventory is full, no item is dropped and the player is told both why and how to use `/tyrant item` after making room. +- [ ] Bound class items are removed when a player loses the class or the Tyrant's reign ends. +- [ ] Death, inventory movement, server restart, repeated commands, and concurrent events cannot duplicate a bound item or its captured mob. + +## Related + +- [Assign unlocked classes](us-004-assign-unlocked-classes.md) +- [Capture and place mobs as a Tamer](us-007-capture-and-place-mobs.md) +- [Persistence model](../concepts/persistence-model.md)