Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Nebula-Modmakers/Nebula-Launcher/llms.txt

Use this file to discover all available pages before exploring further.

Nebula Launcher is structured as four cooperating layers: a phone-friendly Android UI (dev.tates.nebula), a Java bootstrap orchestrator (dev.allofus.fusioncore), a C++ native runtime (libfusion.so), and a thin JNI bridge (libnebulahook.so). Together they prepare the device environment, patch the class loader and Unity player, boot the .NET CoreCLR runtime, and hand off to BepInEx so that IL2CPP plugins load inside Among Us without modifying the game APK.

Component Layers

Each layer has a clear responsibility and communicates with adjacent layers through defined interfaces.

1 — Nebula UI Layer

Package: dev.tates.nebulaThe user-facing Android application. Key activities:
ActivityPurpose
SelectorActivityMain screen; shows the active profile and the Launch button
ProfilesActivityCreates, selects, and deletes mod profiles
ModStoreActivityBrowse and install packages from the Nebula mod catalog
FileBrowserActivityInspect Nebula and BepInEx files; light text editor for supported files
SettingsActivityNebula account, Among Us account linking, verbose-launch toggle
UpdatesActivityChecks for Nebula launcher updates
This layer manages Nebula accounts (with automatic session refresh and a limited offline grace period), optional Among Us account linking for the supported online flow, per-profile plugin storage, .npkg package download and installation through NpkgInstaller, and the in-game utility menu (triple-tap bottom-right edge).

2 — FusionCore Bootstrap

Package: dev.allofus.fusioncoreBootstrapActivity orchestrates the entire launch sequence on a background thread:
  • Verifies the installed Among Us package version against the required build (2026.6.5, version code 7045)
  • Copies Unity game data assets (bin/Data) into private app storage
  • Detects the exact Unity engine version from the copied data
  • Downloads and caches a matching libunity.so when needed (falls back to the game’s own copy if the download fails)
  • Extracts and updates the bundled ARM64 .NET and BepInEx runtime ZIPs only when their SHA-256 fingerprint has changed
  • Registers all game, FusionCore, and data native libraries with NativeLibraryManager
  • Installs ClassLoaderHooks, PackageManagerHooks, and UnityPlayerHooks to redirect library resolution and wrap the Unity player context
  • Hooks the launcher activity’s onCreate via NebulaHook to initialise FusionCore before Unity starts
  • Writes the active FusionConfig to bootstrap/active.cfg via FusionConfigStore
  • Starts the game’s launcher activity and finishes itself
FusionConfig carries all directory paths and the Unity version needed by the native layer. It is serialised to a key-value text file that the C++ runtime reads at init time.

3 — Native FusionCore Library

Binary: libfusion.so (ARM64, loaded via JNI)The core C++ runtime responsible for all low-level hooking and .NET hosting:
  • fusion_stage_from_config_path — reads bootstrap/active.cfg, resolves library paths, hooks libunity.so loading, and patches libil2cpp.so with an injected trampoline pool
  • fusion_bootstrap_from_libmain — called from libmain’s JNI namespace; installs the il2cpp_init hook using Dobby via SafeHook
  • il2cpp_init_hook — intercepts the IL2CPP domain initialisation call; sets all FUSION_* and BEPINEX_* environment variables; initialises .NET CoreCLR via coreclr_initialize; creates a delegate to BepInEx.Unity.IL2CPP.FusionCoreEntrypoint.Start and invokes it
  • EOS hook — uses XDL to locate EOS_Connect_Login across linker namespaces and rewrites placeholder credentials for the Android AuthFix token substitution flow
Third-party dependencies used by this layer:
LibraryRole
DobbyInline (trampoline) function hooks for native code
LSPlantART method hooks for Java/Kotlin via libnebulahook.so
XDLDynamic linker symbol resolution across Android linker namespaces
.NET CoreCLREmbedded managed runtime; hosts BepInEx and IL2CPP interop
BepInEx FusionBepInEx build targeting the FusionCore Android entry-point

4 — NebulaHook JNI Bridge

Binary: libnebulahook.soA thin C++ JNI library that initialises LSPlant against libart.so (resolved via XDL) and exposes two JNI methods to the Java layer:
  • NebulaHook.nativeInitialize() — opens libart.so with XDL and calls lsplant::Init with Dobby as the inline hooker
  • NebulaHook.nativeHook(Member target, HookRecord record) — delegates to lsplant::Hook to install an ART method hook
All Java-level hooks in NativeLibraryManager, UnityPlayerHooks, and BootstrapActivity go through this bridge. The NebulaHook.Callback interface provides beforeCall and afterCall intercept points, and CallFrame lets hooks read arguments, short-circuit the original call, set a return value, or invoke the original method explicitly.

Launch Sequence

1

User taps Launch

The user selects a profile in SelectorActivity and taps Launch. ProfileManager.stageActive() copies the active profile’s plugin DLLs from files/profiles/<name>/plugins/ into the shared FusionCore plugin directory, replacing whatever was there before.
2

BootstrapActivity starts

SelectorActivity fires an Intent targeting BootstrapActivity with EXTRA_TARGET_PACKAGE = "com.innersloth.spacemafia". The bootstrap screen appears and a background thread begins runBootstrapFlow.
3

Game version check and data preparation

BootstrapActivity verifies that the installed Among Us package matches version 2026.6.5 (version code 7045). It then copies Unity bin/Data assets to private storage and detects the Unity engine version from the copied data. If a matching libunity.so is not already cached, it is downloaded from the FusionCore CDN; if the download fails the game’s own copy is used instead.
4

Runtime extraction

BepInEx-arm64.zip and dotnet-arm64.zip are extracted from the app’s bundled assets into the private data directory. Extraction is skipped when the SHA-256 fingerprint of the packaged ZIP matches the stored marker file, keeping the existing BepInEx.cfg intact across updates.
5

Native library registration

Every .so file in the game’s native library directory is registered with NativeLibraryManager. FusionCore’s own libraries (libmain.so, libfusion.so) and data libraries (libil2cpp.so, libunity.so) are registered separately. NativeLibraryManager.setupLibraryHooks then hooks the class loader’s findLibrary method via NebulaHook so that load requests for these names are redirected to the correct paths.
6

Hook installation

Three hook groups are installed:
  • ClassLoaderHooks — patches the game’s class loader to make FusionCore classes visible inside the game process
  • PackageManagerHooks — intercepts package-manager queries to normalise metadata
  • UnityPlayerHooks — hooks every UnityPlayer constructor that accepts a Context argument; replaces the Context with a CustomContextWrapper and restores the original Activity reference in Unity’s fields after construction
7

Game process launched

BootstrapActivity hooks the game’s launcher activity onCreate with NebulaHook. When the hook fires (before Unity initialises), initializeFusion writes the FusionConfig to disk and libfusion.so is given a chance to stage its config via fusion_stage_from_config_path. The game activity starts, BootstrapActivity finishes, and a transparent overlay on the game window monitors BepInEx log output for progress.
8

BepInEx boots and plugins load

Inside the game process, fusion_bootstrap_from_libmain installs the il2cpp_init hook. When IL2CPP initialises its domain, the hook fires: environment variables are set, CoreCLR is started in the FusionHost AppDomain, and BepInEx.Unity.IL2CPP.FusionCoreEntrypoint.Start is invoked. BepInEx generates IL2CPP interop assemblies if needed (this takes up to several minutes on first run), then discovers and loads plugin DLLs from the staged BepInEx/plugins directory. The overlay disappears once Chainloader startup complete appears in BepInEx/LogOutput.log.

Key Directories

The following paths are the most important on-device locations. Paths under files/ are inside Nebula’s private Android data sandbox; FusionCore/ is in shared external storage.

Private app data

Nebula’s internal storage, inaccessible to other apps without root.
PathContents
files/profiles/<name>/plugins/Per-profile plugin DLL storage
files/profiles/<name>/.nebula/packages/Installation records for managed packages
files/<package>/Data_copy/Copied Unity game data for the target package
files/<package>/BepInEx/Extracted BepInEx ARM64 runtime
files/<package>/dotnet/Extracted .NET CoreCLR ARM64 runtime
files/<package>/<abi>/libunity.soCached Unity library for the detected Unity version
files/bootstrap/active.cfgActive FusionConfig key-value file read by libfusion.so

Shared FusionCore data

Accessible to the file browser and shared between Nebula and the game process.
PathContents
FusionCore/com.innersloth.spacemafia/BepInEx/Shared BepInEx runtime and configuration
FusionCore/com.innersloth.spacemafia/BepInEx/plugins/Active staged plugins (overwritten on each launch)
FusionCore/com.innersloth.spacemafia/BepInEx/LogOutput.logBepInEx runtime log for the most recent session
FusionCore/com.innersloth.spacemafia/BepInEx/interop/Generated IL2CPP interop assemblies
The shared BepInEx/plugins/ directory is completely replaced each time a profile is staged. Changes made directly to that folder between launches will be lost. Manage your mods through Nebula’s profile system or the mod store.

Build docs developers (and LLMs) love