1

I'm making a modding system for my game in Godot, where the modders write their code in C# and compile it to a DLL, which the game loads and executes methods from.

The relevant part of the compile method (returns an Assembly)

string dll = //the absolute path...
if (File.Exists(dll)) {
   return Assembly.LoadFrom(dll);
}

Then I invoke the method like this:

    private void ExecuteModMethod(Mod mod, string methodName, object[] methodParameters)
    {
        if (!useMods) return;
        Type type = mod.Assembly.GetType(mod.Name+".Main");
        if (type == null) return;
        MethodInfo method = type.GetMethod(methodName);
    
        mod.Instance = Activator.CreateInstance(type);
        if (method == null) return;
        method.Invoke(mod.Instance, methodParameters);
    }

When I try to invoke the _Ready method, (the Godot init method, that the modders should also name their init method), I get Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

This is the only code file in the mod:

using Godot;


namespace TestMod
{
    public class Main
    {
        //Called when the game is loaded
        public void _Ready()
        {
            GD.Print("Hello from the mod!");
        }
    }
}

I don't know much about DLLs and this sort of thing so any help is appreciated. I just need the error to go away because it stops execution of the application and so no method is invoked.

NOTES

  • I know this is really dangerous and modders could include malware. I will deal with this problem, you don't need to mention how dangerous it is, thanks.
  • This is the only error thrown, the dll path, type, method and mod.Instance are all not null. That is not the problem.
5
  • To get the error fixed, because nothing happens Commented Oct 19, 2024 at 5:12
  • I'm not sure how you want to make the error go away. Usually you can't handle AccessViolationException, you can only discard the process. If you want to fundamentally solve this error, you need to tell us the content of the _Ready method and which specific statement it failed in. Commented Oct 19, 2024 at 5:30
  • I have updated the question to show the code file Commented Oct 19, 2024 at 5:32
  • Thanks, that's promising, I'll take a look Commented Oct 19, 2024 at 5:52
  • Ok, I've looked at it and I can see how it would work. The thing is, that it is important the modders, for example, can use Nuget packages and their own custom application extensions, which would not work if only the Godot and my game assemblies were added to the mod. Another way that this might be possible, is to make the game do something with the csproj and use that in some way, but that's just a thought... Commented Oct 19, 2024 at 6:04

1 Answer 1

1

Godot has 3 AssemblyLoadContexts on initial:

  • Internal.Runtime.InteropServices.IsolatedComponentLoadContext
  • GodotPlugins.PluginLoadContext
  • System.Runtime.Loader.DefaultAssemblyLoadContext

Your scripts are loaded in the second ALC, so you need to load your mod assemblies into this ALC too, the ALC will resolve Godot's assemblies. Because Assembly.LoadFrom loads assemblies into the default one, you need to replace it with the follow code:

var executingASM = Assembly.GetExecutingAssembly();
var executingALC = AssemblyLoadContext.GetLoadContext(executingASM);
var fullDllPath = Path.GetFullPath(dll);
return executingALC.LoadFromAssemblyPath(fullDllPath);
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.