From c579695f4360139b59c6797197d8787ab47158bd Mon Sep 17 00:00:00 2001 From: Chomp Date: Sat, 8 Feb 2025 10:02:50 +0000 Subject: [PATCH] Improved mod examples --- ExampleMods/Mods/{ => 1Logging}/Logging.cs | 7 +-- .../{ => 2EditDatabase}/EditDatabaseValues.cs | 7 +-- .../Mods/{ => 3EditSptConfig}/EditConfigs.cs | 12 +++-- .../4ReadCustomJson5Config/ReadJson5Config.cs | 42 +++++++++++++++++ .../Mods/4ReadCustomJson5Config/config.json5 | 4 ++ .../5ReadCustomJsonConfig/ReadJsonConfig.cs | 45 +++++++++++++++++++ .../Mods/5ReadCustomJsonConfig/config.json | 3 ++ .../Mods/6ReplaceMethod/ReplaceMethod.cs | 34 ++++++++++++++ ExampleMods/Mods/WatermarkOverride.cs | 25 ++++++----- Server/ModDllLoader.cs | 12 ++++- 10 files changed, 167 insertions(+), 24 deletions(-) rename ExampleMods/Mods/{ => 1Logging}/Logging.cs (83%) rename ExampleMods/Mods/{ => 2EditDatabase}/EditDatabaseValues.cs (95%) rename ExampleMods/Mods/{ => 3EditSptConfig}/EditConfigs.cs (92%) create mode 100644 ExampleMods/Mods/4ReadCustomJson5Config/ReadJson5Config.cs create mode 100644 ExampleMods/Mods/4ReadCustomJson5Config/config.json5 create mode 100644 ExampleMods/Mods/5ReadCustomJsonConfig/ReadJsonConfig.cs create mode 100644 ExampleMods/Mods/5ReadCustomJsonConfig/config.json create mode 100644 ExampleMods/Mods/6ReplaceMethod/ReplaceMethod.cs diff --git a/ExampleMods/Mods/Logging.cs b/ExampleMods/Mods/1Logging/Logging.cs similarity index 83% rename from ExampleMods/Mods/Logging.cs rename to ExampleMods/Mods/1Logging/Logging.cs index d0abdf80..b6c200b4 100644 --- a/ExampleMods/Mods/Logging.cs +++ b/ExampleMods/Mods/1Logging/Logging.cs @@ -3,14 +3,15 @@ using Core.Models.Logging; using Core.Models.Utils; using SptCommon.Annotations; -namespace ExampleMods.Mods; +namespace ExampleMods.Mods._1Logging; [Injectable] -public class Logging : IPostSptLoadMod +public class Logging : IPostSptLoadMod // Using this interface means our mod will run AFTER SPT has finished loading { + // Our logger we create in the constructor below private readonly ISptLogger _logger; - // Constructor - Inject a 'ISptLogger' with your mods Class in the diamond brackets + // Constructor - Inject a 'ISptLogger' with your mods Class inside the diamond brackets public Logging( ISptLogger logger ) diff --git a/ExampleMods/Mods/EditDatabaseValues.cs b/ExampleMods/Mods/2EditDatabase/EditDatabaseValues.cs similarity index 95% rename from ExampleMods/Mods/EditDatabaseValues.cs rename to ExampleMods/Mods/2EditDatabase/EditDatabaseValues.cs index 6d6832a4..8414ec0e 100644 --- a/ExampleMods/Mods/EditDatabaseValues.cs +++ b/ExampleMods/Mods/2EditDatabase/EditDatabaseValues.cs @@ -4,14 +4,15 @@ using Core.Models.Utils; using Core.Services; using SptCommon.Annotations; -namespace ExampleMods.Mods; +namespace ExampleMods.Mods._2EditDatabase; [Injectable] -public class EditDatabaseValues : IPostDBLoadMod +public class EditDatabaseValues : IPostDBLoadMod // Using this interface means our mod will run AFTER the SPT database has finished loading but BEFORE SPT code has run { private readonly DatabaseService _databaseService; private readonly ISptLogger _logger; + // Our constructor public EditDatabaseValues( DatabaseService databaseService, ISptLogger logger @@ -35,7 +36,7 @@ public class EditDatabaseValues : IPostDBLoadMod // Let's edit the hideout so it's easier to upgrade the lavatory EditHideout(); - // Lets edit the default scav to + // Lets edit the default scav (assault.json) to have different settings EditScavSettings(); // Lets edit Customs diff --git a/ExampleMods/Mods/EditConfigs.cs b/ExampleMods/Mods/3EditSptConfig/EditConfigs.cs similarity index 92% rename from ExampleMods/Mods/EditConfigs.cs rename to ExampleMods/Mods/3EditSptConfig/EditConfigs.cs index 6464daab..84242a70 100644 --- a/ExampleMods/Mods/EditConfigs.cs +++ b/ExampleMods/Mods/3EditSptConfig/EditConfigs.cs @@ -5,7 +5,7 @@ using Core.Models.Utils; using Core.Servers; using SptCommon.Annotations; -namespace ExampleMods.Mods; +namespace ExampleMods.Mods._3EditSptConfig; [Injectable] public class EditConfigs : IPostDBLoadMod @@ -42,7 +42,7 @@ public class EditConfigs : IPostDBLoadMod public void PostDBLoad() { - // Let's edit the weather config to make the season winter + // Let's edit the weather config to force the season to winter _weatherConfig.OverrideSeason = Season.WINTER; // Let's edit the hideout config to Make all crafts take 60 seconds @@ -51,7 +51,7 @@ public class EditConfigs : IPostDBLoadMod // Let's edit the hideout config to Make all upgrades take 60 seconds _hideoutConfig.OverrideBuildTimeSeconds = 60; - // Let's edit the airdrop config to Make weapon/armor drops really common + // Let's edit the airdrop config to Make weapon/armor drops REALLY common _airdropConfig.AirdropTypeWeightings[SptAirdropTypeEnum.weaponArmor] = 999; // Let's edit the airdrop config to Make weapon/armor drops always have 3 sealed weapon crates @@ -62,7 +62,7 @@ public class EditConfigs : IPostDBLoadMod // Let's make PMCs always mail you when they kill you _pmcChatResponseConfig.Killer.ResponseChancePercent = 100; - // Let's make quest rewards sent to you via mail last for over a week if you have an unheard profile + // Let's make quest rewards sent to you via mail last for over a week for unheard profiles _questConfig.MailRedeemTimeHours["unheard_edition"] = 168; // Let's make the interchange bot cap huge @@ -73,7 +73,11 @@ public class EditConfigs : IPostDBLoadMod // Let's make the conversion rate of scavs to pmcs 100% on factory day var factory4DayConversionSettings = _pmcConfig.ConvertIntoPmcChance["factory4_day"]; + + // We get assault bot settings for factory day var assaultConversionSettings = factory4DayConversionSettings["assault"]; + + // Set min and max to 100% assaultConversionSettings.Min = 100; assaultConversionSettings.Max = 100; diff --git a/ExampleMods/Mods/4ReadCustomJson5Config/ReadJson5Config.cs b/ExampleMods/Mods/4ReadCustomJson5Config/ReadJson5Config.cs new file mode 100644 index 00000000..63e24694 --- /dev/null +++ b/ExampleMods/Mods/4ReadCustomJson5Config/ReadJson5Config.cs @@ -0,0 +1,42 @@ +using Core.Models.External; +using Core.Models.Utils; +using Core.Utils; +using SptCommon.Annotations; + +namespace ExampleMods.Mods._4ReadCustomJson5Config +{ + [Injectable] + public class ReadJson5Config: IPreSptLoadMod + { + private readonly ISptLogger _logger; + private readonly FileUtil _fileUtil; + private readonly JsonUtil _jsonUtil; + + public ReadJson5Config( + ISptLogger logger, + FileUtil fileUtil, + JsonUtil jsonUtil) + { + _logger = logger; + _fileUtil = fileUtil; + _jsonUtil = jsonUtil; + } + + public void PreSptLoad() + { + // Read the content of the config file into a string + var rawContent = _fileUtil.ReadFile("config.json5"); + + // Take the string above and deserialise it into a config file with a type (defined between the diamond brackets) + var config = _jsonUtil.Deserialize(rawContent); + + _logger.Success($"Read property: 'ExampleProperty' from config with value: {config.ExampleProperty}"); + } + } + + // This class should represent your config structure + public class ModConfig + { + public string ExampleProperty { get; set; } + } +} diff --git a/ExampleMods/Mods/4ReadCustomJson5Config/config.json5 b/ExampleMods/Mods/4ReadCustomJson5Config/config.json5 new file mode 100644 index 00000000..008be89c --- /dev/null +++ b/ExampleMods/Mods/4ReadCustomJson5Config/config.json5 @@ -0,0 +1,4 @@ +{ + // Comment goes here, wow + "ExampleProperty": "boop" +} diff --git a/ExampleMods/Mods/5ReadCustomJsonConfig/ReadJsonConfig.cs b/ExampleMods/Mods/5ReadCustomJsonConfig/ReadJsonConfig.cs new file mode 100644 index 00000000..016c9148 --- /dev/null +++ b/ExampleMods/Mods/5ReadCustomJsonConfig/ReadJsonConfig.cs @@ -0,0 +1,45 @@ +using Core.Models.External; +using Core.Models.Utils; +using Core.Utils; +using SptCommon.Annotations; + +namespace ExampleMods.Mods._5ReadCustomJsonConfig +{ + [Injectable] + public class ReadJsonConfig : IPreSptLoadMod + { + private readonly ISptLogger _logger; + private readonly FileUtil _fileUtil; + private readonly JsonUtil _jsonUtil; + + public ReadJsonConfig( + ISptLogger logger, + FileUtil fileUtil, + JsonUtil jsonUtil) + { + _logger = logger; + _fileUtil = fileUtil; + _jsonUtil = jsonUtil; + } + + public void PreSptLoad() + { + // Read the content of the config file into a string + var rawContent = _fileUtil.ReadFile("config.json"); + + // Take the string above and deserialise it into a config file with a type (defined between the diamond brackets) + var config = _jsonUtil.Deserialize(rawContent); + + _logger.Success($"Read property: 'ExampleProperty' from config with value: {config.ExampleProperty}"); + } + } + + // This class should represent your config structure + public class ModConfig + { + public string ExampleProperty + { + get; set; + } + } +} diff --git a/ExampleMods/Mods/5ReadCustomJsonConfig/config.json b/ExampleMods/Mods/5ReadCustomJsonConfig/config.json new file mode 100644 index 00000000..907dc42a --- /dev/null +++ b/ExampleMods/Mods/5ReadCustomJsonConfig/config.json @@ -0,0 +1,3 @@ +{ + "ExampleProperty": "boop" +} diff --git a/ExampleMods/Mods/6ReplaceMethod/ReplaceMethod.cs b/ExampleMods/Mods/6ReplaceMethod/ReplaceMethod.cs new file mode 100644 index 00000000..bacc6dc3 --- /dev/null +++ b/ExampleMods/Mods/6ReplaceMethod/ReplaceMethod.cs @@ -0,0 +1,34 @@ +using Core.Models.Utils; +using Core.Servers; +using Core.Services; +using Core.Utils; +using SptCommon.Annotations; + +namespace ExampleMods.Mods._6ReplaceMethod +{ + [Injectable(InjectableTypeOverride = typeof(Watermark))] + public class ReplaceMethod: Watermark + { + public ReplaceMethod( + ISptLogger logger, + ConfigServer configServer, + LocalisationService localisationService, + WatermarkLocale watermarkLocale) + : base(logger, configServer, localisationService, watermarkLocale) + { + _configServer = configServer; + _localisationService = localisationService; + _watermarkLocale = watermarkLocale; + _logger = logger; + } + + public override void Initialize() + { + // We add a log message to the init method + _logger.Success("This is a watermark mod override!"); + + // This runs the original method (optional) + base.Initialize(); + } + } +} diff --git a/ExampleMods/Mods/WatermarkOverride.cs b/ExampleMods/Mods/WatermarkOverride.cs index afafb8bc..2f45b40d 100644 --- a/ExampleMods/Mods/WatermarkOverride.cs +++ b/ExampleMods/Mods/WatermarkOverride.cs @@ -4,21 +4,22 @@ using Core.Services; using Core.Utils; using SptCommon.Annotations; -namespace ExampleMods.Mods.Override; +namespace ExampleMods.Mods; [Injectable(InjectableTypeOverride = typeof(Watermark))] -public class WatermarkOverride( - ISptLogger _logger, - ConfigServer _configServer, - LocalisationService _localisationService, - WatermarkLocale _watermarkLocale -) : Watermark( - _logger, - _configServer, - _localisationService, - _watermarkLocale -) // was testing overriding with primary constructors, works fine from what i can see +public class WatermarkOverride : Watermark // was testing overriding with primary constructors, works fine from what i can see { + public WatermarkOverride(ISptLogger logger, + ConfigServer configServer, + LocalisationService localisationService, + WatermarkLocale watermarkLocale) + : base(logger, + configServer, + localisationService, + watermarkLocale) + { + } + public override void Initialize() { _logger.Success("This is a watermark mod override!"); diff --git a/Server/ModDllLoader.cs b/Server/ModDllLoader.cs index 249867ad..a7dd39dc 100644 --- a/Server/ModDllLoader.cs +++ b/Server/ModDllLoader.cs @@ -23,7 +23,9 @@ public class ModDllLoader // load both // if either is missing Throw Warning and skip - var modDirectories = Directory.GetDirectories(ModPath); + var modDirectories = GetSortedModDirectories(); + + // TODO: Handle package.json 'Dependencies' property foreach (var modDirectory in modDirectories) { @@ -40,7 +42,13 @@ public class ModDllLoader return mods; } - private static SptMod? LoadMod(string path) + private static string[] GetSortedModDirectories() + { + // TODO: add system to read from package.json and order mod paths by their LoadBefore/LoadAfter properties + return Directory.GetDirectories(ModPath); + } + + private static SptMod LoadMod(string path) { var result = new SptMod(); var asmCount = 0;