to build a mod for valheim (sort of)
Valheim is an open-world survival game. You play as a dead Viking warrior that Odin has resurrected to kill some baddies. There's almost no introduction or tutorial. You just get dumped, naked, onto a procedurally-generated continent, and have to figure everything out from there.
It's great. I've put over 800 hours into it.
Valheim runs on the Unity game engine, which means it's infinitely modifiable. I play with a couple mods, nothing serious, just a few “make farming marginally faster” and “reduce rage when things fall into the water” tweaks. I also use a mod that organizes the many game world servers I frequent, since the built-in server organization tooling is (was, really) non-existent. The mod is called QuickConnect, and it gives me a nice set of buttons that will connect and authenticate me to all my servers.
With a recent game update to Valheim, that authentication bit fell over. Not to worry, thunk I, for I am a ✨programmer✨.
So what you need to understand is that technically yes, I'm a software engineer, that's been my degree and day job and occasionally my hobby for a couple decades, but I don't make games. I don't mod games. I play games? I play games. Once upon a time I patched some World of Warcraft mods in Lua. That's the extent of my game-development experience.
code is code
That's ok, it's all just code and I'm not even building something new, I just want to fix a broken thing. How hard can it be to add a semicolon or whatever the thing needs. Let's look at the code!
QuickConnect.sln
QuickConnect/QuickConnect.csproj
Ah yes, I remember these file extensions. This is a C# project from Visual Studio. Ok I'm not buying Visual Studio but didn't Microsoft fork Atom? They've gotta have good support for their own platform in their own IDE, right? I bet they'll even hold my hand to get me set up.
step 1: make myself a working dev environment
I was starting from absolute scratch, so I clicked the “install stuff” buttons on this helpful setup page until I had Visual Studio Code installed with some semblance of a .NET SDK.
VSCode will do many Git things for me, and I'm not faffing around with real work on Windows, so I installed Git for Windows with as many of the defaults as I could stomach and used VSCode to clone the QuickConnect repository.
Cool, I have the code and the environment. Uh. Build, I guess?
C:\Users\ellotheth\projects\QuickConnect> dotnet build
💥💥💥💥
No. Wrong. Errors everywhere. Let's attack this from a different angle: How would one start writing a new Valheim mod?
step 2: make myself a WORKING dev environment
QuickConnect (and really all the mods I use in Valheim) requires this other mod called BepInEx. It's some sort of foundational modding platform that all other mods build on, so I started there and was immediately rewarded with another beginner setup guide. I'd already done most of the things on the first page:
C:\Users\ellotheth>dotnet --list-sdks
7.0.101 [C:\Program Files\dotnet\sdk]
I got far enough into the second page of the BepInEx guide that I found all my relevant library version numbers in all the various and sundry DLLs from the guide. I created the starter plugin, started clicking around, and realized that all the important stuff is in the *.csproj
file. Back to QuickConnect.
step 3: when you say “working dev environment”
Opening the QuickConnect project in VSCode spat a long string of errors about missing .NET frameworks into the console. QuickConnect.csproj
helpfully indicates which .NET framework I actually needed:
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
so I went and picked that up too. (Really I picked up 4.8.1, thinking it would be the same. It was not. I needed 4.8, exactly. My system is swimming in .NET frameworks at this point.)
step 4: dependencies
When I opened the project back up in VSCode, the errors about the missing .NET framework were gone, but Intellisense had vomited all over the actual code with red squiggles (indicating undefined references). Scrolling further in QuickConnect.csproj
revealed a big list of what appeared to be relative paths to DLLs that didn't exist:
<ItemGroup>
<Reference Include="0Harmony">
<HintPath>..\Libs\0Harmony.dll</HintPath>
</Reference>
<Reference Include="assembly_guiutils">
<HintPath>..\Libs\assembly_guiutils.dll</HintPath>
</Reference>
<Reference Include="assembly_valheim">
<HintPath>..\Libs\assembly_valheim.dll</HintPath>
</Reference>
<Reference Include="BepInEx">
<HintPath>..\Libs\BepInEx.dll</HintPath>
</Reference>
<Reference Include="BepInEx.Harmony">
<HintPath>..\Libs\BepInEx.Harmony.dll</HintPath>
</Reference>
<!-- you get the idea -->
</ItemGroup>
QuickConnect is currently modding my active Valheim installation, so I know those DLLs exist somewhere. I went hunting through my Valheim program files in %steamapps%
and found Valheim\valheim_Data\Managed
and Valheim\unstripped_corlib
. “Unstripped” sounded like a good thing for a development environment (assuming “stripped” means what it usually means, lacking debug symbols and tables and whatnot), so I grabbed everything I could out of there, and filled in the rest from valheim_Data\Managed
. I created that ..\Libs
folder from the *.csproj
file and copied all my new DLLs over.
This whole process seemed weird. Is it weird? If I'm referencing libraries shouldn't they all exist someplace where everything can use them? Should I have changed the paths in the project? Do these DLLs get statically built into the final DLL, or does the final DLL just assume they'll be available and croak if they're not?
Who knows. It's Windows, everything is chaos.
step 5: build? build!
With my DLLs in place, the VSCode console stopped shouting at me (except for an F# tool window that insists it can't open the project it just opened), and Intellisense settled down. I took a shot in the dark and renamed what I hoped was the output basename:
<AssemblyName>QuickConnectFixed</AssemblyName>
so I'd be less likely to confuse it for the original, and
C:\Users\ellotheth\projects\quickconnect> dotnet build
MSBuild version 17.4.0+18d5aef85 for .NET
Determining projects to restore...
Nothing to do. None of the projects specified contain packages to restore.
QuickConnect -> C:\Users\ellotheth\projects\quickconnect\quickconnect\QuickConnect\bin\Debug\QuickConnectFixed.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.67
Success! I have a new DLL!
C:\Users\ellotheth\projects\quickconnect> dir QuickConnect\bin\Debug
Volume in drive C has no label.
Volume Serial Number is 848D-2041
Directory of C:\Users\ellotheth\projects\quickconnect\QuickConnect\bin\Debug
2022-12-15 20:28 <DIR> .
2022-12-15 20:28 <DIR> ..
2022-06-23 07:23 204,800 0Harmony.dll
2022-06-23 07:23 267,107 0Harmony.xml
2022-12-06 14:12 22,016 assembly_guiutils.dll
2022-12-06 14:12 1,310,720 assembly_valheim.dll
2022-06-23 07:23 116,224 BepInEx.dll
2022-06-23 07:23 5,632 BepInEx.Harmony.dll
2022-06-23 07:23 4,056 BepInEx.Harmony.xml
2022-06-23 07:23 85,730 BepInEx.xml
2022-12-15 20:56 12,288 QuickConnectFixed.dll
2022-12-15 20:56 40,448 QuickConnectFixed.pdb
2022-06-04 21:58 1,149,952 UnityEngine.CoreModule.dll
2022-06-04 21:58 92,672 UnityEngine.dll
2022-06-04 21:58 160,768 UnityEngine.IMGUIModule.dll
2022-06-04 21:58 230,912 UnityEngine.UI.dll
14 File(s) 3,703,325 bytes
2 Dir(s) 162,917,765,120 bytes free
And a bunch of old DLLs, I guess the ones I'd copied? That's fine, I just need the one! Probably! It even worked when I installed it as a Valheim mod!
Well, for some values of “worked”. I haven't actually fixed the authentication problem yet. But it loaded and did the things it usually does, and that whole experience took like a couple hours, so I'm moving the goalposts and claiming the match. And getting snacks. Maybe some tea.