← Paracosm·Docs/Reference
Contents · Building the server

Building the Paracosm server

build/build_server.py builds the whole server in one command: from the pristine OpenSimulator 0.9.3.0 source zip to a runnable bin/ with our seven source patches, the official SQLite DLL, our WorldBridge region module and a config made from the templates in config/.

Prerequisites

The versions used for the reference build (2026-09-27):

what version used notes
.NET SDK 8.0.422 any .NET 8 SDK; it includes the runtimes (Microsoft.NETCore.App 8.0.28 and Microsoft.AspNetCore.App 8.0.28 here). Mono and Visual Studio are not needed.
Python 3.12.10 3.8 or later; standard library only
OS Windows 11 Pro 10.0.22631, x64 the script also handles Linux, but has not been run there (see Limits)
OpenSimulator source opensim-0.9.3.0-source.zip, 43,218,173 bytes, SHA-256 44811934c289195420ec82a5d448e6ee28b6cfa6094e1a8e6882e489c0967ab7 from http://opensimulator.org/dist/opensim-0.9.3.0-source.zip
SQLite (Windows) the official sqlite3.dll 3.47.0 x64, 3,209,728 bytes, SHA-256 982cedc4aaebeec3e8efa8e98fb40491bfb1c7e928d3a3dd97d7440eff1536c5 inside https://www.sqlite.org/2024/sqlite-dll-win-x64-3470000.zip

Not needed: git, patch, NuGet packages (the projects reference none; dotnet build's restore is satisfied by the SDK itself), network access (unless you use --fetch-sqlite3).

The one command

Put opensim-0.9.3.0-source.zip in the repository root (or pass --zip PATH), copy .env.example to .env and fill it in, then from the repository root:

python build/build_server.py ../paracosm-server --fetch-sqlite3

Offline, give it the SQLite DLL or its official zip instead of --fetch-sqlite3: --sqlite3-dll PATH/sqlite3.dll or --sqlite3-zip PATH/sqlite-dll-win-x64-3470000.zip.

Other options: --env PATH (a different env file; default .env in the repository), --clean (delete the output directory first; without it the script refuses a non-empty one), --low-priority (run dotnet at idle priority, for building beside a running region), --dotnet PATH, --no-sqlite3, --sqlite3-sha256 HEX (accept a different SQLite release on purpose). The output directory must be outside the repository.

It takes a few minutes. It prints each step and ends with [build] DONE (exit code 0), or [build] FAILED: <why> (exit code 1).

What it does

  1. Prerequisites. Checks for Python 3.8+ and a .NET 8 SDK on PATH, and records the SDK it builds with.
  2. Verify the zip. Its SHA-256 must equal the pinned hash above; anything else stops the build.
  3. Extract the zip into the output directory (its top folder opensim/ is stripped).
  4. Apply the patches in opensim-patches/, in the order listed in opensim-patches/series: asset-instr, sqlite-groups, bulletsim-ghost, startup-script-guard, terrain-script-pbr, sqlite-offlineim, sqlite-profiles. Each is a git-style (-p1) unified diff against the pristine 0.9.3.0 file. The script's own applier is strict: every context and removed line must match byte for byte at the line the hunk names (no fuzz, no offset), and all patches are checked in memory before any file is written. Then every patched file's SHA-256 is compared with opensim-patches/patched-files.sha256, the expected hashes of the patched sources. The seven patches touch disjoint files; each folder's README says what it fixes.
  5. Prebuild, as upstream's runprebuild.bat / runprebuild.sh do: copy the per-OS bin/System.Drawing.Common.dll.win (or .linux) to bin/System.Drawing.Common.dll, then run dotnet bin/prebuild.dll /target vs2022 /targetframework net8_0 /excludedir = "obj | bin" /file prebuild.xml, which writes OpenSim.sln and every .csproj. The script passes the arguments as a list, so the "obj | bin" argument arrives intact (a POSIX shell mangles the .bat's line). Prebuild's wildcards add the new files of sqlite-groups and sqlite-offlineim to OpenSim.Data.SQLite.csproj; the script checks that they are there.
  6. Compile: dotnet build --configuration Release OpenSim.sln (with -nodeReuse:false and -p:UseSharedCompilation=false, so no build server outlives the build). The output lands in bin/.
  7. sqlite3.dll (Windows). The zip's bin/lib64/sqlite3.dll is a Mono-era build that links MSVCR90.dll, which Windows no longer has. .NET 8 ignores Mono's dllmap (bin/Mono.Data.Sqlite.dll.config), so DllImport("sqlite3") finds bin/sqlite3.dll first. The script puts the official SQLite 3.47.0 x64 DLL there, after checking its SHA-256 against the pin; bin/lib64/ is left as upstream shipped it. Skipped on other systems.
  8. WorldBridge. Copies worldbridge/*.cs and WorldBridge.csproj to <out>/.paracosm-build/worldbridge/, builds it there against <out>/bin (-p:OpenSimBin=<out>/bin/), and copies WorldBridge.dll into bin/. The repository is never written to.
  9. Config. Runs tools/make_config.py <out>/bin --env <env file>, which writes OpenSim.ini, config-include/StandaloneCommon.ini, config-include/FlotsamCache.ini, config-include/osslEnable.ini and Regions/Regions.ini from upstream's *.example files, our templates in config/ and the env file (a new region UUID is made once), and puts config/OpenSim.exe.config (log4net: OpenSim.log rolls at 20 MB, five old files kept) in place of upstream's copy. With no --env and no .env in the repository this step is skipped, and the command to run later is printed.
  10. Manifest. Writes <out>/paracosm-build.json: the repository commit, the version in VERSION, the zip hash, each patch's hash and files, every patched file's hash, the SQLite DLL's source (a download's URL, or a local file's name only) and hash, the hashes of OpenSim.dll and WorldBridge.dll, the config files written, and the host's OS, Python and SDK. The commit comes from git when the repository root is a checkout (with -dirty for uncommitted changes), and otherwise from build/source-commit, which git archive fills in (export-subst), so a build from a source release records its commit too.

The server is <out>/bin. The rest of <out> is the patched source tree it was built from.

build/make_release.py runs this script on a release's own source zip to make the prebuilt Windows server of a release: handbook/packaging.md.

Verify

The build checks itself and fails on any mismatch: the zip hash, every hunk of every patch, the patched files' hashes, the generated csproj, the key DLLs in bin/, the SQLite DLL hash, and the config files. To check by hand:

cd <out>
sha256sum -c <repo>/opensim-patches/patched-files.sha256     # every patched source file: OK
ls bin/OpenSim.dll bin/WorldBridge.dll bin/sqlite3.dll bin/OpenSim.ini bin/Regions/Regions.ini
cat paracosm-build.json

(sha256sum is in Git Bash on Windows; in PowerShell use Get-FileHash -Algorithm SHA256 per file.)

To run it: cd <out>/bin, then dotnet OpenSim.dll in a terminal. For running without a terminal (the REST console), see handbook/operations.md #5.

Changing a patch

Edit the file in a patched tree, then regenerate that patch's diff against the pristine file, keeping git-style paths (for a new file the old side is /dev/null):

diff -u --label a/<rel> --label b/<rel> <pristine>/<rel> <patched>/<rel>  >  opensim-patches/<name>.diff

(git diff --no-index also works.) Then update that file's line in opensim-patches/patched-files.sha256 (sha256sum <rel>, run from the patched tree's root), and list a new diff in opensim-patches/series. Upstream's files use CRLF line endings, and the diffs carry them: .gitattributes marks the diffs -text so git never rewrites them. Check with git apply --check or patch -p1 --dry-run on a fresh extraction.

Limits