Multi server connection
This commit is contained in:
@@ -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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user