fix(commands): migrate GreetCommand to BaseCommandExecutor for UltiTools 6.3.0 (#4) - #5
Conversation
…pshots - Bump the UltiTools-API dependency from the released 6.2.2 to the 6.3.0-SNAPSHOT lineage (phase 9, MOD-01/MOD-02), ahead of the 6.3.0 release. - Add the central-snapshots repository entry; without it the snapshot coordinate cannot be resolved at all. - Record, in the pom near the build section, that this repository is deliberately out of scope for the module coverage gate: it has no CI workflow to run one in, and it demonstrates the External Plugin API rather than shipping as a UltiToolsPlugin module. - Module version and line endings unchanged. (cherry picked from commit 1cbbd55)
) - Replace spigot-api 1.20.4 and the SpigotMC repository with paper-api 1.21.11-R0.1-SNAPSHOT from the PaperMC repository, the same pin and repository the UltiKits modules use. UltiTools-API 6.3.0 is a Paper framework (Adventure types throughout), so Spigot is not a supported build target. - Add JUnit 5.10.0, Mockito 5.5.0, AssertJ 3.24.2 and MockBukkit (org.mockbukkit.mockbukkit:mockbukkit-v1.21:4.101.0) as test dependencies, and maven-surefire-plugin 3.1.2, with the coordinates and versions the modules already declare. - Correct the phase-9 scope comment: it said the repository has no CI workflow, which stops being true in this change set. The coverage gate stays out of scope. - Project version unchanged; line endings preserved (CRLF). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017BD9mGr6EsyRsEv3d2BizL
…I 6.3.0 (#4) GreetCommandTest covers the three things an external plugin's command needs on 6.3.0: - Registration contract read by CommandManager#registerAllExternal: the class is a Bukkit CommandExecutor (BaseCommandExecutor) and carries @cmdexecutor with aliases ultiext/uext, permission ultiext.greet, and manualRegister=false; getMappings() holds all five sub-commands. - Dispatch through BaseCommandExecutor#onCommand on a MockBukkit server (permitted player and console), including <name> parameter binding. - Each mapped method's sent messages and DataOperator calls (insert, update, failed update, getAll, del, uninitialised operator), plus help. RED at this commit: GreetCommand still extends the AbstractCommandExecutor that 6.3.0 deleted, so the main sources do not compile. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017BD9mGr6EsyRsEv3d2BizL
Swap the deprecated AbstractCommandExecutor for the current BaseCommandExecutor (import + extends only). All @CmdTarget, @cmdexecutor, @CmdMapping and @CmdParam annotations are preserved verbatim, and the existing handleHelp(CommandSender) override is kept unchanged, satisfying BaseCommandExecutor's protected abstract contract with no stub. Compiles against the existing released UltiTools-API 6.2.2 pin, no snapshot repository added (D-10 round 1). (cherry picked from commit e128f2f)
…mmand (#4) - Add an English-first class javadoc (Chinese supplement) walking a reader through the path this example exists to teach: UltiToolsAPI.connect -> package scan and @Autowired injection -> CommandManager#registerAllExternal -> BaseCommandExecutor#onCommand (mapping match, @CmdTarget and permission checks, parameter binding, next-tick execution), and why commands extend BaseCommandExecutor now that 6.3.0 removed AbstractCommandExecutor. - FEATURES.md: shift the GreetCommand positive-control line numbers by the 25 javadoc lines (@cmdexecutor 21->46; @CmdMapping 31/37/44/74/93 -> 56/62/69/99/118); replace the claim that no comment names the repository's own annotations - already false on master, where the connect comment in UltiToolsExtExample names @cmdexecutor and @eventlistener - with the measured unanchored counts; say AbstractDataEntity was removed in 6.3.0, not deprecated. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017BD9mGr6EsyRsEv3d2BizL
…cklist (#4) Follow-up to the reused migration commit (cherry-picked from PR #1), which cannot carry these files without rewriting it: - CHANGELOG.md (new, Keep a Changelog 1.1.0, English first): ### Fixed - /ultiext sub-commands register again on UltiTools-API 6.3.0 (symptom as measured in #4: plugin and join listener work, every sub-command gets Bukkit's unknown-command reply); ### Changed - builds on UltiTools-API 6.3.0-SNAPSHOT and paper-api 1.21.11 instead of 6.2.2 and spigot-api 1.20.4. - UAT-CHECKLIST.md: a "Build under test" convention. No row names the removed base class or a 6.2.x API, so no row changes; the twelve rows Phase 10 could not run need only a jar built after this migration, and the convention makes a stale jar a setup error rather than a row failure. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017BD9mGr6EsyRsEv3d2BizL
- .github/workflows/maven-ci.yml copied byte-for-byte from UltiWorlds (same pinned actions/checkout and actions/setup-java SHAs, JDK 21 temurin, `mvn -B verify` on every push and pull request), so this repository's pull requests get a real build-and-test check. The repository had no workflow before this. - No publish or release workflow is added. - The copied job name says "coverage gate"; this repository has no JaCoCo check (phase-9 scope decision in pom.xml), so here the job runs the tests and packages the jar. Kept verbatim so the file stays identical to the modules' copy. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017BD9mGr6EsyRsEv3d2BizL
…tration (#4) Gate-1 review WR-01: GreetCommandTest proved the registration contract by reading annotations, but never ran the code that registers the command. - GreetCommandRegistrationTest repeats the container steps PluginManager#registerExternal performs for UltiToolsAPI.connect (plugin class loader, JavaPlugin type, package scan, refresh), calls the real package-private PluginManager.validateCommandExecutorContracts, then the real CommandManager#registerAllExternal against a real Bukkit SimpleCommandMap. It asserts /ultiext and /uext resolve to one PluginCommand with permission ultiext.greet whose executor is the scanned GreetCommand with GreetService injected, and that unregisterAllExternal removes both. Only UltiTools.getInstance() and Bukkit's static accessors are stubbed. - Behaviour-level RED: in a throwaway copy where GreetCommand does not extend BaseCommandExecutor, registerAllExternal skips it without error and the /ultiext assertion fails (a test failure, not a compile error). - Test sources converted to CRLF to match every src/main/java file (review IN-06); GreetCommandTest's content is unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017BD9mGr6EsyRsEv3d2BizL
…'s no-CI claim (#4) - maven-ci.yml (gate-1 review WR-02): the job copied from the modules was named "Test, coverage gate & package" and its comment described a jacoco:check step. This repository has no JaCoCo plugin and no coverage threshold, so a green check promised a gate that does not exist. The job is now "Test & package (JDK ${{ matrix.java-version }})", rendered as "Test & package (JDK 21)", and the comment says only what `mvn -B verify` runs. Pinned actions, triggers and the command are unchanged; the file is no longer byte-identical to the modules' copy, deliberately. - pull_request_template.md (WR-03): the Issue closure comment said the repository has no workflows and no CI. It now says the only workflow is maven-ci.yml, which builds and tests and closes nothing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017BD9mGr6EsyRsEv3d2BizL
Gate-1 review IN-04: - The coverage-gate comment said "sixteen product modules"; there are fifteen active UltiKits product modules. It also carried internal planning codes, which mean nothing to a reader of this public example; the comment now states the facts in words. - The central-snapshots comment carried planning codes and said the other repositories "serve releases only", which stopped being true when the PaperMC repository started serving the paper-api snapshot; it now says the PaperMC repository does not host UltiTools-API. Comments only; no dependency, repository or version change; CRLF kept. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017BD9mGr6EsyRsEv3d2BizL
…ed records (#4) Gate-1 review WR-04, WR-05 and the same-class sweep: - Build under test (WR-04): the jar records no source commit (manifest and plugin.yml version are identical before and after the migration), so the convention now has the executor compare the installed jar's SHA-256 with the build hand-off's. - data.visitors.neg-empty (WR-05): JoinListener creates a record for every joining player, including the executor, and records survive restarts, so "delete what earlier rows created" left records behind and a correct build failed the row. The empty store is now established and checked from the console, the step runs from the console, and a follow-up visit/visitors pair proves the store is readable, so the empty reply cannot pass on a broken store; the row cleans up after itself. - Sweep, same class (an expectation or precondition that ignores state the session or an earlier dispatch creates): - greet.hello: the join greeting is the identical line, so the row could pass with no command registered at all - exactly #4's broken build. It now requires a new line after the command and no unknown-command reply. - data.visitors: "<n> matches the actual stored count" was not observable; now <n> must equal the lines printed, which must include probe and the executor's own join record. - data.visit, data.delvisitor.neg-not-found, data.persistence, join.on-join: preconditions now check the record state with /ultiext visitors and say how to reach it, instead of assuming no earlier dispatch left a record. - join.on-join.neg-rejoin: says when to read N. - A convention bullet states why, and the permission convention no longer claims only one row uses the console. - Unchanged: greet.hello.neg-console, greet.info, data.delvisitor, data.visit.neg-repeat. Row order check: no precondition cites a later row. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017BD9mGr6EsyRsEv3d2BizL
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
@codex review |
|
Codex Review: Didn't find any major issues. Can't wait for the next one! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
…og (#4) The comment rewritten in 9f8b843 said the PaperMC repository does not host UltiTools-API and that the snapshot could not be resolved without central-snapshots. The first CI run on this pull request disproves both: Maven downloaded UltiTools-API-6.3.0-20260917.005350-20.pom and .jar from repo.papermc.io/repository/maven-public, whose group proxies Central's snapshots. The comment now says what the entry is (the repository the framework snapshot is published to) and that the build declares it rather than relying on PaperMC's proxy. Comment only; CRLF kept. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017BD9mGr6EsyRsEv3d2BizL
|
@codex review |
|
Codex Review: Didn't find any major issues. Nice work! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Summary
Moves this example onto UltiTools-API 6.3.0 and Paper.
GreetCommandextendedAbstractCommandExecutor, which 6.3.0 removed, so the plugin loaded but no/ultiextsub-command registered (#4). It now extendsBaseCommandExecutor. The pom builds onUltiTools-API 6.3.0-SNAPSHOTandpaper-api 1.21.11-R0.1-SNAPSHOT, the repository gains its first tests (15) and its first CI workflow, and the UAT checklist is corrected so its rows give the right verdict on a real server.本 PR 将示例迁移到 UltiTools-API 6.3.0 与 Paper:
GreetCommand改为继承BaseCommandExecutor(旧基类已在 6.3.0 移除,导致/ultiext子命令全部无法注册,#4),新增 15 个测试与首个 CI 工作流,并修正 UAT 清单。Issue closure
Closes #4
Superseded pull requests
Both open pull requests are reused, not rewritten. Their commits were cherry-picked onto the latest
masterwithgit cherry-pick -x, keeping the original author and author date. Both applied cleanly and compiled against 6.3.0-SNAPSHOT when measured.1cbbd55066bc59UltiTools-API 6.3.0-SNAPSHOT, addcentral-snapshotse128f2f9cb2317GreetCommandextendsBaseCommandExecutorPR #2's branch already contained PR #1's commit, so these two commits are everything in both. They are kept verbatim to preserve authorship, and two sentences in
9cb2317's message are no longer true where it now sits:AbstractCommandExecutorwas "deprecated". 6.3.0 removed it.066bc59and compiles against 6.3.0-SNAPSHOT.066bc59's pom comment ("no CI workflow") is corrected by later commits. Both pull requests will be closed with a comment pointing here.Checklist rows amended
UAT-CHECKLIST.md:/ultiextsub-command. Because the jar records no source commit, the executor compares the installed jar's SHA-256 with the build hand-off's.ultitools-example.greet.hello:JoinListenersends the identical line on join, so the row now requires a new line after the command and no unknown-command reply. Before, it could pass with no command registered.ultitools-example.data.visitors.neg-empty:visit/visitorsproves the store is readable.ultitools-example.data.visitors:<n>must equal the lines printed, and the list must includeprobeand the executor's own join record.ultitools-example.data.visit,ultitools-example.data.delvisitor.neg-not-found,ultitools-example.data.persistence,ultitools-example.join.on-join: preconditions check the record state with/ultiext visitorsand say how to reach it.ultitools-example.join.on-join.neg-rejoin: says when to readN.FEATURES.md:GreetCommandsource line numbers updated (@CmdExecutor46;@CmdMapping56/62/69/99/118). The "no comment names our annotations" claim is replaced with measured counts.AbstractDataEntityis described as removed, not deprecated.Red-when-reverted evidence
UltiTools-External-Example-4-RED.log/UltiTools-External-Example-4-GREEN.log: with the migration commit reverted, the build fails to compile (cannot find symbol AbstractCommandExecutor,GreetCommand.javalines 6 and 51); at the head,GreetCommandTestruns 14 tests, 0 failures. The RED is a compile error, so it proves the migration is required to build, not that the assertions catch a regression. The next log does that.UltiTools-External-Example-4-MUTATION-registration-RED.log: behaviour-level RED. The copy hasGreetCommandnot extendingBaseCommandExecutor.GreetCommandRegistrationTestfails because/ultiextis not registered: a test failure, not a compile error. That test runsGreetCommandthrough the framework's own code: the container steps ofPluginManager#registerExternal, the realPluginManager.validateCommandExecutorContracts, and the realCommandManager#registerAllExternal/unregisterAllExternalagainst a real BukkitSimpleCommandMap. OnlyUltiTools.getInstance()andBukkit's static accessors are stubbed. End-to-end registration on a server is then covered by the real-machine rowultitools-example.greet.hello.Behaviour changes
From
CHANGELOG.md, verbatim:(The Chinese entries follow each in the file.)
Known limitation
README.mdis unchanged. It still pins6.2.2in the dependency snippet, says "Requires UltiTools-API 6.2.2+", and describes "any standard Bukkit/Spigot/Paper plugin". The 6.2.2+ runtime claim still holds: every framework member the compiled classes use exists with the same signature in 6.2.2. Refreshing the version claims, and saying that the host server must be Paper, belongs to the 6.3.0 release package, together with UltiKits/UltiRecipe#19.CI
.github/workflows/maven-ci.ymlis new, so its first run is on this pull request. It is the modules' workflow (same pinned actions, JDK 21,mvn -B verify) with one deliberate change: the job is namedTest & package (JDK 21)instead ofTest, coverage gate & package (JDK 21), because this repository has no coverage gate and the check should not promise one. No publish or release workflow is added, and the project version is unchanged.Gates
48227ea,6354f3a,9f8b843andb1a4380.Test & package (JDK 21)check on the final head.Verification
mvn -B clean verifyon this head:Tests run: 15, Failures: 0, Errors: 0, Skipped: 0,BUILD SUCCESS(GreetCommandTest14,GreetCommandRegistrationTest1).Checklist
masterpom.xmlandGreetCommand.javastay CRLF; the markdown files and template stay LF. The two new test files are CRLF to match everysrc/main/javafile.FEATURES.mdandUAT-CHECKLIST.mdupdated🤖 Generated with Claude Code
https://claude.ai/code/session_017BD9mGr6EsyRsEv3d2BizL