Repository navigation
NeoTab 1.4.0
NeoTab 1.4.0
1.4.0 is NeoTab's first stable cross-platform release. It keeps the Minecraft minimum at 1.20.6, but the same JAR can now run on Paper, Spigot, and CraftBukkit. This release also contains a broad rendering, lifecycle, performance, and correctness pass based on real testing outside Paper.
The stable build promotes the code tested in 1.4.0-Beta.1. No compatibility or configuration break was introduced between the beta and stable release; the promotion follows another source audit, a clean build, the full regression suite, and extended churn diagnostics.
Highlights
- One shared JAR for Paper, Spigot, and CraftBukkit on Minecraft
1.20.6+. - Tab names, RAM values, scoreboard titles, and animation styles update correctly on Spigot and CraftBukkit.
- MiniMessage colors and RGB gradients remain available without requiring Adventure from the server.
- Tab and scoreboard rendering now use separate animation and statistics schedules.
- Region, scoreboard, GUI, ActionBar, advancement, visibility, and asynchronous save lifecycles were hardened.
- Anonymous bStats metrics were added with strict, aggregated custom charts and plugin ID
32846. - 27 regression tests were added, bringing the suite to 46 tests across 7 suites.
Paper, Spigot, and CraftBukkit support
NeoTab now compiles against the Spigot 1.20.6 API instead of relying on Paper as its shared compile target. Direct Paper-only event, logger, inventory, tablist, item, scoreboard, and plugin-metadata calls were removed from shared code.
Adventure, MiniMessage, and Gson are embedded into the final JAR and relocated into NeoTab's own namespace. This allows the same color and formatting pipeline to work on all three supported server platforms while avoiding dependency conflicts with the server or other plugins.
ActionBar delivery uses a platform bridge:
- Paper and Spigot use the supported Spigot ActionBar API.
- CraftBukkit uses a small runtime packet bridge because it does not expose a public ActionBar API.
- If a future CraftBukkit version changes the internal packet layout, NeoTab falls back to the vanilla
minecraft:title ... actionbarcommand.
Only the CraftBukkit ActionBar packet path depends on non-public implementation details. A warning is emitted only if both the packet bridge and command fallback fail.
LuckPerms integration is isolated behind an optional boundary. PlaceholderAPI, LuckPerms, WorldEdit, FastAsyncWorldEdit, and Geyser remain optional and are not hard dependencies.
Tab rendering and animation fixes
The tab renderer now separates fast animation frames from slower statistic refreshes. Animated text can therefore keep moving smoothly without repeatedly recalculating RAM, ping, prefixes, or other comparatively expensive values.
Cross-platform ownership tracking was corrected for servers that normalize legacy text when a header or footer is applied. NeoTab stores the server's actual read-back representation and compares normalized formatting semantics, preventing Spigot and CraftBukkit from treating NeoTab's own output as foreign ownership. This fixes frozen tab names, RAM displays, and styles while preserving Paper behavior.
Animations received several correctness improvements:
- Rainbow and gradient effects have more visible movement between frames.
- Static endpoint handling no longer collapses an animated transition incorrectly.
- Emoji, surrogate pairs, combining marks, zero-width-joiner sequences, flags, and legacy formatting codes are kept intact.
- Header and footer ownership are completely separate, so another plugin can control one without disabling NeoTab's other section.
- LuckPerms player-name rendering uses a short cache with targeted invalidation instead of repeating the same lookup every animation frame.
- Join and quit refreshes are batched to at most one refresh operation per server tick.
MiniMessage remains NeoTab's internal parser. RGB colors, gradients, and standard decorations survive the string-based Bukkit boundaries. Interactive click events, hover events, insertion events, and custom fonts cannot be represented by those APIs and are therefore not preserved in player-list output, ActionBars, GUIs, item text, or command messages. NeoTab's defaults do not depend on those component-only features.
Scoreboard correctness and performance
Scoreboard rendering now caches static templates, animation frames, and values that are shared during a render pass. PlaceholderAPI is only invoked when text contains an actual %placeholder%, reducing unnecessary work on ordinary lines.
Additional fixes include:
- Animated scoreboard titles and all animation styles now update consistently across supported platforms.
- The minimum scoreboard update interval remains one tick for configurations that intentionally request it.
- Startup and reload warnings explain the performance context of unusually aggressive intervals.
- Scoreboard title and line limits are enforced without splitting Unicode sequences or formatting codes.
- Titles are limited to 128 UTF-16 units and lines to 64 UTF-16 units at the Bukkit boundary.
- Delayed join tasks are tracked and cancelled when a player disables the scoreboard, quits, the plugin reloads, or the plugin disables.
- External scoreboard ownership remains conservative: NeoTab will not overwrite a foreign objective or team.
- GUI scoreboard access now requires both the base GUI permission and the relevant child permission.
Regions and movement handling
Region profiles use an incremental spatial index rather than repeatedly scanning every configured region. Player movement checks only the relevant indexed chunks, while oversized regions are handled separately with explicit safeguards.
To prevent scheduler buildup, region changes are debounced per player and each player can have at most one pending application task. Movement handling now observes the final, non-cancelled destination at MONITOR priority, and respawns trigger a fresh region calculation.
The safety limits are:
- Up to 512 loaded regions.
- Up to 131,072 indexed chunk references.
- Up to 64 oversized regions outside the regular chunk index.
- The full vanilla world-border range remains valid for region coordinates.
/tab region pos1 and /tab region pos2 now report success only when the selection operation actually succeeds.
ActionBar, GUI, visibility, and advancement fixes
- Identical ActionBar output is deduplicated before sending.
- Reflection and fallback strategies are resolved once and cached rather than rediscovered per message.
- Random messages without explicit formatting receive NeoTab's active palette.
- Existing MiniMessage or legacy colors are preserved, and ordinary text such as
<3is no longer mistaken for a MiniMessage tag. - Persistent timer text now requires
neotab.timer.admin. - All NeoTab inventories share a dedicated
NeoTabInventoryHolder, making GUI lifecycle and click ownership reliable. - Nearest-player calculations respect
viewer.canSee(candidate), preventing vanished players from leaking through the feature. - Advancement counting reconciles grant, revoke, and re-grant transitions instead of permanently overcounting.
Safe reloads and configuration writes
Reload now waits for outstanding asynchronous YAML writes without blocking the server thread. Configuration-changing actions are locked during that short barrier so an older write cannot silently overwrite newly loaded state.
Writes retain their ordering across NeoTab YAML files, and shutdown allows up to three seconds for the writer to finish. Existing configurations remain backward compatible: missing settings use defaults and existing user values are not overwritten.
Anonymous metrics
NeoTab uses the official bStats Bukkit library 3.2.1, shaded and relocated into NeoTab's private namespace. Metrics initialize at most once, never block plugin startup, and failures are only reported in debug mode. Server owners can disable NeoTab metrics with:
metrics:
enabled: falsebStats can also be disabled globally in plugins/bStats/config.yml.
Standard bStats data covers server count, player count, Minecraft and plugin versions, Java version, operating system, and server software. NeoTab does not duplicate those standard values. Its custom charts contain only these normalized states:
configured_languagescoreboard_enabledheader_enabledfooter_enabledram_display_enabledping_display_enabledaverage_display_enabledafk_feature_enabledupdate_checker_enabledluckperms_statusplaceholderapi_statusgeyser_statusserver_platformanimation_count
NeoTab does not collect IP addresses, ports, server names, MOTDs, player names or UUIDs, chat messages, permission or group names, tab/header/footer or scoreboard contents, paths, complete configuration values, world names, secrets, tokens, or webhooks.
Validation performed
- Gradle compilation, unit tests, and the platform compatibility gate pass on Java 21.
- 46 tests across 7 suites cover rendering helpers, metrics defaults, platform detection, GUI lifecycle, visibility, scoreboard permissions, asynchronous services, and region behavior.
- The output JAR is checked for relocated bStats, Adventure, MiniMessage, and Gson classes.
- The JAR contains no bundled Bukkit, Spigot, Paper, LuckPerms, PlaceholderAPI, or unrelocated
org.bstats/net.kyoriclasses. - The shared JAR was previously started on a nine-server matrix: Paper, Spigot, and CraftBukkit at Minecraft
1.20.6,1.21.11, and26.2. - Each matrix server reached its ready state and passed RCON checks for plugin version, plugin listing, reload, random-message listing, and region listing before a clean stop.
- The latest rendering and lifecycle fixes were additionally deployed to the Paper lobby plus Spigot and CraftBukkit
1.20.6test servers. Plugin enable, reload, permission, and basic command smoke checks completed without NeoTab errors. - A two-hour diagnostic run exercised 20 active clients with movement, jumping, sprinting, world routing, and 24,450 reconnects. It recorded 24,470 matching server joins and leaves, zero driver errors, zero premature disconnects, 240 fresh Paper/JVM samples, approximately 20 TPS, and no old-generation collection. The scenario is intentionally not presented as a validated 5-reconnects-per-second benchmark: the finite 20-client pool and reconnect latency produced about 3.4 reconnects per second, below the profiler's required schedule. Its measurements are supporting diagnostics rather than a formal performance pass.
Automated checks do not replace visual testing with a connected Minecraft client. Feedback about animated tab and scoreboard rendering, interoperability with other sidebar/tab plugins, GUIs, and ActionBar presentation remains welcome.
Known limitations and watch points
- NeoTab conservatively yields when it finds foreign scoreboard teams or objectives, even if the sidebar slot appears unused. This avoids corrupting another plugin's state but may prevent NeoTab's scoreboard from appearing in some combinations.
- Nearest-player lookup can approach quadratic work in unusually dense groups with many participating players.
- The random-message list currently has no configured maximum size.
- If an atomic YAML save exceeds the three-second shutdown allowance, the daemon writer may finish after the timeout.
- Region files exceeding safety limits load only the accepted subset and emit warnings.
- Future CraftBukkit internals may require an ActionBar bridge adjustment; the vanilla command fallback remains available.
Compatibility and upgrade notes
- Server platforms: Paper, Spigot, and CraftBukkit.
- Minecraft:
1.20.6+. - Java: 21 or newer.
- Existing NeoTab configurations are migrated through missing-value defaults without replacing user-defined values.
Back up the existing plugins/NeoTab folder, replace the old JAR, and perform a full server restart. Please include the server platform, Minecraft version, NeoTab log excerpt, and relevant configuration section when reporting an issue, while removing any private server information.