Exporting Func/Actions in C#?

Hello,

So, I have two scripts. One called “quostix” which is essentially the framework, and another “quostix-vehicles” that needs to access data and functions from “quostix”.

I have all player information loaded into a dictionary that is stored in “quostix”:

public static Dictionary<string, Obj> LoadedPlayers = new Dictionary<string, Obj>();
  1. This all works completely fine within “quostix” but the problem arises when I try to export to “quostix-vehicles”.
public class Obj
{
    public string                      Handle     { get; set; }
    public string                      Identifier { get; set; }
    public string                      Group      { get; set; }
    public CharacterObj                Character  { get; set; }
    public StatusObj                   Status     { get; set; }
    public Dictionary<string, ItemObj> Inventory  { get; set; }
    public LicensesObj                 Licenses   { get; set; }
    // I have removed the other classes etc to shorten the post.
    // So this works and the data is accessiable.

    // But I also have these:
    internal Func<dynamic> GetInventory;
    internal Func<string, dynamic> GetInventoryItem;
    internal Func<string, dynamic> GetInventoryItemSlot;
    internal Func<string> FindEmptySlot;
    internal Action<string, int, dynamic, double, string> AddInventoryItem;
    internal Action<string, int, string> RemoveInventoryItem;

    internal Func<int> GetCash;
    internal Action<int> AddCash;
    internal Action<int> RemoveCash;

    internal Func<string, bool> CheckLicense;
    internal Action<string, bool> UpdateLicense;
}

If I try and access these functions within “quostix”, they work, but they don’t exist upon export, example:

try
{
    dynamic playerObj = Exports["quostix"].GetPlayerObj(player.Handle);
    string  type      = data.Payment;

    int bank = playerObj.Character.Bank.Balance; // <- This works.
    int cash = playerObj.GetCash();              // <- This does not work.
    // This also causes the exception to throw because "GetCash" does not exist
    // in the export despite it working inside "quostix".
}
catch (Exception ex)
{
    Debug.WriteLine($"[^2quostix-vehicles^7] [^1ERROR^7] {ex.Message}");
}

I’m clearly doing something wrong but I’m unsure as to what. I have tried adding “quostix” as a reference in “quostix-vehicles” but this creates another instance and then everything happens multiple times.

  1. Why do these Func/Actions not export?
  2. What can I do to fix my code to solve this issue? Am I exporting wrong or am I doing it in the completely wrong way?

My one solution was to turn all of the Func/Actions into exports and access them via:

Exports["quostix"].GetCash(player.Handle);

But I’m not sure if this is a “bodged” way of doing it.

Help would be appreciated.
Quostix.

I don’t think class functions in msgpack. Though I would wait for someone more familiar with the C# runtime to confirm/give you a work around.

Can you confirm how you’re registering the exports.

This is how I’m registering the export:

Exports.Add("GetPlayerObj", new Func<string, dynamic>(GetPlayerObj));

I misread your post earlier and didn’t see what you were trying to do. Avarian, as far as I know, is correct.

This, or use events and callbacks.

AvarianKnight is correct, functions and field stored delegates aren’t serialized in this manner.

As this is about delegates stored in fields; this may technically be supported with a custom MsgPack serializer, but doing so we’ll make it really easy for everyone to build bad performing applications, we’d be failing: “Make it easy to use it right, hard to use it wrong”.

With most C# resources (not limited to) it’s best and most performant to keep everything in 1 project, no slow inter-runtime calls as every such call comes with a performance hit. Then only open up exports for other resources where it’s really necessary.

Edit: I first thought this was about serializing functions.

1 Like

Thank you for the replies everyone, I appreciate it.

So from my understanding then, if I want to continue the way I am thus far, I’ll need to rework the way I am using the export and make multiple exports for each Func/Action instead of one “global” one. However, this would be the inefficient way to achieve the result I want and I should do the latter and have 1 project.

To clarify the second point. So, I started with Lua - and having several seperate resources was the norm but if I’m understanding correctly, instead of having multiple resources as “quostix”, “quostix-vehicles”, “another_resource”, “resource_again” and so on and so forth, I should essentially include ALL of those within “quostix” instead and eventually end up with 1 massive project?

Correct,

Sending a function/delegate to another runtime comes with the necessary logic to keep them active and open to be called, including holding onto all the objects it may reference, so you may end up with a lot of unused objects, that per each of these delegates on all of these objects. Also; you’re sending a (serialized) copy of the object, not a reference to it, so updating any data will not be reflected to any other runtime. All of this is not a thing if it’s within 1 project, referenced libraries included, granted you use no events, exports, etc.

I should essentially include ALL of those within “quostix” instead and eventually end up with 1 massive project?

By default; yes, C# projects are already designed for big projects, organization and all. You may also look into creating library assemblies, but that in general is more interesting for shared code. Personally I would only create separate resources for elements that are not codependent, some of those things may be assets.

Hope that helps

1 Like

That does help, thank you for taking the time to explain it to me.