137 lines
7.6 KiB
Markdown
137 lines
7.6 KiB
Markdown
# Score Keeper - Plugin Integration and Event Wiring
|
|
|
|
New Score Keeper contributors should start with
|
|
[CONTRIBUTING.md](../CONTRIBUTING.md), which covers architecture, setup, and validation.
|
|
This is an optional detailed reference for runtime wiring and companion-plugin
|
|
authors, not a second onboarding guide. [domain-score-tracking.md](domain-score-tracking.md)
|
|
describes state and [README.md](../README.md) gives full command syntax.
|
|
|
|
## Paper lifecycle
|
|
|
|
The entry point is
|
|
[ScoreKeeperPlugin](../src/main/java/com/majinnaibu/minecraft/plugins/scorekeeper/ScoreKeeperPlugin.java),
|
|
declared in [plugin.yml](../src/main/resources/plugin.yml) under the plugin ID
|
|
`ScoreKeeper`. Compilation targets Paper `26.2.build.129-stable` on Java 25;
|
|
supported server versions are Paper 26.2 and 26.3.
|
|
|
|
| Trigger | Handler / effect |
|
|
| --- | --- |
|
|
| Plugin enable | Register eight executors, initialize `points`, load scores/archives, check existing runs, schedule synchronous checks every 20 ticks |
|
|
| Scheduled check | `checkHighScoreRuns`: finish expired duration runs or runs whose target is reached |
|
|
| Plugin disable | Serialize bucket definitions, scores, assignments, active runs/snapshots, and archives to two YAML files |
|
|
| Minecraft join/quit/death/kill | No built-in listeners or automatic score awards |
|
|
| Companion-plugin API call | Perform requested score/bucket/archive/run operation |
|
|
|
|
There are no `Listener` implementations, `@EventHandler` methods, custom scoring
|
|
events, or event registrations. The scheduler manages runs, not gameplay scoring.
|
|
Expired saved runs finish during enable; `until-disabled` runs persist and resume.
|
|
|
|
## Command wiring
|
|
|
|
Each manifest command is explicitly wired in `onEnable` using `getCommand` and
|
|
`setExecutor`. A missing declaration fails startup via `Objects.requireNonNull`.
|
|
|
|
Handlers are in [commands/](../src/main/java/com/majinnaibu/minecraft/plugins/scorekeeper/commands/).
|
|
|
|
| Command | Executor | Delegation / effect | Permission |
|
|
| --- | --- | --- | --- |
|
|
| `score-get` | `ScoreGetCommand` | `getScore`, active bucket, lazy entry creation | None |
|
|
| `score-add` | `ScoreAddCommand` | `addScore`, signed integer addition | None |
|
|
| `score-subtract` | `ScoreSubtractCommand` | `subtractScore`, signed integer subtraction | None |
|
|
| `score-reset` | `ScoreResetCommand` | `resetScore`, active bucket initial value | None |
|
|
| `score-archive` | `ScoreArchiveCommand` | `archivePlayerScore`, `archiveBucketScores`, or `archiveAllScores` | `scorekeeper.admin` |
|
|
| `score-archive-list` | `ScoreArchiveListCommand` | `getScoreArchives` or `getScoreArchive` | None |
|
|
| `score-bucket` | `ScoreBucketCommand` | View/select own bucket, create bucket, switch another/all players | Admin for create/other/all; none for self |
|
|
| `score-run` | `ScoreRunCommand` | Start target/timed/manual run, or stop it | `scorekeeper.admin` |
|
|
|
|
`scorekeeper.admin` defaults to operators in the manifest. Guards are implemented
|
|
inside selected executors, not per-command manifest permission fields. Public API
|
|
calls do not enforce sender permissions; the caller must enforce its own policy.
|
|
|
|
Named player targets use Paper's `getPlayerExact` and must be online. Players
|
|
may omit the optional name to target themselves; non-player senders have no
|
|
self context. Console/RCON can use archive `all`/`bucket` forms without a player.
|
|
Bucket IDs are case-sensitive even though command keywords such as `all` are not.
|
|
|
|
Parse/validation failures are returned as Adventure usage/error messages.
|
|
Handlers consume commands by returning `true`. Score mutation commands rely on
|
|
bucket/run reporting instead of unconditional success messages; the default
|
|
`none` policy can make a successful mutation silent.
|
|
|
|
## Companion-plugin integration
|
|
|
|
Score Keeper declares no plugin dependencies of its own. A companion that requires
|
|
it should compile against the matching jar as a provided/compile-only dependency,
|
|
and declare `depend: [ScoreKeeper]` in its own Bukkit-style manifest so it loads
|
|
after Score Keeper. For optional integration, use `softdepend` and handle absence
|
|
or disabled state explicitly.
|
|
|
|
There is no ServicesManager registration or standalone API module. Obtain the
|
|
enabled plugin by ID and check its type, for example during the companion's enable:
|
|
|
|
```java
|
|
Plugin candidate = getServer().getPluginManager().getPlugin("ScoreKeeper");
|
|
if (!(candidate instanceof ScoreKeeperPlugin scoreKeeper) || !candidate.isEnabled()) {
|
|
getLogger().severe("Score Keeper is required but is not enabled.");
|
|
getServer().getPluginManager().disablePlugin(this);
|
|
return;
|
|
}
|
|
```
|
|
|
|
Imports for this example are `org.bukkit.plugin.Plugin` and
|
|
`com.majinnaibu.minecraft.plugins.scorekeeper.ScoreKeeperPlugin`. Keep the
|
|
reference for your integration lifecycle, not as a global singleton.
|
|
Do not shade a second copy of Score Keeper into the companion jar.
|
|
|
|
### Public operations
|
|
|
|
| Area | Methods |
|
|
| --- | --- |
|
|
| Bucket definition | `createBucket(id, singular, plural, initialValue[, ScoreReporting])`, `getBucket(id)`, `getBuckets()` |
|
|
| Active selection | `getPlayerBucket(Player)`, `switchPlayerBucket(Player, id)`, `switchAllPlayers(id)` |
|
|
| Score CRUD | `getScore(Player[, id])`, `setScore(Player[, id], score)`, `addScore(Player[, id], amount)`, `subtractScore(Player[, id], amount)`, `resetScore(Player[, id])` |
|
|
| Archives | `archivePlayerScore(Player)`, `archiveBucketScores(id)`, `archiveAllScores()`, `getScoreArchives()`, `getScoreArchive(archiveId)` |
|
|
| Compatibility wrapper | `archiveScore(Player)` delegates to player archive creation but discards the returned ID |
|
|
| Runs | `startTargetScoreRun(id, topN, resetScores, targetScore)`, `startTimedScoreRun(id, topN, resetScores, Duration)`, `startUntilDisabledScoreRun(id, topN, resetScores)`, `stopHighScoreRun(id)`, `hasActiveHighScoreRun(id)` |
|
|
| Messaging/logging | `sendMessage(CommandSender, Component)`, `logInfo`, `logWarning`, `logError` |
|
|
|
|
The bracket notation above describes overloads, not literal Java syntax.
|
|
`getBucket` and `getScoreArchive` return null when unknown; mutating/score methods
|
|
validate bucket existence and throw `IllegalArgumentException` for invalid
|
|
operations. Do not swallow errors or report success after a failure.
|
|
Bucket maps and archive snapshots exposed by getters are immutable copies/views.
|
|
|
|
Example explicit-bucket award, with imports for `ScoreReporting` and `Player`:
|
|
|
|
```java
|
|
if (scoreKeeper.getBucket("event") == null) {
|
|
scoreKeeper.createBucket("event", "point", "points", 0, ScoreReporting.PLAYER);
|
|
}
|
|
scoreKeeper.addScore(player, "event", 10);
|
|
```
|
|
|
|
Only create a shared bucket if its existing definition meets your integration's
|
|
requirements; duplicate creation throws. Explicit-bucket scoring does not switch
|
|
the player's active bucket.
|
|
|
|
### Threading and ownership
|
|
|
|
All calls touching state, players, or reporting must execute on Paper's main
|
|
server thread. The plugin's `LinkedHashMap` state and read-modify-write operations
|
|
are not synchronized. Marshal asynchronous event/work results to a synchronous
|
|
Paper task before calling this API. Score Keeper does not provide Folia/region
|
|
scheduler support.
|
|
|
|
Do not mutate private maps or write the YAML files from another plugin.
|
|
Use the API so reporting, validation, target completion, and snapshots remain
|
|
consistent. API calls change in-memory state; durability is deferred until
|
|
Score Keeper disables successfully.
|
|
|
|
## Verification
|
|
|
|
There is currently no automated plugin harness or real-server test task.
|
|
Validate load ordering, command dispatch, messages, run scheduler behavior, and
|
|
clean-restart persistence on disposable Paper servers using
|
|
[human-tests.md](human-tests.md). Do not assume a successful compilation verifies
|
|
companion load order or runtime API compatibility.
|