Multi server connection

This commit is contained in:
2026-03-01 15:26:08 +01:00
parent d88a476f15
commit d146138fca
7 changed files with 278 additions and 86 deletions

View File

@@ -38,7 +38,8 @@ interface JoinRequest {
interface ConnectedUser {
oderId: string;
ws: WebSocket;
serverId?: string;
serverIds: Set<string>; // all servers the user is a member of
viewedServerId?: string; // currently viewed/active server
displayName?: string;
}
@@ -361,7 +362,7 @@ const wss = new WebSocketServer({ server });
wss.on('connection', (ws: WebSocket) => {
const connectionId = uuidv4();
connectedUsers.set(connectionId, { oderId: connectionId, ws });
connectedUsers.set(connectionId, { oderId: connectionId, ws, serverIds: new Set() });
ws.on('message', (data) => {
try {
@@ -374,13 +375,16 @@ wss.on('connection', (ws: WebSocket) => {
ws.on('close', () => {
const user = connectedUsers.get(connectionId);
if (user?.serverId) {
// Notify others in the room - use user.oderId (the actual user ID), not connectionId
broadcastToServer(user.serverId, {
type: 'user_left',
oderId: user.oderId,
displayName: user.displayName,
}, user.oderId);
if (user) {
// Notify all servers the user was a member of
user.serverIds.forEach((sid) => {
broadcastToServer(sid, {
type: 'user_left',
oderId: user.oderId,
displayName: user.displayName,
serverId: sid,
}, user.oderId);
});
}
connectedUsers.delete(connectionId);
});
@@ -403,44 +407,76 @@ function handleWebSocketMessage(connectionId: string, message: any): void {
console.log(`User identified: ${user.displayName} (${user.oderId})`);
break;
case 'join_server':
user.serverId = message.serverId;
case 'join_server': {
const sid = message.serverId;
const isNew = !user.serverIds.has(sid);
user.serverIds.add(sid);
user.viewedServerId = sid;
connectedUsers.set(connectionId, user);
console.log(`User ${user.displayName || 'Anonymous'} (${user.oderId}) joined server ${message.serverId}`);
console.log(`User ${user.displayName || 'Anonymous'} (${user.oderId}) joined server ${sid} (new=${isNew})`);
// Get list of current users in server (exclude this user by oderId)
// Only include users that have been identified (have displayName)
// Always send the current user list for this server
const usersInServer = Array.from(connectedUsers.values())
.filter(u => u.serverId === message.serverId && u.oderId !== user.oderId && u.displayName)
.filter(u => u.serverIds.has(sid) && u.oderId !== user.oderId && u.displayName)
.map(u => ({ oderId: u.oderId, displayName: u.displayName || 'Anonymous' }));
console.log(`Sending server_users to ${user.displayName || 'Anonymous'}:`, usersInServer);
user.ws.send(JSON.stringify({
type: 'server_users',
serverId: sid,
users: usersInServer,
}));
// Notify others (exclude by oderId, not connectionId)
broadcastToServer(message.serverId, {
type: 'user_joined',
oderId: user.oderId,
displayName: user.displayName || 'Anonymous',
}, user.oderId);
break;
case 'leave_server':
const oldServerId = user.serverId;
user.serverId = undefined;
connectedUsers.set(connectionId, user);
if (oldServerId) {
broadcastToServer(oldServerId, {
type: 'user_left',
// Only broadcast user_joined if this is a brand-new join (not a re-view)
if (isNew) {
broadcastToServer(sid, {
type: 'user_joined',
oderId: user.oderId,
displayName: user.displayName || 'Anonymous',
serverId: sid,
}, user.oderId);
}
break;
}
case 'view_server': {
// Just switch the viewed server without joining/leaving
const viewSid = message.serverId;
user.viewedServerId = viewSid;
connectedUsers.set(connectionId, user);
console.log(`User ${user.displayName || 'Anonymous'} (${user.oderId}) viewing server ${viewSid}`);
// Send current user list for the viewed server
const viewUsers = Array.from(connectedUsers.values())
.filter(u => u.serverIds.has(viewSid) && u.oderId !== user.oderId && u.displayName)
.map(u => ({ oderId: u.oderId, displayName: u.displayName || 'Anonymous' }));
user.ws.send(JSON.stringify({
type: 'server_users',
serverId: viewSid,
users: viewUsers,
}));
break;
}
case 'leave_server': {
const leaveSid = message.serverId || user.viewedServerId;
if (leaveSid) {
user.serverIds.delete(leaveSid);
if (user.viewedServerId === leaveSid) {
user.viewedServerId = undefined;
}
connectedUsers.set(connectionId, user);
broadcastToServer(leaveSid, {
type: 'user_left',
oderId: user.oderId,
displayName: user.displayName || 'Anonymous',
serverId: leaveSid,
}, user.oderId);
}
break;
}
case 'offer':
case 'answer':
@@ -460,11 +496,13 @@ function handleWebSocketMessage(connectionId: string, message: any): void {
}
break;
case 'chat_message':
case 'chat_message': {
// Broadcast chat message to all users in the server
if (user.serverId) {
broadcastToServer(user.serverId, {
const chatSid = message.serverId || user.viewedServerId;
if (chatSid && user.serverIds.has(chatSid)) {
broadcastToServer(chatSid, {
type: 'chat_message',
serverId: chatSid,
message: message.message,
senderId: user.oderId,
senderName: user.displayName,
@@ -472,17 +510,21 @@ function handleWebSocketMessage(connectionId: string, message: any): void {
});
}
break;
}
case 'typing':
case 'typing': {
// Broadcast typing indicator
if (user.serverId) {
broadcastToServer(user.serverId, {
const typingSid = message.serverId || user.viewedServerId;
if (typingSid && user.serverIds.has(typingSid)) {
broadcastToServer(typingSid, {
type: 'user_typing',
serverId: typingSid,
oderId: user.oderId,
displayName: user.displayName,
}, user.oderId);
}
break;
}
default:
console.log('Unknown message type:', message.type);
@@ -492,7 +534,7 @@ function handleWebSocketMessage(connectionId: string, message: any): void {
function broadcastToServer(serverId: string, message: any, excludeOderId?: string): void {
console.log(`Broadcasting to server ${serverId}, excluding ${excludeOderId}:`, message.type);
connectedUsers.forEach((user) => {
if (user.serverId === serverId && user.oderId !== excludeOderId) {
if (user.serverIds.has(serverId) && user.oderId !== excludeOderId) {
console.log(` -> Sending to ${user.displayName} (${user.oderId})`);
user.ws.send(JSON.stringify(message));
}