diff --git a/Minecraft.Server.FourKit/FourKitHost.cs b/Minecraft.Server.FourKit/FourKitHost.cs
index 51f1b128..15f49637 100644
--- a/Minecraft.Server.FourKit/FourKitHost.cs
+++ b/Minecraft.Server.FourKit/FourKitHost.cs
@@ -25,9 +25,15 @@ public static partial class FourKitHost
// host exe's directory instead so end users see a top-level plugins/.
string hostExePath = Environment.ProcessPath ?? AppContext.BaseDirectory;
string serverRoot = Path.GetDirectoryName(hostExePath) ?? AppContext.BaseDirectory;
+
+ // Redirect AppContext.BaseDirectory to the server root so that
+ // plugins using AppContext.BaseDirectory get the exe directory
+ // instead of the runtime/ subfolder.
+ AppContext.SetData("APP_CONTEXT_BASE_DIRECTORY", serverRoot + Path.DirectorySeparatorChar);
+
string pluginsDir = Path.Combine(serverRoot, "plugins");
s_loader = new PluginLoader();
- s_loader.LoadPlugins(pluginsDir);
+ s_loader.LoadPlugins(pluginsDir, serverRoot);
s_loader.EnableAll();
ServerLog.Info("fourkit", "Plugin system ready.");
diff --git a/Minecraft.Server.FourKit/Plugin/ServerPlugin.cs b/Minecraft.Server.FourKit/Plugin/ServerPlugin.cs
index a4fd94f2..c3358039 100644
--- a/Minecraft.Server.FourKit/Plugin/ServerPlugin.cs
+++ b/Minecraft.Server.FourKit/Plugin/ServerPlugin.cs
@@ -28,6 +28,22 @@ public abstract class ServerPlugin
///
public virtual string author { get; } = "Unknown";
+ ///
+ /// The server's root directory (where the server executable lives).
+ /// Use this instead of AppContext.BaseDirectory which points
+ /// to the .NET runtime subfolder. Set automatically before
+ /// is called.
+ ///
+ public string serverDirectory { get; internal set; } = string.Empty;
+
+ ///
+ /// A per-plugin data directory (plugins/<PluginName>/).
+ /// Created automatically if it does not exist. Use this for config
+ /// files, logs, databases, or any plugin-specific storage.
+ /// Set automatically before is called.
+ ///
+ public string dataDirectory { get; internal set; } = string.Empty;
+
///
/// Called when this plugin is enabled
///
diff --git a/Minecraft.Server.FourKit/PluginLoader.cs b/Minecraft.Server.FourKit/PluginLoader.cs
index baecfcd0..9dd89af9 100644
--- a/Minecraft.Server.FourKit/PluginLoader.cs
+++ b/Minecraft.Server.FourKit/PluginLoader.cs
@@ -10,11 +10,16 @@ internal sealed class PluginLoader
BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
private readonly List _plugins = new();
+ private string _serverRoot = string.Empty;
+ private string _pluginsDirectory = string.Empty;
public IReadOnlyList Plugins => _plugins.AsReadOnly();
- public void LoadPlugins(string pluginsDirectory)
+ public void LoadPlugins(string pluginsDirectory, string serverRoot)
{
+ _serverRoot = serverRoot;
+ _pluginsDirectory = pluginsDirectory;
+
if (!Directory.Exists(pluginsDirectory))
{
ServerLog.Info("fourkit", $"Creating plugins directory: {pluginsDirectory}");
@@ -136,8 +141,15 @@ internal sealed class PluginLoader
{
try
{
- InvokePluginMethod(plugin, "onEnable", "OnEnable");
string pName = GetPluginString(plugin, "name", "getName", "GetName", plugin.GetType().Name);
+
+ plugin.serverDirectory = _serverRoot;
+ string dataDir = Path.Combine(_pluginsDirectory, pName);
+ if (!Directory.Exists(dataDir))
+ Directory.CreateDirectory(dataDir);
+ plugin.dataDirectory = dataDir;
+
+ InvokePluginMethod(plugin, "onEnable", "OnEnable");
ServerLog.Info("fourkit", $"Enabled: {pName}");
FourKit.FireEvent(new PluginEnableEvent(plugin));