Skip to content

Quick Start

This is the fastest way to go from nothing to your code running on a server. Code created by users is referenced as "UGC bundles" from here on.

Info

The tl;dr on what a bundle is: .wasm blobs for server, client or both and a config.toml manifest in a folder

This guide uses the official project template, which sets up both components, the manifest and the build in one step.

You need the .NET 10 SDK or newer on Windows or Linux, x64 or arm64. Everything else, including the NativeAOT compiler and the WASI SDK, is downloaded by the NuGet packages on your first build.

winget install Microsoft.DotNet.SDK.10
curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --channel 10.0

Alternatively install the dotnet-sdk package from your distribution.

If you want to see the bundle running right away, you also need a server. See Quick Start in the server documentation.

1. Install the template

dotnet new install replay.blackice.template

The template is published on nuget.org. You only have to install it once. Run the same command again later to update it.

2. Create your bundle

dotnet new blackice-bundle -o my-bundle
cd my-bundle

Whatever name you specify will be the name of your bundle. It will be created in the directory you are currently in. You should not create bundles in the data/ugc/ dir directly, rather make use of the --serverDir argument to automatically symlink the dist/ dir into into the servers bundle root.

You get this layout:

my-bundle/
├── sv/                 server component, entry point sv/App.cs
├── cl/                 client component, entry point cl/App.cs
├── sh/                 code compiled into both components
├── data/config.toml    the bundle manifest
└── dist/               the assembled bundle, written by every build

sv/, cl/ and sh/ are ordinary C# projects, albeit AOT compiled to WebAssembly. Put server-side logic in sv/, per-player logic in cl/, and anything both need, such as net event payloads, in sh/. The manifest in data/config.toml describes what the bundle contains. See Project Layout for what belongs where and Bundle Config for every manifest option.

3. Build it

dotnet build

This will create a debug build. This is what you should use while developing to get the best info out of stack traces when things go wrong. Once you are finished, build via dotnet build -c Release to get an optimized and stripped build.

Each build stages the manifest and both compiled components into dist/:

dist/
├── config.toml
├── sv.wasm
└── cl.wasm

The contents of dist/ are whats considered the bundle itself.

4. Run it

If you did not use the --serverDir option during creation, you can symlink dist/ into the server UGC folder once like this:

dotnet build -p:BundleServerDir=/path/to/server

The first build creates the link, a symlink on Linux and a junction on Windows, at <server>/data/ugc/my-bundle.

Without a link, copy the contents of dist/ into <server>/data/ugc/my-bundle/ yourself.

After creating a new symlink, restart your server once to ensure its picked up. Copying files should work at any time, same goes for updating existing data either via copy or inside the symlinked directory.

bundles         # Lists all bundles and their state
start my-bundle # Start a specific bundle by name

Done! If you print anything using Console.WriteLine in your Start function, it will now show up in the console and log.

5. Rebuild while you work

dotnet watch --project sv build

This watches sv, cl and sh and rebuilds on every save. dotnet watch accepts a single project, so watching sv also covers the rest. Restart the bundle on the server to load the new blobs.

Next steps

  • Project Layout - Detailed explanation of what goes into sv/, cl/ and sh/
  • Bundle Config - The bundle manifest and every option it supports
  • Script API - Commands, events, hooks, HTTP, database access and much more
  • Bundle IO - Console output, the server side VFS and other options of communicating "outside" the sandbox
  • Web UIs - Adding an in-game interface to your bundle, with every web technology you would expect