mirror of
https://github.com/smartcmd/MinecraftConsoles.git
synced 2026-07-01 09:57:03 +00:00
Allowing plugins to be used as dependencies to other plugins (#16)
* fuck everything i did blegh * better exception tracking for plugins * Update PluginLoadContext.Load to return existing instances (basically, make plugin api references possible) * Update docs to help with plugin dependencies --------- Co-authored-by: UniPM <zoc6x8voc@mozmail.com>
This commit is contained in:
parent
8e66b2c19e
commit
50ab3597d0
|
|
@ -21,6 +21,13 @@ internal sealed class PluginLoadContext : AssemblyLoadContext
|
|||
if (assemblyName.Name == typeof(ServerPlugin).Assembly.GetName().Name)
|
||||
return typeof(ServerPlugin).Assembly;
|
||||
|
||||
foreach (var alc in AssemblyLoadContext.All)
|
||||
{
|
||||
var existing = alc.Assemblies
|
||||
.FirstOrDefault(a => a.GetName().Name == assemblyName.Name);
|
||||
if (existing != null) return existing;
|
||||
}
|
||||
|
||||
string? path = _resolver.ResolveAssemblyToPath(assemblyName);
|
||||
if (path != null)
|
||||
return LoadFromAssemblyPath(path);
|
||||
|
|
|
|||
|
|
@ -81,7 +81,13 @@ internal sealed class PluginLoader
|
|||
var assembly = context.LoadFromAssemblyPath(Path.GetFullPath(dllPath));
|
||||
|
||||
int found = 0;
|
||||
foreach (var type in assembly.GetTypes())
|
||||
Type[] types;
|
||||
try {
|
||||
types = assembly.GetTypes();
|
||||
} catch (ReflectionTypeLoadException ex) {
|
||||
types = ex.Types.Where(t => t != null).ToArray()!;
|
||||
}
|
||||
foreach (var type in types)
|
||||
{
|
||||
if (type.IsAbstract || type.IsInterface)
|
||||
continue;
|
||||
|
|
@ -173,9 +179,10 @@ internal sealed class PluginLoader
|
|||
MethodInfo? method = type.GetMethod(camelName, DeclaredPublic, Type.EmptyTypes)
|
||||
?? type.GetMethod(pascalName, DeclaredPublic, Type.EmptyTypes);
|
||||
|
||||
if (method != null)
|
||||
{
|
||||
method.Invoke(plugin, null);
|
||||
try {
|
||||
method?.Invoke(plugin, null);
|
||||
} catch (TargetInvocationException ex) {
|
||||
throw ex.InnerException ?? ex;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -264,6 +264,79 @@ When a plugin folder is made, make sure the main dll matches the name of the fol
|
|||
|
||||
You can also avoid this by using [Fody Costura](https://github.com/Fody/Costura) and bundle the dependencies into your DLL.
|
||||
|
||||
### Plugin Dependencies
|
||||
|
||||
In certain cases, like if you wanted to implement an addon to an already existing plugin, you can put the plugin in your .csproj and use functions from that plugin!
|
||||
|
||||
This is much like the Dependencies section above, but you shouldn't use Fody Costura for this.
|
||||
|
||||
Example of implementing external plugin functions:
|
||||
|
||||
```xml
|
||||
<ItemGroup>
|
||||
<Reference Include="CoolPlugin">
|
||||
<HintPath>.\CoolPlugin\CoolPlugin.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
```
|
||||
|
||||
```csharp
|
||||
public class PluginAddon : ServerPlugin
|
||||
{
|
||||
public override void onEnable() {
|
||||
CoolPlugin.CoolPluginAPI.CoolFunction(arg1, arg2, arg3);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```csharp
|
||||
public class CoolPluginAPI
|
||||
{
|
||||
// example API function
|
||||
public static void CoolFunction(arg1, arg2, arg3) {
|
||||
Console.WriteLine("This is a cool function!");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If the API wants to access instance variables (like a list from the main ServerPlugin), you will have to make sure the instance is already initialized.
|
||||
|
||||
This is because the plugin referencing the API might load before the actual plugin with the API. The API will be usable, but not the instance.
|
||||
|
||||
You can do this by initializing the instance in the API if its not already initialized.
|
||||
|
||||
```csharp
|
||||
public class CoolPlugin : ServerPlugin
|
||||
{
|
||||
private static CoolPlugin? _instance;
|
||||
public static CoolPlugin? getInstance() => _instance;
|
||||
internal static void setInstance(CoolPlugin inst) => _instance = inst;
|
||||
|
||||
// example instance variable
|
||||
internal List<int> coolList = [];
|
||||
|
||||
public override void onEnable() {
|
||||
// initializes the instance if it isn't already initialized
|
||||
instance ??= this;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```csharp
|
||||
public class CoolPluginAPI
|
||||
{
|
||||
// guarantee an instance when the API is used
|
||||
internal static CoolPlugin? getCoolPlugin() {
|
||||
if (CoolPlugin.getInstance() == null) CoolPlugin.setInstance(new CoolPlugin());
|
||||
return CoolPlugin.getInstance();
|
||||
}
|
||||
|
||||
public static void CoolFunction(arg1, arg2, arg3) {
|
||||
getCoolPlugin()?.coolList.Add(404);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Fody Costura
|
||||
|
||||
Fody Costura isnt very well documented, but heres the general usage guide that has worked for users:
|
||||
|
|
@ -300,4 +373,4 @@ Fody Costura isnt very well documented, but heres the general usage guide that h
|
|||
Build
|
||||
<p>After you've done all this, it should build and put all dependencies into one DLL in your output folder.</p>
|
||||
</li>
|
||||
</ol>
|
||||
</ol>
|
||||
|
|
|
|||
Loading…
Reference in a new issue