From 33577660d9966f4a2fae7c96ff7991b36b90ba80 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Thu, 21 Jul 2022 03:52:00 +0700 Subject: [PATCH] Refactor `TimeAPI`, add it to client side --- .../ClientRealm/API/Unreal/ClientUnrealAPI.uc | 17 +- sources/ClientRealm/ClientAcediaAdapter.uc | 1 + sources/ClientRealm/ClientGlobal.uc | 1 + .../API/Time/Events/Timer_OnElapsed_Signal.uc | 0 .../API/Time/Events/Timer_OnElapsed_Slot.uc | 0 .../API/Time/TimeAPI.uc} | 46 +++-- .../API/Time/Timer.uc | 138 ++----------- sources/CoreRealm/API/UnrealAPI/UnrealAPI.uc | 2 + sources/CoreRealm/AcediaAdapter.uc | 3 +- sources/CoreRealm/CoreGlobal.uc | 4 +- .../{Server/Unreal => Core}/ActorStalker.uc | 0 .../Core/Time/KF1_RealTimer.uc} | 2 +- .../Time/KF1_TimeAPI.uc} | 28 +-- sources/KFRealm/Core/Time/KF1_Timer.uc | 181 ++++++++++++++++++ .../ServerRealm/API/Unreal/ServerUnrealAPI.uc | 23 +-- sources/ServerRealm/ServerAcediaAdapter.uc | 3 +- sources/ServerRealm/ServerGlobal.uc | 8 +- 17 files changed, 277 insertions(+), 180 deletions(-) rename sources/{ServerRealm => CoreRealm}/API/Time/Events/Timer_OnElapsed_Signal.uc (100%) rename sources/{ServerRealm => CoreRealm}/API/Time/Events/Timer_OnElapsed_Slot.uc (100%) rename sources/{ServerRealm/API/Time/ServerTimeAPI.uc => CoreRealm/API/Time/TimeAPI.uc} (68%) rename sources/{ServerRealm => CoreRealm}/API/Time/Timer.uc (56%) rename sources/KFRealm/{Server/Unreal => Core}/ActorStalker.uc (100%) rename sources/{ServerRealm/API/Time/RealTimer.uc => KFRealm/Core/Time/KF1_RealTimer.uc} (96%) rename sources/KFRealm/{Server/Time/KF1_ServerTimeAPI.uc => Core/Time/KF1_TimeAPI.uc} (68%) create mode 100644 sources/KFRealm/Core/Time/KF1_Timer.uc diff --git a/sources/ClientRealm/API/Unreal/ClientUnrealAPI.uc b/sources/ClientRealm/API/Unreal/ClientUnrealAPI.uc index 388e9b3..3cf2ee3 100644 --- a/sources/ClientRealm/API/Unreal/ClientUnrealAPI.uc +++ b/sources/ClientRealm/API/Unreal/ClientUnrealAPI.uc @@ -25,17 +25,18 @@ var protected bool initialized; var public InteractionAPI interaction; -public function Initialize(class adapterClass) +public function Initialize(class adapterClass) { - if (initialized) { - return; - } + local class asClientAdapter; + + if (initialized) return; + asClientAdapter = class(adapterClass); + if (asClientAdapter == none) return; + + super.Initialize(adapterClass); initialized = true; - if (adapterClass == none) { - return; - } interaction = InteractionAPI(_.memory.Allocate( - adapterClass.default.clientInteractionAPIClass)); + asClientAdapter.default.clientInteractionAPIClass)); } /** diff --git a/sources/ClientRealm/ClientAcediaAdapter.uc b/sources/ClientRealm/ClientAcediaAdapter.uc index 69ed40e..4000ea0 100644 --- a/sources/ClientRealm/ClientAcediaAdapter.uc +++ b/sources/ClientRealm/ClientAcediaAdapter.uc @@ -27,6 +27,7 @@ var public const class clientInteractionAPIClass; defaultproperties { + timeAPIClass = class'KF1_TimeAPI' clientUnrealAPIClass = class'KF1_ClientUnrealAPI' clientInteractionAPIClass = class'KF1_InteractionAPI' } \ No newline at end of file diff --git a/sources/ClientRealm/ClientGlobal.uc b/sources/ClientRealm/ClientGlobal.uc index c1c3bfc..bdc9314 100644 --- a/sources/ClientRealm/ClientGlobal.uc +++ b/sources/ClientRealm/ClientGlobal.uc @@ -68,6 +68,7 @@ protected function Initialize() unreal = ClientUnrealAPI( _.memory.Allocate(clientAdapterClass.default.clientUnrealAPIClass)); unreal.Initialize(clientAdapterClass); + time.Initialize(unreal); // Create `AcediaInteraction` localPlayer = unreal.GetLocalPlayer(); if (localPlayer != none) diff --git a/sources/ServerRealm/API/Time/Events/Timer_OnElapsed_Signal.uc b/sources/CoreRealm/API/Time/Events/Timer_OnElapsed_Signal.uc similarity index 100% rename from sources/ServerRealm/API/Time/Events/Timer_OnElapsed_Signal.uc rename to sources/CoreRealm/API/Time/Events/Timer_OnElapsed_Signal.uc diff --git a/sources/ServerRealm/API/Time/Events/Timer_OnElapsed_Slot.uc b/sources/CoreRealm/API/Time/Events/Timer_OnElapsed_Slot.uc similarity index 100% rename from sources/ServerRealm/API/Time/Events/Timer_OnElapsed_Slot.uc rename to sources/CoreRealm/API/Time/Events/Timer_OnElapsed_Slot.uc diff --git a/sources/ServerRealm/API/Time/ServerTimeAPI.uc b/sources/CoreRealm/API/Time/TimeAPI.uc similarity index 68% rename from sources/ServerRealm/API/Time/ServerTimeAPI.uc rename to sources/CoreRealm/API/Time/TimeAPI.uc index b863d3f..d7ebf80 100644 --- a/sources/ServerRealm/API/Time/ServerTimeAPI.uc +++ b/sources/CoreRealm/API/Time/TimeAPI.uc @@ -17,9 +17,28 @@ * You should have received a copy of the GNU General Public License * along with Acedia. If not, see . */ -class ServerTimeAPI extends AcediaObject +class TimeAPI extends AcediaObject abstract; +// API to use to initialize `Timer`s, should be chosen depending on where +// `Timer`s are created. +var protected UnrealAPI api; + +/** + * Initializes caller `TimeAPI` with given `UnrealAPI` instance that will + * be used to create all `Timer`s. + * + * This is necessary, because we don't know where `TimeAPI` will be used: + * on server or on client. + */ +public function Initialize(UnrealAPI newAPI) +{ + if (api != none) { + return; + } + api = newAPI; +} + /** * Creates new `Timer`. Does not start it. * @@ -49,33 +68,34 @@ public function Timer NewTimer( public function Timer StartTimer(float interval, optional bool autoReset); /** - * Creates new `RealTimer`. Does not start it. + * Creates new `Timer` that measures real time, not in-game one. + * Does not start it. * - * @param interval Returned `RealTimer` will be configured to emit + * @param interval Returned `Timer` will be configured to emit * `OnElapsed()` signals every `interval` seconds. - * @param autoReset `true` will configure caller `RealTimer` to repeatedly + * @param autoReset `true` will configure caller `Timer` to repeatedly * emit `OnElapsed()` every `interval` seconds, `false` (default value) - * will make returned `RealTimer` emit that signal only once. - * @return `RealTimer`, configured to emit `OnElapsed()` every `interval` + * will make returned `Timer` emit that signal only once. + * @return `Timer`, configured to emit `OnElapsed()` every `interval` * seconds. Not started. Guaranteed to be not `none`. */ -public function RealTimer NewRealTimer( +public function Timer NewRealTimer( optional float interval, optional bool autoReset); /** - * Creates and starts new `RealTimer`. + * Creates and starts new `Timer` that measures real time, not in-game one. * - * @param interval Returned `RealTimer` will be configured to emit + * @param interval Returned `Timer` will be configured to emit * `OnElapsed()` signals every `interval` seconds. - * @param autoReset Setting this to `true` will configure caller `RealTimer` + * @param autoReset Setting this to `true` will configure caller `Timer` * to repeatedly emit `OnElapsed()` signal every `interval` seconds, - * `false` (default value) will make returned `RealTimer` emit that signal + * `false` (default value) will make returned `Timer` emit that signal * only once. - * @return `RealTimer`, configured to emit `OnElapsed()` every `interval` + * @return `Timer`, configured to emit `OnElapsed()` every `interval` * seconds. Guaranteed to be not `none`. */ -public function RealTimer StartRealTimer( +public function Timer StartRealTimer( float interval, optional bool autoReset); diff --git a/sources/ServerRealm/API/Time/Timer.uc b/sources/CoreRealm/API/Time/Timer.uc similarity index 56% rename from sources/ServerRealm/API/Time/Timer.uc rename to sources/CoreRealm/API/Time/Timer.uc index 2947768..f9dd79e 100644 --- a/sources/ServerRealm/API/Time/Timer.uc +++ b/sources/CoreRealm/API/Time/Timer.uc @@ -1,7 +1,7 @@ /** * Timer class that generates a signal after a set interval, with an option * to generate recurring signals. - * Copyright 2021 Anton Tarasenko + * Copyright 2022 Anton Tarasenko *------------------------------------------------------------------------------ * This file is part of Acedia. * @@ -18,7 +18,8 @@ * You should have received a copy of the GNU General Public License * along with Acedia. If not, see . */ -class Timer extends AcediaObject; +class Timer extends AcediaObject + abstract; /** * Because the `Timer` depends on the `Tick()` event, it has the same @@ -31,35 +32,6 @@ class Timer extends AcediaObject; * the same exact time. */ -// Is timer currently tracking time until the next event? -var private bool isTimerEnabled; -// Should timer automatically reset after the next event to -// also generate recurring signals? -var private bool isTimerAutoReset; -// Currently elapsed time since this timer has started waiting for the -// next event -var private float totalElapsedTime; -// Time interval between timer's start and generating the signal -var private float eventInterval; -// This flag tells `Timer` to stop trying to emit messages that accumulated -// between two `Tick()` updates. Used in case `Timer` was disables or -// stopped during one of them. -var private bool clearEventQueue; - -var private Timer_OnElapsed_Signal onElapsedSignal; - -protected function Constructor() -{ - onElapsedSignal = Timer_OnElapsed_Signal( - _.memory.Allocate(class'Timer_OnElapsed_Signal')); -} - -protected function Finalizer() -{ - _.memory.Free(onElapsedSignal); - StopMe(); // Disconnects from listening to `_server.unreal.OnTick()` -} - /** * Signal that will be emitted every time timer's interval is elapsed. * @@ -69,10 +41,7 @@ protected function Finalizer() * @param source `Timer` that emitted the signal. */ /* SIGNAL */ -public final function Timer_OnElapsed_Slot OnElapsed(AcediaObject receiver) -{ - return Timer_OnElapsed_Slot(onElapsedSignal.NewSlot(receiver)); -} +public function Timer_OnElapsed_Slot OnElapsed(AcediaObject receiver); /** * This method is called every tick while the caller `Timer` is running and @@ -92,10 +61,7 @@ public final function Timer_OnElapsed_Slot OnElapsed(AcediaObject receiver) */ protected function float HandleTimeDilation( float timeDelta, - float dilationCoefficient) -{ - return timeDelta; -} + float dilationCoefficient); /** * Returns current interval between `OnElapsed()` signals for the @@ -104,10 +70,7 @@ protected function float HandleTimeDilation( * @return How many seconds separate two `OnElapsed()` signals * (or starting a timer and next `OnElapsed()` event). */ -public final function float GetInterval() -{ - return eventInterval; -} +public function float GetInterval(); /** * Sets current interval between `OnElapsed()` signals for the @@ -121,19 +84,7 @@ public final function float GetInterval() * Setting a value `<= 0` disables the timer. * @return Caller `Timer` to allow for method chaining. */ -public final function Timer SetInterval(float newInterval) -{ - eventInterval = newInterval; - if (eventInterval <= 0) - { - StopMe(); - return self; - } - if (isTimerEnabled) { - Start(); - } - return self; -} +public function Timer SetInterval(float newInterval); /** * Checks whether the timer is currently enabled (emitting signals with @@ -141,10 +92,7 @@ public final function Timer SetInterval(float newInterval) * * @return `true` if caller `Timer` is enabled and `false` otherwise. */ -public final function bool IsEnabled() -{ - return isTimerEnabled; -} +public function bool IsEnabled(); /** * Checks whether this `Timer` would automatically reset after the emitted @@ -153,10 +101,7 @@ public final function bool IsEnabled() * @return `true` if `Timer` will emit `OnElapse()` signal each time * the interval elapses and `false` otherwise. */ -public final function bool IsAutoReset(float newInterval) -{ - return isTimerAutoReset; -} +public function bool IsAutoReset(float newInterval); /** * Sets whether this `Timer` would automatically reset after the emitted @@ -166,11 +111,7 @@ public final function bool IsAutoReset(float newInterval) * each time the interval elapses and `false` otherwise. * @return Caller `Timer` to allow for method chaining. */ -public final function Timer SetAutoReset(bool doAutoReset) -{ - isTimerAutoReset = doAutoReset; - return self; -} +public function Timer SetAutoReset(bool doAutoReset); /** * Starts emitting `OneElapsed()` signal. @@ -183,31 +124,14 @@ public final function Timer SetAutoReset(bool doAutoReset) * * @return Caller `Timer` to allow for method chaining. */ -public final function Timer Start() -{ - if (eventInterval <= 0) { - return self; - } - if (!isTimerEnabled) { - _server.unreal.OnTick(self).connect = Tick; - } - isTimerEnabled = true; - totalElapsedTime = 0.0; - return self; -} +public function Timer Start(); /** * Stops emitting `OneElapsed()` signal. * * @return Caller `Timer` to allow for method chaining. */ -public final function Timer StopMe() -{ - _server.unreal.OnTick(self).Disconnect(); - isTimerEnabled = false; - clearEventQueue = true; - return self; -} +public function Timer StopMe(); /** * Returns currently elapsed time since caller `Timer` has started waiting for @@ -215,43 +139,9 @@ public final function Timer StopMe() * * @return Elapsed time since caller `Timer` has started. */ -public final function float GetElapsedTime() -{ - return totalElapsedTime; -} - -private final function Tick(float delta, float dilationCoefficient) -{ - local int lifeVersion; +public function float GetElapsedTime(); - if (onElapsedSignal == none || eventInterval <= 0.0) - { - StopMe(); - return; - } - totalElapsedTime += HandleTimeDilation(delta, dilationCoefficient); - clearEventQueue = false; - while (totalElapsedTime > eventInterval && !clearEventQueue) - { - // It is important to modify _before_ the signal call in case `Timer` - // is reset there and already has a zeroed `totalElapsedTime` - totalElapsedTime -= eventInterval; - // Stop `Timer` before emitting a signal, to allow user to potentially - // restart it - if (!isTimerAutoReset) { - StopMe(); - } - // During signal emission caller `Timer` can get reallocated and - // used to perform a completely different role. - // In such a case we need to bail from this method as soom as - // possible. - lifeVersion = GetLifeVersion(); - onElapsedSignal.Emit(self); - if (!isTimerEnabled || lifeVersion != GetLifeVersion()) { - return; - } - } -} +private function Tick(float delta, float dilationCoefficient); defaultproperties { diff --git a/sources/CoreRealm/API/UnrealAPI/UnrealAPI.uc b/sources/CoreRealm/API/UnrealAPI/UnrealAPI.uc index 604bec6..d3f3251 100644 --- a/sources/CoreRealm/API/UnrealAPI/UnrealAPI.uc +++ b/sources/CoreRealm/API/UnrealAPI/UnrealAPI.uc @@ -21,6 +21,8 @@ class UnrealAPI extends AcediaObject abstract; +public function Initialize(class adapterClass); + /** * Signal that will be emitted every tick. * diff --git a/sources/CoreRealm/AcediaAdapter.uc b/sources/CoreRealm/AcediaAdapter.uc index 676b4be..b7cc9d1 100644 --- a/sources/CoreRealm/AcediaAdapter.uc +++ b/sources/CoreRealm/AcediaAdapter.uc @@ -35,7 +35,8 @@ class AcediaAdapter extends AcediaObject * specify desired `AcediaAdapter` before loading server/client core. */ -var public const class sideEffectAPIClass; +var public const class sideEffectAPIClass; +var public const class timeAPIClass; defaultproperties { diff --git a/sources/CoreRealm/CoreGlobal.uc b/sources/CoreRealm/CoreGlobal.uc index d14d09f..64eddbc 100644 --- a/sources/CoreRealm/CoreGlobal.uc +++ b/sources/CoreRealm/CoreGlobal.uc @@ -24,7 +24,8 @@ class CoreGlobal extends Object; var protected bool initialized; var protected class adapterClass; -var public SideEffectAPI sideEffects; +var public SideEffectAPI sideEffects; +var public TimeAPI time; var private LoggerAPI.Definition fatNoAdapterClass; @@ -52,6 +53,7 @@ protected function Initialize() api = class'Global'.static.GetInstance().memory; sideEffects = SideEffectAPI(api.Allocate(adapterClass.default.sideEffectAPIClass)); + time = TimeAPI(api.Allocate(adapterClass.default.timeAPIClass)); } /** diff --git a/sources/KFRealm/Server/Unreal/ActorStalker.uc b/sources/KFRealm/Core/ActorStalker.uc similarity index 100% rename from sources/KFRealm/Server/Unreal/ActorStalker.uc rename to sources/KFRealm/Core/ActorStalker.uc diff --git a/sources/ServerRealm/API/Time/RealTimer.uc b/sources/KFRealm/Core/Time/KF1_RealTimer.uc similarity index 96% rename from sources/ServerRealm/API/Time/RealTimer.uc rename to sources/KFRealm/Core/Time/KF1_RealTimer.uc index 0b05c7a..1a79628 100644 --- a/sources/ServerRealm/API/Time/RealTimer.uc +++ b/sources/KFRealm/Core/Time/KF1_RealTimer.uc @@ -18,7 +18,7 @@ * You should have received a copy of the GNU General Public License * along with Acedia. If not, see . */ -class RealTimer extends Timer; +class KF1_RealTimer extends KF1_Timer; protected function float HandleTimeDilation( float timeDelta, diff --git a/sources/KFRealm/Server/Time/KF1_ServerTimeAPI.uc b/sources/KFRealm/Core/Time/KF1_TimeAPI.uc similarity index 68% rename from sources/KFRealm/Server/Time/KF1_ServerTimeAPI.uc rename to sources/KFRealm/Core/Time/KF1_TimeAPI.uc index 252d83a..d427019 100644 --- a/sources/KFRealm/Server/Time/KF1_ServerTimeAPI.uc +++ b/sources/KFRealm/Core/Time/KF1_TimeAPI.uc @@ -1,5 +1,5 @@ /** - * Acedia's default `ServerTimeAPI` API implementation + * Acedia's default `TimeAPI` API implementation * Copyright 2021-2022 Anton Tarasenko *------------------------------------------------------------------------------ * This file is part of Acedia. @@ -17,45 +17,45 @@ * You should have received a copy of the GNU General Public License * along with Acedia. If not, see . */ -class KF1_ServerTimeAPI extends ServerTimeAPI; +class KF1_TimeAPI extends TimeAPI; public function Timer NewTimer( optional float interval, optional bool autoReset) { - return Timer(_.memory.Allocate(class'Timer')) + return KF1_Timer(_.memory.Allocate(class'KF1_Timer')) + .Initialize(api) .SetInterval(interval) .SetAutoReset(autoReset); } public function Timer StartTimer(float interval, optional bool autoReset) { - return Timer(_.memory.Allocate(class'Timer')) + return KF1_Timer(_.memory.Allocate(class'KF1_Timer')) + .Initialize(api) .SetInterval(interval) .SetAutoReset(autoReset) .Start(); } -public function RealTimer NewRealTimer( +public function Timer NewRealTimer( optional float interval, optional bool autoReset) { - local RealTimer newTimer; - newTimer = RealTimer(_.memory.Allocate(class'RealTimer')); - newTimer.SetInterval(interval).SetAutoReset(autoReset); - return newTimer; + return KF1_Timer(_.memory.Allocate(class'KF1_RealTimer')) + .Initialize(api) + .SetInterval(interval).SetAutoReset(autoReset); } -public function RealTimer StartRealTimer( +public function Timer StartRealTimer( float interval, optional bool autoReset) { - local RealTimer newTimer; - newTimer = RealTimer(_.memory.Allocate(class'RealTimer')); - newTimer.SetInterval(interval) + return KF1_Timer(_.memory.Allocate(class'KF1_RealTimer')) + .Initialize(api) + .SetInterval(interval) .SetAutoReset(autoReset) .Start(); - return newTimer; } defaultproperties diff --git a/sources/KFRealm/Core/Time/KF1_Timer.uc b/sources/KFRealm/Core/Time/KF1_Timer.uc new file mode 100644 index 0000000..faae97e --- /dev/null +++ b/sources/KFRealm/Core/Time/KF1_Timer.uc @@ -0,0 +1,181 @@ +/** + * Acedia's default implementation for `Timer` class. + * Copyright 2021-2022 Anton Tarasenko + *------------------------------------------------------------------------------ + * This file is part of Acedia. + * + * Acedia is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License, or + * (at your option) any later version. + * + * Acedia is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Acedia. If not, see . + */ +class KF1_Timer extends Timer; + +// Is timer currently tracking time until the next event? +var protected bool isTimerEnabled; +// Should timer automatically reset after the next event to +// also generate recurring signals? +var protected bool isTimerAutoReset; +// Currently elapsed time since this timer has started waiting for the +// next event +var protected float totalElapsedTime; +// Time interval between timer's start and generating the signal +var protected float eventInterval; +// This flag tells `Timer` to stop trying to emit messages that accumulated +// between two `Tick()` updates. Used in case `Timer` was disables or +// stopped during one of them. +var protected bool clearEventQueue; + +// `UnrealAPI` to use, has to be set to access `OnTick()` signal. +var protected UnrealAPI api; + +var protected Timer_OnElapsed_Signal onElapsedSignal; + +protected function Constructor() +{ + onElapsedSignal = Timer_OnElapsed_Signal( + _.memory.Allocate(class'Timer_OnElapsed_Signal')); +} + +protected function Finalizer() +{ + _.memory.Free(onElapsedSignal); + StopMe(); // Disconnects from listening to `api.OnTick()` + api = none; +} + +/** + * Initializes caller `Timer` with given `UnrealAPI` instance that will be used + * to track `OnTick()` signal. + * + * This is necessary, because we don't know where `KF1_Timer` will be used: + * on server or on client. + */ +public function Timer Initialize(UnrealAPI newAPI) +{ + if (api != none) { + return self; + } + api = newAPI; + return self; +} + +/* SIGNAL */ +public function Timer_OnElapsed_Slot OnElapsed(AcediaObject receiver) +{ + return Timer_OnElapsed_Slot(onElapsedSignal.NewSlot(receiver)); +} + +protected function float HandleTimeDilation( + float timeDelta, + float dilationCoefficient) +{ + return timeDelta; +} + + +public function float GetInterval() +{ + return eventInterval; +} + +public function Timer SetInterval(float newInterval) +{ + eventInterval = newInterval; + if (eventInterval <= 0) + { + StopMe(); + return self; + } + if (isTimerEnabled) { + Start(); + } + return self; +} + +public function bool IsEnabled() +{ + return isTimerEnabled; +} + +public function bool IsAutoReset(float newInterval) +{ + return isTimerAutoReset; +} + +public function Timer SetAutoReset(bool doAutoReset) +{ + isTimerAutoReset = doAutoReset; + return self; +} + +public function Timer Start() +{ + if (eventInterval <= 0) { + return self; + } + if (!isTimerEnabled) { + api.OnTick(self).connect = Tick; + } + isTimerEnabled = true; + totalElapsedTime = 0.0; + return self; +} + +public function Timer StopMe() +{ + api.OnTick(self).Disconnect(); + isTimerEnabled = false; + clearEventQueue = true; + return self; +} + +public function float GetElapsedTime() +{ + return totalElapsedTime; +} + +private function Tick(float delta, float dilationCoefficient) +{ + local int lifeVersion; + + if (onElapsedSignal == none || eventInterval <= 0.0) + { + StopMe(); + return; + } + totalElapsedTime += HandleTimeDilation(delta, dilationCoefficient); + clearEventQueue = false; + while (totalElapsedTime > eventInterval && !clearEventQueue) + { + // It is important to modify _before_ the signal call in case `Timer` + // is reset there and already has a zeroed `totalElapsedTime` + totalElapsedTime -= eventInterval; + // Stop `Timer` before emitting a signal, to allow user to potentially + // restart it + if (!isTimerAutoReset) { + StopMe(); + } + // During signal emission caller `Timer` can get reallocated and + // used to perform a completely different role. + // In such a case we need to bail from this method as soom as + // possible. + lifeVersion = GetLifeVersion(); + onElapsedSignal.Emit(self); + if (!isTimerEnabled || lifeVersion != GetLifeVersion()) { + return; + } + } +} + +defaultproperties +{ +} \ No newline at end of file diff --git a/sources/ServerRealm/API/Unreal/ServerUnrealAPI.uc b/sources/ServerRealm/API/Unreal/ServerUnrealAPI.uc index bf8e219..3e8b7b4 100644 --- a/sources/ServerRealm/API/Unreal/ServerUnrealAPI.uc +++ b/sources/ServerRealm/API/Unreal/ServerUnrealAPI.uc @@ -28,23 +28,24 @@ var public GameRulesAPI gameRules; var public BroadcastAPI broadcasts; var public InventoryAPI inventory; -public function Initialize(class adapterClass) +public function Initialize(class adapterClass) { - if (initialized) { - return; - } + local class asServerAdapter; + + if (initialized) return; + asServerAdapter = class(adapterClass); + if (asServerAdapter == none) return; + + super.Initialize(adapterClass); initialized = true; - if (adapterClass == none) { - return; - } mutator = MutatorAPI(_.memory.Allocate( - adapterClass.default.serverMutatorAPIClass)); + asServerAdapter.default.serverMutatorAPIClass)); gameRules = GameRulesAPI(_.memory.Allocate( - adapterClass.default.serverGameRulesAPIClass)); + asServerAdapter.default.serverGameRulesAPIClass)); broadcasts = BroadcastAPI(_.memory.Allocate( - adapterClass.default.serverBroadcastAPIClass)); + asServerAdapter.default.serverBroadcastAPIClass)); inventory = InventoryAPI (_.memory.Allocate( - adapterClass.default.serverInventoryAPIClass)); + asServerAdapter.default.serverInventoryAPIClass)); } defaultproperties diff --git a/sources/ServerRealm/ServerAcediaAdapter.uc b/sources/ServerRealm/ServerAcediaAdapter.uc index dff3223..5eb3290 100644 --- a/sources/ServerRealm/ServerAcediaAdapter.uc +++ b/sources/ServerRealm/ServerAcediaAdapter.uc @@ -22,7 +22,6 @@ class ServerAcediaAdapter extends AcediaAdapter abstract; -var public const class serverTimeAPIClass; var public const class serverUnrealAPIClass; var public const class serverBroadcastAPIClass; var public const class serverGameRulesAPIClass; @@ -31,7 +30,7 @@ var public const class serverMutatorAPIClass; defaultproperties { - serverTimeAPIClass = class'KF1_ServerTimeAPI' + timeAPIClass = class'KF1_TimeAPI' serverUnrealAPIClass = class'KF1_ServerUnrealAPI' serverBroadcastAPIClass = class'KF1_BroadcastAPI' serverGameRulesAPIClass = class'KF1_GameRulesAPI' diff --git a/sources/ServerRealm/ServerGlobal.uc b/sources/ServerRealm/ServerGlobal.uc index a217f84..85c436e 100644 --- a/sources/ServerRealm/ServerGlobal.uc +++ b/sources/ServerRealm/ServerGlobal.uc @@ -27,7 +27,6 @@ var protected ServerGlobal myself; var public KFFrontend kf; var public ServerUnrealAPI unreal; -var public ServerTimeAPI time; var private LoggerAPI.Definition fatBadAdapterClass; @@ -64,12 +63,11 @@ protected function Initialize() return; } _ = class'Global'.static.GetInstance(); - unreal = ServerUnrealAPI( + unreal = ServerUnrealAPI( _.memory.Allocate(serverAdapterClass.default.serverUnrealAPIClass)); unreal.Initialize(serverAdapterClass); - time = ServerTimeAPI( - _.memory.Allocate(serverAdapterClass.default.serverTimeAPIClass)); - kf = KFFrontend(_.memory.Allocate(class'KF1_Frontend')); + time.Initialize(unreal); + kf = KFFrontend(_.memory.Allocate(class'KF1_Frontend')); } public final function bool ConnectServerLevelCore()