isle-portable/LEGO1/omni/src/notify/mxnotificationmanager.cpp
foxtacles 569c8b467b
Separate extensions (#18)
* WIP

* WIP

* Make camera the single source of truth for broadcast state

Remove redundant local copies of walkAnimId, idleAnimId, and
displayActorIndex from NetworkManager. BroadcastLocalState now reads
these from the camera's Controller, eliminating dual-copy sync issues.

Additional cleanup:
- Early-return on null cam in SendEmote/HandleCustomize for clarity
- Only consume camera-dependent pending requests when cam is available
- Move local name bubble creation from BroadcastLocalState to Tickle
- Remove dead NetworkManager::SetDisplayActorIndex method

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix clang format

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 23:12:07 +01:00

207 lines
4.6 KiB
C++

#include "mxnotificationmanager.h"
#include "compat.h"
#include "decomp.h"
#include "extensions/siloader.h"
#include "mxautolock.h"
#include "mxmisc.h"
#include "mxnotificationparam.h"
#include "mxparam.h"
#include "mxticklemanager.h"
#include "mxtypes.h"
DECOMP_SIZE_ASSERT(MxNotification, 0x08);
DECOMP_SIZE_ASSERT(MxNotificationManager, 0x40);
using namespace Extensions;
// FUNCTION: LEGO1 0x100ac220
MxNotification::MxNotification(MxCore* p_target, const MxNotificationParam& p_param)
{
m_target = p_target;
m_param = p_param.Clone();
}
// FUNCTION: LEGO1 0x100ac240
MxNotification::~MxNotification()
{
delete m_param;
}
// FUNCTION: LEGO1 0x100ac250
// FUNCTION: BETA10 0x10125805
MxNotificationManager::MxNotificationManager() : MxCore(), m_lock(), m_listenerIds()
{
m_unk0x2c = 0;
m_queue = NULL;
m_active = TRUE;
m_sendList = NULL;
}
// FUNCTION: LEGO1 0x100ac450
MxNotificationManager::~MxNotificationManager()
{
AUTOLOCK(m_lock);
Tickle();
delete m_queue;
m_queue = NULL;
TickleManager()->UnregisterClient(this);
}
// FUNCTION: LEGO1 0x100ac600
MxResult MxNotificationManager::Create(MxU32 p_frequencyMS, MxBool p_createThread)
{
MxResult result = SUCCESS;
m_queue = new MxNotificationPtrList();
if (m_queue == NULL) {
result = FAILURE;
}
else {
TickleManager()->RegisterClient(this, 10);
}
return result;
}
// FUNCTION: LEGO1 0x100ac6c0
// FUNCTION: BETA10 0x10125b57
MxResult MxNotificationManager::Send(MxCore* p_listener, const MxNotificationParam& p_param)
{
AUTOLOCK(m_lock);
if (!m_active) {
return FAILURE;
}
MxIdList::iterator it = find(m_listenerIds.begin(), m_listenerIds.end(), p_listener->GetId());
if (it == m_listenerIds.end()) {
return FAILURE;
}
MxNotification* notif = new MxNotification(p_listener, p_param);
if (notif != NULL) {
m_queue->push_back(notif);
return SUCCESS;
}
return FAILURE;
}
// FUNCTION: LEGO1 0x100ac800
MxResult MxNotificationManager::Tickle()
{
m_sendList = new MxNotificationPtrList();
if (m_sendList == NULL) {
return FAILURE;
}
else {
{
AUTOLOCK(m_lock);
MxNotificationPtrList* temp1 = m_queue;
MxNotificationPtrList* temp2 = m_sendList;
m_queue = temp2;
m_sendList = temp1;
}
while (m_sendList->size() != 0) {
MxNotification* notif = m_sendList->front();
m_sendList->pop_front();
if (notif->GetParam()->GetNotification() == c_notificationEndAction) {
Extension<SiLoaderExt>::Call(SI::HandleEndAction, (MxEndActionNotificationParam&) *notif->GetParam());
}
notif->GetTarget()->Notify(*notif->GetParam());
delete notif;
}
delete m_sendList;
m_sendList = NULL;
return SUCCESS;
}
}
// FUNCTION: LEGO1 0x100ac990
void MxNotificationManager::FlushPending(MxCore* p_listener)
{
MxNotificationPtrList pending;
MxNotification* notif;
{
AUTOLOCK(m_lock);
// Find all notifications from, and addressed to, p_listener.
if (m_sendList != NULL) {
MxNotificationPtrList::iterator it = m_sendList->begin();
while (it != m_sendList->end()) {
notif = *it;
if (notif->GetTarget()->GetId() == p_listener->GetId() ||
(notif->GetParam()->GetSender() && notif->GetParam()->GetSender()->GetId() == p_listener->GetId()
)) {
m_sendList->erase(it++);
pending.push_back(notif);
}
else {
it++;
}
}
}
MxNotificationPtrList::iterator it = m_queue->begin();
while (it != m_queue->end()) {
notif = *it;
if (notif->GetTarget()->GetId() == p_listener->GetId() ||
(notif->GetParam()->GetSender() && notif->GetParam()->GetSender()->GetId() == p_listener->GetId())) {
m_queue->erase(it++);
pending.push_back(notif);
}
else {
it++;
}
}
}
// Deliver those notifications.
while (pending.size() != 0) {
notif = pending.front();
pending.pop_front();
if (notif->GetParam()->GetNotification() == c_notificationEndAction) {
Extension<SiLoaderExt>::Call(SI::HandleEndAction, (MxEndActionNotificationParam&) *notif->GetParam());
}
notif->GetTarget()->Notify(*notif->GetParam());
delete notif;
}
}
// FUNCTION: LEGO1 0x100acd20
// STUB: BETA10 0x1012666a
void MxNotificationManager::Register(MxCore* p_listener)
{
AUTOLOCK(m_lock);
MxIdList::iterator it = find(m_listenerIds.begin(), m_listenerIds.end(), p_listener->GetId());
if (it != m_listenerIds.end()) {
return;
}
m_listenerIds.push_back(p_listener->GetId());
}
// FUNCTION: LEGO1 0x100acdf0
// FUNCTION: BETA10 0x10126785
void MxNotificationManager::Unregister(MxCore* p_listener)
{
AUTOLOCK(m_lock);
MxIdList::iterator it = find(m_listenerIds.begin(), m_listenerIds.end(), p_listener->GetId());
if (it != m_listenerIds.end()) {
m_listenerIds.erase(it);
FlushPending(p_listener);
}
}