separate libs, internal plugins, and shutdown improvements

This commit is contained in:
zontreck 2024-12-18 16:19:34 -07:00
parent b0e8a4d459
commit b3bddfc5d1
7 changed files with 108 additions and 12 deletions

View file

@ -5,8 +5,8 @@ using System.Reflection;
[assembly: AssemblyCompany("Piccari Creations")]
[assembly: AssemblyAlgorithmId(System.Configuration.Assemblies.AssemblyHashAlgorithm.MD5)]
[assembly: AssemblyCopyright("(C) 2020 Tara Piccari")]
[assembly: AssemblyFileVersion("6.0.1.0001")]
[assembly: AssemblyCopyright("(C) 2020-2024 Tara Piccari")]
[assembly: AssemblyFileVersion("6.0.1.0002")]
[assembly: AssemblyDescription("ForgeCore Bot Server")]
namespace ForgeCore.Assemble
@ -14,6 +14,6 @@ namespace ForgeCore.Assemble
public class ASMInfo
{
public static string BotName = "ForgeCore";
public static string BotVer = "2.0.121724.1716";
public static string BotVer = "2.0.121824.1617";
}
}

View file

@ -23,8 +23,9 @@ public class ForgeCore
ArgumentBuilder builder = new ArgumentBuilder();
builder.withVersionArgument().withHelpArgument();
builder.withStringArgument("plugindir", "Plugins", true);
builder.withStringArgument("plugindir", "Plugins", false);
builder.withBooleanArgument("daemon", true);
builder.withStringArgument("libdir", "Libs", false);
Arguments defaults = builder.Build();
@ -41,20 +42,37 @@ public class ForgeCore
if (arguments.HasArg("plugindir"))
PluginSystem.PluginDirectory = arguments.GetArgument("plugindir").GetValue() as string;
if (!Directory.Exists("Plugins"))
Directory.CreateDirectory("Plugins");
if(arguments.HasArg("libdir"))
PluginSystem.LibraryDir = arguments.GetArgument("libdir").GetValue() as string;
if (!Directory.Exists(PluginSystem.PluginDirectory))
Directory.CreateDirectory(PluginSystem.PluginDirectory);
if(!Directory.Exists(PluginSystem.LibraryDir))
Directory.CreateDirectory(PluginSystem.LibraryDir);
PluginSystem.InitializeSystem(PluginSystem.PluginDirectory);
SharedSessionData sessionData = SharedSessionData.GetInstance();
// Subscribe to the interrupt event
Console.CancelKeyPress += delegate
{
Console.WriteLine("CTRL+C Detected. Processing shutdown request...");
SharedSessionData.GetInstance().ShouldShutdown = true;
};
// Start the server tick loop
while (!sessionData.ShouldShutdown)
{
long tasksExecuted = 0;
if (sessionData.TotalTasksPerTick == 0 && sessionData.TotalTicks > 0)
if (!sessionData.HasShutdownMethod)
{
sessionData.ShouldShutdown = true;
Console.WriteLine("FATAL ERROR\n\nNo plugins are loaded. This server would be doing nothing in a infinite loop with no way to exit. Aborting startup procedure. \n\n\n>> Recommendation: Add one of the standard ForgeCore Plugins which include methods of executing a shutdown");
Console.WriteLine("/!\\ FATAL ERROR /!\\\n\nNo plugin has a method for shutting down. This server would be unable to cleanly shut down. Consider adding a plugin with a shutdown method of any kind\n\nCTRL+C is not advised, as server settings may not get saved with an interrupt");
}
foreach (var plugin in PluginSystem.Plugins)

View file

@ -4,8 +4,8 @@ using System.Reflection;
[assembly:AssemblyCompany("Piccari Creations")]
[assembly:AssemblyProduct("ForgeCoreAPI")]
[assembly:AssemblyCopyright("Copyright (c) 2024 Piccari Creations")]
[assembly:AssemblyVersion("2.0.0.0")]
[assembly:AssemblyFileVersion("2.0.0.0")]
[assembly:AssemblyVersion("2.0.0.1")]
[assembly:AssemblyFileVersion("2.0.0.1")]
[assembly:AssemblyDescription("API Library for ForgeCore")]
@ -14,5 +14,7 @@ namespace ForgeCoreAPI.ASM
public class ASMInfo
{
// Static readonly assembly attributes
public static readonly string ASSEMBLY_NAME = "ForgeCoreAPI";
public static readonly string ASSEMBLY_VERSION = "2.0.121824.1618";
}
}

View file

@ -57,8 +57,10 @@ public interface IPlugin
public class ForgeCorePluginAttribute : Attribute
{
public string pluginName;
public ForgeCorePluginAttribute(string PluginName)
public bool providesShutdownMethod = false;
public ForgeCorePluginAttribute(string PluginName, bool ProvidesShutdownMethod = false)
{
this.pluginName = PluginName;
this.providesShutdownMethod = ProvidesShutdownMethod;
}
}

View file

@ -5,4 +5,5 @@ public class PluginContainer
public IPlugin plugin;
public bool enabled = true;
public string pluginName;
public bool providesShutdownMethod = false;
}

View file

@ -9,13 +9,14 @@ public class PluginSystem
public static string PluginDirectory { get; set; } = "Plugins";
public static List<PluginContainer> Plugins = new List<PluginContainer>();
public static string LibraryDir { get; set; } = "Libs";
private static void PSysLog(string Message)
{
Console.WriteLine($"[PLUGINS] {Message}");
}
public static void InitializeSystem(string pluginDirectory)
public static void InitializeSystem(string pluginDirectory, string libraryDirectory = "Libs")
{
CompoundTag pluginsData = new CompoundTag();
if (!File.Exists("PluginStorage.dat"))
@ -24,6 +25,66 @@ public class PluginSystem
// Leave pluginsData empty
} else pluginsData = NbtIo.Read("PluginStorage.dat");
// Search the primary executable for non-removable plugins
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (var type in asm.GetTypes())
{
if (type.GetCustomAttribute<ForgeCorePluginAttribute>() != null)
{
ForgeCorePluginAttribute attr = type.GetCustomAttribute<ForgeCorePluginAttribute>();
PluginContainer container = new PluginContainer();
container.pluginName = attr.pluginName;
container.providesShutdownMethod = attr.providesShutdownMethod;
IPlugin plugin = Activator.CreateInstance(type) as IPlugin;
container.plugin = plugin;
plugin.Initialize();
PSysLog($"> Loading plugin: {container.pluginName}");
Tag? store = pluginsData.Get(container.pluginName);
if (store == null)
{
plugin.ResetMemory();
}
else
{
CompoundTag plugTag = (CompoundTag)store;
CompoundTag data = (CompoundTag)plugTag.Get("data");
bool enabled = NbtUtils.ReadBoolean(plugTag, "enabled");
container.enabled = enabled;
plugin.LoadConfig(data);
PSysLog($"> Loaded plugin: {container.pluginName}");
if (enabled)
{
plugin.Enable();
PSysLog($"> Enabled plugin: {container.pluginName}");
}
else
{
plugin.Disable();
PSysLog($"> Disabled plugin: {container.pluginName}");
}
}
Plugins.Add(container);
}
}
}
// Search library folder for any libraries required to be loaded before the plugins
string[] libs = Directory.GetFiles(libraryDirectory, "*.dll");
foreach (string lib in libs)
{
Assembly.LoadFile(lib);
// We do not need to do anything else with the loaded library.
}
// Search the Plugins directory for DLL files
string[] files = Directory.GetFiles(pluginDirectory, "*.dll");
@ -48,6 +109,7 @@ public class PluginSystem
Tag? pluginStore = pluginsData.Get(attrib.pluginName);
nPlugin.pluginName = attrib.pluginName;
nPlugin.providesShutdownMethod = attrib.providesShutdownMethod;
PSysLog($"> Loading plugin: {nPlugin.pluginName}");
@ -55,6 +117,10 @@ public class PluginSystem
if (pluginStore == null)
{
plugin.ResetMemory();
plugin.Enable();
nPlugin.enabled = true;
PSysLog($"> Loaded plugin: {nPlugin.pluginName}");
PSysLog($"> No existing settings found for plugin: {nPlugin.pluginName}");
}
else
{
@ -82,5 +148,11 @@ public class PluginSystem
}
}
}
// Check if any plugin provides a shutdown method
foreach (var plugin in Plugins)
{
if (plugin.providesShutdownMethod) SharedSessionData.GetInstance().HasShutdownMethod = true;
}
}
}

View file

@ -18,4 +18,5 @@ public class SharedSessionData
public long TotalTicks { get; set; } = 0;
public long TasksLastTick { get; set; } = 0;
public long TotalTasksPerTick { get; set; } = 0;
public bool HasShutdownMethod { get; set; } = false;
}