From a7dd8197f4c68c3723873588cad6f0d531d7b870 Mon Sep 17 00:00:00 2001 From: remyCases Date: Mon, 1 Sep 2025 02:08:22 +0200 Subject: [PATCH 1/9] [Minor] rewrites gettable since there is no need for decompilation here, loading sequence is 10 times faster now --- ModLoader.cs | 12 ++++---- ModUtils/AsmUtils.cs | 66 +++++++++++++++++++++++++++----------------- 2 files changed, 46 insertions(+), 32 deletions(-) diff --git a/ModLoader.cs b/ModLoader.cs index 519d4cc..99ab7a7 100644 --- a/ModLoader.cs +++ b/ModLoader.cs @@ -55,13 +55,11 @@ public static void AddMenu(string name, params UIComponent[] components) try { UndertaleCode table = Data.Code.First(t => t.Name.Content == name); - GlobalDecompileContext context = new(Data, false); - string text = Decompiler.Decompile(table, context); - string matchedText = Regex.Match(text, "return (\\[.*\\])").Groups[1].Value; - List? tableAsList = JsonConvert.DeserializeObject>(matchedText); - - Log.Information(string.Format("Get table: {0}", name.ToString())); - return tableAsList; + return table.Instructions + .Where(i => AssemblyWrapper.IsPushString(i)) + .Select(i => (i.Value as UndertaleResourceById)!.Resource.Content) + .Reverse() + .ToList(); } catch(Exception ex) { diff --git a/ModUtils/AsmUtils.cs b/ModUtils/AsmUtils.cs index ca0276c..baa1cc5 100644 --- a/ModUtils/AsmUtils.cs +++ b/ModUtils/AsmUtils.cs @@ -148,9 +148,10 @@ public static void InjectAssemblyInstruction(string name, Func CreateRefVariable(string name, UndertaleInstruction.InstanceType instanceType) + public static UndertaleInstruction.Reference CreateRefVariable(string name, UndertaleInstruction.InstanceType instanceType) { - if (ModLoader.Data == null) { + if (ModLoader.Data == null) + { throw new NullReferenceException("Data is null"); } @@ -159,7 +160,7 @@ public static UndertaleInstruction.Reference CreateRefVariabl uint oldId = ModLoader.Data.VarCount1; if (bytecode14) - instanceType = UndertaleInstruction.InstanceType.Undefined; + instanceType = UndertaleInstruction.InstanceType.Undefined; if (!bytecode14) { @@ -210,9 +211,10 @@ public static void CheckRefLocalVariableOrCreate(UndertaleCode code, string name if (localvar == null) { UndertaleInstruction.Reference refVariable = CreateRefVariable(name, UndertaleInstruction.InstanceType.Local); - localvar = new() { - Index = (uint)refVariable.Target.VarID, - Name = refVariable.Target.Name + localvar = new() + { + Index = (uint)refVariable.Target.VarID, + Name = refVariable.Target.Name }; locals.Locals.Add(localvar); } @@ -251,12 +253,12 @@ public static void CheckRefVariableOrCreate(string name, UndertaleInstruction.In } public static UndertaleInstruction.Reference GetRefVariableOrCreate(string name, UndertaleInstruction.InstanceType instanceType) { - try + try { UndertaleInstruction.Reference refVariable; UndertaleVariable? variable = ModLoader.Data.Variables.FirstOrDefault(t => t.Name?.Content == name); - - if (variable == null) + + if (variable == null) refVariable = CreateRefVariable(name, instanceType); else refVariable = new UndertaleInstruction.Reference(variable, UndertaleInstruction.VariableType.Normal); @@ -276,7 +278,7 @@ public static string CreateLocalVarAssemblyAsString(UndertaleCode code) IEnumerable newLocalVars = ModLoader.Data.CodeLocals.For(code).Locals; StringBuilder sb = new(); - foreach(UndertaleCodeLocals.LocalVar newLocalVar in newLocalVars) + foreach (UndertaleCodeLocals.LocalVar newLocalVar in newLocalVars) { if (originalLocalVarsName.Contains(newLocalVar.Name.Content)) continue; UndertaleVariable? refVar = ModLoader.Data.Variables.FirstOrDefault(x => x.Name.Content == newLocalVar.Name.Content && x.VarID == newLocalVar.Index); @@ -292,7 +294,7 @@ public static string CreateLocalVarAssemblyAsString(UndertaleCode code) return sb.ToString(); } - public static UndertaleResourceById CreateString(string name) + public static UndertaleResourceById CreateString(string name) { UndertaleString str = ModLoader.Data.Strings.MakeString(name, out int ind); Log.Information(string.Format("Created string: {0}", str.ToString())); @@ -300,10 +302,11 @@ public static UndertaleResourceById CreateS } public static UndertaleResourceById GetStringOrCreate(string name) { - try { + try + { UndertaleResourceById stringById; (int ind, UndertaleString str) = ModLoader.Data.Strings.Enumerate().FirstOrDefault(x => x.Item2.Content == name); - + if (str == null) stringById = CreateString(name); else @@ -313,41 +316,46 @@ public static UndertaleResourceById GetStri return stringById; } - catch(Exception ex) { + catch (Exception ex) + { Log.Error(ex, "Something went wrong"); throw; } } public static UndertaleInstruction PushShort(short val) { - return new() { + return new() + { Kind = UndertaleInstruction.Opcode.PushI, Value = val, Type1 = UndertaleInstruction.DataType.Int16, }; } - + public static UndertaleInstruction PushInt(int val) { - return new() { + return new() + { Kind = UndertaleInstruction.Opcode.Push, Value = val, Type1 = UndertaleInstruction.DataType.Int32, }; } - public static UndertaleInstruction PushString(string val) + public static UndertaleInstruction PushString(string val) { - return new() { + return new() + { Kind = UndertaleInstruction.Opcode.Push, Value = GetStringOrCreate(val), Type1 = UndertaleInstruction.DataType.String, }; } - public static UndertaleInstruction PushGlb(string val) + public static UndertaleInstruction PushGlb(string val) { - return new() { + return new() + { Kind = UndertaleInstruction.Opcode.PushGlb, Value = GetRefVariableOrCreate(val, UndertaleInstruction.InstanceType.Global), Type1 = UndertaleInstruction.DataType.Variable, @@ -357,7 +365,8 @@ public static UndertaleInstruction PushGlb(string val) public static UndertaleInstruction PopIntGlb(string val) { - return new() { + return new() + { Kind = UndertaleInstruction.Opcode.Pop, Destination = GetRefVariableOrCreate(val, UndertaleInstruction.InstanceType.Global), Type1 = UndertaleInstruction.DataType.Variable, @@ -367,7 +376,8 @@ public static UndertaleInstruction PopIntGlb(string val) } public static UndertaleInstruction PopIntLcl(string val) { - return new() { + return new() + { Kind = UndertaleInstruction.Opcode.Pop, Destination = GetRefVariableOrCreate(val, UndertaleInstruction.InstanceType.Local), Type1 = UndertaleInstruction.DataType.Variable, @@ -375,10 +385,11 @@ public static UndertaleInstruction PopIntLcl(string val) TypeInst = UndertaleInstruction.InstanceType.Local, }; } - + public static UndertaleInstruction PopIntSelf(string val) { - return new() { + return new() + { Kind = UndertaleInstruction.Opcode.Pop, Destination = GetRefVariableOrCreate(val, UndertaleInstruction.InstanceType.Self), Type1 = UndertaleInstruction.DataType.Variable, @@ -386,5 +397,10 @@ public static UndertaleInstruction PopIntSelf(string val) TypeInst = UndertaleInstruction.InstanceType.Self, }; } + + public static bool IsPushString(UndertaleInstruction instruction) + { + return instruction.Kind == UndertaleInstruction.Opcode.Push && instruction.Value is UndertaleResourceById stringRef; + } } } \ No newline at end of file From c7f98f339add22f81e54775ccdc85b76e9f4d814 Mon Sep 17 00:00:00 2001 From: remyCases Date: Tue, 2 Sep 2025 03:05:44 +0200 Subject: [PATCH 2/9] [Minor] log improvement --- ModUtils/LogUtils.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/ModUtils/LogUtils.cs b/ModUtils/LogUtils.cs index 80c2513..ae0e96c 100644 --- a/ModUtils/LogUtils.cs +++ b/ModUtils/LogUtils.cs @@ -21,9 +21,11 @@ public static void InjectLog() var string_log = ""["" + time + ""]: "" + argument0 + ""\n""; var len_log = string_byte_length(string_log); - if (len_log > global._msl_log.size) + if (len_log > global._msl_log.size - 1) { - string_log = string_copy(string_log, 1, global._msl_log.size - 1) + ""\n""; + var msg_space = global._msl_log.size - string_byte_length(""["" + time + ""]: \n"") - 1; + argument0 = string_copy(argument0, 1, msg_space); + string_log = ""["" + time + ""]: "" + argument0 + ""\n""; len_log = string_byte_length(string_log); } @@ -59,8 +61,13 @@ public static void InjectLog() string mslLogSave = @"function scr_msl_log_save() { + if (global._msl_log.save_in_progress) return; + + global._msl_log.save_in_progress = true; var nfile_name = global._msl_log.name + ""_"" + string(global._msl_log.nfile) + "".txt""; buffer_save_async(global._msl_log.buf, nfile_name, 0, global._msl_log.cur_size); + + global._msl_log.save_in_progress = false; instance_destroy(global._msl_log.timer); }"; @@ -89,6 +96,7 @@ public static void InjectLog() buf = buffer_create(size, buffer_wrap, 1); cur_size = 0 nfile = 0 +save_in_progress = false var curr_time = date_current_datetime(); var format_time = string_format(date_get_year(curr_time), 2, 0) + string_format(date_get_month(curr_time), 2, 0) + string_format(date_get_day(curr_time), 2, 0) + ""_"" + string_format(date_get_hour(curr_time), 2, 0) + string_format(date_get_minute(curr_time), 2, 0); @@ -102,7 +110,9 @@ public static void InjectLog() Msl.AddFunction(mslLog, "scr_msl_log"); Msl.LoadGML(Msl.EventName("o_gameLoader", EventType.Create, 0)) .MatchAll() - .InsertBelow(@"global._msl_log = instance_create_depth(0, 0, -100, o_msl_log);") + .InsertBelow(@" +global._msl_log = instance_create_depth(0, 0, -100, o_msl_log); +") .Save(); } } \ No newline at end of file From 7876cfb0537b49213404c61236611423517e03c1 Mon Sep 17 00:00:00 2001 From: remyCases Date: Sat, 6 Sep 2025 23:32:09 +0200 Subject: [PATCH 3/9] [Minor] better naming for some variables, remove some OLD legacy code --- Controls/ModInfos.xaml.cs | 6 +-- Extensions/ModShard.cs | 67 ------------------------------ FileReader.cs | 8 ++-- Main.xaml.cs | 14 +++---- ModLoader.cs | 86 +++------------------------------------ ModUtils/CodeUtils.cs | 16 ++++---- ModUtils/GeneralUtils.cs | 3 +- 7 files changed, 27 insertions(+), 173 deletions(-) delete mode 100644 Extensions/ModShard.cs diff --git a/Controls/ModInfos.xaml.cs b/Controls/ModInfos.xaml.cs index 7ff1e38..3eb52d6 100644 --- a/Controls/ModInfos.xaml.cs +++ b/Controls/ModInfos.xaml.cs @@ -36,14 +36,14 @@ private async void Save_Click(object sender, EventArgs e) bool patchSucess = false; - try + try { ModLoader.PatchFile(); Log.Information("Successfully patch vanilla"); patchSucess = true; Main.Instance.LogModList(); } - catch(Exception ex) + catch (Exception ex) { Main.Instance.LogModList(); Log.Error(ex, "Something went wrong"); @@ -52,7 +52,7 @@ private async void Save_Click(object sender, EventArgs e) } // attempt to save the patched data - if (patchSucess) + if (patchSucess) { Task save = DataLoader.DoSaveDialog(); await save; diff --git a/Extensions/ModShard.cs b/Extensions/ModShard.cs deleted file mode 100644 index f750d64..0000000 --- a/Extensions/ModShard.cs +++ /dev/null @@ -1,67 +0,0 @@ -using UndertaleModLib; -using UndertaleModLib.Models; - -namespace ModShardLauncher.Extensions -{ - public class ModShard : UndertaleExtensionFile - { - public ModShard() - { - Filename = DataLoader.data.Strings.MakeString("ModShard.dll"); - CleanupScript = DataLoader.data.Strings.MakeString(""); - InitScript = DataLoader.data.Strings.MakeString(""); - Kind = UndertaleExtensionKind.Dll; - CreateFunc(); - } - public void CreateFunc() - { - UndertaleExtensionFunction ScriptThread = new() - { - Name = DataLoader.data.Strings.MakeString("ScriptThread"), - ExtName = DataLoader.data.Strings.MakeString("ScriptThread"), - RetType = UndertaleExtensionVarType.Double, - Arguments = new UndertaleSimpleList(), - Kind = 11, - ID = DataLoader.data.ExtensionFindLastId() - }; - Functions.Add(ScriptThread); - UndertaleExtensionFunction GetScript = new() - { - Name = DataLoader.data.Strings.MakeString("GetScript"), - ExtName = DataLoader.data.Strings.MakeString("GetScript"), - RetType = UndertaleExtensionVarType.String, - Arguments = new UndertaleSimpleList(), - Kind = 11, - ID = ScriptThread.ID + 1 - }; - Functions.Add(GetScript); - UndertaleExtensionFunction PopScript = new() - { - Name = DataLoader.data.Strings.MakeString("PopScript"), - ExtName = DataLoader.data.Strings.MakeString("PopScript"), - RetType = UndertaleExtensionVarType.Double, - Arguments = new UndertaleSimpleList(), - Kind = 11, - ID = GetScript.ID + 1 - }; - Functions.Add(PopScript); - UndertaleExtensionFunction RunCallBack = new() - { - Name = DataLoader.data.Strings.MakeString("RunCallBack"), - ExtName = DataLoader.data.Strings.MakeString("RunCallBack"), - RetType = UndertaleExtensionVarType.Double, - Arguments = new UndertaleSimpleList() - { - new UndertaleExtensionFunctionArg() - { - Type = UndertaleExtensionVarType.String - } - }, - Kind = 11, - ID = PopScript.ID + 1 - }; - Functions.Add(RunCallBack); - - } - } -} diff --git a/FileReader.cs b/FileReader.cs index 67bd534..1782a1b 100644 --- a/FileReader.cs +++ b/FileReader.cs @@ -24,7 +24,7 @@ public class ModSource { public string Name { get; set; } public string Path { get; set; } - public bool isExisted => File.Exists(Path); + public bool Existed => File.Exists(Path); public override string ToString() { return Name; @@ -46,9 +46,9 @@ public class ModFile public FileStream Stream; public string Path; public Mod instance { get; set; } - public bool isEnabled { get; set; } + public bool Enabled { get; set; } public PatchStatus PatchStatus { get; set; } = PatchStatus.None; - public bool isExisted => File.Exists(Path); + public bool Existed => File.Exists(Path); public byte[] Icon { get; set; } = Array.Empty(); public override string ToString() { @@ -56,7 +56,7 @@ public override string ToString() } public byte[] GetFile(string fileName) { - if(!isExisted) + if(!Existed) { MessageBox.Show(Application.Current.FindResource("ModLostWarning").ToString() + " : " + Name); ModLoader.LoadFiles(); diff --git a/Main.xaml.cs b/Main.xaml.cs index 6382b3d..6a1d4e6 100644 --- a/Main.xaml.cs +++ b/Main.xaml.cs @@ -133,7 +133,7 @@ private void SetInitialSize() public void LogModList() { - foreach (ModFile modFile in ModPage.Mods.Where(x => x.isEnabled)) + foreach (ModFile modFile in ModPage.Mods.Where(x => x.Enabled)) { string statusMessage = ""; switch (modFile.PatchStatus) @@ -219,7 +219,7 @@ public class UserSettings { public string Language = "English"; public bool EnableLogger = true; - public List EnableMods = new(); + public List EnabledMods = new(); public static void LoadSettings() { // if no settings file, early stop @@ -233,16 +233,14 @@ public static void LoadSettings() CheckLog(Main.Settings.EnableLogger); // auto check active mods - if (Main.Settings.EnableMods.Count > 0) + if (Main.Settings.EnabledMods.Count > 0) { List listModFile = ModInfos.Instance.Mods; - foreach (string i in Main.Settings.EnableMods) + foreach (string i in Main.Settings.EnabledMods) { (int indexMod, ModFile? modFile) = listModFile.Enumerate().FirstOrDefault(t => t.Item2.Name == i); - if (modFile != null) - listModFile[indexMod].isEnabled = true; - else - Log.Warning($"Mod {i} not found"); + if (modFile != null) listModFile[indexMod].Enabled = true; + else Log.Warning($"Mod {i} not found"); } } } diff --git a/ModLoader.cs b/ModLoader.cs index 99ab7a7..5c8c473 100644 --- a/ModLoader.cs +++ b/ModLoader.cs @@ -11,10 +11,8 @@ using System.IO; using System.Reflection; using UndertaleModLib.Models; -using ModShardLauncher.Extensions; using ModShardLauncher.Controls; using Serilog; -using Xunit.Sdk; namespace ModShardLauncher { @@ -152,7 +150,7 @@ public static void LoadFiles() f.instance = mod; ModFile? old = mods.Find(t => t.Name == f.Name); - if (old != null) f.isEnabled = old.isEnabled; + if (old != null) f.Enabled = old.Enabled; modCaches.Add(f); } @@ -177,13 +175,14 @@ public static void PatchMods() Stopwatch watch = Stopwatch.StartNew(); foreach (ModFile mod in mods) { - if (!mod.isEnabled) continue; - if (!mod.isExisted) + if (!mod.Enabled) continue; + if (!mod.Existed) { MessageBox.Show(Application.Current.FindResource("ModLostWarning").ToString() + " : " + mod.Name); continue; } - Main.Settings.EnableMods.Add(mod.Name); + + Main.Settings.EnabledMods.Add(mod.Name); mod.PatchStatus = PatchStatus.Patching; if (mod.Version != Main.Instance.mslVersion) @@ -192,11 +191,6 @@ public static void PatchMods() } TextureLoader.LoadTextures(mod); mod.instance.PatchMod(); - foreach (Type type in Array.FindAll(mod.Assembly.GetTypes(), t => !t.IsAbstract)) - { - if (type.IsSubclassOf(typeof(Weapon))) - LoadWeapon(type); - } mod.PatchStatus = PatchStatus.Success; } Msl.AddDisclaimerRoom(Credits.Select(x => x.Item1).ToArray(), Credits.SelectMany(x => x.Item2).Distinct().ToArray()); @@ -207,83 +201,13 @@ public static void PatchMods() long elapsedMs = watch.ElapsedMilliseconds; Log.Information("Patching lasts {{{0}}} ms", elapsedMs); } - public static void LoadWeapon(Type type) - { - if (Activator.CreateInstance(type) is not Weapon weapon) return; - weapon.SetDefaults(); - (string, string, string) strs = weapon.AsString(); - Weapons.Insert(Weapons.IndexOf("SWORDS - BLADES;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;") + 1, strs.Item1); - WeaponDescriptions.Insert(WeaponDescriptions.IndexOf(";;SWORDS;;;;;;SWORDS;SWORDS;;;;") + 1, weapon.Name + ";" + string.Join(";", weapon.NameList.Values)); - WeaponDescriptions.Insert(WeaponDescriptions.IndexOf(";weapon_desc;weapon_desc;weapon_desc;weapon_desc;weapon_desc;weapon_desc;weapon_desc;weapon_desc;weapon_desc;weapon_desc;weapon_desc;weapon_desc;") + 1, - weapon.Name + ";" + string.Join(";", weapon.WeaponDescriptions.Values)); - WeaponDescriptions.Insert(WeaponDescriptions.IndexOf(";weapon_pronoun;weapon_pronoun;weapon_pronoun;weapon_pronoun;weapon_pronoun;weapon_pronoun;weapon_pronoun;weapon_pronoun;weapon_pronoun;weapon_pronoun;weapon_pronoun;weapon_pronoun;") + 1, - weapon.Name + ";He;;;It;She;She;She;She;He;;;;"); - } public static void PatchFile() { // add new msl log function LogUtils.InjectLog(); - PatchInnerFile(); PatchMods(); // add the new loot related functions if there is any LootUtils.InjectLootScripts(); } - internal static void PatchInnerFile() - { - if (Data.Code.All(x => x.Name.Content != "msl_print")) - Msl.AddInnerFunction("msl_print"); - if (Data.Code.All(x => x.Name.Content != "give")) - Msl.AddInnerFunction("give"); - if (Data.Code.All(x => x.Name.Content != "SendMsg")) - Msl.AddInnerFunction("SendMsg"); - if (Data.Code.All(x => x.Name.Content != "createHookObj")) - Msl.AddInnerFunction("createHookObj"); - - // Find the display_mouse_lock extension - var displayMouseLockExtension = Data.Extensions.FirstOrDefault(x => x.Name.Content == "display_mouse_lock"); - // Check if the display_mouse_lock extension exists and if ModShard.dll is not present among its files - if (displayMouseLockExtension != null && displayMouseLockExtension.Files.All(x => x.Filename.Content != "ModShard.dll")) - { - // Add ModShard extension - AddExtension(new ModShard()); - } - - if (Data.GameObjects.All(x => x.Name.Content != "o_ScriptEngine")) - { - UndertaleGameObject engine = Msl.AddObject("o_ScriptEngine"); - engine.Persistent = true; - UndertaleGameObject.Event ev = new() - { - EventSubtypeOther = EventSubtypeOther.AsyncNetworking - }; - ev.Actions.Add(new UndertaleGameObject.EventAction() - { - CodeId = Msl.AddInnerCode("ScriptEngine_server") - }); - engine.Events[7].Add(ev); - UndertaleGameObject.Event create = new(); - create.Actions.Add(new UndertaleGameObject.EventAction() - { - CodeId = Msl.AddInnerCode("ScriptEngine_create") - }); - engine.Events[0].Add(create); - UndertaleRoom start = Data.Rooms.First(t => t.Name.Content == "START"); - UndertaleRoom.GameObject newObj = new() - { - ObjectDefinition = engine, - InstanceID = Data.GeneralInfo.LastObj++ - }; - - start.GameObjects.Add(newObj); - } - else - // Should probably be replaced with a dialog box as it's not very visible as it is - Log.Warning("You are patching a non-vanilla .win file. This may cause some issues and is not recommended."); - } - public static void AddExtension(UndertaleExtensionFile file) - { - UndertaleExtension ext = Data.Extensions.First(t => t.Name.Content == "display_mouse_lock"); - ext.Files.Add(file); - } } } diff --git a/ModUtils/CodeUtils.cs b/ModUtils/CodeUtils.cs index 8af9f2c..5918f50 100644 --- a/ModUtils/CodeUtils.cs +++ b/ModUtils/CodeUtils.cs @@ -510,8 +510,8 @@ public static string Collect(this FileEnumerable<(Match, string)> fe) public static IEnumerable<(Match, string)> MatchBelow(this IEnumerable ienumerable, IEnumerable other, int len) { int i = 0; // used for keeping tracked about how many lines after the block we pass by - bool encounteredTheBlock = false; // bool to track if we already encountered the block, disabling the 2nd case of the if/else - bool passedTheBlock = false; // bool to track if we already passed the block, disabling the 1st case of the if/else + bool encounteredBlock = false; // bool to track if we already encountered the block, disabling the 2nd case of the if/else + bool passedBlock = false; // bool to track if we already passed the block, disabling the 1st case of the if/else string? otherString = null; IEnumerator otherEnumerator = other.GetEnumerator(); if (otherEnumerator.MoveNext()) @@ -519,25 +519,25 @@ public static string Collect(this FileEnumerable<(Match, string)> fe) foreach (string element in ienumerable) { - if (!passedTheBlock && otherString != null && element.Contains(otherString)) // can only test the other iter if in Before + if (!passedBlock && otherString != null && element.Contains(otherString)) // can only test the other iter if in Before { - encounteredTheBlock = true; + encounteredBlock = true; yield return (Match.Before, element); if (otherEnumerator.MoveNext()) otherString = otherEnumerator.Current; else { // consumed the iter, time go to in matching - passedTheBlock = true; + passedBlock = true; } } - else if (!encounteredTheBlock) // here when you still havent encountered the other iter + else if (!encounteredBlock) // here when you still havent encountered the other iter { yield return (Match.Before, element); } else if (i < len) // here when either the iter was consumed, either it was not matching anymore { - passedTheBlock = true; + passedBlock = true; yield return (Match.Matching, element); i++; // can stay only len in matching } @@ -547,7 +547,7 @@ public static string Collect(this FileEnumerable<(Match, string)> fe) } } - if (!encounteredTheBlock) + if (!encounteredBlock) { throw new Exception("MatchBelow: No matching lines found. Items to match: " + string.Join("\r\n", other)); } diff --git a/ModUtils/GeneralUtils.cs b/ModUtils/GeneralUtils.cs index 7a11ee9..983434e 100644 --- a/ModUtils/GeneralUtils.cs +++ b/ModUtils/GeneralUtils.cs @@ -306,8 +306,7 @@ public static IEnumerable SelectionSamplingTechnique(this IList list, i while(m < nn) { // they implement the xoshiro256** but only for non-negative int64 - // what some fucking donkeys - // so I've written a proper xoshiro256** return a UINT64 + // so I've written a proper xoshiro256** that returns a UINT64 x = NextUINT64(); // conversion to a [0, 1] uniform double // see https://prng.di.unimi.it/ From d1a363d664b79c869978977a5cbae047f67df092 Mon Sep 17 00:00:00 2001 From: remyCases Date: Sun, 7 Sep 2025 01:36:36 +0200 Subject: [PATCH 4/9] Major] removing useless legacy code, new resource loader, logger for MSL as external resource GML --- CodeResources.cs | 41 +++++ ModShardLauncher.csproj | 160 +----------------- ModShardLauncherTest/LocalizationUtilsTest.cs | 4 - ModUtils/CodeUtils.cs | 11 +- ModUtils/LogUtils.cs | 107 +----------- Resources/Codes/CodeResources.Designer.cs | 123 -------------- Resources/Codes/CodeResources.resx | 139 --------------- .../Codes/LoggerModule/o_msl_log_Create_0.gml | 11 ++ .../LoggerModule/o_msl_timer_Create_0.gml | 3 + .../Codes/LoggerModule/o_msl_timer_Step_0.gml | 9 + Resources/Codes/LoggerModule/scr_msl_log.gml | 47 +++++ Resources/Codes/ScriptEngine_create.gml | 5 - Resources/Codes/ScriptEngine_server.gml | 38 ----- Resources/Codes/SendMsg.gml | 21 --- Resources/Codes/createHookObj.gml | 7 - Resources/Codes/give.gml | 13 -- Resources/Codes/msl_print.gml | 4 - 17 files changed, 127 insertions(+), 616 deletions(-) create mode 100644 CodeResources.cs delete mode 100644 Resources/Codes/CodeResources.Designer.cs delete mode 100644 Resources/Codes/CodeResources.resx create mode 100644 Resources/Codes/LoggerModule/o_msl_log_Create_0.gml create mode 100644 Resources/Codes/LoggerModule/o_msl_timer_Create_0.gml create mode 100644 Resources/Codes/LoggerModule/o_msl_timer_Step_0.gml create mode 100644 Resources/Codes/LoggerModule/scr_msl_log.gml delete mode 100644 Resources/Codes/ScriptEngine_create.gml delete mode 100644 Resources/Codes/ScriptEngine_server.gml delete mode 100644 Resources/Codes/SendMsg.gml delete mode 100644 Resources/Codes/createHookObj.gml delete mode 100644 Resources/Codes/give.gml delete mode 100644 Resources/Codes/msl_print.gml diff --git a/CodeResources.cs b/CodeResources.cs new file mode 100644 index 0000000..a49dc6e --- /dev/null +++ b/CodeResources.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using Serilog; + +namespace ModShardLauncher +{ + internal static class CodeResources + { + private static readonly Lazy> _scripts = new(LoadAllScripts); + public static string GetGML(string name) + { + if (_scripts.Value.TryGetValue(name, out var script)) return script; + + throw new ArgumentException($"GML script '{name}' not found"); + } + private static Dictionary LoadAllScripts() + { + Dictionary scripts = new(); + Assembly assembly = Assembly.GetExecutingAssembly(); + + // Load all .gml resources + IEnumerable resourceNames = assembly.GetManifestResourceNames() + .Where(name => name.EndsWith(".gml")); + foreach (string resourceName in resourceNames) + { + string? scriptName = Path.GetFileNameWithoutExtension(resourceName); + + using Stream? stream = + assembly.GetManifestResourceStream(resourceName) ?? + throw new FileNotFoundException($"GML script '{scriptName}' not found"); + using StreamReader reader = new(stream); + scripts[scriptName.Split('.').Last()] = reader.ReadToEnd(); + } + + return scripts; + } + } +} diff --git a/ModShardLauncher.csproj b/ModShardLauncher.csproj index dc1d6a8..0ed98f9 100644 --- a/ModShardLauncher.csproj +++ b/ModShardLauncher.csproj @@ -14,133 +14,19 @@ - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - True - True - CodeResources.resx - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -171,45 +57,11 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - ResXFileCodeGenerator - CodeResources.Designer.cs - + diff --git a/ModShardLauncherTest/LocalizationUtilsTest.cs b/ModShardLauncherTest/LocalizationUtilsTest.cs index 3919ab5..eebc8a2 100644 --- a/ModShardLauncherTest/LocalizationUtilsTest.cs +++ b/ModShardLauncherTest/LocalizationUtilsTest.cs @@ -1,9 +1,5 @@ -using Xunit; -using System.Collections.Generic; using ModShardLauncher.Mods; using System.Reflection; -using ModShardLauncher.Extensions; -using ModShardLauncher; namespace ModShardLauncherTest { diff --git a/ModUtils/CodeUtils.cs b/ModUtils/CodeUtils.cs index 5918f50..12e54ae 100644 --- a/ModUtils/CodeUtils.cs +++ b/ModUtils/CodeUtils.cs @@ -1,9 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using ModShardLauncher.Resources.Codes; using Serilog; using UndertaleModLib; using UndertaleModLib.Decompiler; @@ -174,13 +171,7 @@ public static UndertaleCode AddCodeAsm(string codeAsString, string name) /// internal static string GetCodeRes(string name) { - var data = CodeResources.ResourceManager.GetObject(name, CodeResources.Culture) as byte[]; - if (data == null) - { - Log.Information($"Code resource not found :{name}"); - return ""; - } - return Encoding.UTF8.GetString(data); + return CodeResources.GetGML(name); } /// /// Add a new code from the code in this tool. diff --git a/ModUtils/LogUtils.cs b/ModUtils/LogUtils.cs index ae0e96c..715f19f 100644 --- a/ModUtils/LogUtils.cs +++ b/ModUtils/LogUtils.cs @@ -11,108 +11,19 @@ public static class LogUtils { public static void InjectLog() { - string mslLog = @"function scr_msl_log(argument0) -{ -var time = date_datetime_string(date_current_datetime()); -if (global._msl_log != noone) -{ - if (global._msl_log.buf != noone) - { - var string_log = ""["" + time + ""]: "" + argument0 + ""\n""; - var len_log = string_byte_length(string_log); - - if (len_log > global._msl_log.size - 1) - { - var msg_space = global._msl_log.size - string_byte_length(""["" + time + ""]: \n"") - 1; - argument0 = string_copy(argument0, 1, msg_space); - string_log = ""["" + time + ""]: "" + argument0 + ""\n""; - len_log = string_byte_length(string_log); - } - - if (len_log + global._msl_log.cur_size > global._msl_log.size) - { - scr_msl_log_save(); - global._msl_log.nfile += 1; - global._msl_log.cur_size = 0; - } - - buffer_write(global._msl_log.buf, buffer_text, string_log); - global._msl_log.cur_size += len_log; - - if (global._msl_log.timer == noone || !instance_exists(global._msl_log.timer)) - { - var t = instance_create_depth(0, 0, -100, o_msl_timer); - t.end_time = 5; - t.func = gml_Script_scr_msl_log_save; - - global._msl_log.timer = t.id; - } - } - else - { - scr_actionsLogUpdate(""msl log buff does not exist. Please report that bug to the MSL devs.""); - } -} -else -{ - scr_actionsLogUpdate(""msl log does not exist. Please report that bug to the MSL devs.""); -} -}"; - - string mslLogSave = @"function scr_msl_log_save() -{ - if (global._msl_log.save_in_progress) return; - - global._msl_log.save_in_progress = true; - var nfile_name = global._msl_log.name + ""_"" + string(global._msl_log.nfile) + "".txt""; - buffer_save_async(global._msl_log.buf, nfile_name, 0, global._msl_log.cur_size); - - global._msl_log.save_in_progress = false; - instance_destroy(global._msl_log.timer); -}"; - UndertaleGameObject timer = Msl.AddObject("o_msl_timer", isPersistent: true); - Msl.AddNewEvent(timer, @" -func = -4; -end_time = 0; -cumulative_time = 0;", - EventType.Create, 0); - - Msl.AddNewEvent(timer, @" -cumulative_time += delta_time / 1000000; -if (cumulative_time > end_time) -{ - if (func != noone) - { - script_execute(func) - } - instance_destroy(); -}", - EventType.Step, 0); - UndertaleGameObject log = Msl.AddObject("o_msl_log", isPersistent: true); - Msl.AddNewEvent(log, @" -size = 1000000 -buf = buffer_create(size, buffer_wrap, 1); -cur_size = 0 -nfile = 0 -save_in_progress = false - -var curr_time = date_current_datetime(); -var format_time = string_format(date_get_year(curr_time), 2, 0) + string_format(date_get_month(curr_time), 2, 0) + string_format(date_get_day(curr_time), 2, 0) + ""_"" + string_format(date_get_hour(curr_time), 2, 0) + string_format(date_get_minute(curr_time), 2, 0); -name = ""Logs/msl_log_"" + string_replace_all(format_time, "" "", ""0""); -timer = -4 -", - EventType.Create, 0); - - Msl.AddFunction(mslLogSave, "scr_msl_log_save"); - Msl.AddFunction(mslLog, "scr_msl_log"); Msl.LoadGML(Msl.EventName("o_gameLoader", EventType.Create, 0)) .MatchAll() - .InsertBelow(@" -global._msl_log = instance_create_depth(0, 0, -100, o_msl_log); -") - .Save(); + .InsertBelow("global._msl_log = instance_create_depth(0, 0, -100, o_msl_log);") + .Save(); + + Msl.AddNewEvent(timer, Msl.GetCodeRes("o_msl_timer_Create_0"), EventType.Create, 0); + Msl.AddNewEvent(timer, Msl.GetCodeRes("o_msl_timer_Step_0"), EventType.Step, 0); + Msl.AddNewEvent(log, Msl.GetCodeRes("o_msl_log_Create_0"), EventType.Create, 0); + + Msl.AddInnerFunction("scr_msl_log_save"); + Msl.AddInnerFunction("scr_msl_log"); } } \ No newline at end of file diff --git a/Resources/Codes/CodeResources.Designer.cs b/Resources/Codes/CodeResources.Designer.cs deleted file mode 100644 index e2c9372..0000000 --- a/Resources/Codes/CodeResources.Designer.cs +++ /dev/null @@ -1,123 +0,0 @@ -//------------------------------------------------------------------------------ -// -// 此代码由工具生成。 -// 运行时版本:4.0.30319.42000 -// -// 对此文件的更改可能会导致不正确的行为,并且如果 -// 重新生成代码,这些更改将会丢失。 -// -//------------------------------------------------------------------------------ - -namespace ModShardLauncher.Resources.Codes { - using System; - - - /// - /// 一个强类型的资源类,用于查找本地化的字符串等。 - /// - // 此类是由 StronglyTypedResourceBuilder - // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 - // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen - // (以 /str 作为命令选项),或重新生成 VS 项目。 - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class CodeResources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal CodeResources() { - } - - /// - /// 返回此类使用的缓存的 ResourceManager 实例。 - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ModShardLauncher.Resources.Codes.CodeResources", typeof(CodeResources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// 重写当前线程的 CurrentUICulture 属性,对 - /// 使用此强类型资源类的所有资源查找执行重写。 - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// 查找 System.Byte[] 类型的本地化资源。 - /// - internal static byte[] createHookObj { - get { - object obj = ResourceManager.GetObject("createHookObj", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// 查找 System.Byte[] 类型的本地化资源。 - /// - internal static byte[] give { - get { - object obj = ResourceManager.GetObject("give", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// 查找 System.Byte[] 类型的本地化资源。 - /// - internal static byte[] msl_print { - get { - object obj = ResourceManager.GetObject("msl_print", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// 查找 System.Byte[] 类型的本地化资源。 - /// - internal static byte[] ScriptEngine_create { - get { - object obj = ResourceManager.GetObject("ScriptEngine_create", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// 查找 System.Byte[] 类型的本地化资源。 - /// - internal static byte[] ScriptEngine_server { - get { - object obj = ResourceManager.GetObject("ScriptEngine_server", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// 查找 System.Byte[] 类型的本地化资源。 - /// - internal static byte[] SendMsg { - get { - object obj = ResourceManager.GetObject("SendMsg", resourceCulture); - return ((byte[])(obj)); - } - } - } -} diff --git a/Resources/Codes/CodeResources.resx b/Resources/Codes/CodeResources.resx deleted file mode 100644 index 501e387..0000000 --- a/Resources/Codes/CodeResources.resx +++ /dev/null @@ -1,139 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - createHookObj.gml;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - give.gml;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - msl_print.gml;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ScriptEngine_create.gml;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ScriptEngine_server.gml;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - SendMsg.gml;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/Resources/Codes/LoggerModule/o_msl_log_Create_0.gml b/Resources/Codes/LoggerModule/o_msl_log_Create_0.gml new file mode 100644 index 0000000..d4b8a5a --- /dev/null +++ b/Resources/Codes/LoggerModule/o_msl_log_Create_0.gml @@ -0,0 +1,11 @@ +size = 1000000 +buf = buffer_create(size, buffer_wrap, 1); +cur_size = 0 +nfile = 0 +save_in_progress = false + +var curr_time = date_current_datetime(); +var format_time = string_format(date_get_year(curr_time), 2, 0) + string_format(date_get_month(curr_time), 2, 0) + string_format(date_get_day(curr_time), 2, 0) + "_" + string_format(date_get_hour(curr_time), 2, 0) + string_format(date_get_minute(curr_time), 2, 0); +name = "Logs/msl_log_" + string_replace_all(format_time, " ", "0"); + +timer = -4 \ No newline at end of file diff --git a/Resources/Codes/LoggerModule/o_msl_timer_Create_0.gml b/Resources/Codes/LoggerModule/o_msl_timer_Create_0.gml new file mode 100644 index 0000000..844bbb9 --- /dev/null +++ b/Resources/Codes/LoggerModule/o_msl_timer_Create_0.gml @@ -0,0 +1,3 @@ +func = -4; +end_time = 0; +cumulative_time = 0; \ No newline at end of file diff --git a/Resources/Codes/LoggerModule/o_msl_timer_Step_0.gml b/Resources/Codes/LoggerModule/o_msl_timer_Step_0.gml new file mode 100644 index 0000000..3ad7b67 --- /dev/null +++ b/Resources/Codes/LoggerModule/o_msl_timer_Step_0.gml @@ -0,0 +1,9 @@ +cumulative_time += delta_time / 1000000; +if (cumulative_time > end_time) +{ + if (func != noone) + { + script_execute(func) + } + instance_destroy(); +} \ No newline at end of file diff --git a/Resources/Codes/LoggerModule/scr_msl_log.gml b/Resources/Codes/LoggerModule/scr_msl_log.gml new file mode 100644 index 0000000..39af3d7 --- /dev/null +++ b/Resources/Codes/LoggerModule/scr_msl_log.gml @@ -0,0 +1,47 @@ +function scr_msl_log(argument0) +{ + var time = date_datetime_string(date_current_datetime()); + if (global._msl_log != noone) + { + if (global._msl_log.buf != noone) + { + var string_log = "[" + time + "]: " + argument0 + "\n"; + var len_log = string_byte_length(string_log); + + if (len_log > global._msl_log.size - 1) + { + var msg_space = global._msl_log.size - string_byte_length("[" + time + "]: \n") - 1; + argument0 = string_copy(argument0, 1, msg_space); + string_log = "[" + time + "]: " + argument0 + "\n"; + len_log = string_byte_length(string_log); + } + + if (len_log + global._msl_log.cur_size > global._msl_log.size) + { + scr_msl_log_save(); + global._msl_log.nfile += 1; + global._msl_log.cur_size = 0; + } + + buffer_write(global._msl_log.buf, buffer_text, string_log); + global._msl_log.cur_size += len_log; + + if (global._msl_log.timer == noone || !instance_exists(global._msl_log.timer)) + { + var t = instance_create_depth(0, 0, -100, o_msl_timer); + t.end_time = 5; + t.func = gml_Script_scr_msl_log_save; + + global._msl_log.timer = t.id; + } + } + else + { + scr_actionsLogUpdate("msl log buff does not exist. Please report that bug to the MSL devs."); + } + } + else + { + scr_actionsLogUpdate("msl log does not exist. Please report that bug to the MSL devs."); + } +} \ No newline at end of file diff --git a/Resources/Codes/ScriptEngine_create.gml b/Resources/Codes/ScriptEngine_create.gml deleted file mode 100644 index b38dd7a..0000000 --- a/Resources/Codes/ScriptEngine_create.gml +++ /dev/null @@ -1,5 +0,0 @@ -client = network_create_socket(0) -network_set_config(network_config_connect_timeout, 1000) -server = network_connect_raw(client, "127.0.0.1", 1333) -global.Server = server -SendMsg("HOK", "OnGameStart", true) \ No newline at end of file diff --git a/Resources/Codes/ScriptEngine_server.gml b/Resources/Codes/ScriptEngine_server.gml deleted file mode 100644 index bf00203..0000000 --- a/Resources/Codes/ScriptEngine_server.gml +++ /dev/null @@ -1,38 +0,0 @@ -if (server >= 0 && ds_exists(async_load, 1)) -{ - var cid = ds_map_find_value(async_load, "id") - var t = ds_map_find_value(async_load, "type") - if (t == 3) - { - var buffer = ds_map_find_value(async_load, "buffer") - var length = buffer_read(buffer, buffer_u32) - var ID = buffer_read(buffer, buffer_u32) - var message = "" - for (var i = 0; i < length; i++) - message += buffer_read(buffer, buffer_string) - var scr = string_split(message, " ") - var scriptID = asset_get_index(scr[0]) - array_delete(scr, 0, 1) - for (i = 0; i < array_length(scr); i++) - { - if (string_starts_with(scr[i], "\"") && string_ends_with(scr[i], "\"")) - { - scr[i] = string_replace_all(scr[i], "_", " ") - scr[i] = string_delete(scr[i], 1, 1) - scr[i] = string_delete(scr[i], string_length(scr[i]), 1) - } - } - var ret = "" - if (scriptID == -1) - ret = ("script is wrong: " + message) - else if (array_length(scr) > 0) - ret = script_execute_ext(scriptID, scr) - else - ret = script_execute(scriptID) - buffer = buffer_create(4, buffer_grow, 1) - buffer_write(buffer, buffer_u32, ID) - buffer_write(buffer, buffer_string, "[CLB]") - buffer_write(buffer, buffer_string, message) - network_send_raw(server, buffer, buffer_get_size(buffer)) - } -} \ No newline at end of file diff --git a/Resources/Codes/SendMsg.gml b/Resources/Codes/SendMsg.gml deleted file mode 100644 index fdacd42..0000000 --- a/Resources/Codes/SendMsg.gml +++ /dev/null @@ -1,21 +0,0 @@ -function SendMsg(argument0, argument1, argument2) -{ - var buffer = buffer_create(4, buffer_grow, 1) - switch (argument0) - { - case "MSG": - buffer_write(buffer, buffer_u32, -1) - break - case "CLB": - buffer_write(buffer, buffer_u32, argument2) - break - case "HOK": - buffer_write(buffer, buffer_u32, -1) - break - } - - buffer_write(buffer, buffer_string, (("[" + argument0) + "]")) - buffer_write(buffer, buffer_string, argument1) - if (argument0 == "HOK") buffer_write(buffer, buffer_string, "" + string(argument2)) - network_send_raw(global.Server, buffer, buffer_get_size(buffer)) -} \ No newline at end of file diff --git a/Resources/Codes/createHookObj.gml b/Resources/Codes/createHookObj.gml deleted file mode 100644 index b787da3..0000000 --- a/Resources/Codes/createHookObj.gml +++ /dev/null @@ -1,7 +0,0 @@ -function createHookObj() -{ - var res = array_create(argument[0]) - for(var i = 1; i <= argument[0]; i++) - res[i - 1] = variable_instance_get(id, argument[i]) - return json_stringify(res, 1) -} \ No newline at end of file diff --git a/Resources/Codes/give.gml b/Resources/Codes/give.gml deleted file mode 100644 index d507af3..0000000 --- a/Resources/Codes/give.gml +++ /dev/null @@ -1,13 +0,0 @@ -function give(argument0, argument1) -{ - switch argument1 - { - case "weapon": - with (o_inventory) - { - with (scr_inventory_add_weapon(argument0, (1 << 0))) - scr_inv_atr_set("Duration", 100) - } - break - } -} \ No newline at end of file diff --git a/Resources/Codes/msl_print.gml b/Resources/Codes/msl_print.gml deleted file mode 100644 index f06617a..0000000 --- a/Resources/Codes/msl_print.gml +++ /dev/null @@ -1,4 +0,0 @@ -function msl_print(argument0) -{ - show_message(argument0) -} \ No newline at end of file From 91e4a3b757935678e0bdc8aa025e205beee5a812 Mon Sep 17 00:00:00 2001 From: remyCases Date: Sun, 7 Sep 2025 01:37:19 +0200 Subject: [PATCH 5/9] Major] missing external resource GML --- Resources/Codes/LoggerModule/scr_msl_log_save.gml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 Resources/Codes/LoggerModule/scr_msl_log_save.gml diff --git a/Resources/Codes/LoggerModule/scr_msl_log_save.gml b/Resources/Codes/LoggerModule/scr_msl_log_save.gml new file mode 100644 index 0000000..a4b920f --- /dev/null +++ b/Resources/Codes/LoggerModule/scr_msl_log_save.gml @@ -0,0 +1,11 @@ +function scr_msl_log_save() +{ + if (global._msl_log.save_in_progress) return; + + global._msl_log.save_in_progress = true; + var nfile_name = global._msl_log.name + "_" + string(global._msl_log.nfile) + ".txt"; + buffer_save_async(global._msl_log.buf, nfile_name, 0, global._msl_log.cur_size); + + global._msl_log.save_in_progress = false; + instance_destroy(global._msl_log.timer); +} \ No newline at end of file From 1ba6d8e3c8b9bc2c4d5817e152b0d9a352006e88 Mon Sep 17 00:00:00 2001 From: remyCases Date: Sun, 7 Sep 2025 02:47:18 +0200 Subject: [PATCH 6/9] [Major] loot utils scripts as external gml files, fixes loot utils for chest --- ModUtils/LootUtils.cs | 333 +----------------- .../scr_msl_resolve_guaranteed_items.gml | 30 ++ .../LootModule/scr_msl_resolve_items.gml | 49 +++ .../LootModule/scr_msl_resolve_loot_table.gml | 68 ++++ .../scr_msl_resolve_random_items.gml | 75 ++++ .../scr_msl_resolve_refence_table.gml | 86 +++++ 6 files changed, 317 insertions(+), 324 deletions(-) create mode 100644 Resources/Codes/LootModule/scr_msl_resolve_guaranteed_items.gml create mode 100644 Resources/Codes/LootModule/scr_msl_resolve_items.gml create mode 100644 Resources/Codes/LootModule/scr_msl_resolve_loot_table.gml create mode 100644 Resources/Codes/LootModule/scr_msl_resolve_random_items.gml create mode 100644 Resources/Codes/LootModule/scr_msl_resolve_refence_table.gml diff --git a/ModUtils/LootUtils.cs b/ModUtils/LootUtils.cs index 308db2e..ed2a824 100644 --- a/ModUtils/LootUtils.cs +++ b/ModUtils/LootUtils.cs @@ -97,330 +97,12 @@ public static void InjectLootScripts() { if (LootTables.Count == 0 && ReferenceTables.Count == 0) return; - string mslItemsFunction = @"function scr_msl_resolve_items(argument0, argument1, argument2, argument3, argument4) -{ - if (argument1 == -1) - { - var objectName = argument0; - var obj = """"; - if (argument3 == 0) - { - obj = asset_get_index(""o_inv_"" + objectName) - if (obj > -1) - { - scr_inventory_add_item(obj); - } - else - { - scr_msl_log(""invalid object "" + string(objectName)); - } - } - else - { - obj = asset_get_index(""o_loot_"" + objectName) - if (obj > -1) - { - scr_loot_drop(argument4.x, argument4.y, obj) - } - else - { - scr_msl_log(""invalid object "" + string(objectName)); - } - } - } - else - { - if (argument3 == 0) - { - with (scr_inventory_add_weapon(argument0, argument1)) - { - scr_inv_atr_set(""Duration"", argument2); - } - } - else - { - with (scr_weapon_loot(argument0, argument4.x, argument4.y, 100, argument1)) - { - scr_inv_atr_set(""Duration"", argument2) - } - } - } -}"; + Msl.AddInnerFunction("scr_msl_resolve_items"); + Msl.AddInnerFunction("scr_msl_resolve_refence_table"); + Msl.AddInnerFunction("scr_msl_resolve_guaranteed_items"); + Msl.AddInnerFunction("scr_msl_resolve_random_items"); + Msl.AddInnerFunction("scr_msl_resolve_loot_table"); - string mslRefFunction = @"function scr_msl_resolve_refence_table(argument0) -{ - var objectName = object_get_name(argument0.object_index); - var refFile = file_text_open_read(""reference_table.json""); - var refJson = file_text_read_string(refFile); - var refData = json_parse(refJson); - - var min_lvl = scr_globaltile_dungeon_get(""mob_lvl_min""); - var max_lvl = scr_globaltile_dungeon_get(""mob_lvl_max""); - var tier = floor(((max_lvl + min_lvl) / 2)); - scr_msl_log(""current tier: "" + string(tier)); - - if (!variable_struct_exists(refData, objectName)) - { - scr_msl_log(""cant find object "" + objectName); - file_text_close(refFile); - return -4; - } - var refStruct = variable_struct_get(refData, objectName); - var referenceLootTableIndex = -1; - - if (!variable_struct_exists(refStruct, ""DefaultTable"")) - { - scr_msl_log(""cant find DefaultTable""); - file_text_close(refFile); - return -4; - } - var defaultTable = variable_struct_get(refStruct, ""DefaultTable""); - - if (!variable_struct_exists(refStruct, ""Ids"")) - { - scr_msl_log(""cant find Ids""); - file_text_close(refFile); - return -4; - } - var idsStruct = variable_struct_get(refStruct, ""Ids""); - - var _ids = variable_struct_get_names(idsStruct); - for (var i = 0; i < array_length(_ids); i++;) - { - if (real(_ids[i]) == argument0.id) - { - var referenceLootTable = variable_struct_get(idsStruct, _ids[i]); - scr_msl_log(""ref with id: "" + referenceLootTable); - file_text_close(refFile); - return referenceLootTable; - } - } - - if (!variable_struct_exists(refStruct, ""Tiers"")) - { - scr_msl_log(""cant find Tiers""); - file_text_close(refFile); - return -4; - } - var tiersStruct = variable_struct_get(refStruct, ""Tiers""); - var tiers = variable_struct_get_names(tiersStruct); - var indexTier = -1; - - for (var i = 0; i < array_length(tiers); i++;) - { - if (tier < real(tiers[i])) - { - indexTier = i - 1; - break; - } - else - { - indexTier = i; - } - } - - if (indexTier == -1) - { - var referenceLootTable = defaultTable; - scr_msl_log(""ref with default: "" + referenceLootTable); - } - else - { - var referenceLootTable = variable_struct_get(tiersStruct, tiers[indexTier]); - scr_msl_log(""ref with tier: "" + referenceLootTable); - } - - file_text_close(refFile); - return referenceLootTable; -}"; - - string mslLootGuaranteedItemsFunction = @"function scr_msl_resolve_guaranteed_items(argument0, argument1, argument2) -{ - if (!variable_struct_exists(argument0, ""ListItems"") - || !variable_struct_exists(argument0, ""ListRarity"") - || !variable_struct_exists(argument0, ""ListDurability"")) - { - scr_msl_log(""no ItemsTable data""); - return 0; - } - - var items = variable_struct_get(argument0, ""ListItems""); - var rarity = variable_struct_get(argument0, ""ListRarity""); - var durability = variable_struct_get(argument0, ""ListDurability""); - - var size_array = array_length(items); - - if (size_array != array_length(rarity) || - size_array != array_length(durability)) - { - scr_msl_log(""List with incorrect size""); - return 0; - } - - for(var _i = 0; _i < size_array; _i++) - { - scr_msl_resolve_items(items[_i], rarity[_i], durability[_i], argument1, argument2); - } - - return 1; -} -"; - string mslLootRandomItemsFunction = @"function scr_msl_resolve_random_items(argument0, argument1, argument2, argument3, argument4) -{ - if (!variable_struct_exists(argument0, ""ItemsTable"") - || !variable_struct_exists(argument0, ""ListWeight"")) - { - scr_msl_log(""no randomLoot data""); - return 0; - } - - var itemsTable = variable_struct_get(argument0, ""ItemsTable""); - var weight = variable_struct_get(argument0, ""ListWeight""); - - if (!variable_struct_exists(itemsTable, ""ListItems"") - || !variable_struct_exists(itemsTable, ""ListRarity"") - || !variable_struct_exists(itemsTable, ""ListDurability"")) - { - scr_msl_log(""no randomLoot data""); - return 0; - } - - var items = variable_struct_get(itemsTable, ""ListItems""); - var rarity = variable_struct_get(itemsTable, ""ListRarity""); - var durability = variable_struct_get(itemsTable, ""ListDurability""); - - var sizeItems = array_length(items); - var tableItemsSpecialLootAlready = array_create(sizeItems, 0); - - for (var _j = 0; _j < argument3; _j++) - { - var totalWeight = argument4; - for (var _i = 0; _i < sizeItems; _i++) - { - if (ds_list_find_index(scr_atr(""specialItemsPool""), items[_i]) != -1) - { - tableItemsSpecialLootAlready[_i] = 1; - } - else - { - totalWeight += weight[_i]; - } - } - scr_msl_log(""totalWeight "" + string(totalWeight)); - - var randomWeight = irandom(totalWeight - 1); - scr_msl_log(""randomWeight "" + string(randomWeight)); - var cumulativeWeight = 0; - var index = -1; - - for (var _i = 0; _i < sizeItems; _i++) - { - if (tableItemsSpecialLootAlready[_i] == 1) - { - continue; - } - cumulativeWeight += weight[_i] - if (randomWeight < cumulativeWeight) - { - index = _i; - break; - } - } - - if (index != -1) - { - scr_msl_log(""found "" + string(index)); - scr_msl_resolve_items(items[index], rarity[index], durability[index], argument1, argument2); - } - else - { - scr_msl_log(""found empty""); - } - } - - return 1; -}"; - - string mslLootFunction = @"function scr_msl_resolve_loot_table(argument0, argument1) -{ - var objectName = object_get_name(argument0.object_index); - scr_msl_log(""instance: "" + string(argument0.id) + "" of "" + objectName); - - var referenceLootTable = scr_msl_resolve_refence_table(argument0); - if (referenceLootTable == noone) - { - scr_msl_log(""Reference Table resolution failed""); - return 0; - } - - var file = file_text_open_read(""loot_table.json""); - var json = file_text_read_string(file); - var data = json_parse(json); - - if (!variable_struct_exists(data, referenceLootTable)) - { - scr_msl_log(""cant find ref "" + referenceLootTable); - file_text_close(file); - return 0; - } - var lootStruct = variable_struct_get(data, referenceLootTable); - - if (!variable_struct_exists(lootStruct, ""GuaranteedItems"")) - { - scr_msl_log(""no guaranteedItems""); - file_text_close(""loot_table.json""); - return 0; - } - var guaranteedItems = variable_struct_get(lootStruct, ""GuaranteedItems""); - - if (!scr_msl_resolve_guaranteed_items(guaranteedItems, argument1, argument0)) - { - scr_msl_log(""Guaranteed Items resolution failed""); - file_text_close(""loot_table.json""); - return 0; - } - - if (!variable_struct_exists(lootStruct, ""RandomLootMin"") || !variable_struct_exists(lootStruct, ""RandomLootMax"") || !variable_struct_exists(lootStruct, ""EmptyWeight"")) - { - scr_msl_log(""no int""); - file_text_close(""loot_table.json""); - return 0; - } - - var randomLootMin = variable_struct_get(lootStruct, ""RandomLootMin""); - var randomLootMax = variable_struct_get(lootStruct, ""RandomLootMax""); - var emptyWeight = variable_struct_get(lootStruct, ""EmptyWeight""); - - var iteration = randomLootMin + irandom(randomLootMax - randomLootMin); - scr_msl_log(""iteration "" + string(iteration)); - - if (!variable_struct_exists(lootStruct, ""RandomItemsTable"")) - { - scr_msl_log(""no RandomItemsTable""); - file_text_close(""loot_table.json""); - return 0; - } - - var randomItemsTable = variable_struct_get(lootStruct, ""RandomItemsTable""); - - scr_msl_resolve_random_items(randomItemsTable, argument1, argument0, iteration, emptyWeight); - - file_text_close(file); - - return 1; -}"; - - Msl.AddFunction(mslItemsFunction, "scr_msl_resolve_items"); - Msl.AddFunction(mslRefFunction, "scr_msl_resolve_refence_table"); - Msl.AddFunction(mslLootGuaranteedItemsFunction, "scr_msl_resolve_guaranteed_items"); - Msl.AddFunction(mslLootRandomItemsFunction, "scr_msl_resolve_random_items"); - Msl.AddFunction(mslLootFunction, "scr_msl_resolve_loot_table"); - - Msl.LoadGML("gml_Object_o_chest_p_Alarm_1") - .MatchFrom("script_execute") - .InsertBelow("scr_msl_resolve_loot_table(other, 0)") - .Save(); - Msl.LoadGML("gml_Object_c_container_Other_10") .MatchFrom("script_execute") .InsertBelow("scr_msl_resolve_loot_table(other, 0)") @@ -438,20 +120,23 @@ public static void AddLootTable(string lootTableID, ItemsTable guaranteedItems, { LootTable lootTable = new(guaranteedItems, randomLootMin, randomLootMax, emptyWeight, randomItemsTable); LootUtils.LootTables.Add(lootTableID, lootTable); + Log.Information("Adding LootTable {0}", lootTableID); } public static void AddReferenceTable(string nameObject, string table) { LootUtils.ReferenceTables.Add(nameObject, new ReferenceTable(table, new Dictionary(), new Dictionary())); + Log.Information("Adding ReferenceTable {0} for {1}", table, nameObject); } public static void AddReferenceTable(string nameObject, string table, Dictionary? ids, Dictionary? tiers) { LootUtils.ReferenceTables.Add(nameObject, new ReferenceTable(table, ids ?? new Dictionary(), tiers ?? new Dictionary())); + Log.Information("Adding ReferenceTable {0} for {1}", table, nameObject); } public static void AddReferenceTableForMultipleObjects(string table, params string[] nameObjects) { foreach(string nameObject in nameObjects) { - LootUtils.ReferenceTables.Add(nameObject, new ReferenceTable(table, new Dictionary(), new Dictionary())); + Msl.AddReferenceTable(nameObject, table); } } } diff --git a/Resources/Codes/LootModule/scr_msl_resolve_guaranteed_items.gml b/Resources/Codes/LootModule/scr_msl_resolve_guaranteed_items.gml new file mode 100644 index 0000000..76c71b7 --- /dev/null +++ b/Resources/Codes/LootModule/scr_msl_resolve_guaranteed_items.gml @@ -0,0 +1,30 @@ +function scr_msl_resolve_guaranteed_items(argument0, argument1, argument2) +{ + if (!variable_struct_exists(argument0, "ListItems") + || !variable_struct_exists(argument0, "ListRarity") + || !variable_struct_exists(argument0, "ListDurability")) + { + scr_msl_log("no ItemsTable data"); + return 0; + } + + var items = variable_struct_get(argument0, "ListItems"); + var rarity = variable_struct_get(argument0, "ListRarity"); + var durability = variable_struct_get(argument0, "ListDurability"); + + var size_array = array_length(items); + + if (size_array != array_length(rarity) || + size_array != array_length(durability)) + { + scr_msl_log("List with incorrect size"); + return 0; + } + + for(var _i = 0; _i < size_array; _i++) + { + scr_msl_resolve_items(items[_i], rarity[_i], durability[_i], argument1, argument2); + } + + return 1; +} \ No newline at end of file diff --git a/Resources/Codes/LootModule/scr_msl_resolve_items.gml b/Resources/Codes/LootModule/scr_msl_resolve_items.gml new file mode 100644 index 0000000..793835b --- /dev/null +++ b/Resources/Codes/LootModule/scr_msl_resolve_items.gml @@ -0,0 +1,49 @@ +function scr_msl_resolve_items(argument0, argument1, argument2, argument3, argument4) +{ + if (argument1 == -1) + { + var objectName = argument0; + var obj = ""; + if (argument3 == 0) + { + obj = asset_get_index("o_inv_" + objectName) + if (obj > -1) + { + scr_inventory_add_item(obj); + } + else + { + scr_msl_log("invalid object " + string(objectName)); + } + } + else + { + obj = asset_get_index("o_loot_" + objectName) + if (obj > -1) + { + scr_loot_drop(argument4.x, argument4.y, obj) + } + else + { + scr_msl_log("invalid object " + string(objectName)); + } + } + } + else + { + if (argument3 == 0) + { + with (scr_inventory_add_weapon(argument0, argument1)) + { + scr_inv_atr_set("Duration", argument2); + } + } + else + { + with (scr_weapon_loot(argument0, argument4.x, argument4.y, 100, argument1)) + { + scr_inv_atr_set("Duration", argument2) + } + } + } +} \ No newline at end of file diff --git a/Resources/Codes/LootModule/scr_msl_resolve_loot_table.gml b/Resources/Codes/LootModule/scr_msl_resolve_loot_table.gml new file mode 100644 index 0000000..37ecfb1 --- /dev/null +++ b/Resources/Codes/LootModule/scr_msl_resolve_loot_table.gml @@ -0,0 +1,68 @@ +function scr_msl_resolve_loot_table(argument0, argument1) +{ + var objectName = object_get_name(argument0.object_index); + scr_msl_log("instance: " + string(argument0.id) + " of " + objectName); + + var referenceLootTable = scr_msl_resolve_refence_table(argument0); + if (referenceLootTable == noone) + { + scr_msl_log("Reference Table resolution failed"); + return 0; + } + + var file = file_text_open_read("loot_table.json"); + var json = file_text_read_string(file); + var data = json_parse(json); + + if (!variable_struct_exists(data, referenceLootTable)) + { + scr_msl_log("cant find ref " + referenceLootTable); + file_text_close(file); + return 0; + } + var lootStruct = variable_struct_get(data, referenceLootTable); + + if (!variable_struct_exists(lootStruct, "GuaranteedItems")) + { + scr_msl_log("no guaranteedItems"); + file_text_close("loot_table.json"); + return 0; + } + var guaranteedItems = variable_struct_get(lootStruct, "GuaranteedItems"); + + if (!scr_msl_resolve_guaranteed_items(guaranteedItems, argument1, argument0)) + { + scr_msl_log("Guaranteed Items resolution failed"); + file_text_close("loot_table.json"); + return 0; + } + + if (!variable_struct_exists(lootStruct, "RandomLootMin") || !variable_struct_exists(lootStruct, "RandomLootMax") || !variable_struct_exists(lootStruct, "EmptyWeight")) + { + scr_msl_log("no int"); + file_text_close("loot_table.json"); + return 0; + } + + var randomLootMin = variable_struct_get(lootStruct, "RandomLootMin"); + var randomLootMax = variable_struct_get(lootStruct, "RandomLootMax"); + var emptyWeight = variable_struct_get(lootStruct, "EmptyWeight"); + + var iteration = randomLootMin + irandom(randomLootMax - randomLootMin); + scr_msl_log("iteration " + string(iteration)); + + if (!variable_struct_exists(lootStruct, "RandomItemsTable")) + { + scr_msl_log("no RandomItemsTable"); + file_text_close("loot_table.json"); + return 0; + } + + var randomItemsTable = variable_struct_get(lootStruct, "RandomItemsTable"); + + scr_msl_resolve_random_items(randomItemsTable, argument1, argument0, iteration, emptyWeight); + + file_text_close(file); + + return 1; +} \ No newline at end of file diff --git a/Resources/Codes/LootModule/scr_msl_resolve_random_items.gml b/Resources/Codes/LootModule/scr_msl_resolve_random_items.gml new file mode 100644 index 0000000..a36d006 --- /dev/null +++ b/Resources/Codes/LootModule/scr_msl_resolve_random_items.gml @@ -0,0 +1,75 @@ +function scr_msl_resolve_random_items(argument0, argument1, argument2, argument3, argument4) +{ + if (!variable_struct_exists(argument0, "ItemsTable") + || !variable_struct_exists(argument0, "ListWeight")) + { + scr_msl_log("no randomLoot data"); + return 0; + } + + var itemsTable = variable_struct_get(argument0, "ItemsTable"); + var weight = variable_struct_get(argument0, "ListWeight"); + + if (!variable_struct_exists(itemsTable, "ListItems") + || !variable_struct_exists(itemsTable, "ListRarity") + || !variable_struct_exists(itemsTable, "ListDurability")) + { + scr_msl_log("no randomLoot data"); + return 0; + } + + var items = variable_struct_get(itemsTable, "ListItems"); + var rarity = variable_struct_get(itemsTable, "ListRarity"); + var durability = variable_struct_get(itemsTable, "ListDurability"); + + var sizeItems = array_length(items); + var tableItemsSpecialLootAlready = array_create(sizeItems, 0); + + for (var _j = 0; _j < argument3; _j++) + { + var totalWeight = argument4; + for (var _i = 0; _i < sizeItems; _i++) + { + if (ds_list_find_index(scr_atr("specialItemsPool"), items[_i]) != -1) + { + tableItemsSpecialLootAlready[_i] = 1; + } + else + { + totalWeight += weight[_i]; + } + } + scr_msl_log("totalWeight " + string(totalWeight)); + + var randomWeight = irandom(totalWeight - 1); + scr_msl_log("randomWeight " + string(randomWeight)); + var cumulativeWeight = 0; + var index = -1; + + for (var _i = 0; _i < sizeItems; _i++) + { + if (tableItemsSpecialLootAlready[_i] == 1) + { + continue; + } + cumulativeWeight += weight[_i] + if (randomWeight < cumulativeWeight) + { + index = _i; + break; + } + } + + if (index != -1) + { + scr_msl_log("found " + string(index)); + scr_msl_resolve_items(items[index], rarity[index], durability[index], argument1, argument2); + } + else + { + scr_msl_log("found empty"); + } + } + + return 1; +} \ No newline at end of file diff --git a/Resources/Codes/LootModule/scr_msl_resolve_refence_table.gml b/Resources/Codes/LootModule/scr_msl_resolve_refence_table.gml new file mode 100644 index 0000000..34eb633 --- /dev/null +++ b/Resources/Codes/LootModule/scr_msl_resolve_refence_table.gml @@ -0,0 +1,86 @@ +function scr_msl_resolve_refence_table(argument0) +{ + var objectName = object_get_name(argument0.object_index); + var refFile = file_text_open_read("reference_table.json"); + var refJson = file_text_read_string(refFile); + var refData = json_parse(refJson); + + var min_lvl = scr_globaltile_dungeon_get("mob_lvl_min"); + var max_lvl = scr_globaltile_dungeon_get("mob_lvl_max"); + var tier = floor(((max_lvl + min_lvl) / 2)); + scr_msl_log("current tier: " + string(tier)); + + if (!variable_struct_exists(refData, objectName)) + { + scr_msl_log("cant find object " + objectName); + file_text_close(refFile); + return -4; + } + var refStruct = variable_struct_get(refData, objectName); + var referenceLootTableIndex = -1; + + if (!variable_struct_exists(refStruct, "DefaultTable")) + { + scr_msl_log("cant find DefaultTable"); + file_text_close(refFile); + return -4; + } + var defaultTable = variable_struct_get(refStruct, "DefaultTable"); + + if (!variable_struct_exists(refStruct, "Ids")) + { + scr_msl_log("cant find Ids"); + file_text_close(refFile); + return -4; + } + var idsStruct = variable_struct_get(refStruct, "Ids"); + + var _ids = variable_struct_get_names(idsStruct); + for (var i = 0; i < array_length(_ids); i++;) + { + if (real(_ids[i]) == argument0.id) + { + var referenceLootTable = variable_struct_get(idsStruct, _ids[i]); + scr_msl_log("ref with id: " + referenceLootTable); + file_text_close(refFile); + return referenceLootTable; + } + } + + if (!variable_struct_exists(refStruct, "Tiers")) + { + scr_msl_log("cant find Tiers"); + file_text_close(refFile); + return -4; + } + var tiersStruct = variable_struct_get(refStruct, "Tiers"); + var tiers = variable_struct_get_names(tiersStruct); + var indexTier = -1; + + for (var i = 0; i < array_length(tiers); i++;) + { + if (tier < real(tiers[i])) + { + indexTier = i - 1; + break; + } + else + { + indexTier = i; + } + } + + if (indexTier == -1) + { + var referenceLootTable = defaultTable; + scr_msl_log("ref with default: " + referenceLootTable); + } + else + { + var referenceLootTable = variable_struct_get(tiersStruct, tiers[indexTier]); + scr_msl_log("ref with tier: " + referenceLootTable); + } + + file_text_close(refFile); + return referenceLootTable; +} \ No newline at end of file From 863a8186aaf438bd786a3996fb2e23f300ebc980 Mon Sep 17 00:00:00 2001 From: remyCases Date: Sun, 7 Sep 2025 02:48:20 +0200 Subject: [PATCH 7/9] [Minor] fixes mods that couldnt be enabled --- Controls/GeneralPage.xaml | 2 +- Controls/ModBar.xaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Controls/GeneralPage.xaml b/Controls/GeneralPage.xaml index 2223692..a5a220c 100644 --- a/Controls/GeneralPage.xaml +++ b/Controls/GeneralPage.xaml @@ -292,7 +292,7 @@