Wew lad, it's been a while. Aside from this post, I've got two neat little things to show off to you guys. But between then and now, I figured it'd be a good idea to make a short, boring old little post documenting the minor changes, updates, and revisions I've made to the project since the last time. One of those includes adding the project to source control, which means it'll now be much easier to track changes and updates I make over time. Go DevBlogs!
Re-organized the namespace
Is what it says on the tin really; re-organization. I re-jigged the way alot of the files, classes, etc were laid out within the program, which will make things a little more pleasing to the eye when working on it. I still have a little more to go in terms of the actual namespace (how stuff is structured in programmatic terms), and some funky partial classes to add in, but we'll get there at some point.
'Custom' 'Build' 'System'
I basically wrote a fat batch script which copies, pastes, moves, patches, and builds files whenever the main PsychoMod project is built. This will make it much easier to track where output files are (and hence push updates), and also will allow me to keep better track of the patchers we use (software used to add certain bits of code to .dll files). Hopefully when I get around to adding new hooks there will be less fuckery to deal with, and it'll make the whole process a little smoother.
I started packaging dependencies in both PsychoMod and FileBuilder (the compiler used to build dll's serverside). Basically, rather than having to have extra dll files added to the Managed folder on the client (or next to the FileBuilder exe), they can now be put inside the respective parts, and loaded either at runtime, or on an "as-needed" basis - I haven't decided which is better in the case of PsychoMod yet.
This is great, as it basically means less fuckery has to happen in terms of game files - I personally think we should try and keep them closer to vanilla files as possible, unlike other some cough clients which will completely butcher them.
Furthermore, updating means FShield will only have to stream the one dll, rather than also downloading and installing the other 8 or so dependencies (which may increase in the future). One downside to this is it takes longer to inject PsychoMod into the game, albeit only by a few seconds (at the very most), so it's no big deal really.
Mono.Cecil vs FileBuilder
I found out about this little tool called Mono.Cecil, and it's amazing. It basically allows you to load up a dll, and edit it via code. This is awesome for a small part of FileBuilder; let me explain why.
Say you have a dll loaded into a program (eg a mod loaded into the client), and you want to update it with a new version on the fly (something really important if you don't want people restarting their games every time you update a mod). Usually, you feed your injector the new dll, and it won't work. It thinks "hey, this dll is already loaded, what's the point of loading it again?". Instead, what you are required to do is update the AssemblyVersion of the dll into a version higher than what's currently loaded. Thankfully, C# makes this easy, as using "1.0.0.*" will make the AssemblyVersion auto-update every time you compile it. Previously, you would have to have this defined in every mod, which looked kind of shitty, and was a little redundant, as it was the same in every single mod:
But, using Mono.Cecil we can now add this when the file is compiled in FileBuilder, rather than in the code itself. This means we can remove that bit of redundant code from the .cs file, and have it auto-added in the FileBuilder instead:
NetUserHelpers and Remote Procedure Calls
In a game, when you want to call a piece of code on the client from the server (or vice-versa), you use something called an RPC - a Remote Procedure Call. In Unity, you have your two game object's, and you attach a network view to each. Then you assign the same network view to both, and boom, you can make calls between the server and client. With mods however, we don't quite have this luxury. For whatever reason, uLink (the networking library in Legacy) will refuse to dynamically assign a view ID to any network view we create ourselves. This means we are forced to assign them manually, which (from experience) causes issues with collisions, as we only have about 2^16 to play with. The way around this? Fairly simple - we just piggy-back off of one of the pre-existing network views. Which one? The main one for the player of course!
By adding an extension (a piece of code which extends the functionality of a class) within our PsychoMod Oxide extension (not to confuse the two), we are then able to make a call ('CallClientMethod'), passing the mod name, method name, and any arguments we wish (as long as they are serializable). This is then sent to an RPC receiver clientside, which is hooked by PsychoMod. PsychoMod then takes this information, finds the appropriate mod, and calls the given method using the provided arguments. This works great, and allowed me to make another neat little mod, which will help in writing plugins:
When writing plugins, especially doing server-side AntiCheat where dealing with raycasts, colliders, and positioning is critical, being able to view positions in the 3D world is insanely useful. In new Rust, this is trivial - you either spawn a small sphere at that position, or can send a command to the client which draws one for you. But in Legacy? Not so much. Not only do they not handily provide a command for drawing spheres, they also don't include many assets which can be dynamically spawned (somewhere between 10 and 30 in total, compared to new Rust's hundreds, if not thousands). Enter PositionHighlighter.
The idea is to use the aforementioned RPC calls (which are basically essential for this whole modding platform to be of any use), and have one of the calls spawn a sphere at given coordinates, of a given size and 'stay-alive' time. This means we can take positions serverside (such as the position of a sleeping bag, or a wood gate) and display them on the client via a little grey sphere, making it much easier to see whether the distances and positions you're using are appropriate. This won't mean much to any players, aside from the fact that it'll be a lot less stressful when developing new AntiCheat/AntiGlitch methods and patches.
Previously, I would have to do some next level hacky-code type shit to get the websocket responsible for streaming mods to shutdown properly when the server does. This worked okayyyyisshshh, but was still hacky as fuck. Turns out Oxide has an OnShutdown function which you can override in extensions (but isn't a hook for some reason cough, yet). All in all, I'm now using that, and I can once again be at peace with the world.
Compiler is now 10% less bootless, beetle-headed boor-pig
The compiler enjoyed having a fit whenever you felt like using it. It revelled in complaining about files being in use when they weren't (but still managing to compile them anyway), and was starting to do my head in. Not to mention, DraB really doesn't like big red errors.
I jumped in and swung my keyboard about, and managed to make things a little better. It seems to throw a fit slightly less often, but "don't you dare try to compile two mods at once or I'll av ya!" - I'll fix this at some point. Maybe.
Although it seems like little progress has been made, you have to bear in mind there is little reward for the amount of time inputted. Each of these subjects excluding the namespace tidying and the PositionHighlighter itself took multiple hours. Conglomerated into a single post, you're currently looking at a couple months of break and a couple more of progress. Not to mention this isn't all I have to talk about - I have been working on some more skitz shit.
In a few days time (at most) I may be be able to rustle something a little more exciting up for you. Some of you may already know what I'm probably going to show, but hopefully for a lot of you this'll be the first time you'll see it, at least in action. While we're on the topic of adding things, I've also got something short coming on removing things. Expect that to come first.