Skip to content

Commit 5bb85ba

Browse files
committed
Fix Glow Controllers once and for all
1 parent b78dc90 commit 5bb85ba

File tree

1 file changed

+78
-34
lines changed

1 file changed

+78
-34
lines changed

src/Entities/Misc/GlowController.cs

Lines changed: 78 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
using Celeste.Mod.Helpers;
12
using Mono.Cecil.Cil;
23
using MonoMod.Cil;
34
using System.Collections;
5+
using System.Collections.Generic;
46
using System.Linq;
57
using System.Reflection;
68

@@ -9,14 +11,18 @@ namespace Celeste.Mod.CommunalHelper.Entities;
911
[CustomEntity("CommunalHelper/GlowController")]
1012
public class GlowController : Entity
1113
{
14+
#region Hooks
15+
1216
public static void Load()
1317
{
1418
IL.Celeste.LightingRenderer.BeforeRender += IL_LightingRenderer_BeforeRender;
19+
IL.Monocle.EntityList.UpdateLists += IL_EntityList_UpdateLists;
1520
}
1621

1722
public static void Unload()
1823
{
1924
IL.Celeste.LightingRenderer.BeforeRender -= IL_LightingRenderer_BeforeRender;
25+
IL.Monocle.EntityList.UpdateLists -= IL_EntityList_UpdateLists;
2026
}
2127

2228
private static void IL_LightingRenderer_BeforeRender(ILContext il)
@@ -39,6 +45,49 @@ private static void IL_LightingRenderer_BeforeRender(ILContext il)
3945
}
4046
});
4147
}
48+
49+
private static void IL_EntityList_UpdateLists(ILContext il)
50+
{
51+
ILCursor cursor = new(il);
52+
53+
if (!cursor.TryGotoNextBestFit(MoveType.Before,
54+
instr => instr.MatchLdarg(0),
55+
instr => instr.MatchLdfld<EntityList>("toAwake"),
56+
instr => instr.MatchCallvirt<List<Entity>>("GetEnumerator"),
57+
instr => instr.MatchStloc(4)))
58+
return;
59+
60+
VariableDefinition allGlowControllers = new(il.Import(typeof(GlowController[])));
61+
il.Body.Variables.Add(allGlowControllers);
62+
63+
cursor.Emit(OpCodes.Ldarg_0);
64+
cursor.EmitDelegate<Func<EntityList, GlowController[]>>(entityList =>
65+
{
66+
// not sure whether the tracker will work here so doing this just in case
67+
IEnumerable<Entity> allEntities = entityList.Concat(entityList.ToAdd);
68+
return allEntities.Where(entity => entity is GlowController)
69+
.Cast<GlowController>()
70+
.ToArray();
71+
});
72+
cursor.Emit(OpCodes.Stloc, allGlowControllers);
73+
74+
if (!cursor.TryGotoNextBestFit(MoveType.After,
75+
instr => instr.MatchLdloc(5),
76+
instr => instr.MatchLdarg(0),
77+
instr => instr.MatchCallvirt<EntityList>("get_Scene"),
78+
instr => instr.MatchCallvirt<Entity>("Awake")))
79+
return;
80+
81+
cursor.Emit(OpCodes.Ldloc, 5);
82+
cursor.Emit(OpCodes.Ldloc, allGlowControllers);
83+
cursor.EmitDelegate<Action<Entity, GlowController[]>>((entity, glowControllers) =>
84+
{
85+
foreach (GlowController controller in glowControllers)
86+
controller.Process(entity);
87+
});
88+
}
89+
90+
#endregion
4291

4392
private readonly string[] lightWhitelist;
4493
private readonly string[] lightBlacklist;
@@ -79,44 +128,39 @@ public GlowController(EntityData data, Vector2 offset)
79128
respawnAnimationIds = data.Attr("respawnAnimationIds", "respawn").Split(',');
80129
}
81130

82-
public override void Awake(Scene scene)
131+
private void Process(Entity entity)
83132
{
84-
base.Awake(scene);
85-
var allEntities = scene.Entities.Concat(scene.Entities.ToAdd);
86-
foreach (var entity in allEntities)
87-
{
88-
var type = entity.GetType();
89-
var typeName = type.FullName;
90-
var requiresRemovalRoutine = false;
133+
var type = entity.GetType();
134+
var typeName = type.FullName;
135+
var requiresRemovalRoutine = false;
91136

92-
if (lightBlacklist.Contains(typeName))
93-
{
94-
entity.Remove(entity.Components.GetAll<VertexLight>().ToArray<Component>());
95-
}
96-
if (lightWhitelist.Contains(typeName))
97-
{
98-
entity.Add(new VertexLight(lightOffset, lightColor, lightAlpha, lightStartFade, lightEndFade));
99-
requiresRemovalRoutine = true;
100-
}
137+
if (lightBlacklist.Contains(typeName))
138+
{
139+
entity.Remove(entity.Components.GetAll<VertexLight>().ToArray<Component>());
140+
}
141+
if (lightWhitelist.Contains(typeName))
142+
{
143+
entity.Add(new VertexLight(lightOffset, lightColor, lightAlpha, lightStartFade, lightEndFade));
144+
requiresRemovalRoutine = true;
145+
}
101146

102-
if (bloomBlacklist.Contains(typeName))
103-
{
104-
entity.Remove(entity.Components.GetAll<BloomPoint>().ToArray<Component>());
105-
entity.Remove(entity.Components.GetAll<CustomBloom>().ToArray<Component>());
106-
}
107-
if (bloomWhitelist.Contains(typeName))
108-
{
109-
entity.Add(new BloomPoint(bloomOffset, bloomAlpha, bloomRadius));
110-
requiresRemovalRoutine = true;
111-
}
147+
if (bloomBlacklist.Contains(typeName))
148+
{
149+
entity.Remove(entity.Components.GetAll<BloomPoint>().ToArray<Component>());
150+
entity.Remove(entity.Components.GetAll<CustomBloom>().ToArray<Component>());
151+
}
152+
if (bloomWhitelist.Contains(typeName))
153+
{
154+
entity.Add(new BloomPoint(bloomOffset, bloomAlpha, bloomRadius));
155+
requiresRemovalRoutine = true;
156+
}
112157

113-
// some entities get a special coroutine that hides lights and blooms
114-
// if it's a glider or otherwise has a sprite with an animation id contained in `deathAnimationIds`
115-
if (requiresRemovalRoutine &&
116-
entity.Components.GetAll<Sprite>().FirstOrDefault(s => deathAnimationIds.Any(s.Has)) is { } sprite)
117-
{
118-
entity.Add(new Coroutine(DeathRemovalRoutine(entity, sprite)));
119-
}
158+
// some entities get a special coroutine that hides lights and blooms
159+
// if it's a glider or otherwise has a sprite with an animation id contained in `deathAnimationIds`
160+
if (requiresRemovalRoutine &&
161+
entity.Components.GetAll<Sprite>().FirstOrDefault(s => deathAnimationIds.Any(s.Has)) is { } sprite)
162+
{
163+
entity.Add(new Coroutine(DeathRemovalRoutine(entity, sprite)));
120164
}
121165
}
122166

0 commit comments

Comments
 (0)