From fbd08d83095ac7a0abde68eb0ac437ccfa02b27c Mon Sep 17 00:00:00 2001 From: DemoJameson Date: Thu, 3 Aug 2023 15:54:36 +0800 Subject: [PATCH] Make Add(entity) and Remove(entity) methods to crash when entity is null, so modders can catch bug in time --- Celeste.Mod.mm/Patches/Monocle/EntityList.cs | 35 ++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/Celeste.Mod.mm/Patches/Monocle/EntityList.cs b/Celeste.Mod.mm/Patches/Monocle/EntityList.cs index 8e6bab233..d9afad552 100644 --- a/Celeste.Mod.mm/Patches/Monocle/EntityList.cs +++ b/Celeste.Mod.mm/Patches/Monocle/EntityList.cs @@ -33,7 +33,16 @@ internal void ClearEntities() { [MonoModIgnore] [PatchEntityListUpdateLists] internal extern void UpdateLists(); + + [MonoModIgnore] + [PatchEntityListAddAndRemove] + internal extern void Add(Entity entity); + + [MonoModIgnore] + [PatchEntityListAddAndRemove] + internal extern void Remove(Entity entity); } + public static class EntityListExt { // Mods can't access patch_ classes directly. @@ -61,6 +70,13 @@ class PatchEntityListUpdateAttribute : Attribute { } [MonoModCustomMethodAttribute(nameof(MonoModRules.PatchEntityListUpdateLists))] class PatchEntityListUpdateListsAttribute : Attribute { } + /// + /// Make Add(entity) and Remove(entity) methods to crash when entity is null + /// so modders can catch bugs in time + /// + [MonoModCustomMethodAttribute(nameof(MonoModRules.PatchEntityListAddAndRemove))] + class PatchEntityListAddAndRemoveAttribute : Attribute { } + static partial class MonoModRules { public static void PatchEntityListUpdate(ILContext context, CustomAttribute attrib) { @@ -115,5 +131,24 @@ public static void PatchEntityListUpdateLists(ILContext context, CustomAttribute cursor.Next.Operand = hashRemoveOperand; } + public static void PatchEntityListAddAndRemove(ILContext context, CustomAttribute attrib) { + // insert the following code at the beginning of the method + // if (entity == null) throw new ArgumentNullException("entity") + + TypeDefinition t_ArgumentNullException = MonoModRule.Modder.FindType("System.ArgumentNullException").Resolve(); + MethodReference ctor_ArgumentNullException = MonoModRule.Modder.Module.ImportReference(t_ArgumentNullException.FindMethod("System.Void .ctor(System.String)")); + + ILCursor cursor = new ILCursor(context); + ILLabel label = cursor.DefineLabel(); + cursor.Emit(OpCodes.Ldarg_1); + cursor.Emit(OpCodes.Ldnull); + cursor.Emit(OpCodes.Ceq); + cursor.Emit(OpCodes.Brfalse_S, label); + cursor.Emit(OpCodes.Ldstr, "entity"); + cursor.Emit(OpCodes.Newobj, ctor_ArgumentNullException); + cursor.Emit(OpCodes.Throw); + cursor.MarkLabel(label); + } + } }