Browse Source

Refactor GameRulesAPI to only add rule when needed

Now `AcediaGameRules` are only added when Acedia actually needs their
events.
AcediaCore now also outputs console message about adding them and
registers a side effect.
pull/8/head
Anton Tarasenko 2 years ago
parent
commit
44c2d8700e
  1. 2
      sources/Gameplay/BaseClasses/Frontend/Health/AHealthComponent.uc
  2. 23
      sources/Gameplay/KF1Frontend/Health/KF1_HealthComponent.uc
  3. 40
      sources/Unreal/GameRulesAPI/GameRulesAPI.uc
  4. 43
      sources/Unreal/GameRulesAPI/GameRulesSideEffect.uc
  5. 36
      sources/Unreal/UnrealService.uc

2
sources/Gameplay/BaseClasses/Frontend/Health/AHealthComponent.uc

@ -54,7 +54,7 @@ protected function Finalizer()
* as a result of the damage dealt.
*/
/* SIGNAL */
public final function Health_OnDamage_Slot OnDamage(AcediaObject receiver)
public function Health_OnDamage_Slot OnDamage(AcediaObject receiver)
{
return Health_OnDamage_Slot(onDamageSignal.NewSlot(receiver));
}

23
sources/Gameplay/KF1Frontend/Health/KF1_HealthComponent.uc

@ -21,6 +21,8 @@ class KF1_HealthComponent extends AHealthComponent
dependson(ConnectionService)
config(AcediaSystem);
var private bool connectedToGameRules;
/**
* Unfortunately, thanks to the TWI's code, there's no way to catch events
* of when certain kinds of damage are dealt: from welder, bloat's bile and
@ -58,7 +60,6 @@ public function PseudoConstructor()
{
local LevelCore core;
_.unreal.gameRules.OnNetDamage(self).connect = OnNetDamageHandler;
if (!replaceBloatAndSirenDamageTypes) {
return;
}
@ -67,8 +68,6 @@ public function PseudoConstructor()
if (core != none)
{
ReplaceDamageTypes(core);
// Fixes achievements
_.unreal.gameRules.OnScoreKill(self).connect = UpdateBileAchievement;
core.OnShutdown(self).connect = RestoreDamageTypes;
}
else {
@ -84,6 +83,24 @@ protected function Finalizer()
if (replaceBloatAndSirenDamageTypes) {
RestoreDamageTypes();
}
connectedToGameRules = false;
}
public function Health_OnDamage_Slot OnDamage(AcediaObject receiver)
{
TryConnectToGameRules();
return super.OnDamage(receiver);
}
private final function TryConnectToGameRules()
{
if (connectedToGameRules) {
return;
}
connectedToGameRules = true;
_.unreal.gameRules.OnNetDamage(self).connect = OnNetDamageHandler;
// Fixes achievements
_.unreal.gameRules.OnScoreKill(self).connect = UpdateBileAchievement;
}
private final function ReplaceDamageTypes(LevelCore core)

40
sources/Unreal/GameRulesAPI/GameRulesAPI.uc

@ -20,6 +20,8 @@
*/
class GameRulesAPI extends AcediaObject;
var private LoggerAPI.Definition infoAddedGameRules;
/**
* Called when game decides on a player's spawn point. If a `NavigationPoint`
* is returned, signal propagation will be interrupted and returned value will
@ -43,7 +45,9 @@ public final function GameRules_OnFindPlayerStart_Slot OnFindPlayerStart(
{
local Signal signal;
local UnrealService service;
service = UnrealService(class'UnrealService'.static.Require());
TryAddingGameRules(service);
signal = service.GetSignal(class'GameRules_OnFindPlayerStart_Signal');
return GameRules_OnFindPlayerStart_Slot(signal.NewSlot(receiver));
}
@ -67,7 +71,9 @@ public final function GameRules_OnHandleRestartGame_Slot OnHandleRestartGame(
{
local Signal signal;
local UnrealService service;
service = UnrealService(class'UnrealService'.static.Require());
TryAddingGameRules(service);
signal = service.GetSignal(class'GameRules_OnHandleRestartGame_Signal');
return GameRules_OnHandleRestartGame_Slot(signal.NewSlot(receiver));
}
@ -93,7 +99,9 @@ public final function GameRules_OnCheckEndGame_Slot OnCheckEndGame(
{
local Signal signal;
local UnrealService service;
service = UnrealService(class'UnrealService'.static.Require());
TryAddingGameRules(service);
signal = service.GetSignal(class'GameRules_OnCheckEndGame_Signal');
return GameRules_OnCheckEndGame_Slot(signal.NewSlot(receiver));
}
@ -120,7 +128,9 @@ public final function GameRules_OnCheckScore_Slot OnCheckScore(
{
local Signal signal;
local UnrealService service;
service = UnrealService(class'UnrealService'.static.Require());
TryAddingGameRules(service);
signal = service.GetSignal(class'GameRules_OnCheckScore_Signal');
return GameRules_OnCheckScore_Slot(signal.NewSlot(receiver));
}
@ -151,7 +161,9 @@ public final function GameRules_OnOverridePickupQuery_Slot
{
local Signal signal;
local UnrealService service;
service = UnrealService(class'UnrealService'.static.Require());
TryAddingGameRules(service);
signal = service.GetSignal(class'GameRules_OnOverridePickupQuery_Signal');
return GameRules_OnOverridePickupQuery_Slot(signal.NewSlot(receiver));
}
@ -192,7 +204,9 @@ public final function GameRules_OnNetDamage_Slot OnNetDamage(
{
local Signal signal;
local UnrealService service;
service = UnrealService(class'UnrealService'.static.Require());
TryAddingGameRules(service);
signal = service.GetSignal(class'GameRules_OnNetDamage_Signal');
return GameRules_OnNetDamage_Slot(signal.NewSlot(receiver));
}
@ -224,7 +238,9 @@ public final function GameRules_OnPreventDeath_Slot OnPreventDeath(
{
local Signal signal;
local UnrealService service;
service = UnrealService(class'UnrealService'.static.Require());
TryAddingGameRules(service);
signal = service.GetSignal(class'GameRules_OnPreventDeath_Signal');
return GameRules_OnPreventDeath_Slot(signal.NewSlot(receiver));
}
@ -244,11 +260,34 @@ public final function GameRules_OnScoreKill_Slot OnScoreKill(
{
local Signal signal;
local UnrealService service;
service = UnrealService(class'UnrealService'.static.Require());
TryAddingGameRules(service);
signal = service.GetSignal(class'GameRules_OnScoreKill_Signal');
return GameRules_OnScoreKill_Slot(signal.NewSlot(receiver));
}
private final function TryAddingGameRules(UnrealService service)
{
local AcediaGameRules gameRules;
local GameRulesSideEffect sideEffect;
if (AreAdded(class'AcediaGameRules')) {
return;
}
gameRules = AcediaGameRules(Add(class'AcediaGameRules'));
if (gameRules != none)
{
gameRules.Initialize(service);
sideEffect =
GameRulesSideEffect(_.memory.Allocate(class'GameRulesSideEffect'));
sideEffect.Initialize();
_server.sideEffects.Add(sideEffect);
_.memory.Free(sideEffect);
_.logger.Auto(infoAddedGameRules);
}
}
/**
* Adds new `GameRules` class to the current `GameInfo`.
* Does nothing if given `GameRules` class was already added before.
@ -351,4 +390,5 @@ public final function bool AreAdded(
defaultproperties
{
infoAddedGameRules = (l=LOG_Info,m="Added AcediaCore's `AcediaGameRules`.")
}

43
sources/Unreal/GameRulesAPI/GameRulesSideEffect.uc

@ -0,0 +1,43 @@
/**
* Object representing a side effect introduced into the game/server.
* Side effects in Acedia refer to changes that aren't a part of mod's main
* functionality, but rather something necessary to make that functionality
* possible that might also affect how other mods work.
* This is a simple data container that is meant to describe relevant
* changes to the human user.
* 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 <https://www.gnu.org/licenses/>.
*/
class GameRulesSideEffect extends SideEffect;
public final function Initialize()
{
sideEffectName =
_.text.FromString("AcediaCore's `AcediaGameRules` added");
sideEffectDescription =
_.text.FromString("`GameRule`s is one of the main ways to get notified"
@ "about various gameplay-related events in Unreal Engine."
@ "Of course AcediaCore would require handling some of those events,"
@ "depending on how it's used.");
sideEffectPackage = _.text.FromString("AcediaCore");
sideEffectSource = _.text.FromString("UnrealAPI");
sideEffectStatus = _.text.FromFormattedString("{$TextPositive active}");
}
defaultproperties
{
}

36
sources/Unreal/UnrealService.uc

@ -27,24 +27,27 @@ struct SignalRecord
};
var private array<SignalRecord> serviceSignals;
var private Unreal_OnTick_Signal onTickSignal;
var private AcediaGameRules gameRules;
protected function OnLaunch()
{
CreateSignals();
// Create game rules
gameRules = AcediaGameRules(_.unreal.gameRules.Add(class'AcediaGameRules'));
if (gameRules != none) {
gameRules.Initialize(self);
local int i;
onTickSignal = Unreal_OnTick_Signal(
_.memory.Allocate(class'Unreal_OnTick_Signal'));
for (i = 0; i < serviceSignals.length; i += 1)
{
if (serviceSignals[i].instance != none) continue;
if (serviceSignals[i].signalClass == none) continue;
serviceSignals[i].instance =
Signal(_.memory.Allocate(serviceSignals[i].signalClass));
}
}
protected function OnShutdown()
{
local int i;
if (gameRules != none) {
gameRules.Cleanup();
}
_.unreal.broadcasts.Remove(class'BroadcastEventsObserver');
_.unreal.gameRules.Remove(class'AcediaGameRules');
for (i = 0; i < serviceSignals.length; i += 1) {
@ -55,21 +58,6 @@ protected function OnShutdown()
onTickSignal = none;
}
private final function CreateSignals()
{
local int i;
onTickSignal = Unreal_OnTick_Signal(
_.memory.Allocate(class'Unreal_OnTick_Signal'));
for (i = 0; i < serviceSignals.length; i += 1)
{
if (serviceSignals[i].instance != none) continue;
if (serviceSignals[i].signalClass == none) continue;
serviceSignals[i].instance =
Signal(_.memory.Allocate(serviceSignals[i].signalClass));
}
}
public final function Signal GetSignal(class<Signal> requiredClass)
{
local int i;

Loading…
Cancel
Save