Skip to content

Commit 86e9e67

Browse files
Fixed memory leak caused by logging out and back in
1 parent 22f9391 commit 86e9e67

26 files changed

Lines changed: 636 additions & 41 deletions

Chromatics/Core/GameController.cs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ namespace Chromatics.Core
2323

2424
public static class GameController
2525
{
26+
private static LayerProcessorFactory _layerProcessorFactory;
2627
private static MemoryHandler _memoryHandler;
2728
public static event JobChanged jobChanged;
2829
private static CustomComparers.LayerComparer comparer = new();
@@ -45,8 +46,10 @@ public static void Setup()
4546
{
4647
if (gameSetup) return;
4748

49+
_layerProcessorFactory = LayerProcessorFactory.Instance;
4850
comparer = new CustomComparers.LayerComparer();
4951

52+
5053
if (!gameConnected)
5154
{
5255
RGBController.StopEffects();
@@ -155,6 +158,8 @@ private static void StopGameLoop(bool reconnect = false)
155158
_masterCancellationToken.Dispose();
156159
_masterCancellationToken = new CancellationTokenSource();
157160

161+
_layerProcessorFactory.DisposeAll();
162+
158163
if (reconnect)
159164
{
160165
_GameConnectionCancellationTokenSource.Dispose();
@@ -337,6 +342,8 @@ private static void ConnectFFXIVClient()
337342
Debug.WriteLine($"Found {location.Key}. Location: {location.Value.GetAddress().ToInt64():X}");
338343
}
339344
#endif
345+
346+
GC.Collect();
340347
}
341348
}
342349
catch (Exception ex)
@@ -415,6 +422,8 @@ private static void GameProcessLayers()
415422
Debug.WriteLine(@"User on title or character screen");
416423
#endif
417424

425+
_layerProcessorFactory.DisposeAll();
426+
418427
_onTitle = true;
419428
wasPreviewed = false;
420429
}
@@ -436,6 +445,7 @@ private static void GameProcessLayers()
436445
RGBController.StopEffects();
437446
RGBController.ResetLayerGroups();
438447
_onTitle = false;
448+
GC.Collect();
439449
}
440450

441451
}
@@ -466,27 +476,23 @@ private static void GameProcessLayers()
466476
switch (layer.rootLayerType)
467477
{
468478
case LayerType.BaseLayer:
469-
470-
var baseLayerProcessors = BaseLayerProcessorFactory.GetProcessors();
471-
baseLayerProcessors[(BaseLayerType)layer.layerTypeindex].Process(layer);
479+
var baseProcessor = _layerProcessorFactory.GetProcessor((BaseLayerType)layer.layerTypeindex);
480+
baseProcessor.Process(layer);
472481
break;
473482

474483
case LayerType.DynamicLayer:
475-
476-
var dynamicLayerProcessors = DynamicLayerProcessorFactory.GetProcessors();
477-
dynamicLayerProcessors[(DynamicLayerType)layer.layerTypeindex].Process(layer);
484+
var dynamicProcessor = _layerProcessorFactory.GetProcessor((DynamicLayerType)layer.layerTypeindex);
485+
dynamicProcessor.Process(layer);
478486
break;
479487

480488
case LayerType.EffectLayer:
481-
foreach (var layerProcessor in EffectLayerProcessorFactory.GetProcessors())
489+
var effectProcessors = EffectLayerProcessorFactory.GetProcessors();
490+
foreach (var effectProcessor in effectProcessors)
482491
{
483-
layerProcessor.Value.Process(layer);
492+
effectProcessor.Value.Process(layer);
484493
}
485494
break;
486-
487495
}
488-
489-
490496
}
491497
}
492498
catch (Exception ex)

Chromatics/Layers/BaseLayers/BattleStance.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,26 @@ namespace Chromatics.Layers
1212
{
1313
public class BaseBattleStanceProcessor : LayerProcessor
1414
{
15+
private static BaseBattleStanceProcessor _instance;
1516
private bool _disposed = false;
1617
private Dictionary<int, HashSet<Led>> _layergroupledcollections = new Dictionary<int, HashSet<Led>>();
1718

19+
// Private constructor to prevent direct instantiation
20+
private BaseBattleStanceProcessor() { }
21+
22+
// Singleton instance access
23+
public static BaseBattleStanceProcessor Instance
24+
{
25+
get
26+
{
27+
if (_instance == null)
28+
{
29+
_instance = new BaseBattleStanceProcessor();
30+
}
31+
return _instance;
32+
}
33+
}
34+
1835
public override void Process(IMappingLayer layer)
1936
{
2037
if (_disposed) return;
@@ -122,6 +139,7 @@ protected override void Dispose(bool disposing)
122139
}
123140

124141
base.Dispose(disposing);
142+
_instance = null;
125143
}
126144
}
127145
}

Chromatics/Layers/BaseLayers/JobClasses.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,26 @@ namespace Chromatics.Layers
1212
{
1313
public class JobClassesProcessor : LayerProcessor
1414
{
15+
private static JobClassesProcessor _instance;
1516
private bool _disposed = false;
1617
private Dictionary<int, HashSet<Led>> _layergroupledcollections = new Dictionary<int, HashSet<Led>>();
1718

19+
// Private constructor to prevent direct instantiation
20+
private JobClassesProcessor() { }
21+
22+
// Singleton instance access
23+
public static JobClassesProcessor Instance
24+
{
25+
get
26+
{
27+
if (_instance == null)
28+
{
29+
_instance = new JobClassesProcessor();
30+
}
31+
return _instance;
32+
}
33+
}
34+
1835
public override void Process(IMappingLayer layer)
1936
{
2037
if (_disposed) return;
@@ -116,6 +133,7 @@ protected override void Dispose(bool disposing)
116133
}
117134

118135
base.Dispose(disposing);
136+
_instance = null;
119137
}
120138
}
121139
}

Chromatics/Layers/BaseLayers/ReactiveWeather.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ namespace Chromatics.Layers
3232
{
3333
public class ReactiveWeatherProcessor : LayerProcessor
3434
{
35+
private static ReactiveWeatherProcessor _instance;
3536
private static Dictionary<int, ReactiveWeatherBaseModel> layerProcessorModel = new Dictionary<int, ReactiveWeatherBaseModel>();
3637

3738
internal static int _previousArrayIndex = 0;
@@ -43,6 +44,22 @@ public class ReactiveWeatherProcessor : LayerProcessor
4344
private SolidColorBrush weather_brush;
4445
private bool _disposed = false;
4546

47+
// Private constructor to prevent direct instantiation
48+
private ReactiveWeatherProcessor() { }
49+
50+
// Singleton instance access
51+
public static ReactiveWeatherProcessor Instance
52+
{
53+
get
54+
{
55+
if (_instance == null)
56+
{
57+
_instance = new ReactiveWeatherProcessor();
58+
}
59+
return _instance;
60+
}
61+
}
62+
4663
protected override void Dispose(bool disposing)
4764
{
4865
if (!_disposed)
@@ -73,6 +90,7 @@ protected override void Dispose(bool disposing)
7390

7491
// Call base class implementation to clean up base resources
7592
base.Dispose(disposing);
93+
_instance = null;
7694
}
7795

7896
public override void Process(IMappingLayer layer)

Chromatics/Layers/BaseLayers/ScreenCapture.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,26 @@ namespace Chromatics.Layers
3333
{
3434
public class ScreenCaptureProcessor : LayerProcessor
3535
{
36+
private static ScreenCaptureProcessor _instance;
3637
private static Dictionary<int, ScreenCaptureBaseModel> layerProcessorModel = new Dictionary<int, ScreenCaptureBaseModel>();
3738
private static ScreenCaptureExtension screenCapture;
3839

40+
// Private constructor to prevent direct instantiation
41+
private ScreenCaptureProcessor() { }
42+
43+
// Singleton instance access
44+
public static ScreenCaptureProcessor Instance
45+
{
46+
get
47+
{
48+
if (_instance == null)
49+
{
50+
_instance = new ScreenCaptureProcessor();
51+
}
52+
return _instance;
53+
}
54+
}
55+
3956
public override void Process(IMappingLayer layer)
4057
{
4158
if (RGBController.IsBaseLayerEffectRunning()) return;

Chromatics/Layers/BaseLayers/Static.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,26 @@ namespace Chromatics.Layers
1212
{
1313
public class StaticProcessor : LayerProcessor
1414
{
15+
private static StaticProcessor _instance;
1516
private bool _disposed = false;
1617
private Dictionary<int, HashSet<Led>> _layergroupledcollections = new Dictionary<int, HashSet<Led>>();
1718

19+
// Private constructor to prevent direct instantiation
20+
private StaticProcessor() { }
21+
22+
// Singleton instance access
23+
public static StaticProcessor Instance
24+
{
25+
get
26+
{
27+
if (_instance == null)
28+
{
29+
_instance = new StaticProcessor();
30+
}
31+
return _instance;
32+
}
33+
}
34+
1835
public override void Process(IMappingLayer layer)
1936
{
2037
if (_disposed) return;
@@ -101,6 +118,7 @@ protected override void Dispose(bool disposing)
101118
}
102119

103120
base.Dispose(disposing);
121+
_instance = null;
104122
}
105123
}
106124
}

Chromatics/Layers/DynamicLayers/BattleStance.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,25 @@ namespace Chromatics.Layers
1111
{
1212
public class DynamicBattleStanceProcessor : LayerProcessor
1313
{
14+
private static DynamicBattleStanceProcessor _instance;
1415
private bool _disposed = false;
1516

17+
// Private constructor to prevent direct instantiation
18+
private DynamicBattleStanceProcessor() { }
19+
20+
// Singleton instance access
21+
public static DynamicBattleStanceProcessor Instance
22+
{
23+
get
24+
{
25+
if (_instance == null)
26+
{
27+
_instance = new DynamicBattleStanceProcessor();
28+
}
29+
return _instance;
30+
}
31+
}
32+
1633
public override void Process(IMappingLayer layer)
1734
{
1835
if (_disposed)
@@ -107,6 +124,7 @@ protected override void Dispose(bool disposing)
107124
}
108125

109126
base.Dispose(disposing);
127+
_instance = null;
110128
}
111129
}
112130
}

Chromatics/Layers/DynamicLayers/Castbar.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,26 @@ namespace Chromatics.Layers
1313
{
1414
public class CastbarProcessor : LayerProcessor
1515
{
16+
private static CastbarProcessor _instance;
1617
private static Dictionary<int, CastbarDynamicModel> layerProcessorModel = new Dictionary<int, CastbarDynamicModel>();
1718
private bool _disposed = false;
1819

20+
// Private constructor to prevent direct instantiation
21+
private CastbarProcessor() { }
22+
23+
// Singleton instance access
24+
public static CastbarProcessor Instance
25+
{
26+
get
27+
{
28+
if (_instance == null)
29+
{
30+
_instance = new CastbarProcessor();
31+
}
32+
return _instance;
33+
}
34+
}
35+
1936
public override void Process(IMappingLayer layer)
2037
{
2138
if (_disposed)
@@ -205,6 +222,7 @@ protected override void Dispose(bool disposing)
205222
}
206223

207224
base.Dispose(disposing);
225+
_instance = null;
208226
}
209227

210228
private class CastbarDynamicModel

Chromatics/Layers/DynamicLayers/EnmityTracker.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,26 @@ namespace Chromatics.Layers
1313
{
1414
public class EnmityTrackerProcessor : LayerProcessor
1515
{
16+
private static EnmityTrackerProcessor _instance;
1617
private static Dictionary<int, EnmityDynamicModel> layerProcessorModel = new Dictionary<int, EnmityDynamicModel>();
1718
private bool _disposed = false;
1819

20+
// Private constructor to prevent direct instantiation
21+
private EnmityTrackerProcessor() { }
22+
23+
// Singleton instance access
24+
public static EnmityTrackerProcessor Instance
25+
{
26+
get
27+
{
28+
if (_instance == null)
29+
{
30+
_instance = new EnmityTrackerProcessor();
31+
}
32+
return _instance;
33+
}
34+
}
35+
1936
public override void Process(IMappingLayer layer)
2037
{
2138
if (_disposed)
@@ -290,6 +307,7 @@ protected override void Dispose(bool disposing)
290307
}
291308

292309
base.Dispose(disposing);
310+
_instance = null;
293311
}
294312

295313
private class EnmityDynamicModel

Chromatics/Layers/DynamicLayers/ExperienceTracker.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,27 @@ namespace Chromatics.Layers
1616
{
1717
public class ExperienceTrackerProcessor : LayerProcessor
1818
{
19+
private static ExperienceTrackerProcessor _instance;
1920
private static Dictionary<int, ExpTrackerDynamicModel> layerProcessorModel = new Dictionary<int, ExpTrackerDynamicModel>();
2021
private static Dictionary<int, int> levelMap = new Dictionary<int, int>();
2122
private bool _disposed = false;
2223

24+
// Private constructor to prevent direct instantiation
25+
private ExperienceTrackerProcessor() { }
26+
27+
// Singleton instance access
28+
public static ExperienceTrackerProcessor Instance
29+
{
30+
get
31+
{
32+
if (_instance == null)
33+
{
34+
_instance = new ExperienceTrackerProcessor();
35+
}
36+
return _instance;
37+
}
38+
}
39+
2340
public override void Process(IMappingLayer layer)
2441
{
2542
if (_disposed)
@@ -229,6 +246,7 @@ protected override void Dispose(bool disposing)
229246
}
230247

231248
base.Dispose(disposing);
249+
_instance = null;
232250
}
233251

234252
private int GetJobCurrentExperience(CurrentPlayerResult currentPlayer)

0 commit comments

Comments
 (0)