Compare commits

...
Author SHA1 Message Date
Ben 9b3f4c939c Correct NeoForge support metadata and documentation 2026-10-16 14:08:03 -06:00
2 changed files with 8 additions and 8 deletions

No files matched your search

@@ -6,7 +6,7 @@ license="CC BY 3.0"
modId="votingplugin"
version="${project.version}"
displayName="VotingPlugin"
description="VotingPlugin NeoForge bootstrap (vote processing is not available yet)."
description="Experimental VotingPlugin NeoForge support for authenticated proxy SOCKETS votes and limited reward replay."
[[dependencies.votingplugin]]
modId="neoforge"
+7 -7
View File
@@ -1,12 +1,12 @@
# NeoForge bootstrap status
# NeoForge support status
The single `VotingPlugin.jar` contains an experimental NeoForge 21.1 entry point for Minecraft 1.21.1. Native vote ingress remains disabled. Bukkit and proxy behavior remains on its existing paths.
The single `VotingPlugin.jar` contains experimental NeoForge 21.1 support for Minecraft 1.21.1. It can receive authenticated `SOCKETS` votes from BungeeCord and Velocity and replay the restricted reward subset described below. Native Votifier ingress is not supported. Bukkit and proxy behavior remains on its existing paths.
On server start, the entry point creates `config/votingplugin/`, installs the packaged `Config.yml`, `VoteSites.yml`, and `SpecialRewards.yml` only when missing, reads them, and opens the existing AdvancedCore SQLite user backend in `VotingPlugin.db`. The bootstrap currently accepts `DataStorage: SQLITE` only. Its separate `VotingPlugin_NeoForgeUsers` table stores the player name, all-time/monthly/daily/weekly totals, points, and per-site last-vote timestamps needed by the shared accounting step. Existing UUID-only bootstrap tables are extended in place. The accounting adapter is a storage foundation and is not wired to live vote ingress. The runtime closes the backend and clears queued tasks and online player identities on server stop.
On server start, the entry point creates `config/votingplugin/`, installs the packaged `Config.yml`, `VoteSites.yml`, and `SpecialRewards.yml` only when missing, reads them, and opens the existing AdvancedCore SQLite user backend in `VotingPlugin.db`. The bootstrap currently accepts `DataStorage: SQLITE` only. Its separate `VotingPlugin_NeoForgeUsers` table stores the player name, all-time/monthly/daily/weekly totals, points, and per-site last-vote timestamps needed by the shared accounting step. Existing UUID-only bootstrap tables are extended in place. Incoming proxy votes enter the durable inbox; the bounded replay worker commits accounting with supported reward completion. The runtime closes the backend and clears queued tasks and online player identities on server stop.
The NeoForge bridge tracks login/logout identity and runs submitted bootstrap tasks on server ticks. Player identity access uses reflection because NeoForge's published universal Maven JAR does not include Minecraft classes on Maven's compile path; these method names were checked against the installed 1.21.1 server JAR.
An internal synthetic vote boundary now supports identity and enabled-site resolution, Bukkit-compatible vote-delay decisions, and the existing shared totals/points policy in one atomic SQLite transaction. `ACCOUNTING_ONLY` is deliberately an internal test/migration scope and returns `ACCOUNTED`, rather than claiming that a production vote completed. `COMPLETE` votes do not change timestamps, totals, or points. They are retained in an ordered SQLite inbox under their stable vote ID until NeoForge implements rewards, offline queues, vote party, broadcasts, streaks, milestones, cooldown actions, post-vote events, and placeholder updates. Repeated submission of the same vote ID is idempotent even after player or site state changes. The inbox admits at most 64 votes per player and 4,096 votes across the runtime. A full inbox returns an explicit capacity result that a future ingress must treat as non-success.
`ACCOUNTING_ONLY` is an internal test/migration scope for identity and enabled-site resolution, Bukkit-compatible vote-delay decisions, and the shared totals/points policy in one atomic SQLite transaction. It returns `ACCOUNTED`, rather than claiming that a production vote completed. Production `COMPLETE` votes first enter an ordered SQLite inbox under their stable vote IDs without immediately changing timestamps, totals, or points. The bounded replay worker later completes supported votes; unsupported reward or post-vote semantics keep them pending. Repeated submission of the same vote ID is idempotent even after player or site state changes. The inbox admits at most 64 votes per player and 4,096 votes across the runtime. A full inbox returns an explicit capacity result that the proxy must treat as non-success.
Native Votifier ingress remains disabled. VotifierPlus's hardened packet handling is currently packaged with its Bukkit, BungeeCord, and Velocity plugin runtime rather than as a platform-neutral API that this single VotingPlugin artifact can reuse. Depending on that full plugin would pull unrelated platform code into VotingPlugin, while copying its security-sensitive protocol implementation would create a second implementation.
@@ -64,13 +64,13 @@ Current transport support is:
Only the reward subset described below can complete. Votes requiring unsupported reward or post-vote semantics remain durable and observable instead of being acknowledged as fully processed and lost.
Deferred votes can now be claimed in memory and completed through one SQLite transaction that writes a completion receipt and removes the pending payload. An abandoned claim leaves the durable payload pending, while a committed transaction leaves no pending-without-receipt window. Completion receipts are bounded to 4,096 per player and 262,144 across the runtime. They are not evicted by age because no native ingress acknowledgement can yet prove that a sender has stopped retrying. If either receipt limit is full, completion stops and keeps the original pending payload. A later ingress handshake may add safe receipt release with a bounded post-release tombstone, following the existing proxy delivery pattern. A bounded replay worker now processes at most 16 retained votes per scan. It supports one existing inline `Messages.Player` or `Commands` action per vote. Player messages and console commands run on the NeoForge server tick lane; SQLite scans and completion writes remain on the replay worker. The worker validates the entire reward tree before running any action. A vote stays pending with an observable blocked or waiting result if it requires multiple or unsupported reward actions, `AnySiteRewards`, an offline player message, vote broadcasts, vote party, streaks, milestones, monthly vote limiting, cooldown events, `CloseInventoryOnVote`, or `WaitUntilVoteDelay` processing. An ambiguous external action or completion-write result is durably quarantined and remains fenced across restart for operator reconciliation. Legacy retained rows without an accepted accounting snapshot also remain blocked instead of being recalculated with newer configuration. The packaged defaults enable some unsupported features, so administrators must explicitly disable them before retained votes can complete. Configuration changes currently take effect after a server restart.
Deferred votes can now be claimed in memory and completed through one SQLite transaction that writes a completion receipt and removes the pending payload. An abandoned claim leaves the durable payload pending, while a committed transaction leaves no pending-without-receipt window. Completion receipts are bounded to 4,096 per player and 262,144 across the runtime. Unreleased completion receipts do not expire by age. If either receipt limit is full, completion stops and keeps the original pending payload. The existing proxy receipt-release handshake permits bounded released tombstones to expire as described below. A bounded replay worker now processes at most 16 retained votes per scan. It supports one existing inline `Messages.Player` or `Commands` action per vote. Player messages and console commands run on the NeoForge server tick lane; SQLite scans and completion writes remain on the replay worker. The worker validates the entire reward tree before running any action. A vote stays pending with an observable blocked or waiting result if it requires multiple or unsupported reward actions, `AnySiteRewards`, an offline player message, vote broadcasts, vote party, streaks, milestones, monthly vote limiting, cooldown events, `CloseInventoryOnVote`, or `WaitUntilVoteDelay` processing. An ambiguous external action or completion-write result is durably quarantined and remains fenced across restart for operator reconciliation. Legacy retained rows without an accepted accounting snapshot also remain blocked instead of being recalculated with newer configuration. The packaged defaults enable some unsupported features, so administrators must explicitly disable them before retained votes can complete. Configuration changes currently take effect after a server restart.
Before a supported external action is dispatched, replay durably fences the pending occurrence. After the action succeeds, accounting, the completion receipt, and pending removal commit in one SQLite transaction. A completed vote ID remains fenced across restart and cannot rerun accounting. If the JVM or completion write fails after the pre-dispatch fence, automatic replay stays stopped for operator reconciliation, so it cannot blindly repeat a command or message. A crash between writing that fence and executing the action is indistinguishable from a crash immediately after execution and can therefore leave an action omitted unless an operator retries it; a manual retry after an uncertain outcome can instead duplicate it. The current reward APIs cannot make a Minecraft command and SQLite commit atomic, so this version does not claim exactly-once external side effects.
`SharedVoteProcessor.Operations` was reviewed operation by operation. NeoForge can currently implement its configuration, identity, site, delay, timestamp, and accounting operations. Logging and proxy-only identity fields have no processing effect at this internal non-proxy boundary. Reward delivery, offline queuing, vote party, broadcast, inventory/effects, streak, milestone, cooldown, post-event, and placeholder operations require future platform services. The adapter therefore reuses `SharedVoteIdentity`, `SharedVoteInput`, `SharedVotePolicy`, and `SharedVoteAccounting` without implementing the broad Bukkit production interface with false no-ops.
The NeoForge adapter reuses `SharedVoteIdentity`, `SharedVoteInput`, `SharedVotePolicy`, and `SharedVoteAccounting` without implementing the broad Bukkit production interface with false no-ops. Its native action adapter supports only the player-message or console-command subset above. Full Bukkit reward trees, offline-queue parity, vote party, broadcasts, inventory/effects, streaks, milestones, cooldown actions, post-vote events, and placeholder updates still require additional platform services.
Validation for this step covers unit startup/shutdown, isolated classloader startup/shutdown from the packaged JAR, and a NeoForge 21.1.211 dedicated server smoke run. The server reached its ready state, initialized the bootstrap, and exited cleanly after `stop`. This does not verify player joins, vote receipt, or rewards.
Existing headless and packaged-JAR tests exercise bootstrap startup/shutdown, isolated class loading, and the restricted proxy/replay paths. A historical NeoForge 21.1.211 dedicated-server smoke test reached its ready state and exited cleanly after `stop`; it covered startup and stop only. It does not establish live proxy receipt, player reward execution, or restart recovery for a current release candidate.
### Proxy receipt release before deferred completion