EML Docs

Launcher

Launcher is the core class of EML Lib. It manages the full launch pipeline: computing what needs to be downloaded, fetching files, installing the mod loader, checking Java, and spawning the game process.

import { Launcher, MicrosoftAuth } from 'eml-lib'

launchGame()

async function launchGame() {
  const launcher = new Launcher({
    url: 'https://at.myserver.com',
    root: 'myserver',
    account: account // obtained from MicrosoftAuth or another *Auth class
  })

  launcher.on('launch_download', (d) => {
    updateProgressBar(d.total.downloaded / d.total.amount)
  })

  await launcher.launch()
}

Tip

Use the configuration generator to build a valid Config object interactively.

Constructor

ParameterTypeDescriptionRequired?
configConfigThe launcher configuration. See below.Yes

launch() method

Runs the full launch pipeline and spawns the Minecraft process.

Note

This method automatically patches the Log4j vulnerability.

Returns: Promise<void>

Throws: FETCH_ERROR — If a request to fetch configuration or manifests fails. • DOWNLOAD_ERROR — If a file download fails. • EXEC_ERROR — If the game process cannot be spawned.

Emits: See Events below.

Config

FieldTypeDescriptionRequired?
rootstringName of the root game directory, without a leading dot (e.g. 'myserver'). EML Lib prepends a dot automatically on all platforms.Yes
accountAccountThe authenticated player account. Use any *Auth class to obtain one.Yes
urlstringURL of your EML AdminTool instance or your self-hosted manifest JSON. If omitted and no minecraft.version is set, Vanilla latest release is used. Ignored if minecraft.version or profile.minecraft.version is set.No
profileIProfileThe profile to launch. Retrieve the list with Profiles.getProfiles(). In agnostic mode (no url), the profile must have a valid slug for folder naming.No
profile.minecraftobjectPer-profile Minecraft configuration. Takes precedence over minecraft and AdminTool data.No
profile.minecraft.versionstringMinecraft version for this profile (e.g. '1.21.1', 'latest_release', 'latest_snapshot'). Setting this makes url irrelevant for version resolution.No
profile.minecraft.loaderobjectMod loader config for this profile. Ignored if profile.minecraft.version is not set.No
profile.minecraft.loader.loader'vanilla' | 'forge' | 'neoforge' | 'fabric' | 'quilt'The mod loader to use for this profile.No (defaults to 'vanilla')
profile.minecraft.loader.versionstringThe mod loader version. Required for any loader other than 'vanilla'.No
profile.minecraft.modpackUrlstringDirect URL to a modpack manifest JSON. Ignored if profile.minecraft.version is not set.No
profile.minecraft.argsstring[]Custom Minecraft launch arguments for this profile.No (defaults to [])
minecraftobjectGlobal Minecraft configuration. Overridden by profile.minecraft if that field defines a version.No
minecraft.versionstringGlobal Minecraft version. Setting this makes url irrelevant for version resolution.No
minecraft.loaderobjectGlobal mod loader configuration. Ignored if minecraft.version is not set.No
minecraft.loader.loader'vanilla' | 'forge' | 'neoforge' | 'fabric' | 'quilt'The global mod loader type.No (defaults to 'vanilla')
minecraft.loader.versionstringThe global mod loader version. Required for any loader other than 'vanilla'.No
minecraft.modpackUrlstringGlobal modpack manifest URL. Ignored if minecraft.version is not set.No
minecraft.argsstring[]Global custom launch arguments.No (defaults to [])
storage'isolated' | 'shared'How game files are organised on disk. 'isolated' gives each profile its own folder. 'shared' shares assets and libraries between profiles while keeping mods, config, and saves separate. If 'shared', set cleaning.enabled to false.No (defaults to 'isolated')
cleaning.enabledbooleanWhether to remove files from the instance folder that are not present in the modpack manifest. Must be false when storage is 'shared'.No (defaults to true)
cleaning.ignoredstring[]Paths and files that the cleaner will never delete, even if they are absent from the manifest (e.g. 'saves/', 'options.txt').No (defaults to a standard Minecraft ignore list)
java.install'auto' | 'manual''auto' downloads and manages the correct Java version automatically. 'manual' uses a pre-installed Java executable.No (defaults to 'auto')
java.absolutePathstringAbsolute path to the Java executable. Required if install is 'manual' and relativePath is not set. Overrides relativePath.No
java.relativePathstringPath to Java relative to the game root. Ignored if install is 'auto' or absolutePath is set.No
java.argsstring[]Custom JVM arguments. Do not add Log4j patches here — they are applied automatically.No (defaults to [])
memory.minnumberMinimum RAM allocated to Minecraft, in MB.No (defaults to 512)
memory.maxnumberMaximum RAM allocated to Minecraft, in MB.No (defaults to 1024)
window.widthnumberMinecraft window width in pixels.No (defaults to 854)
window.heightnumberMinecraft window height in pixels.No (defaults to 480)
window.fullscreenbooleanLaunch Minecraft in fullscreen.No (defaults to false)

Events

Events are emitted on the Launcher instance via .on(event, callback).

Step events mark the start of a major phase in the launch pipeline.

EventDescriptionCallback data
launch_compute_downloadComputing which files need to be downloaded.
launch_downloadDownloading game files.{ total: { amount, size }, downloaded: { amount, size } }
launch_install_loaderInstalling the mod loader.{ type, loaderVersion }
launch_copy_assetsCopying asset files to the instance folder.
launch_extract_nativesExtracting native libraries.
launch_patch_loaderPatching the mod loader.
launch_check_javaChecking the Java installation.
launch_cleanCleaning unrecognised files from the instance folder.
launch_launchSpawning the Minecraft process.{ version, loader, loaderVersion }

Progress events are emitted continuously within a step.

EventDescriptionCallback data
launch_dataA line of stdout/stderr from the Minecraft process.string
launch_closeThe Minecraft process has exited.number (exit code)
launch_debugInternal debug log from EML Lib.string
download_progressA file is being downloaded.{ type, total: { amount, size }, downloaded: { amount, size }, speed }
download_errorA file download failed.{ filename, type, message }
download_endAll files of a given type have been downloaded.{ amount, size }
extract_progressA file is being extracted.{ filename }
extract_endExtraction complete.{ amount }
copy_progressA file is being copied.{ filename, destination }
copy_endCopy complete.{ amount }
copy_debugDebug log from the copy step.string
java_infoJava version and architecture in use.{ version, arch }
patch_progressA file is being patched.{ filename }
patch_endPatching complete.{ amount }
patch_errorA file could not be patched.{ filename, message }
patch_debugDebug log from the patch step.string
clean_progressA file is being removed by the cleaner.{ filename }
clean_endCleaning complete.{ amount }

Preserving player-modified files

When cleaning.enabled is true, the cleaner removes any file in the instance folder that is absent from the modpack manifest. This includes files the player has created or modified locally — for example, a custom options.txt.

To protect a file from being deleted while still keeping the cleaner active, add it to cleaning.ignored:

const launcher = new Launcher({
  // ...
  cleaning: {
    enabled: true,
    ignored: ['options.txt', 'saves/', 'screenshots/']
  }
})

Note

cleaning.ignored only prevents deletion. If the same file is also present in the modpack manifest (uploaded via Files Updater), it will still be downloaded and overwrite the player’s local version. To truly preserve a player-modified file, do not upload it to Files Updater and add it to cleaning.ignored.

Use a default options.txt without overwriting player settings

If you want to provide a default options.txt with recommended keybinds and video settings, but don’t want to overwrite players’ custom settings on every launch, use the following workaround:

  1. Open the js/ts file where you create the Launcher instance.

  2. Import the fs module from Node.js:

    import fs from 'node:fs'
  3. In you Config object passed to the Launcher constructor: if cleaning.enabled is true, ensure that options.txt is included in the cleaning.ignored array to prevent it from being deleted by the cleaner.

    const launcher = new Launcher({
      // ...
      cleaning: {
        enabled: true,
        ignored: [..., 'options.txt'] // add options.txt to the ignored list
      }
    })
  4. Update your launch code to check if options.txt exists in the instance folder. If it doesn’t, create it with your default content. Then proceed to launch as normal.

    const optionsPath = path.join(launcher.config.root, 'options.txt')
    
    try {
      if (!fs.existsSync(optionsPath)) {
        if (!fs.existsSync(launcher.config.root)) {
          fs.mkdirSync(launcher.config.root, { recursive: true })
        }
        fs.writeFileSync(optionsPath, `DEFAULT OPTIONS CONTENT HERE`) // replace with your default options.txt content
      }
    
      launcher.launch() // proceed to launch as normal
    } catch (err) {
      logger.error('Launcher error:', err)
    }

Tip

This approach could be used to provide default configuration for any file, not just options.txt. Just remember to add it to cleaning.ignored to prevent the cleaner from deleting it.