feat: integrate invitation access, world NPCs, and deployment

This commit is contained in:
2026-09-08 22:22:38 +08:00
parent 2a3125075f
commit 513a3eba31
75 changed files with 9566 additions and 1070 deletions

View File

@@ -28,6 +28,7 @@ import {
HttpStatus,
HttpException,
Logger,
Headers,
} from '@nestjs/common';
import {
ApiTags,
@@ -39,6 +40,7 @@ import {
import { JwtAuthGuard } from '../auth/jwt_auth.guard';
import { ChatService } from '../../business/chat/chat.service';
import { ChatWebSocketGateway } from './chat.gateway';
import { WorldNpcService } from '../../business/world_npc/world_npc.service';
import { SendChatMessageDto, GetChatHistoryDto } from './chat.dto';
import {
ChatMessageResponseDto,
@@ -67,8 +69,37 @@ export class ChatController {
constructor(
private readonly chatService: ChatService,
private readonly websocketGateway: ChatWebSocketGateway,
private readonly worldNpcService: WorldNpcService,
) {}
@Get('world-npcs/status')
@ApiOperation({ summary: '查看AI小镇NPC的当前计划、位置与动作状态' })
getWorldNpcStatus() {
return this.worldNpcService.getTownStatus();
}
@Post('world-npcs/test-time')
@ApiOperation({ summary: '开发环境设置AI小镇测试时间' })
async setWorldNpcTestTime(
@Body() body: { timestamp?: number | string | null },
@Headers('x-world-npc-test-token') token?: string,
) {
const enabled = process.env.NODE_ENV !== 'production'
&& process.env.WORLD_NPC_TEST_CONTROLS === 'enabled';
const expectedToken = String(process.env.WORLD_NPC_TEST_CONTROL_TOKEN || '').trim();
if (!enabled || !expectedToken || token !== expectedToken) {
throw new HttpException('测试时间控制未启用', HttpStatus.FORBIDDEN);
}
if (body.timestamp === null || body.timestamp === undefined || body.timestamp === '') {
return this.worldNpcService.setTownTimeForTesting(undefined);
}
const numeric = typeof body.timestamp === 'number'
? body.timestamp
: Date.parse(String(body.timestamp));
if (!Number.isFinite(numeric)) throw new HttpException('timestamp无效', HttpStatus.BAD_REQUEST);
return this.worldNpcService.setTownTimeForTesting(numeric);
}
/**
* 发送聊天消息REST API 方式)
*
@@ -91,7 +122,7 @@ export class ChatController {
// REST API 没有 WebSocket 连接,提示使用 WebSocket
throw new HttpException(
'聊天消息发送需要通过 WebSocket 连接。请使用 WebSocket 接口wss://whaletownend.xinghangee.icu/game',
'聊天消息发送需要通过 WebSocket 连接。请使用 WebSocket 接口wss://whaletown.novamailio.com/game',
HttpStatus.BAD_REQUEST,
);
}
@@ -180,7 +211,7 @@ export class ChatController {
@ApiOperation({ summary: '获取 WebSocket 连接信息' })
async getWebSocketInfo() {
return {
websocketUrl: 'wss://whaletownend.xinghangee.icu/game',
websocketUrl: 'wss://whaletown.novamailio.com/game',
protocol: 'native-websocket',
path: '/game',
supportedEvents: ['login', 'chat', 'position'],