Browse Source

Refactor how `BroadcastAPI` injects its handler

This patch changes AcediaCore to only inject `BroadcastEventsObserver`
when its events are actually needed.
Other changes are making this change produce a log entry and adding a
relevant `SideEffect` that describes this change.
pull/8/head
Anton Tarasenko 2 years ago
parent
commit
4f23c616f1
  1. 6
      sources/BaseRealm/Global.uc
  2. 17
      sources/Chat/ChatAPI.uc
  3. 4
      sources/CoreRealm/API/SideEffects/SideEffectAPI.uc
  4. 51
      sources/Unreal/BroadcastsAPI/BroadcastAPI.uc
  5. 65
      sources/Unreal/BroadcastsAPI/BroadcastSideEffect.uc
  6. 8
      sources/Unreal/UnrealService.uc

6
sources/BaseRealm/Global.uc

@ -66,13 +66,13 @@ protected function Initialize()
box = BoxAPI(memory.Allocate(class'BoxAPI'));
text = TextAPI(memory.Allocate(class'TextAPI'));
collections = CollectionsAPI(memory.Allocate(class'CollectionsAPI'));
unreal = ServerUnrealAPI(memory.Allocate(class'ServerUnrealAPI'));
time = TimeAPI(memory.Allocate(class'TimeAPI'));
logger = LoggerAPI(memory.Allocate(class'LoggerAPI'));
color = ColorAPI(memory.Allocate(class'ColorAPI'));
alias = AliasesAPI(memory.Allocate(class'AliasesAPI'));
unreal = ServerUnrealAPI(memory.Allocate(class'ServerUnrealAPI'));
time = TimeAPI(memory.Allocate(class'TimeAPI'));
console = ConsoleAPI(memory.Allocate(class'ConsoleAPI'));
chat = ChatAPI(memory.Allocate(class'ChatAPI'));
color = ColorAPI(memory.Allocate(class'ColorAPI'));
users = UserAPI(memory.Allocate(class'UserAPI'));
players = PlayersAPI(memory.Allocate(class'PlayersAPI'));
json = JSONAPI(memory.Allocate(class'JSONAPI'));

17
sources/Chat/ChatAPI.uc

@ -19,6 +19,8 @@
*/
class ChatAPI extends AcediaObject;
var protected bool connectedToBroadcastAPI;
var protected ChatAPI_OnMessage_Signal onMessageSignal;
var protected ChatAPI_OnMessageFor_Signal onMessageForSignal;
@ -28,8 +30,6 @@ protected function Constructor()
_.memory.Allocate(class'ChatAPI_OnMessage_Signal'));
onMessageForSignal = ChatAPI_OnMessageFor_Signal(
_.memory.Allocate(class'ChatAPI_OnMessageFor_Signal'));
_.unreal.broadcasts.OnHandleText(self).connect = HandleText;
_.unreal.broadcasts.OnHandleTextFor(self).connect = HandleTextFor;
}
protected function Finalizer()
@ -40,6 +40,17 @@ protected function Finalizer()
onMessageForSignal = none;
_.unreal.broadcasts.OnHandleText(self).Disconnect();
_.unreal.broadcasts.OnHandleTextFor(self).Disconnect();
connectedToBroadcastAPI = false;
}
private final function TryConnectingBroadcastSignals()
{
if (connectedToBroadcastAPI) {
return;
}
connectedToBroadcastAPI = true;
_.unreal.broadcasts.OnHandleText(self).connect = HandleText;
_.unreal.broadcasts.OnHandleTextFor(self).connect = HandleTextFor;
}
/**
@ -67,6 +78,7 @@ protected function Finalizer()
public function ChatAPI_OnMessage_Slot OnMessage(
AcediaObject receiver)
{
TryConnectingBroadcastSignals();
return ChatAPI_OnMessage_Slot(onMessageSignal.NewSlot(receiver));
}
@ -97,6 +109,7 @@ public function ChatAPI_OnMessage_Slot OnMessage(
public function ChatAPI_OnMessageFor_Slot OnMessageFor(
AcediaObject receiver)
{
TryConnectingBroadcastSignals();
return ChatAPI_OnMessageFor_Slot(onMessageForSignal.NewSlot(receiver));
}

4
sources/CoreRealm/API/SideEffects/SideEffectAPI.uc

@ -103,7 +103,7 @@ public final function array<SideEffect> GetFromPackage(BaseText packageName)
* active side effect. Must not be `none`.
* @return `true` if new side effect was added and `false` otherwise.
*/
public final function bool AddSideEffect(SideEffect newSideEffect)
public final function bool Add(SideEffect newSideEffect)
{
local int i;
@ -130,7 +130,7 @@ public final function bool AddSideEffect(SideEffect newSideEffect)
* and `false` otherise (even if there was no side effect of specified
* class to begin with).
*/
public final function bool RemoveSideEffectClass(
public final function bool RemoveClass(
class<SideEffect> sideEffectClass)
{
local int i;

51
sources/Unreal/BroadcastsAPI/BroadcastAPI.uc

@ -57,6 +57,8 @@ struct LocalizedMessage
var Object relatedObject;
};
var private LoggerAPI.Definition infoInjectedBroadcastEventsObserver;
/**
* Called before text message is sent to any player, during the check for
* whether it is at all allowed to be broadcasted. Corresponds to
@ -87,7 +89,9 @@ public final function Broadcast_OnBroadcastCheck_Slot OnBroadcastCheck(
{
local Signal signal;
local UnrealService service;
service = UnrealService(class'UnrealService'.static.Require());
TryInjectBroadcastHandler(service);
signal = service.GetSignal(class'Broadcast_OnBroadcastCheck_Signal');
return Broadcast_OnBroadcastCheck_Slot(signal.NewSlot(receiver));
}
@ -138,7 +142,9 @@ public final function Broadcast_OnHandleText_Slot OnHandleText(
{
local Signal signal;
local UnrealService service;
service = UnrealService(class'UnrealService'.static.Require());
TryInjectBroadcastHandler(service);
signal = service.GetSignal(class'Broadcast_OnHandleText_Signal');
return Broadcast_OnHandleText_Slot(signal.NewSlot(receiver));
}
@ -176,7 +182,9 @@ public final function Broadcast_OnHandleTextFor_Slot OnHandleTextFor(
{
local Signal signal;
local UnrealService service;
service = UnrealService(class'UnrealService'.static.Require());
TryInjectBroadcastHandler(service);
signal = service.GetSignal(class'Broadcast_OnHandleTextFor_Signal');
return Broadcast_OnHandleTextFor_Slot(signal.NewSlot(receiver));
}
@ -219,7 +227,9 @@ public final function Broadcast_OnHandleLocalized_Slot OnHandleLocalized(
{
local Signal signal;
local UnrealService service;
service = UnrealService(class'UnrealService'.static.Require());
TryInjectBroadcastHandler(service);
signal = service.GetSignal(class'Broadcast_OnHandleLocalized_Signal');
return Broadcast_OnHandleLocalized_Slot(signal.NewSlot(receiver));
}
@ -254,11 +264,51 @@ public final function Broadcast_OnHandleLocalizedFor_Slot OnHandleLocalizedFor(
{
local Signal signal;
local UnrealService service;
service = UnrealService(class'UnrealService'.static.Require());
TryInjectBroadcastHandler(service);
signal = service.GetSignal(class'Broadcast_OnHandleLocalizedFor_Signal');
return Broadcast_OnHandleLocalizedFor_Slot(signal.NewSlot(receiver));
}
private final function TryInjectBroadcastHandler(UnrealService service)
{
local InjectionLevel usedLevel;
local BroadcastSideEffect sideEffect;
local BroadcastEventsObserver broadcastObserver;
if (IsAdded(class'BroadcastEventsObserver')) {
return;
}
usedLevel = class'BroadcastEventsObserver'.default.usedInjectionLevel;
broadcastObserver = BroadcastEventsObserver(_.unreal.broadcasts.Add(
class'BroadcastEventsObserver', usedLevel));
if (broadcastObserver != none)
{
broadcastObserver.Initialize(service);
sideEffect =
BroadcastSideEffect(_.memory.Allocate(class'BroadcastSideEffect'));
sideEffect.Initialize(usedLevel);
_server.sideEffects.Add(sideEffect);
_.memory.Free(sideEffect);
_.logger
.Auto(infoInjectedBroadcastEventsObserver)
.Arg(InjectionLevelIntoText(usedLevel));
}
}
private final function Text InjectionLevelIntoText(
InjectionLevel injectionLevel)
{
if (injectionLevel == BHIJ_Root) {
return P("BHIJ_Root");
}
if (injectionLevel == BHIJ_Registered) {
return P("BHIJ_Registered");
}
return P("BHIJ_None");
}
/**
* Adds new `BroadcastHandler` class to the current `GameInfo`.
* Does nothing if given `BroadcastHandler` class was already added before.
@ -397,4 +447,5 @@ public final function bool IsAdded(class<BroadcastHandler> BHClassToFind)
defaultproperties
{
infoInjectedBroadcastEventsObserver = (l=LOG_Info,m="Injected AcediaCore's `BroadcastEventsObserver` with level `%1`.")
}

65
sources/Unreal/BroadcastsAPI/BroadcastSideEffect.uc

@ -0,0 +1,65 @@
/**
* 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 BroadcastSideEffect extends SideEffect
dependson(BroadcastAPI);
public final function Initialize(BroadcastAPI.InjectionLevel usedInjectionLevel)
{
sideEffectName =
_.text.FromString("AcediaCore's `BroadcastHandler` injected");
sideEffectDescription =
_.text.FromString("Handling text and localized messages between server"
@ "and clients requires AcediaCore to add its own `BroadcastHandler`"
@ "into their linked list."
@ "This is normal, since `BroadcastHandler` class was designed to allow"
@ "mods to do that, however, for full functionality Acedia requires to"
@ "inject it as the very first element (`BHIJ_Root` level injection),"
@ "since some of the events become otherwise inaccessible."
@ "This can result in incompatibility with other mods that are trying"
@ "to do the same."
@ "For that reason AcediaCore can also inject its `BroadcastHandler` as"
@ "`BHIJ_Registered`.");
sideEffectPackage = _.text.FromString("AcediaCore");
sideEffectSource = _.text.FromString("UnrealAPI");
if (usedInjectionLevel == BHIJ_Root)
{
sideEffectStatus =
_.text.FromFormattedString("{$TextPositive BHIJ_Root}");
}
else if (usedInjectionLevel == BHIJ_Registered)
{
sideEffectStatus =
_.text.FromFormattedString("{$TextNetutral BHIJ_Registered}");
}
else
{
sideEffectStatus =
_.text.FromFormattedString("{$TextNegative BHIJ_None (???)}");
}
}
defaultproperties
{
}

8
sources/Unreal/UnrealService.uc

@ -31,15 +31,7 @@ var private AcediaGameRules gameRules;
protected function OnLaunch()
{
local BroadcastEventsObserver broadcastObserver;
CreateSignals();
// Create broadcast handler
broadcastObserver = BroadcastEventsObserver(_.unreal.broadcasts.Add(
class'BroadcastEventsObserver',
class'BroadcastEventsObserver'.default.usedInjectionLevel));
if (broadcastObserver != none) {
broadcastObserver.Initialize(self);
}
// Create game rules
gameRules = AcediaGameRules(_.unreal.gameRules.Add(class'AcediaGameRules'));
if (gameRules != none) {

Loading…
Cancel
Save