From ba78a15613a73a476774066cda5a2d661d14af97 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 10 Jan 2025 23:42:41 +0000 Subject: [PATCH] Sample mod project and modding bootstrap --- Core/Utils/Watermark.cs | 2 +- ExampleOverrideMod/ExampleOverrideMod.csproj | 13 +++++++++ ExampleOverrideMod/WatermarkOverride.cs | 26 ++++++++++++++++++ Server/HarmonyBootstrapper.cs | 24 ++++++++++++++++ Server/ModDllLoader.cs | 26 ++++++++++++++++++ Server/Program.cs | 18 ++++++++---- .../user/mods/TestMod/ExampleOverrideMod.dll | Bin 0 -> 4608 bytes server-csharp.sln | 6 ++++ 8 files changed, 109 insertions(+), 6 deletions(-) create mode 100644 ExampleOverrideMod/ExampleOverrideMod.csproj create mode 100644 ExampleOverrideMod/WatermarkOverride.cs create mode 100644 Server/HarmonyBootstrapper.cs create mode 100644 Server/ModDllLoader.cs create mode 100644 Server/user/mods/TestMod/ExampleOverrideMod.dll diff --git a/Core/Utils/Watermark.cs b/Core/Utils/Watermark.cs index 934a285d..882303ed 100644 --- a/Core/Utils/Watermark.cs +++ b/Core/Utils/Watermark.cs @@ -68,7 +68,7 @@ public class Watermark { sptConfig = _configServer.GetConfig(ConfigTypes.CORE); } - public void Initialize() + public virtual void Initialize() { var description = _watermarkLocale.GetDescription(); var warning = _watermarkLocale.GetWarning(); diff --git a/ExampleOverrideMod/ExampleOverrideMod.csproj b/ExampleOverrideMod/ExampleOverrideMod.csproj new file mode 100644 index 00000000..3cebe147 --- /dev/null +++ b/ExampleOverrideMod/ExampleOverrideMod.csproj @@ -0,0 +1,13 @@ + + + + net9.0 + enable + enable + + + + + + + diff --git a/ExampleOverrideMod/WatermarkOverride.cs b/ExampleOverrideMod/WatermarkOverride.cs new file mode 100644 index 00000000..5f220ed1 --- /dev/null +++ b/ExampleOverrideMod/WatermarkOverride.cs @@ -0,0 +1,26 @@ +using Core.Annotations; +using Core.Models.Utils; +using Core.Servers; +using Core.Services; +using Core.Utils; + +namespace ExampleOverrideMod; + +[Injectable(InjectableTypeOverride = typeof(Watermark))] +public class WatermarkOverride : Watermark +{ + public WatermarkOverride( + ILogger logger, + ConfigServer configServer, + LocalisationService localisationService, + WatermarkLocale watermarkLocale + ) : base(logger, configServer, localisationService, watermarkLocale) + { + } + + public override void Initialize() + { + Console.WriteLine("This is a watermark mod override!"); + base.Initialize(); + } +} diff --git a/Server/HarmonyBootstrapper.cs b/Server/HarmonyBootstrapper.cs new file mode 100644 index 00000000..db8d20c3 --- /dev/null +++ b/Server/HarmonyBootstrapper.cs @@ -0,0 +1,24 @@ +using System.Reflection; + +namespace Server; + +public class HarmonyBootstrapper +{ + public static void LoadAllPatches(List assemblies) + { + /* TODO: Benched idea until someone can figure out how to make Harmony work on net9.0 runtime if even possible? + var hamony = new Harmony("SPT"); + foreach (var assembly in assemblies) + { + try + { + hamony.PatchAll(assembly); + } + catch (Exception e) + { + Console.WriteLine(e); + } + } + */ + } +} diff --git a/Server/ModDllLoader.cs b/Server/ModDllLoader.cs new file mode 100644 index 00000000..f718e6a4 --- /dev/null +++ b/Server/ModDllLoader.cs @@ -0,0 +1,26 @@ +using System.Reflection; + +namespace Server; + +public class ModDllLoader +{ + private const string ModPath = "./user/mods/"; + public static List LoadAllMods() + { + if (!Directory.Exists(ModPath)) + Directory.CreateDirectory(ModPath); + var mods = new List(); + foreach (var file in Directory.GetFiles(ModPath, "*.dll", SearchOption.AllDirectories)) + { + try + { + mods.Add(Assembly.LoadFile(Path.GetFullPath(file))); + } + catch (Exception e) + { + Console.WriteLine(e); + } + } + return mods; + } +} diff --git a/Server/Program.cs b/Server/Program.cs index 8b146f57..a74760ec 100644 --- a/Server/Program.cs +++ b/Server/Program.cs @@ -1,6 +1,6 @@ -using Core.Annotations; +using System.Reflection; +using Core.Annotations; using Core.Context; -using Core.Servers; using Core.Utils; namespace Server; @@ -9,12 +9,13 @@ public static class Program { public static void Main(string[] args) { + var assemblies = ModDllLoader.LoadAllMods(); + HarmonyBootstrapper.LoadAllPatches(assemblies); var builder = WebApplication.CreateBuilder(args); RegisterSptComponents(builder.Services); - - // TODO: deal with modding overriding services here! - + RegisterModOverrideComponents(builder.Services, assemblies); + try { @@ -33,6 +34,13 @@ public static class Program } } + private static void RegisterModOverrideComponents(IServiceCollection builderServices, List assemblies) + { + // We get all the services from this assembly first, since mods will override them later + RegisterComponents(builderServices, assemblies.SelectMany(a => a.GetTypes()) + .Where(type => Attribute.IsDefined(type, typeof(Injectable)))); + } + private static void RegisterComponents(IServiceCollection builderServices, IEnumerable types) { var groupedTypes = types.Select(t => diff --git a/Server/user/mods/TestMod/ExampleOverrideMod.dll b/Server/user/mods/TestMod/ExampleOverrideMod.dll new file mode 100644 index 0000000000000000000000000000000000000000..9b58eb5f15ae0bbdecb2915f7d36f00a561db9ab GIT binary patch literal 4608 zcmeHKU2Ggz6+W|GyROqXw$r9TK$z4;ag#8t*|lp2OxNDE+fDr!?Pugc5Gtssc?h8P3Gq@zQ3Xgm@PI0aK%y!_3J*Ng{mz{k z@7fMk$P-B1^_+YD?z!jZ{(0_eFHr{(CGl--5nV^mEi2*2gUb;2e&!dwbnX5dN3Sch zH;$GrTE1HM+^VP7R8w~xH&6|sdJRXl95ugCRBLWoX#4l~JQ|r^oFoUT`!CyNK=8SB(8{x{%73jsBAJEu&mp1( zMzTb|hffsk#B%?2KIM7qouTTDm^^T6Lyjf_$l~5 z_${L6(W|J-U@`D4r|PrDk2*tt2hSGi@4z|C!6(la@+`!9xr!+Vr)<|?8Vx3tCm$l> zRMWqdG#v`#LnqS&xlAkD*^iH750^qZ5$2(bzNx&K=%QN^zD3_p9H8G|SQq_;4uF3{ zIRluNP?7M6gs)2YF0s_a*dF>ZZ2^CiP6OWn-b0Ti-UH{Fl$we6!SND(9X<4E`XTW1 z^j@Nuz6X6c73GX`ry%NSBy&>Yiz-W>JA5TE2>ODgeoaZ(MS8$l!{`KE0_>n+aFSF- zHm)GLe!wpJ1Ry*C?1P-)xP+4u79>0);a4Tp0TpTjJ_O&cB#zLx0SD=4^csC0IM1xo z8ucm1=NqR~E@AdL>v4B#h801lD^c!FLBOw+FbzeqO$bMyzmrzO7#m?M)8Dap%m z^l)D`J{)94BRWGbODwEd#Ej0foqEs2!Y|Fa<%TW3Ow*fst!|5jb>VqdS%6KmuBqFW zuLqXv6ot2LnS!vx_VCW@f$(a&w-yhkZH_b{Xd~8$=z_B<%s@A6LB*yYh?0AM^HEfo|Kw(K{?kGlov*$T4gJf0k($G2n0>~zNi^?vt$MB?2_(P zMKFUiS!}r8+Ftz`%NFN^=VOAs!h%zA5g_M5xBsmcLa12Ph9~t}MwUdSs8>YLTtc4x z7C-0K>Xt2)mxQfvN~}#DN3!UlLT1n!INz{s4jS|E3EC3GBiOR;G+Tlwo01<`hGknp zo3!9qfrX-eW4joUz7~awL#I{IJ1i8fY}-*C<8mTs8x=;vs4(kRtHQ&|kzJT2UQXbd zGG!5=nStxY2J)6(bzDENOkWmTix!|CE5tsAX%ybJJX{s<8B171gU<$*9ihy%eXWf% z$#-;^{nk`i3UZ6&N_3Gd^0Ajgr~}&|odWD&k7~d?>~a;DOJ(#ftxJgq{W7ql(#+MV zpRD%X`t$57ndjeLedp~5DXA(-cZW(!Cy@SrCVRWp4yAu&V7!~D&V6c987K_Q4V)P` znJdH!ONm40J-t5fI@6n`sB_Ls7d>~wSD<&F!qZPEbXc38 zF7d9Jtk+LQb)8rr*HSRh`{4G*$XkBh)|>O#C*3?kg~r1Q4cy^$pdN)fWwLSQVy0o- zVE7TG71AVeLX4Q{ba`yl980Ii)5eIAsu;tWj6Rad7>|#Z$J3*g5kpT2+;|)bZ7T9I z+CsYozZMU*&I#W2@$qto;|MFLZJ#tJRpy>li9m97MvYTx(R^dCe zy)6~<#p|yx|MVX>yK^tBynlQ3_BiGv%AZ=!6|uYdDD;RnwEeS@Y0?KT>zX3U)}Up@`Den{ z*J69)cb)>PeEQ7bq_J_*6!4m;$Q4WUs2o*-R0r3GoKGwZQYSL=M)LPCs=%iJS{C@# zJ6O6VbyA2s{AI}C96<9R#^zwJMs+zy6A|g4u$j@OX;V^l>Dj`rGjR^%%2ID$+KD5` zW3-RA4*OHz;qTqrOW|Zxw&OSldmb#d;vUAkDz*I)e0~`EoVoBkci^?%7RlYrt05K} zKW;-fz!aLryj5w5GgQYbkt3?&CgJ~gRD9>;ybBSZv(NL!d0;Bc9|_tZK^-uI)WE6omf=o0b22-NX3*5BZ