Leohearts

拥有一颗坚强而又温柔的心 *version 1.1

cover

Guide: Use Sandboxed tModLoader to Develop Mods

In tModLoader, the Develop Mods section is disabled in sandboxed environments, such as flatpak. But instead of creating a containment breach of PrOprIetarY software (steam), or take a long time building steam with dotnet sdk attached, how could we develop mods without taking tModLoader out of sandbox ?

Debelopment

It's easy to bootstrap a Terraria mod - just fork an example mod on Github, grab your favorite text editor and write C# like what you are good at on other open source projects.

To build it without using tModLoader's UI, you will need to put your source directory under the ModSources folder, typically ~/.var/app/com.valvesoftware.Steam/data/Terraria/tModLoader/ModSources/, in which a file called tModLoader.targets exists.

Now we have our targets, dotnet build in your project will, if nothing goes wrong, produce an DLL file. then , cd to your tModLoader install dir, dotnet tModLoader.dll -build [Your source dir] will give you a .tmod file. Copy that .tmod file from ~/.local/share/Terraria/tModLoader/Mods/ to ~/.var/app/com.valvesoftware.Steam/data/Terraria/tModLoader/Mods/, and you will be able to load and play it in tModLoader.

Publish to Steam Workshop (Optional)

If you just want to play a mod yourself, it's done! But unfortunately, working with Workshop needs tModLoader development UI. That means, we must start over to the hard path.

Let's take a look to tModLoader's source code. How does it detect sandboxes ?

Reading source

Searching the error message leads us to UIModSources.cs#L264, which says they first detect IsCompatibleDotnetSdkAvailable, if not, check if IsRunningInSandbox.

Digging into IsCompatibleDotnetSdkAvailable. They use ModCompile.StartOnHost to invoke dotnet --list-sdks.

Then ModCompile.StartOnHost checks if PRESSURE_VESSEL_RUNTIME presents, if yes, wrap it with steam-runtime-launch-client.

Since it's invoked without an absolute path, we could inject our own steam-runtime-launch-client to it's $PATH.

PATH injection attack

in start-tModLoader.sh, replace the last line with this:

PATH="./bin:$PATH" ./LaunchUtils/ScriptCaller.sh "$@" &

Next, create a folder in tModLoader installation dir named bin.

create a file steam-runtime-launch-client:

#!/bin/sh
echo $@ | sed 's#--alongside-steam --host -- ##' | PATH=`echo $PATH|sed 's@./bin:@@'` steam-runtime-launch-client --alongside-steam --host -- /usr/bin/flatpak-spawn --host sh

dont forget to give that file executable permissions.

Allow Steam to use dotnet SDKs on the host

flatpak override com.valvesoftware.Steam --talk-name=org.freedesktop.Flatpak

Done! You can also do this with Flatseal or your distro's permission control page.

Now if everything went well, You'll be able to see tModLoader's Develop Mods page.

One more thing ?

Since tModLoader builds the mod in our host environment, the .tmod file will be placed under ~/.local/share/Terraria/tModLoader/Mods/. In order to publish it to Steam, you need to hard link the mod file to ~/.var/app/com.valvesoftware.Steam/data/Terraria/tModLoader/Mods/, because tModLoader's inner logic are still running in flatpak.

If you get File is open error, just make sure the mod file is hard linked, and restart your tModLoader.

Behind the story

This is a write-up for my own Terraria mod development with Linux and Flatpak. It took me <1h to write C# code for my mod (Chat Filter), ~2h for this hack, and 30m to write this down.

This work is licensed under
Creative Commons Attribution-NonCommercial 4.0 International

添加新评论