From 2a8e5db73fed43a4e3e683350a86019a97320377 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Tue, 3 Aug 2021 15:37:34 +0700 Subject: [PATCH] Fix `_textCache` missing for some classes Previously `_textCache` relied on static constructor inside base classes `AcediaObject` / `AceduaActor` to be created and filled with necessary data. This was faulty approach, since their static constructor was only ever supposed to be called once. This patch moves `_textCache` creation into `_constructor()` and `T()`, `P()`, `C()`, `F()` methods. --- sources/Types/AcediaActor.uc | 48 +++++++++++++++++------------------ sources/Types/AcediaObject.uc | 48 +++++++++++++++++------------------ 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/sources/Types/AcediaActor.uc b/sources/Types/AcediaActor.uc index 48479f5..5fd90c5 100644 --- a/sources/Types/AcediaActor.uc +++ b/sources/Types/AcediaActor.uc @@ -114,7 +114,9 @@ public function _constructor() default._ = class'Global'.static.GetInstance(); _ = default._; } - if (!default._staticConstructorWasCalled) { + if (!default._staticConstructorWasCalled) + { + CreateTextCache(); StaticConstructor(); default._staticConstructorWasCalled = true; } @@ -165,7 +167,7 @@ protected function Constructor(){} /** * When using proper methods for creating objects (`MemoryAPI`), * this method is guaranteed to be called after object of this (or it's child) - * class is deallocated. + * class is allocated. * * If you overload this method, first two lines must always be * ____________________________________________________________________________ @@ -174,22 +176,27 @@ protected function Constructor(){} * |___________________________________________________________________________ * otherwise behavior of constructors should be considered undefined. */ -public static function StaticConstructor() +public static function StaticConstructor(){} + +// By default this method will only create `TextCache` instance if it +// is needed, which is detected by checking whether `stringConstantsCopy` array +// is empty. +// However even if it is - class might make use of `P()`, `C()` or `F()` +// methods that also use `TextCache`. To force creating `TextCache` for them - +// set `forceCreation` parameter to `true`. +private final static function CreateTextCache(optional bool forceCreation) { local int i; local array stringConstantsCopy; - if (StaticConstructorGuard()) return; + // Cache already created + if (default._textCache != none) return; + // Do not do it for the cache itself + if (default.class == class'TextCache') return; // If there is no string constants to convert into `Text`s, // then this constructor has nothing to do. - if (default.stringConstants.length <= 0) return; - // Since `TextCache` does not have any string constants to convert, - // this check should never fail, but still do check to make extra sure - // there would not be any infinite loops if someone decided to add them. - if (default.class == class'TextCache') return; + if (!forceCreation && default.stringConstants.length <= 0) return; - if (default._textCache == none) { - default._textCache = TextCache(__().memory.Allocate(class'TextCache')); - } + default._textCache = TextCache(__().memory.Allocate(class'TextCache')); // Create `Text` constants stringConstantsCopy = default.stringConstants; for (i = 0; i < stringConstantsCopy.length; i += 1) { @@ -325,9 +332,8 @@ public final function int GetLifeVersion() */ public static final function Text T(int index) { - if (default._textCache == none) { - default._textCache = TextCache(__().memory.Allocate(class'TextCache')); - } + // Here cache should already be created, but make extra sure + CreateTextCache(true); return default._textCache.GetIndexedText(index); } @@ -346,9 +352,7 @@ public static final function Text T(int index) */ public static final function Text P(string string) { - if (default._textCache == none) { - default._textCache = TextCache(__().memory.Allocate(class'TextCache')); - } + CreateTextCache(true); return default._textCache.GetPlainText(string); } @@ -368,9 +372,7 @@ public static final function Text P(string string) */ public static final function Text C(string string) { - if (default._textCache == none) { - default._textCache = TextCache(__().memory.Allocate(class'TextCache')); - } + CreateTextCache(true); return default._textCache.GetColoredText(string); } @@ -390,9 +392,7 @@ public static final function Text C(string string) */ public static final function Text F(string string) { - if (default._textCache == none) { - default._textCache = TextCache(__().memory.Allocate(class'TextCache')); - } + CreateTextCache(true); return default._textCache.GetFormattedText(string); } diff --git a/sources/Types/AcediaObject.uc b/sources/Types/AcediaObject.uc index 55a08b8..8715e09 100644 --- a/sources/Types/AcediaObject.uc +++ b/sources/Types/AcediaObject.uc @@ -115,7 +115,9 @@ public final function _constructor() default._ = class'Global'.static.GetInstance(); _ = default._; } - if (!default._staticConstructorWasCalled) { + if (!default._staticConstructorWasCalled) + { + CreateTextCache(); StaticConstructor(); default._staticConstructorWasCalled = true; } @@ -166,7 +168,7 @@ protected function Constructor(){} /** * When using proper methods for creating objects (`MemoryAPI`), * this method is guaranteed to be called after object of this (or it's child) - * class is deallocated. + * class is allocated. * * If you overload this method, first two lines must always be * ____________________________________________________________________________ @@ -175,22 +177,27 @@ protected function Constructor(){} * |___________________________________________________________________________ * otherwise behavior of constructors should be considered undefined. */ -public static function StaticConstructor() +public static function StaticConstructor(){} + +// By default this method will only create `TextCache` instance if it +// is needed, which is detected by checking whether `stringConstantsCopy` array +// is empty. +// However even if it is - class might make use of `P()`, `C()` or `F()` +// methods that also use `TextCache`. To force creating `TextCache` for them - +// set `forceCreation` parameter to `true`. +private final static function CreateTextCache(optional bool forceCreation) { local int i; local array stringConstantsCopy; - if (StaticConstructorGuard()) return; + // Cache already created + if (default._textCache != none) return; + // Do not do it for the cache itself + if (default.class == class'TextCache') return; // If there is no string constants to convert into `Text`s, // then this constructor has nothing to do. - if (default.stringConstants.length <= 0) return; - // Since `TextCache` does not have any string constants to convert, - // this check should never fail, but still do check to make extra sure - // there would not be any infinite loops if someone decided to add them. - if (default.class == class'TextCache') return; + if (!forceCreation && default.stringConstants.length <= 0) return; - if (default._textCache == none) { - default._textCache = TextCache(__().memory.Allocate(class'TextCache')); - } + default._textCache = TextCache(__().memory.Allocate(class'TextCache')); // Create `Text` constants stringConstantsCopy = default.stringConstants; for (i = 0; i < stringConstantsCopy.length; i += 1) { @@ -340,9 +347,8 @@ public final function int GetLifeVersion() */ public static final function Text T(int index) { - if (default._textCache == none) { - default._textCache = TextCache(__().memory.Allocate(class'TextCache')); - } + // Here cache should already be created, but make extra sure + CreateTextCache(true); return default._textCache.GetIndexedText(index); } @@ -361,9 +367,7 @@ public static final function Text T(int index) */ public static final function Text P(string string) { - if (default._textCache == none) { - default._textCache = TextCache(__().memory.Allocate(class'TextCache')); - } + CreateTextCache(true); return default._textCache.GetPlainText(string); } @@ -383,9 +387,7 @@ public static final function Text P(string string) */ public static final function Text C(string string) { - if (default._textCache == none) { - default._textCache = TextCache(__().memory.Allocate(class'TextCache')); - } + CreateTextCache(true); return default._textCache.GetColoredText(string); } @@ -405,9 +407,7 @@ public static final function Text C(string string) */ public static final function Text F(string string) { - if (default._textCache == none) { - default._textCache = TextCache(__().memory.Allocate(class'TextCache')); - } + CreateTextCache(true); return default._textCache.GetFormattedText(string); }