FunkFrog / ShareSuite

Risk of Rain 2 Item, Money, & Equipment sharing mod build upon BepInEx
https://thunderstore.io/package/FunkFrog-and-Sipondo/ShareSuite/
GNU General Public License v3.0
39 stars 26 forks source link

Make entrypoint for other mods to add money #67

Closed harbingerofme closed 4 years ago

harbingerofme commented 4 years ago

Is your feature request related to a problem? Please describe. Mods are currenunable to add money easily when moneysharing is enabled.

Describe the solution you'd like A method in the main plugin class to add money to a charactermaster/body. This could be found using reflection so that other mods can make themselves compatible with sharesuites moneysharing.

Describe alternatives you've considered The better solution would be changing how money is handled by sharesuite in the firdt place, but the first solution provides a bandaid fix.

Additional context BiggerBazaar and Debugtoolkit are noteworthy incompatibilities.

harbingerofme commented 4 years ago

EDIT: I have since learned a better way, see my comment down below.

Such a method could be retrieved and cached by external plugins like so:

private MethodInfo AddMoney = null;
private BaseUnityPlugin ShareSuite = null;
private void Start(){
            if (Chainloader.PluginInfos.ContainsKey("com.funkfrog_sipondo.sharesuite"))
            {
                ShareSuite = Chainloader.PluginInfos["com.funkfrog_sipondo.sharesuite"].Instance;
                AddMoney = ShareSuite.GetType().GetMethod("AddMoneyExternal", BindingFlags.Instance | BindingFlags.Public);
            }
}

And then be called at any point later like so:

if(ShareSuite)
        AddMoney.Invoke(ShareSuite, new object[] { amount });

If an external plugin wants to call the chainloader during their constructor or their Awake, they will need to add

[BepInDependency("com.funkfrog_sipondo.sharesuite",BepInDependency.DependencyFlags.SoftDependency)]

To their plugin class. This ensures BepInEx loads sharesuite before them and thus the sharesuite instance exists.

FunkFrog commented 4 years ago

Added in 1.15.0. AddMoneyExternal in the MoneySharingHooks class.

harbingerofme commented 4 years ago

To enable cross compatibility of your mod with ShareSuite, you will need to do the following things:

You must use those additional methods, because an end user might not have ShareSuite installed, so the types for it may not be in the AppDomain, causing the JIT to crash. You may combine those additional methods if you really want to, but make sure they aren't being tried to call whenever you are not sure that ShareSuite is currently available.

Here's an example:

using ShareSuite;

class myPlugin {
private bool hasShareSuite= false;

public void awake(){
    if (Chainloader.PluginInfos.ContainsKey("com.funkfrog_sipondo.sharesuite")) {
          this.hasShareSuite = true;
    }
}

void myMoneyAddingStuff(CharacterMaster target, int amount){
    if(this.hasShareSuite && checkUseShareSuite()){
        //maybe divide the amount of money gained by players in the game or something, who knows?
        giveMoneyShareSuite(amount);
        return;
     } else {
        target.GiveMoney(amount);
    }
}

[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
bool checkUseShareSuite(){
    return ShareSuite.ShareSuite.MoneyIsShared.Value;
}

[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
void ShareSuiteGive(int amount)
{
      ShareSuite.MoneySharingHooks.AddMoneyExternal(amount);
}

}

You'll notice I use [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] to make double sure that the JIT doesn't try anything wonky.