From c92e3d04351e27a1f09332c62153badab627e062 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Mon, 18 Jul 2022 02:00:07 +0700 Subject: [PATCH] Add client-side `UnrealAPI` --- .../ClientRealm/API/Unreal/ClientUnrealAPI.uc | 137 ++++++++++++++++++ .../API/Unreal/ClientUnrealAPIBase.uc | 35 +++++ sources/ClientRealm/ClientAcediaAdapter.uc | 30 ++++ sources/ClientRealm/ClientGlobal.uc | 32 ++++ sources/{ => ClientRealm}/ClientLevelCore.uc | 10 +- .../API/UnrealAPI}/ActorService.uc | 0 .../CoreRealm/API/UnrealAPI/UnrealAPIBase.uc | 133 +++++++++++++++++ sources/CoreRealm/LevelCore.uc | 31 +++- .../API/Unreal/BroadcastsAPI/BroadcastAPI.uc | 36 ++--- .../BroadcastsAPI/BroadcastEventsObserver.uc | 2 +- .../Unreal/GameRulesAPI/AcediaGameRules.uc | 2 +- .../API/Unreal/GameRulesAPI/GameRulesAPI.uc | 54 +++---- .../API/Unreal/MutatorsAPI/MutatorAPI.uc | 18 +-- .../ServerRealm/API/Unreal/ServerUnrealAPI.uc | 21 ++- .../API/Unreal/ServerUnrealAPIBase.uc | 120 +-------------- ...nrealService.uc => ServerUnrealService.uc} | 2 +- 16 files changed, 473 insertions(+), 190 deletions(-) create mode 100644 sources/ClientRealm/API/Unreal/ClientUnrealAPI.uc create mode 100644 sources/ClientRealm/API/Unreal/ClientUnrealAPIBase.uc create mode 100644 sources/ClientRealm/ClientAcediaAdapter.uc rename sources/{ => ClientRealm}/ClientLevelCore.uc (79%) rename sources/{Types => CoreRealm/API/UnrealAPI}/ActorService.uc (100%) create mode 100644 sources/CoreRealm/API/UnrealAPI/UnrealAPIBase.uc rename sources/ServerRealm/API/Unreal/{UnrealService.uc => ServerUnrealService.uc} (98%) diff --git a/sources/ClientRealm/API/Unreal/ClientUnrealAPI.uc b/sources/ClientRealm/API/Unreal/ClientUnrealAPI.uc new file mode 100644 index 0000000..beee114 --- /dev/null +++ b/sources/ClientRealm/API/Unreal/ClientUnrealAPI.uc @@ -0,0 +1,137 @@ +/** + * Acedia's default implementation for `ClientUnrealAPIBase`. + * 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 ClientUnrealAPI extends ClientUnrealAPIBase; + +var private LoggerAPI.Definition fatalNoStalker; + +protected function Constructor() +{ + _.environment.OnShutDownSystem(self).connect = HandleShutdown; +} + +protected function HandleShutdown() +{ + local ServerUnrealService service; + + service = ServerUnrealService( + class'ServerUnrealService'.static.GetInstance()); + // This has to clean up anything we've added + if (service != none) { + service.Destroy(); + } +} + +/* SIGNAL */ +public function Unreal_OnTick_Slot OnTick( + AcediaObject receiver) +{ + local Signal signal; + local ServerUnrealService service; + + service = ServerUnrealService(class'ServerUnrealService'.static.Require()); + signal = service.GetSignal(class'Unreal_OnTick_Signal'); + return Unreal_OnTick_Slot(signal.NewSlot(receiver)); +} + +/* SIGNAL */ +public function SimpleSlot OnDestructionFor( + AcediaObject receiver, + Actor targetToStalk) +{ + local ActorStalker stalker; + + if (receiver == none) return none; + if (targetToStalk == none) return none; + + // Failing to spawn this actor without any collision flags is considered + // completely unexpected and grounds for fatal failure on Acedia' part + stalker = ActorStalker(class'ClientLevelCore'.static + .GetInstance() + .Allocate(class'ActorStalker')); + if (stalker == none) + { + _.logger.Auto(fatalNoStalker); + return none; + } + // This will not fail, since we have already ensured that + // `targetToStalk == none` + stalker.Initialize(targetToStalk); + return stalker.OnActorDestruction(receiver); +} + +public function LevelInfo GetLevel() +{ + return class'ClientLevelCore'.static.GetInstance().level; +} + +public function GameReplicationInfo GetGameRI() +{ + return class'ClientLevelCore'.static.GetInstance().level.GRI; +} + +public function KFGameReplicationInfo GetKFGameRI() +{ + return KFGameReplicationInfo(GetGameRI()); +} + +public function GameInfo GetGameType() +{ + return class'ClientLevelCore'.static.GetInstance().level.game; +} + +public function KFGameType GetKFGameType() +{ + return KFGameType(GetGameType()); +} + +public function Actor FindActorInstance(class classToFind) +{ + local Actor result; + local LevelCore core; + + core = class'ClientLevelCore'.static.GetInstance(); + foreach core.AllActors(classToFind, result) + { + if (result != none) { + break; + } + } + return result; +} + +public function PlayerController GetLocalPlayer() +{ + return class'ClientLevelCore'.static.GetInstance().level + .GetLocalPlayerController(); +} + +public function NativeActorRef ActorRef(optional Actor value) +{ + local NativeActorRef ref; + + ref = NativeActorRef(_.memory.Allocate(class'NativeActorRef')); + ref.Set(value); + return ref; +} + +defaultproperties +{ + fatalNoStalker = (l=LOG_Fatal,m="Cannot spawn `PawnStalker`") +} \ No newline at end of file diff --git a/sources/ClientRealm/API/Unreal/ClientUnrealAPIBase.uc b/sources/ClientRealm/API/Unreal/ClientUnrealAPIBase.uc new file mode 100644 index 0000000..1470307 --- /dev/null +++ b/sources/ClientRealm/API/Unreal/ClientUnrealAPIBase.uc @@ -0,0 +1,35 @@ +/** + * Low-level API that provides set of utility methods for working with + * unreal script classes on the clients. + * Copyright 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 ClientUnrealAPIBase extends UnrealAPIBase + abstract; + +/** + * Returns current local player's `Controller`. Useful because `level` + * is not accessible inside objects. + * + * @return `PlayerController` instance for the local player. `none` iff run on + * dedicated servers. + */ +public function PlayerController GetLocalPlayer(); + +defaultproperties +{ +} \ No newline at end of file diff --git a/sources/ClientRealm/ClientAcediaAdapter.uc b/sources/ClientRealm/ClientAcediaAdapter.uc new file mode 100644 index 0000000..22a17ed --- /dev/null +++ b/sources/ClientRealm/ClientAcediaAdapter.uc @@ -0,0 +1,30 @@ +/** + * Base class for objects that will provide an access to a Acedia's client- and + * server-specific functionality by giving a reference to this object to all + * Acedia's objects and actors, emulating a global API namespace. + * Copyright 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 ClientAcediaAdapter extends AcediaAdapter + abstract; + +var public const class clientUnrealAPIClass; + +defaultproperties +{ + clientUnrealAPIClass = class'ClientUnrealAPI' +} \ No newline at end of file diff --git a/sources/ClientRealm/ClientGlobal.uc b/sources/ClientRealm/ClientGlobal.uc index c5e57e3..2432701 100644 --- a/sources/ClientRealm/ClientGlobal.uc +++ b/sources/ClientRealm/ClientGlobal.uc @@ -25,6 +25,10 @@ class ClientGlobal extends CoreGlobal; // main instance in this variable's default value. var protected ClientGlobal myself; +var public ClientUnrealAPIBase unreal; + +var private LoggerAPI.Definition fatBadAdapterClass; + public final static function ClientGlobal GetInstance() { if (default.myself == none) @@ -38,13 +42,41 @@ public final static function ClientGlobal GetInstance() protected function Initialize() { + local Global _; + local class clientAdapterClass; + if (initialized) { return; } super.Initialize(); initialized = true; + clientAdapterClass = class(adapterClass); + if (adapterClass != none && clientAdapterClass == none) + { + class'Global'.static.GetInstance().logger + .Auto(fatBadAdapterClass) + .ArgClass(self.class); + return; + } + if (clientAdapterClass == none) { + return; + } + _ = class'Global'.static.GetInstance(); + unreal = ClientUnrealAPIBase( + _.memory.Allocate(clientAdapterClass.default.clientUnrealAPIClass)); +} + +public final function bool ConnectClientLevelCore() +{ + if (class'ClientLevelCore'.static.GetInstance() == none) { + return false; + } + Initialize(); + return true; } defaultproperties { + adapterClass = class'ClientAcediaAdapter' + fatBadAdapterClass = (l=LOG_Fatal,m="non-`ClientAcediaAdapter` class was specified as an adapter for `%1` level core class. This should not have happened. AcediaCore cannot properly function.") } \ No newline at end of file diff --git a/sources/ClientLevelCore.uc b/sources/ClientRealm/ClientLevelCore.uc similarity index 79% rename from sources/ClientLevelCore.uc rename to sources/ClientRealm/ClientLevelCore.uc index 79d1fc4..850624a 100644 --- a/sources/ClientLevelCore.uc +++ b/sources/ClientRealm/ClientLevelCore.uc @@ -18,12 +18,18 @@ */ class ClientLevelCore extends LevelCore; -public static function LevelCore CreateLevelCore(Actor source) +public simulated static function LevelCore CreateLevelCore(Actor source) { + local LevelCore newCore; + if (source == none) return none; if (source.level.netMode == NM_DedicatedServer) return none; - return super.CreateLevelCore(source); + newCore = super.CreateLevelCore(source); + if (newCore != none) { + __client().ConnectClientLevelCore(); + } + return newCore; } defaultproperties diff --git a/sources/Types/ActorService.uc b/sources/CoreRealm/API/UnrealAPI/ActorService.uc similarity index 100% rename from sources/Types/ActorService.uc rename to sources/CoreRealm/API/UnrealAPI/ActorService.uc diff --git a/sources/CoreRealm/API/UnrealAPI/UnrealAPIBase.uc b/sources/CoreRealm/API/UnrealAPI/UnrealAPIBase.uc new file mode 100644 index 0000000..a62b8db --- /dev/null +++ b/sources/CoreRealm/API/UnrealAPI/UnrealAPIBase.uc @@ -0,0 +1,133 @@ +/** + * Low-level API that provides set of utility methods for working with + * unreal script classes. + * 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 UnrealAPIBase extends AcediaObject + abstract; + +/** + * Signal that will be emitted every tick. + * + * [Signature] + * void (float delta, float dilationCoefficient) + * + * @param delta In-game time in seconds that has passed since + * the last tick. To obtain real time passed from the last tick divide + * `delta` by `dilationCoefficient`. + * @param dilationCoefficient How fast is in-game time flow compared to + * the real world's one? `2` means twice as fast and + * `0.5` means twice as slow. + */ +/* SIGNAL */ +public function Unreal_OnTick_Slot OnTick(AcediaObject receiver); + +/** + * Signal that will be emitted when a passed `targetToStalk` is destroyed. + * + * Passed parameter `targetToStalk` cannot be `none`, otherwise `none` will be + * returned instead of a valid slot. + * + * @param receiver Specify a receiver like for any other signal. + * @param targetToStalk Actor whose destruction we want to detect. + * + * [Signature] + * void () + */ +/* SIGNAL */ +public function SimpleSlot OnDestructionFor( + AcediaObject receiver, + Actor targetToStalk); + +/** + * Returns current game's `LevelInfo`. Useful because `level` variable + * is not defined inside objects. + * + * @return `LevelInfo` instance for the current game. Guaranteed to + * not be `none`. + */ +public function LevelInfo GetLevel(); + +/** + * Returns current game's `GameReplicationInfo`. Useful because `level.game` + * is not accessible inside objects. + * + * @return `GameReplicationInfo` instance for the current game. Guaranteed to + * not be `none`. + */ +public function GameReplicationInfo GetGameRI(); + +/** + * Returns current game's `GameReplicationInfo` as `KFGameReplicationInfo`. + * Useful because `level.game` is not accessible inside objects and because it + * auto converts game replication info type to `KFGameReplicationInfo`, which + * virtually all mods for killing floor use (by itself or as a base class). + * + * @return `KFGameReplicationInfo` instance for the current game. + * Can be `none` only if game was modded to run a `KFGameReplicationInfo` + * not derived from `KFGameType`. + */ +public function KFGameReplicationInfo GetKFGameRI(); + +/** + * Returns current game's `GameInfo`. Useful because `level.game` is not + * accessible inside objects. + * + * @return `GameInfo` instance for the current game. Guaranteed to + * not be `none`. + */ +public function GameInfo GetGameType(); + +/** + * Returns current game's `GameInfo` as `KFGameType`. Useful because + * `level.game` is not accessible inside objects and because it auto converts + * game type to `KFGameType`, which virtually all mods for killing floor use + * (by itself or as a base class). + * + * @return `KFGameType` instance for the current game. Can be `none` only if + * game was modded to run a `GameInfo` not derived from `KFGameType`. + */ +public function KFGameType GetKFGameType(); + +/** + * Searches all `Actor`s on the level for an instance of specific class and + * returns it. + * + * @param classToFind Class we want to find an instance of. + * @result A pre-existing instance of class `classToFind`, `none` if + * no instances exist at the moment of this method's call. + */ +public function Actor FindActorInstance(class classToFind); + +/** + * Creates reference object to store a `Actor` value. + * + * Such references are necessary, since `Actor` references aren't safe to store + * inside non-actor `Object`s. To allow that Acedia uses a round about way of + * storing all `Actor` references in a special `Actor`, while allowing to refer + * to them via `NativeActorRef` (also `ActorRef` for `AcediaActor`s + * specifically). + * + * @param value Initial value to store in reference. + * @return `NativeActorRef`, containing `value`. + */ +public function NativeActorRef ActorRef(optional Actor value); + +defaultproperties +{ +} \ No newline at end of file diff --git a/sources/CoreRealm/LevelCore.uc b/sources/CoreRealm/LevelCore.uc index af0afe4..d883783 100644 --- a/sources/CoreRealm/LevelCore.uc +++ b/sources/CoreRealm/LevelCore.uc @@ -78,7 +78,7 @@ public final function SimpleSlot OnShutdown(AcediaObject receiver) return SimpleSlot(onShutdownSignal.NewSlot(receiver)); } -public static function LevelCore CreateLevelCore(Actor source) +public simulated static function LevelCore CreateLevelCore(Actor source) { if (GetInstance() != none) return none; if (source == none) return none; @@ -89,6 +89,35 @@ public static function LevelCore CreateLevelCore(Actor source) return default.activeInstance; } +/** + * Creates new `Actor` in the level as the caller `LevelCore`. + * + * For `AcediaActor`s calls their constructors. + * + * @param classToAllocate Class of the `Object` that this method will + * create. Must not be subclass of `Actor`. + * @return Newly created object. + * Will only be `none` if `classToAllocate` is `none` or `classToAllocate` + * is abstract. + */ +public final function Actor Allocate(class classToAllocate) +{ + local Actor allocatedActor; + local class acediaClassToAllocate; + + if (classToAllocate == none) { + return none; + } + acediaClassToAllocate = class(classToAllocate); + allocatedActor = Spawn(classToAllocate); + // Call constructor here, just in case, to make sure constructor is called + // as soon as possible + if (acediaClassToAllocate != none) { + AcediaActor(allocatedActor)._constructor(); + } + return allocatedActor; +} + public final static function LevelCore GetInstance() { local bool instanceExists; diff --git a/sources/ServerRealm/API/Unreal/BroadcastsAPI/BroadcastAPI.uc b/sources/ServerRealm/API/Unreal/BroadcastsAPI/BroadcastAPI.uc index 61d50df..b13c28c 100644 --- a/sources/ServerRealm/API/Unreal/BroadcastsAPI/BroadcastAPI.uc +++ b/sources/ServerRealm/API/Unreal/BroadcastsAPI/BroadcastAPI.uc @@ -31,10 +31,10 @@ var private LoggerAPI.Definition errBroadcasthandlerUnknown; public function Broadcast_OnBroadcastCheck_Slot OnBroadcastCheck( AcediaObject receiver) { - local Signal signal; - local UnrealService service; + local Signal signal; + local ServerUnrealService service; - service = UnrealService(class'UnrealService'.static.Require()); + service = ServerUnrealService(class'ServerUnrealService'.static.Require()); TryInjectBroadcastHandler(service); signal = service.GetSignal(class'Broadcast_OnBroadcastCheck_Signal'); return Broadcast_OnBroadcastCheck_Slot(signal.NewSlot(receiver)); @@ -44,10 +44,10 @@ public function Broadcast_OnBroadcastCheck_Slot OnBroadcastCheck( public function Broadcast_OnHandleText_Slot OnHandleText( AcediaObject receiver) { - local Signal signal; - local UnrealService service; + local Signal signal; + local ServerUnrealService service; - service = UnrealService(class'UnrealService'.static.Require()); + service = ServerUnrealService(class'ServerUnrealService'.static.Require()); TryInjectBroadcastHandler(service); signal = service.GetSignal(class'Broadcast_OnHandleText_Signal'); return Broadcast_OnHandleText_Slot(signal.NewSlot(receiver)); @@ -57,10 +57,10 @@ public function Broadcast_OnHandleText_Slot OnHandleText( public function Broadcast_OnHandleTextFor_Slot OnHandleTextFor( AcediaObject receiver) { - local Signal signal; - local UnrealService service; + local Signal signal; + local ServerUnrealService service; - service = UnrealService(class'UnrealService'.static.Require()); + service = ServerUnrealService(class'ServerUnrealService'.static.Require()); TryInjectBroadcastHandler(service); signal = service.GetSignal(class'Broadcast_OnHandleTextFor_Signal'); return Broadcast_OnHandleTextFor_Slot(signal.NewSlot(receiver)); @@ -70,10 +70,10 @@ public function Broadcast_OnHandleTextFor_Slot OnHandleTextFor( public function Broadcast_OnHandleLocalized_Slot OnHandleLocalized( AcediaObject receiver) { - local Signal signal; - local UnrealService service; + local Signal signal; + local ServerUnrealService service; - service = UnrealService(class'UnrealService'.static.Require()); + service = ServerUnrealService(class'ServerUnrealService'.static.Require()); TryInjectBroadcastHandler(service); signal = service.GetSignal(class'Broadcast_OnHandleLocalized_Signal'); return Broadcast_OnHandleLocalized_Slot(signal.NewSlot(receiver)); @@ -83,10 +83,10 @@ public function Broadcast_OnHandleLocalized_Slot OnHandleLocalized( public function Broadcast_OnHandleLocalizedFor_Slot OnHandleLocalizedFor( AcediaObject receiver) { - local Signal signal; - local UnrealService service; + local Signal signal; + local ServerUnrealService service; - service = UnrealService(class'UnrealService'.static.Require()); + service = ServerUnrealService(class'ServerUnrealService'.static.Require()); TryInjectBroadcastHandler(service); signal = service.GetSignal(class'Broadcast_OnHandleLocalizedFor_Signal'); return Broadcast_OnHandleLocalizedFor_Slot(signal.NewSlot(receiver)); @@ -96,10 +96,10 @@ public function Broadcast_OnHandleLocalizedFor_Slot OnHandleLocalizedFor( * Method that attempts to inject Acedia's `BroadcastEventObserver`, while * respecting settings inside `class'SideEffects'`. * - * @param service Reference to `UnrealService` to exchange signal and slots - * classes with. + * @param service Reference to `ServerUnrealService` to exchange signal and + * slots classes with. */ -protected final function TryInjectBroadcastHandler(UnrealService service) +protected final function TryInjectBroadcastHandler(ServerUnrealService service) { local InjectionLevel usedLevel; local BroadcastSideEffect sideEffect; diff --git a/sources/ServerRealm/API/Unreal/BroadcastsAPI/BroadcastEventsObserver.uc b/sources/ServerRealm/API/Unreal/BroadcastsAPI/BroadcastEventsObserver.uc index 36f1657..d220408 100644 --- a/sources/ServerRealm/API/Unreal/BroadcastsAPI/BroadcastEventsObserver.uc +++ b/sources/ServerRealm/API/Unreal/BroadcastsAPI/BroadcastEventsObserver.uc @@ -204,7 +204,7 @@ var private Broadcast_OnHandleLocalizedFor_Signal onHandleLocalizedFor; var private Broadcast_OnHandleText_Signal onHandleText; var private Broadcast_OnHandleTextFor_Signal onHandleTextFor; -public final function Initialize(UnrealService service) +public final function Initialize(ServerUnrealService service) { usedInjectionLevel = class'SideEffects'.default.broadcastHandlerInjectionLevel; diff --git a/sources/ServerRealm/API/Unreal/GameRulesAPI/AcediaGameRules.uc b/sources/ServerRealm/API/Unreal/GameRulesAPI/AcediaGameRules.uc index abc4b06..d2c190a 100644 --- a/sources/ServerRealm/API/Unreal/GameRulesAPI/AcediaGameRules.uc +++ b/sources/ServerRealm/API/Unreal/GameRulesAPI/AcediaGameRules.uc @@ -29,7 +29,7 @@ var private GameRules_OnNetDamage_Signal onNetDamage; var private GameRules_OnPreventDeath_Signal onPreventDeath; var private GameRules_OnScoreKill_Signal onScoreKill; -public final function Initialize(UnrealService service) +public final function Initialize(ServerUnrealService service) { if (service == none) { return; diff --git a/sources/ServerRealm/API/Unreal/GameRulesAPI/GameRulesAPI.uc b/sources/ServerRealm/API/Unreal/GameRulesAPI/GameRulesAPI.uc index 9e32d62..243e8b3 100644 --- a/sources/ServerRealm/API/Unreal/GameRulesAPI/GameRulesAPI.uc +++ b/sources/ServerRealm/API/Unreal/GameRulesAPI/GameRulesAPI.uc @@ -31,10 +31,10 @@ var private LoggerAPI.Definition errGameRulesUnknown; public function GameRules_OnFindPlayerStart_Slot OnFindPlayerStart( AcediaObject receiver) { - local Signal signal; - local UnrealService service; + local Signal signal; + local ServerUnrealService service; - service = UnrealService(class'UnrealService'.static.Require()); + service = ServerUnrealService(class'ServerUnrealService'.static.Require()); TryAddingGameRules(service); signal = service.GetSignal(class'GameRules_OnFindPlayerStart_Signal'); return GameRules_OnFindPlayerStart_Slot(signal.NewSlot(receiver)); @@ -44,10 +44,10 @@ public function GameRules_OnFindPlayerStart_Slot OnFindPlayerStart( public function GameRules_OnHandleRestartGame_Slot OnHandleRestartGame( AcediaObject receiver) { - local Signal signal; - local UnrealService service; + local Signal signal; + local ServerUnrealService service; - service = UnrealService(class'UnrealService'.static.Require()); + service = ServerUnrealService(class'ServerUnrealService'.static.Require()); TryAddingGameRules(service); signal = service.GetSignal(class'GameRules_OnHandleRestartGame_Signal'); return GameRules_OnHandleRestartGame_Slot(signal.NewSlot(receiver)); @@ -57,10 +57,10 @@ public function GameRules_OnHandleRestartGame_Slot OnHandleRestartGame( public function GameRules_OnCheckEndGame_Slot OnCheckEndGame( AcediaObject receiver) { - local Signal signal; - local UnrealService service; + local Signal signal; + local ServerUnrealService service; - service = UnrealService(class'UnrealService'.static.Require()); + service = ServerUnrealService(class'ServerUnrealService'.static.Require()); TryAddingGameRules(service); signal = service.GetSignal(class'GameRules_OnCheckEndGame_Signal'); return GameRules_OnCheckEndGame_Slot(signal.NewSlot(receiver)); @@ -70,10 +70,10 @@ public function GameRules_OnCheckEndGame_Slot OnCheckEndGame( public function GameRules_OnCheckScore_Slot OnCheckScore( AcediaObject receiver) { - local Signal signal; - local UnrealService service; + local Signal signal; + local ServerUnrealService service; - service = UnrealService(class'UnrealService'.static.Require()); + service = ServerUnrealService(class'ServerUnrealService'.static.Require()); TryAddingGameRules(service); signal = service.GetSignal(class'GameRules_OnCheckScore_Signal'); return GameRules_OnCheckScore_Slot(signal.NewSlot(receiver)); @@ -83,10 +83,10 @@ public function GameRules_OnCheckScore_Slot OnCheckScore( public function GameRules_OnOverridePickupQuery_Slot OnOverridePickupQuery(AcediaObject receiver) { - local Signal signal; - local UnrealService service; + local Signal signal; + local ServerUnrealService service; - service = UnrealService(class'UnrealService'.static.Require()); + service = ServerUnrealService(class'ServerUnrealService'.static.Require()); TryAddingGameRules(service); signal = service.GetSignal(class'GameRules_OnOverridePickupQuery_Signal'); return GameRules_OnOverridePickupQuery_Slot(signal.NewSlot(receiver)); @@ -95,10 +95,10 @@ public function GameRules_OnOverridePickupQuery_Slot /* SIGNAL */ public function GameRules_OnNetDamage_Slot OnNetDamage(AcediaObject receiver) { - local Signal signal; - local UnrealService service; + local Signal signal; + local ServerUnrealService service; - service = UnrealService(class'UnrealService'.static.Require()); + service = ServerUnrealService(class'ServerUnrealService'.static.Require()); TryAddingGameRules(service); signal = service.GetSignal(class'GameRules_OnNetDamage_Signal'); return GameRules_OnNetDamage_Slot(signal.NewSlot(receiver)); @@ -108,10 +108,10 @@ public function GameRules_OnNetDamage_Slot OnNetDamage(AcediaObject receiver) public function GameRules_OnPreventDeath_Slot OnPreventDeath( AcediaObject receiver) { - local Signal signal; - local UnrealService service; + local Signal signal; + local ServerUnrealService service; - service = UnrealService(class'UnrealService'.static.Require()); + service = ServerUnrealService(class'ServerUnrealService'.static.Require()); TryAddingGameRules(service); signal = service.GetSignal(class'GameRules_OnPreventDeath_Signal'); return GameRules_OnPreventDeath_Slot(signal.NewSlot(receiver)); @@ -121,10 +121,10 @@ public function GameRules_OnPreventDeath_Slot OnPreventDeath( public function GameRules_OnScoreKill_Slot OnScoreKill( AcediaObject receiver) { - local Signal signal; - local UnrealService service; + local Signal signal; + local ServerUnrealService service; - service = UnrealService(class'UnrealService'.static.Require()); + service = ServerUnrealService(class'ServerUnrealService'.static.Require()); TryAddingGameRules(service); signal = service.GetSignal(class'GameRules_OnScoreKill_Signal'); return GameRules_OnScoreKill_Slot(signal.NewSlot(receiver)); @@ -134,10 +134,10 @@ public function GameRules_OnScoreKill_Slot OnScoreKill( * Method that attempts to inject Acedia's `AcediaGameRules`, while * respecting settings inside `class'SideEffects'`. * - * @param service Reference to `UnrealService` to exchange signal and slots - * classes with. + * @param service Reference to `ServerUnrealService` to exchange signal and + * slots classes with. */ -protected function TryAddingGameRules(UnrealService service) +protected function TryAddingGameRules(ServerUnrealService service) { local AcediaGameRules gameRules; local GameRulesSideEffect sideEffect; diff --git a/sources/ServerRealm/API/Unreal/MutatorsAPI/MutatorAPI.uc b/sources/ServerRealm/API/Unreal/MutatorsAPI/MutatorAPI.uc index c115faf..d0645b7 100644 --- a/sources/ServerRealm/API/Unreal/MutatorsAPI/MutatorAPI.uc +++ b/sources/ServerRealm/API/Unreal/MutatorsAPI/MutatorAPI.uc @@ -23,10 +23,10 @@ class MutatorAPI extends MutatorAPIBase; public function Mutator_OnCheckReplacement_Slot OnCheckReplacement( AcediaObject receiver) { - local Signal signal; - local UnrealService service; + local Signal signal; + local ServerUnrealService service; - service = UnrealService(class'UnrealService'.static.Require()); + service = ServerUnrealService(class'ServerUnrealService'.static.Require()); signal = service.GetSignal(class'Mutator_OnCheckReplacement_Signal'); return Mutator_OnCheckReplacement_Slot(signal.NewSlot(receiver)); } @@ -35,10 +35,10 @@ public function Mutator_OnCheckReplacement_Slot OnCheckReplacement( public function Mutator_OnMutate_Slot OnMutate( AcediaObject receiver) { - local Signal signal; - local UnrealService service; + local Signal signal; + local ServerUnrealService service; - service = UnrealService(class'UnrealService'.static.Require()); + service = ServerUnrealService(class'ServerUnrealService'.static.Require()); signal = service.GetSignal(class'Mutator_OnMutate_Signal'); return Mutator_OnMutate_Slot(signal.NewSlot(receiver)); } @@ -47,10 +47,10 @@ public function Mutator_OnMutate_Slot OnMutate( public function Mutator_OnModifyLogin_Slot OnModifyLogin( AcediaObject receiver) { - local Signal signal; - local UnrealService service; + local Signal signal; + local ServerUnrealService service; - service = UnrealService(class'UnrealService'.static.Require()); + service = ServerUnrealService(class'ServerUnrealService'.static.Require()); signal = service.GetSignal(class'Mutator_OnModifyLogin_Signal'); return Mutator_OnModifyLogin_Slot(signal.NewSlot(receiver)); } diff --git a/sources/ServerRealm/API/Unreal/ServerUnrealAPI.uc b/sources/ServerRealm/API/Unreal/ServerUnrealAPI.uc index 2fb8889..f7bf8d0 100644 --- a/sources/ServerRealm/API/Unreal/ServerUnrealAPI.uc +++ b/sources/ServerRealm/API/Unreal/ServerUnrealAPI.uc @@ -28,9 +28,10 @@ protected function Constructor() protected function HandleShutdown() { - local UnrealService service; + local ServerUnrealService service; - service = UnrealService(class'UnrealService'.static.GetInstance()); + service = + ServerUnrealService(class'ServerUnrealService'.static.GetInstance()); // This has to clean up anything we've added if (service != none) { service.Destroy(); @@ -41,10 +42,10 @@ protected function HandleShutdown() public function Unreal_OnTick_Slot OnTick( AcediaObject receiver) { - local Signal signal; - local UnrealService service; + local Signal signal; + local ServerUnrealService service; - service = UnrealService(class'UnrealService'.static.Require()); + service = ServerUnrealService(class'ServerUnrealService'.static.Require()); signal = service.GetSignal(class'Unreal_OnTick_Signal'); return Unreal_OnTick_Slot(signal.NewSlot(receiver)); } @@ -61,7 +62,9 @@ public function SimpleSlot OnDestructionFor( // Failing to spawn this actor without any collision flags is considered // completely unexpected and grounds for fatal failure on Acedia' part - stalker = ActorStalker(_.memory.Allocate(class'ActorStalker')); + stalker = ActorStalker(class'ServerLevelCore'.static + .GetInstance() + .Allocate(class'ActorStalker')); if (stalker == none) { _.logger.Auto(fatalNoStalker); @@ -113,12 +116,6 @@ public function Actor FindActorInstance(class classToFind) return result; } -public function PlayerController GetLocalPlayer() -{ - return class'ServerLevelCore'.static.GetInstance().level - .GetLocalPlayerController(); -} - public function NativeActorRef ActorRef(optional Actor value) { local NativeActorRef ref; diff --git a/sources/ServerRealm/API/Unreal/ServerUnrealAPIBase.uc b/sources/ServerRealm/API/Unreal/ServerUnrealAPIBase.uc index 8c4c80a..5c13cfb 100644 --- a/sources/ServerRealm/API/Unreal/ServerUnrealAPIBase.uc +++ b/sources/ServerRealm/API/Unreal/ServerUnrealAPIBase.uc @@ -1,7 +1,7 @@ /** * Low-level API that provides set of utility methods for working with * unreal script classes. - * Copyright 2021-2022 Anton Tarasenko + * Copyright 2022 Anton Tarasenko *------------------------------------------------------------------------------ * This file is part of Acedia. * @@ -18,7 +18,7 @@ * You should have received a copy of the GNU General Public License * along with Acedia. If not, see . */ -class ServerUnrealAPIBase extends AcediaObject +class ServerUnrealAPIBase extends UnrealAPIBase abstract; var protected bool initialized; @@ -47,122 +47,6 @@ public function Initialize(class adapterClass) adapterClass.default.serverInventoryAPIClass)); } -/** - * Signal that will be emitted every tick. - * - * [Signature] - * void (float delta, float dilationCoefficient) - * - * @param delta In-game time in seconds that has passed since - * the last tick. To obtain real time passed from the last tick divide - * `delta` by `dilationCoefficient`. - * @param dilationCoefficient How fast is in-game time flow compared to - * the real world's one? `2` means twice as fast and - * `0.5` means twice as slow. - */ -/* SIGNAL */ -public function Unreal_OnTick_Slot OnTick(AcediaObject receiver); - -/** - * Signal that will be emitted when a passed `targetToStalk` is destroyed. - * - * Passed parameter `targetToStalk` cannot be `none`, otherwise `none` will be - * returned instead of a valid slot. - * - * @param receiver Specify a receiver like for any other signal. - * @param targetToStalk Actor whose destruction we want to detect. - * - * [Signature] - * void () - */ -/* SIGNAL */ -public function SimpleSlot OnDestructionFor( - AcediaObject receiver, - Actor targetToStalk); - -/** - * Returns current game's `LevelInfo`. Useful because `level` variable - * is not defined inside objects. - * - * @return `LevelInfo` instance for the current game. Guaranteed to - * not be `none`. - */ -public function LevelInfo GetLevel(); - -/** - * Returns current game's `GameReplicationInfo`. Useful because `level.game` - * is not accessible inside objects. - * - * @return `GameReplicationInfo` instance for the current game. Guaranteed to - * not be `none`. - */ -public function GameReplicationInfo GetGameRI(); - -/** - * Returns current game's `GameReplicationInfo` as `KFGameReplicationInfo`. - * Useful because `level.game` is not accessible inside objects and because it - * auto converts game replication info type to `KFGameReplicationInfo`, which - * virtually all mods for killing floor use (by itself or as a base class). - * - * @return `KFGameReplicationInfo` instance for the current game. - * Can be `none` only if game was modded to run a `KFGameReplicationInfo` - * not derived from `KFGameType`. - */ -public function KFGameReplicationInfo GetKFGameRI(); - -/** - * Returns current game's `GameInfo`. Useful because `level.game` is not - * accessible inside objects. - * - * @return `GameInfo` instance for the current game. Guaranteed to - * not be `none`. - */ -public function GameInfo GetGameType(); - -/** - * Returns current game's `GameInfo` as `KFGameType`. Useful because - * `level.game` is not accessible inside objects and because it auto converts - * game type to `KFGameType`, which virtually all mods for killing floor use - * (by itself or as a base class). - * - * @return `KFGameType` instance for the current game. Can be `none` only if - * game was modded to run a `GameInfo` not derived from `KFGameType`. - */ -public function KFGameType GetKFGameType(); - -/** - * Searches all `Actor`s on the level for an instance of specific class and - * returns it. - * - * @param classToFind Class we want to find an instance of. - * @result A pre-existing instance of class `classToFind`, `none` if - * no instances exist at the moment of this method's call. - */ -public function Actor FindActorInstance(class classToFind); - -/** - * Returns current local player's `Controller`. Useful because `level` - * is not accessible inside objects. - * - * @return `PlayerController` instance for the local player. `none` iff run on - * dedicated servers. - */ -public function PlayerController GetLocalPlayer(); - -/** - * Creates reference object to store a `Actor` value. - * - * Such references are necessary, since `Actor` references aren't safe to store - * inside non-actor `Object`s. To allow that Acedia uses a round about way of - * storing all `Actor` references in a special `Actor`, while allowing to refer - * to them via `NativeActorRef` (also `ActorRef` for `AcediaActor`s - * specifically). - * - * @param value Initial value to store in reference. - * @return `NativeActorRef`, containing `value`. - */ -public function NativeActorRef ActorRef(optional Actor value); - defaultproperties { } \ No newline at end of file diff --git a/sources/ServerRealm/API/Unreal/UnrealService.uc b/sources/ServerRealm/API/Unreal/ServerUnrealService.uc similarity index 98% rename from sources/ServerRealm/API/Unreal/UnrealService.uc rename to sources/ServerRealm/API/Unreal/ServerUnrealService.uc index 0f199d0..2bd1a04 100644 --- a/sources/ServerRealm/API/Unreal/UnrealService.uc +++ b/sources/ServerRealm/API/Unreal/ServerUnrealService.uc @@ -18,7 +18,7 @@ * You should have received a copy of the GNU General Public License * along with Acedia. If not, see . */ -class UnrealService extends Service; +class ServerUnrealService extends Service; struct SignalRecord {