Data loaders
A data loader reads a file into memory once, at startup. Moongate loads all of its world data this way — skills, professions, regions, item and mobile templates — and a plugin can add its own loader for its own files.
The interface
public interface IDataLoader
{
ValueTask LoadAsync(CancellationToken ct = default);
}
LoadAsync runs once during startup. A loader typically resolves a file under the server root,
parses it, and hands the result to a registry service the rest of the plugin reads from.
Locating and parsing the file
Inject DirectoriesConfig to resolve a path under the server root, and use YamlUtils to
parse — both from SquidStd.Core. RegisterDirectory returns the absolute path and creates the
directory if it is missing, so the file simply sits under <root>/plugins/myshard/. This is the
same shape as the built-in SkillLoader.
using Moongate.Server.Abstractions.Interfaces.Loading;
using SquidStd.Core.Directories;
using SquidStd.Core.Yaml;
namespace MyShard.Motd.Loading;
/// <summary>Loads plugins/myshard/motd.yaml (a list of lines) into the MOTD registry.</summary>
public sealed class MotdLoader : IDataLoader
{
private readonly DirectoriesConfig _directories;
private readonly MotdRegistry _registry;
public MotdLoader(DirectoriesConfig directories, MotdRegistry registry)
{
_directories = directories;
_registry = registry;
}
public ValueTask LoadAsync(CancellationToken ct = default)
{
var directory = _directories.RegisterDirectory("plugins/myshard");
var path = Path.Combine(directory, "motd.yaml");
if (!File.Exists(path))
{
return ValueTask.CompletedTask;
}
var lines = YamlUtils.DeserializeFromFile<List<string>>(path) ?? [];
_registry.SetLines(lines);
return ValueTask.CompletedTask;
}
}
The registry is an ordinary singleton the loader fills and everything else injects:
namespace MyShard.Motd;
/// <summary>Holds the message-of-the-day lines loaded at startup.</summary>
public sealed class MotdRegistry
{
private IReadOnlyList<string> _lines = [];
public IReadOnlyList<string> Lines => _lines;
public void SetLines(IReadOnlyList<string> lines)
=> _lines = lines;
}
A matching plugins/myshard/motd.yaml:
- "Welcome to MyShard!"
- "Server resets nightly at 04:00."
Registering and ordering
Register the registry and the loader in your plugin's Configure:
container.Register<MotdRegistry>(Reuse.Singleton);
container.RegisterDataLoader<MotdLoader>(priority: 1000);
Loaders run in ascending priority. Moongate's own loaders occupy the low numbers (up to
150), so pick a priority above them — 1000 here — to load once the core world data your file
might reference is already in place.