
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.
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
![]()
![]()
![]()