Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c2d0d2b
Add opt-in automation, usage charges and durable perk lifecycle
BenCodez Oct 10, 2026
07d44dc
Resample precision state on enable reload and reconnect
BenCodez Oct 10, 2026
c58888c
Retain unavailable shutdown perks and restore unexpired time
BenCodez Oct 10, 2026
b769075
Stage perk admission before gameplay hooks
BenCodez Oct 10, 2026
cf1ebc8
Restore persisted perks without replaying activation rewards
BenCodez Oct 10, 2026
13e4d21
Fence direct activation before credit debit and retire old reload cal…
BenCodez Oct 10, 2026
6d097a0
Fence limited direct starts and preserve parallel personal banks
BenCodez Oct 10, 2026
37c912b
Register feature command argument matchers
BenCodez Oct 10, 2026
f191f33
Persist and detach perks before native storage shutdown
BenCodez Oct 10, 2026
9e82160
Document the current Folia loader restriction
BenCodez Oct 10, 2026
c022cf7
Confirm bank cooldown admission and report completed reload outcomes
BenCodez Oct 10, 2026
f334af0
Cover custom offhand refills and competing harvest replacements
BenCodez Oct 11, 2026
0273ec0
Use current activation policy in reload diagnostics
BenCodez Oct 11, 2026
15c87bf
Confirm ordered native shutdown publication and explicit mutation intent
BenCodez Oct 13, 2026
0e98fcc
Initialize inherited lifecycle synchronization in shutdown test fixtures
BenCodez Oct 14, 2026
75fffaa
Move MCPerks regression tests into the dedicated test namespace
BenCodez Oct 19, 2026
1ac7d52
Verify registered usage-charge commands wait for durable acknowledgement
BenCodez Oct 19, 2026
dcedc3c
Checkpoint bank eligibility and verify native overflow integration
BenCodez Oct 19, 2026
5ad5091
Preserve owner task retirement with the upgraded scheduler
BenCodez Oct 22, 2026
5934bf3
Add harvest seed and maturity admission regressions
BenCodez Oct 23, 2026
24ff4a6
Cover registered queue command ownership and durable replies
BenCodez Oct 23, 2026
c071751
Cover registered diagnostic command boundaries
BenCodez Oct 23, 2026
4ee7412
Cover registered banked-time command boundaries
BenCodez Oct 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Maintainer and AI-agent guide

MCPerks is a Bukkit/Paper/Folia plugin built on AdvancedCore. It grants time-limited perks and effects at player, server, permission, Towny, or Factions scope and optionally integrates with VotingPlugin, Vault, RoseStacker, mcMMO, PlaceholderAPI, and other plugins.
MCPerks is a Bukkit/Paper plugin built on AdvancedCore. It grants time-limited perks and effects at player, server, permission, Towny, or Factions scope and optionally integrates with VotingPlugin, Vault, RoseStacker, mcMMO, PlaceholderAPI, and other plugins. The current descriptor does not declare Folia support, and Folia refuses to load it. Conditional Folia scheduler paths are not a platform-support guarantee; do not add the descriptor flag without auditing and validating the complete plugin lifecycle and integrations.

## Build and verification

Expand Down Expand Up @@ -35,6 +35,29 @@ The supported scope values are `ALL`, `PLAYER`, `TOWNY`, `FACTIONS`, and `PERMIS
7. Reward or command integration must preserve idempotency where the caller can retry and must not grant before required state is durably recorded.
8. Keep configuration keys, perk files, placeholders, permissions, aliases, and serialized user/server data backward compatible unless a migration is explicit and tested.

9. Optional interaction effects use immutable options captured at load. Charge budgets belong to a player UUID and one
fixed effect, require durable asynchronous admission before gameplay, and remain spent after an uncertain effect or
crash. Never create per-reservation SQL keys or fetch perk files from gameplay listeners. Shared charge ownership is
rejected; legacy unlimited shared perks remain supported.
10. Queue entries reserve existing entitlement without decrementing while waiting. Persist stable IDs and start fences
before consumption; limited queued activations require shared-runtime atomic user ownership and otherwise remain
waiting. Use confirmed asynchronous storage completion, consume one selected activation, and never replay
an uncertain start. Self cancellation checks ownership; pause and reordering are durable. Display unknown ETA when
eligibility or permanent/banked state prevents a reliable estimate.
11. Banked personal time is an explicit optional mode, separate from legacy absolute expirations. Lifecycle checkpoints
consume online eligible elapsed time, including final disconnect/world/pause/reload/shutdown intervals; queries remain pure. Unsupported one-shot, periodic and persistent-effect
activation paths are rejected. Resuming a bank never grants entitlement or replays reward/command hooks. Retired
player or reload timer callbacks cannot remove effects from a newer session.
Nonpositive legacy reactivation timers remain disabled and supported. A bank replacement starts its elapsed/debit
ownership boundary only after durable publication; prior debit reservations cannot consume the replacement balance.
Grant publication must retain concurrent pause/eligibility transitions. Every acknowledged queue/bank state file
must remain within the same 3,000,000 serialized-byte recovery bound; capacity rejection preserves usable prior state and must precede irreversible activation consumption.
A clock first attached during an additive publication can debit only the pre-grant balance for that wait.
12. Retire gameplay admissions and detach owner-thread effects before AdvancedCore storage retirement. Persist legacy
restart records before clearing native expirations. Keep the ordered feature worker open through both that
completion stage and AdvancedCore final permission-data cleanup; deferred shutdown may return before storage
preparation settles. Cleanup failures remain observable and must not prevent other perks from being persisted.

## Drop-in upgrade and compatibility contract

Treat compatibility as a release invariant for every new feature, refactor, fix, persistence change, configuration change, integration change, and dependency change. Unless the task explicitly says otherwise, an MCPerks upgrade must remain a **drop-in JAR replacement**: administrators replace the JAR and existing perks, timers, user/server state, configuration, commands, permissions, placeholders, and integrations continue working without manual migration steps.
Expand All @@ -53,10 +76,18 @@ For compatibility-sensitive changes, add regression coverage for established con

## Dependencies and packaging

Startup defers native LastUpdated/version saves until strict ServerData reconciliation after predecessor drain. TimedPermissions become native-owned only after the actual AdvancedCore PermissionHandler restores the reconciled nodes through owner-scheduled native APIs; a generic empty YAML cache cannot clear recovered disk permissions. Compare the early native-handler baseline with current per-node state so successor revocations, renewals and new grants remain authoritative. Read only the bundled synchronized timedPermissionSnapshot/offlinePermissionSnapshot methods with exact schema checks; unsupported contracts fail initialization closed. Preserve pending offline nodes through the native final save without resurrecting revoked nodes. Successful bank replacement advances a FeatureState-owned debit epoch even for disconnected/reloaded/retired clocks; retained ownership is one scalar per bounded bank, never a retained list of session clocks.

Ordered ServerData snapshots include a fixed leading format comment and stay within 4,000,000 encoded bytes including that comment. Unmarked native legacy YAML may migrate once after predecessor drain, with strict parsing and no symlink/unreadable-file bypass; consumed permissions and advisory history can yield the bounded format. An indispensable larger payload cannot migrate losslessly into this bounded file. Still-active oversized permission rows are conservatively checked before publishing a cleared snapshot, the original file stays intact, and initialization/final-save failures remain observable. Offline queued permission nodes have no native public snapshot API; the guarded bundled synchronized snapshot adapter preserves their pending native ownership. Future rows remain indispensable while that owner exists. Resolve excess active permissions on the prior version or reduce other indispensable payload before upgrading; do not add a supplemental persistence engine or silently discard those fields.

AdvancedCore is shaded and relocated. Before changing its version, shading, or API usage, inspect the actual dependency contract and downstream artifact. Avoid unpinned `LATEST` dependencies in reproducible release paths. Check that provided optional dependencies are not accidentally bundled and relocated libraries do not leak original packages or service metadata.

## Change and PR workflow

Keep changes focused. Before any commit, push, PR update, review reply, or other remote change, run focused checks, the full Maven package build, fresh-artifact inspection, and `git diff --check`; then inspect the complete base-to-HEAD diff. Before committing local work, also inspect the staged changes and every relevant intended unstaged or untracked change as one effective final patch.

For substantive work, obtain a fresh source-read-only review. The implementation agent verifies and fixes accepted findings, reruns validation, and obtains a new review of the updated snapshot. Do not reuse an old clean verdict after changes, and do not merge without explicit authorization.

Queue-enabled direct activation retains the queue start fence through asynchronous bank publication, the initial player-owner attachment attempt, and cooldown confirmation. Queued bank starts retain their existing fence through the same attachment handoff. Resumed or reconnected banks wait behind unrelated active perks without consuming waiting time; queue-disabled personal banks retain parallel behavior. The first attachment attempt may finish ineligible or retired while preserving the published bank for a later eligible resume; it does not mint time or replay activation hooks.

Limited direct starts persist an existing-format `STARTING` entry before any debit and never transition to queue `WAITING`. Validate and confirm current ServerData and caller storage before the atomic debit; publish new expiration/cooldown fields only after successful consumption so a rejected start cannot restore as a free permanent grant. Definite pre-debit failure or an authoritative false debit removes that entry with unchanged credit; debit ambiguity and later failure retain uncertainty without replay/refund. Hold owner/perk/lifecycle admission through all accepted callbacks and completion publication. Queue-disabled personal banks remain parallel across owners unless the same perk has a server-wide cooldown; bank attachment must never add the purchased balance again.
22 changes: 21 additions & 1 deletion MCPerks/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -260,9 +260,18 @@
</repositories>
<dependencies>
<dependency>
<groupId>org.mockito</groupId><artifactId>mockito-core</artifactId><version>5.14.2</version><scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.bencodez</groupId>
<artifactId>advancedcore</artifactId>
<version>LATEST</version>
<version>3.8.2-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
Expand Down Expand Up @@ -320,4 +329,15 @@
<scope>provided</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>tests</id>
<activation><activeByDefault>true</activeByDefault></activation>
<build><plugins><plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.2.5</version>
</plugin></plugins></build>
</profile>
</profiles>
</project>
Loading