Skip to content

fix: UltiEssentials residue defects (#21, #24, #33, #39, #40, #41, #42, #45, #47, #48, #49, #51, #54, #56, #59, #60, #61, #62) - #64

Merged
wisdommen merged 62 commits into
masterfrom
fix/p17-w4-residue
Sep 29, 2026
Merged

wisdommen merged 62 commits into
masterfrom
fix/p17-w4-residue

Conversation

@wisdommen

@wisdommen wisdommen commented Sep 27, 2026 •

Copy link
Copy Markdown
Member

Issue closure

Closes #21 — the main-class test runs in the build, from a module jar the test builds itself
(主类测试在构建中运行,使用测试自行构建的模块 jar)

Closes #24 — /wild loads candidate chunks asynchronously and does all world work and the teleport on the main thread
(/wild 异步加载区块,世界读取和传送都在主线程执行)

Closes #33 — /wild reports the landing block position
(/wild 报告实际落脚的方块坐标)

Closes #39 — /back records only this module's own teleports
(/back 只记录本模块自己的传送)

Closes #40 — one board per player, reused; main-board teams copied onto it so name prefixes stay visible; the sidebar yields to another plugin's scoreboard
(每位玩家复用一个计分板;复制主计分板队伍使名称前缀可见;让出被其他插件占用的侧边栏位置)

Closes #41 — lines are truncated before they are made unique
(先截断再去重)

Closes #42 — the checklist and inventory name the real key, features.scheduled-commands.commands
(清单与清单文档写明真实键名 features.scheduled-commands.commands)

Closes #45 — /scoreboard off right after joining stays off
(刚加入时执行 /scoreboard off 后保持关闭)

Closes #47 — the never-reachable BanService#unbanIp/#unbanPlayer(UUID) and the /unbanip javadoc line are removed; the command is requested in #63
(删除不可达的 unbanIp/unbanPlayer(UUID) 和 /unbanip 文档;功能请求见 #63)

Closes #48 — the pardon alias is removed
(删除 pardon 别名)

Closes #49 — test-scope H2 and commons-dbutils run a real relational insert, update and delete
(测试范围引入 H2 与 commons-dbutils,执行真实的关系型增改删)

Closes #51 — after an unload the delayed join callbacks do nothing and every pending /tpa expiry is cancelled
(卸载后延迟回调不再执行,所有待处理的 /tpa 过期任务被取消)

Closes #54 — the /tpa cooldown map drops expired entries
(/tpa 冷却表清除过期条目)

Closes #56 — vanished players are hidden from /tpa, /tpahere and ban completions, and can un-vanish whatever features.hide.enabled says
(隐身玩家不会出现在 /tpa、/tpahere 和封禁补全中;无论开关如何都能取消隐身)

Closes #59 — built-in placeholders are filled in one pass before PlaceholderAPI
(内置占位符一次性填充后再交给 PlaceholderAPI)

Closes #60 — the w alias of /warp is removed
(删除 /warp 的 w 别名)

Closes #61 — /ban, /banlist and /scoreboard are documented as deliberate takeovers of the vanilla commands (vanilla stays reachable as minecraft:)
(文档写明 /ban、/banlist、/scoreboard 有意接管原版命令(原版可用 minecraft: 前缀))

Closes #62 — the ul, l and sb aliases are removed
(删除 ul、l、sb 别名)

Decisions applied

  • Scoreboard (maintainer, 2026-09-27): both UltiEssentials and UltiSideBar change. Each copies the main scoreboard's teams onto the private board it shows. The first sidebar shown keeps the slot; the other waits and returns a player to the main scoreboard only while its own board is on screen. When both are enabled, each logs one start-up line, and turning a sidebar on while the other holds the slot says so truthfully. The companion pull request fix: UltiSideBar residue defects (#17, #19, #20, #21, #26, #27) UltiSideBar#28 carries the other half.
  • Vanilla labels (maintainer, 2026-09-27): aliases equal to a vanilla label (pardon, w) are removed; the primary names /ban, /banlist and /scoreboard are kept and documented as takeovers.
  • Aliases shared with other UltiKits components (maintainer, 2026-09-27): UltiEssentials gives up ul, l and sb.
  • Cooldown maps (maintainer, 2026-09-27): expired entries are dropped; behaviour is unchanged and a reconnect does not reset a cooldown.
  • Placeholders (maintainer, 2026-09-27): every placeholder of a line is filled in one pass.
  • Vanish (maintainer, 2026-09-27): all three exposures are fixed.
  • Unreachable declarations (maintainer, 2026-09-22): removed, with the IP-unban command filed as a feature request (Feature request: a command to lift an IP ban (and to create one) #63).
  • Private scoreboard ownership (maintainer, 2026-09-27, Question: does the sidebar's private scoreboard belong to the sidebar alone, or must it coexist with other plugins writing onto it? #65, closed): the board this module assigns to a player belongs to this module alone; another plugin writing onto it is not supported. FEATURES.md, README.md and the service javadoc say so.
  • Supported platform: the README now states Paper 1.19+ only, as the framework requires; the old badge advertised Spigot and 1.8.

Checklist rows amended

UAT-CHECKLIST.md: ultiessentials.wild.teleport, ultiessentials.back.teleport, ultiessentials.back.teleport.neg-no-location, ultiessentials.back.track, ultiessentials.back.track.neg-foreign-teleport, ultiessentials.tpa.send.neg-vanished-target, ultiessentials.hide.toggle.neg-disabled-unvanish, ultiessentials.scoreboard.toggle, ultiessentials.scoreboard.enable, ultiessentials.scoreboard.disable, ultiessentials.scoreboard.auto-enable-on-join, ultiessentials.ban.ban.neg-completion-vanished, ultiessentials.ban.unban.neg-also-server-banned, ultiessentials.nameprefix.on-join, ultiessentials.scheduledcommands.run, ultiessentials.lifecycle.reload-scoreboard-off, ultiessentials.compat.ultisidebar-yield

FEATURES.md: ultiessentials.wild.teleport, ultiessentials.back.teleport, ultiessentials.back.track, ultiessentials.warp.teleport, ultiessentials.tpa.send, ultiessentials.tpa.send-here, ultiessentials.hide.toggle, ultiessentials.scoreboard.toggle, ultiessentials.scoreboard.enable, ultiessentials.scoreboard.disable, ultiessentials.scoreboard.auto-enable-on-join, ultiessentials.ban.ban, ultiessentials.ban.unban, ultiessentials.banlist.list, ultiessentials.lock.lock, ultiessentials.lock.unlock, ultiessentials.nameprefix.on-join, ultiessentials.lifecycle.unload-tasks, ultiessentials.config.essentials.features.hide.enabled, ultiessentials.config.essentials.features.scoreboard.enabled, ultiessentials.config.essentials.features.scoreboard.title, ultiessentials.config.essentials.features.scoreboard.lines, ultiessentials.config.essentials.features.nameprefix.prefix-format, ultiessentials.compat.ultisidebar-yield

Row IDs are taken from the diff against the base branch; a row whose ID appears is added, removed or changed.

Red-when-reverted evidence

Each fix was reverted on its own at the head and its tests re-run: red with the fix reverted, green with it (log file names, kept with the phase evidence). A -review- pair proves a fix made after this pull request's own review, a -codex-rN pair a fix made after the automated review's round N, and a -sweep- pair a same-class fix found by a sweep.

Behaviour changes

From CHANGELOG.md ## [Unreleased], as added by this pull request:

- `/back` now returns only from teleports this module's own commands started (`/home`, `/warp`,
  `/spawn`, `/lobby`, `/wild`, an accepted `/tpa` or `/tpahere`, and `/back` itself). Another plugin's
  teleport or a vanilla `/tp` no longer gives `/back` a place to return to, so a teleport by something
  else after a rejoin no longer re-arms it. A second `/back` still returns to where the first one started
  (UltiKits/UltiEssentials#39).
- `/back` 现在只会返回由本模块自己的命令发起的传送(`/home`、`/warp`、`/spawn`、`/lobby`、`/wild`、被接受的 `/tpa` 或
  `/tpahere`,以及 `/back` 本身)。其它插件的传送或原版 `/tp` 不再为 `/back` 记录返回点,因此重新进服后被其它来源传送
  也不会再让 `/back` 生效。连续两次 `/back` 仍会回到第一次 `/back` 出发的位置(UltiKits/UltiEssentials#39)。
- `/wild`'s success message now reports the height the player lands at (the feet position); it used to
  report the ground block one below (UltiKits/UltiEssentials#33).
- `/wild` 成功提示现在报告玩家落脚的高度(脚所在的位置);此前报告的是下方一格的地面方块高度(UltiKits/UltiEssentials#33)。
- `/wild` no longer stalls the server while it looks for a place: each candidate chunk is loaded (and
  generated, if new) asynchronously, and the safety check and the teleport run on the main thread once it
  has loaded. A player who logs out meanwhile is not teleported, and a search still waiting for a chunk
  when the module is unloaded does nothing (UltiKits/UltiEssentials#24).
- `/wild` 寻找落点时不再卡住服务器:每个候选区块都异步加载(新区块异步生成),加载完成后再在主线程做安全检查并传送;
  期间下线的玩家不会被传送;模块卸载时仍在等待区块的搜索不会再执行任何操作(UltiKits/UltiEssentials#24)。
- A vanished player is no longer found through `/tpa` or `/tpahere` (a sender who may not see vanished
  players is told the player is not online, and no request is delivered) or through `/ban` and
  `/tempban` completion, and a vanished player can always un-vanish: `features.hide.enabled: false`
  now refuses only a new vanish (UltiKits/UltiEssentials#56).
- 隐身玩家不再能通过 `/tpa`、`/tpahere`(无权看见隐身玩家的发送者会被告知对方不在线,请求也不会送达)或 `/ban`、
  `/tempban` 的补全被发现;隐身玩家也总能解除隐身:`features.hide.enabled: false` 现在只拒绝新的隐身
  (UltiKits/UltiEssentials#56)。
- Unloading this module (`/upm uninstall UltiEssentials`) now also cancels a pending `/tpa` or
  `/tpahere` request's expiry, so neither player gets an expiry message from the uninstalled module, and
  a player who joined in the second before the uninstall is no longer put on a sidebar or into a
  name-prefix team afterwards (UltiKits/UltiEssentials#51).
- 卸载本模块(`/upm uninstall UltiEssentials`)现在还会取消待处理的 `/tpa`、`/tpahere` 请求的过期任务,双方不会再收到
  已卸载模块发出的过期提示;在卸载前一秒内加入的玩家也不会在卸载后被放上侧边栏或加入名字前缀队伍
  (UltiKits/UltiEssentials#51)。
- With PlaceholderAPI installed, the scoreboard now shows its built-in placeholders (`%online_players%`,
  `%max_players%`, `%player_food%` and the others) as values instead of the raw tokens: the module's own
  placeholders are filled first and PlaceholderAPI's afterwards, in the scoreboard and in name prefixes
  (UltiKits/UltiEssentials#59).
- 装有 PlaceholderAPI 时,计分板现在会把内置变量(`%online_players%`、`%max_players%`、`%player_food%` 等)显示为数值,
  不再原样显示:计分板与名字前缀先填入本模块自己的变量,再交给 PlaceholderAPI(UltiKits/UltiEssentials#59)。
- `/scoreboard off` run right after joining now sticks: the sidebar no longer appears a moment later
  from the delayed auto-enable, nor from a reload that turns the scoreboard feature on. The choice lasts
  until the player quits or runs `/scoreboard on` (UltiKits/UltiEssentials#45).
- 刚进服就执行的 `/scoreboard off` 现在会生效:侧边栏不会再被延迟的自动开启在片刻后重新显示,重载开启计分板功能时也不会。该选择持续到玩家退出或执行
  `/scoreboard on` 为止(UltiKits/UltiEssentials#45)。
- The sidebar no longer replaces another plugin's sidebar (such as UltiSideBar's): whichever sidebar a
  player sees first stays, and this one appears once the other is turned off. `/scoreboard on` and
  `/scoreboard` now say when another scoreboard keeps the slot, and `/scoreboard off` no longer removes
  another plugin's sidebar. When UltiSideBar's sidebar is also enabled, one console line says so after
  start-up (UltiKits/UltiEssentials#40).
- 侧边栏不再顶替其它插件的侧边栏(例如 UltiSideBar 的):玩家先看到哪个侧边栏就保留哪个,另一个关闭后本侧边栏才显示。
  `/scoreboard on` 与 `/scoreboard` 在另一个计分板占用该位置时会如实说明,`/scoreboard off` 也不再移除其它插件的侧边栏。
  UltiSideBar 的侧边栏同时开启时,启动后控制台会有一行提示(UltiKits/UltiEssentials#40)。
- Name prefixes (`features.nameprefix`) and other main-scoreboard teams (vanilla `/team` teams, other
  plugins' teams) now show while this module's sidebar is on: the sidebar's own scoreboard now carries
  the server's main-scoreboard teams and follows their changes on every update. Previously every
  player with the sidebar on saw no team prefix on anybody. A sidebar line that reads exactly like a
  team member's name keeps its own look rather than taking that team's prefix (UltiKits/UltiEssentials#40).
- The sidebar is no longer rebuilt every second: each player keeps one sidebar scoreboard that is
  updated in place, and its lines are rewritten only when they change. If another plugin removes the
  sidebar's objective, clears or takes its slot, or resets its lines, the next update restores them;
  what another plugin puts on that board (its own teams, objectives and scores) is left alone
  (UltiKits/UltiEssentials#40).
- 本模块的侧边栏开启时,名字前缀(`features.nameprefix`)和主计分板上的其它队伍(原版 `/team` 队伍、其它插件的队伍)
  现在都会显示:侧边栏自己的计分板会带上服务器主计分板的队伍,并在每次刷新时跟随其变化;此前开着侧边栏的玩家
  看不到任何人的队伍前缀。与某个队伍成员名字完全相同的侧边栏行保持原样,不会带上该队伍的前缀(UltiKits/UltiEssentials#40)。
- 侧边栏不再每秒重建:每位玩家保留同一块侧边栏计分板并原地刷新,内容行只在变化时重写。若其他插件删除了侧边栏的目标、
  清空或占用了其显示位置、或重置了其内容行,下一次刷新会恢复它们;其他插件放在这块计分板上的内容(其队伍、目标和分数)
  不受影响(UltiKits/UltiEssentials#40)。
- Two scoreboard lines that differ only after their 40th character now both show; previously the
  second one replaced the first (UltiKits/UltiEssentials#41).
- 只在第 40 个字符之后才不同的两行计分板内容现在都会显示;此前第二行会顶替第一行(UltiKits/UltiEssentials#41)。
- `/ban`, `/banlist` and `/scoreboard` deliberately take over the vanilla commands of the same name, as
  the maintainer decided; this is now stated in the documentation. The vanilla commands stay reachable as
  `minecraft:ban`, `minecraft:banlist` and `minecraft:scoreboard` (UltiKits/UltiEssentials#61).
- `/ban`、`/banlist`、`/scoreboard` 按维护者决定有意接管同名原版命令,现已写入文档;原版命令仍可用 `minecraft:ban`、
  `minecraft:banlist`、`minecraft:scoreboard` 调用(UltiKits/UltiEssentials#61)。
- Removed three aliases other UltiKits components own: `ul` of `/unlock` (the framework's own `/ul`),
  `l` of `/lock` (UltiLogin's `/l` for `/login`) and `sb` of `/scoreboard` (UltiSideBar's `/sb` for
  `/sidebar`). Use `/unlock`, `/lock` and `/scoreboard` (UltiKits/UltiEssentials#62).
- 删除三个与其它 UltiKits 组件冲突的别名:`/unlock` 的 `ul`(框架自己的 `/ul`)、`/lock` 的 `l`(UltiLogin 登录命令的 `/l`)、
  `/scoreboard` 的 `sb`(UltiSideBar 侧边栏命令的 `/sb`)。请使用 `/unlock`、`/lock`、`/scoreboard`(UltiKits/UltiEssentials#62)。
- Removed the `w` alias of `/warp`: `/w` is vanilla's private-message shortcut (`/w <player> <message>`),
  which the alias could take over. Use `/warp` (UltiKits/UltiEssentials#60).
- 删除 `/warp` 的别名 `w`:`/w` 是原版的私聊快捷命令(`/w <玩家> <消息>`),该别名可能把它抢走。请使用 `/warp`
  (UltiKits/UltiEssentials#60)。
- Removed the `pardon` alias of `/unban`: `pardon` is the vanilla command that lifts the server's own
  ban, and the alias made the bare label reach this module or vanilla depending on load order. Use
  `/unban` for this module's bans (UltiKits/UltiEssentials#48).
- 删除 `/unban` 的别名 `pardon`:`pardon` 是解除服务器自身封禁的原版命令,该别名会让这一标签视加载顺序进入本模块或原版。
  本模块的封禁请用 `/unban` 解除(UltiKits/UltiEssentials#48)。
- Removed the two unban helpers that no command reached — unbanning by player UUID and by IP address —
  and the `/unbanip` line in `/unban`'s documentation, which named a command that does not exist.
  `/unban <player>` is unchanged; an IP-unban command is tracked as a feature request,
  UltiKits/UltiEssentials#63 (UltiKits/UltiEssentials#47).
- 删除两个没有任何命令调用的解封方法(按玩家 UUID 解封、按 IP 解封),以及 `/unban` 说明中指向不存在命令的
  `/unbanip` 一行。`/unban <玩家>` 不变;IP 解封命令作为功能需求在 UltiKits/UltiEssentials#63 跟踪(UltiKits/UltiEssentials#47)。

Known limitation

This module's plugin.yml api-version and any README compatibility line still advertise the pre-6.3.0 API level, and the framework's 6.3.0 lifecycle hooks (onReload(), onUnregister()) run only under a 6.3.0 framework. The api-version: 630 pin lands together with the UltiTools 6.3.0 release package, by an earlier maintainer decision, before any module release. No module version is bumped and nothing is released from this pull request. Tracking instance: UltiKits/UltiRecipe#19.

Gates

This repository is not onboarded to Codacy — gate 2 for module repositories is the Codex review only, per the phase's carried-forward decision.

Gate Status
1 — own deep review done: 0 blockers, 0 warnings, 4 notes
2 — Codex review 9 rounds, converged. Fixed after review: a /wild search pending at unload; sidebar rows formatted by a copied team; the reused sidebar board's objective, slot and lines not restored, and board-wide writes reaching another plugin's content; a vanished player hidden from themselves (P3); a reload that turned the feature on overriding /scoreboard off. Settled by the maintainer's decisions: ownership of the private board (#65), a foreign board counting as occupied (UltiKits/UltiSideBar#29). Platform finding answered by stating Paper 1.19+ in the README. Final head f882df7: "Codex Review: Didn't find any major issues. Can't wait for the next one!"
3 — real-server acceptance runs in the combined real-server session for these pull requests, before merge
4 — maven-ci success on f882df7 — https://github.com/UltiKits/UltiEssentials/actions/runs/36331091983

🤖 Generated with Claude Code

wisdommen and others added 30 commits September 27, 2026 21:30
#41)

The two existing ensureUnique tests seeded the board's own entries to force a
collision; they now configure two equal lines, the collision the dedup exists
for, since a line is made unique against this update's lines.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…nd is kept per player (#40)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…eboard's teams onto it (#40)

Maintainer decision 2026-09-27: whoever gives a player a private scoreboard
carries the main board's teams onto it. The board is built once and updated in
place, so the copy survives and the sidebar is no longer rebuilt every second.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ays so (#40)

The test player's scoreboard now follows setScoreboard. The update-loop
isolation test asserted that the second player's board was assigned again on
every update; it now asserts that the refresh rendered the player's line, since a
board already on screen is no longer assigned again. Red on master by
compilation (the slot query does not exist yet); behaviour-level reds are
mutation proofs on each yield guard.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…board (#40)

The offline-player isolation test re-enabled the same player object while it
still held the board of its earlier session; a returning player views the main
scoreboard, which is what the yield guard reads.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…aken (#40)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ys so (#40)

Mutual yield as the maintainer decided on 2026-09-27: the board is shown only
while the player views the main scoreboard or this module's own board, is
removed only while it is on screen, and comes back on the next update once the
slot is free. /scoreboard on and toggle reply truthfully when another
scoreboard keeps the slot, and one start-up line reports UltiSideBar's sidebar.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ed auto-enable (#45)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The command test verified the service's plain disable; turning it off now goes
through the call that also remembers the choice for the session.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…es it off (#45)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…h PlaceholderAPI installed (#59)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ugh the title (#59)

The test made the rebuild fail through player.getWorld(), which the old
fallback called for every line whatever it contained; built-in placeholders are
now filled only where they occur, so the reloaded title names the world.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Scoreboard lines and name prefixes fill this module's own placeholders in one
pass over the text as written, then hand the result to PlaceholderAPI when it is
installed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…e is shut down (#51)

ScoreboardService and NamePrefixService set a flag in shutdown() that reload()
clears again, so a delayed enable or prefix update that fires after an unload
does nothing.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
)

The unload tests now register the teleport-request service in the container,
since the unload shuts it down too; with it, five services are unreachable in an
empty container instead of four.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ervice (#51)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… unloads (#51)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…es (#54)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Expired on read and swept on every new request, as the maintainer decided on
2026-09-27; the cooldown itself behaves as before and a reconnect still does not
reset it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… or ban completion, and can always un-vanish (#56)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… completion, and let them always un-vanish (#56)

All three paths as the maintainer decided on 2026-09-27.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… player lands (#24, #33)

The existing /wild tests now let the chunk load complete at once and run the
main-thread task inline (Mockito) or tick until it has run (MockBukkit, with the
framework plugin registered under its name).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ous chunk load (#24)

The safety-check tests left the player offline, which the main-thread check
now respects, and the MockBukkit thread test runs on a world that answers the
asynchronous chunk request MockBukkit itself leaves unimplemented.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…hem on the main thread (#24)

Attempts are chained, up to ten as before; the configured cooldown is
unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ation (#33)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The listener tests that recorded a raw COMMAND or PLUGIN teleport now assert
that such a teleport, which this module did not start, is not recorded; the
event-bus test now drives /back's own teleport through the bus.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…rts (#39)

An OwnTeleports mark is set for one player around each of this module's
command teleports and removed in a finally block; the listener records only
a teleport carrying it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…reaches (#47)

Tests of the two uncalled unban methods are removed; those that exercised the
shared verified-deactivation logic through the by-UUID method now go through
the by-name method, which /unban uses.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…this module alone (#40)

Maintainer decision on #65: another plugin writing onto the board this module
assigns is not supported. FEATURES, README and the service javadoc say so.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@wisdommen

Copy link
Copy Markdown
Member Author

@codex review

354894f: documentation of the maintainer's decisions only — the sidebar's private scoreboard belongs to this module alone (#65).

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 354894f1e7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

Comment on lines +77 to +78
if (!Objects.equals(source.displayName(), copy.displayName())) {
copy.displayName(source.displayName());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve compatibility with legacy scoreboard APIs

On the advertised Minecraft 1.8–1.21 range, releases whose scoreboard API predates the Adventure component accessors do not provide Team.displayName(), prefix(), or suffix(), so the first default-enabled sidebar refresh reaches this method and fails at runtime with NoSuchMethodError. The previous implementation used the legacy string prefix/suffix API; use compatible accessors or isolate these calls behind a version adapter so the new team mirror does not disable the sidebar on older supported servers.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a failure on a server this module can run on, but the advertised platform was wrong, and that is fixed in ee65c1a. The UltiTools framework this module is loaded by declares Bukkit api-version: 1.19 and uses Paper's Adventure API throughout (its own Component messages), so neither Spigot nor a pre-1.19 server can load the framework at all, let alone reach this method. On Paper 1.19+ Team#displayName()/prefix()/suffix() are present (Paper has had them since 1.16.5). The README badge claimed "Minecraft 1.8–1.21" linked to spigotmc.org; it now says Paper 1.19–1.21 and states that Spigot and older servers are not supported. The Adventure accessors are kept on purpose: the legacy string accessors round-trip through a legacy serializer and can lose hex colours in a copied prefix.

…rk does

The badge advertised Spigot and 1.8; the framework declares api-version 1.19
and uses Paper's Adventure API throughout, so neither ever ran this module.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@wisdommen

Copy link
Copy Markdown
Member Author

@codex review

ee65c1a: the README now states the supported platform (Paper 1.19+, as the framework), answering the team-accessor finding.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ee65c1ae7c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

return;
}

declinedPlayers.remove(player.getUniqueId());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve declined choices during automatic reload enablement

When a player has used /scoreboard off and an administrator disables then re-enables the scoreboard feature during the same session, reload() sees wasRunning == false, follows scoreboard.auto-enable, and calls this method, which clears the player's decline marker and shows the sidebar again. This violates the new session-long opt-out behavior; automatic reload restoration should skip declined players or only the explicit /scoreboard on path should remove this marker.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 673c033 (test) and f882df7 (fix). The decline was honoured by the delayed join enable only; the reload path was the other automatic caller of the same enable and was missed. enableScoreboard now skips a declined player, so no automatic enable can override the choice, and only the player's own /scoreboard on or toggle (acceptScoreboard) clears it. The test turns the feature off and on by two reloads after /scoreboard off; a control without the off still shows the sidebar.

wisdommen and others added 2 commits September 28, 2026 01:49
…yer's /scoreboard off (#45)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…scoreboard off (#45)

The decline was honoured by the delayed join enable only; a reload that turns
the feature on enabled by auto-enable and cleared it. enableScoreboard now skips
a declined player, and only /scoreboard on and toggle (acceptScoreboard) clear
the decline. Two command tests now verify the renamed call.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@wisdommen

Copy link
Copy Markdown
Member Author

@codex review

f882df7: no automatic enable (join or reload) overrides a player's /scoreboard off.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Can't wait for the next one!

Reviewed commit: f882df763e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

@wisdommen
wisdommen merged commit 0875d16 into master Sep 29, 2026
2 checks passed
This was referenced Sep 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment