Spigot Ignis
Server-wide earned shadow progression for Social Minecraft. Foundation work only; no player abilities or commands are implemented yet. Do not deploy this foundation as a gameplay release.
Build
Requires Java 17+ to launch Gradle; the wrapper resolves a Java 25 toolchain for compilation/testing. Toolchain downloads require network access when no compatible cache is available.
./gradlew clean check jar
./gradlew clean jar -PreleaseVersion=0.1.0
Targets Purpur 26.2.build.2618-stable. The API is not bundled. Source builds do not require the private wiki.
Knowledge and delivery
The canonical project and stories live in the shared private SoMC wiki. There is no repository-local knowledge bundle.
CI/release workflows are scaffolded but not remotely verified. Release publication requires the repository Actions secret RELEASE_TOKEN, securely provisioned separately before the first main push. The release workflow uses Git askpass and curl stdin for authentication rather than embedding a release credential in URLs or process arguments. Never enable tracing. GitOps and production release need separate approvals.
Foundation interfaces and state
StateService.open(repository)loads on a dedicated persistence worker and completes only when ready. Failed/corrupt loads do not substitute empty state. No caller may use gameplay state before successful initialization.snapshot()provides an immutable, last-successfully-saved view.update(pureChange)serializes mutations, saves first, then publishes/acknowledges. Mutation functions run off-thread and must not access Bukkit or perform gameplay side effects. Marshal downstream gameplay work back to the server thread.configure(invisibilityMillis, pearls, darknessMillis)validates positive thresholds and atomically saves limits with resulting unlocks. Defaults are 43,200,000 ms (12 h), 313 pearls, and 21,600,000 ms (6 h). Lower limits unlock satisfied tracks during evaluation; higher limits do not revoke unlocks. VOID is objective-based and is excluded from numeric threshold grants.- UUID state includes per-track progress, unlock/activation flags, invalidation generations, and pending reward identifiers. This is storage infrastructure, not implemented reward delivery, item revocation, or challenge tracking. Issuance/transfer provenance remains a later design decision.
close()rejects new mutations and lets already queued writes drain without blocking the caller. Hard process termination can lose unacknowledged updates. The worker does not force Bukkit/world access from its thread.
The foundation bootstrap reads only plugins/SpigotIgnis/state.bin; it does not read or migrate Stealth data. No commands, crafting, reset handlers, event counters, restart challenge resets, or rendering hooks are registered. Runtime settings currently have a Java service API only, not a config-file editor or admin command.
Recovery and format
state.bin is a versioned binary data format (not Java object serialization): magic/version, positive thresholds, UUID player maps, named track states, and UUID pending rewards. Invalid versions, counts, duplicate keys, malformed flags, negative counters, truncated input, and trailing bytes are rejected. Record counts are bounded at 100,000 players and 100,000 pending rewards per player.
Writes use a same-directory temporary file, flush it to disk, and require atomic replacement. Unsupported atomic moves or write failures retain the prior active snapshot and fail the mutation; there is no non-atomic fallback. Abandoned temporary files are ignored, never auto-promoted. This does not guarantee survival of arbitrary storage hardware or power failures.
If loading fails, preserve the original file for investigation. Under an approved maintenance plan, stop the server, back up current data, restore a verified matching-version backup, and restart. Do not delete state to recover: that loses earned progress and invalidation records. Do not hand-edit the binary file or import another plugin's state. Restoring an old backup can also restore older revocation/progress state; review that consequence before doing it.
Verification limits
JUnit tests exercise real temporary-file persistence, serialized writes, fault injection, threshold policies, metadata, and static workflow guardrails. YAML/shell parsing is not remote CI verification. No Purpur startup/shutdown, live gameplay, client presentation, command registration, or actual release publishing has been tested yet.