saltyhotdog / BattletechIssueTracker

Public issue tracker to communicate with modders and HBS.
MIT License
6 stars 0 forks source link

Load External (Mod) Assemblies #3

Open mpstark opened 6 years ago

mpstark commented 6 years ago

Background Information The modding community uses several tools that allow modders to change game behavior at runtime. These tools are:

Harmony by Andreas Pardeike, a "library for patching, replacing and decorating .NET and Mono methods during runtime" developed out of the Rimworld modding community.

BattleTech Mod Loader (BTML) by myself, which injects a reference and a single method call into Assembly-CSharp.dll. This method loads Harmony and then loads external assemblies from the root of the Mods folder.

ModTek by myself, which is loaded by BTML, and handles the "fiddly bits" of modding -- loading mods from subfolders of the Mods folder, handling load order, merging mod JSON into game JSON, adding into the VersionManifest, and doing other things that enable mods to work.

With these three tools, modders should have nearly full access to change what they want, as long as they put the time into their research. The only one that requires modification of game files is BTML and it's the main stumbling block of users, as it needs to be re-run when the game updates, the install process is fairly non-intuitive, and since it includes a code injection tool, it is falsely flagged by anti-virus software.

It would be a great boon to the modding community if BTML could be replaced by an addition to the game that does largely the same thing -- load and run assemblies from the root of the Mods folder.

Describe the location in the code your suggestion is about Currently, BTML hooks into BattleTech.GameInstance's constructor and becomes the first thing that the constructor does. This is to allow mods to hook into the many different pieces of the game as they are loaded up.

An injected assembly has this modification to BattleTech.GameInstance.ctor:

public GameInstance()
{
    BTModLoader.Init();
    base..ctor();
    this.MessageCenter = new MessageCenter();
    this.MessageRecorder = new MessageRecorder(this.MessageCenter, this);
    //... the rest of the constructor ...
}

What is your suggestion for this code In GameInstances constructor, or potentially in another place that is loaded fairly early on, mod assemblies could be loaded. Below is a simplification of how BTML does it as an illustration of how this would be achieved.

var modDir = @"C:\Games\GOG Galaxy\Games\BATTLETECH\Mods\";
var dllPaths = Directory.GetFiles(modDir).Where(x => Path.GetExtension(x).ToLower() == ".dll").ToArray();
foreach (var dllPath in dllPaths)
{
    // load the assembly from the path
    var assembly = Assembly.LoadFrom(path);

    // get a class that contains a public static Init method
    var type = assembly.GetTypes().First(x => x.GetMethod("Init", BindingFlags.Public | BindingFlags.Static) != null);

    // get a reference to the method itself
    var entryMethod = type.GetMethod("Init", BindingFlags.Public | BindingFlags.Static);

    // invoke the method with no instance (method is static) and no parameters
    entryMethod.Invoke(null, null);
}

Again, this is a drastic simplification with no error checking, the source code of BTML is located here on GitHub, if further implementation details are desired. I suspect that HBS, if it chooses to take this step, will not use BTML's source whole-cloth, though BTML's source has been released to the public domain with no restrictions.

Leave any additional comments here Everyone reading this is a massive fan of the BattleTech franchise, and we all want this incarnation of the franchise to succeed on every level. For some of us, like myself, this is a game that we've been waiting for since our childhoods. I believe that most of the community understands the business decision to not ship with mod support. It costs dollars -- potentially lots of dollars.

Ultimately, this change isn't mod support, but it enables the community to build it for themselves without the fairly cumbersome process of patching Assembly-CSharp.dll.

caardappel-hbs commented 6 years ago

Some version of this is being considered for official DLC support. I'll report back as the design develops.

saltyhotdog commented 6 years ago

We'll resurrect this ticket when HBS announces their first DLC!

Morphyum commented 5 years ago

DLC was announced any updates on this?

caardappel-hbs commented 5 years ago

This work is officially slated for the 1.9 release.

mpstark commented 5 years ago

Thanks for the update!