▶️ ЗАБЕРИ СВОИ 8 ПОДАРКОВ 🎁 ПРИ СОЗДАНИИ СВОЕГО МАЙНКРАФТ СЕРВЕРА
Плагины/NodeRunner
NodeRunner

NodeRunner

Run your Node.js Discord bot directly alongside your Minecraft server! Features auto-setup, live web dashboard, and in-game controls

Оцените первым
58
1
Все версииNodeRunner 1.3.0

NodeRunner 1.3.0

Release27.04.2026

Список изменений

🆕 What's new in 1.3.0

Dashboard — Settings & Bot Management

The web dashboard has been completely overhauled. It is no longer just a log viewer — it now gives you full control over the plugin without ever touching config.yml or SSHing into the server.

New Settings tab — every config value is editable live from the browser:

  • Process behaviour: auto-restart toggle, restart delay, max restarts, crash window, startup delay
  • Node.js runtime: version pin and custom executable path
  • Discord webhook: URL, enable/disable, and individual toggles for each event type (start, stop, crash, log lines)
  • Dashboard: log history line count and password (changing the password immediately invalidates all active sessions)

New Bots tab — full bot instance management with TunnelMC-style modal dialogs:

  • Add a new bot (name, entry file, env vars) — starts automatically
  • Edit an existing bot — stops it, applies the new config, and restarts
  • Delete a bot — stops it and removes it from config.yml
  • All changes persist to disk immediately

Download logs — a new button on the sidebar downloads the current bot.log as a file attachment.

SSE push-based streaming — log lines are now pushed directly to the browser the moment they are written, rather than polled. This eliminates latency and CPU overhead.

Log counter fix — the line counter now reflects what is actually visible in the DOM (capped at 3000) rather than a stale incrementing integer that could exceed the cap.

switchBot() race fixed — historical logs are now fully loaded before the SSE stream connects, preventing out-of-order or duplicate lines when switching bots.

Bug Fixes

  • failedAttempts map unbounded growth — the brute-force attempt tracker is now swept hourly alongside the session map, preventing unbounded accumulation of stale IP entries.

  • JSON injection in status/bots API — bot names and entry file paths are now serialised with Gson instead of string concatenation, preventing malformed JSON if a name contains quotes or backslashes.

  • setsid path now covers Alpine Linux / Pterodactyl — checks /usr/bin/setsid, /bin/setsid, and /usr/local/bin/setsid before falling back gracefully. Previously only /usr/bin/setsid was checked, so process group killing silently did nothing on Alpine-based containers.

  • FileReader platform charset/proc/<pid>/status is now read with explicit UTF-8 instead of the JVM default charset.

  • FileUtils.deleteDir() now returns boolean — failures are logged per-file instead of silently swallowed.

  • GET endpoints reject non-GET requests/api/status, /api/bots, /api/logs/recent, /api/logs/stream now return 405 for wrong-method requests.

  • Log timestamps include the date — entries now use MM-dd HH:mm:ss format so logs spanning midnight are unambiguous.

  • Content-Security-Policy header added to all dashboard responses.

  • Gradle performance flagsparallel, caching, and G1GC JVM args added to gradle.properties for faster local builds.

  • Fixed state race conditionBotState is now managed via AtomicReference instead of a plain volatile field, eliminating a class of bugs where background threads could set the state back to RUNNING after a stop was already requested.

  • Fixed child process orphaning on stop — NodeRunner now launches the bot with setsid on Linux/macOS and sends kill -TERM -<pgid> on stop, matching PyRunner's behaviour. Previously, any subprocesses spawned by the bot (workers, shell scripts, etc.) were left running after the parent was killed.

  • Fixed extractTar double-reading the archive — The extracted directory is now located by diffing the folder listing before and after extraction. The old approach ran tar tf on the archive file a second time, which could fail if the archive had already been deleted.

  • Fixed restart() busy-wait — The polling loop (Thread.sleep(200) in a while loop) has been replaced with a CountDownLatch, so restarts are both more reliable and use zero CPU while waiting.

  • Fixed HttpClient created per request — A single shared HttpClient instance is now reused across all Node.js version and download requests, rather than constructing a new one (with its own thread pools and connection pool) for each call.

  • Fixed config values not validated — All numeric config getters (restart-delay-seconds, max-restarts, crash-window-seconds, startup-delay-seconds) now clamp to valid ranges, preventing Thread.sleep(-N) exceptions from negative values.

  • Fixed log-history cap not enforcedgetDashboardLogHistory() is now capped at 500 (matching LogManager's ring buffer size), so requesting more lines than the buffer holds no longer silently returns a truncated result without warning.

  • Fixed static instance not volatile — The singleton is now declared volatile for safe cross-thread visibility, and is nulled out in onDisable() to prevent classloader leaks on plugin reload.

  • Fixed Discord embed JSON escaping — Webhook embeds now use Gson's toJson() for string serialisation instead of a manual replace() chain, correctly escaping all Unicode control characters (\u0000\u001F) that could cause Discord to reject payloads.

  • Fixed malformed bot entries crashing plugin load — Each entry in the bots: YAML list is now parsed inside a try-catch; a bad entry logs a warning and is skipped rather than throwing a ClassCastException that aborts the whole enable sequence.

  • Added default password warning — A prominent console warning is now printed at startup if the dashboard is enabled and the password is still set to "changeme".

  • Improved getBotDir() fallback — When entry-file has no directory component (e.g. index.js instead of bot/index.js), the plugin now derives the directory from the actual file path and logs a descriptive warning, rather than silently assuming "bot".

  • Fixed dashboard SSE exhausting the HTTP thread pool — The server now uses Java 21 virtual threads (newVirtualThreadPerTaskExecutor) instead of a fixed 8-thread pool. Previously, 8+ simultaneous SSE log-stream connections (e.g. multiple open tabs or reconnect storms) would fill the pool and cause all other API requests — status polls, button clicks — to hang indefinitely.

  • Fixed DashboardServer.jsonString() unsafe escaping — Dashboard log API responses now use GSON.toJson() instead of a manual replace() chain. Log lines containing Unicode control characters (\u0000\u001F) could previously produce malformed JSON that failed to parse in the browser.

  • Fixed memory cache non-atomic reads — The three separate volatile fields (cachedMemKb, cachedMemPid, cachedMemTime) have been replaced with a single volatile MemCache record, swapped atomically. A thread could previously observe a new timestamp alongside stale memory values from the previous cycle.

  • Fixed SSE handler busy-polling — The while (!heartbeatFuture.isDone()) Thread.sleep(1000) loop is replaced with heartbeatFuture.get(), eliminating the 1-second wake-up overhead while waiting for clients to disconnect.

  • Fixed session map growing without bound — A ScheduledExecutorService now sweeps expired sessions every hour. Previously, repeated logins without a server restart would accumulate stale entries in the map indefinitely.

  • Fixed dashboard password using string equality — The login check now uses MessageDigest.isEqual() for constant-time comparison, preventing theoretical timing attacks on the password.

  • Fixed duplicate deleteDir() logic — A new shared util/FileUtils.deleteDir() (NIO-based) replaces the identical recursive-delete method that was duplicated across NodeBotCommand and DashboardServer.

  • Fixed plugin.yml api-version outdated — Updated from '1.13' to '1.21' to match the actual target platform and suppress Paper's deprecation warnings on load.

  • Fixed Gson used as implicit transitive dependency — Gson is now declared explicitly as compileOnly in build.gradle.kts so the build doesn't silently rely on Paper's bundled copy, which Paper reserves the right to relocate or remove.

  • Fixed legacy § color codes in commands — All in-game messages in NodeBotCommand now use the Paper Adventure API (MiniMessage) instead of deprecated §-prefixed color codes, eliminating deprecation warnings and ensuring correct rendering in modern clients.


Changes

  • Dashboard now uses a bounded thread pool (8 threads) instead of an unbounded cached pool
  • SSE heartbeats use a shared scheduled executor instead of per-connection threads
  • NodeDownloader is now a shared singleton — multiple bots no longer trigger duplicate downloads
  • Webhook shutdown is now handled cleanly on plugin disable
  • Restart now waits for the process to fully stop before starting again (prevents race conditions)

Bug Fixes

  • Fixed stop command not waiting for the process to actually terminate before reporting "stopped"
  • Fixed auto-restart thread not being interrupted when manually stopping a bot

Config changes

New option added to config.yml:

# Per-bot env vars (in bots: list)
bots:
  - name: "modbot"
    entry-file: "bot/modbot/index.js"
    env:
      BOT_TOKEN: "modbot-token-here"

Existing configs remain fully compatible — all new keys use their defaults if not present.

Файлы

NodeRunner.jar(71.60 KiB)
Основной
Скачать

Метаданные

Канал релиза

Release

Номер версии

1.3.0

Загрузчики

Bukkit
Paper
Purpur
Spigot

Версии игры

1.21–1.21.11

Загрузок

6

Дата публикации

27.04.2026

Загрузил

ID версии

Главная