Commit 56894877 authored by nanahira's avatar nanahira

add getHidPlayerName

parent a3e235cc
......@@ -2,3 +2,5 @@ webpack.config.js
dist/*
build/*
*.js
/ygopro
/windbot
import { NetPlayerType, YGOProStocHsPlayerEnter } from 'ygopro-msg-encode';
import { Context } from '../app';
import { DuelStage, OnRoomGameStart, RoomManager } from '../room';
import { DuelStage, OnRoomGameStart, Room, RoomManager } from '../room';
import { Client } from '../client';
declare module '../room' {
interface Room {
......@@ -14,30 +15,42 @@ export class HidePlayerNameProvider {
constructor(private ctx: Context) {}
async init() {
if (!this.enabled) {
return;
}
this.ctx.middleware(YGOProStocHsPlayerEnter, async (msg, client, next) => {
if (!client.roomName) {
return next();
getHidPlayerName(
client: Pick<Client, 'pos' | 'name' | 'roomName'>,
sightPlayer?: Client,
) {
if (!sightPlayer?.roomName) {
return client.name;
}
const room = this.roomManager.findByName(client.roomName);
const room = this.roomManager.findByName(
client.roomName || sightPlayer?.roomName,
);
if (!room?.hidePlayerNames || !this.shouldHide(room.duelStage)) {
return next();
return client.name;
}
const pos = msg.pos ?? -1;
if (
pos < 0 ||
pos >= NetPlayerType.OBSERVER ||
pos === client.pos ||
!msg.name
client.pos < 0 ||
client.pos >= NetPlayerType.OBSERVER ||
(sightPlayer && sightPlayer.pos === client.pos) ||
!client.name
) {
return next();
return client.name;
}
return `Player ${client.pos + 1}`;
}
async init() {
if (!this.enabled) {
return;
}
msg.name = `Player ${pos + 1}`;
this.ctx.middleware(YGOProStocHsPlayerEnter, async (msg, client, next) => {
const hidPlayerName = this.getHidPlayerName(msg, client);
if (hidPlayerName !== msg.name) {
msg.name = hidPlayerName;
}
return next();
});
......
......@@ -6,6 +6,7 @@ import { ChatColor } from 'ygopro-msg-encode';
import { Context } from '../../app';
import { RoomCheckDeck } from '../../room';
import { isUpdateDeckPayloadEqual } from '../../utility/deck-compare';
import { HidePlayerNameProvider } from '../hide-player-name-provider';
import { LockDeckExpectedDeckCheck } from './lock-deck-check';
class SrvproDeckBadError extends YGOProLFListError {
......@@ -20,6 +21,8 @@ class SrvproDeckBadError extends YGOProLFListError {
}
export class LockDeckService {
private hidePlayerNameProvider = this.ctx.get(() => HidePlayerNameProvider);
constructor(private ctx: Context) {}
async init() {
......@@ -44,7 +47,11 @@ export class LockDeckService {
}
if (expectedDeck === null) {
await client.sendChat(`${client.name}#{deck_not_found}`, ChatColor.RED);
const playerName = this.hidePlayerNameProvider.getHidPlayerName(
client,
client,
);
await client.sendChat(`${playerName}#{deck_not_found}`, ChatColor.RED);
return msg.use(new SrvproDeckBadError());
}
......
import { ChatColor, NetPlayerType } from 'ygopro-msg-encode';
import { Context } from '../app';
import { HidePlayerNameProvider } from './hide-player-name-provider';
import { OnRoomJoinObserver } from '../room/room-event/on-room-join-observer';
import { OnRoomLeave } from '../room/room-event/on-room-leave';
export class PlayerStatusNotify {
private hidePlayerNameProvider = this.ctx.get(() => HidePlayerNameProvider);
constructor(private ctx: Context) {}
async init() {
// 观战者加入
this.ctx.middleware(OnRoomJoinObserver, async (event, client, next) => {
const room = event.room;
await room.sendChat(`${client.name} #{watch_join}`, ChatColor.LIGHTBLUE);
await room.sendChat(
(sightPlayer) =>
`${this.hidePlayerNameProvider.getHidPlayerName(client, sightPlayer)} #{watch_join}`,
ChatColor.LIGHTBLUE,
);
return next();
});
......@@ -20,12 +27,17 @@ export class PlayerStatusNotify {
if (client.pos === NetPlayerType.OBSERVER) {
// 观战者离开
await room.sendChat(
`${client.name} #{quit_watch}`,
(sightPlayer) =>
`${this.hidePlayerNameProvider.getHidPlayerName(client, sightPlayer)} #{quit_watch}`,
ChatColor.LIGHTBLUE,
);
} else {
// 玩家离开
await room.sendChat(`${client.name} #{left_game}`, ChatColor.LIGHTBLUE);
await room.sendChat(
(sightPlayer) =>
`${this.hidePlayerNameProvider.getHidPlayerName(client, sightPlayer)} #{left_game}`,
ChatColor.LIGHTBLUE,
);
}
return next();
});
......
......@@ -100,6 +100,7 @@ export class RandomDuelProvider {
private clientKeyProvider = this.ctx.get(() => ClientKeyProvider);
private hidePlayerNameProvider = this.ctx.get(() => HidePlayerNameProvider);
private defaultHostInfoProvider = this.ctx.get(() => DefaultHostInfoProvider);
private hidePlayerName = this.ctx.get(() => HidePlayerNameProvider);
enabled = this.ctx.config.getBoolean('ENABLE_RANDOM_DUEL');
noRematchCheck = this.ctx.config.getBoolean('RANDOM_DUEL_NO_REMATCH_CHECK');
......@@ -530,7 +531,11 @@ export class RandomDuelProvider {
await this.unwelcome(room, client);
}
if (abuseCount >= 5) {
await room.sendChat(`${client.name} #{chat_banned}`, ChatColor.RED);
await room.sendChat(
(sightPlayer) =>
`${this.hidePlayerName.getHidPlayerName(client, sightPlayer)} #{chat_banned}`,
ChatColor.RED,
);
await this.punishPlayer(client, 'ABUSE');
client.disconnect();
}
......@@ -746,7 +751,7 @@ export class RandomDuelProvider {
const clientScoreText = await this.getScoreDisplay(
this.getClientKey(client),
client.name,
this.hidePlayerName.getHidPlayerName(client, client),
);
for (const player of players) {
if (clientScoreText) {
......@@ -757,7 +762,7 @@ export class RandomDuelProvider {
}
const playerScoreText = await this.getScoreDisplay(
this.getClientKey(player),
player.name,
this.hidePlayerName.getHidPlayerName(player, client),
);
if (playerScoreText) {
await client.sendChat(playerScoreText, ChatColor.GREEN);
......
......@@ -24,6 +24,7 @@ import { YGOProCtosDisconnect } from '../../utility/ygopro-ctos-disconnect';
import { isUpdateDeckPayloadEqual } from '../../utility/deck-compare';
import { CanReconnectCheck } from './can-reconnect-check';
import { ClientKeyProvider } from '../client-key-provider';
import { HidePlayerNameProvider } from '../hide-player-name-provider';
import { RefreshFieldService } from './refresh-field-service';
interface DisconnectInfo {
......@@ -57,6 +58,7 @@ export class Reconnect {
private disconnectList = new Map<string, DisconnectInfo>();
private reconnectTimeout = this.ctx.config.getInt('RECONNECT_TIMEOUT'); // 超时时间,单位:毫秒(默认 180000ms = 3分钟)
private clientKeyProvider = this.ctx.get(() => ClientKeyProvider);
private hidePlayerNameProvider = this.ctx.get(() => HidePlayerNameProvider);
private refreshFieldService = this.ctx.get(() => RefreshFieldService);
constructor(private ctx: Context) {}
......@@ -145,7 +147,8 @@ export class Reconnect {
// 通知房间
await room.sendChat(
`${client.name} #{disconnect_from_game}`,
(sightPlayer) =>
`${this.hidePlayerNameProvider.getHidPlayerName(client, sightPlayer)} #{disconnect_from_game}`,
ChatColor.LIGHTBLUE,
);
......@@ -283,7 +286,8 @@ export class Reconnect {
// 通知房间
await room.sendChat(
`${client.name} #{reconnect_to_game}`,
(sightPlayer) =>
`${this.hidePlayerNameProvider.getHidPlayerName(client, sightPlayer)} #{reconnect_to_game}`,
ChatColor.LIGHTBLUE,
);
......@@ -308,7 +312,8 @@ export class Reconnect {
// 通知房间
await room.sendChat(
`${client.name} #{reconnect_to_game}`,
(sightPlayer) =>
`${this.hidePlayerNameProvider.getHidPlayerName(client, sightPlayer)} #{reconnect_to_game}`,
ChatColor.LIGHTBLUE,
);
......
import { ChatColor, YGOProMsgNewTurn } from 'ygopro-msg-encode';
import { Context } from '../app';
import { RoomManager, DuelStage, OnRoomDuelStart, Room } from '../room';
import { HidePlayerNameProvider } from './hide-player-name-provider';
const DEATH_WIN_REASON = 0x11;
......@@ -12,6 +13,7 @@ declare module '../room' {
export class RoomDeathService {
private roomManager = this.ctx.get(() => RoomManager);
private hidePlayerNameProvider = this.ctx.get(() => HidePlayerNameProvider);
constructor(private ctx: Context) {}
......@@ -54,9 +56,17 @@ export class RoomDeathService {
if (room.turnCount >= room.death) {
if (lp0 !== lp1 && room.turnCount > 1) {
const winner = lp0 > lp1 ? 0 : 1;
const winnerName = room.getDuelPosPlayers(winner)[0]?.name || '';
const winnerPlayer = room.getDuelPosPlayers(winner)[0];
await room.sendChat(
`#{death_finish_part1}${winnerName}#{death_finish_part2}`,
(sightPlayer) =>
`#{death_finish_part1}${
winnerPlayer
? this.hidePlayerNameProvider.getHidPlayerName(
winnerPlayer,
sightPlayer,
)
: ''
}#{death_finish_part2}`,
ChatColor.BABYBLUE,
);
await room.win({
......@@ -96,9 +106,17 @@ export class RoomDeathService {
score0 !== score1
) {
const winner = score0 > score1 ? 0 : 1;
const winnerName = room.getDuelPosPlayers(winner)[0]?.name || '';
const winnerPlayer = room.getDuelPosPlayers(winner)[0];
await room.sendChat(
`#{death2_finish_part1}${winnerName}#{death2_finish_part2}`,
(sightPlayer) =>
`#{death2_finish_part1}${
winnerPlayer
? this.hidePlayerNameProvider.getHidPlayerName(
winnerPlayer,
sightPlayer,
)
: ''
}#{death2_finish_part2}`,
ChatColor.BABYBLUE,
);
await room.win(
......
......@@ -9,6 +9,7 @@ import {
OnRoomSidingStart,
Room,
} from '../room';
import { HidePlayerNameProvider } from './hide-player-name-provider';
import { merge, Subscription, timer } from 'rxjs';
import { filter, finalize, share, take, takeUntil } from 'rxjs/operators';
......@@ -22,6 +23,7 @@ declare module '../room' {
export class SideTimeout {
private logger = this.ctx.createLogger('SideTimeout');
private sideTimeoutMinutes = this.ctx.config.getInt('SIDE_TIMEOUT_MINUTES');
private hidePlayerNameProvider = this.ctx.get(() => HidePlayerNameProvider);
private onSidingReady$ = this.ctx.event$(OnRoomSidingReady).pipe(share());
private onLeavePlayer$ = this.ctx.event$(OnRoomLeavePlayer).pipe(share());
private onGameStart$ = this.ctx.event$(OnRoomGameStart).pipe(share());
......@@ -148,7 +150,8 @@ export class SideTimeout {
if (remainMinutes <= 1) {
this.clearSideTimeout(room, pos);
await room.sendChat(
`${client.name} #{side_overtime_room}`,
(sightPlayer) =>
`${this.hidePlayerNameProvider.getHidPlayerName(client, sightPlayer)} #{side_overtime_room}`,
ChatColor.BABYBLUE,
);
await client.sendChat('#{side_overtime}', ChatColor.RED);
......
......@@ -20,6 +20,7 @@ import {
Room,
RoomManager,
} from '../room';
import { HidePlayerNameProvider } from './hide-player-name-provider';
import { OnClientWaitTimeout } from './random-duel/random-duel-events';
export interface WaitForPlayerConfig {
......@@ -52,6 +53,7 @@ interface WaitForPlayerTickRuntime {
export class WaitForPlayerProvider {
private logger = this.ctx.createLogger(this.constructor.name);
private roomManager = this.ctx.get(() => RoomManager);
private hidePlayerNameProvider = this.ctx.get(() => HidePlayerNameProvider);
private tickRuntimes = new Map<number, WaitForPlayerTickRuntime>();
private nextTickId = 1;
......@@ -392,7 +394,8 @@ export class WaitForPlayerProvider {
) {
room.waitForPlayerReadyWarnRemain = remainSeconds;
await room.sendChat(
`${target.name} ${remainSeconds} #{kick_count_down}`,
(sightPlayer) =>
`${this.hidePlayerNameProvider.getHidPlayerName(target, sightPlayer)} ${remainSeconds} #{kick_count_down}`,
remainSeconds <= 9 ? ChatColor.RED : ChatColor.LIGHTBLUE,
);
}
......@@ -411,7 +414,8 @@ export class WaitForPlayerProvider {
return;
}
await room.sendChat(
`${latestTarget.name} #{kicked_by_system}`,
(sightPlayer) =>
`${this.hidePlayerNameProvider.getHidPlayerName(latestTarget, sightPlayer)} #{kicked_by_system}`,
ChatColor.RED,
);
await this.ctx.dispatch(
......@@ -462,7 +466,8 @@ export class WaitForPlayerProvider {
room.lastActiveTime = new Date(nowMs);
room.waitForPlayerHangWarnElapsed = undefined;
await room.sendChat(
`${waitingPlayer.name} #{kicked_by_system}`,
(sightPlayer) =>
`${this.hidePlayerNameProvider.getHidPlayerName(waitingPlayer, sightPlayer)} #{kicked_by_system}`,
ChatColor.RED,
);
await this.ctx.dispatch(
......@@ -485,7 +490,8 @@ export class WaitForPlayerProvider {
);
if (remainSeconds > 0) {
await room.sendChat(
`${waitingPlayer.name} #{afk_warn_part1}${remainSeconds}#{afk_warn_part2}`,
(sightPlayer) =>
`${this.hidePlayerNameProvider.getHidPlayerName(waitingPlayer, sightPlayer)} #{afk_warn_part1}${remainSeconds}#{afk_warn_part2}`,
ChatColor.RED,
);
}
......
......@@ -2,10 +2,12 @@ import { ChatColor, YGOProCtosJoinGame } from 'ygopro-msg-encode';
import { Context } from '../app';
import { LegacyBanEntity } from './legacy-ban.entity';
import { RoomManager } from '../room';
import { HidePlayerNameProvider } from '../feats';
import { LegacyApiService } from './legacy-api-service';
export class LegacyBanService {
private logger = this.ctx.createLogger('LegacyBanService');
private hidePlayerNameProvider = this.ctx.get(() => HidePlayerNameProvider);
constructor(private ctx: Context) {
this.ctx
......@@ -76,7 +78,8 @@ export class LegacyBanService {
}
await room.sendChat(
`${player.name} #{kicked_by_system}`,
(sightPlayer) =>
`${this.hidePlayerNameProvider.getHidPlayerName(player, sightPlayer)} #{kicked_by_system}`,
ChatColor.RED,
);
await room.kick(player);
......
......@@ -959,11 +959,19 @@ export class Room {
return this.sendChat(msg.msg, this.getIngamePos(client));
}
async sendChat(msg: string, type: number = ChatColor.BABYBLUE) {
async sendChat(
msg: string | ((p: Client) => Awaitable<string>),
type: number = ChatColor.BABYBLUE,
) {
if (this.finalizing) {
return;
}
return Promise.all(this.allPlayers.map((p) => p.sendChat(msg, type)));
return Promise.all(
this.allPlayers.map(async (p) => {
const resolvedMessage = typeof msg === 'function' ? await msg(p) : msg;
return p.sendChat(resolvedMessage, type);
}),
);
}
firstgoPos?: number;
......
......@@ -20,6 +20,7 @@
"*.ts",
"src/**/*.ts",
"test/**/*.ts",
"tests/**/*.ts"
"tests/**/*.ts",
"plugins/**/*.ts"
]
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment