Files
Vladimir Zagainov c06c205b7b feat: add launch module (manifest, interpolation, process exec)
- manifest: Manifest struct (files, launch config, server info), LoadManifest, LibraryFiles/ModFiles filters
- launch: Game struct (Prepare/BuildCommand/Start lifecycle)
  - Prepare: download manifest, resolve Java, sync files with SHA-1, soft-delete unknown mods
  - BuildCommand: classpath assembly, variable interpolation (, , etc.), authlib-injector injection
  - Start: execute the assembled command
- interpolate:  template replacement
- cleanupUnknownMods: moves untracked mods to mods_backup/

Co-Authored-By: OWL <noreply@anthropic.com>
2026-05-26 11:49:51 +03:00

76 lines
2.1 KiB
Go

// package launch handles Minecraft process launching.
package launch
import (
"encoding/json"
"fmt"
"os"
)
// Manifest describes the contents of a modpack as provided by the backend.
type Manifest struct {
MinecraftVersion string `json:"minecraft_version"`
JavaVersion int `json:"java_version"`
ServerInfo ServerInfo `json:"server_info"`
Files []ManifestFile `json:"files"`
Launch LaunchConfig `json:"launch"`
}
// ServerInfo is the game server address injected into servers.dat.
type ServerInfo struct {
Name string `json:"name"`
IP string `json:"ip"`
}
// ManifestFile is a single file entry with SHA-1 verification.
type ManifestFile struct {
Path string `json:"path"`
Hash string `json:"hash"`
Size int64 `json:"size"`
URL string `json:"url"`
}
// LaunchConfig contains the JVM and game arguments template.
type LaunchConfig struct {
MainClass string `json:"mainClass"`
JVMArgs []string `json:"jvmArgs"`
GameArgs []string `json:"gameArgs"`
NativeLibs []string `json:"nativeLibs"`
AuthLibInjector string `json:"authLibInjector"` // URL to authlib-injector.jar
}
// LoadManifest reads and parses a manifest.json from disk.
func LoadManifest(path string) (*Manifest, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("reading manifest %s: %w", path, err)
}
var m Manifest
if err := json.Unmarshal(data, &m); err != nil {
return nil, fmt.Errorf("parsing manifest %s: %w", path, err)
}
return &m, nil
}
// LibraryFiles returns the subset of Files that are .jar libraries (classpath).
func (m *Manifest) LibraryFiles() []ManifestFile {
var libs []ManifestFile
for _, f := range m.Files {
if len(f.Path) > 4 && f.Path[len(f.Path)-4:] == ".jar" {
libs = append(libs, f)
}
}
return libs
}
// ModFiles returns the subset of Files that go into the mods/ directory.
func (m *Manifest) ModFiles() []ManifestFile {
var mods []ManifestFile
for _, f := range m.Files {
if len(f.Path) > 5 && f.Path[:5] == "mods/" {
mods = append(mods, f)
}
}
return mods
}