Help us shape the future of Go! Take the 2026 Go Developer Survey

bepinex

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 2, 2026 License: MIT Imports: 18 Imported by: 0

README

go-bepinex

Go


Installs BepInEx 5 into a Unity game: the pack, the Doorstop files, launch arguments and the Proton DLL override. Package bepinex, module github.com/Rethunk-Tech/go-bepinex.

A pack zip is untrusted: it is extracted under go-archive's caps and a name that climbs out fails the install before the profile changes. user.reg edits are byte-exact apart from the one override line.

Quick start

go get github.com/Rethunk-Tech/go-bepinex

A worked example and the contracts: HUMANS.md.

Features

  • InstallPack lays a BepInEx 5 or 6 pack into a folder, replacing the old pack but keeping mods and player config.
  • LaunchArgs and VanillaArgs give the Doorstop 3 and 4 flags, with Wine Z: paths on request.
  • WriteAbsoluteConfig makes a doorstop_config.ini that works from the game folder.
  • PlaceUnityLibs keeps and places the Unity base libraries an IL2CPP game needs.
  • plugins.ScanDir, ScanEach, PluginsIn, DLLs and PluginFile read which BepInEx plugins the DLLs in a folder declare, through go-dotnet; Owners maps the names a log uses to the folder that declares them.
  • plugins.LoadOrder and Loadable give the order BepInEx 5's chainloader loads plugins in, dependencies first.
  • logline.Parse, SplitStamp and Format read and write LogOutput.log header lines, with a logger mod's timestamp.
  • wineoverride.Ensure sets a native,builtin DLL override in a Proton prefix's user.reg.

Documentation

Doc Audience
HUMANS.md Running and using the package
AGENTS.md Internals, invariants, and why
CONTRIBUTING.md Process — commits, tests, docs
SECURITY.md Vulnerability disclosure
CHANGELOG.md Release notes

License

MIT — see LICENSE. © 2026 Rethunk.Tech, LLC.

Documentation

Overview

Package bepinex installs a BepInEx 5 (or 6) pack into a profile folder for a Unity game and describes how Doorstop starts it: the Doorstop files that belong beside the game executable, the launch flags, and the Unity base libraries an IL2CPP game needs. It knows no game catalogue and no profile model; the caller passes plain paths.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DoorstopFiles

func DoorstopFiles(profileRoot, fallback string) []string

DoorstopFiles lists, relative to profileRoot and with forward slashes, the files that must sit next to the game executable: doorstop_config.ini and the pack's Doorstop proxy (fallback names the proxy to look for when none is installed). Absent ones are left out. Everything else of the pack stays in the profile.

func Entry

func Entry(profileRoot string) string

Entry is the entry assembly of the pack installed in profileRoot, relative to it and in the host's separators; the BepInEx 5 preloader when no entry assembly is installed.

func HasCLR

func HasCLR(profileRoot string) bool

HasCLR reports whether the pack in profileRoot ships the .NET runtime an IL2CPP pack starts through.

func HostPath

func HostPath(profileRoot, rel string, proton bool) string

HostPath is rel under profileRoot as an absolute path, in the Wine Z: form when proton is set.

func IsIL2CPPGame added in v0.2.0

func IsIL2CPPGame(gameDir string) bool

IsIL2CPPGame reports whether the Unity game in gameDir is an IL2CPP build: GameAssembly (.dll, .so, or the .dylib of a macOS .app's folder) is there and the game's il2cpp_data folder exists. gameDir is the folder holding the executable, or a macOS .app. A game without both is Mono (or not a Unity game).

func LaunchArgs

func LaunchArgs(profileRoot string, doorstopMajor int, proton bool) []string

LaunchArgs are the Doorstop flags that start the game with BepInEx rooted in profileRoot, with an IL2CPP pack's .NET runtime. Doorstop 3 and 4 spell the flags differently (doorstopMajor is Installed.Doorstop); proton gives the paths in the Wine Z: form.

func LaunchOption added in v0.2.0

func LaunchOption(script string) string

LaunchOption is the Steam launch option that runs the game through the script at the absolute path script: `"<script>" %command%`.

func PlaceUnityLibs

func PlaceUnityLibs(ctx context.Context, gameDir, profileDir, cacheDir string) error

PlaceUnityLibs puts the game's Unity base libraries in the profile's BepInEx/unity-libs, so an IL2CPP game's first start needs no network. The zip is downloaded once into cacheDir/unity-libs and copied from there into each later profile. A game with no readable Unity version is a no-op; on any error BepInEx fetches the libraries itself at launch, so a caller may treat the error as non-fatal.

func Proxies

func Proxies() []string

Proxies are the file names a pack gives its Doorstop proxy library, the usual one first.

func Proxy

func Proxy(profileRoot, fallback string) string

Proxy is the Doorstop proxy library the pack in profileRoot ships; fallback before it holds a pack.

func SetScriptExecutable added in v0.2.0

func SetScriptExecutable(script []byte, name string) []byte

SetScriptExecutable sets executable_name in the pack's run_bepinex.sh to name, the game's app name (the .app folder without its suffix), single-quoted so the shell reads it literally. A script without the variable comes back as is.

func UnityVersion

func UnityVersion(gameDir string) string

UnityVersion is the Unity version of the game in gameDir (2022.3.21), read from its *_Data folder, or "".

func VanillaArgs

func VanillaArgs() []string

VanillaArgs start the game with Doorstop switched off, even while its files sit in the game folder. A vanilla start has no profile to read the Doorstop version from, and the proxy left in the folder may be either, so both spellings are passed; each proxy ignores the other's.

func WriteAbsoluteConfig

func WriteAbsoluteConfig(profileRoot, dst string, doorstopMajor int, proton bool) error

WriteAbsoluteConfig writes the profile's doorstop_config.ini to dst with its target assembly set to the profile's entry (added, in the spelling of the Doorstop major version, when the config names none) and the pack's runtime paths made absolute. Doorstop reads relative paths from the game folder, where the profile's files are not, so the copy in the game folder loads the profile's BepInEx even when a start cannot pass Doorstop's flags. A path in the config that leaves the profile is left as written. The file's line endings are kept; proton gives paths in the Wine Z: form.

Types

type Flavor added in v0.2.0

type Flavor int

Flavor is which BepInEx build an installed pack is.

const (
	// FlavorNone is a folder with no BepInEx entry assembly.
	FlavorNone Flavor = iota
	// FlavorBepInEx5 is BepInEx 5, which runs on Mono.
	FlavorBepInEx5
	// FlavorBepInEx6Mono is BepInEx 6 for a Mono game.
	FlavorBepInEx6Mono
	// FlavorBepInEx6IL2CPP is BepInEx 6 for an IL2CPP game.
	FlavorBepInEx6IL2CPP
)

func Detect added in v0.2.0

func Detect(profileRoot string) Flavor

Detect tells which BepInEx build is installed in profileRoot from its entry assembly. When a folder holds more than one, the IL2CPP entry wins, then the BepInEx 6 Mono one, as Entry does.

func (Flavor) String added in v0.2.0

func (f Flavor) String() string

String is the flavor's name, as "BepInEx 6 IL2CPP".

type Installed

type Installed struct {
	// Manifest is the pack's manifest.json as the archive holds it (at most 1 MiB), or nil when it has none or it is
	// larger. It is untrusted input for the caller to parse.
	Manifest []byte
	// Doorstop is the major version of the Doorstop proxy, from .doorstop_version; 3 when the pack has none.
	Doorstop int
}

Installed is what InstallPack found in the pack.

func InstallPack

func InstallPack(zipPath, profileRoot string) (Installed, error)

InstallPack lays the pack zip's root folder out into profileRoot, replacing files already there: a folder named anything that holds an entry assembly (BepInExPack/, BepInExPack_Valheim/), or the zip itself when it has BepInEx/ at its top. The zip is extracted by go-archive under its default caps, so a name that climbs out, a link or a special file fails the install before profileRoot is touched.

Files of a previous pack are cleared first (see the Doorstop files and core libraries it owns); BepInEx/plugins, patchers and a core folder of a mod stay, and an existing BepInEx/config file is never overwritten.

type Placement added in v0.2.0

type Placement struct {
	// Files are the profile files, relative with forward slashes, that the start needs. On Windows and Linux they sit
	// beside the game executable (DoorstopFiles); on darwin they stay in the profile, since the launch option names
	// the script by its absolute path.
	Files []string
	// Executable are the Files that need the execute bit (0o755); archives do not always keep it. Darwin only.
	Executable []string
	// LaunchOption is the Steam launch option that starts the game through the pack's script, or "" when the pack has
	// none or the platform has no such option. Darwin only.
	LaunchOption string
}

Placement is what a platform's start needs from the pack installed in a profile. It is data: the caller copies the files, sets the modes and applies the launch option.

func PlacementFor added in v0.2.0

func PlacementFor(profileRoot, goos string) Placement

PlacementFor is the Placement of the pack in profileRoot for goos ("windows", "linux", "darwin"). Windows and Linux give DoorstopFiles, with the usual proxy named as the fallback. darwin has no winhttp.dll proxy: Doorstop is injected by dyld from libdoorstop.dylib (at the pack's top or under doorstop_libs/) when run_bepinex.sh starts the game. A pack without the script gives an empty LaunchOption, which means it cannot start on macOS.

Directories

Path Synopsis
Package logline reads and writes the lines of BepInEx's LogOutput.log: a header naming a level and a source, then the message, optionally behind the timestamp a logger mod adds.
Package logline reads and writes the lines of BepInEx's LogOutput.log: a header naming a level and a source, then the message, optionally behind the timestamp a logger mod adds.
Package plugins reads which BepInEx plugins the compiled assemblies in a folder declare, through go-dotnet, and orders them the way BepInEx 5's chainloader loads them.
Package plugins reads which BepInEx plugins the compiled assemblies in a folder declare, through go-dotnet, and orders them the way BepInEx 5's chainloader loads them.
Package wineoverride edits a Wine or Proton prefix's user.reg so Wine loads a loader's proxy library natively, and writes host paths the way a game under Wine reads them.
Package wineoverride edits a Wine or Proton prefix's user.reg so Wine loads a loader's proxy library natively, and writes host paths the way a game under Wine reads them.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL