feat(chat): 添加地图切换功能

范围: src/gateway/chat/
- 新增 change_map 事件处理
- 实现 handleChangeMap() 方法
- 支持玩家在不同地图间切换
- 自动更新房间成员和广播通知
- 完善地图切换的错误处理

功能说明:
- 玩家可以通过 WebSocket 发送 change_map 事件切换地图
- 自动处理房间加入/离开逻辑
- 向旧地图广播玩家离开,向新地图广播玩家加入
- 支持携带初始位置坐标,默认使用 (400, 300)
This commit is contained in:
moyin
2026-01-19 17:43:59 +08:00
parent 01787d701c
commit cd2a197288

View File

@@ -169,6 +169,9 @@ export class ChatWebSocketGateway implements OnModuleInit, OnModuleDestroy, ICha
case 'position':
await this.handlePosition(ws, message);
break;
case 'change_map':
await this.handleChangeMap(ws, message);
break;
default:
this.logger.warn(`未知消息类型: ${messageType}`);
this.sendError(ws, `未知消息类型: ${messageType}`);
@@ -254,7 +257,7 @@ export class ChatWebSocketGateway implements OnModuleInit, OnModuleDestroy, ICha
* 处理聊天消息
*
* @param ws WebSocket 连接实例
* @param message 聊天消息(包含 content, scope
* @param message 聊天消息(包含 content, scope, mapId
*/
private async handleChat(ws: ExtendedWebSocket, message: any) {
if (!ws.authenticated) {
@@ -271,7 +274,8 @@ export class ChatWebSocketGateway implements OnModuleInit, OnModuleDestroy, ICha
const result = await this.chatService.sendChatMessage({
socketId: ws.id,
content: message.content,
scope: message.scope || 'local'
scope: message.scope || 'local',
mapId: message.mapId || ws.currentMap, // 支持指定目标地图
});
if (result.success) {
@@ -335,6 +339,82 @@ export class ChatWebSocketGateway implements OnModuleInit, OnModuleDestroy, ICha
}
}
/**
* 处理切换地图
*
* @param ws WebSocket 连接实例
* @param message 切换地图消息(包含 mapId
*/
private async handleChangeMap(ws: ExtendedWebSocket, message: any) {
if (!ws.authenticated) {
this.sendError(ws, '请先登录');
return;
}
if (!message.mapId) {
this.sendError(ws, '地图ID不能为空');
return;
}
try {
const oldMapId = ws.currentMap;
const newMapId = message.mapId;
// 如果地图相同,直接返回成功
if (oldMapId === newMapId) {
this.sendMessage(ws, {
t: 'map_changed',
mapId: newMapId,
message: '已在当前地图'
});
return;
}
// 更新房间
this.leaveMapRoom(ws.id, oldMapId);
this.joinMapRoom(ws.id, newMapId);
ws.currentMap = newMapId;
// 更新会话中的地图信息(使用默认位置)
await this.chatService.updatePlayerPosition({
socketId: ws.id,
x: message.x || 400,
y: message.y || 300,
mapId: newMapId
});
// 通知客户端切换成功
this.sendMessage(ws, {
t: 'map_changed',
mapId: newMapId,
oldMapId: oldMapId,
message: '地图切换成功'
});
// 向旧地图广播玩家离开
this.broadcastToMap(oldMapId, {
t: 'player_left',
userId: ws.userId,
username: ws.username,
mapId: oldMapId
});
// 向新地图广播玩家加入
this.broadcastToMap(newMapId, {
t: 'player_joined',
userId: ws.userId,
username: ws.username,
mapId: newMapId
}, ws.id);
this.logger.log(`用户切换地图: ${ws.username} (${oldMapId} -> ${newMapId})`);
} catch (error) {
this.logger.error('切换地图处理失败', error);
this.sendError(ws, '切换地图处理失败');
}
}
/**
* 处理连接关闭
*