Chess v1.0.5
Chess v1.0.5 adds three major features: a built-in engine opponent you can play from the
command line, a cross-server hub that links every connected server into a shared roster, and a
web dashboard at castled.codes where you can challenge in-game players and play moves through
the browser.
Added
CPU opponent (/chess duelcpu)
Play against a built-in engine at one of ten difficulty levels. The bot runs off the server
threads — it receives an immutable FEN snapshot and never touches the live board — so it never
blocks a click handler or a clock tick.
/chess duelcpu <1-10> <time>
Difficulty 1 plays like a beginner: it searches only a couple of moves deep and deliberately
plays a worse move most of the time. Difficulty 10 searches deeper but still within a
wall-clock budget, so a move always exists and the bot never outlasts a player's patience. The
levels vary both depth and intentional error rate, because a shallow search alone still takes
every hanging piece and then makes an alien-looking move — erring on purpose reads far more
like a real beginner.
The bot holds a colour, has a clock, and can be checkmated. Everything downstream treats it as
a participant who happens never to be online, which the views and messaging already handled.
Its answer is not trusted: before it is applied the game is rechecked, the notation is parsed
defensively, and an illegal move resigns the bot rather than corrupting the game.
Chess Hub — cross-server play
Servers dial out to a central hub over a WebSocket and publish who is online. Tab completion
now offers players from every server on the network, not just this one.
# settings.yml — added in this version
network:
enabled: true # join the hub on startup (default: true)
url: wss://castled.codes/api/chess/ws
label: "" # defaults to the server MOTDZero configuration. A server generates its own key on first start and writes it back to
settings.yml. The hub has never seen the key before and does not need to: the key is the
identity. Nothing has to be pasted in to take part. The server name defaults to the MOTD so it
appears recognisable without being asked to name itself.
The roster is sent whole rather than as deltas, so a server that misses a frame recovers on
the next one. It is held locally and answered from memory because tab completion asks on the
main thread and must not wait on a network. Reconnection backs off so a hub restart does not
require restarting every server attached to it.
The hub refuses offline-mode servers outright. Players are matched by Mojang UUID, and offline
mode derives UUIDs from names, so two such servers can mint the same UUID for different people
— across a shared network that is an impersonation hole rather than an inconvenience.
Duelling someone who is only on another server now says "That player is on another server"
rather than claiming they are offline.
Web dashboard play
A web admin at castled.codes can challenge an in-game player, and the in-game player can
accept and play a real game through the browser.
Challenging from the dashboard:
- Click a player in the online list.
- Pick a time control (1, 5, 10, or 30 minutes).
- Choose a display name (shown in-game and on the board).
- Send the challenge.
The in-game player receives a normal duel request and accepts with
/chess accept <name>. The dashboard board opens automatically once the game starts.
Playing from the dashboard:
Click two squares to attempt a move in UCI notation. The move is relayed through the hub to
the server, which validates it against the engine. Illegal moves are silently rejected and the
board re-renders from the real position on the next poll.
The web player is held to the same standard as a bot: it is refused unless it really is that
participant's turn and the engine accepts the move in the position it lands in. A browser is
the least trustworthy source of a move in the system, so nothing about one is assumed.
Multi-word names: /chess accept Castled King works. All tokens after the subcommand are
joined into a single name.
Clock sync: The game clock publishes to the hub every few seconds in addition to after
moves, so the dashboard's extrapolated countdown stays in sync.
FEN, fifty-move clock, and threefold repetition
The engine now tracks a halfmove clock, a move number, and a count of how often each position
has occurred. Both draws are applied automatically rather than offered as a claim — nobody
will claim a draw against an engine, and a game with no pawn moves left could otherwise run
forever.
FEN loading and UCI move notation are also in, which is what lets the bot run off the server
threads and what lets a remote board read the position.
Changed
- Tab completion now includes remote players from the network roster for
/chess duel,
/chess accept,/chess decline, and/chess watch. /chess duelon a remote player says "That player is on another server" instead of
"Your requested opponent is not online."- The watch broadcast asks the bot or web participant for its own name instead of reading
from Bukkit, so spectating a CPU or web game works. - Config upgrades are tested: an upgraded server picks up new settings by merging in
whatever the bundled default has and it lacks. Tests now pin that an existingsettings.yml
gains every key the code reads, that explicit values survive the merge, and that nothing
quietly stays at a default forever.
Commands
/chess duel <player> <time>
/chess duelcpu <1-10> <time> (new)
/chess accept <player> (supports multi-word names)
/chess decline <player> (supports multi-word names)
/chess watch <player>
/chess open
/chess help
Configuration
settings.yml gains a network section:
network:
enabled: true
url: ""
label: ""When network.enabled is true and a hub URL is configured, the server connects on startup
and begins exchanging rosters. When disabled or misconfigured, an OfflineNetwork stands in
and everything works as before — tab completion shows only local players.
Existing installs need no editing. Chess merges keys missing from an on-disk config with the
bundled defaults at startup, so the network section is added automatically.
Verification
gradle clean buildsucceeds.- Tab completion for
/chess duel,/chess accept,/chess decline, and/chess watch
includes remote players from the network roster cache. - A headless game between two bots drives the same select, move, promote and toggle sequence
the plugin performs, asserts the engine accepts every move the bot proposes, and verifies the
game terminates via the fifty-move or repetition rules. - The dashboard board renders a square grid and relays moves through the hub to the server.
Upgrade Note
Replace the previous Chess.jar and fully restart the server. Chess will overwrite
plugins/Chess/resourcepack.zip with the bundled pack during startup.
The resource pack is unchanged from v1.0.4. The network section in settings.yml is added
automatically when absent — no manual edits are required. If you want to join the hub, set
network.url to your hub address; otherwise leave network.enabled: false and everything
works as before.
Chess v1.0.5 targets Java 21 and Minecraft 1.21.11 on Spigot, Paper, or Folia.