This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Xenon is a Mindustry launcher carved out of an HMCL fork. The HMCL JavaFX UI shell (decorator, sidebar, wizard, animations, themes) is preserved verbatim; the Minecraft-specific download / launch / mod / account backends have been replaced with Mindustry equivalents under the package root determination.xenon.mindustry.*. Per-instance isolation is delivered through -Dmindustry.data.dir=<.data>, which is the same property Mindustry's official launcher honours.
Group is determination, root version is 0.1.0. Source/target is Java 17. JavaFX 17+ is required at runtime.
The project is a multi-module Gradle build (Xenon, XenonCore, XenonBoot, plus two Minecraft loader libraries under minecraft/libraries/).
./gradlew :Xenon:compileJava # fast type-check after edits
./gradlew :Xenon:run # dev launch (depends on :Xenon:jar => shadowJar)
./gradlew :Xenon:shadowJar # fat jar => Xenon/build/libs/Xenon-<ver>.jar
./gradlew :Xenon:packagePortable # JRE-less zip => Xenon/build/dist/Xenon-portable-<ver>.zip
./gradlew :Xenon:packageAll # portable zip + host-OS jpackage (.msi/.dmg/.deb/.AppImage)
./gradlew :Xenon:checkTranslations # validates I18N_*.properties bundles parity
./gradlew :Xenon:checkstyle # license header + style; runs main + test
./gradlew :XenonCore:test # all XenonCore unit tests (JUnit 5)
./gradlew :XenonCore:test --tests 'determination.xenon.util.io.NetworkUtilsTest' # single classThe default tasks are clean build. :Xenon:run honours XENON_JAVA_HOME and XENON_JAVA_OPTS (defaults to -Xmx1g).
Per AGENTS.md: when invoking gradle, set GRADLE_USER_HOME to a workspace-local .gradle-user-home directory, and use a 10-minute timeout for test tasks. Example: ./gradlew -g .gradle-user-home :XenonCore:test.
XenonCore— backend: data model, repositories, downloaders, file-format parsers, process spawn, server lifecycle. No JavaFX. The Mindustry replacements live underdetermination.xenon.mindustry.*:XenonGameRepository/MindustryVersion/VersionVariant/DataDirectoryPolicy— version registry on disk under<config>/versions/<id>/XenonLauncher/LaunchOptions—ProcessBuilderdriver, injects-Dmindustry.data.dir,-Dmindustry.player.uuid/.namemod/— local mod manager + remotemindustry-modsindex (community browser)save/,schematic/—.msavheader parser,.mschimport/export with base64 share-codescrash/— scanscrashes/*.txt+last_log.txt, highlights mod stack frames, maps variant → GitHub issue templateserver/— full dedicated-server stack:ServerInstance/ServerInstanceManager,ServerProcess,ServerConsoleSession(sealedConsoleEvent:Started/StdoutLine/StderrLine/Exited/Restarted),ServerSessionRunner(auto-restart supervisor),ServerAutoRestartPolicy,ServerConfig/ServerConfigManager,ServerMapPool,ServerModsBridge,PortChecker,{Vanilla,Be,MindustryX}ServerVersionList,ServerJarInstallerscriptagent/— ScriptAgent4Mindustry hookuuid/— replaces HMCL's account system; one nickname per UUIDdownload/MirrorDownloader— races GitHub-release mirrors (ghproxy / hub.gitmirror / kgithub / gh.api.99866) with fallback to upstream
Xenon— JavaFX UI. Hosts the HMCL fork shell. Mindustry-specific UI is segregated underdetermination.xenon.mindustry.ui.*:MindustryRoutes— central routing helper.Versions.*/GameItempatches detour to it when an id matches the Mindustry repoMindustryVersionPage— per-instance management (Mod / Save / Schematic / Crash tabs); pattern reused everywhereMindustryVariantPickerPane,install/XenonInstallWizardProvider+ wizard pages — install flowMindustryModBrowserPane— community mod index browserui/server/— server-management UI:MindustryServerListPane,MindustryServerDetailPage(Console / Config / Maps / Mods / Settings tabs),MindustryServer{Console,Config,Maps,Mods,Settings}Pane
XenonBoot— bootstrap launcher (Main), self-update, dependency patcherminecraft/libraries/HMCLTransformerDiscoveryService,HMCLMultiMCBootstrap— Minecraft-loader libs kept compiling for backward-compat; not invoked from the Mindustry path
<config>/ Windows %APPDATA%\Xenon, Linux ~/.xenon, macOS ~/Library/Application Support/Xenon
├── xenon.json global settings (HMCL-compatible schema)
├── caches/github/ GitHub release metadata, ETag-aware
├── java/ Adoptium Temurin auto-downloads
├── uuid-profiles.json
├── versions/<id>/ one client instance
│ ├── version.json { variant, build, javaReq, jarPath, dataDirPolicy, ... }
│ ├── <id>.jar
│ └── .data/ ← -Dmindustry.data.dir
│ ├── saves/ mods/ maps/ schematics/ crashes/ config/
│ └── settings.bin
└── servers/<sid>/ one dedicated-server instance
├── server.json { jar, javaReq, scriptAgent, autoRestart, port, ... }
├── server-release.jar
└── .data/
MindustryVersion#resolveDataDir(versionRoot) and ServerInstance#resolveDataDir(serverRoot) are the canonical resolvers — never reconstruct paths by hand. DataDirectoryPolicy covers ISOLATED (default), GLOBAL, CUSTOM.
RootPage.Skin (Xenon/src/main/java/determination/xenon/ui/main/RootPage.java) builds the left sidebar. Mindustry sidebar entries live alongside HMCL ones and dispatch via Controllers.navigate(...). Controllers.initialize(stage) configures the primary stage; the Stage is StageStyle.UNDECORATED and gets DWM rounded corners on Win11 via WindowsNativeUtils.applyDwmRoundedCorners after show(). A WS_EX_APPWINDOW fix-up runs there too so the taskbar treats the window as a normal top-level. System-tray (single-click restore) is installed by TrayIconManager from Launcher.start.
The HMCL "VersionPage" pattern — DecoratorAnimatedPage + AdvancedListBox sidebar + TabHeader over a TransitionPane — is the canonical layout for any Mindustry detail page. Reuse it (MindustryVersionPage, MindustryServerDetailPage are the two existing examples).
- Annotate every class with JetBrains
@NotNullByDefault; mark every nullable type/field/param/return/local/type-arg@Nullable. Nullability is never implicit. - Mark immutable arrays/collections
@Unmodifiableor@UnmodifiableView. For arrays use type-use syntax:String @Unmodifiable []. - Every class, field, method gets
///markdown javadoc. Add inline implementation comments where they materially aid readability. Xenon/build.gradle.ktsdefines a longaddOpenslist. New code that touches JavaFX internals must respect it; the manifest mirrors it asAdd-Opens.- License header is enforced by
config/checkstyle/license-header.txt.
UI strings live under Xenon/src/main/resources/assets/lang/I18N*.properties. The canonical bundle is I18N.properties (English); I18N_zh_CN.properties (Simplified Chinese) and I18N_zh.properties (Traditional) must stay in lock-step. New keys must be added to all three at minimum or :Xenon:checkTranslations will fail. Other languages are best-effort. The build also generates an upside-down English bundle (I18N_en_Qabs.properties) and a LocaleNames resource bundle from language-subtag-registry.
- The Stage uses
StageStyle.UNDECORATED; transparent windows on Win11 24H2 don't get reliable taskbar proxies, hence the explicitWS_EX_APPWINDOW+ DWM rounded-corner pair. - AppUserModelID is intentionally not set during
gradle :Xenon:run— without a matching.lnkshortcut, Win11 shell hides the taskbar icon. Re-enable it from the jpackagedXenon.exebuild. - JavaFX 25's
MethodHandles.privateLookupIn(Window.class, ...)route fails (module javafx.graphics does not open javafx.stage), soWindowsNativeUtils.getWindowHandlelooks up the HWND viauser32!FindWindowWfirst, with the reflective path as fallback. - JNA bindings are minimal hand-rolled
Native.load("user32"/"shell32"/"dwmapi", …)interfaces;jna-platformis not on the classpath.
The fork lives at https://github.com/DeterMination-Wind/Xenon (rebrand of HMCL upstream https://github.com/HMCL-dev/HMCL). Metadata.PUBLISH_URL and Metadata.XENON_UPDATE_URL point at the fork; the in-app self-updater talks to api.github.com/repos/DeterMination-Wind/Xenon/releases/latest.