diff --git a/BenchmarkTest/BenchmarkTest.csproj b/BenchmarkTest/BenchmarkTest.csproj
new file mode 100644
index 0000000..f569f93
--- /dev/null
+++ b/BenchmarkTest/BenchmarkTest.csproj
@@ -0,0 +1,18 @@
+
+
+
+ Exe
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
diff --git a/BenchmarkTest/DecompileBenchmark.cs b/BenchmarkTest/DecompileBenchmark.cs
new file mode 100644
index 0000000..e83979f
--- /dev/null
+++ b/BenchmarkTest/DecompileBenchmark.cs
@@ -0,0 +1,41 @@
+using BenchmarkDotNet.Attributes;
+using UndertaleModLib;
+using UndertaleModLib.Decompiler;
+using UndertaleModLib.Models;
+
+namespace BenchmarkTest;
+
+[MemoryDiagnoser]
+public class DecompileBenchmark
+{
+ public UndertaleData data;
+ public GlobalDecompileContext decompileContext;
+
+ [GlobalSetup]
+ public void GlobalSetup()
+ {
+ using (FileStream fs = new FileInfo(@"/home/narr/Dokumente/am2r 1.5.5/assets/game.unx_older").OpenRead())
+ {
+ data = UndertaleIO.Read(fs);
+ }
+ decompileContext = new GlobalDecompileContext(data, false);
+ }
+
+ [Benchmark]
+ public void AppendVariableToEveryEntry()
+ {
+ void AppendGML(UndertaleCode code, string appendedText)
+ {
+ var codeText = Decompiler.Decompile(code, decompileContext);
+ codeText = codeText + appendedText + "\n";
+ code.ReplaceGML(codeText, data);
+ }
+
+ foreach (UndertaleCode codeentry in data.Code.SkipLast((int)(data.Code.Count * 0.99)))
+ {
+ if (codeentry.Name.Content == "gml_Object_oRm_a5c11lock_Collision_267") continue;
+
+ AppendGML(codeentry, "var this_variable_is_not_used_and_thus_completely_uselesss = 1; if (!this_variable_is_not_used_and_thus_completely_uselesss) this_variable_is_not_used_and_thus_completely_uselesss = 1");
+ }
+ }
+}
diff --git a/BenchmarkTest/Program.cs b/BenchmarkTest/Program.cs
new file mode 100644
index 0000000..334df3d
--- /dev/null
+++ b/BenchmarkTest/Program.cs
@@ -0,0 +1,7 @@
+// See https://aka.ms/new-console-template for more information
+
+using BenchmarkDotNet.Running;
+using BenchmarkTest;
+
+Console.WriteLine("Hello, World!");
+BenchmarkRunner.Run();
diff --git a/YAMS-LIB/ExtensionMethods.cs b/YAMS-LIB/ExtensionMethods.cs
index d2a07aa..f952f64 100644
--- a/YAMS-LIB/ExtensionMethods.cs
+++ b/YAMS-LIB/ExtensionMethods.cs
@@ -25,7 +25,18 @@ public static string GetGMLCode(this UndertaleCode code)
public static void ReplaceGMLInCode(this UndertaleCode code, string textToReplace, string replacementText, bool ignoreErrors = false)
{
- var codeText = Decompiler.Decompile(code, decompileContext);
+ string codeText;
+
+ if (Patcher.CodeCache.TryGetValue(code, out string? value))
+ {
+ codeText = value;
+ }
+ else
+ {
+ codeText = Decompiler.Decompile(code, decompileContext);
+ Patcher.CodeCache.Add(code, codeText);
+ }
+
if (!codeText.Contains(textToReplace))
{
if (ignoreErrors)
@@ -34,26 +45,52 @@ public static void ReplaceGMLInCode(this UndertaleCode code, string textToReplac
throw new ApplicationException($"The text \"{textToReplace}\" was not found in \"{code.Name.Content}\"!");
}
codeText = codeText.Replace(textToReplace, replacementText);
- code.ReplaceGML(codeText, gmData);
+ Patcher.CodeCache[code] = codeText;
}
public static void PrependGMLInCode(this UndertaleCode code, string prependedText)
{
- var codeText = Decompiler.Decompile(code, decompileContext);
+ string codeText;
+ if (Patcher.CodeCache.TryGetValue(code, out string? value))
+ {
+ codeText = value;
+ }
+ else
+ {
+ codeText = Decompiler.Decompile(code, decompileContext);
+ Patcher.CodeCache.Add(code, codeText);
+ }
codeText = prependedText + "\n" + codeText;
- code.ReplaceGML(codeText, gmData);
+ Patcher.CodeCache[code] = codeText;
}
public static void AppendGMLInCode(this UndertaleCode code, string appendedText)
{
- var codeText = Decompiler.Decompile(code, decompileContext);
+ string codeText;
+ if (Patcher.CodeCache.TryGetValue(code, out string? value))
+ {
+ codeText = value;
+ }
+ else
+ {
+ codeText = Decompiler.Decompile(code, decompileContext);
+ Patcher.CodeCache.Add(code, codeText);
+ }
codeText = codeText + appendedText + "\n";
- code.ReplaceGML(codeText, gmData);
+ Patcher.CodeCache[code] = codeText;
}
public static void SubstituteGMLCode(this UndertaleCode code, string newGMLCode)
{
- code.ReplaceGML(newGMLCode, gmData);
+ Patcher.CodeCache[code] = newGMLCode;
+ }
+
+ public static void FlushCode()
+ {
+ foreach ((var codeName, var codeText) in Patcher.CodeCache)
+ {
+ codeName.ReplaceGML(codeText, gmData);
+ }
}
public static UndertaleRoom.Tile CreateRoomTile(int x, int y, int depth, UndertaleBackground tileset, uint sourceX, uint sourceY, uint width = 16, uint height = 16, uint? id = null)
diff --git a/YAMS-LIB/Program.cs b/YAMS-LIB/Program.cs
index ded077f..668ce3e 100644
--- a/YAMS-LIB/Program.cs
+++ b/YAMS-LIB/Program.cs
@@ -21,6 +21,8 @@ public class Patcher
internal static GlobalDecompileContext? decompileContext;
internal static bool isHorde = false;
+ internal static Dictionary CodeCache = new Dictionary(1024);
+
private static string CreateVersionString()
{
Assembly assembly = Assembly.GetExecutingAssembly();
@@ -49,13 +51,17 @@ public static void Main(string am2rPath, string outputAm2rPath, string jsonPath)
SeedObject? seedObject = JsonSerializer.Deserialize(File.ReadAllText(jsonPath));
- // Read 1.5.x data
- gmData = new UndertaleData();
+ Stopwatch sw = new Stopwatch();
+ sw.Start();
+ // Read 1.5.x data
using (FileStream fs = new FileInfo(am2rPath).OpenRead())
{
gmData = UndertaleIO.Read(fs);
}
+ sw.Stop();
+ var afterRead = sw.Elapsed;
+ sw.Start();
Console.WriteLine("Read data file.");
decompileContext = new GlobalDecompileContext(gmData, false);
@@ -628,10 +634,18 @@ public static void Main(string am2rPath, string outputAm2rPath, string jsonPath)
Multiworld.Apply(gmData, decompileContext, seedObject);
AddBossMWTracking.Apply(gmData, decompileContext, seedObject);
+
// Write back to disk
+ ExtensionMethods.FlushCode();
+ sw.Stop();
+ var beforeWrite = sw.Elapsed;
+ sw.Start();
using (FileStream fs = new FileInfo(outputAm2rPath).OpenWrite())
{
UndertaleIO.Write(fs, gmData, Console.WriteLine);
}
+ sw.Stop();
+ Console.WriteLine($"Total Time: {sw.Elapsed}");
+ Console.WriteLine($"Patching Time Only: {beforeWrite-afterRead}");
}
}
diff --git a/YAMS-LIB/patches/DecoupleItemsFromLocations.cs b/YAMS-LIB/patches/DecoupleItemsFromLocations.cs
index 4b8d386..6d06780 100644
--- a/YAMS-LIB/patches/DecoupleItemsFromLocations.cs
+++ b/YAMS-LIB/patches/DecoupleItemsFromLocations.cs
@@ -38,31 +38,31 @@ public static void Apply(UndertaleData gmData, GlobalDecompileContext decompileC
gmData.Code.ByName(code).ReplaceGMLInCode("global.item[0]", "global.hasBombs");
}
- UndertaleGameObject? elderSeptogg = gmData.GameObjects.ByName("oElderSeptogg");
+ const string elderSeptoggName = "oElderSeptogg";
foreach (var gameObject in new[]
{
- gmData.Rooms.ByName("rm_a0h11").GameObjects.First(go => go.X == 480 && go.Y == 768 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content),
- gmData.Rooms.ByName("rm_a0h25").GameObjects.First(go => go.X == 120 && go.Y == 816 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content),
- gmData.Rooms.ByName("rm_a0h25").GameObjects.First(go => go.X == 168 && go.Y == 256 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content),
- gmData.Rooms.ByName("rm_a0h29").GameObjects.First(go => go.X == 384 && go.Y == 312 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content),
- gmData.Rooms.ByName("rm_a1h05").GameObjects.First(go => go.X == 1184 && go.Y == 832 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content),
- gmData.Rooms.ByName("rm_a3h04").GameObjects.First(go => go.X == 528 && go.Y == 1344 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content),
- gmData.Rooms.ByName("rm_a3h04").GameObjects.First(go => go.X == 1728 && go.Y == 1248 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content),
- gmData.Rooms.ByName("rm_a3a07").GameObjects.First(go => go.X == 112 && go.Y == 240 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content),
- gmData.Rooms.ByName("rm_a3b02").GameObjects.First(go => go.X == 192 && go.Y == 896 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content),
- gmData.Rooms.ByName("rm_a3b08").GameObjects.First(go => go.X == 224 && go.Y == 352 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content),
- gmData.Rooms.ByName("rm_a0h17").GameObjects.First(go => go.X == 96 && go.Y == 352 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content),
- gmData.Rooms.ByName("rm_a4b02a").GameObjects.First(go => go.X == 120 && go.Y == 816 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content),
- gmData.Rooms.ByName("rm_a4b10").GameObjects.First(go => go.X == 144 && go.Y == 624 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content),
- gmData.Rooms.ByName("rm_a4b10").GameObjects.First(go => go.X == 512 && go.Y == 256 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content),
- gmData.Rooms.ByName("rm_a4b11").GameObjects.First(go => go.X == 224 && go.Y == 2288 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content),
- gmData.Rooms.ByName("rm_a5c13").GameObjects.First(go => go.X == 96 && go.Y == 704 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content),
- gmData.Rooms.ByName("rm_a5c14").GameObjects.First(go => go.X == 1056 && go.Y == 288 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content),
- gmData.Rooms.ByName("rm_a5c17").GameObjects.First(go => go.X == 192 && go.Y == 288 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content),
- gmData.Rooms.ByName("rm_a5c18").GameObjects.First(go => go.X == 128 && go.Y == 192 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content),
- gmData.Rooms.ByName("rm_a5c18").GameObjects.First(go => go.X == 480 && go.Y == 192 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content),
- gmData.Rooms.ByName("rm_a5c21").GameObjects.First(go => go.X == 160 && go.Y == 384 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content),
- gmData.Rooms.ByName("rm_a5c21").GameObjects.First(go => go.X == 96 && go.Y == 560 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content),
+ gmData.Rooms.ByName("rm_a0h11").GameObjects.First(go => go.X == 480 && go.Y == 768 && go.ObjectDefinition.Name.Content == elderSeptoggName),
+ gmData.Rooms.ByName("rm_a0h25").GameObjects.First(go => go.X == 120 && go.Y == 816 && go.ObjectDefinition.Name.Content == elderSeptoggName),
+ gmData.Rooms.ByName("rm_a0h25").GameObjects.First(go => go.X == 168 && go.Y == 256 && go.ObjectDefinition.Name.Content == elderSeptoggName),
+ gmData.Rooms.ByName("rm_a0h29").GameObjects.First(go => go.X == 384 && go.Y == 312 && go.ObjectDefinition.Name.Content == elderSeptoggName),
+ gmData.Rooms.ByName("rm_a1h05").GameObjects.First(go => go.X == 1184 && go.Y == 832 && go.ObjectDefinition.Name.Content == elderSeptoggName),
+ gmData.Rooms.ByName("rm_a3h04").GameObjects.First(go => go.X == 528 && go.Y == 1344 && go.ObjectDefinition.Name.Content == elderSeptoggName),
+ gmData.Rooms.ByName("rm_a3h04").GameObjects.First(go => go.X == 1728 && go.Y == 1248 && go.ObjectDefinition.Name.Content == elderSeptoggName),
+ gmData.Rooms.ByName("rm_a3a07").GameObjects.First(go => go.X == 112 && go.Y == 240 && go.ObjectDefinition.Name.Content == elderSeptoggName),
+ gmData.Rooms.ByName("rm_a3b02").GameObjects.First(go => go.X == 192 && go.Y == 896 && go.ObjectDefinition.Name.Content == elderSeptoggName),
+ gmData.Rooms.ByName("rm_a3b08").GameObjects.First(go => go.X == 224 && go.Y == 352 && go.ObjectDefinition.Name.Content == elderSeptoggName),
+ gmData.Rooms.ByName("rm_a0h17").GameObjects.First(go => go.X == 96 && go.Y == 352 && go.ObjectDefinition.Name.Content == elderSeptoggName),
+ gmData.Rooms.ByName("rm_a4b02a").GameObjects.First(go => go.X == 120 && go.Y == 816 && go.ObjectDefinition.Name.Content == elderSeptoggName),
+ gmData.Rooms.ByName("rm_a4b10").GameObjects.First(go => go.X == 144 && go.Y == 624 && go.ObjectDefinition.Name.Content == elderSeptoggName),
+ gmData.Rooms.ByName("rm_a4b10").GameObjects.First(go => go.X == 512 && go.Y == 256 && go.ObjectDefinition.Name.Content == elderSeptoggName),
+ gmData.Rooms.ByName("rm_a4b11").GameObjects.First(go => go.X == 224 && go.Y == 2288 && go.ObjectDefinition.Name.Content == elderSeptoggName),
+ gmData.Rooms.ByName("rm_a5c13").GameObjects.First(go => go.X == 96 && go.Y == 704 && go.ObjectDefinition.Name.Content == elderSeptoggName),
+ gmData.Rooms.ByName("rm_a5c14").GameObjects.First(go => go.X == 1056 && go.Y == 288 && go.ObjectDefinition.Name.Content == elderSeptoggName),
+ gmData.Rooms.ByName("rm_a5c17").GameObjects.First(go => go.X == 192 && go.Y == 288 && go.ObjectDefinition.Name.Content == elderSeptoggName),
+ gmData.Rooms.ByName("rm_a5c18").GameObjects.First(go => go.X == 128 && go.Y == 192 && go.ObjectDefinition.Name.Content == elderSeptoggName),
+ gmData.Rooms.ByName("rm_a5c18").GameObjects.First(go => go.X == 480 && go.Y == 192 && go.ObjectDefinition.Name.Content == elderSeptoggName),
+ gmData.Rooms.ByName("rm_a5c21").GameObjects.First(go => go.X == 160 && go.Y == 384 && go.ObjectDefinition.Name.Content == elderSeptoggName),
+ gmData.Rooms.ByName("rm_a5c21").GameObjects.First(go => go.X == 96 && go.Y == 560 && go.ObjectDefinition.Name.Content == elderSeptoggName),
})
{
gameObject.CreationCode.ReplaceGMLInCode("global.item[0]", "global.hasBombs");
@@ -77,7 +77,7 @@ public static void Apply(UndertaleData gmData, GlobalDecompileContext decompileC
subscreenMenuStep.ReplaceGMLInCode("global.item[2] == 0", "!global.hasSpiderball");
foreach (UndertaleCode code in gmData.Code.Where(c =>
(c.Name.Content.StartsWith("gml_Script_scr_septoggs_") && c.Name.Content.Contains('2')) ||
- c.Name.Content == gmData.Rooms.ByName("rm_a0h25").GameObjects.First(go => go.X == 120 && go.Y == 816 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content).CreationCode.Name.Content)
+ c.Name.Content == gmData.Rooms.ByName("rm_a0h25").GameObjects.First(go => go.X == 120 && go.Y == 816 && go.ObjectDefinition.Name.Content == elderSeptoggName).CreationCode.Name.Content)
)
{
code.ReplaceGMLInCode("global.item[2]", "global.hasSpiderball");
@@ -95,7 +95,7 @@ public static void Apply(UndertaleData gmData, GlobalDecompileContext decompileC
foreach (UndertaleCode? code in gmData.Code.Where(c =>
(c.Name.Content.StartsWith("gml_Script_scr_septoggs_") && c.Name.Content.Contains('4')) ||
c.Name.Content == "gml_Room_rm_a3b08_Create" ||
- c == gmData.Rooms.ByName("rm_a5c17").GameObjects.First(go => go.X == 192 && go.Y == 288 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content).CreationCode)
+ c == gmData.Rooms.ByName("rm_a5c17").GameObjects.First(go => go.X == 192 && go.Y == 288 && go.ObjectDefinition.Name.Content == elderSeptoggName).CreationCode)
)
{
code.ReplaceGMLInCode("global.item[4]", "global.hasHijump");
@@ -120,7 +120,7 @@ public static void Apply(UndertaleData gmData, GlobalDecompileContext decompileC
foreach (UndertaleCode? code in gmData.Code.Where(c =>
(c.Name.Content.StartsWith("gml_Script_scr_septoggs_") && c.Name.Content.Contains('6')) ||
gmData.Rooms.ByName("rm_a5a03").GameObjects.Where(go => go.X is >= 96 and <= 112 && go.Y is >= 240 and <= 288 && go.ObjectDefinition.Name.Content == "oBlockStep").Select(go => go.CreationCode).Contains(c) ||
- c == gmData.Rooms.ByName("rm_a0h25").GameObjects.First(go => go.X == 120 && go.Y == 816 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content).CreationCode)
+ c == gmData.Rooms.ByName("rm_a0h25").GameObjects.First(go => go.X == 120 && go.Y == 816 && go.ObjectDefinition.Name.Content == elderSeptoggName).CreationCode)
)
{
code.ReplaceGMLInCode("global.item[6]", "global.hasSpacejump");
@@ -210,7 +210,7 @@ public static void Apply(UndertaleData gmData, GlobalDecompileContext decompileC
}
""");
subscreenMenuStep.ReplaceGMLInCode("""
- if (global.curropt == 7 && (!global.hasIbeam))
+ if (global.curropt == 7 && !global.hasIbeam)
global.curropt += 1
""", """
if (global.curropt == 7 && (!global.hasIbeam))
@@ -219,7 +219,7 @@ public static void Apply(UndertaleData gmData, GlobalDecompileContext decompileC
global.curropt += 1
""");
subscreenMenuStep.ReplaceGMLInCode("""
- if (global.curropt == 7 && (!global.hasIbeam))
+ if (global.curropt == 7 && !global.hasIbeam)
global.curropt -= 1
""", """
if (global.curropt == 8 && (!global.hasMorph))
diff --git a/YAMS-LIB/patches/StartingItems.cs b/YAMS-LIB/patches/StartingItems.cs
index 34a8eb6..944274f 100644
--- a/YAMS-LIB/patches/StartingItems.cs
+++ b/YAMS-LIB/patches/StartingItems.cs
@@ -1,3 +1,4 @@
+using System.Text;
using UndertaleModLib;
using UndertaleModLib.Decompiler;
using UndertaleModLib.Models;
@@ -9,12 +10,13 @@ public class StartingItems
public static void Apply(UndertaleData gmData, GlobalDecompileContext decompileContext, SeedObject seedObject)
{
UndertaleCode? characterVarsCode = gmData.Code.ByName("gml_Script_load_character_vars");
+ StringBuilder textToAppend = new StringBuilder();
// Set starting items
bool alreadyAddedMissiles = false;
bool alreadyAddedSupers = false;
bool alreadyAddedPBombs = false;
- characterVarsCode.AppendGMLInCode("global.collectedItems = \"items:\"");
+ textToAppend.AppendLine("global.collectedItems = \"items:\";");
int howMuchDna = 0;
foreach ((ItemEnum item, int quantity) in seedObject.StartingItems)
{
@@ -22,8 +24,8 @@ public static void Apply(UndertaleData gmData, GlobalDecompileContext decompileC
switch (item)
{
case ItemEnum.EnergyTank:
- characterVarsCode.AppendGMLInCode($"global.etanks = {quantity};");
- characterVarsCode.AppendGMLInCode($"global.playerhealth = {seedObject.Patches.EnergyPerTank + seedObject.Patches.EnergyPerTank * quantity - 1};");
+ textToAppend.AppendLine($"global.etanks = {quantity};");
+ textToAppend.AppendLine($"global.playerhealth = {seedObject.Patches.EnergyPerTank + seedObject.Patches.EnergyPerTank * quantity - 1};");
break;
case ItemEnum.LockedMissile:
case ItemEnum.Missile:
@@ -36,7 +38,7 @@ public static void Apply(UndertaleData gmData, GlobalDecompileContext decompileC
if (item == ItemEnum.LockedMissile && seedObject.StartingItems.TryGetValue(ItemEnum.Missile, out int missileQuantity)) finalQuantity += missileQuantity;
- characterVarsCode.AppendGMLInCode($"global.missiles = {finalQuantity};");
+ textToAppend.AppendLine($"global.missiles = {finalQuantity};");
alreadyAddedMissiles = true;
break;
case ItemEnum.LockedSuperMissile:
@@ -50,7 +52,7 @@ public static void Apply(UndertaleData gmData, GlobalDecompileContext decompileC
if (item == ItemEnum.LockedSuperMissile && seedObject.StartingItems.TryGetValue(ItemEnum.SuperMissile, out int superQuantity)) finalQuantity += superQuantity;
- characterVarsCode.AppendGMLInCode($"global.smissiles = {finalQuantity};");
+ textToAppend.AppendLine($"global.smissiles = {finalQuantity};");
alreadyAddedSupers = true;
break;
@@ -62,7 +64,7 @@ public static void Apply(UndertaleData gmData, GlobalDecompileContext decompileC
if (item == ItemEnum.LockedPBomb && seedObject.StartingItems.TryGetValue(ItemEnum.PBomb, out int pBombQuantity)) finalQuantity += pBombQuantity;
- characterVarsCode.AppendGMLInCode($"global.pbombs = {finalQuantity};");
+ textToAppend.AppendLine($"global.pbombs = {finalQuantity};");
alreadyAddedPBombs = true;
break;
case ItemEnum.MissileLauncher:
@@ -77,114 +79,114 @@ public static void Apply(UndertaleData gmData, GlobalDecompileContext decompileC
break;
case ItemEnum.Bombs:
- characterVarsCode.AppendGMLInCode($"global.hasBombs = {quantity};");
+ textToAppend.AppendLine($"global.hasBombs = {quantity};");
break;
case ItemEnum.Powergrip:
- characterVarsCode.AppendGMLInCode($"global.hasPowergrip = {quantity};");
+ textToAppend.AppendLine($"global.hasPowergrip = {quantity};");
break;
case ItemEnum.Spiderball:
- characterVarsCode.AppendGMLInCode($"global.hasSpiderball = {quantity};");
+ textToAppend.AppendLine($"global.hasSpiderball = {quantity};");
break;
case ItemEnum.Springball:
- characterVarsCode.AppendGMLInCode($"global.hasJumpball = {quantity};");
+ textToAppend.AppendLine($"global.hasJumpball = {quantity};");
break;
case ItemEnum.Hijump:
- characterVarsCode.AppendGMLInCode($"global.hasHijump = {quantity};");
+ textToAppend.AppendLine($"global.hasHijump = {quantity};");
break;
case ItemEnum.Varia:
- characterVarsCode.AppendGMLInCode($"global.hasVaria = {quantity};");
+ textToAppend.AppendLine($"global.hasVaria = {quantity};");
break;
case ItemEnum.Spacejump:
- characterVarsCode.AppendGMLInCode($"global.hasSpacejump = {quantity};");
+ textToAppend.AppendLine($"global.hasSpacejump = {quantity};");
break;
case ItemEnum.ProgressiveJump:
- if (quantity >= 1) characterVarsCode.AppendGMLInCode("global.hasHijump = 1;");
+ if (quantity >= 1) textToAppend.AppendLine("global.hasHijump = 1;");
- if (quantity >= 2) characterVarsCode.AppendGMLInCode("global.hasSpacejump = 1;");
+ if (quantity >= 2) textToAppend.AppendLine("global.hasSpacejump = 1;");
break;
case ItemEnum.Speedbooster:
- characterVarsCode.AppendGMLInCode($"global.hasSpeedbooster = {quantity};");
+ textToAppend.AppendLine($"global.hasSpeedbooster = {quantity};");
break;
case ItemEnum.Screwattack:
- characterVarsCode.AppendGMLInCode($"global.hasScrewattack = {quantity};");
+ textToAppend.AppendLine($"global.hasScrewattack = {quantity};");
break;
case ItemEnum.Gravity:
- characterVarsCode.AppendGMLInCode($"global.hasGravity = {quantity};");
+ textToAppend.AppendLine($"global.hasGravity = {quantity};");
break;
case ItemEnum.ProgressiveSuit:
- if (quantity >= 1) characterVarsCode.AppendGMLInCode("global.hasVaria = 1;");
+ if (quantity >= 1) textToAppend.AppendLine("global.hasVaria = 1;");
- if (quantity >= 2) characterVarsCode.AppendGMLInCode( "global.hasGravity = 1;");
+ if (quantity >= 2) textToAppend.AppendLine( "global.hasGravity = 1;");
break;
case ItemEnum.Power:
// Stubbed for now, may get a purpose in the future
break;
case ItemEnum.Charge:
- characterVarsCode.AppendGMLInCode($"global.hasCbeam = {quantity};");
+ textToAppend.AppendLine($"global.hasCbeam = {quantity};");
break;
case ItemEnum.Ice:
- characterVarsCode.AppendGMLInCode($"global.hasIbeam = {quantity};");
+ textToAppend.AppendLine($"global.hasIbeam = {quantity};");
break;
case ItemEnum.Wave:
- characterVarsCode.AppendGMLInCode($"global.hasWbeam = {quantity};");
+ textToAppend.AppendLine($"global.hasWbeam = {quantity};");
break;
case ItemEnum.Spazer:
- characterVarsCode.AppendGMLInCode($"global.hasSbeam = {quantity};");
+ textToAppend.AppendLine($"global.hasSbeam = {quantity};");
break;
case ItemEnum.Plasma:
- characterVarsCode.AppendGMLInCode($"global.hasPbeam = {quantity};");
+ textToAppend.AppendLine($"global.hasPbeam = {quantity};");
break;
case ItemEnum.Morphball:
- characterVarsCode.AppendGMLInCode($"global.hasMorph = {quantity};");
+ textToAppend.AppendLine($"global.hasMorph = {quantity};");
break;
case ItemEnum.Flashlight:
- characterVarsCode.AppendGMLInCode($"global.flashlightLevel = {quantity};");
+ textToAppend.AppendLine($"global.flashlightLevel = {quantity};");
break;
case ItemEnum.Blindfold:
- characterVarsCode.AppendGMLInCode($"global.flashlightLevel = -{quantity};");
+ textToAppend.AppendLine($"global.flashlightLevel = -{quantity};");
break;
case ItemEnum.SpeedBoosterUpgrade:
- characterVarsCode.AppendGMLInCode($"global.speedBoosterFramesReduction = {quantity}");
+ textToAppend.AppendLine($"global.speedBoosterFramesReduction = {quantity};");
break;
case ItemEnum.WalljumpBoots:
- characterVarsCode.AppendGMLInCode($"global.hasWJ = {quantity}");
+ textToAppend.AppendLine($"global.hasWJ = {quantity};");
break;
case ItemEnum.InfiniteBombPropulsion:
- characterVarsCode.AppendGMLInCode($"global.hasIBJ = {quantity}");
+ textToAppend.AppendLine($"global.hasIBJ = {quantity};");
break;
case ItemEnum.LongBeam:
- characterVarsCode.AppendGMLInCode($"global.hasLongBeam = {quantity}");
+ textToAppend.AppendLine($"global.hasLongBeam = {quantity};");
break;
case ItemEnum.Nothing:
break;
default:
throw new ArgumentOutOfRangeException();
}
- characterVarsCode.AppendGMLInCode($"global.collectedItems += \"{item.GetEnumMemberValue()}|{quantity},\"");
+ textToAppend.AppendLine($"global.collectedItems += \"{item.GetEnumMemberValue()}|{quantity},\";");
}
// After we have gotten our starting items, adjust the DNA counter
- characterVarsCode.PrependGMLInCode($"global.dna = (46 - {seedObject.Patches.RequiredDNAmount}) + {howMuchDna}");
+ characterVarsCode.PrependGMLInCode($"global.dna = (46 - {seedObject.Patches.RequiredDNAmount}) + {howMuchDna};");
// Check whether option has been set for non-main launchers or if starting with them, if yes enable the main launchers in character var
if (!seedObject.Patches.RequireMissileLauncher || seedObject.StartingItems.ContainsKey(ItemEnum.MissileLauncher))
{
- characterVarsCode.AppendGMLInCode("global.missileLauncher = 1");
+ textToAppend.AppendLine("global.missileLauncher = 1;");
}
if (!seedObject.Patches.RequireSuperLauncher || seedObject.StartingItems.ContainsKey(ItemEnum.SuperMissileLauncher))
{
- characterVarsCode.AppendGMLInCode("global.SMissileLauncher = 1");
+ textToAppend.AppendLine("global.SMissileLauncher = 1;");
}
if (!seedObject.Patches.RequirePBLauncher || seedObject.StartingItems.ContainsKey(ItemEnum.PBombLauncher))
{
- characterVarsCode.AppendGMLInCode("global.PBombLauncher = 1");
+ textToAppend.AppendLine("global.PBombLauncher = 1;");
}
// Make all item activation dependent on whether the main item is enabled.
- characterVarsCode.AppendGMLInCode("""
+ textToAppend.AppendLine("""
global.morphball = global.hasMorph;
global.jumpball = global.hasJumpball;
global.powergrip = global.hasPowergrip;
@@ -200,11 +202,13 @@ public static void Apply(UndertaleData gmData, GlobalDecompileContext decompileC
global.sbeam = global.hasSbeam;
global.cbeam = global.hasCbeam;
- global.maxhealth = global.playerhealth
- global.maxmissiles = global.missiles
- global.maxsmissiles = global.smissiles
+ global.maxhealth = global.playerhealth;
+ global.maxmissiles = global.missiles;
+ global.maxsmissiles = global.smissiles;
global.maxpbombs = global.pbombs;
""");
- characterVarsCode.AppendGMLInCode("global.currentsuit = 0; if (global.hasGravity) global.currentsuit = 2; else if (global.hasVaria) global.currentsuit = 1;");
+ textToAppend.AppendLine("global.currentsuit = 0; if (global.hasGravity) global.currentsuit = 2; else if (global.hasVaria) global.currentsuit = 1;");
+
+ characterVarsCode.AppendGMLInCode(textToAppend.ToString());
}
}
diff --git a/YAMS-LIB/patches/misc/DontRespawnBombBlocks.cs b/YAMS-LIB/patches/misc/DontRespawnBombBlocks.cs
index 45ffff1..b01e0ce 100644
--- a/YAMS-LIB/patches/misc/DontRespawnBombBlocks.cs
+++ b/YAMS-LIB/patches/misc/DontRespawnBombBlocks.cs
@@ -19,7 +19,7 @@ public static void Apply(UndertaleData gmData, GlobalDecompileContext decompileC
// The bomb block puzzle in te room before varia don't need to have their special handling from am2random
var rm_a2a06 = gmData.Rooms.ByName("rm_a2a06");
rm_a2a06.GameObjects.First(go => go.X == 608 && go.Y == 112 && go.ObjectDefinition.Name.Content == "oBlockBomb").CreationCode.ReplaceGMLInCode(
- "if (oControl.mod_randomgamebool == 1 && global.hasBombs == 0 && (!global.hasJumpball) && global.hasGravity == 0)",
+ "if (oControl.mod_randomgamebool == 1 && global.hasBombs == 0 && !global.hasJumpball && global.hasGravity == 0)",
"if (false)");
rm_a2a06.GameObjects.First(go => go.X == 624 && go.Y == 48 && go.ObjectDefinition.Name.Content == "oBlockBomb").CreationCode.ReplaceGMLInCode(
"if (oControl.mod_randomgamebool == 1 && global.hasBombs == 0 && global.hasGravity == 0)",
diff --git a/YAMS-LIB/patches/qol/ShowFullyUnexploredMap.cs b/YAMS-LIB/patches/qol/ShowFullyUnexploredMap.cs
index c7f44b5..bfb2160 100644
--- a/YAMS-LIB/patches/qol/ShowFullyUnexploredMap.cs
+++ b/YAMS-LIB/patches/qol/ShowFullyUnexploredMap.cs
@@ -40,12 +40,12 @@ public static void Apply(UndertaleData gmData, GlobalDecompileContext decompileC
// Don't ever draw the debug pipe tiles
gmData.Code.ByName("gml_Script_draw_mapblock").ReplaceGMLInCode($$"""
- if (argument7 == "H"{{(isHorde ? " || argument8 == \"H\"" : "")}})
- draw_sprite(sMapSP, 12, argument0, argument1)
- if (argument7 == "V")
- draw_sprite(sMapSP, 13, argument0, argument1)
- if (argument7 == "C")
- draw_sprite(sMapSP, 14, argument0, argument1)
+ if (argument7 == "H"{{(isHorde ? " || argument8 == \"H\"" : "")}})
+ draw_sprite(sMapSP, 12, argument0, argument1)
+ if (argument7 == "V")
+ draw_sprite(sMapSP, 13, argument0, argument1)
+ if (argument7 == "C")
+ draw_sprite(sMapSP, 14, argument0, argument1)
""", "");
// Also show item pickups and metroids
diff --git a/diff.txt b/diff.txt
new file mode 100644
index 0000000..1a17044
--- /dev/null
+++ b/diff.txt
@@ -0,0 +1,40 @@
+diff --git a/UndertaleModLib/Compiler/Compiler.cs b/UndertaleModLib/Compiler/Compiler.cs
+index 3fa2ae6b..72e3d7c9 100644
+--- a/UndertaleModLib/Compiler/Compiler.cs
++++ b/UndertaleModLib/Compiler/Compiler.cs
+@@ -142,8 +142,11 @@ namespace UndertaleModLib.Compiler
+ for (int i = 0; i < list.Count; i++)
+ {
+ string name = list[i].Name?.Content;
+- if (name != null)
+- assetIds[name] = i;
++ if (name is not null)
++ {
++ assetIds.Add(name, i);
++ }
++ //assetIds[name] = i;
+ }
+ }
+ }
+@@ -154,6 +157,8 @@ namespace UndertaleModLib.Compiler
+ public delegate void MainThreadFunc();
+ public delegate void MainThreadDelegate(MainThreadFunc f);
+
++ private static Dictionary codeToContextMapping = new Dictionary();
++
+ // A simple matching convenience
+ public static bool In(this T obj, params T[] args)
+ {
+@@ -169,7 +174,11 @@ namespace UndertaleModLib.Compiler
+
+ public static CompileContext CompileGMLText(string input, UndertaleData data, UndertaleCode code)
+ {
+- return CompileGMLText(input, new CompileContext(data, code));
++ bool isInMapping = codeToContextMapping.TryGetValue(data, out CompileContext ctx);
++ var returnedContext = CompileGMLText(input, ctx ?? new CompileContext(data, code));
++ if (!isInMapping)
++ codeToContextMapping.Add(data, returnedContext);
++ return returnedContext;
+ }
+
+ public static CompileContext CompileGMLText(string input, CompileContext context, bool redoAssets = false)