mirror of
https://github.com/isledecomp/isle-portable.git
synced 2026-05-02 02:23:56 +00:00
Move routing info into message header, make relay type-agnostic
This commit is contained in:
parent
a8c3ec7b2f
commit
9e8ecd6d44
@ -90,7 +90,6 @@ class NetworkManager : public MxCore {
|
||||
|
||||
RemotePlayer* CreateAndSpawnPlayer(uint32_t p_peerId, uint8_t p_actorId, uint8_t p_displayActorIndex);
|
||||
|
||||
void HandleJoin(const PlayerJoinMsg& p_msg);
|
||||
void HandleLeave(const PlayerLeaveMsg& p_msg);
|
||||
void HandleState(const PlayerStateMsg& p_msg);
|
||||
void HandleHostAssign(const HostAssignMsg& p_msg);
|
||||
|
||||
@ -10,8 +10,12 @@ class LegoPathActor;
|
||||
namespace Multiplayer
|
||||
{
|
||||
|
||||
// Routing target constants for MessageHeader.target
|
||||
const uint32_t TARGET_BROADCAST = 0; // Broadcast to all except sender
|
||||
const uint32_t TARGET_HOST = 0xFFFFFFFF; // Send to host only
|
||||
const uint32_t TARGET_BROADCAST_ALL = 0xFFFFFFFE; // Broadcast to all including sender
|
||||
|
||||
enum MessageType : uint8_t {
|
||||
MSG_JOIN = 1,
|
||||
MSG_LEAVE = 2,
|
||||
MSG_STATE = 3,
|
||||
MSG_HOST_ASSIGN = 4,
|
||||
@ -74,12 +78,7 @@ struct MessageHeader {
|
||||
uint8_t type;
|
||||
uint32_t peerId;
|
||||
uint32_t sequence;
|
||||
};
|
||||
|
||||
struct PlayerJoinMsg {
|
||||
MessageHeader header;
|
||||
uint8_t actorId;
|
||||
char name[20];
|
||||
uint32_t target;
|
||||
};
|
||||
|
||||
struct PlayerLeaveMsg {
|
||||
@ -115,10 +114,9 @@ struct RequestSnapshotMsg {
|
||||
};
|
||||
|
||||
// Host -> specific client: full world state blob (variable length)
|
||||
// Relay reads targetPeerId at offset 9 and routes to that peer only.
|
||||
// Relay reads header.target and routes to that peer only.
|
||||
struct WorldSnapshotMsg {
|
||||
MessageHeader header;
|
||||
uint32_t targetPeerId;
|
||||
uint16_t dataLength;
|
||||
// Followed by dataLength bytes of serialized plant + building state
|
||||
};
|
||||
|
||||
@ -312,7 +312,7 @@ void NetworkManager::BroadcastLocalState()
|
||||
}
|
||||
|
||||
PlayerStateMsg msg{};
|
||||
msg.header = {MSG_STATE, m_localPeerId, m_sequence++};
|
||||
msg.header = {MSG_STATE, m_localPeerId, m_sequence++, TARGET_BROADCAST};
|
||||
msg.actorId = actorId;
|
||||
msg.worldId = (int8_t) currentWorld->GetWorldId();
|
||||
msg.vehicleType = DetectVehicleType(userActor);
|
||||
@ -397,16 +397,6 @@ void NetworkManager::ProcessIncomingPackets()
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_JOIN: {
|
||||
PlayerJoinMsg msg;
|
||||
if (DeserializeMsg(data, length, msg) && msg.header.type == MSG_JOIN) {
|
||||
msg.name[sizeof(msg.name) - 1] = '\0';
|
||||
if (IsValidActorId(msg.actorId)) {
|
||||
HandleJoin(msg);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_LEAVE: {
|
||||
PlayerLeaveMsg msg;
|
||||
if (DeserializeMsg(data, length, msg) && msg.header.type == MSG_LEAVE) {
|
||||
@ -494,18 +484,6 @@ RemotePlayer* NetworkManager::CreateAndSpawnPlayer(uint32_t p_peerId, uint8_t p_
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void NetworkManager::HandleJoin(const PlayerJoinMsg& p_msg)
|
||||
{
|
||||
uint32_t peerId = p_msg.header.peerId;
|
||||
|
||||
if (m_remotePlayers.count(peerId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
CreateAndSpawnPlayer(peerId, p_msg.actorId, p_msg.actorId - 1);
|
||||
NotifyPlayerCountChanged();
|
||||
}
|
||||
|
||||
void NetworkManager::HandleLeave(const PlayerLeaveMsg& p_msg)
|
||||
{
|
||||
RemoveRemotePlayer(p_msg.header.peerId);
|
||||
@ -594,7 +572,7 @@ void NetworkManager::SendEmote(uint8_t p_emoteId)
|
||||
m_thirdPersonCamera.TriggerEmote(p_emoteId);
|
||||
|
||||
EmoteMsg msg{};
|
||||
msg.header = {MSG_EMOTE, m_localPeerId, m_sequence++};
|
||||
msg.header = {MSG_EMOTE, m_localPeerId, m_sequence++, TARGET_BROADCAST};
|
||||
msg.emoteId = p_emoteId;
|
||||
SendMessage(msg);
|
||||
}
|
||||
@ -713,7 +691,7 @@ bool NetworkManager::IsClonedCharacter(const char* p_name) const
|
||||
void NetworkManager::SendCustomize(uint32_t p_targetPeerId, uint8_t p_changeType, uint8_t p_partIndex)
|
||||
{
|
||||
CustomizeMsg msg{};
|
||||
msg.header = {MSG_CUSTOMIZE, m_localPeerId, m_sequence++};
|
||||
msg.header = {MSG_CUSTOMIZE, m_localPeerId, m_sequence++, TARGET_BROADCAST_ALL};
|
||||
msg.targetPeerId = p_targetPeerId;
|
||||
msg.changeType = p_changeType;
|
||||
msg.partIndex = p_partIndex;
|
||||
|
||||
@ -1,14 +1,12 @@
|
||||
import {
|
||||
HEADER_SIZE,
|
||||
MSG_CUSTOMIZE,
|
||||
MSG_REQUEST_SNAPSHOT,
|
||||
MSG_WORLD_EVENT_REQUEST,
|
||||
MSG_WORLD_SNAPSHOT,
|
||||
SNAPSHOT_MIN_SIZE,
|
||||
TARGET_BROADCAST,
|
||||
TARGET_HOST,
|
||||
TARGET_BROADCAST_ALL,
|
||||
createAssignIdMsg,
|
||||
createHostAssignMsg,
|
||||
createLeaveMsg,
|
||||
readTargetPeerId,
|
||||
readTarget,
|
||||
stampSender,
|
||||
} from "./protocol";
|
||||
import type { Env } from "./relay";
|
||||
@ -166,30 +164,17 @@ export class GameRoom implements DurableObject {
|
||||
return;
|
||||
}
|
||||
|
||||
const msgType = data[0];
|
||||
const stamped = stampSender(data, peerId);
|
||||
const target = readTarget(stamped);
|
||||
|
||||
if (
|
||||
msgType === MSG_REQUEST_SNAPSHOT ||
|
||||
msgType === MSG_WORLD_EVENT_REQUEST
|
||||
) {
|
||||
if (target === TARGET_BROADCAST) {
|
||||
this.broadcastExcept(stamped.buffer, peerId);
|
||||
} else if (target === TARGET_HOST) {
|
||||
this.sendToHost(stamped);
|
||||
} else if (
|
||||
msgType === MSG_WORLD_SNAPSHOT &&
|
||||
data.length >= SNAPSHOT_MIN_SIZE
|
||||
) {
|
||||
const targetId = readTargetPeerId(stamped);
|
||||
if (targetId === 0) {
|
||||
this.broadcastExcept(stamped.buffer, peerId);
|
||||
} else {
|
||||
this.sendToTarget(stamped);
|
||||
}
|
||||
} else if (msgType === MSG_CUSTOMIZE) {
|
||||
// Broadcast to all including sender so the clicker sees effects
|
||||
// on the target's clone on their own screen.
|
||||
} else if (target === TARGET_BROADCAST_ALL) {
|
||||
this.broadcast(stamped.buffer);
|
||||
} else {
|
||||
this.broadcastExcept(stamped.buffer, peerId);
|
||||
this.sendToTarget(stamped, target);
|
||||
}
|
||||
}
|
||||
|
||||
@ -200,8 +185,7 @@ export class GameRoom implements DurableObject {
|
||||
}
|
||||
}
|
||||
|
||||
private sendToTarget(data: Uint8Array): void {
|
||||
const targetId = readTargetPeerId(data);
|
||||
private sendToTarget(data: Uint8Array, targetId: number): void {
|
||||
const targetWs = this.connections.get(targetId);
|
||||
if (targetWs) {
|
||||
if (!this.trySend(targetWs, data.buffer)) {
|
||||
|
||||
@ -1,30 +1,27 @@
|
||||
// Protocol constants — must stay in sync with protocol.h
|
||||
|
||||
// MessageHeader binary layout: type(1) + peerId(4) + sequence(4) = 9 bytes
|
||||
export const HEADER_SIZE = 9;
|
||||
// MessageHeader binary layout: type(1) + peerId(4) + sequence(4) + target(4) = 13 bytes
|
||||
export const HEADER_SIZE = 13;
|
||||
export const PEER_ID_OFFSET = 1;
|
||||
export const SEQUENCE_OFFSET = 5;
|
||||
export const TARGET_OFFSET = 9;
|
||||
|
||||
// Message types the relay inspects for routing decisions.
|
||||
// All other types are broadcast to every peer in the room.
|
||||
// Routing target constants
|
||||
export const TARGET_BROADCAST = 0;
|
||||
export const TARGET_HOST = 0xffffffff;
|
||||
export const TARGET_BROADCAST_ALL = 0xfffffffe;
|
||||
|
||||
// Message types used by server message constructors only.
|
||||
export const MSG_LEAVE = 2;
|
||||
export const MSG_HOST_ASSIGN = 4;
|
||||
export const MSG_REQUEST_SNAPSHOT = 5;
|
||||
export const MSG_WORLD_SNAPSHOT = 6;
|
||||
export const MSG_WORLD_EVENT_REQUEST = 8;
|
||||
export const MSG_CUSTOMIZE = 10;
|
||||
export const MSG_ASSIGN_ID = 0xff;
|
||||
|
||||
// AssignIdMsg: compact server-only message — type(1) + peerId(4) + maxActors(1)
|
||||
const ASSIGN_ID_SIZE = 1 + 4 + 1;
|
||||
|
||||
// HostAssignMsg: header(9) + hostPeerId(4)
|
||||
// HostAssignMsg: header(13) + hostPeerId(4)
|
||||
const HOST_ASSIGN_SIZE = HEADER_SIZE + 4;
|
||||
|
||||
// WorldSnapshotMsg: header(9) + targetPeerId(4) + dataLength(2) + data...
|
||||
export const SNAPSHOT_TARGET_OFFSET = HEADER_SIZE;
|
||||
export const SNAPSHOT_MIN_SIZE = HEADER_SIZE + 4 + 2;
|
||||
|
||||
export function createAssignIdMsg(peerId: number, maxActors: number): ArrayBuffer {
|
||||
const buf = new ArrayBuffer(ASSIGN_ID_SIZE);
|
||||
const view = new DataView(buf);
|
||||
@ -40,6 +37,7 @@ export function createHostAssignMsg(hostPeerId: number): ArrayBuffer {
|
||||
view.setUint8(0, MSG_HOST_ASSIGN);
|
||||
view.setUint32(PEER_ID_OFFSET, 0, true);
|
||||
view.setUint32(SEQUENCE_OFFSET, 0, true);
|
||||
view.setUint32(TARGET_OFFSET, 0, true);
|
||||
view.setUint32(HEADER_SIZE, hostPeerId, true);
|
||||
return buf;
|
||||
}
|
||||
@ -50,6 +48,7 @@ export function createLeaveMsg(peerId: number): ArrayBuffer {
|
||||
view.setUint8(0, MSG_LEAVE);
|
||||
view.setUint32(PEER_ID_OFFSET, peerId, true);
|
||||
view.setUint32(SEQUENCE_OFFSET, 0, true);
|
||||
view.setUint32(TARGET_OFFSET, 0, true);
|
||||
return buf;
|
||||
}
|
||||
|
||||
@ -61,6 +60,6 @@ export function stampSender(data: Uint8Array, peerId: number): Uint8Array {
|
||||
return stamped;
|
||||
}
|
||||
|
||||
export function readTargetPeerId(data: Uint8Array): number {
|
||||
return new DataView(data.buffer).getUint32(SNAPSHOT_TARGET_OFFSET, true);
|
||||
export function readTarget(data: Uint8Array): number {
|
||||
return new DataView(data.buffer).getUint32(TARGET_OFFSET, true);
|
||||
}
|
||||
|
||||
@ -232,7 +232,7 @@ MxBool WorldStateSync::HandleSkyLightMutation(uint8_t p_entityType, uint8_t p_ch
|
||||
void WorldStateSync::SendSnapshotRequest()
|
||||
{
|
||||
RequestSnapshotMsg msg{};
|
||||
msg.header = {MSG_REQUEST_SNAPSHOT, m_localPeerId, m_sequence++};
|
||||
msg.header = {MSG_REQUEST_SNAPSHOT, m_localPeerId, m_sequence++, TARGET_HOST};
|
||||
SendMessage(msg);
|
||||
|
||||
m_snapshotRequested = true;
|
||||
@ -270,8 +270,7 @@ void WorldStateSync::SendWorldSnapshot(uint32_t p_targetPeerId)
|
||||
stateBuffer[dataLength++] = (uint8_t) lightPos;
|
||||
|
||||
WorldSnapshotMsg msg{};
|
||||
msg.header = {MSG_WORLD_SNAPSHOT, m_localPeerId, m_sequence++};
|
||||
msg.targetPeerId = p_targetPeerId;
|
||||
msg.header = {MSG_WORLD_SNAPSHOT, m_localPeerId, m_sequence++, p_targetPeerId};
|
||||
msg.dataLength = (uint16_t) dataLength;
|
||||
|
||||
std::vector<uint8_t> msgBuf(sizeof(WorldSnapshotMsg) + dataLength);
|
||||
@ -284,7 +283,7 @@ void WorldStateSync::SendWorldSnapshot(uint32_t p_targetPeerId)
|
||||
void WorldStateSync::BroadcastWorldEvent(uint8_t p_entityType, uint8_t p_changeType, uint8_t p_entityIndex)
|
||||
{
|
||||
WorldEventMsg msg{};
|
||||
msg.header = {MSG_WORLD_EVENT, m_localPeerId, m_sequence++};
|
||||
msg.header = {MSG_WORLD_EVENT, m_localPeerId, m_sequence++, TARGET_BROADCAST};
|
||||
msg.entityType = p_entityType;
|
||||
msg.changeType = p_changeType;
|
||||
msg.entityIndex = p_entityIndex;
|
||||
@ -294,7 +293,7 @@ void WorldStateSync::BroadcastWorldEvent(uint8_t p_entityType, uint8_t p_changeT
|
||||
void WorldStateSync::SendWorldEventRequest(uint8_t p_entityType, uint8_t p_changeType, uint8_t p_entityIndex)
|
||||
{
|
||||
WorldEventRequestMsg msg{};
|
||||
msg.header = {MSG_WORLD_EVENT_REQUEST, m_localPeerId, m_sequence++};
|
||||
msg.header = {MSG_WORLD_EVENT_REQUEST, m_localPeerId, m_sequence++, TARGET_HOST};
|
||||
msg.entityType = p_entityType;
|
||||
msg.changeType = p_changeType;
|
||||
msg.entityIndex = p_entityIndex;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user