Be ready to expect a series of smaller bite-sized updates (compared to my previous "book") as I catch you all up on the current progress of the Clientside Modding project. I'm going to write each post as if I had just created each piece, to keep it all consistent. In this post, I'll take a minute to talk about the compiler running server side.
Depending on how familiar you are with C# development (or programming/software development overall), you may or may not be aware of how programs are written and created. If you're not, let me give you a brief overview (feel free to skip this if you're already a l33t coder).
If you read my last post, you might've heard me talk about libraries. These are essential in C# - collections of code and data that allow you to do stuff. I also talked about the Managed folder - this is a collection of libraries that are loaded up into the game at runtime (when the game starts), which contains all the code for the game. Our goal here is to add some of our own code to that big code-soup, so we need to create our own library. C# libraries are stored in .dll files, but unfortunately we can't edit .dll files directly. Instead we have to run our source code (stored in .cs files, which are basically text files but with a different extension) through a compiler. This compiler takes our source code, checks it for errors, and eventually spits out a .dll file. So, unless we want to create a new project every time we want to make a new mod (I'd rather not), we're going to need a nice little compiler.
We start off with a fresh C# console program project. Title? FileBuilder. Gracious, I know. The idea here is we want to start the program, and feed it three arguments: input file, output file, and a references path (I'll explain this part in a minute). Luckily for us, Microsoft kindly provide an entire library for compiling stuff. It goes by the name of: "Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider" (bit of a mouthful eh Microsoft?). With a bit of prodding we can take our input file, throw it at the compiler, and it will spit out a .dll. Perfect!
But Psycho! The "references"?? What are dis ?
Calm young grasshopper - I haven't forgotten. When you write any piece of software, chances are you're going to want to use other libraries. I mean, since we're writing a mod for Legacy, we're going to need to access some of the code from Legacy. The problem is with our compiler, is that when we write "Player.MakeScreenGoBlack()" in our code, the compiler doesn't know what a "Player" is, or if we're using the function "MakeScreenGoBlack" correctly, or if it even exists. This is where references come in - references show the compiler all the other libraries we may have used to write our program - now the compiler knows "Player.MakeScreenGoBlack()" does indeed exist, and we are (surprisingly) using it correctly.
Once we hit the magic Control + Shift + B key-wombo-combo we can build our program into an exe file, and with a quick test in Command Prompt we can verify it's working correctly.
Linking with the extension
Since we can't open programs directly from plugins (remember those plugin limitations I talked about in the last post?), we're going to have to add this to the extension. No problem! I actually decided to use multithreading for this. This means theoretically, everything is handled on another thread from main, and that way we don't get big lags when @DraB decide he needs to compile a random file he downloaded off the internet. When we call CompileFile(), we create a new thread, add it to a list of threads, and then start that thread by calling our _compileFile() function which is responsible for the actual compilation. Then when we're done, we can clean up the threads and call it a day.
Why does this make Ben's life easy?
Good question. When I write a mod, here's what I'd have to do before:
1) Create an entire new Visual Studio project
2) Write some code
3) Build the project
4) Copy my dll into the mods folder
5) Restart my game
As you can see this (mainly creating an entire VS project) is pretty inefficient. But now?
1) Create a new .cs file
2) Write some code
3) Type "mods.compile <name>"
4) Restart my game
Much better. I still spy on some steps we can knock out here, but we'll get onto them later.
As usual, I made a short video showcasing this functionality:
Thanks for reading! To be honest - I thought this update would be about 5 words, but I guess I have a knack for over-complicating things. As always, make sure to keep your eyes peeled for more progress on the project!