Hybrid Runtimes

A hybrid runtime loads Bukkit plugins and mods (Forge, NeoForge or Fabric) in the same server. VoxelBench runs on it as an ordinary plugin. It recognises the main hybrids by name and changes a few things when it does.

This page explains what changes, and how to set up a hybrid server for reliable results. For the other server types, see Compatibility.

Recognised Runtimes

VoxelBench recognises Mohist, Arclight, Banner, NeoTenet, Magma, CatServer and Cardboard. It identifies them from the classes the server provides (and, as a last resort, from the server's version string) before it looks for Paper or Spigot: a hybrid often presents itself as Paper or Spigot, and would otherwise be reported as one.

Recognised does not mean tested: see Continuous Integration for the runtimes that are actually started with VoxelBench.

A Bukkit-on-mod-loader server that is not in this list is reported as the server it presents itself as (usually Paper or Spigot), and none of the hybrid handling below applies to it. Its mods are still listed in reports (see Mods in Reports).

At Startup

VoxelBench logs the detected runtime when it starts. On a recognised hybrid, a second line follows:

[VoxelBench] Runtime: Mohist (MC 1.20.1-R0.1-SNAPSHOT)
[VoxelBench]   โš  Hybrid runtime detected โ€” Bukkit-on-mod-loader. Most tests work but Paper-only optimisations are skipped and modded BlockData may interact unpredictably with block-placing tests.

The version in brackets is the Bukkit version the server reports. If this line names Paper or Spigot on your hybrid, the runtime was not recognised.

The VoxelBench Server Compatibility block, also logged at startup, gives the same server type and lists the server APIs that are available (native TPS and MSPT, chunk tickets, force-loaded chunks). /bench info server shows the type on its Type line.

What Changes

Benchmark Worlds

On Forge and NeoForge hybrids, asking the server for a flat world can produce normal terrain, because the mod loader takes over world generation. So on a recognised hybrid, every world VoxelBench creates, with /bench world create or as a temporary world for a run, is generated by VoxelBench itself: bedrock, two layers of dirt and a layer of grass (the classic superflat layers), with no structures. Other servers get the vanilla flat generator with the same layers.

The server may still report such a world as NORMAL. VoxelBench recognises its own generator, so neither /bench start nor its pre-flight check warns that the world is not flat. Each creation is logged with what the server actually applied:

[VoxelBench] Bench world 'voxelbench_bench' created โ€” type=NORMAL (asked FLAT), seed=โ€ฆ (asked โ€ฆ), generator=FlatChunkGenerator.

If the server hands back a world with no spawn point, or whose spawn chunk does not load, VoxelBench deletes it rather than run in it. /bench world create then reports that it could not create the world. A full run that needed a temporary world (/bench start, /bench stresslimit, a custom profile) falls back to the server's main world, and the console says falling back to default world. A /bench test that writes to the world is refused instead (see Benchmarks). Pinning a world avoids both (see Recommended Setup).

Paper and Folia Features

VoxelBench never assumes a hybrid is Paper. Each feature that relies on Paper (native dialogs, the tick event used for tick durations, asynchronous chunk loading and teleports, Paper's TPS and MSPT) is looked up on its own and used only if the server provides it. Otherwise VoxelBench does what it does on Spigot, for example measuring TPS and MSPT itself. This is what the startup message calls skipping Paper-only optimisations. The Folia code path is never used on a hybrid: tests are scheduled on the main thread, as on Spigot and Paper.

Missing Server Methods

If a test calls a server method the hybrid does not implement, that test alone fails, with an error that starts with HybridCompat: (for example HybridCompat: NoSuchMethodError: โ€ฆ). The console logs Runtime API mismatch in <test> (likely a hybrid-server compatibility issue), and the rest of the run goes on.

Mods in Reports

Every report says whether the server is a recognised hybrid, which mod loader VoxelBench found (forge, neoforge, fabric, or none) and how many mods are loaded. The list of mods (id, name and version) is included too, unless anonymization is FULL (see Privacy).

In the GUI, Server Information โ†’ Minecraft Server โ†’ Mods shows the loader and lists the mods.

What Stays the Same

Commands, permissions, config.yml, the test catalogue, custom profiles and the extension API work as on any other server. Reports have the same format, plus the fields above, and are sent to voxelbench.com as usual.

  1. Check the detection. The Runtime: line must name your hybrid.
  2. Create a benchmark world and pin it:
    /bench world create bench
    /bench world set voxelbench_bench
    
    Tests then build their zones on VoxelBench's flat terrain, away from modded terrain and structures, and runs no longer depend on the hybrid accepting a new temporary world every time. See Benchmark Worlds. /bench world set writes the pin to config.yml:
    benchmark:
      target-world: "voxelbench_bench"
      auto-temp-world: true
    
  3. Leave auto-temp-world on (the default). It only applies when no world is pinned, or when the pinned world is not loaded. Turned off, those runs go to the main world instead (see Configuration).
  4. Restarts are handled. At startup, VoxelBench loads again every voxelbench_<name> world that is on disk but not loaded, with the same generator, so the pin survives a restart even without a world manager. This happens on every server type. The log lists them (Auto-loaded 1 persistent benchmark world(s) from disk:), with a ! and the reason for any that could not be loaded.
  5. Compare like with like. Mods add work of their own: compare a hybrid's results with runs on the same runtime and the same mods.

If a benchmark world could not be loaded again, its folder stays on disk and /bench world create refuses to reuse the name, because the old chunks would mix with new terrain. /bench world delete only removes a loaded world: pick another name, or stop the server and delete the folder.

Known Limitations

  • Modded content. Mods that change world generation, dimensions, block placement or entities can interfere with the tests that place blocks or spawn entities. A pinned VoxelBench world keeps modded terrain out of the test zones, not the mods that act on every world or every entity.
  • Coverage. Hybrids are only booted in CI, never benchmarked, and behaviour varies between hybrid builds. If a test fails with HybridCompat:, report it with the runtime and its version.
  • Unloading worlds. Some hybrids refuse to unload a world. A temporary world (voxelbench_temp_<timestamp>) that could not be deleted at the end of a run is deleted the next time the server starts.
  • spark installed as a mod. The Spark integration can use it if spark's API is reachable from plugins. The startup summary then says which one it found: Spark hooked (forge-mod), neoforge-mod or fabric-mod.

Continuous Integration

The runtime-compat workflow starts hybrid servers with a development build of VoxelBench every day, and whenever the plugin's code changes:

RuntimeMinecraftServer download
Mohist1.20.1A community mirror, as MohistMC's own downloads are broken
Arclight (Forge build)1.20.1, 1.20.4Arclight's GitHub releases

Each job boots the server, checks that VoxelBench is enabled, runs bench info and bench tests list from the console, and fails on a linkage error in VoxelBench (NoSuchMethodError, NoClassDefFoundError, LinkageError) or an error while enabling it. Whether the Runtime: line names the expected hybrid is only reported as a warning. No test or benchmark is run.

These jobs do not block anything: a failure shows in the run summary but leaves the workflow green, and a server that cannot be downloaded, or crashes during its own startup, is skipped. The other recognised runtimes (Banner, NeoTenet, Magma, CatServer, Cardboard) and other versions are not started in CI.