Everything needed to build, test and run this port, with Linux treated as a first-class target rather than an afterthought.
The repository was developed on macOS on Apple silicon. Every claim below is marked with how it was established. Where something could not be verified from a macOS machine it says so rather than guessing, because a documented uncertainty costs a newcomer minutes and a confident wrong instruction costs them a day.
- Verified here means it was run on the development machine (macOS 27, aarch64) and the output was read.
- Verified by inspection means the artefact itself was fetched or read and checked, without executing it on the target platform.
- Unverified means it follows from the tool's own documentation and nobody has run it on Linux.
- The JDK
- Maven
- The source boundary
- The Warcraft II game data
- The Opus test vectors
- Building and testing
- Reading a test run: skips are not passes
- Display, audio and headless
- Running the game
- Certifying a multiplayer flight record
- Continuous integration
- Packaging
- Linux-specific risks not yet exercised
The project is pinned to a specific JetBrains Runtime 25 SDK build:
jbrsdk-25.0.2-linux-x64-b329.117 and its siblings, from JetBrains release tag
jbr-release-25.0.2b329.117. The pin lives in one file,
scripts/jbr/jbr-25.env, as a URL and an SHA-512
per platform.
It is an SDK (jbrsdk-, not jbr-), which matters: the release lane needs
jpackage and jlink, and a plain JBR runtime does not ship them.
scripts/jbr/with-jbr-25.sh is a three-line wrapper. It runs
install-jbr-25.sh, exports the resulting JAVA_HOME and prepends its bin
to PATH, then execs whatever you gave it. All the work is in
scripts/jbr/lib-jbr-25.sh, and jbr_detect_platform there handles
linux:x64, linux:aarch64, macos:x64, macos:aarch64 and windows:x64.
Only macos:* gets the Contents/Home suffix; a Linux install is used as
extracted.
So on Linux the command is the same as on macOS:
scripts/jbr/with-jbr-25.sh mvn -DskipTests install
scripts/run-tests.shVerified by inspection, and thoroughly: the Linux x64 archive was
downloaded from the pinned URL on this machine (249,917,983 bytes), its
SHA-512 was computed and matched CHONK_JBR_LINUX_X64_SHA512 exactly, the
tarball was confirmed to contain bin/java, bin/jlink and bin/jpackage,
and its release file was read:
JAVA_VERSION="25.0.2"
IMPLEMENTOR="JetBrains s.r.o."
JAVA_RUNTIME_VERSION="25.0.2+10-b329.117"
Those are the three strings jbr_verify_home checks, and they match
CHONK_JBR_DISPLAY_VERSION, CHONK_JBR_VENDOR_EXPECTED and
CHONK_JBR_RUNTIME_VERSION. The install path on Linux is therefore expected to
work end to end; what was not done is execute a Linux ELF, which cannot be done
from macOS.
The linux-aarch64 URL was confirmed to resolve and serve 247,862,041 bytes.
Its checksum was not verified.
install-jbr-25.sh first looks for an already-good JDK, in this order:
$CHONK_JBR_HOME, if set~/Documents/jdks/jbrsdk-25.0.2-<platform>-b329.117~/Documents/jdk/jbrsdk-25.0.2-<platform>-b329.117$CHONK_JBR_INSTALL_ROOT, default~/.chonk/jdks, same directory name
A candidate only counts if running its java -XshowSettings:properties reports
the pinned vendor, version and runtime version. Otherwise the archive is
downloaded to ~/.chonk/jdks/downloads, checksummed, and extracted. Override
the roots with CHONK_JBR_INSTALL_ROOT and CHONK_JBR_DOWNLOAD_ROOT.
The download is roughly 250 MB and happens once.
bash, curl, tar, and either shasum or sha512sum. The library prefers
shasum and falls back to sha512sum, which is the one Linux normally has, so
no coreutils extras are required. Verified by inspection of
jbr_hash_file.
scripts/jbr/with-jbr-25.sh scripts/jbr/assert-jbr-25.shPrints the release tag, vendor, java.version, java.runtime.version,
java.home and the jpackage version, and exits non-zero if any of the first
three is not the pin. Run this first when a build behaves oddly. Verified
here on macOS aarch64.
Nothing in the poms requires JetBrains specifically; maven.compiler.release
is 25 and that is the hard requirement. Any JDK 25 will compile and test the
project. The pin exists so that this repository, ChonkBlocker and Seven Days to
Tomorrow fail in the same way on the same machine, and so that the packaging
lane has a known jpackage. If you set JAVA_HOME to some other JDK 25 and
call mvn directly, the build works and you have simply opted out of the pin.
The release scripts still call with-jbr-25.sh explicitly and will fetch the
pinned SDK regardless.
Maven 3.9+ on PATH, installed by you. Nothing in the repository installs it.
Verified here with Maven 3.9.9. On Debian/Ubuntu, apt install maven gives
a recent enough version on current releases; check with mvn -v if in doubt.
Do not rely on the java your distribution's Maven package pulls in. Always go
through scripts/jbr/with-jbr-25.sh, or set JAVA_HOME yourself.
The player runtime does not read an external source checkout or separately installed content tree. Its complete input contract is a game JAR plus one authenticated chonkpack.
Historical GPL source remains available through repository history and the
provenance described in README, but no sibling checkout, source-directory
property, interpreter, or content tree participates in a build or test. Run
python3 scripts/check-source-boundary.py and
python3 scripts/check-native-runtime.py to verify that invariant.
Warcraft II data is not in this repository and never will be. The port reads your own 1995 installation, either directly or through an asset pack built from it.
Point at the installation with -Dwc2.install.dir=/path/to/Warcraft or the
environment variable WC2_INSTALL_DIR. Either the game directory or its DATA
subdirectory works. This is what the test suite uses and it is not going
away. Everything below about archives, disc images and the cache applies to
it unchanged.
Players start with scripts/run-launcher.sh in a checkout, or ChonkCraft in
a native package. The first screen requires a graphics pack before Play is
enabled. Its graphics selector opens the ChonkPack manager. Drop an installed
directory, mounted physical CD, ZIP, ISO or Toast
image, BIN/CUE or IMG/CCD image, StuffIt, 7z, RAR or tar archive there, or use
the file chooser. The same manager selects, exports and deletes completed
packs. Cooked ISO9660, raw 2352-byte sectors and classic Mac HFS data tracks
are read directly. 7-Zip and unar are accepted as fallbacks for archive
containers. The launcher reports each normalization step, builds through the
same verifier as scripts/build-asset-pack.sh, records source-version and
checksum provenance, and installs the pack only after verification passes.
The managed library defaults to ~/.chonkcraft. Set chonkcraft.home or
CHONKCRAFT_HOME to isolate it for testing. Packs and game versions are kept
separately, so updating game code does not rebuild or modify a pack.
A pack is one file holding everything the game draws, plays and reads, in a modern encoding. It is what a player gets, and it is what the game loads when one is available.
scripts/build-asset-pack.sh # writes chonkcraft.chonkpack
scripts/build-asset-pack.sh --out /tmp/wc2.chonkpack # somewhere else
CHONKCRAFT_ASSET_PACK=/tmp/wc2.chonkpack scripts/run-game.shAssetSource.fromEnvironment() checks -Dchonkcraft.pack, then
CHONKCRAFT_ASSET_PACK, then a chonkcraft.chonkpack sitting beside the installation,
and falls back to reading the installation directly. So a machine with only
WC2_INSTALL_DIR set behaves exactly as it did before this existed.
Building a pack takes about forty seconds and verifies itself: every one of its 1,355 assets is read back out of the finished file, rebuilt into the archive entry the engine expects, and compared against what the installation produced. On the reference installation with both discs, 1.0 GB of 1995 data becomes a 157 MB pack. The format is specified in asset-pack-format.md.
Two things to know when working on the pack path:
-
The extractor cannot see the game.
extractor/IsolationTestfails the build on any mention ofengine,desktoporruntimein the module. If the extractor needs something the game has, it belongs inassetpack/ordata/. -
PackParityTestis the end-to-end proof and it needs a pack, which the suite cannot build for itself. It skips unless you give it one:scripts/build-asset-pack.sh --out /tmp/wc2.chonkpack mvn -pl engine test -Dtest=PackParityTest \ -Dchonkcraft.pack=/tmp/wc2.chonkpack -Dwc2.install.dir="$WC2_INSTALL_DIR"
Warcraft2Install (in
data/src/main/java/net/chonkbase/chonkcraft/data/source/Warcraft2Install.java)
treats maindat.war as the marker. Without it, fromEnvironment() returns
null and everything that needs game data skips.
That class is package-private, and deliberately: it is the only thing in
the port that knows an installation is a directory, and
InstallSource
in the same package is the only class that can construct or name one. Callers
outside data.source -- the extractor, the tests, the game -- go through
InstallSource.fromEnvironment(), which reads the same two configuration names
in the same order. The engine and the desktop layer may not name it at all;
see CONTRIBUTING.md and the NoInstallDirectoryTest in each of those modules.
The archives it knows how to find, by PC name and by the Mac release's different name:
| PC name | Mac name | Holds |
|---|---|---|
maindat.war |
War Data |
Graphics, tilesets, fonts, cursors. Required |
strdat.war |
War Strings |
The name table. Required |
rezdat.war |
War Resources |
Interface art. Also how the expansion is detected, by file size |
sfxdat.sud |
War Sounds |
Sound effects |
snddat.war |
War Music |
Music. Not present in a DOS hard-disk install |
muddat.cud |
War Movies |
Cutscenes. Not present in a DOS hard-disk install |
.PUD maps sit loose in the install root.
Resolution walks the root, then DATA/, then data/, and matches names
case-insensitively by explicit code (findIgnoringCase). This matters on Linux
far more than on macOS: a DOS install has DATA/MAINDAT.WAR in upper case,
ext4 is case-sensitive, and macOS's default APFS volume is not. The
install-locating code is careful about this and CI exercises the boundary on a
case-sensitive filesystem. See
Linux-specific risks.
The DOS release installs only part of itself. The music archive and the video
archive stay on the disc. If snddat.war or muddat.cud is not on disk,
Warcraft2Install.fromDisc scans the install root for *.img, *.iso or
*.bin, reads the raw-sector CloneCD image and its ISO 9660 filesystem
directly, and extracts the archive to:
<install root>/chonkcraft-cache/MUDDAT.CUD
<install root>/chonkcraft-cache/SNDDAT.WAR
So the install directory must be writable if you want music or cutscenes
from a DOS install with a disc image beside it. A read-only mount, or a copy
under /usr/share, will silently give you a game without either. This is not
Linux-specific, but a Linux user is more likely to mount game data read-only.
The reference installation used here looks like this:
WarcrafD/
ALAMO.PUD CHANNEL.PUD DEATH.PUD ... the shipped skirmish maps
DATA/
MAINDAT.WAR REZDAT.WAR SFXDAT.SUD STRDAT.WAR
cd/
WC2TOD.img WC2TOD.cue WC2BTDP.img ... disc images
chonkcraft-cache/
MUDDAT.CUD SNDDAT.WAR extracted from the images
The assetpack module ships a pure-Java Opus decoder and encoder, and the
claim it rests on is not "it sounds right" but "every pure-CELT packet in the
official RFC 6716 test vectors decodes bit-exact". That claim is checked by 21
tests, and those 21 skip without the vectors, which are a 20 MB download that
this repository does not carry:
curl -O https://opus-codec.org/static/testvectors/opus_testvectors.tar.gz
tar xzf opus_testvectors.tar.gz
curl -O https://www.rfc-editor.org/rfc/rfc6716.txt
scripts/run-tests.sh -Dopus.testvectors="$PWD/opus_testvectors" \
-Dopus.rfc="$PWD/rfc6716.txt"Ten allocation-table tests also read the public RFC text. Put rfc6716.txt
beside the vectors directory as above, or set -Dopus.rfc / OPUS_RFC.
This is the fourth external input, and the one most worth configuring per megabyte: without it a codec that decodes the game's audio wrongly still gets a green build.
There is a fifth, -Dopus.music, and it is deliberately not asked for. Five
tests in CeltEncoderTest -- determinism, misalignment, real-music round trip,
ffmpeg interop and achieved bitrate -- want a directory of 16-bit WAV files to
encode. A rip of the red book audio is a heavier ask than the other four
inputs, so those five are recorded as expected skips even in the full
profile. Point -Dopus.music at a directory of WAVs and they run.
scripts/jbr/with-jbr-25.sh mvn -DskipTests install # compile everything
scripts/run-tests.sh # the full reactor test runscripts/run-tests.sh forwards its arguments to Maven and then runs test, on
the pinned JDK. Configure the authenticated player input once:
export CHONKCRAFT_ASSET_PACK=/path/to/warcraft-ii-bne.chonkpack
scripts/run-tests.shRaw WC2_INSTALL_DIR remains an extractor/development input, not a shipped-game
input. The game and 18-lane playability certification never read a ChonkCraft
source directory.
-Djava.awt.headless=true is often written out in commands and audit notes. It
is redundant: the root pom already puts it in the Surefire argLine. Passing
it does no harm and makes the intent visible.
Tests needing retail assets still use JUnit assumptions, so an ordinary Maven
run can be green with those tests skipped. Inspect the Surefire summaries. For
the player contract, run scripts/run-bne-playability-gate.py: all 18 selected
player/referee lanes must pass, any skip makes the receipt fail, and the runner
forces the retired ChonkCraft source property to a nonexistent path.
Almost everything, including the rendering tests. Twenty-odd tests in desktop
and engine paint into a BufferedImage and assert on pixels --
FogRenderingTest, MenuRenderSweepTest, InfoPanelRenderTest,
SidePanelVisualTest, MissileRenderingTest, ImpactRenderingTest and the
rest. Java2D's software pipeline handles all of it headless. MenuRenderSweepTest
additionally writes PNGs to desktop/target/menu-qa as diagnostics for a human
to look at; they are not what it asserts on.
Rendering performance documents the repeatable paint/allocation benchmark, display checks at 1x and 2x scale, and a bounded memory stress run. Software and device pipelines need separate measurements.
Two places in main code guard the calls that genuinely throw without a display
(GameCursors asking for a custom cursor size, SidePanel adding an
AWTEventListener), so headless runs do not trip over them.
Only real JFrame work: AppWindowTest and part of PlatformFullscreenTest.
On Linux you can run them:
xvfb-run -a scripts/run-tests.sh -Dsurefire.argLine= ...The empty -Dsurefire.argLine= is needed because the root pom hard-codes
-Djava.awt.headless=true into the argLine, and the tests skip on the
GraphicsEnvironment.isHeadless() check rather than on the presence of a
display. Unverified: this follows from reading the pom and the tests, and
has not been run.
Requires xvfb (apt install xvfb). If you have a real desktop session, the
same works without xvfb-run.
No test opens an audio device. The runtime's audio tests drive a fake
device rather than AudioSystem; the MIDI tests use javax.sound.midi only to
parse and inspect sequences. So a Linux box with no sound card, no ALSA and no
PulseAudio runs the full suite.
The game does want audio, and fails soft without it:
JavaSoundPcmSinkacquires the output line on a single daemon lane with a deadline. A missing, failing or stalled device leaves the mixer running and accepting frames into silence, rather than hanging startup.MusicPlayerwrapsMidiSystem.getSequencer()in atry/catch; no sequencer means no music and a running game.
On Linux, expect the default Java Sound line to go through ALSA. Unverified which Linux audio stack the pinned JBR resolves to in practice, and whether PulseAudio or PipeWire needs the ALSA compatibility layer installed. If the game is silent, that is the first thing to check.
Controller support comes from libsdl4j, a JNA binding, in the vendored
runtime. SdlNativeRuntime fails soft when the native library is missing, so a
machine without SDL2 simply has no gamepad support. Keyboard and mouse do not
go through SDL.
On Debian/Ubuntu the native is libsdl2-2.0-0. Unverified on Linux.
Override the search path with SEVEN_SDL_LIBRARY_PATH or
-Dseven.sdl.library.path.
Java2DPipeline sets rendering-backend system properties before AWT
initialises, chosen by operating system:
| OS | Default |
|---|---|
| macOS | Metal |
| Windows | Direct3D |
| Linux, BSD | OpenGL |
| anything else | software |
Override with SEVEN_JAVA2D_PIPELINE=metal|opengl|xrender|d3d|software or
-Dseven.java2d.pipeline=. If the game renders wrongly or crashes in the
driver on Linux, try xrender and then software before suspecting the port.
The defaults are verified by inspection of Java2DPipeline.defaultForOs.
OpenGL rendering and memory stress have also been exercised on Linux/Asahi;
see the rendering measurements.
The AppImage entry point selects native Wayland with software Java2D when
WAYLAND_DISPLAY names an existing socket and the bundled runtime includes
WLToolkit. The selection reaches both the launcher and its child game.
An X11 session, an unavailable Wayland socket, or an explicit JVM graphics
override keeps the existing Java graphics selection. Explicit
SEVEN_JAVA2D_PIPELINE=opengl also keeps the X11 path.
Use ChonkCraft-<version>-linux-<arch>.AppImage --xwayland to choose Xwayland,
or --wayland to require native Wayland. The equivalent persistent choices
are CHONKCRAFT_DISPLAY=x11 and CHONKCRAFT_DISPLAY=wayland; the default is
auto. Put the display switch before launcher arguments such as --launch.
On the tested M3 system, Java's Vulkan renderer delayed the event thread during
presentation; software rendering kept native Wayland input responsive.
PlatformFullscreen.detectStrategy gives macOS the MAC_EAWT strategy and
everything else BORDERLESS_BOUNDS, which is plain AWT. Linux therefore
needs none of the macOS --add-opens=java.desktop/com.apple.eawt=ALL-UNNAMED
plumbing, and scripts/run-game.sh already adds that flag only when uname -s
is Darwin. Force borderless anywhere with
-Dseven.fullscreen.force.borderless=true.
The AppImage can use the bundled JBR's native Wayland toolkit, while direct game launches retain the JVM's toolkit selection. Native Wayland map rendering, resizing, and menu input at 2x scale have been exercised on ChonkStep. Borderless fullscreen across other compositors remains unverified.
export CHONKCRAFT_ASSET_PACK=/path/to/warcraft-ii-bne.chonkpack
scripts/run-launcher.sh
scripts/run-game.sh ALAMO.PUDrun-launcher.sh installs the current verified game JAR and starts it with the
selected pack. run-game.sh is the direct developer shortcut. Neither command
reads executable scripts, a source checkout or a separate content archive. Set
CHONKCRAFT_SKIP_BUILD=1 to reuse the last build.
Press Command-Shift-E during play on macOS. You do not need the Fn key;
this shortcut uses the letter E, not an F-row key. On Windows or Linux use
Ctrl-Shift-E. The game prints a visible evidence saved confirmation and
writes one directory under:
~/.chonkcraft/evidence/playtest-<timestamp>-c<cycle>/
The directory contains screen.png, a resumable state.sav.gz, and
evidence.json. The JSON records the map, mission, cycle, camera, selected and
nearby units, orders, AI behavior, targets, projectile position/frame/facing,
both RNG streams, and nearby visual tile codes plus simulation flags. Capture
it immediately when a projectile flips, a unit appears idle, or a ship seems
to enter shore. Ordinary saves remain small and unchanged.
The map/window/music flags remain -Dchonkcraft.map, -Dchonkcraft.window and
-Dchonkcraft.music for settings compatibility; those names do not identify a
source-tree dependency.
An ordinary multiplayer match keeps a bounded local recording under
~/.chonkcraft/recordings. It never uploads the bundle or includes chat. To
authenticate and deterministically replay one recording against the current
checkout and a verified pack:
scripts/check-bne-recording.sh \
~/.chonkcraft/recordings/game-YYYYMMDD-HHMMSS-map \
/path/to/warcraft-ii-bne.chonkpackThe wrapper builds the referee with the pinned JBR, validates the manifest and
all sealed artifact hashes, reconstructs the exact player table and initial
world, decodes every 17-byte command, and compares the synchronization hash
after every released lockstep batch. It prints one JSON report and exits
non-zero for an unsafe bundle, incomplete evidence identity, unsupported hash
schema, wrong initial world, or the first replay divergence. A complete: true
report requires all of these:
- current schema-2 artifacts and all 16 player slots are sealed;
- the producing game JAR is bound to an installed source revision;
- every recorded batch replays exactly; and
- the referee is itself bound to a verified installed release or a clean Git revision. A dirty checkout remains identified by its referee JAR SHA-256 but cannot issue a complete certificate.
Schema-1 recordings predate those identities. The reader still authenticates
their present map, save and stream bytes and can report a bounded exact replay
prefix, but it labels their inferred roster legacy-inferred-noncertifying and
can never turn them into current evidence.
Moved to its own document: ci.md. Both workflows, the skip gate, the self-hosted runner and its data mounts, how to debug a red run and how to re-baseline the counts.
The hosted, data-free job runs on every push and pull request. A private
authenticated job runs only for master pushes or a maintainer's manual
dispatch, using a read-only copy of the installation and authenticated pack.
It asserts 1,419 skips, so 1,666 tests actually run without exposing licensed
media to public pull-request code. The authenticated classic lane asserts 31
skips out of at least 3,085 tests; a development machine with the three private
playtest-save referees installed uses full-with-playtest-saves and asserts 28.
An exact BNE source plus matching pack and those saves uses
full-bne-with-playtest-saves and asserts 30 release-format-specific skips.
Tests backed
by retail sequences deliberately join the hosted lane's skip inventory while
running on the private authenticated runner.
Native packages bundle a trimmed JetBrains Runtime, so a player needs no Java. They never include game data.
scripts/release/build-macos-app.sh --dmg # macOS
scripts/release/build-linux-package.sh # app image only
scripts/release/install-pinned-appimagetool.sh /tmp/appimagetool
scripts/release/build-linux-appimage.sh /tmp/appimagetool # portable AppImage
scripts/release/build-windows-package.sh --msi # Windows
scripts/release/build-update-assets.sh # game jar and hash catalogEach platform's script refuses to run anywhere else -- jpackage builds for the
platform it runs on, and there is no cross-compiling. The Release Builds
GitHub Actions workflow runs all three; it is workflow_dispatch only, on
purpose, because the artefacts are large.
The CI macOS lane runs on the shared chonk-mac-arm64 Apple-silicon runner and
requires a real Developer ID identity plus Apple notarization credentials. It
does not fall back to an ad-hoc release. Use the same MAC_CERTIFICATE_* and
App Store Connect API-key secrets as ChonkBlocker, or the documented
APPLE_ID/APPLE_APP_PASSWORD/APPLE_TEAM_ID fallback. The resulting DMG is
signed, notarized, stapled, Gatekeeper-assessed and accompanied by a SHA-256
file. The optional publish_macos_release workflow input attaches both files
to v<version>; leave it disabled for an Actions-only test artifact.
CHONKCRAFT_VERSION stamps the public version, currently 0.1.1-beta11.
jpackage receives a private nonzero seed to satisfy its validation; before
signing, the bundle metadata is replaced with the honest 0.1.0 marketing
version and an Actions run-number build value.
The update script writes a signed latest.properties plus a content-addressed
JAR under desktop/target/dist/update. The launcher resolves the JAR URL
relative to the catalog, checks its mandatory byte count and SHA-256, and only
then makes it the one current game.
Smoke-test the real macOS bundle, including its bundled Java executable, launcher render, pack selection, child game process and one gameplay frame:
CHONKCRAFT_ASSET_PACK=/path/to/chonkcraft.chonkpack \
scripts/release/verify-macos-app.sh desktop/target/dist/macos/ChonkCraft.appThe Linux release is a Type-2 x86-64 AppImage. The local build scripts also
support aarch64, producing a linux-arm64.AppImage with the host's bundled JBR.
CI downloads the same
checksum-pinned appimagetool release used by the sister project, inspects the
SquashFS payload, and launches it with APPIMAGE_EXTRACT_AND_RUN=1 so the proof
does not depend on FUSE being available on the build host.
Run scripts/jbr/with-jbr-25.sh python3 scripts/release/test_appimage_entry.py to check display selection,
fallbacks, and propagation to the child process. Existing AppImage downloads
need to be replaced with a build containing this entry point; the signed game
JAR updater cannot replace the enclosing AppImage or its launcher script.
Written down so the next person knows where to look first, rather than discovering them one at a time.
-
Case sensitivity.Verified continuously. The hosted Linux job asserts a case-sensitive filesystem and exercises the data-free path. The dedicated case-sensitivity script copies only the retail installation onto a case-sensitive APFS volume and runs the native data tests. That covers archive names and resource paths without any external source tree, including the DOS-uppercaseDATA/MAINDAT.WARlayout.Warcraft2Install's deliberate case-insensitive lookup and theLocale.ROOTnormalisation in the.PUDand disc-image scans do hold up.Reproduce with
scripts/ci/check-case-sensitivity.sh. Note the limit of the claim: this verifies filesystem case sensitivity, not Linux. Items 3, 4 and 5 below are untouched by it. If assets still fail to load on Linux and load on macOS,Mainprints unresolved asset paths at startup, which is the fastest way to see it. -
Partly closed. Both CI jobs run headless withoutjava.awt.headlessand the seven display tests.xvfband the seven skip as designed, which is the documented steady state; what remains unrun is thexvfb-runrecipe that would make them execute. Related and now known: a container with no fonts installed renders no text at all, which is not a skip but a silent blank -- see ci.md. -
Audio stack. Which of ALSA, PulseAudio or PipeWire the pinned JBR's Java Sound resolves to, and whether a stalled device path behaves as the sink's recovery policy expects.
-
OpenGL Java2D pipeline. The Linux default. Untested on real drivers.
-
jpackagedeb/rpm host tooling. See above. -
scripts/sync-runtime.shneedsrsyncand a checkout ofseven-days-to-tomorrowbeside this one; setSEVEN_DAYS_DIR. It is a diff tool for keepingruntime/source-identical to upstream, not part of the build. -
No CI runs the test suite.Closed..github/workflows/tests.ymlnow runs the suite on Linux on every push, and gates on the skip count rather than on Maven's exit code. See ci.md.Verified, 2026-07-27, and the first runs were findings rather than a clean bill. The hosted job had been red on master for nine consecutive pushes on the same step: nine assetpack tests skip on Linux for want of
ffmpegandflac, which the development Mac has from Homebrew. Both jobs install them now.A second job was added on a self-hosted runner that has the game data, so the
fullprofile is asserted too: 23 of 2,421 tests skip, so 2,398 tests actually run. See the self-hosted runner.