-
Notifications
You must be signed in to change notification settings - Fork 1
Development
Skynomi provides a flexible system for loading external extensions, allowing developers to add new functionality dynamically. This guide explains how to create and integrate a Skynomi extension.
- TShock Server (with Skynomi installed)
- .NET 6+
- Basic C# knowledge
Your extension must implement the ISkynomiExtension interface.
using Skynomi.Utils;
using TShockAPI;
namespace Skynomi.Extensions
{
public class MyExtension : Loader.ISkynomiExtension
{
public string Name => "My Extension";
public string Description => "A simple Skynomi extension.";
public Version Version => new Version(1, 0, 0);
public string Author => "YourName";
public void Initialize()
{
TShockAPI.Commands.ChatCommands.Add(new Command("myextension.use", MyCommand, "mycommand"));
Console.WriteLine("[Skynomi] My Extension Loaded!");
}
private void MyCommand(CommandArgs args)
{
args.Player.SendSuccessMessage("Hello from My Extension!");
}
}
}Extensions can optionally support reloading, disposing, and post-initialization.
To allow reloading, implement ISkynomiExtensionReloadable.
public class MyExtension : Loader.ISkynomiExtension, Loader.ISkynomiExtensionReloadable
{
public void Reload(ReloadEventArgs args)
{
Console.WriteLine("[Skynomi] My Extension Reloaded!");
}
}To perform cleanup when unloading, implement ISkynomiExtensionDisposable.
public class MyExtension : Loader.ISkynomiExtension, Loader.ISkynomiExtensionDisposable
{
public void Dispose()
{
Console.WriteLine("[Skynomi] My Extension Disposed!");
}
}If your extension requires additional steps after loading, implement ISkynomiExtensionPostInit.
public class MyExtension : Loader.ISkynomiExtension, Loader.ISkynomiExtensionPostInit
{
public void PostInitialize(EventArgs args)
{
Console.WriteLine("[Skynomi] My Extension Post-Initialized!");
}
}-
❌ Don't do this
ServerApi.Hooks.NetGreetPlayer.Register(this, OnPlayerJoin);
-
✅ Do this
ServerApi.Hooks.NetGreetPlayer.Register(Loader.GetPlugin(), OnPlayerJoin);
-
Build your extension into a
.dllfile. -
Move the
.dllfile intoServerPlugins/with nameSkynomi.xxx.dll. - Restart the server
Use the command:
/listextensionThis displays all loaded extensions along with their details.
To get more information about a specific extension:
/listextension <name>Skynomi provides a built-in caching system that allows extensions to store and retrieve data efficiently.
To load data from the database into the cache:
var balanceCache = CacheManager.Cache.GetCache<long>("balances");
balanceCache.SqliteQuery = "SELECT Username AS 'Key', Balance AS 'Value' FROM Accounts;";
balanceCache.MysqlQuery = "SELECT Username AS 'Key', Balance AS 'Value' FROM Accounts;";
balanceCache.Init();To load complex data from the database into the cache:
public class TRank
{
public int Rank { get; set; }
public int HighestRank { get; set; }
}
var Rankcache = Skynomi.Database.CacheManager.Cache.GetCache<TRank>("Ranks");
Rankcache.MysqlQuery = "SELECT Username AS 'Key', JSON_OBJECT('Rank', Rank, 'HighestRank', HighestRank) AS 'Value' FROM Ranks";
Rankcache.SqliteQuery = Rankcache.MysqlQuery;
Rankcache.SaveMysqlQuery = "INSERT INTO Ranks (Username, Rank, HighestRank) VALUES (@key, @value_Rank, @value_HighestRank) DUPLICATE KEY UPDATE Rank = @value_Rank, HighestRank = @value_HighestRank";
Rankcache.SaveSqliteQuery = "INSERT INTO Ranks (Username, Rank, HighestRank) VALUES (@key, @value_Rank, @value_HighestRank) CONFLICT(Username) DO UPDATE SET Rank = @value_Rank, HighestRank = @value_HighestRank";
Rankcache.Init();To modify cache entries:
var rankCache = CacheManager.Cache.GetCache<TRank>("Ranks");
// Define an updater function to increase the rank by 1
Func<TRank, TRank> increaseRank = existingRank =>
{
existingRank.Rank += 1;
return existingRank;
};
rankCache.Modify("player1", increaseRank);To store and persist data:
balanceCache.SaveMysqlQuery = "UPDATE Accounts SET Balance = @value WHERE Username = @key";
balanceCache.Update("player1", 5000);
balanceCache.Save();For structured data like auction items:
var shopCache = CacheManager.Cache.GetCache<ShopItem>("auctions");
shopCache.SaveMysqlQuery = "INSERT INTO Auctions (Username, ItemId, Price, Amount) VALUES (@key, @value_ItemId, @value_Price, @value_Amount)";
shopCache.Update("player1", new ShopItem { ItemId = 1, Price = 100, Amount = 5 });
shopCache.Save();Enable automatic cache saving:
CacheManager.AutoSave(60); // Save cache every 60 secondsThe Skynomi.Utils.Log class provides a robust logging system for Skynomi plugins, ensuring that all important events, errors, and general information are recorded effectively.
- Console logging with different log levels (Info, Error, Success, Warn, General).
- File-based logging with timestamped entries.
- Automatic log directory creation.
- Stack trace tracking to identify the caller method.
Logs a message to both the console and log files.
Parameters:
-
message(string): The message to be logged.
Logs an informational message.
Example:
Skynomi.Utils.Log.Info("Server started successfully.");Logs an error message.
Example:
Skynomi.Utils.Log.Error("Failed to load configuration file.");Logs a success message.
Example:
Skynomi.Utils.Log.Success("Plugin loaded without errors.");Logs a warning message.
Example:
Skynomi.Utils.Log.Warn("Configuration file is missing optional parameters.");Logs a general message without a specific severity.
Example:
Skynomi.Utils.Log.General("Plugin initialized.");Each log entry follows this format:
yyyy-MM-dd-HH-mm [LEVEL] (ClassName) => Message
Where:
-
LEVELis one ofINFO,ERROR,SUCCESS,WARN,UNKNOWN. -
ClassNamerepresents the class where the log was triggered. -
Messageis the log content.
2025-03-19-14-30 [I] (SkynomiPlugin) => Server started successfully.
2025-03-19-14-32 [E] (ConfigManager) => Failed to load configuration file.
With this guide, you can now develop powerful extensions for Skynomi, expanding its functionality dynamically. 🚀 Happy coding! 🎉