Compare commits
9 Commits
cde20c6fd7
...
feature/ch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd2a197288 | ||
| 01787d701c | |||
| 6e7de1a11a | |||
|
|
d92a078fc7 | ||
| 9785908ca9 | |||
| 592a745b8f | |||
| 299627dac7 | |||
| ae3a256c52 | |||
| 97ea698f38 |
@@ -6,6 +6,7 @@ import { AppController } from './app.controller';
|
||||
import { AppService } from './app.service';
|
||||
import { LoggerModule } from './core/utils/logger/logger.module';
|
||||
import { UsersModule } from './core/db/users/users.module';
|
||||
import { ZulipAccountsModule } from './core/db/zulip_accounts/zulip_accounts.module';
|
||||
import { LoginCoreModule } from './core/login_core/login_core.module';
|
||||
import { AuthGatewayModule } from './gateway/auth/auth.gateway.module';
|
||||
import { ChatGatewayModule } from './gateway/chat/chat.gateway.module';
|
||||
@@ -62,6 +63,8 @@ function isDatabaseConfigured(): boolean {
|
||||
database: process.env.DB_NAME,
|
||||
entities: [__dirname + '/**/*.entity{.ts,.js}'],
|
||||
synchronize: false,
|
||||
// 字符集配置 - 支持中文和emoji
|
||||
charset: 'utf8mb4',
|
||||
// 添加连接超时和重试配置
|
||||
connectTimeout: 10000,
|
||||
retryAttempts: 3,
|
||||
@@ -70,6 +73,8 @@ function isDatabaseConfigured(): boolean {
|
||||
] : []),
|
||||
// 根据数据库配置选择用户模块模式
|
||||
isDatabaseConfigured() ? UsersModule.forDatabase() : UsersModule.forMemory(),
|
||||
// Zulip账号关联模块 - 全局单例,其他模块无需重复导入
|
||||
ZulipAccountsModule.forRoot(),
|
||||
LoginCoreModule,
|
||||
AuthGatewayModule, // 认证网关模块
|
||||
ChatGatewayModule, // 聊天网关模块
|
||||
|
||||
@@ -27,7 +27,6 @@ import { AdminCoreModule } from '../../core/admin_core/admin_core.module';
|
||||
import { LoggerModule } from '../../core/utils/logger/logger.module';
|
||||
import { UsersModule } from '../../core/db/users/users.module';
|
||||
import { UserProfilesModule } from '../../core/db/user_profiles/user_profiles.module';
|
||||
import { ZulipAccountsModule } from '../../core/db/zulip_accounts/zulip_accounts.module';
|
||||
import { AdminController } from './admin.controller';
|
||||
import { AdminService } from './admin.service';
|
||||
import { AdminDatabaseController } from './admin_database.controller';
|
||||
@@ -55,8 +54,7 @@ function isDatabaseConfigured(): boolean {
|
||||
UsersModule,
|
||||
// 根据数据库配置选择UserProfiles模块模式
|
||||
isDatabaseConfigured() ? UserProfilesModule.forDatabase() : UserProfilesModule.forMemory(),
|
||||
// 根据数据库配置选择ZulipAccounts模块模式
|
||||
isDatabaseConfigured() ? ZulipAccountsModule.forDatabase() : ZulipAccountsModule.forMemory(),
|
||||
// 注意:ZulipAccountsModule 是全局模块,已在 AppModule 中导入,无需重复导入
|
||||
// 注册AdminOperationLog实体
|
||||
TypeOrmModule.forFeature([AdminOperationLog])
|
||||
],
|
||||
|
||||
@@ -36,7 +36,6 @@ import { LoginService } from './login.service';
|
||||
import { RegisterService } from './register.service';
|
||||
import { LoginCoreModule } from '../../core/login_core/login_core.module';
|
||||
import { ZulipCoreModule } from '../../core/zulip_core/zulip_core.module';
|
||||
import { ZulipAccountsModule } from '../../core/db/zulip_accounts/zulip_accounts.module';
|
||||
import { UsersModule } from '../../core/db/users/users.module';
|
||||
|
||||
@Module({
|
||||
@@ -44,7 +43,7 @@ import { UsersModule } from '../../core/db/users/users.module';
|
||||
// 导入核心层模块
|
||||
LoginCoreModule,
|
||||
ZulipCoreModule,
|
||||
ZulipAccountsModule.forRoot(),
|
||||
// 注意:ZulipAccountsModule 是全局模块,已在 AppModule 中导入,无需重复导入
|
||||
UsersModule,
|
||||
],
|
||||
providers: [
|
||||
|
||||
@@ -36,7 +36,6 @@ import { ZulipEventProcessorService } from './services/zulip_event_processor.ser
|
||||
import { ZulipAccountsBusinessService } from './services/zulip_accounts_business.service';
|
||||
// 依赖模块
|
||||
import { ZulipCoreModule } from '../../core/zulip_core/zulip_core.module';
|
||||
import { ZulipAccountsModule } from '../../core/db/zulip_accounts/zulip_accounts.module';
|
||||
import { RedisModule } from '../../core/redis/redis.module';
|
||||
import { LoggerModule } from '../../core/utils/logger/logger.module';
|
||||
import { LoginCoreModule } from '../../core/login_core/login_core.module';
|
||||
@@ -50,8 +49,7 @@ import { ChatModule } from '../chat/chat.module';
|
||||
CacheModule.register(),
|
||||
// Zulip核心服务模块
|
||||
ZulipCoreModule,
|
||||
// Zulip账号关联模块
|
||||
ZulipAccountsModule.forRoot(),
|
||||
// 注意:ZulipAccountsModule 是全局模块,已在 AppModule 中导入,无需重复导入
|
||||
// Redis模块
|
||||
RedisModule,
|
||||
// 日志模块
|
||||
|
||||
@@ -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, '切换地图处理失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理连接关闭
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user