Skip to content

Rewrite MCScript server from scratch for v2.0.0 - #61

Merged
perronosaurio merged 19 commits into
masterfrom
revival-2026
Sep 29, 2026
Merged

perronosaurio merged 19 commits into
masterfrom
revival-2026

Conversation

@perronosaurio

@perronosaurio perronosaurio commented Sep 29, 2026 •

Copy link
Copy Markdown
Owner

This is a complete rewrite of MCScript, a ClassiCube/Minecraft Classic server in JavaScript. The entire codebase has been rebuilt from the ground up, replacing the old src/ and client.js architecture with a modern, modular design.

Summary

MCScript v2.0.0 is a production-ready ClassiCube server that supports the classic protocol plus CPE extensions, runs multiple levels concurrently, and implements most features as loadable plugins. The server has no runtime dependencies beyond Node.js.

Key Changes

Core Server Architecture:

  • New lib/server.js - Main server class with player management, level loading, and heartbeat announcements
  • New lib/player.js - Player entity with position tracking, inventory, permissions, and CPE support
  • New lib/network/ - Connection handling with TCP and WebSocket support for both classic clients and web clients
  • New lib/protocol/ - Complete Classic protocol v7 and CPE packet definitions with CP437 encoding

Level & World System:

  • New lib/level/ - Level management with support for multiple concurrent worlds, custom blocks, and environment customization
  • New lib/level/generators.js - Procedural world generation with Perlin noise
  • Level persistence using ClassicWorld (.cw) format with NBT serialization

Command & Plugin System:

  • New lib/commands/manager.js - Command registry with rank-based permissions
  • New lib/plugins/manager.js - Plugin loader supporting dependencies, configuration, and lifecycle hooks
  • Core plugins for essentials, moderation, building, worlds, blocks, and minigames
  • Plugin installer for npm packages

Storage & Configuration:

  • New lib/storage/ - JSON-based player database and configuration management
  • New lib/config.js - Server configuration with environment variable overrides
  • New lib/ranks.js - Rank system with permission levels

Utilities:

  • New lib/util/text.js - Color code handling and text formatting
  • New lib/util/nbt.js - NBT serialization for level metadata
  • New lib/util/logger.js - Structured logging with file output
  • New lib/events.js - Event bus with priorities and cancellable events

Plugins (20+ included):

  • Building tools: cuboid, replace, line, sphere, fill, copy, paste, undo/redo, paint
  • Essentials: teleport, private messages, player info, models, nicknames, AFK detection
  • Moderation: ranks, kicks, bans, mutes, freeze, vanish, anti-spam
  • Worlds: create, load, visit, import, backup, environment customization
  • Custom blocks with CPE BlockDefinitions
  • Physics simulation (sand/gravel falling, water/lava flow)
  • Minigames: Parkour, TNT Wars, Capture the Flag, Zombie Survival
  • Chat relays for Discord and IRC
  • Web administration panel
  • Economy system with shops and ranks

Testing & Documentation:

  • New test/ - Integration and unit tests using Node.js test runner
  • New docs/ - Configuration, plugin development, and release guides
  • Comprehensive README with setup instructions

Notable Implementation Details

  • CPE Support: Full negotiation of extensions (ExtendedBlocks, BlockDefinitions, CustomModels, etc.)
  • Block History: Append-only binary log for undo/redo and player history tracking
  • Async/Await: Modern async patterns throughout for cleaner code
  • No Dependencies: Uses only Node.js built-ins (net, zlib, crypto, etc.)
  • Plugin Isolation: Plugins can be loaded/unloaded without server restart
  • Event System: Cancellable events allow plugins to intercept and modify behavior
  • Rank Permissions: Fine-grained control over commands, blocks, and level access

Migration Notes

Old v1.x code (src/, client.js) has been completely removed. Existing levels/level.dat files can be imported via the /import command.

The old workflow deployed every push of any branch to an FTP host.
It now runs npm ci, lint and tests on Node 20 and 22.
- Own packet codec (sizes verified against the ClassiCube client) with 30 CPE
  extensions: CustomBlocks, BlockDefinitions(Ext), BulkBlockUpdate, FastMap,
  EnvColors, EnvMapAspect, ExtPlayerList v2, HeldBlock, SelectionCuboid, ...
- WebSocket support on the same port for the web client
- Multiple levels in ClassicWorld (.cw) format, MCGalaxy .lvl and legacy
  level.dat import, world generators, autosave and backups
- Ranks, block permissions, player database, name verification, heartbeat
- Command manager and plugin manager with hot load/unload/reload
- Fixes old bugs: everyone was op, /kick crash, map sent before auth checks,
  entity id overflow, missing CPE negotiation
- No runtime dependencies; node:test unit and integration tests
core-essentials, core-moderation, core-worlds, core-building, core-blocks,
warps, zones, portals, bots, announcer, relay-irc, relay-discord and a
documented example plugin.
- Per-connection packet sizes: block ids up to 767 (two-array map transfer,
  BulkBlockUpdate high bits) and 32-bit entity coordinates for levels
  bigger than 1023 blocks; levels are stored with BlockArray2 like ClassiCube
- Fix SetInventoryOrder field order (block, then order)
- Optional SQLite player database (node:sqlite) that imports players.json
- /sudo to run a command as another player
- Verified against a real ClassiCube 1.3.8 client built from source
- /pinstall installs a plugin from a URL (GitHub links supported) or an npm
  package (without running install scripts); /puninstall moves it aside
- physics: falling sand/gravel, flowing water and lava, sponges, stone from
  water + lava, and on level 2 grass growth and TNT chain explosions
- Block changes are logged to disk per level: /about and the new
  /undoplayer keep working after a restart
- economy plugin: /money, /pay, /baltop, /eco, /shop and /buy (ranks,
  titles, colors and personal levels)
- Levels can have owners who can always build (/map owner)
- web-panel plugin (disabled by default): token protected browser panel
  with players, levels, live log and console
- Parkour (start, checkpoints, finish, timer, records), TNT Wars,
  Capture the Flag and Zombie Survival with rounds, teams, scoreboard,
  economy rewards and arena restore
- New blockPermission event lets plugins override block permissions
- Temporary model changes (setModel(model, false))
…fyAction and ToggleBlockList

- Protocol support (float fields, 8 new packets) and player/server APIs:
  defineModel, defineParticle/spawnParticles, setCinematic,
  sendPluginMessage, toggleBlockList; pluginMessage and notifyAction events
- effects plugin: particle presets, /effect, /cinematic, /blocklist
- custom-models plugin: example models (cube, spinner, bighead) and
  JSON models from config/plugins/custom-models
- Verified in a real ClassiCube client
- /write draws text with blocks using a built-in 5x7 font
- README and docs/PLUGINS.md cover the new plugins, events and APIs
Players: /back /ascend /descend /tpa /kill /clear /roll /8ball /hug /high5
/faq /news /view /top /search /blocks /pclients /whonick /tcolor /send
/inbox /loginmessage /logoutmessage /emotes /ccols /modelscale /entityrot
/lastcmd, plus (emote) replacements in chat.

Moderation: /warn /xban /temprank /report /whitelist /moveall /moderate
/voice /opchat /adminchat (# and + prefixes) /rankmsg /baninfo /banedit
/follow /p2p /patrol /rankinfo /playeredit /limit /oprules.

Levels: /copylvl /renamelvl /resizelvl /lockdown /reload /fixgrass /unflood.

Building: /hollow /outline /pyramid /tree /torus /spheroid /maze /rainbow
/drill /center /mirror /spin /mark /bind /mode /calculate.

Other: /plugin, /restart, /give, /take, /explode, /slap.
- Drop Node 20 (end of life); CI now runs on Node 22, 24 and 26 with
  current actions, read-only permissions and npm audit. Add Dependabot.
- Keep player names and plugin data keys such as __proto__ from
  polluting object prototypes.
- Limit connections per IP, cap WebSocket messages at 64 KB and reject
  unmasked frames. An exception in a packet handler kicks that player
  instead of stopping the server; async event handler errors are logged.
- Send heartbeats whenever verifyNames is on, so name verification also
  works on servers that are not public.
- /pinstall: HTTPS only (except localhost), stop reading after 2 MB,
  validate npm package specs and plugin names.
- New installs no longer make the original authors owners or list the
  server publicly by default.
Rewrite the README with install, hosting, updating and troubleshooting
guides.
The old server in src/ and client.js has not been used since the rewrite.
levels/level.dat made every fresh install start on the 2019 map; an old
level.dat copied in by hand is still converted on the first start.
Also trim .gitignore to what the project creates and add .editorconfig
and .gitattributes.
/pdisable and /penable (also /plugin disable|enable) unload or load a
plugin and store the choice in disabledPlugins, so it holds after a
restart. /plugins shows which ones are off.

The web panel now follows the ClassiCube forum layout: banner, breadcrumb
bar, category blocks with alternating rows and a statistics footer. Its
plugin list shows every plugin on disk with a Turn on / Turn off link.
Pushing a v* tag runs the tests and creates a release with a zip and a
tar.gz and the matching CHANGELOG section as notes (docs/RELEASING.md).
The server asks GitHub for the latest release when it starts and says so
in the console if there is a newer one (checkForUpdates).

Add issue and pull request templates.
It only printed an 'old plugin format' warning on every start.
The bundled level.dat is gone, so the test was always skipped.
@perronosaurio
perronosaurio merged commit 7f56bfb into master Sep 29, 2026
12 checks passed
@perronosaurio
perronosaurio deleted the revival-2026 branch September 29, 2026 20:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant