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

@@ -98,10 +98,19 @@ export interface MapPlayerPresence {
cafeCompanion?: ICafeCompanionPresence | null;
/** 是否锁定移动 */
movementLocked?: boolean;
/** 面向方向 */
direction?: 'down' | 'up' | 'right' | 'left';
/** 移动动画状态 */
movementState?: 'idle' | 'walk';
/** 当前连接内的移动消息序号 */
sequence?: number;
}
export interface PlayerPresenceMetadata {
appearance?: IPlayerAppearance;
direction?: 'down' | 'up' | 'right' | 'left';
movementState?: 'idle' | 'walk';
sequence?: number;
}
export interface BusinessPresenceUpdate {
@@ -196,6 +205,9 @@ export class ChatSessionService implements ISessionManagerService {
currentMap: initialMap || this.DEFAULT_MAP,
position: initialPosition || { ...this.DEFAULT_POSITION },
appearance: this.mergeAppearance(undefined, initialAppearance),
direction: 'down',
movementState: 'idle',
movementSequence: 0,
lastActivity: now,
createdAt: now,
};
@@ -561,6 +573,9 @@ export class ChatSessionService implements ISessionManagerService {
appearance: session.appearance,
cafeCompanion: session.cafeCompanion ?? null,
movementLocked: Boolean(session.movementLocked),
direction: session.direction || 'down',
movementState: session.movementState || 'idle',
sequence: Number(session.movementSequence ?? 0),
});
}
@@ -627,6 +642,9 @@ export class ChatSessionService implements ISessionManagerService {
appearance: session.appearance,
cafeCompanion: session.cafeCompanion ?? null,
movementLocked: Boolean(session.movementLocked),
direction: session.direction || 'down',
movementState: session.movementState || 'idle',
sequence: Number(session.movementSequence ?? 0),
};
} catch (error) {
this.logger.error('更新玩家业务状态失败', { socketId, error: (error as Error).message });
@@ -649,12 +667,22 @@ export class ChatSessionService implements ISessionManagerService {
y: number,
metadata: PlayerPresenceMetadata = {},
): Promise<boolean> {
if (!socketId?.trim() || !mapId?.trim()) return false;
return (await this.updatePlayerPositionWithPresence(socketId, mapId, x, y, metadata)) !== null;
}
async updatePlayerPositionWithPresence(
socketId: string,
mapId: string,
x: number,
y: number,
metadata: PlayerPresenceMetadata = {},
): Promise<MapPlayerPresence | null> {
if (!socketId?.trim() || !mapId?.trim()) return null;
try {
const sessionKey = `${this.SESSION_PREFIX}${socketId}`;
const sessionData = await this.redisService.get(sessionKey);
if (!sessionData) return false;
if (!sessionData) return null;
const session = this.deserializeSession(sessionData);
const oldMapId = session.currentMap;
@@ -666,6 +694,15 @@ export class ChatSessionService implements ISessionManagerService {
session.position = { x, y };
}
session.appearance = this.mergeAppearance(session.appearance, metadata.appearance);
if (metadata.direction !== undefined) {
session.direction = metadata.direction;
}
if (metadata.movementState !== undefined) {
session.movementState = metadata.movementState;
}
if (metadata.sequence !== undefined) {
session.movementSequence = metadata.sequence;
}
if (mapId !== 'whale_cafe') {
session.cafeCompanion = null;
session.movementLocked = false;
@@ -681,10 +718,23 @@ export class ChatSessionService implements ISessionManagerService {
await this.redisService.expire(newMapKey, SESSION_TIMEOUT);
}
return true;
return {
socketId: session.socketId,
userId: session.userId,
username: session.username,
mapId: session.currentMap,
x: Number(session.position?.x ?? 0),
y: Number(session.position?.y ?? 0),
appearance: session.appearance,
cafeCompanion: session.cafeCompanion ?? null,
movementLocked: Boolean(session.movementLocked),
direction: session.direction || 'down',
movementState: session.movementState || 'idle',
sequence: Number(session.movementSequence ?? 0),
};
} catch (error) {
this.logger.error('更新位置失败', { socketId, error: (error as Error).message });
return false;
return null;
}
}