Extract PlatformCallbacks interface and consolidate Emscripten files

Move all Emscripten-specific multiplayer code under platforms/emscripten/
and introduce an abstract PlatformCallbacks interface for outbound
notifications, mirroring the existing NetworkTransport pattern. This
removes all #ifdef __EMSCRIPTEN__ blocks from networkmanager.cpp.
This commit is contained in:
Christian Semmler 2026-03-02 15:46:37 -08:00
parent e47d2dab67
commit 0997610bad
No known key found for this signature in database
GPG Key ID: 086DAA1360BEEE5C
12 changed files with 128 additions and 62 deletions

View File

@ -535,9 +535,14 @@ if (ISLE_EXTENSIONS)
extensions/src/multiplayer/charactercloner.cpp
extensions/src/multiplayer/networkmanager.cpp
extensions/src/multiplayer/remoteplayer.cpp
extensions/src/multiplayer/websockettransport.cpp
extensions/src/multiplayer/worldstatesync.cpp
)
if(EMSCRIPTEN)
target_sources(lego1 PRIVATE
extensions/src/multiplayer/platforms/emscripten/websockettransport.cpp
extensions/src/multiplayer/platforms/emscripten/callbacks.cpp
)
endif()
endif()
if (ISLE_BUILD_APP)
@ -595,7 +600,7 @@ if (ISLE_BUILD_APP)
)
if(ISLE_EXTENSIONS)
target_sources(isle PRIVATE
extensions/src/multiplayer/wasm_exports.cpp
extensions/src/multiplayer/platforms/emscripten/wasm_exports.cpp
)
endif()
target_compile_definitions(isle PRIVATE "ISLE_EMSCRIPTEN_HOST=\"${ISLE_EMSCRIPTEN_HOST}\"")

View File

@ -13,6 +13,7 @@ namespace Multiplayer
{
class NetworkManager;
class NetworkTransport;
class PlatformCallbacks;
} // namespace Multiplayer
namespace Extensions
@ -42,6 +43,7 @@ class MultiplayerExt {
private:
static Multiplayer::NetworkManager* s_networkManager;
static Multiplayer::NetworkTransport* s_transport;
static Multiplayer::PlatformCallbacks* s_callbacks;
};
#ifdef EXTENSIONS

View File

@ -1,6 +1,7 @@
#pragma once
#include "extensions/multiplayer/networktransport.h"
#include "extensions/multiplayer/platformcallbacks.h"
#include "extensions/multiplayer/protocol.h"
#include "extensions/multiplayer/remoteplayer.h"
#include "extensions/multiplayer/worldstatesync.h"
@ -33,7 +34,7 @@ class NetworkManager : public MxCore {
return !strcmp(p_name, NetworkManager::ClassName()) || MxCore::IsA(p_name);
}
void Initialize(NetworkTransport* p_transport);
void Initialize(NetworkTransport* p_transport, PlatformCallbacks* p_callbacks);
void Shutdown();
void Connect(const char* p_roomId);
@ -78,6 +79,7 @@ class NetworkManager : public MxCore {
void SendMessage(const T& p_msg);
NetworkTransport* m_transport;
PlatformCallbacks* m_callbacks;
WorldStateSync m_worldSync;
std::map<uint32_t, std::unique_ptr<RemotePlayer>> m_remotePlayers;

View File

@ -0,0 +1,15 @@
#pragma once
namespace Multiplayer
{
class PlatformCallbacks {
public:
virtual ~PlatformCallbacks() = default;
// Called when the visible player count changes (joins, leaves, world transitions).
// p_count = players visible in current world, or -1 if not in a multiplayer world.
virtual void OnPlayerCountChanged(int p_count) = 0;
};
} // namespace Multiplayer

View File

@ -0,0 +1,17 @@
#pragma once
#ifdef __EMSCRIPTEN__
#include "extensions/multiplayer/platformcallbacks.h"
namespace Multiplayer
{
class EmscriptenCallbacks : public PlatformCallbacks {
public:
void OnPlayerCountChanged(int p_count) override;
};
} // namespace Multiplayer
#endif // __EMSCRIPTEN__

View File

@ -8,8 +8,11 @@
#include "legoentity.h"
#include "legogamestate.h"
#include "misc.h"
#ifdef __EMSCRIPTEN__
#include "extensions/multiplayer/websockettransport.h"
#include "extensions/multiplayer/platforms/emscripten/callbacks.h"
#include "extensions/multiplayer/platforms/emscripten/websockettransport.h"
#include <emscripten.h>
#endif
@ -21,6 +24,7 @@ std::string MultiplayerExt::relayUrl;
std::string MultiplayerExt::room;
Multiplayer::NetworkManager* MultiplayerExt::s_networkManager = nullptr;
Multiplayer::NetworkTransport* MultiplayerExt::s_transport = nullptr;
Multiplayer::PlatformCallbacks* MultiplayerExt::s_callbacks = nullptr;
void MultiplayerExt::Initialize()
{
@ -33,9 +37,10 @@ void MultiplayerExt::Initialize()
#ifdef __EMSCRIPTEN__
s_transport = new Multiplayer::WebSocketTransport(relayUrl);
s_callbacks = new Multiplayer::EmscriptenCallbacks();
s_networkManager = new Multiplayer::NetworkManager();
s_networkManager->Initialize(s_transport);
s_networkManager->Initialize(s_transport, s_callbacks);
s_networkManager->Connect(room.c_str());
#endif

View File

@ -11,9 +11,6 @@
#include <SDL3/SDL_stdinc.h>
#include <SDL3/SDL_timer.h>
#include <vector>
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
using namespace Multiplayer;
@ -32,8 +29,9 @@ void NetworkManager::SendMessage(const T& p_msg)
}
NetworkManager::NetworkManager()
: m_transport(nullptr), m_localPeerId(0), m_hostPeerId(0), m_sequence(0), m_lastBroadcastTime(0),
m_lastValidActorId(0), m_localWalkAnimId(0), m_localIdleAnimId(0), m_inIsleWorld(false), m_registered(false)
: m_transport(nullptr), m_callbacks(nullptr), m_localPeerId(0), m_hostPeerId(0), m_sequence(0),
m_lastBroadcastTime(0), m_lastValidActorId(0), m_localWalkAnimId(0), m_localIdleAnimId(0), m_inIsleWorld(false),
m_registered(false)
{
}
@ -78,9 +76,10 @@ MxResult NetworkManager::Tickle()
return SUCCESS;
}
void NetworkManager::Initialize(NetworkTransport* p_transport)
void NetworkManager::Initialize(NetworkTransport* p_transport, PlatformCallbacks* p_callbacks)
{
m_transport = p_transport;
m_callbacks = p_callbacks;
m_worldSync.SetTransport(p_transport);
}
@ -460,7 +459,10 @@ void NetworkManager::RemoveAllRemotePlayers()
void NetworkManager::NotifyPlayerCountChanged()
{
#ifdef __EMSCRIPTEN__
if (!m_callbacks) {
return;
}
int count = -1;
if (m_inIsleWorld) {
count = 1; // local player
@ -470,17 +472,8 @@ void NetworkManager::NotifyPlayerCountChanged()
}
}
}
// clang-format off
MAIN_THREAD_EM_ASM({
var canvas = Module.canvas;
if (canvas) {
canvas.dispatchEvent(new CustomEvent('playerCountChanged', {
detail: { count: $0 < 0 ? null : $0 }
}));
}
}, count);
// clang-format on
#endif
m_callbacks->OnPlayerCountChanged(count);
}
int8_t NetworkManager::DetectLocalVehicleType()

View File

@ -0,0 +1,26 @@
#ifdef __EMSCRIPTEN__
#include "extensions/multiplayer/platforms/emscripten/callbacks.h"
#include <emscripten.h>
namespace Multiplayer
{
void EmscriptenCallbacks::OnPlayerCountChanged(int p_count)
{
// clang-format off
MAIN_THREAD_EM_ASM({
var canvas = Module.canvas;
if (canvas) {
canvas.dispatchEvent(new CustomEvent('playerCountChanged', {
detail: { count: $0 < 0 ? null : $0 }
}));
}
}, p_count);
// clang-format on
}
} // namespace Multiplayer
#endif // __EMSCRIPTEN__

View File

@ -0,0 +1,39 @@
#ifdef __EMSCRIPTEN__
#include "extensions/multiplayer.h"
#include "extensions/multiplayer/networkmanager.h"
#include <emscripten.h>
using namespace Extensions;
extern "C"
{
EMSCRIPTEN_KEEPALIVE void mp_set_walk_animation(int index)
{
Multiplayer::NetworkManager* mgr = MultiplayerExt::GetNetworkManager();
if (mgr) {
mgr->SetWalkAnimation(static_cast<uint8_t>(index));
}
}
EMSCRIPTEN_KEEPALIVE void mp_set_idle_animation(int index)
{
Multiplayer::NetworkManager* mgr = MultiplayerExt::GetNetworkManager();
if (mgr) {
mgr->SetIdleAnimation(static_cast<uint8_t>(index));
}
}
EMSCRIPTEN_KEEPALIVE void mp_trigger_emote(int index)
{
Multiplayer::NetworkManager* mgr = MultiplayerExt::GetNetworkManager();
if (mgr) {
mgr->SendEmote(static_cast<uint8_t>(index));
}
}
} // extern "C"
#endif

View File

@ -1,6 +1,6 @@
#ifdef __EMSCRIPTEN__
#include "extensions/multiplayer/websockettransport.h"
#include "extensions/multiplayer/platforms/emscripten/websockettransport.h"
#include <SDL3/SDL_stdinc.h>
#include <emscripten.h>

View File

@ -1,38 +0,0 @@
#ifdef __EMSCRIPTEN__
#include "extensions/multiplayer.h"
#include "extensions/multiplayer/networkmanager.h"
#include <emscripten.h>
using namespace Extensions;
extern "C" {
EMSCRIPTEN_KEEPALIVE void mp_set_walk_animation(int index)
{
Multiplayer::NetworkManager* mgr = MultiplayerExt::GetNetworkManager();
if (mgr) {
mgr->SetWalkAnimation(static_cast<uint8_t>(index));
}
}
EMSCRIPTEN_KEEPALIVE void mp_set_idle_animation(int index)
{
Multiplayer::NetworkManager* mgr = MultiplayerExt::GetNetworkManager();
if (mgr) {
mgr->SetIdleAnimation(static_cast<uint8_t>(index));
}
}
EMSCRIPTEN_KEEPALIVE void mp_trigger_emote(int index)
{
Multiplayer::NetworkManager* mgr = MultiplayerExt::GetNetworkManager();
if (mgr) {
mgr->SendEmote(static_cast<uint8_t>(index));
}
}
} // extern "C"
#endif