Commit 33727617 authored by nanahira's avatar nanahira

Merge branch 'master' of ../srvpro into koishi

parents 9e33544d 599ef254
...@@ -22,7 +22,7 @@ class Challonge { ...@@ -22,7 +22,7 @@ class Challonge {
return this.previous; return this.previous;
} }
try { try {
const { data: { tournament } } = await axios_1.default.get(`https://api.challonge.com/v1/tournaments/${this.config.tournament_id}.json`, { const { data: { tournament } } = await axios_1.default.get(`${this.config.challonge_url}/v1/tournaments/${this.config.tournament_id}.json`, {
params: { params: {
api_key: this.config.api_key, api_key: this.config.api_key,
include_participants: 1, include_participants: 1,
...@@ -35,7 +35,7 @@ class Challonge { ...@@ -35,7 +35,7 @@ class Challonge {
return tournament; return tournament;
} }
catch (e) { catch (e) {
this.log.error(`Failed to get tournament ${this.config.tournament_id}`, e); this.log.error(`Failed to get tournament ${this.config.tournament_id}: ${e}`);
return; return;
} }
} }
...@@ -47,7 +47,7 @@ class Challonge { ...@@ -47,7 +47,7 @@ class Challonge {
} }
async putScore(matchId, match, retried = 0) { async putScore(matchId, match, retried = 0) {
try { try {
await axios_1.default.put(`https://api.challonge.com/v1/tournaments/${this.config.tournament_id}/matches/${matchId}.json`, { await axios_1.default.put(`${this.config.challonge_url}/v1/tournaments/${this.config.tournament_id}/matches/${matchId}.json`, {
api_key: this.config.api_key, api_key: this.config.api_key,
match: match, match: match,
}); });
...@@ -56,7 +56,7 @@ class Challonge { ...@@ -56,7 +56,7 @@ class Challonge {
return true; return true;
} }
catch (e) { catch (e) {
this.log.error(`Failed to put score for match ${matchId}`, e); this.log.error(`Failed to put score for match ${matchId}: ${e}`);
if (retried < 5) { if (retried < 5) {
this.log.info(`Retrying match ${matchId}`); this.log.info(`Retrying match ${matchId}`);
return this.putScore(matchId, match, retried + 1); return this.putScore(matchId, match, retried + 1);
...@@ -67,6 +67,34 @@ class Challonge { ...@@ -67,6 +67,34 @@ class Challonge {
} }
} }
} }
async clearParticipants() {
try {
await axios_1.default.delete(`${this.config.challonge_url}/v1/tournaments/${this.config.tournament_id}/participants/clear.json`, {
params: {
api_key: this.config.api_key
},
validateStatus: () => true,
});
return true;
}
catch (e) {
this.log.error(`Failed to clear participants for tournament ${this.config.tournament_id}: ${e}`);
return false;
}
}
async uploadParticipants(participantNames) {
try {
await axios_1.default.post(`${this.config.challonge_url}/v1/tournaments/${this.config.tournament_id}/participants/bulk_add.json`, {
api_key: this.config.api_key,
participants: participantNames.map(name => ({ name })),
});
return true;
}
catch (e) {
this.log.error(`Failed to upload participants for tournament ${this.config.tournament_id}: ${e}`);
return false;
}
}
} }
exports.Challonge = Challonge; exports.Challonge = Challonge;
//# sourceMappingURL=challonge.js.map //# sourceMappingURL=challonge.js.map
\ No newline at end of file
...@@ -2,34 +2,15 @@ import axios from 'axios'; ...@@ -2,34 +2,15 @@ import axios from 'axios';
import { createLogger } from 'bunyan'; import { createLogger } from 'bunyan';
import moment, { Moment } from 'moment'; import moment, { Moment } from 'moment';
import PQueue from 'p-queue'; import PQueue from 'p-queue';
import _ from 'underscore';
export interface Match { export interface Match {
attachment_count?: any;
created_at: string;
group_id?: any;
has_attachment: boolean;
id: number; id: number;
identifier: string; state: 'pending' | 'open' | 'complete'; // pending: 还未开始,open: 进行中,complete: 已结束
location?: any;
loser_id?: any;
player1_id: number; player1_id: number;
player1_is_prereq_match_loser: boolean;
player1_prereq_match_id?: any;
player1_votes?: any;
player2_id: number; player2_id: number;
player2_is_prereq_match_loser: boolean; winner_id?: number | 'tie'; // 如果存在,则代表该比赛已经结束
player2_prereq_match_id?: any; scores_csv?: string; // 比分,2-1 这样的格式,请保证和上传的情况相同
player2_votes?: any;
round: number;
scheduled_time?: any;
started_at: string;
state: string;
tournament_id: number;
underway_at?: any;
updated_at: string;
winner_id?: any;
prerequisite_match_ids_csv: string;
scores_csv: string;
} }
export interface MatchWrapper { export interface MatchWrapper {
...@@ -37,34 +18,9 @@ export interface MatchWrapper { ...@@ -37,34 +18,9 @@ export interface MatchWrapper {
} }
export interface Participant { export interface Participant {
active: boolean;
checked_in_at?: any;
created_at: string;
final_rank?: any;
group_id?: any;
icon?: any;
id: number; id: number;
invitation_id?: any;
invite_email?: any;
misc?: any;
name: string; name: string;
on_waiting_list: boolean; deckbuf?: string;
seed: number;
tournament_id: number;
updated_at: string;
challonge_username?: any;
challonge_email_address_verified?: any;
removable: boolean;
participatable_or_invitation_attached: boolean;
confirm_remove: boolean;
invitation_pending: boolean;
display_name_with_invitation_email_address: string;
email_hash?: any;
username?: any;
attached_participatable_portrait_url?: any;
can_check_in: boolean;
checked_in: boolean;
reactivatable: boolean;
} }
export interface ParticipantWrapper { export interface ParticipantWrapper {
...@@ -72,86 +28,27 @@ export interface ParticipantWrapper { ...@@ -72,86 +28,27 @@ export interface ParticipantWrapper {
} }
export interface Tournament { export interface Tournament {
accept_attachments: boolean;
allow_participant_match_reporting: boolean;
anonymous_voting: boolean;
category?: any;
check_in_duration?: any;
completed_at?: any;
created_at: string;
created_by_api: boolean;
credit_capped: boolean;
description: string;
game_id: number;
group_stages_enabled: boolean;
hide_forum: boolean;
hide_seeds: boolean;
hold_third_place_match: boolean;
id: number; id: number;
max_predictions_per_user: number;
name: string;
notify_users_when_matches_open: boolean;
notify_users_when_the_tournament_ends: boolean;
open_signup: boolean;
participants_count: number;
prediction_method: number;
predictions_opened_at?: any;
private: boolean;
progress_meter: number;
pts_for_bye: string;
pts_for_game_tie: string;
pts_for_game_win: string;
pts_for_match_tie: string;
pts_for_match_win: string;
quick_advance: boolean;
ranked_by: string;
require_score_agreement: boolean;
rr_pts_for_game_tie: string;
rr_pts_for_game_win: string;
rr_pts_for_match_tie: string;
rr_pts_for_match_win: string;
sequential_pairings: boolean;
show_rounds: boolean;
signup_cap?: any;
start_at?: any;
started_at: string;
started_checking_in_at?: any;
state: string;
swiss_rounds: number;
teams: boolean;
tie_breaks: string[];
tournament_type: string;
updated_at: string;
url: string;
description_source: string;
subdomain?: any;
full_challonge_url: string;
live_image_url: string;
sign_up_url?: any;
review_before_finalizing: boolean;
accepting_predictions: boolean;
participants_locked: boolean;
game_name: string;
participants_swappable: boolean;
team_convertable: boolean;
group_stages_were_started: boolean;
participants: ParticipantWrapper[]; participants: ParticipantWrapper[];
matches: MatchWrapper[]; matches: MatchWrapper[];
} }
// GET /v1/tournaments/${tournament_id}.json?api_key=xxx&include_participants=1&include_matches=1 returns { tournament: Tournament }
export interface TournamentWrapper { export interface TournamentWrapper {
tournament: Tournament; tournament: Tournament;
} }
// PUT /v1/tournaments/${tournament_id}/matches/${match_id}.json { api_key: string, match: MatchPost } returns ANY
export interface MatchPost { export interface MatchPost {
scores_csv: string; scores_csv: string; // 比分。2-1 这样的格式。可能有特殊情况,比如 -9-1 或者 1--9,代表有一方掉线,或是加时赛胜利。也就是允许负数(从第一串数字的最后一个 - 区分)
winner_id: number; winner_id?: number | 'tie'; // 上传比分的时候这个字段不一定存在。如果不存在的话代表比赛没打完(比如 1-0 就会上传,这时候换 side)
} }
export interface ChallongeConfig { export interface ChallongeConfig {
api_key: string; api_key: string;
tournament_id: string; tournament_id: string;
cache_ttl: number; cache_ttl: number;
challonge_url: string;
} }
export class Challonge { export class Challonge {
...@@ -169,7 +66,7 @@ export class Challonge { ...@@ -169,7 +66,7 @@ export class Challonge {
} }
try { try {
const { data: { tournament } } = await axios.get<TournamentWrapper>( const { data: { tournament } } = await axios.get<TournamentWrapper>(
`https://api.challonge.com/v1/tournaments/${this.config.tournament_id}.json`, `${this.config.challonge_url}/v1/tournaments/${this.config.tournament_id}.json`,
{ {
params: { params: {
api_key: this.config.api_key, api_key: this.config.api_key,
...@@ -183,7 +80,7 @@ export class Challonge { ...@@ -183,7 +80,7 @@ export class Challonge {
this.previousTime = moment(); this.previousTime = moment();
return tournament; return tournament;
} catch (e) { } catch (e) {
this.log.error(`Failed to get tournament ${this.config.tournament_id}`, e); this.log.error(`Failed to get tournament ${this.config.tournament_id}: ${e}`);
return; return;
} }
} }
...@@ -198,7 +95,7 @@ export class Challonge { ...@@ -198,7 +95,7 @@ export class Challonge {
async putScore(matchId: number, match: MatchPost, retried = 0) { async putScore(matchId: number, match: MatchPost, retried = 0) {
try { try {
await axios.put( await axios.put(
`https://api.challonge.com/v1/tournaments/${this.config.tournament_id}/matches/${matchId}.json`, `${this.config.challonge_url}/v1/tournaments/${this.config.tournament_id}/matches/${matchId}.json`,
{ {
api_key: this.config.api_key, api_key: this.config.api_key,
match: match, match: match,
...@@ -208,7 +105,7 @@ export class Challonge { ...@@ -208,7 +105,7 @@ export class Challonge {
this.previousTime = undefined; this.previousTime = undefined;
return true; return true;
} catch (e) { } catch (e) {
this.log.error(`Failed to put score for match ${matchId}`, e); this.log.error(`Failed to put score for match ${matchId}: ${e}`);
if (retried < 5) { if (retried < 5) {
this.log.info(`Retrying match ${matchId}`); this.log.info(`Retrying match ${matchId}`);
return this.putScore(matchId, match, retried + 1); return this.putScore(matchId, match, retried + 1);
...@@ -218,4 +115,34 @@ export class Challonge { ...@@ -218,4 +115,34 @@ export class Challonge {
} }
} }
} }
// DELETE /v1/tournaments/${tournament_id}/participants/clear.json?api_key=xxx returns ANY
async clearParticipants() {
try {
await axios.delete(`${this.config.challonge_url}/v1/tournaments/${this.config.tournament_id}/participants/clear.json`, {
params: {
api_key: this.config.api_key
},
validateStatus: () => true,
})
return true;
} catch (e) {
this.log.error(`Failed to clear participants for tournament ${this.config.tournament_id}: ${e}`);
return false;
}
}
// POST /v1/tournaments/${tournament_id}/participants/bulk_add.json { api_key: string, participants: { name: string }[] } returns ANY
async uploadParticipants(participantNames: string[]) {
try {
await axios.post(`${this.config.challonge_url}/v1/tournaments/${this.config.tournament_id}/participants/bulk_add.json`, {
api_key: this.config.api_key,
participants: participantNames.map(name => ({ name })),
});
return true;
} catch (e) {
this.log.error(`Failed to upload participants for tournament ${this.config.tournament_id}: ${e}`);
return false;
}
}
} }
...@@ -726,12 +726,12 @@ class DataManager { ...@@ -726,12 +726,12 @@ class DataManager {
newScore.name = name; newScore.name = name;
return await this.saveRandomDuelScore(newScore); return await this.saveRandomDuelScore(newScore);
} }
async getRandomDuelScoreDisplay(name) { async getRandomDuelScoreDisplay(name, displayName) {
const score = await this.getRandomDuelScore(name); const score = await this.getRandomDuelScore(name);
if (!score) { if (!score) {
return `${name.split("$")[0]} \${random_score_blank}`; return `${displayName} \${random_score_blank}`;
} }
return score.getScoreText(); return score.getScoreText(displayName);
} }
async randomDuelPlayerWin(name) { async randomDuelPlayerWin(name) {
const score = await this.getOrCreateRandomDuelScore(name); const score = await this.getOrCreateRandomDuelScore(name);
......
...@@ -723,12 +723,12 @@ export class DataManager { ...@@ -723,12 +723,12 @@ export class DataManager {
newScore.name = name; newScore.name = name;
return await this.saveRandomDuelScore(newScore); return await this.saveRandomDuelScore(newScore);
} }
async getRandomDuelScoreDisplay(name: string) { async getRandomDuelScoreDisplay(name: string, displayName: string) {
const score = await this.getRandomDuelScore(name); const score = await this.getRandomDuelScore(name);
if(!score) { if(!score) {
return `${name.split("$")[0]} \${random_score_blank}`; return `${displayName} \${random_score_blank}`;
} }
return score.getScoreText(); return score.getScoreText(displayName);
} }
async randomDuelPlayerWin(name: string) { async randomDuelPlayerWin(name: string) {
const score = await this.getOrCreateRandomDuelScore(name); const score = await this.getOrCreateRandomDuelScore(name);
......
...@@ -33,8 +33,7 @@ let RandomDuelScore = class RandomDuelScore extends CreateAndUpdateTimeBase_1.Cr ...@@ -33,8 +33,7 @@ let RandomDuelScore = class RandomDuelScore extends CreateAndUpdateTimeBase_1.Cr
++this.fleeCount; ++this.fleeCount;
this.lose(); this.lose();
} }
getScoreText() { getScoreText(displayName) {
const displayName = this.getDisplayName();
const total = this.winCount + this.loseCount; const total = this.winCount + this.loseCount;
if (this.winCount < 2 && total < 3) { if (this.winCount < 2 && total < 3) {
return `${displayName} \${random_score_not_enough}`; return `${displayName} \${random_score_not_enough}`;
......
...@@ -40,8 +40,7 @@ export class RandomDuelScore extends CreateAndUpdateTimeBase { ...@@ -40,8 +40,7 @@ export class RandomDuelScore extends CreateAndUpdateTimeBase {
this.lose(); this.lose();
} }
getScoreText() { getScoreText(displayName: string) {
const displayName = this.getDisplayName();
const total = this.winCount + this.loseCount; const total = this.winCount + this.loseCount;
if (this.winCount < 2 && total < 3) { if (this.winCount < 2 && total < 3) {
return `${displayName} \${random_score_not_enough}`; return `${displayName} \${random_score_not_enough}`;
......
...@@ -90,6 +90,7 @@ ...@@ -90,6 +90,7 @@
"record_match_scores": false, "record_match_scores": false,
"post_match_scores": false, "post_match_scores": false,
"post_match_accesskey": "123456", "post_match_accesskey": "123456",
"disable_chat": false,
"blank_pass_modes": { "blank_pass_modes": {
"S": true, "S": true,
"M": true, "M": true,
...@@ -163,7 +164,8 @@ ...@@ -163,7 +164,8 @@
"cache_ttl": 60000, "cache_ttl": 60000,
"no_match_mode": false, "no_match_mode": false,
"api_key": "123", "api_key": "123",
"tournament_id": "456" "tournament_id": "456",
"challonge_url": "https://api.challonge.com"
}, },
"deck_log": { "deck_log": {
"enabled": false, "enabled": false,
......
...@@ -209,6 +209,7 @@ ...@@ -209,6 +209,7 @@
"refresh_failed": "Refresh field failed.", "refresh_failed": "Refresh field failed.",
"banned_athletic_deck_part1": "Entertainment Mode does not allow top ", "banned_athletic_deck_part1": "Entertainment Mode does not allow top ",
"banned_athletic_deck_part2": " popular meta decks. Please change your deck.", "banned_athletic_deck_part2": " popular meta decks. Please change your deck.",
"chat_disabled": "Chat is disabled in this room.",
"using_athletic_deck": " is using a competitive deck." "using_athletic_deck": " is using a competitive deck."
}, },
"es-es": { "es-es": {
...@@ -567,6 +568,7 @@ ...@@ -567,6 +568,7 @@
"refresh_fail": "刷新场面失败。", "refresh_fail": "刷新场面失败。",
"banned_athletic_deck_part1": "娱乐匹配中禁止使用使用数前", "banned_athletic_deck_part1": "娱乐匹配中禁止使用使用数前",
"banned_athletic_deck_part2": "的竞技卡组。请更换卡组。", "banned_athletic_deck_part2": "的竞技卡组。请更换卡组。",
"chat_disabled": "本房间禁止聊天。",
"using_athletic_deck": " 正在使用竞技卡组。" "using_athletic_deck": " 正在使用竞技卡组。"
}, },
"ko-kr": { "ko-kr": {
......
...@@ -78,7 +78,8 @@ ...@@ -78,7 +78,8 @@
], ],
"STOC_HS_PlayerEnter": [ "STOC_HS_PlayerEnter": [
{"name": "name", "type": "unsigned short", "length": 20, "encoding": "UTF-16LE"}, {"name": "name", "type": "unsigned short", "length": 20, "encoding": "UTF-16LE"},
{"name": "pos", "type": "unsigned char"} {"name": "pos", "type": "unsigned char"},
{"name": "padding", "type": "unsigned char"}
], ],
"STOC_HS_PlayerChange": [ "STOC_HS_PlayerChange": [
{"name": "status", "type": "unsigned char"} {"name": "status", "type": "unsigned char"}
......
...@@ -395,6 +395,9 @@ init = () -> ...@@ -395,6 +395,9 @@ init = () ->
} }
delete settings.modules.random_duel.blank_pass_match delete settings.modules.random_duel.blank_pass_match
imported = true imported = true
if settings.modules.hide_name == true
settings.modules.hide_name = "start"
imported = true
#finish #finish
keysFromEnv = Object.keys(process.env).filter((key) => key.startsWith('SRVPRO_')) keysFromEnv = Object.keys(process.env).filter((key) => key.startsWith('SRVPRO_'))
if keysFromEnv.length > 0 if keysFromEnv.length > 0
...@@ -810,10 +813,10 @@ ROOM_player_flee = global.ROOM_player_flee = (name)-> ...@@ -810,10 +813,10 @@ ROOM_player_flee = global.ROOM_player_flee = (name)->
await dataManager.randomDuelPlayerFlee(name) await dataManager.randomDuelPlayerFlee(name)
return return
ROOM_player_get_score = global.ROOM_player_get_score = (player)-> ROOM_player_get_score = global.ROOM_player_get_score = (player, display_name)->
if !settings.modules.mysql.enabled if !settings.modules.mysql.enabled
return "" return ""
return await dataManager.getRandomDuelScoreDisplay(player.name_vpass) return await dataManager.getRandomDuelScoreDisplay(player.name_vpass, display_name)
ROOM_find_or_create_by_name = global.ROOM_find_or_create_by_name = (name, player_ip)-> ROOM_find_or_create_by_name = global.ROOM_find_or_create_by_name = (name, player_ip)->
uname=name.toUpperCase() uname=name.toUpperCase()
...@@ -853,7 +856,7 @@ ROOM_find_or_create_random = global.ROOM_find_or_create_random = (type, player_i ...@@ -853,7 +856,7 @@ ROOM_find_or_create_random = global.ROOM_find_or_create_random = (type, player_i
max_player = if type == 'T' then 4 else 2 max_player = if type == 'T' then 4 else 2
playerbanned = (randomDuelBanRecord and randomDuelBanRecord.count > 3 and moment_now < randomDuelBanRecord.time) playerbanned = (randomDuelBanRecord and randomDuelBanRecord.count > 3 and moment_now < randomDuelBanRecord.time)
result = _.find ROOM_all, (room)-> result = _.find ROOM_all, (room)->
return room and room.random_type != '' and room.duel_stage == ygopro.constants.DUEL_STAGE.BEGIN and !room.windbot and return room and room.random_type != '' and !room.disconnector and room.duel_stage == ygopro.constants.DUEL_STAGE.BEGIN and !room.windbot and
((type == '' and ((type == '' and
(room.random_type == settings.modules.random_duel.default_type or (room.random_type == settings.modules.random_duel.default_type or
settings.modules.random_duel.blank_pass_modes[room.random_type])) or settings.modules.random_duel.blank_pass_modes[room.random_type])) or
...@@ -1023,7 +1026,7 @@ CLIENT_reconnect_register = global.CLIENT_reconnect_register = (client, room_id, ...@@ -1023,7 +1026,7 @@ CLIENT_reconnect_register = global.CLIENT_reconnect_register = (client, room_id,
dinfo.timeout = tmot dinfo.timeout = tmot
disconnect_list[CLIENT_get_authorize_key(client)] = dinfo disconnect_list[CLIENT_get_authorize_key(client)] = dinfo
#console.log("#{client.name} ${disconnect_from_game}") #console.log("#{client.name} ${disconnect_from_game}")
ygopro.stoc_send_chat_to_room(room, "#{client.name} ${disconnect_from_game}" + if error then ": #{error}" else '') ygopro.stoc_send_chat_to_room(room, "#{room.getMaskedPlayerName(client)} ${disconnect_from_game}" + if error then ": #{error}" else '')
if client.time_confirm_required if client.time_confirm_required
client.time_confirm_required = false client.time_confirm_required = false
ygopro.ctos_send(client.server, 'TIME_CONFIRM') ygopro.ctos_send(client.server, 'TIME_CONFIRM')
...@@ -1088,13 +1091,13 @@ CLIENT_is_able_to_reconnect = global.CLIENT_is_able_to_reconnect = (client, deck ...@@ -1088,13 +1091,13 @@ CLIENT_is_able_to_reconnect = global.CLIENT_is_able_to_reconnect = (client, deck
if !room if !room
CLIENT_reconnect_unregister(client) CLIENT_reconnect_unregister(client)
return false return false
if deckbuf and deckbuf.compare(disconnect_info.deckbuf) != 0 if deckbuf and not deckbuf.equals(disconnect_info.deckbuf)
return false return false
return true return true
CLIENT_get_kick_reconnect_target = global.CLIENT_get_kick_reconnect_target = (client, deckbuf) -> CLIENT_get_kick_reconnect_target = global.CLIENT_get_kick_reconnect_target = (client, deckbuf) ->
for room in ROOM_all when room and room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN and !room.windbot for room in ROOM_all when room and room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN and !room.windbot
for player in room.get_playing_player() when !player.isClosed and player.name == client.name and (settings.modules.challonge.enabled or player.pass == client.pass) and (settings.modules.mycard.enabled or settings.modules.tournament_mode.enabled or player.ip == client.ip or (client.vpass and client.vpass == player.vpass)) and (!deckbuf or deckbuf.compare(player.start_deckbuf) == 0) for player in room.get_playing_player() when !player.isClosed and player.name == client.name and (settings.modules.challonge.enabled or player.pass == client.pass) and (settings.modules.mycard.enabled or settings.modules.tournament_mode.enabled or player.ip == client.ip or (client.vpass and client.vpass == player.vpass)) and (!deckbuf or deckbuf.equals(player.start_deckbuf))
return player return player
return null return null
...@@ -1116,8 +1119,9 @@ CLIENT_send_pre_reconnect_info = global.CLIENT_send_pre_reconnect_info = (client ...@@ -1116,8 +1119,9 @@ CLIENT_send_pre_reconnect_info = global.CLIENT_send_pre_reconnect_info = (client
}) })
for player in room.players for player in room.players
ygopro.stoc_send(client, 'HS_PLAYER_ENTER', { ygopro.stoc_send(client, 'HS_PLAYER_ENTER', {
name: player.name, name: room.getMaskedPlayerName(player, old_client),
pos: player.pos, pos: player.pos,
padding: 0,
}) })
return return
...@@ -1185,7 +1189,7 @@ CLIENT_reconnect = global.CLIENT_reconnect = (client) -> ...@@ -1185,7 +1189,7 @@ CLIENT_reconnect = global.CLIENT_reconnect = (client) ->
CLIENT_import_data(client, dinfo.old_client, room) CLIENT_import_data(client, dinfo.old_client, room)
CLIENT_send_reconnect_info(client, client.server, room) CLIENT_send_reconnect_info(client, client.server, room)
#console.log("#{client.name} ${reconnect_to_game}") #console.log("#{client.name} ${reconnect_to_game}")
ygopro.stoc_send_chat_to_room(room, "#{client.name} ${reconnect_to_game}") ygopro.stoc_send_chat_to_room(room, "#{room.getMaskedPlayerName(client)} ${reconnect_to_game}")
CLIENT_reconnect_unregister(client, true) CLIENT_reconnect_unregister(client, true)
return return
...@@ -1566,8 +1570,9 @@ class Room ...@@ -1566,8 +1570,9 @@ class Room
return if @deleted return if @deleted
#log.info 'room-delete', this.name, ROOM_all.length #log.info 'room-delete', this.name, ROOM_all.length
score_array=[] score_array=[]
for name, score of @scores for name_vpass, score of @scores
score_form = { name: name.split('$')[0], score: score, deck: null, name_vpass: name } name = name_vpass.split('$')[0]
score_form = { name: name, score: score, deck: null, name_vpass: name_vpass }
if @decks[name] if @decks[name]
score_form.deck = @decks[name] score_form.deck = @decks[name]
score_array.push score_form score_array.push score_form
...@@ -1809,7 +1814,7 @@ class Room ...@@ -1809,7 +1814,7 @@ class Room
if settings.modules.random_duel.record_match_scores and @random_type == 'M' if settings.modules.random_duel.record_match_scores and @random_type == 'M'
ROOM_player_flee(client.name_vpass) ROOM_player_flee(client.name_vpass)
if @players.length and !(@windbot and client.is_host and @duel_stage == ygopro.constants.DUEL_STAGE.BEGIN) and !(@arena and @duel_stage == ygopro.constants.DUEL_STAGE.BEGIN and client.pos <= 3) if @players.length and !(@windbot and client.is_host and @duel_stage == ygopro.constants.DUEL_STAGE.BEGIN) and !(@arena and @duel_stage == ygopro.constants.DUEL_STAGE.BEGIN and client.pos <= 3)
left_name = (if settings.modules.hide_name and @duel_stage == ygopro.constants.DUEL_STAGE.BEGIN then "********" else client.name) left_name = @getMaskedPlayerName(client)
ygopro.stoc_send_chat_to_room this, "#{left_name} ${left_game}" + if error then ": #{error}" else '' ygopro.stoc_send_chat_to_room this, "#{left_name} ${left_game}" + if error then ": #{error}" else ''
roomlist.update(this) if !@windbot and @duel_stage == ygopro.constants.DUEL_STAGE.BEGIN and settings.modules.http.websocket_roomlist roomlist.update(this) if !@windbot and @duel_stage == ygopro.constants.DUEL_STAGE.BEGIN and settings.modules.http.websocket_roomlist
#client.room = null #client.room = null
...@@ -1983,10 +1988,17 @@ class Room ...@@ -1983,10 +1988,17 @@ class Room
@watcher_buffers.push chat_buf @watcher_buffers.push chat_buf
return return
getMaskedPlayerName: (player, sight_player) ->
if not settings.modules.hide_name or (sight_player and player == sight_player) or not (@random_type or @arena)
return player.name
if (@duel_stage == ygopro.constants.DUEL_STAGE.BEGIN and settings.modules.hide_name == "start") or settings.modules.hide_name == "always"
return "Player #{player.pos + 1}"
return player.name
# 网络连接 # 网络连接
netRequestHandler = (client) -> netRequestHandler = (client) ->
if !client.isWs if !client.isWs
client.ip = client.remoteAddress client.ip = client.remoteAddress or ''
client.is_local = client.ip and (client.ip.includes('127.0.0.1') or client.ip.includes(real_windbot_server_ip)) client.is_local = client.ip and (client.ip.includes('127.0.0.1') or client.ip.includes(real_windbot_server_ip))
connect_count = ROOM_connected_ip[client.ip] or 0 connect_count = ROOM_connected_ip[client.ip] or 0
...@@ -2382,8 +2394,8 @@ ygopro.ctos_follow 'JOIN_GAME', true, (buffer, info, client, server, datas)-> ...@@ -2382,8 +2394,8 @@ ygopro.ctos_follow 'JOIN_GAME', true, (buffer, info, client, server, datas)->
#console.log(options) #console.log(options)
if options.rule == 2 if options.rule == 2
options.lflist = -1 options.lflist = -1
else if options.rule != 3 #else if options.rule != 3
options.lflist = _.findIndex lflists, (list)-> ((options.rule == 1) == list.tcg) and list.date.isBefore() # options.lflist = _.findIndex lflists, (list)-> ((options.rule == 1) == list.tcg) and list.date.isBefore()
room_title = info.pass.slice(8).replace(String.fromCharCode(0xFEFF), ' ') room_title = info.pass.slice(8).replace(String.fromCharCode(0xFEFF), ' ')
if badwordR.level3.test(room_title) if badwordR.level3.test(room_title)
log.warn("BAD ROOM NAME LEVEL 3", room_title, client.name, client.ip) log.warn("BAD ROOM NAME LEVEL 3", room_title, client.name, client.ip)
...@@ -2604,7 +2616,7 @@ ygopro.stoc_follow 'JOIN_GAME', false, (buffer, info, client, server, datas)-> ...@@ -2604,7 +2616,7 @@ ygopro.stoc_follow 'JOIN_GAME', false, (buffer, info, client, server, datas)->
ygopro.stoc_send_chat(client, room.welcome, ygopro.constants.COLORS.BABYBLUE) ygopro.stoc_send_chat(client, room.welcome, ygopro.constants.COLORS.BABYBLUE)
if room.welcome2 if room.welcome2
ygopro.stoc_send_chat(client, room.welcome2, ygopro.constants.COLORS.PINK) ygopro.stoc_send_chat(client, room.welcome2, ygopro.constants.COLORS.PINK)
if settings.modules.arena_mode.enabled and !client.is_local #and not client.score_shown if settings.modules.arena_mode.enabled and !client.is_local and settings.modules.arena_mode.get_score #and not client.score_shown
request request
url: settings.modules.arena_mode.get_score + encodeURIComponent(client.name), url: settings.modules.arena_mode.get_score + encodeURIComponent(client.name),
json: true json: true
...@@ -2620,9 +2632,10 @@ ygopro.stoc_follow 'JOIN_GAME', false, (buffer, info, client, server, datas)-> ...@@ -2620,9 +2632,10 @@ ygopro.stoc_follow 'JOIN_GAME', false, (buffer, info, client, server, datas)->
#client.score_shown = true #client.score_shown = true
return return
if settings.modules.random_duel.record_match_scores and room.random_type == 'M' if settings.modules.random_duel.record_match_scores and room.random_type == 'M'
ygopro.stoc_send_chat_to_room(room, await ROOM_player_get_score(client), ygopro.constants.COLORS.GREEN) for player in room.players when player.pos != 7
ygopro.stoc_send_chat(player, await ROOM_player_get_score(client, room.getMaskedPlayerName(client, player)), ygopro.constants.COLORS.GREEN)
for player in room.players when player.pos != 7 and player != client for player in room.players when player.pos != 7 and player != client
ygopro.stoc_send_chat(client, await ROOM_player_get_score(player), ygopro.constants.COLORS.GREEN) ygopro.stoc_send_chat(client, await ROOM_player_get_score(player, room.getMaskedPlayerName(player, client)), ygopro.constants.COLORS.GREEN)
if !room.recorder if !room.recorder
room.recorder = recorder = net.connect room.port, -> room.recorder = recorder = net.connect room.port, ->
ygopro.ctos_send recorder, 'PLAYER_INFO', { ygopro.ctos_send recorder, 'PLAYER_INFO', {
...@@ -3026,12 +3039,12 @@ ygopro.stoc_follow 'TYPE_CHANGE', true, (buffer, info, client, server, datas)-> ...@@ -3026,12 +3039,12 @@ ygopro.stoc_follow 'TYPE_CHANGE', true, (buffer, info, client, server, datas)->
ygopro.stoc_follow 'HS_PLAYER_ENTER', true, (buffer, info, client, server, datas)-> ygopro.stoc_follow 'HS_PLAYER_ENTER', true, (buffer, info, client, server, datas)->
room=ROOM_all[client.rid] room=ROOM_all[client.rid]
return false unless room and settings.modules.hide_name and room.duel_stage == ygopro.constants.DUEL_STAGE.BEGIN if room and (room.random_type or room.arena) and settings.modules.hide_name and room.duel_stage == ygopro.constants.DUEL_STAGE.BEGIN
pos = info.pos pos = info.pos
if pos < 4 and pos != client.pos if pos < 4 and pos != client.pos
struct = ygopro.structs.get("STOC_HS_PlayerEnter") struct = ygopro.structs.get("STOC_HS_PlayerEnter")
struct._setBuff(buffer) struct._setBuff(buffer)
struct.set("name", "********") struct.set("name", "Player " + (pos + 1))
buffer = struct.buffer buffer = struct.buffer
await return false await return false
...@@ -3135,7 +3148,7 @@ wait_room_start_arena = (room)-> ...@@ -3135,7 +3148,7 @@ wait_room_start_arena = (room)->
if room.waiting_for_player_time > 0 if room.waiting_for_player_time > 0
unless room.waiting_for_player_time % 5 unless room.waiting_for_player_time % 5
for player in room.players when player for player in room.players when player
display_name = (if settings.modules.hide_name and player != room.waiting_for_player then "********" else room.waiting_for_player.name) display_name = room.getMaskedPlayerName(player, room.waiting_for_player)
ygopro.stoc_send_chat(player, "#{if room.waiting_for_player_time <= 9 then ' ' else ''}#{room.waiting_for_player_time}${kick_count_down_arena_part1} #{display_name} ${kick_count_down_arena_part2}", if room.waiting_for_player_time <= 9 then ygopro.constants.COLORS.RED else ygopro.constants.COLORS.LIGHTBLUE) ygopro.stoc_send_chat(player, "#{if room.waiting_for_player_time <= 9 then ' ' else ''}#{room.waiting_for_player_time}${kick_count_down_arena_part1} #{display_name} ${kick_count_down_arena_part2}", if room.waiting_for_player_time <= 9 then ygopro.constants.COLORS.RED else ygopro.constants.COLORS.LIGHTBLUE)
else else
ygopro.stoc_send_chat_to_room(room, "#{room.waiting_for_player.name} ${kicked_by_system}", ygopro.constants.COLORS.RED) ygopro.stoc_send_chat_to_room(room, "#{room.waiting_for_player.name} ${kicked_by_system}", ygopro.constants.COLORS.RED)
...@@ -3209,11 +3222,12 @@ ygopro.stoc_follow 'DUEL_START', false, (buffer, info, client, server, datas)-> ...@@ -3209,11 +3222,12 @@ ygopro.stoc_follow 'DUEL_START', false, (buffer, info, client, server, datas)->
clearInterval client.side_interval clearInterval client.side_interval
client.side_interval = null client.side_interval = null
client.side_tcount = null client.side_tcount = null
if settings.modules.hide_name and room.duel_count == 0 if settings.modules.hide_name == "start" and room.duel_count == 0
for player in room.get_playing_player() when player != client for player in room.get_playing_player() when player != client
ygopro.stoc_send(client, 'HS_PLAYER_ENTER', { ygopro.stoc_send(client, 'HS_PLAYER_ENTER', {
name: player.name, name: player.name,
pos: player.pos pos: player.pos
padding: 0,
}) })
if settings.modules.tips.enabled if settings.modules.tips.enabled
ygopro.stoc_send_random_tip(client) ygopro.stoc_send_random_tip(client)
...@@ -3271,13 +3285,13 @@ ygopro.ctos_follow 'SURRENDER', true, (buffer, info, client, server, datas)-> ...@@ -3271,13 +3285,13 @@ ygopro.ctos_follow 'SURRENDER', true, (buffer, info, client, server, datas)->
ygopro.stoc_send_chat(client, "${surrender_denied}", ygopro.constants.COLORS.BABYBLUE) ygopro.stoc_send_chat(client, "${surrender_denied}", ygopro.constants.COLORS.BABYBLUE)
return true return true
if room.hostinfo.mode == 2 if room.hostinfo.mode == 2
if !client.surrend_confirm and !CLIENT_get_partner(client).closed and !CLIENT_get_partner(client).is_local if !client.surrend_confirm and !CLIENT_get_partner(client).isClosed and !CLIENT_get_partner(client).is_local
sur_player = CLIENT_get_partner(client) sur_player = CLIENT_get_partner(client)
ygopro.stoc_send_chat(sur_player, "${surrender_confirm_tag}", ygopro.constants.COLORS.BABYBLUE) ygopro.stoc_send_chat(sur_player, "${surrender_confirm_tag}", ygopro.constants.COLORS.BABYBLUE)
ygopro.stoc_send_chat(client, "${surrender_confirm_sent}", ygopro.constants.COLORS.BABYBLUE) ygopro.stoc_send_chat(client, "${surrender_confirm_sent}", ygopro.constants.COLORS.BABYBLUE)
sur_player.surrend_confirm = true sur_player.surrend_confirm = true
for player in [client, sur_player] for player in [client, sur_player]
ygopro.stoc_send(client, 'TEAMMATE_SURRENDER') ygopro.stoc_send(player, 'TEAMMATE_SURRENDER')
return true return true
await return false await return false
...@@ -3321,13 +3335,13 @@ ygopro.ctos_follow 'CHAT', true, (buffer, info, client, server, datas)-> ...@@ -3321,13 +3335,13 @@ ygopro.ctos_follow 'CHAT', true, (buffer, info, client, server, datas)->
ygopro.ctos_send(client.server, 'SURRENDER') ygopro.ctos_send(client.server, 'SURRENDER')
else else
sur_player = CLIENT_get_partner(client) sur_player = CLIENT_get_partner(client)
if !sur_player or sur_player.closed or sur_player.is_local if !sur_player or sur_player.isClosed or sur_player.is_local
sur_player = client sur_player = client
if room.hostinfo.mode==2 and sur_player != client if room.hostinfo.mode==2 and sur_player != client
ygopro.stoc_send_chat(sur_player, "${surrender_confirm_tag}", ygopro.constants.COLORS.BABYBLUE) ygopro.stoc_send_chat(sur_player, "${surrender_confirm_tag}", ygopro.constants.COLORS.BABYBLUE)
ygopro.stoc_send_chat(client, "${surrender_confirm_sent}", ygopro.constants.COLORS.BABYBLUE) ygopro.stoc_send_chat(client, "${surrender_confirm_sent}", ygopro.constants.COLORS.BABYBLUE)
for player in [client, sur_player] for player in [client, sur_player]
ygopro.stoc_send(client, 'TEAMMATE_SURRENDER') ygopro.stoc_send(player, 'TEAMMATE_SURRENDER')
else else
ygopro.stoc_send_chat(client, "${surrender_confirm}", ygopro.constants.COLORS.BABYBLUE) ygopro.stoc_send_chat(client, "${surrender_confirm}", ygopro.constants.COLORS.BABYBLUE)
sur_player.surrend_confirm = true sur_player.surrend_confirm = true
...@@ -3516,6 +3530,9 @@ ygopro.ctos_follow 'CHAT', true, (buffer, info, client, server, datas)-> ...@@ -3516,6 +3530,9 @@ ygopro.ctos_follow 'CHAT', true, (buffer, info, client, server, datas)->
ygopro.stoc_send_chat_to_room(room, "#{client.name}: #{msg}", 9) ygopro.stoc_send_chat_to_room(room, "#{client.name}: #{msg}", 9)
return true return true
return cancel return cancel
if room.random_type and settings.modules.random_duel.disable_chat
ygopro.stoc_send_chat(client, "${chat_disabled}", ygopro.constants.COLORS.BABYBLUE)
return true
if client.abuse_count>=5 or CLIENT_is_banned_by_mc(client) if client.abuse_count>=5 or CLIENT_is_banned_by_mc(client)
log.warn "BANNED CHAT", client.name, client.ip, msg log.warn "BANNED CHAT", client.name, client.ip, msg
ygopro.stoc_send_chat(client, "${banned_chat_tip}" + (if client.ban_mc and client.ban_mc.message then (": " + client.ban_mc.message) else ""), ygopro.constants.COLORS.RED) ygopro.stoc_send_chat(client, "${banned_chat_tip}" + (if client.ban_mc and client.ban_mc.message then (": " + client.ban_mc.message) else ""), ygopro.constants.COLORS.RED)
...@@ -3621,13 +3638,22 @@ ygopro.ctos_follow 'UPDATE_DECK', true, (buffer, info, client, server, datas)-> ...@@ -3621,13 +3638,22 @@ ygopro.ctos_follow 'UPDATE_DECK', true, (buffer, info, client, server, datas)->
return true return true
struct = ygopro.structs.get("deck") struct = ygopro.structs.get("deck")
struct._setBuff(buffer) struct._setBuff(buffer)
deck_ok = (msg) ->
ygopro.stoc_send_chat(client, msg, ygopro.constants.COLORS.BABYBLUE)
return false
deck_bad = (msg) ->
struct.set("mainc", 1)
struct.set("sidec", 1)
struct.set("deckbuf", [4392470, 4392470])
ygopro.stoc_send_chat(client, msg, ygopro.constants.COLORS.RED)
return false
if room.random_type or room.arena if room.random_type or room.arena
if client.pos == 0 if client.pos == 0
room.waiting_for_player = room.waiting_for_player2 room.waiting_for_player = room.waiting_for_player2
room.refreshLastActiveTime() room.refreshLastActiveTime()
if room.duel_stage == ygopro.constants.DUEL_STAGE.BEGIN and room.recovering if room.duel_stage == ygopro.constants.DUEL_STAGE.BEGIN and room.recovering
recover_player_data = _.find(room.recover_duel_log.players, (player) -> recover_player_data = _.find(room.recover_duel_log.players, (player) ->
return player.realName == client.name_vpass and buffer.compare(Buffer.from(player.startDeckBuffer, "base64")) == 0 return player.realName == client.name_vpass and buffer.equals(Buffer.from(player.startDeckBuffer, "base64"))
) )
if recover_player_data if recover_player_data
recoveredDeck = recover_player_data.getCurrentDeck() recoveredDeck = recover_player_data.getCurrentDeck()
...@@ -3637,37 +3663,39 @@ ygopro.ctos_follow 'UPDATE_DECK', true, (buffer, info, client, server, datas)-> ...@@ -3637,37 +3663,39 @@ ygopro.ctos_follow 'UPDATE_DECK', true, (buffer, info, client, server, datas)->
if recover_player_data.isFirst if recover_player_data.isFirst
room.determine_firstgo = client room.determine_firstgo = client
else else
struct.set("mainc", 1) return deck_bad("${deck_incorrect_reconnect}")
struct.set("sidec", 1) else if room.duel_stage == ygopro.constants.DUEL_STAGE.BEGIN
struct.set("deckbuf", [4392470, 4392470])
ygopro.stoc_send_chat(client, "${deck_incorrect_reconnect}", ygopro.constants.COLORS.RED)
return false
else
if room.arena and settings.modules.athletic_check.enabled and settings.modules.athletic_check.banCount if room.arena and settings.modules.athletic_check.enabled and settings.modules.athletic_check.banCount
athleticCheckResult = await athleticChecker.checkAthletic({main: buff_main, side: buff_side}) athleticCheckResult = await athleticChecker.checkAthletic({main: buff_main, side: buff_side})
if athleticCheckResult.success if athleticCheckResult.success
if athleticCheckResult.athletic and athleticCheckResult.athletic <= settings.modules.athletic_check.banCount if athleticCheckResult.athletic and athleticCheckResult.athletic <= settings.modules.athletic_check.banCount
struct.set("mainc", 1) return deck_bad("${banned_athletic_deck_part1}#{settings.modules.athletic_check.banCount}${banned_athletic_deck_part2}")
struct.set("sidec", 1)
struct.set("deckbuf", [4392470, 4392470])
ygopro.stoc_send_chat(client, "${banned_athletic_deck_part1}#{settings.modules.athletic_check.banCount}${banned_athletic_deck_part2}", ygopro.constants.COLORS.RED)
return false
else else
log.warn("GET ATHLETIC FAIL", client.name, athleticCheckResult.message) log.warn("GET ATHLETIC FAIL", client.name, athleticCheckResult.message)
if room.duel_stage == ygopro.constants.DUEL_STAGE.BEGIN and settings.modules.tournament_mode.enabled and settings.modules.tournament_mode.deck_check if settings.modules.tournament_mode.enabled and settings.modules.tournament_mode.deck_check
if settings.modules.challonge.enabled and client.challonge_info and client.challonge_info.deckbuf
trim_deckbuf = (buf) ->
mainc = buf.readUInt32LE(0)
sidec = buf.readUInt32LE(4)
# take first (2 + mainc + sidec) * 4 bytes
return buf.slice(0, (2 + mainc + sidec) * 4)
deckbuf_from_challonge = Buffer.from(client.challonge_info.deckbuf, "base64")
if trim_deckbuf(deckbuf_from_challonge).equals(trim_deckbuf(buffer))
#log.info("deck ok: " + client.name)
return deck_ok("${deck_correct_part1} #{client.challonge_info.name} ${deck_correct_part2}")
else
#log.info("bad deck: " + client.name + " / " + buff_main + " / " + buff_side)
return deck_bad("${deck_incorrect_part1} #{client.challonge_info.name} ${deck_incorrect_part2}")
else
decks = await fs.promises.readdir(settings.modules.tournament_mode.deck_path) decks = await fs.promises.readdir(settings.modules.tournament_mode.deck_path)
if decks.length if decks.length
struct.set("mainc", 1)
struct.set("sidec", 1)
struct.set("deckbuf", [4392470, 4392470])
buffer = struct.buffer
found_deck=false found_deck=false
for deck in decks for deck in decks
if deck_name_match(deck, client.name) if deck_name_match(deck, client.name)
found_deck=deck found_deck=deck
if found_deck if found_deck
deck_text = await fs.promises.readFile(settings.modules.tournament_mode.deck_path+found_deck,{encoding:"ASCII"}) deck_text = await fs.promises.readFile(settings.modules.tournament_mode.deck_path+found_deck,{encoding:"ASCII"})
deck_array=deck_text.split("\n") deck_array=deck_text.split(/\r?\n/)
deck_main=[] deck_main=[]
deck_side=[] deck_side=[]
current_deck=deck_main current_deck=deck_main
...@@ -3675,23 +3703,16 @@ ygopro.ctos_follow 'UPDATE_DECK', true, (buffer, info, client, server, datas)-> ...@@ -3675,23 +3703,16 @@ ygopro.ctos_follow 'UPDATE_DECK', true, (buffer, info, client, server, datas)->
if line.indexOf("!side")>=0 if line.indexOf("!side")>=0
current_deck=deck_side current_deck=deck_side
card=parseInt(line) card=parseInt(line)
current_deck.push(card) unless isNaN(card) current_deck.push(card) unless isNaN(card) or line.endsWith("#")
if _.isEqual(buff_main, deck_main) and _.isEqual(buff_side, deck_side) if _.isEqual(buff_main, deck_main) and _.isEqual(buff_side, deck_side)
deckbuf=deck_main.concat(deck_side)
struct.set("mainc", deck_main.length)
struct.set("sidec", deck_side.length)
struct.set("deckbuf", deckbuf)
buffer = struct.buffer
#log.info("deck ok: " + client.name) #log.info("deck ok: " + client.name)
ygopro.stoc_send_chat(client, "${deck_correct_part1} #{found_deck} ${deck_correct_part2}", ygopro.constants.COLORS.BABYBLUE) return deck_ok("${deck_correct_part1} #{found_deck} ${deck_correct_part2}")
else else
#log.info("bad deck: " + client.name + " / " + buff_main + " / " + buff_side) #log.info("bad deck: " + client.name + " / " + buff_main + " / " + buff_side)
ygopro.stoc_send_chat(client, "${deck_incorrect_part1} #{found_deck} ${deck_incorrect_part2}", ygopro.constants.COLORS.RED) return deck_bad("${deck_incorrect_part1} #{found_deck} ${deck_incorrect_part2}")
return false
else else
#log.info("player deck not found: " + client.name) #log.info("player deck not found: " + client.name)
ygopro.stoc_send_chat(client, "#{client.name}${deck_not_found}", ygopro.constants.COLORS.RED) return deck_bad("#{client.name}${deck_not_found}")
return false
await return false await return false
ygopro.ctos_follow 'RESPONSE', false, (buffer, info, client, server, datas)-> ygopro.ctos_follow 'RESPONSE', false, (buffer, info, client, server, datas)->
......
...@@ -511,6 +511,10 @@ ...@@ -511,6 +511,10 @@
delete settings.modules.random_duel.blank_pass_match; delete settings.modules.random_duel.blank_pass_match;
imported = true; imported = true;
} }
if (settings.modules.hide_name === true) {
settings.modules.hide_name = "start";
imported = true;
}
//finish //finish
keysFromEnv = Object.keys(process.env).filter((key) => { keysFromEnv = Object.keys(process.env).filter((key) => {
return key.startsWith('SRVPRO_'); return key.startsWith('SRVPRO_');
...@@ -1040,11 +1044,11 @@ ...@@ -1040,11 +1044,11 @@
await dataManager.randomDuelPlayerFlee(name); await dataManager.randomDuelPlayerFlee(name);
}; };
ROOM_player_get_score = global.ROOM_player_get_score = async function(player) { ROOM_player_get_score = global.ROOM_player_get_score = async function(player, display_name) {
if (!settings.modules.mysql.enabled) { if (!settings.modules.mysql.enabled) {
return ""; return "";
} }
return (await dataManager.getRandomDuelScoreDisplay(player.name_vpass)); return (await dataManager.getRandomDuelScoreDisplay(player.name_vpass, display_name));
}; };
ROOM_find_or_create_by_name = global.ROOM_find_or_create_by_name = async function(name, player_ip) { ROOM_find_or_create_by_name = global.ROOM_find_or_create_by_name = async function(name, player_ip) {
...@@ -1106,7 +1110,7 @@ ...@@ -1106,7 +1110,7 @@
playerbanned = randomDuelBanRecord && randomDuelBanRecord.count > 3 && moment_now < randomDuelBanRecord.time; playerbanned = randomDuelBanRecord && randomDuelBanRecord.count > 3 && moment_now < randomDuelBanRecord.time;
result = _.find(ROOM_all, function(room) { result = _.find(ROOM_all, function(room) {
var ref; var ref;
return room && room.random_type !== '' && room.duel_stage === ygopro.constants.DUEL_STAGE.BEGIN && !room.windbot && ((type === '' && (room.random_type === settings.modules.random_duel.default_type || settings.modules.random_duel.blank_pass_modes[room.random_type])) || room.random_type === type) && (0 < (ref = room.get_playing_player().length) && ref < max_player) && (settings.modules.random_duel.no_rematch_check || room.get_host() === null || room.get_host().ip !== ROOM_players_oppentlist[player_ip]) && (playerbanned === room.deprecated || type === 'T'); return room && room.random_type !== '' && !room.disconnector && room.duel_stage === ygopro.constants.DUEL_STAGE.BEGIN && !room.windbot && ((type === '' && (room.random_type === settings.modules.random_duel.default_type || settings.modules.random_duel.blank_pass_modes[room.random_type])) || room.random_type === type) && (0 < (ref = room.get_playing_player().length) && ref < max_player) && (settings.modules.random_duel.no_rematch_check || room.get_host() === null || room.get_host().ip !== ROOM_players_oppentlist[player_ip]) && (playerbanned === room.deprecated || type === 'T');
}); });
if (result) { if (result) {
result.welcome = '${random_duel_enter_room_waiting}'; result.welcome = '${random_duel_enter_room_waiting}';
...@@ -1333,7 +1337,7 @@ ...@@ -1333,7 +1337,7 @@
dinfo.timeout = tmot; dinfo.timeout = tmot;
disconnect_list[CLIENT_get_authorize_key(client)] = dinfo; disconnect_list[CLIENT_get_authorize_key(client)] = dinfo;
//console.log("#{client.name} ${disconnect_from_game}") //console.log("#{client.name} ${disconnect_from_game}")
ygopro.stoc_send_chat_to_room(room, `${client.name} \${disconnect_from_game}` + (error ? `: ${error}` : '')); ygopro.stoc_send_chat_to_room(room, `${room.getMaskedPlayerName(client)} \${disconnect_from_game}` + (error ? `: ${error}` : ''));
if (client.time_confirm_required) { if (client.time_confirm_required) {
client.time_confirm_required = false; client.time_confirm_required = false;
ygopro.ctos_send(client.server, 'TIME_CONFIRM'); ygopro.ctos_send(client.server, 'TIME_CONFIRM');
...@@ -1437,7 +1441,7 @@ ...@@ -1437,7 +1441,7 @@
CLIENT_reconnect_unregister(client); CLIENT_reconnect_unregister(client);
return false; return false;
} }
if (deckbuf && deckbuf.compare(disconnect_info.deckbuf) !== 0) { if (deckbuf && !deckbuf.equals(disconnect_info.deckbuf)) {
return false; return false;
} }
return true; return true;
...@@ -1451,7 +1455,7 @@ ...@@ -1451,7 +1455,7 @@
ref = room.get_playing_player(); ref = room.get_playing_player();
for (l = 0, len1 = ref.length; l < len1; l++) { for (l = 0, len1 = ref.length; l < len1; l++) {
player = ref[l]; player = ref[l];
if (!player.isClosed && player.name === client.name && (settings.modules.challonge.enabled || player.pass === client.pass) && (settings.modules.mycard.enabled || settings.modules.tournament_mode.enabled || player.ip === client.ip || (client.vpass && client.vpass === player.vpass)) && (!deckbuf || deckbuf.compare(player.start_deckbuf) === 0)) { if (!player.isClosed && player.name === client.name && (settings.modules.challonge.enabled || player.pass === client.pass) && (settings.modules.mycard.enabled || settings.modules.tournament_mode.enabled || player.ip === client.ip || (client.vpass && client.vpass === player.vpass)) && (!deckbuf || deckbuf.equals(player.start_deckbuf))) {
return player; return player;
} }
} }
...@@ -1485,8 +1489,9 @@ ...@@ -1485,8 +1489,9 @@
for (j = 0, len = ref.length; j < len; j++) { for (j = 0, len = ref.length; j < len; j++) {
player = ref[j]; player = ref[j];
ygopro.stoc_send(client, 'HS_PLAYER_ENTER', { ygopro.stoc_send(client, 'HS_PLAYER_ENTER', {
name: player.name, name: room.getMaskedPlayerName(player, old_client),
pos: player.pos pos: player.pos,
padding: 0
}); });
} }
}; };
...@@ -1564,7 +1569,7 @@ ...@@ -1564,7 +1569,7 @@
CLIENT_import_data(client, dinfo.old_client, room); CLIENT_import_data(client, dinfo.old_client, room);
CLIENT_send_reconnect_info(client, client.server, room); CLIENT_send_reconnect_info(client, client.server, room);
//console.log("#{client.name} ${reconnect_to_game}") //console.log("#{client.name} ${reconnect_to_game}")
ygopro.stoc_send_chat_to_room(room, `${client.name} \${reconnect_to_game}`); ygopro.stoc_send_chat_to_room(room, `${room.getMaskedPlayerName(client)} \${reconnect_to_game}`);
CLIENT_reconnect_unregister(client, true); CLIENT_reconnect_unregister(client, true);
}; };
...@@ -2028,20 +2033,21 @@ ...@@ -2028,20 +2033,21 @@
} }
delete() { delete() {
var end_time, formatted_replays, index, j, len, log_rep_id, name, player_datas, recorder_buffer, ref, ref1, repbuf, replay_id, room_name, score, score_array, score_form; var end_time, formatted_replays, index, j, len, log_rep_id, name, name_vpass, player_datas, recorder_buffer, ref, ref1, repbuf, replay_id, room_name, score, score_array, score_form;
if (this.deleted) { if (this.deleted) {
return; return;
} }
//log.info 'room-delete', this.name, ROOM_all.length //log.info 'room-delete', this.name, ROOM_all.length
score_array = []; score_array = [];
ref = this.scores; ref = this.scores;
for (name in ref) { for (name_vpass in ref) {
score = ref[name]; score = ref[name_vpass];
name = name_vpass.split('$')[0];
score_form = { score_form = {
name: name.split('$')[0], name: name,
score: score, score: score,
deck: null, deck: null,
name_vpass: name name_vpass: name_vpass
}; };
if (this.decks[name]) { if (this.decks[name]) {
score_form.deck = this.decks[name]; score_form.deck = this.decks[name];
...@@ -2403,7 +2409,7 @@ ...@@ -2403,7 +2409,7 @@
} }
} }
if (this.players.length && !(this.windbot && client.is_host && this.duel_stage === ygopro.constants.DUEL_STAGE.BEGIN) && !(this.arena && this.duel_stage === ygopro.constants.DUEL_STAGE.BEGIN && client.pos <= 3)) { if (this.players.length && !(this.windbot && client.is_host && this.duel_stage === ygopro.constants.DUEL_STAGE.BEGIN) && !(this.arena && this.duel_stage === ygopro.constants.DUEL_STAGE.BEGIN && client.pos <= 3)) {
left_name = (settings.modules.hide_name && this.duel_stage === ygopro.constants.DUEL_STAGE.BEGIN ? "********" : client.name); left_name = this.getMaskedPlayerName(client);
ygopro.stoc_send_chat_to_room(this, `${left_name} \${left_game}` + (error ? `: ${error}` : '')); ygopro.stoc_send_chat_to_room(this, `${left_name} \${left_game}` + (error ? `: ${error}` : ''));
if (!this.windbot && this.duel_stage === ygopro.constants.DUEL_STAGE.BEGIN && settings.modules.http.websocket_roomlist) { if (!this.windbot && this.duel_stage === ygopro.constants.DUEL_STAGE.BEGIN && settings.modules.http.websocket_roomlist) {
roomlist.update(this); roomlist.update(this);
...@@ -2667,13 +2673,23 @@ ...@@ -2667,13 +2673,23 @@
} }
} }
getMaskedPlayerName(player, sight_player) {
if (!settings.modules.hide_name || (sight_player && player === sight_player) || !(this.random_type || this.arena)) {
return player.name;
}
if ((this.duel_stage === ygopro.constants.DUEL_STAGE.BEGIN && settings.modules.hide_name === "start") || settings.modules.hide_name === "always") {
return `Player ${player.pos + 1}`;
}
return player.name;
}
}; };
// 网络连接 // 网络连接
netRequestHandler = function(client) { netRequestHandler = function(client) {
var closeHandler, connect_count, dataHandler, server; var closeHandler, connect_count, dataHandler, server;
if (!client.isWs) { if (!client.isWs) {
client.ip = client.remoteAddress; client.ip = client.remoteAddress || '';
} }
client.is_local = client.ip && (client.ip.includes('127.0.0.1') || client.ip.includes(real_windbot_server_ip)); client.is_local = client.ip && (client.ip.includes('127.0.0.1') || client.ip.includes(real_windbot_server_ip));
connect_count = ROOM_connected_ip[client.ip] || 0; connect_count = ROOM_connected_ip[client.ip] || 0;
...@@ -3136,11 +3152,9 @@ ...@@ -3136,11 +3152,9 @@
//console.log(options) //console.log(options)
if (options.rule === 2) { if (options.rule === 2) {
options.lflist = -1; options.lflist = -1;
} else if (options.rule !== 3) {
options.lflist = _.findIndex(lflists, function(list) {
return ((options.rule === 1) === list.tcg) && list.date.isBefore();
});
} }
//else if options.rule != 3
// options.lflist = _.findIndex lflists, (list)-> ((options.rule == 1) == list.tcg) and list.date.isBefore()
room_title = info.pass.slice(8).replace(String.fromCharCode(0xFEFF), ' '); room_title = info.pass.slice(8).replace(String.fromCharCode(0xFEFF), ' ');
if (badwordR.level3.test(room_title)) { if (badwordR.level3.test(room_title)) {
log.warn("BAD ROOM NAME LEVEL 3", room_title, client.name, client.ip); log.warn("BAD ROOM NAME LEVEL 3", room_title, client.name, client.ip);
...@@ -3391,7 +3405,7 @@ ...@@ -3391,7 +3405,7 @@
}); });
ygopro.stoc_follow('JOIN_GAME', false, async function(buffer, info, client, server, datas) { ygopro.stoc_follow('JOIN_GAME', false, async function(buffer, info, client, server, datas) {
var j, len, playWords, player, recorder, ref, room, watcher; var j, l, len, len1, playWords, player, recorder, ref, ref1, room, watcher;
//欢迎信息 //欢迎信息
room = ROOM_all[client.rid]; room = ROOM_all[client.rid];
if (!(room && !client.reconnecting)) { if (!(room && !client.reconnecting)) {
...@@ -3417,7 +3431,7 @@ ...@@ -3417,7 +3431,7 @@
if (room.welcome2) { if (room.welcome2) {
ygopro.stoc_send_chat(client, room.welcome2, ygopro.constants.COLORS.PINK); ygopro.stoc_send_chat(client, room.welcome2, ygopro.constants.COLORS.PINK);
} }
if (settings.modules.arena_mode.enabled && !client.is_local) { //and not client.score_shown if (settings.modules.arena_mode.enabled && !client.is_local && settings.modules.arena_mode.get_score) { //and not client.score_shown
request({ request({
url: settings.modules.arena_mode.get_score + encodeURIComponent(client.name), url: settings.modules.arena_mode.get_score + encodeURIComponent(client.name),
json: true json: true
...@@ -3436,12 +3450,18 @@ ...@@ -3436,12 +3450,18 @@
} }
//client.score_shown = true //client.score_shown = true
if (settings.modules.random_duel.record_match_scores && room.random_type === 'M') { if (settings.modules.random_duel.record_match_scores && room.random_type === 'M') {
ygopro.stoc_send_chat_to_room(room, (await ROOM_player_get_score(client)), ygopro.constants.COLORS.GREEN);
ref = room.players; ref = room.players;
for (j = 0, len = ref.length; j < len; j++) { for (j = 0, len = ref.length; j < len; j++) {
player = ref[j]; player = ref[j];
if (player.pos !== 7) {
ygopro.stoc_send_chat(player, (await ROOM_player_get_score(client, room.getMaskedPlayerName(client, player))), ygopro.constants.COLORS.GREEN);
}
}
ref1 = room.players;
for (l = 0, len1 = ref1.length; l < len1; l++) {
player = ref1[l];
if (player.pos !== 7 && player !== client) { if (player.pos !== 7 && player !== client) {
ygopro.stoc_send_chat(client, (await ROOM_player_get_score(player)), ygopro.constants.COLORS.GREEN); ygopro.stoc_send_chat(client, (await ROOM_player_get_score(player, room.getMaskedPlayerName(player, client))), ygopro.constants.COLORS.GREEN);
} }
} }
} }
...@@ -3477,15 +3497,15 @@ ...@@ -3477,15 +3497,15 @@
ygopro.ctos_send(watcher, 'HS_TOOBSERVER'); ygopro.ctos_send(watcher, 'HS_TOOBSERVER');
}); });
watcher.on('data', function(data) { watcher.on('data', function(data) {
var l, len1, ref1, w; var len2, m, ref2, w;
room = ROOM_all[client.rid]; room = ROOM_all[client.rid];
if (!room) { if (!room) {
return; return;
} }
room.watcher_buffers.push(data); room.watcher_buffers.push(data);
ref1 = room.watchers; ref2 = room.watchers;
for (l = 0, len1 = ref1.length; l < len1; l++) { for (m = 0, len2 = ref2.length; m < len2; m++) {
w = ref1[l]; w = ref2[m];
if (w) { //a WTF fix if (w) { //a WTF fix
ygopro.helper.send(w, data); ygopro.helper.send(w, data);
} }
...@@ -3993,16 +4013,15 @@ ...@@ -3993,16 +4013,15 @@
ygopro.stoc_follow('HS_PLAYER_ENTER', true, async function(buffer, info, client, server, datas) { ygopro.stoc_follow('HS_PLAYER_ENTER', true, async function(buffer, info, client, server, datas) {
var pos, room, struct; var pos, room, struct;
room = ROOM_all[client.rid]; room = ROOM_all[client.rid];
if (!(room && settings.modules.hide_name && room.duel_stage === ygopro.constants.DUEL_STAGE.BEGIN)) { if (room && (room.random_type || room.arena) && settings.modules.hide_name && room.duel_stage === ygopro.constants.DUEL_STAGE.BEGIN) {
return false;
}
pos = info.pos; pos = info.pos;
if (pos < 4 && pos !== client.pos) { if (pos < 4 && pos !== client.pos) {
struct = ygopro.structs.get("STOC_HS_PlayerEnter"); struct = ygopro.structs.get("STOC_HS_PlayerEnter");
struct._setBuff(buffer); struct._setBuff(buffer);
struct.set("name", "********"); struct.set("name", "Player " + (pos + 1));
buffer = struct.buffer; buffer = struct.buffer;
} }
}
return false; return false;
}); });
...@@ -4169,7 +4188,7 @@ ...@@ -4169,7 +4188,7 @@
if (!(player)) { if (!(player)) {
continue; continue;
} }
display_name = (settings.modules.hide_name && player !== room.waiting_for_player ? "********" : room.waiting_for_player.name); display_name = room.getMaskedPlayerName(player, room.waiting_for_player);
ygopro.stoc_send_chat(player, `${room.waiting_for_player_time <= 9 ? ' ' : ''}${room.waiting_for_player_time}\${kick_count_down_arena_part1} ${display_name} \${kick_count_down_arena_part2}`, room.waiting_for_player_time <= 9 ? ygopro.constants.COLORS.RED : ygopro.constants.COLORS.LIGHTBLUE); ygopro.stoc_send_chat(player, `${room.waiting_for_player_time <= 9 ? ' ' : ''}${room.waiting_for_player_time}\${kick_count_down_arena_part1} ${display_name} \${kick_count_down_arena_part2}`, room.waiting_for_player_time <= 9 ? ygopro.constants.COLORS.RED : ygopro.constants.COLORS.LIGHTBLUE);
} }
} }
...@@ -4289,14 +4308,15 @@ ...@@ -4289,14 +4308,15 @@
client.side_tcount = null; client.side_tcount = null;
} }
} }
if (settings.modules.hide_name && room.duel_count === 0) { if (settings.modules.hide_name === "start" && room.duel_count === 0) {
ref1 = room.get_playing_player(); ref1 = room.get_playing_player();
for (l = 0, len1 = ref1.length; l < len1; l++) { for (l = 0, len1 = ref1.length; l < len1; l++) {
player = ref1[l]; player = ref1[l];
if (player !== client) { if (player !== client) {
ygopro.stoc_send(client, 'HS_PLAYER_ENTER', { ygopro.stoc_send(client, 'HS_PLAYER_ENTER', {
name: player.name, name: player.name,
pos: player.pos pos: player.pos,
padding: 0
}); });
} }
} }
...@@ -4376,7 +4396,7 @@ ...@@ -4376,7 +4396,7 @@
return true; return true;
} }
if (room.hostinfo.mode === 2) { if (room.hostinfo.mode === 2) {
if (!client.surrend_confirm && !CLIENT_get_partner(client).closed && !CLIENT_get_partner(client).is_local) { if (!client.surrend_confirm && !CLIENT_get_partner(client).isClosed && !CLIENT_get_partner(client).is_local) {
sur_player = CLIENT_get_partner(client); sur_player = CLIENT_get_partner(client);
ygopro.stoc_send_chat(sur_player, "${surrender_confirm_tag}", ygopro.constants.COLORS.BABYBLUE); ygopro.stoc_send_chat(sur_player, "${surrender_confirm_tag}", ygopro.constants.COLORS.BABYBLUE);
ygopro.stoc_send_chat(client, "${surrender_confirm_sent}", ygopro.constants.COLORS.BABYBLUE); ygopro.stoc_send_chat(client, "${surrender_confirm_sent}", ygopro.constants.COLORS.BABYBLUE);
...@@ -4384,7 +4404,7 @@ ...@@ -4384,7 +4404,7 @@
ref = [client, sur_player]; ref = [client, sur_player];
for (j = 0, len = ref.length; j < len; j++) { for (j = 0, len = ref.length; j < len; j++) {
player = ref[j]; player = ref[j];
ygopro.stoc_send(client, 'TEAMMATE_SURRENDER'); ygopro.stoc_send(player, 'TEAMMATE_SURRENDER');
} }
return true; return true;
} }
...@@ -4447,7 +4467,7 @@ ...@@ -4447,7 +4467,7 @@
ygopro.ctos_send(client.server, 'SURRENDER'); ygopro.ctos_send(client.server, 'SURRENDER');
} else { } else {
sur_player = CLIENT_get_partner(client); sur_player = CLIENT_get_partner(client);
if (!sur_player || sur_player.closed || sur_player.is_local) { if (!sur_player || sur_player.isClosed || sur_player.is_local) {
sur_player = client; sur_player = client;
} }
if (room.hostinfo.mode === 2 && sur_player !== client) { if (room.hostinfo.mode === 2 && sur_player !== client) {
...@@ -4456,7 +4476,7 @@ ...@@ -4456,7 +4476,7 @@
ref = [client, sur_player]; ref = [client, sur_player];
for (j = 0, len = ref.length; j < len; j++) { for (j = 0, len = ref.length; j < len; j++) {
player = ref[j]; player = ref[j];
ygopro.stoc_send(client, 'TEAMMATE_SURRENDER'); ygopro.stoc_send(player, 'TEAMMATE_SURRENDER');
} }
} else { } else {
ygopro.stoc_send_chat(client, "${surrender_confirm}", ygopro.constants.COLORS.BABYBLUE); ygopro.stoc_send_chat(client, "${surrender_confirm}", ygopro.constants.COLORS.BABYBLUE);
...@@ -4720,6 +4740,10 @@ ...@@ -4720,6 +4740,10 @@
} }
return cancel; return cancel;
} }
if (room.random_type && settings.modules.random_duel.disable_chat) {
ygopro.stoc_send_chat(client, "${chat_disabled}", ygopro.constants.COLORS.BABYBLUE);
return true;
}
if (client.abuse_count >= 5 || CLIENT_is_banned_by_mc(client)) { if (client.abuse_count >= 5 || CLIENT_is_banned_by_mc(client)) {
log.warn("BANNED CHAT", client.name, client.ip, msg); log.warn("BANNED CHAT", client.name, client.ip, msg);
ygopro.stoc_send_chat(client, "${banned_chat_tip}" + (client.ban_mc && client.ban_mc.message ? ": " + client.ban_mc.message : ""), ygopro.constants.COLORS.RED); ygopro.stoc_send_chat(client, "${banned_chat_tip}" + (client.ban_mc && client.ban_mc.message ? ": " + client.ban_mc.message : ""), ygopro.constants.COLORS.RED);
...@@ -4790,7 +4814,7 @@ ...@@ -4790,7 +4814,7 @@
}); });
ygopro.ctos_follow('UPDATE_DECK', true, async function(buffer, info, client, server, datas) { ygopro.ctos_follow('UPDATE_DECK', true, async function(buffer, info, client, server, datas) {
var athleticCheckResult, buff_main, buff_side, card, current_deck, deck, deck_array, deck_main, deck_side, deck_text, deckbuf, decks, found_deck, i, j, l, len, len1, line, oppo_pos, recover_player_data, recoveredDeck, room, struct, win_pos; var athleticCheckResult, buff_main, buff_side, card, current_deck, deck, deck_array, deck_bad, deck_main, deck_ok, deck_side, deck_text, deckbuf_from_challonge, decks, found_deck, i, j, l, len, len1, line, oppo_pos, recover_player_data, recoveredDeck, room, struct, trim_deckbuf, win_pos;
if (settings.modules.reconnect.enabled && client.pre_reconnecting) { if (settings.modules.reconnect.enabled && client.pre_reconnecting) {
if (!CLIENT_is_able_to_reconnect(client) && !CLIENT_is_able_to_kick_reconnect(client)) { if (!CLIENT_is_able_to_reconnect(client) && !CLIENT_is_able_to_kick_reconnect(client)) {
ygopro.stoc_send_chat(client, "${reconnect_failed}", ygopro.constants.COLORS.RED); ygopro.stoc_send_chat(client, "${reconnect_failed}", ygopro.constants.COLORS.RED);
...@@ -4862,6 +4886,17 @@ ...@@ -4862,6 +4886,17 @@
} }
struct = ygopro.structs.get("deck"); struct = ygopro.structs.get("deck");
struct._setBuff(buffer); struct._setBuff(buffer);
deck_ok = function(msg) {
ygopro.stoc_send_chat(client, msg, ygopro.constants.COLORS.BABYBLUE);
return false;
};
deck_bad = function(msg) {
struct.set("mainc", 1);
struct.set("sidec", 1);
struct.set("deckbuf", [4392470, 4392470]);
ygopro.stoc_send_chat(client, msg, ygopro.constants.COLORS.RED);
return false;
};
if (room.random_type || room.arena) { if (room.random_type || room.arena) {
if (client.pos === 0) { if (client.pos === 0) {
room.waiting_for_player = room.waiting_for_player2; room.waiting_for_player = room.waiting_for_player2;
...@@ -4870,7 +4905,7 @@ ...@@ -4870,7 +4905,7 @@
} }
if (room.duel_stage === ygopro.constants.DUEL_STAGE.BEGIN && room.recovering) { if (room.duel_stage === ygopro.constants.DUEL_STAGE.BEGIN && room.recovering) {
recover_player_data = _.find(room.recover_duel_log.players, function(player) { recover_player_data = _.find(room.recover_duel_log.players, function(player) {
return player.realName === client.name_vpass && buffer.compare(Buffer.from(player.startDeckBuffer, "base64")) === 0; return player.realName === client.name_vpass && buffer.equals(Buffer.from(player.startDeckBuffer, "base64"));
}); });
if (recover_player_data) { if (recover_player_data) {
recoveredDeck = recover_player_data.getCurrentDeck(); recoveredDeck = recover_player_data.getCurrentDeck();
...@@ -4881,13 +4916,9 @@ ...@@ -4881,13 +4916,9 @@
room.determine_firstgo = client; room.determine_firstgo = client;
} }
} else { } else {
struct.set("mainc", 1); return deck_bad("${deck_incorrect_reconnect}");
struct.set("sidec", 1);
struct.set("deckbuf", [4392470, 4392470]);
ygopro.stoc_send_chat(client, "${deck_incorrect_reconnect}", ygopro.constants.COLORS.RED);
return false;
} }
} else { } else if (room.duel_stage === ygopro.constants.DUEL_STAGE.BEGIN) {
if (room.arena && settings.modules.athletic_check.enabled && settings.modules.athletic_check.banCount) { if (room.arena && settings.modules.athletic_check.enabled && settings.modules.athletic_check.banCount) {
athleticCheckResult = (await athleticChecker.checkAthletic({ athleticCheckResult = (await athleticChecker.checkAthletic({
main: buff_main, main: buff_main,
...@@ -4895,23 +4926,32 @@ ...@@ -4895,23 +4926,32 @@
})); }));
if (athleticCheckResult.success) { if (athleticCheckResult.success) {
if (athleticCheckResult.athletic && athleticCheckResult.athletic <= settings.modules.athletic_check.banCount) { if (athleticCheckResult.athletic && athleticCheckResult.athletic <= settings.modules.athletic_check.banCount) {
struct.set("mainc", 1); return deck_bad(`\${banned_athletic_deck_part1}${settings.modules.athletic_check.banCount}\${banned_athletic_deck_part2}`);
struct.set("sidec", 1);
struct.set("deckbuf", [4392470, 4392470]);
ygopro.stoc_send_chat(client, `\${banned_athletic_deck_part1}${settings.modules.athletic_check.banCount}\${banned_athletic_deck_part2}`, ygopro.constants.COLORS.RED);
return false;
} }
} else { } else {
log.warn("GET ATHLETIC FAIL", client.name, athleticCheckResult.message); log.warn("GET ATHLETIC FAIL", client.name, athleticCheckResult.message);
} }
} }
if (room.duel_stage === ygopro.constants.DUEL_STAGE.BEGIN && settings.modules.tournament_mode.enabled && settings.modules.tournament_mode.deck_check) { if (settings.modules.tournament_mode.enabled && settings.modules.tournament_mode.deck_check) {
if (settings.modules.challonge.enabled && client.challonge_info && client.challonge_info.deckbuf) {
trim_deckbuf = function(buf) {
var mainc, sidec;
mainc = buf.readUInt32LE(0);
sidec = buf.readUInt32LE(4);
// take first (2 + mainc + sidec) * 4 bytes
return buf.slice(0, (2 + mainc + sidec) * 4);
};
deckbuf_from_challonge = Buffer.from(client.challonge_info.deckbuf, "base64");
if (trim_deckbuf(deckbuf_from_challonge).equals(trim_deckbuf(buffer))) {
//log.info("deck ok: " + client.name)
return deck_ok(`\${deck_correct_part1} ${client.challonge_info.name} \${deck_correct_part2}`);
} else {
//log.info("bad deck: " + client.name + " / " + buff_main + " / " + buff_side)
return deck_bad(`\${deck_incorrect_part1} ${client.challonge_info.name} \${deck_incorrect_part2}`);
}
} else {
decks = (await fs.promises.readdir(settings.modules.tournament_mode.deck_path)); decks = (await fs.promises.readdir(settings.modules.tournament_mode.deck_path));
if (decks.length) { if (decks.length) {
struct.set("mainc", 1);
struct.set("sidec", 1);
struct.set("deckbuf", [4392470, 4392470]);
buffer = struct.buffer;
found_deck = false; found_deck = false;
for (j = 0, len = decks.length; j < len; j++) { for (j = 0, len = decks.length; j < len; j++) {
deck = decks[j]; deck = decks[j];
...@@ -4923,7 +4963,7 @@ ...@@ -4923,7 +4963,7 @@
deck_text = (await fs.promises.readFile(settings.modules.tournament_mode.deck_path + found_deck, { deck_text = (await fs.promises.readFile(settings.modules.tournament_mode.deck_path + found_deck, {
encoding: "ASCII" encoding: "ASCII"
})); }));
deck_array = deck_text.split("\n"); deck_array = deck_text.split(/\r?\n/);
deck_main = []; deck_main = [];
deck_side = []; deck_side = [];
current_deck = deck_main; current_deck = deck_main;
...@@ -4933,27 +4973,21 @@ ...@@ -4933,27 +4973,21 @@
current_deck = deck_side; current_deck = deck_side;
} }
card = parseInt(line); card = parseInt(line);
if (!isNaN(card)) { if (!(isNaN(card) || line.endsWith("#"))) {
current_deck.push(card); current_deck.push(card);
} }
} }
if (_.isEqual(buff_main, deck_main) && _.isEqual(buff_side, deck_side)) { if (_.isEqual(buff_main, deck_main) && _.isEqual(buff_side, deck_side)) {
deckbuf = deck_main.concat(deck_side);
struct.set("mainc", deck_main.length);
struct.set("sidec", deck_side.length);
struct.set("deckbuf", deckbuf);
buffer = struct.buffer;
//log.info("deck ok: " + client.name) //log.info("deck ok: " + client.name)
ygopro.stoc_send_chat(client, `\${deck_correct_part1} ${found_deck} \${deck_correct_part2}`, ygopro.constants.COLORS.BABYBLUE); return deck_ok(`\${deck_correct_part1} ${found_deck} \${deck_correct_part2}`);
} else { } else {
//log.info("bad deck: " + client.name + " / " + buff_main + " / " + buff_side) //log.info("bad deck: " + client.name + " / " + buff_main + " / " + buff_side)
ygopro.stoc_send_chat(client, `\${deck_incorrect_part1} ${found_deck} \${deck_incorrect_part2}`, ygopro.constants.COLORS.RED); return deck_bad(`\${deck_incorrect_part1} ${found_deck} \${deck_incorrect_part2}`);
return false;
} }
} else { } else {
//log.info("player deck not found: " + client.name) //log.info("player deck not found: " + client.name)
ygopro.stoc_send_chat(client, `${client.name}\${deck_not_found}`, ygopro.constants.COLORS.RED); return deck_bad(`${client.name}\${deck_not_found}`);
return false; }
} }
} }
} }
......
...@@ -23,6 +23,8 @@ const auth = require('./ygopro-auth.js'); ...@@ -23,6 +23,8 @@ const auth = require('./ygopro-auth.js');
const settings = loadJSON('./config/config.json'); const settings = loadJSON('./config/config.json');
config = settings.modules.tournament_mode; config = settings.modules.tournament_mode;
challonge_config = settings.modules.challonge; challonge_config = settings.modules.challonge;
const { Challonge } = require('./challonge');
const challonge = new Challonge(challonge_config);
ssl_config = settings.modules.http.ssl; ssl_config = settings.modules.http.ssl;
const _async = require("async"); const _async = require("async");
...@@ -73,7 +75,7 @@ const readDeck = async function(deck_name, deck_full_path) { ...@@ -73,7 +75,7 @@ const readDeck = async function(deck_name, deck_full_path) {
const deck={}; const deck={};
deck.name=deck_name; deck.name=deck_name;
deck_text = await fs.promises.readFile(deck_full_path, { encoding: "ASCII" }); deck_text = await fs.promises.readFile(deck_full_path, { encoding: "ASCII" });
deck_array = deck_text.split("\n"); deck_array = deck_text.split(/\r?\n/);
deck.main = []; deck.main = [];
deck.extra = []; deck.extra = [];
deck.side = []; deck.side = [];
...@@ -87,7 +89,7 @@ const readDeck = async function(deck_name, deck_full_path) { ...@@ -87,7 +89,7 @@ const readDeck = async function(deck_name, deck_full_path) {
current_deck = deck.side; current_deck = deck.side;
} }
card = parseInt(line); card = parseInt(line);
if (!isNaN(card)) { if (!isNaN(card) && !line.endsWith("#")) {
current_deck.push(card); current_deck.push(card);
} }
} }
...@@ -156,19 +158,11 @@ const UploadToChallonge = async function () { ...@@ -156,19 +158,11 @@ const UploadToChallonge = async function () {
sendResponse("读取玩家列表完毕,共有" + player_list.length + "名玩家。"); sendResponse("读取玩家列表完毕,共有" + player_list.length + "名玩家。");
try { try {
sendResponse("开始清空 Challonge 玩家列表。"); sendResponse("开始清空 Challonge 玩家列表。");
await axios.delete(`https://api.challonge.com/v1/tournaments/${challonge_config.tournament_id}/participants/clear.json`, { await challonge.clearParticipants();
params: {
api_key: challonge_config.api_key
},
validateStatus: () => true,
});
sendResponse("开始上传玩家列表至 Challonge。"); sendResponse("开始上传玩家列表至 Challonge。");
for (const chunk of _.chunk(player_list, 10)) { for (const chunk of _.chunk(player_list, 10)) {
sendResponse(`开始上传玩家 ${chunk.join(', ')} 至 Challonge。`); sendResponse(`开始上传玩家 ${chunk.join(', ')} 至 Challonge。`);
await axios.post(`https://api.challonge.com/v1/tournaments/${challonge_config.tournament_id}/participants/bulk_add.json`, { await challonge.uploadParticipants(chunk);
api_key: challonge_config.api_key,
participants: chunk.map(name => ({ name })),
});
} }
sendResponse("玩家列表上传完成。"); sendResponse("玩家列表上传完成。");
} catch (e) { } catch (e) {
......
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