Commit 04888860 authored by nanahira's avatar nanahira

rework server init

parent de15fb02
......@@ -59,7 +59,7 @@ add_log = (message) ->
text = mt.format('YYYY-MM-DD HH:mm:ss') + " --> " + message + "\n"
res = false
try
await util.promisify(fs.appendFile)("./logs/"+mt.format('YYYY-MM-DD')+".log", text)
await fs.promises.appendFile("./logs/"+mt.format('YYYY-MM-DD')+".log", text)
res = true
catch
res = false
......@@ -69,7 +69,7 @@ add_log = (message) ->
default_data = loadJSON('./data/default_data.json')
setting_save = (settings) ->
try
await util.promisify(fs.writeFile)(settings.file, JSON.stringify(settings, null, 2))
await fs.promises.writeFile(settings.file, JSON.stringify(settings, null, 2))
catch e
add_log("save fail");
return
......
......@@ -73,7 +73,7 @@
text = mt.format('YYYY-MM-DD HH:mm:ss') + " --> " + message + "\n";
res = false;
try {
await util.promisify(fs.appendFile)("./logs/" + mt.format('YYYY-MM-DD') + ".log", text);
await fs.promises.appendFile("./logs/" + mt.format('YYYY-MM-DD') + ".log", text);
res = true;
} catch (error) {
res = false;
......@@ -86,7 +86,7 @@
setting_save = async function(settings) {
var e;
try {
await util.promisify(fs.writeFile)(settings.file, JSON.stringify(settings, null, 2));
await fs.promises.writeFile(settings.file, JSON.stringify(settings, null, 2));
} catch (error) {
e = error;
add_log("save fail");
......
......@@ -21,6 +21,7 @@ request = require 'request'
axios = require 'axios'
qs = require "querystring"
zlib = require 'zlib'
axios = require 'axios'
bunyan = require 'bunyan'
log = global.log = bunyan.createLogger name: "mycard"
......@@ -83,29 +84,62 @@ merge = require 'deepmerge'
loadJSON = require('load-json-file').sync
loadJSONAsync = require('load-json-file')
util = require("util")
Q = require("q")
#heapdump = require 'heapdump'
# 配置
# 导入旧配置
if not fs.existsSync('./config')
fs.mkdirSync('./config')
try
oldconfig=loadJSON('./config.user.json')
checkFileExists = (path) =>
try
await fs.promises.access(path)
return true
catch e
return false
createDirectoryIfNotExists = (path) =>
if !await checkFileExists(path)
await fs.promises.mkdir(path, {recursive: true})
setting_save = global.setting_save = (settings) ->
try
await fs.promises.writeFile(settings.file, JSON.stringify(settings, null, 2))
catch e
log.warn("setting save fail", e.toString())
return
setting_change = global.setting_change = (settings, path, val) ->
# path should be like "modules:welcome"
log.info("setting changed", path, val) if _.isString(val)
path=path.split(':')
if path.length == 0
settings[path[0]]=val
else
target=settings
while path.length > 1
key=path.shift()
target=target[key]
key = path.shift()
target[key] = val
await setting_save(settings)
return
importOldConfig = () ->
try
oldconfig=await loadJSONAsync('./config.user.json')
if oldconfig.tips
oldtips = {}
oldtips.file = './config/tips.json'
oldtips.tips = oldconfig.tips
fs.writeFileSync(oldtips.file, JSON.stringify(oldtips, null, 2))
await fs.promises.writeFile(oldtips.file, JSON.stringify(oldtips, null, 2))
delete oldconfig.tips
if oldconfig.dialogues
olddialogues = {}
olddialogues.file = './config/dialogues.json'
olddialogues.dialogues = oldconfig.dialogues
fs.writeFileSync(olddialogues.file, JSON.stringify(olddialogues, null, 2))
await fs.promises.writeFile(olddialogues.file, JSON.stringify(olddialogues, null, 2))
delete oldconfig.dialogues
oldbadwords={}
if oldconfig.ban
......@@ -119,66 +153,97 @@ try
oldbadwords.level3 = oldconfig.ban.badword_level3
if not _.isEmpty(oldbadwords)
oldbadwords.file = './config/badwords.json'
fs.writeFileSync(oldbadwords.file, JSON.stringify(oldbadwords, null, 2))
await fs.promises.writeFile(oldbadwords.file, JSON.stringify(oldbadwords, null, 2))
delete oldconfig.ban.badword_level0
delete oldconfig.ban.badword_level1
delete oldconfig.ban.badword_level2
delete oldconfig.ban.badword_level3
if not _.isEmpty(oldconfig)
# log.info oldconfig
fs.writeFileSync('./config/config.json', JSON.stringify(oldconfig, null, 2))
await fs.promises.writeFile('./config/config.json', JSON.stringify(oldconfig, null, 2))
log.info 'imported old config from config.user.json'
fs.renameSync('./config.user.json', './config.user.bak')
catch e
await fs.promises.rename('./config.user.json', './config.user.bak')
catch e
log.info e unless e.code == 'ENOENT'
setting_save = global.setting_save = (settings) ->
try
await fs.promises.writeFile(settings.file, JSON.stringify(settings, null, 2))
catch e
log.warn("setting save fail", e.toString())
return
auth = global.auth = require './ygopro-auth.js'
ygopro = global.ygopro = require './ygopro.js'
roomlist = null
setting_change = global.setting_change = (settings, path, val) ->
# path should be like "modules:welcome"
log.info("setting changed", path, val) if _.isString(val)
path=path.split(':')
if path.length == 0
settings[path[0]]=val
else
target=settings
while path.length > 1
key=path.shift()
target=target[key]
key = path.shift()
target[key] = val
await setting_save(settings)
return
settings = {}
tips = null
dialogues = null
badwords = null
lflists = global.lflists = []
real_windbot_server_ip = null
long_resolve_cards = []
ReplayParser = null
athleticChecker = null
users_cache = {}
geoip = null
dataManager = null
disconnect_list = {} # {old_client, old_server, room_id, timeout, deckbuf}
challonge = null
challonge_cache = {
participants: null
matches: null
}
challonge_queue_callbacks = {
participants: []
matches: []
}
is_challonge_requesting = {
participants: null
matches: null
}
get_callback = () ->
replaced_index = () ->
refresh_challonge_cache = () ->
class ResolveData
constructor: (@func) ->
resolved: false
resolve: (err, data) ->
if @resolved
return false
@resolved = true
@func(err, data)
return true
# 读取配置
default_config = loadJSON('./data/default_config.json')
if fs.existsSync('./config/config.json')
loadLFList = (path) ->
try
for list in fs.promises.readFile(path, 'utf8').match(/!.*/g)
date=list.match(/!([\d\.]+)/)
continue unless date
lflists.push({date: moment(list.match(/!([\d\.]+)/)[1], 'YYYY.MM.DD').utcOffset("-08:00"), tcg: list.indexOf('TCG') != -1})
catch
init = () ->
await createDirectoryIfNotExists("./config")
await importOldConfig()
defaultConfig = await loadJSONAsync('./data/default_config.json')
if await checkFileExists("./config/config.json")
try
config = loadJSON('./config/config.json')
config = await loadJSONAsync('./config/config.json')
catch e
console.error("Failed reading config: ", e.toString())
process.exit(1)
else
else
config = {}
settings = global.settings = merge(default_config, config, { arrayMerge: (destination, source) -> source })
auth = global.auth = require './ygopro-auth.js'
#import old configs
imported = false
#reset http.quick_death_rule from true to 1
if settings.modules.http.quick_death_rule == true
settings = global.settings = merge(defaultConfig, config, { arrayMerge: (destination, source) -> source })
#import old configs
imported = false
#reset http.quick_death_rule from true to 1
if settings.modules.http.quick_death_rule == true
settings.modules.http.quick_death_rule = 1
imported = true
#import the old passwords to new admin user system
if settings.modules.http.password
auth.add_user("olduser", settings.modules.http.password, true, {
#import the old passwords to new admin user system
if settings.modules.http.password
await auth.add_user("olduser", settings.modules.http.password, true, {
"get_rooms": true,
"shout": true,
"stop": true,
......@@ -189,8 +254,8 @@ if settings.modules.http.password
})
delete settings.modules.http.password
imported = true
if settings.modules.tournament_mode.password
auth.add_user("tournament", settings.modules.tournament_mode.password, true, {
if settings.modules.tournament_mode.password
await auth.add_user("tournament", settings.modules.tournament_mode.password, true, {
"duel_log": true,
"download_replay": true,
"clear_duel_log": true,
......@@ -199,142 +264,117 @@ if settings.modules.tournament_mode.password
})
delete settings.modules.tournament_mode.password
imported = true
if settings.modules.pre_util.password
auth.add_user("pre", settings.modules.pre_util.password, true, {
if settings.modules.pre_util.password
await auth.add_user("pre", settings.modules.pre_util.password, true, {
"pre_dashboard": true
})
delete settings.modules.pre_util.password
imported = true
if settings.modules.update_util.password
auth.add_user("update", settings.modules.update_util.password, true, {
if settings.modules.update_util.password
await auth.add_user("update", settings.modules.update_util.password, true, {
"update_dashboard": true
})
delete settings.modules.update_util.password
imported = true
#import the old enable_priority hostinfo
if settings.hostinfo.enable_priority or settings.hostinfo.enable_priority == false
#import the old enable_priority hostinfo
if settings.hostinfo.enable_priority or settings.hostinfo.enable_priority == false
if settings.hostinfo.enable_priority
settings.hostinfo.duel_rule = 3
else
settings.hostinfo.duel_rule = 5
delete settings.hostinfo.enable_priority
imported = true
#import the old Challonge api key option
if settings.modules.challonge.api_key
#import the old Challonge api key option
if settings.modules.challonge.api_key
settings.modules.challonge.options.apiKey = settings.modules.challonge.api_key
delete settings.modules.challonge.api_key
imported = true
#import the old random_duel.blank_pass_match option
if settings.modules.random_duel.blank_pass_match == true
#import the old random_duel.blank_pass_match option
if settings.modules.random_duel.blank_pass_match == true
settings.modules.random_duel.blank_pass_modes = {"S":true,"M":true,"T":false}
delete settings.modules.random_duel.blank_pass_match
imported = true
if settings.modules.random_duel.blank_pass_match == false
if settings.modules.random_duel.blank_pass_match == false
settings.modules.random_duel.blank_pass_modes = {"S":true,"M":false,"T":false}
delete settings.modules.random_duel.blank_pass_match
imported = true
#finish
if imported
setting_save(settings)
# 读取数据
default_data = loadJSON('./data/default_data.json')
try
tips = global.tips = loadJSON('./config/tips.json')
catch
#finish
if imported
await setting_save(settings)
# 读取数据
default_data = await loadJSONAsync('./data/default_data.json')
try
tips = global.tips = await loadJSONAsync('./config/tips.json')
catch
tips = global.tips = default_data.tips
setting_save(tips)
try
dialogues = global.dialogues = loadJSON('./config/dialogues.json')
catch
await setting_save(tips)
try
dialogues = global.dialogues = await loadJSONAsync('./config/dialogues.json')
catch
dialogues = global.dialogues = default_data.dialogues
setting_save(dialogues)
try
badwords = global.badwords = loadJSON('./config/badwords.json')
catch
await setting_save(dialogues)
try
badwords = global.badwords = await loadJSONAsync('./config/badwords.json')
catch
badwords = global.badwords = default_data.badwords
setting_save(badwords)
try
chat_color = global.chat_color = loadJSON('./config/chat_color.json')
catch
await setting_save(badwords)
if settings.modules.chat_color.enabled
try
chat_color = global.chat_color = await loadJSONAsync('./config/chat_color.json')
catch
chat_color = global.chat_color = default_data.chat_color
setting_save(chat_color)
try
cppversion = parseInt(fs.readFileSync('ygopro/gframe/game.cpp', 'utf8').match(/PRO_VERSION = ([x\dABCDEF]+)/)[1], '16')
setting_change(settings, "version", cppversion)
await setting_save(chat_color)
try
cppversion = parseInt(await fs.promises.readFile('ygopro/gframe/game.cpp', 'utf8').match(/PRO_VERSION = ([x\dABCDEF]+)/)[1], '16')
await setting_change(settings, "version", cppversion)
log.info "ygopro version 0x"+settings.version.toString(16), "(from source code)"
catch
catch
#settings.version = settings.version_default
log.info "ygopro version 0x"+settings.version.toString(16), "(from config)"
# load the lflist of current date
lflists = global.lflists = []
# expansions/lflist
try
for list in fs.readFileSync('ygopro/expansions/lflist.conf', 'utf8').match(/!.*/g)
date=list.match(/!([\d\.]+)/)
continue unless date
lflists.push({date: moment(list.match(/!([\d\.]+)/)[1], 'YYYY.MM.DD').utcOffset("-08:00"), tcg: list.indexOf('TCG') != -1})
catch
# lflist
try
for list in fs.readFileSync('ygopro/lflist.conf', 'utf8').match(/!.*/g)
date=list.match(/!([\d\.]+)/)
continue unless date
lflists.push({date: moment(list.match(/!([\d\.]+)/)[1], 'YYYY.MM.DD').utcOffset("-08:00"), tcg: list.indexOf('TCG') != -1})
catch
# load the lflist of current date
await loadLFList('ygopro/expansions/lflist.conf')
await loadLFList('ygopro/lflist.conf')
if settings.modules.windbot.enabled
windbots = global.windbots = loadJSON(settings.modules.windbot.botlist).windbots
if settings.modules.windbot.enabled
windbots = global.windbots = await loadJSONAsync(settings.modules.windbot.botlist).windbots
real_windbot_server_ip = global.real_windbot_server_ip = settings.modules.windbot.server_ip
if !settings.modules.windbot.server_ip.includes("127.0.0.1")
dns = require('dns')
dns.lookup(settings.modules.windbot.server_ip,(err,addr) ->
if(!err)
real_windbot_server_ip = global.real_windbot_server_ip = addr
)
if settings.modules.heartbeat_detection.enabled
long_resolve_cards = global.long_resolve_cards = loadJSON('./data/long_resolve_cards.json')
real_windbot_server_ip = global.real_windbot_server_ip = await util.promisify(dns.lookup)(settings.modules.windbot.server_ip)
if settings.modules.heartbeat_detection.enabled
long_resolve_cards = global.long_resolve_cards = await loadJSONAsync('./data/long_resolve_cards.json')
if settings.modules.tournament_mode.enable_recover
if settings.modules.tournament_mode.enable_recover
ReplayParser = global.ReplayParser = require "./Replay.js"
if settings.modules.athletic_check.enabled
if settings.modules.athletic_check.enabled
AthleticChecker = require("./athletic-check.js").AthleticChecker
athleticChecker = global.athleticChecker = new AthleticChecker(settings.modules.athletic_check)
# 组件
ygopro = global.ygopro = require './ygopro.js'
roomlist = global.roomlist = require './roomlist.js' if settings.modules.http.websocket_roomlist
if settings.modules.i18n.auto_pick
if settings.modules.http.websocket_roomlist
roomlist = global.roomlist = require './roomlist.js'
if settings.modules.i18n.auto_pick
geoip = require('geoip-country-lite')
# cache users of mycard login
users_cache = {}
if settings.modules.mysql.enabled
if settings.modules.mysql.enabled
DataManager = require('./data-manager/DataManager.js').DataManager
dataManager = global.dataManager = new DataManager(settings.modules.mysql.db, log)
dataManager.init().then(() -> log.info("Database ready."))
else
await dataManager.init()
else
log.warn("Some functions may be limited without MySQL .")
if settings.modules.cloud_replay.enabled
settings.modules.cloud_replay.enabled = false
setting_save(settings)
await setting_save(settings)
log.warn("Cloud replay cannot be enabled because no MySQL.")
if settings.modules.enable_recover.enabled
settings.modules.enable_recover.enabled = false
setting_save(settings)
await setting_save(settings)
log.warn("Recover mode cannot be enabled because no MySQL.")
if settings.modules.chat_color.enabled
settings.modules.chat_color.enabled = false
setting_save(settings)
await setting_save(settings)
log.warn("Chat color cannot be enabled because no MySQL.")
if settings.modules.mycard.enabled
if settings.modules.mycard.enabled
pgClient = require('pg').Client
pg_client = global.pg_client = new pgClient(settings.modules.mycard.auth_database)
pg_client.on 'error', (err) ->
......@@ -355,35 +395,22 @@ if settings.modules.mycard.enabled
log.info "loading mycard user..."
pg_client.connect()
if settings.modules.arena_mode.enabled and settings.modules.arena_mode.init_post.enabled
request.post { url : settings.modules.arena_mode.init_post.url , qs : {
postData = qs.stringify({
ak: settings.modules.arena_mode.init_post.accesskey,
arena: settings.modules.arena_mode.mode
}}, (error, response, body)=>
if error
log.warn 'ARENA INIT POST ERROR', error
else
if response.statusCode >= 400
log.warn 'ARENA INIT POST FAIL', response.statusCode, response.statusMessage, body
#else
# log.info 'ARENA INIT POST OK', response.statusCode, response.statusMessage
return
class ResolveData
constructor: (@func) ->
resolved: false
resolve: (err, data) ->
if @resolved
return false
@resolved = true
@func(err, data)
return true
})
try
await axios.post(settings.modules.arena_mode.init_post.url + "?" + postData, {
responseType: "json"
})
catch e
log.warn 'ARENA INIT POST ERROR', e
if settings.modules.challonge.enabled
if settings.modules.challonge.enabled
challonge_module_name = 'challonge'
if settings.modules.challonge.use_custom_module
challonge_module_name = settings.modules.challonge.use_custom_module
challonge = global.challonge = require(challonge_module_name).createClient(settings.modules.challonge.options)
if settings.modules.challonge.cache_ttl
challonge_cache = {
participants: null
matches: null
......@@ -436,42 +463,152 @@ if settings.modules.challonge.enabled
challonge_cache.matches = null
return
refresh_challonge_cache()
# challonge.participants._index({
# id: settings.modules.challonge.tournament_id,
# callback: (() ->
# challonge.matches._index({
# id: settings.modules.challonge.tournament_id,
# callback: (() ->
# return
# )
# })
# return
# )
# })
if settings.modules.challonge.cache_ttl
setInterval(refresh_challonge_cache, settings.modules.challonge.cache_ttl)
if settings.modules.tips.get
load_tips()
setInterval ()->
for room in ROOM_all when room and room.established
ygopro.stoc_send_random_tip_to_room(room) if room.duel_stage == ygopro.constants.DUEL_STAGE.SIDING or room.duel_stage == ygopro.constants.DUEL_STAGE.BEGIN
return
, 30000
if settings.modules.dialogues.get
load_dialogues()
if settings.modules.random_duel.post_match_scores
setInterval(()->
scores_pair = _.pairs ROOM_players_scores
scores_by_lose = _.sortBy(scores_pair, (score)-> return score[1].lose).reverse() # 败场由高到低
scores_by_win = _.sortBy(scores_by_lose, (score)-> return score[1].win).reverse() # 然后胜场由低到高,再逆转,就是先排胜场再排败场
scores = _.first(scores_by_win, 10)
#log.info scores
request.post { url : settings.modules.random_duel.post_match_scores , form : {
accesskey: settings.modules.random_duel.post_match_accesskey,
rank: JSON.stringify(scores)
}}, (error, response, body)=>
if error
log.warn 'RANDOM SCORE POST ERROR', error
else
if response.statusCode != 204 and response.statusCode != 200
log.warn 'RANDOM SCORE POST FAIL', response.statusCode, response.statusMessage, body
#else
# log.info 'RANDOM SCORE POST OK', response.statusCode, response.statusMessage
return
return
, 60000)
if settings.modules.random_duel.enabled
setInterval ()->
for room in ROOM_all when room and room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN and room.random_type and room.last_active_time and room.waiting_for_player and room.get_disconnected_count() == 0 and (!settings.modules.side_timeout or room.duel_stage != ygopro.constants.DUEL_STAGE.SIDING) and !room.recovered
time_passed = Math.floor((moment() - room.last_active_time) / 1000)
#log.info time_passed
if time_passed >= settings.modules.random_duel.hang_timeout
room.last_active_time = moment()
await ROOM_ban_player(room.waiting_for_player.name, room.waiting_for_player.ip, "${random_ban_reason_AFK}")
room.scores[room.waiting_for_player.name_vpass] = -9
#log.info room.waiting_for_player.name, room.scores[room.waiting_for_player.name_vpass]
ygopro.stoc_send_chat_to_room(room, "#{room.waiting_for_player.name} ${kicked_by_system}", ygopro.constants.COLORS.RED)
CLIENT_send_replays(room.waiting_for_player, room)
CLIENT_kick(room.waiting_for_player)
else if time_passed >= (settings.modules.random_duel.hang_timeout - 20) and not (time_passed % 10)
ygopro.stoc_send_chat_to_room(room, "#{room.waiting_for_player.name} ${afk_warn_part1}#{settings.modules.random_duel.hang_timeout - time_passed}${afk_warn_part2}", ygopro.constants.COLORS.RED)
ROOM_unwelcome(room, room.waiting_for_player, "${random_ban_reason_AFK}")
return
, 1000
if settings.modules.mycard.enabled
setInterval ()->
for room in ROOM_all when room and room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN and room.arena and room.last_active_time and room.waiting_for_player and room.get_disconnected_count() == 0 and (!settings.modules.side_timeout or room.duel_stage != ygopro.constants.DUEL_STAGE.SIDING) and !room.recovered
time_passed = Math.floor((moment() - room.last_active_time) / 1000)
#log.info time_passed
if time_passed >= settings.modules.random_duel.hang_timeout
room.last_active_time = moment()
ygopro.stoc_send_chat_to_room(room, "#{room.waiting_for_player.name} ${kicked_by_system}", ygopro.constants.COLORS.RED)
room.scores[room.waiting_for_player.name_vpass] = -9
#log.info room.waiting_for_player.name, room.scores[room.waiting_for_player.name_vpass]
CLIENT_send_replays(room.waiting_for_player, room)
CLIENT_kick(room.waiting_for_player)
else if time_passed >= (settings.modules.random_duel.hang_timeout - 20) and not (time_passed % 10)
ygopro.stoc_send_chat_to_room(room, "#{room.waiting_for_player.name} ${afk_warn_part1}#{settings.modules.random_duel.hang_timeout - time_passed}${afk_warn_part2}", ygopro.constants.COLORS.RED)
return
if true # settings.modules.arena_mode.punish_quit_before_match
for room in ROOM_all when room and room.arena and room.duel_stage == ygopro.constants.DUEL_STAGE.BEGIN and room.get_playing_player().length < 2
player = room.get_playing_player()[0]
if player and player.join_time and !player.arena_quit_free
waited_time = moment() - player.join_time
if waited_time >= 30000
ygopro.stoc_send_chat(player, "${arena_wait_timeout}", ygopro.constants.COLORS.BABYBLUE)
player.arena_quit_free = true
else if waited_time >= 5000 and waited_time < 6000
ygopro.stoc_send_chat(player, "${arena_wait_hint}", ygopro.constants.COLORS.BABYBLUE)
return
, 1000
if settings.modules.heartbeat_detection.enabled
setInterval ()->
for room in ROOM_all when room and room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN and (room.hostinfo.time_limit == 0 or room.duel_stage != ygopro.constants.DUEL_STAGE.DUELING) and !room.windbot
for player in room.get_playing_player() when player and (room.duel_stage != ygopro.constants.DUEL_STAGE.SIDING or player.selected_preduel)
CLIENT_heartbeat_register(player, true)
return
, settings.modules.heartbeat_detection.interval
if settings.modules.windbot.enabled and settings.modules.windbot.spawn
spawn_windbot()
setInterval ()->
current_time = moment()
for room in ROOM_all when room and room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN and room.hostinfo.auto_death and !room.auto_death_triggered and current_time - moment(room.start_time) > 60000 * room.hostinfo.auto_death
room.auto_death_triggered = true
room.start_death()
, 1000
net.createServer(netRequestHandler).listen settings.port, ->
log.info "server started", settings.port
return
if settings.modules.stop
log.info "NOTE: server not open due to config, ", settings.modules.stop
http_server = http.createServer(httpRequestListener)
http_server.listen settings.modules.http.port
if settings.modules.http.ssl.enabled
https = require 'https'
options =
cert: await fs.promises.readFile(settings.modules.http.ssl.cert)
key: await fs.promises.readFile(settings.modules.http.ssl.key)
https_server = https.createServer(options, httpRequestListener)
if settings.modules.http.websocket_roomlist and roomlist
roomlist.init https_server, ROOM_all
https_server.listen settings.modules.http.ssl.port
mkdirList = [
"./plugins",
settings.modules.tournament_mode.deck_path,
settings.modules.tournament_mode.replay_path,
settings.modules.tournament_mode.log_save_path,
settings.modules.deck_log.local
]
for path in mkdirList
await createDirectoryIfNotExists(path)
plugin_list = await fs.promises.readdir("./plugins")
for plugin_filename in plugin_list
plugin_path = process.cwd() + "/plugins/" + plugin_filename
require(plugin_path)
log.info("Plugin loaded:", plugin_filename)
# 获取可用内存
memory_usage = global.memory_usage = 0
get_memory_usage = get_memory_usage = ()->
prc_free = exec("free")
prc_free.stdout.on 'data', (data)->
lines = data.toString().split(/\n/g)
line = lines[0].split(/\s+/)
new_free = if line[6] == 'available' then true else false
line = lines[1].split(/\s+/)
total = parseInt(line[1], 10)
free = parseInt(line[3], 10)
buffers = parseInt(line[5], 10)
if new_free
actualFree = parseInt(line[6], 10)
else
cached = parseInt(line[6], 10)
actualFree = free + buffers + cached
percentUsed = parseFloat(((1 - (actualFree / total)) * 100).toFixed(2))
get_memory_usage = global.get_memory_usage = ()->
percentUsed = os.freemem() * os.totalmem() * 100
memory_usage = global.memory_usage = percentUsed
return
return
get_memory_usage()
setInterval(get_memory_usage, 3000)
......@@ -555,28 +692,6 @@ ROOM_player_get_score = global.ROOM_player_get_score = (player)->
return "${random_score_part1}#{player.name} ${random_score_part2} #{Math.ceil(score.win/total*100)}${random_score_part3} #{Math.ceil(score.flee/total*100)}${random_score_part4}"
return
if settings.modules.random_duel.post_match_scores
setInterval(()->
scores_pair = _.pairs ROOM_players_scores
scores_by_lose = _.sortBy(scores_pair, (score)-> return score[1].lose).reverse() # 败场由高到低
scores_by_win = _.sortBy(scores_by_lose, (score)-> return score[1].win).reverse() # 然后胜场由低到高,再逆转,就是先排胜场再排败场
scores = _.first(scores_by_win, 10)
#log.info scores
request.post { url : settings.modules.random_duel.post_match_scores , form : {
accesskey: settings.modules.random_duel.post_match_accesskey,
rank: JSON.stringify(scores)
}}, (error, response, body)=>
if error
log.warn 'RANDOM SCORE POST ERROR', error
else
if response.statusCode != 204 and response.statusCode != 200
log.warn 'RANDOM SCORE POST FAIL', response.statusCode, response.statusMessage, body
#else
# log.info 'RANDOM SCORE POST OK', response.statusCode, response.statusMessage
return
return
, 60000)
ROOM_find_or_create_by_name = global.ROOM_find_or_create_by_name = (name, player_ip)->
uname=name.toUpperCase()
if settings.modules.windbot.enabled and (uname[0...2] == 'AI' or (!settings.modules.random_duel.enabled and uname == ''))
......@@ -980,9 +1095,6 @@ CLIENT_kick_reconnect = global.CLIENT_kick_reconnect = (client, deckbuf) ->
CLIENT_reconnect_unregister(client, true)
return
if settings.modules.reconnect.enabled
disconnect_list = {} # {old_client, old_server, room_id, timeout, deckbuf}
CLIENT_heartbeat_unregister = global.CLIENT_heartbeat_unregister = (client) ->
if !settings.modules.heartbeat_detection.enabled or !client.heartbeat_timeout
return false
......@@ -1606,7 +1718,7 @@ class Room
await return
# 网络连接
net.createServer (client) ->
netRequestHandler = (client) ->
client.ip = client.remoteAddress
client.is_local = client.ip and (client.ip.includes('127.0.0.1') or client.ip.includes(real_windbot_server_ip))
......@@ -1786,12 +1898,6 @@ net.createServer (client) ->
return
return
.listen settings.port, ->
log.info "server started", settings.port
return
if settings.modules.stop
log.info "NOTE: server not open due to config, ", settings.modules.stop
deck_name_match = global.deck_name_match = (deck_name, player_name) ->
if deck_name == player_name or deck_name == player_name + ".ydk" or deck_name == player_name + ".ydk.ydk"
......@@ -2396,25 +2502,8 @@ ygopro.stoc_follow 'JOIN_GAME', false, (buffer, info, client, server, datas)->
await return
# 登场台词
load_dialogues = global.load_dialogues = (callback) ->
request
url: settings.modules.dialogues.get
json: true
, (error, response, body)->
if _.isString body
log.warn "dialogues bad json", body
else if error or !body
log.warn 'dialogues error', error, response
else
setting_change(dialogues, "dialogues", body)
log.info "dialogues loaded", _.size dialogues.dialogues
if callback
callback(error, body)
return
await return
if settings.modules.dialogues.get
load_dialogues()
load_dialogues = global.load_dialogues = () ->
return await loadRemoteData(dialogues, "dialogues", settings.modules.dialogues.get)
ygopro.stoc_follow 'GAME_MSG', true, (buffer, info, client, server, datas)->
room=ROOM_all[client.rid]
......@@ -2883,30 +2972,26 @@ ygopro.stoc_send_random_tip_to_room = (room)->
ygopro.stoc_send_chat_to_room(room, "Tip: " + tips.tips[Math.floor(Math.random() * tips.tips.length)])
await return
load_tips = global.load_tips = (callback)->
request
url: settings.modules.tips.get
json: true
, (error, response, body)->
loadRemoteData = global.loadRemoteData = (loadObject, name, url)->
try
body = (await axios.get(url, {
responseType: "json"
})).data
if _.isString body
log.warn "tips bad json", body
else if error or !body
log.warn 'tips error', error, response
else
setting_change(tips, "tips", body)
log.info "tips loaded", tips.tips.length
if callback
callback(error, body)
return
await return
log.warn "#{name} bad json", body
return false
if !body
log.warn "#{name} empty", body
return false
await setting_change(loadObject, name, body)
log.info "#{name} loaded"
return true
catch e
log.warn "#{name} error", e
return false
if settings.modules.tips.get
load_tips()
setInterval ()->
for room in ROOM_all when room and room.established
ygopro.stoc_send_random_tip_to_room(room) if room.duel_stage == ygopro.constants.DUEL_STAGE.SIDING or room.duel_stage == ygopro.constants.DUEL_STAGE.BEGIN
return
, 30000
load_tips = global.load_tips = ()->
return await loadRemoteData(tips, "tips", settings.modules.tips.get)
ygopro.stoc_follow 'DUEL_START', false, (buffer, info, client, server, datas)->
room=ROOM_all[client.rid]
......@@ -3522,70 +3607,6 @@ ygopro.stoc_follow 'REPLAY', true, (buffer, info, client, server, datas)->
else
await return settings.modules.replay_delay and room.hostinfo.mode == 1
if settings.modules.random_duel.enabled
setInterval ()->
for room in ROOM_all when room and room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN and room.random_type and room.last_active_time and room.waiting_for_player and room.get_disconnected_count() == 0 and (!settings.modules.side_timeout or room.duel_stage != ygopro.constants.DUEL_STAGE.SIDING) and !room.recovered
time_passed = Math.floor((moment() - room.last_active_time) / 1000)
#log.info time_passed
if time_passed >= settings.modules.random_duel.hang_timeout
room.last_active_time = moment()
await ROOM_ban_player(room.waiting_for_player.name, room.waiting_for_player.ip, "${random_ban_reason_AFK}")
room.scores[room.waiting_for_player.name_vpass] = -9
#log.info room.waiting_for_player.name, room.scores[room.waiting_for_player.name_vpass]
ygopro.stoc_send_chat_to_room(room, "#{room.waiting_for_player.name} ${kicked_by_system}", ygopro.constants.COLORS.RED)
CLIENT_send_replays(room.waiting_for_player, room)
CLIENT_kick(room.waiting_for_player)
else if time_passed >= (settings.modules.random_duel.hang_timeout - 20) and not (time_passed % 10)
ygopro.stoc_send_chat_to_room(room, "#{room.waiting_for_player.name} ${afk_warn_part1}#{settings.modules.random_duel.hang_timeout - time_passed}${afk_warn_part2}", ygopro.constants.COLORS.RED)
ROOM_unwelcome(room, room.waiting_for_player, "${random_ban_reason_AFK}")
return
, 1000
if settings.modules.mycard.enabled
setInterval ()->
for room in ROOM_all when room and room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN and room.arena and room.last_active_time and room.waiting_for_player and room.get_disconnected_count() == 0 and (!settings.modules.side_timeout or room.duel_stage != ygopro.constants.DUEL_STAGE.SIDING) and !room.recovered
time_passed = Math.floor((moment() - room.last_active_time) / 1000)
#log.info time_passed
if time_passed >= settings.modules.random_duel.hang_timeout
room.last_active_time = moment()
ygopro.stoc_send_chat_to_room(room, "#{room.waiting_for_player.name} ${kicked_by_system}", ygopro.constants.COLORS.RED)
room.scores[room.waiting_for_player.name_vpass] = -9
#log.info room.waiting_for_player.name, room.scores[room.waiting_for_player.name_vpass]
CLIENT_send_replays(room.waiting_for_player, room)
CLIENT_kick(room.waiting_for_player)
else if time_passed >= (settings.modules.random_duel.hang_timeout - 20) and not (time_passed % 10)
ygopro.stoc_send_chat_to_room(room, "#{room.waiting_for_player.name} ${afk_warn_part1}#{settings.modules.random_duel.hang_timeout - time_passed}${afk_warn_part2}", ygopro.constants.COLORS.RED)
return
if true # settings.modules.arena_mode.punish_quit_before_match
for room in ROOM_all when room and room.arena and room.duel_stage == ygopro.constants.DUEL_STAGE.BEGIN and room.get_playing_player().length < 2
player = room.get_playing_player()[0]
if player and player.join_time and !player.arena_quit_free
waited_time = moment() - player.join_time
if waited_time >= 30000
ygopro.stoc_send_chat(player, "${arena_wait_timeout}", ygopro.constants.COLORS.BABYBLUE)
player.arena_quit_free = true
else if waited_time >= 5000 and waited_time < 6000
ygopro.stoc_send_chat(player, "${arena_wait_hint}", ygopro.constants.COLORS.BABYBLUE)
return
, 1000
if settings.modules.heartbeat_detection.enabled
setInterval ()->
for room in ROOM_all when room and room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN and (room.hostinfo.time_limit == 0 or room.duel_stage != ygopro.constants.DUEL_STAGE.DUELING) and !room.windbot
for player in room.get_playing_player() when player and (room.duel_stage != ygopro.constants.DUEL_STAGE.SIDING or player.selected_preduel)
CLIENT_heartbeat_register(player, true)
return
, settings.modules.heartbeat_detection.interval
setInterval ()->
current_time = moment()
for room in ROOM_all when room and room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN and room.hostinfo.auto_death and !room.auto_death_triggered and current_time - moment(room.start_time) > 60000 * room.hostinfo.auto_death
room.auto_death_triggered = true
room.start_death()
, 1000
# spawn windbot
windbot_looplimit = 0
windbot_process = global.windbot_process = null
......@@ -3622,18 +3643,15 @@ spawn_windbot = global.spawn_windbot = () ->
return
return
if settings.modules.windbot.enabled and settings.modules.windbot.spawn
spawn_windbot()
global.rebooted = false
#http
if settings.modules.http
if true
addCallback = (callback, text)->
if not callback then return text
return callback + "( " + text + " );"
requestListener = (request, response)->
httpRequestListener = (request, response)->
parseQueryString = true
u = url.parse(request.url, parseQueryString)
#pass_validated = u.query.pass == settings.modules.http.password
......@@ -3823,26 +3841,24 @@ if settings.modules.http
response.writeHead(200)
response.end(addCallback(u.query.callback, "['密码错误', 0]"))
return
load_tips((err)->
success = await load_tips()
response.writeHead(200)
if(err)
response.end(addCallback(u.query.callback, "['tip fail', '" + settings.modules.tips.get + "']"))
else
if success
response.end(addCallback(u.query.callback, "['tip ok', '" + settings.modules.tips.get + "']"))
)
else
response.end(addCallback(u.query.callback, "['tip fail', '" + settings.modules.tips.get + "']"))
else if u.query.loaddialogues
if !await auth.auth(u.query.username, u.query.pass, "change_settings", "change_dialogues")
response.writeHead(200)
response.end(addCallback(u.query.callback, "['密码错误', 0]"))
return
load_dialogues((err)->
success = await load_tips()
response.writeHead(200)
if(err)
response.end(addCallback(u.query.callback, "['dialogues fail', '" + settings.modules.dialogues.get + "']"))
if success
response.end(addCallback(u.query.callback, "['dialogue ok', '" + settings.modules.tips.get + "']"))
else
response.end(addCallback(u.query.callback, "['dialogues ok', '" +settings.modules.dialogues.get + "']"))
)
response.end(addCallback(u.query.callback, "['dialogue fail', '" + settings.modules.tips.get + "']"))
else if u.query.ban
if !await auth.auth(u.query.username, u.query.pass, "ban_user", "ban_user")
......@@ -3942,31 +3958,4 @@ if settings.modules.http
response.end()
return
http_server = http.createServer(requestListener)
http_server.listen settings.modules.http.port
if settings.modules.http.ssl.enabled
https = require 'https'
options =
cert: fs.readFileSync(settings.modules.http.ssl.cert)
key: fs.readFileSync(settings.modules.http.ssl.key)
https_server = https.createServer(options, requestListener)
if settings.modules.http.websocket_roomlist and roomlist
roomlist.init https_server, ROOM_all
https_server.listen settings.modules.http.ssl.port
mkdirList = [
"./plugins",
settings.modules.tournament_mode.deck_path,
settings.modules.tournament_mode.replay_path,
settings.modules.tournament_mode.log_save_path,
settings.modules.deck_log.local
]
if not fs.existsSync('./plugins')
fs.mkdirSync('./plugins')
plugin_list = fs.readdirSync("./plugins")
for plugin_filename in plugin_list
plugin_path = process.cwd() + "/plugins/" + plugin_filename
require(plugin_path)
log.info("Plugin loaded:", plugin_filename)
init()
// Generated by CoffeeScript 2.5.1
(function() {
// 标准库
var AthleticChecker, CLIENT_get_authorize_key, CLIENT_get_kick_reconnect_target, CLIENT_heartbeat_register, CLIENT_heartbeat_unregister, CLIENT_import_data, CLIENT_is_able_to_kick_reconnect, CLIENT_is_able_to_reconnect, CLIENT_is_banned_by_mc, CLIENT_is_player, CLIENT_kick, CLIENT_kick_reconnect, CLIENT_pre_reconnect, CLIENT_reconnect, CLIENT_reconnect_register, CLIENT_reconnect_unregister, CLIENT_send_pre_reconnect_info, CLIENT_send_reconnect_info, CLIENT_send_replays, DataManager, Q, ROOM_all, ROOM_bad_ip, ROOM_ban_player, ROOM_clear_disconnect, ROOM_connected_ip, ROOM_find_by_name, ROOM_find_by_pid, ROOM_find_by_port, ROOM_find_by_title, ROOM_find_or_create_ai, ROOM_find_or_create_by_name, ROOM_find_or_create_random, ROOM_kick, ROOM_player_flee, ROOM_player_get_score, ROOM_player_lose, ROOM_player_win, ROOM_players_oppentlist, ROOM_players_scores, ROOM_unwelcome, ROOM_validate, ReplayParser, ResolveData, Room, SERVER_clear_disconnect, SERVER_kick, SOCKET_flush_data, _, _async, addCallback, athleticChecker, auth, axios, badwords, ban_user, bunyan, challonge, challonge_cache, challonge_module_name, challonge_queue_callbacks, challonge_type, chat_color, config, cppversion, crypto, dataManager, date, deck_name_match, default_config, default_data, dialogues, disconnect_list, dns, e, exec, execFile, fs, geoip, getSeedTimet, get_callback, get_memory_usage, http, http_server, https, https_server, import_datas, imported, is_challonge_requesting, j, l, len, len1, len2, len3, lflists, list, loadJSON, load_dialogues, load_tips, log, long_resolve_cards, m, memory_usage, merge, mkdirList, moment, n, net, oldbadwords, oldconfig, olddialogues, oldtips, options, os, path, pgClient, pg_client, pg_query, plugin_filename, plugin_list, plugin_path, qs, real_windbot_server_ip, ref, ref1, ref2, refresh_challonge_cache, release_disconnect, replaced_index, report_to_big_brother, request, requestListener, roomlist, setting_change, setting_save, settings, spawn, spawnSync, spawn_windbot, tips, url, users_cache, util, wait_room_start, wait_room_start_arena, windbot_looplimit, windbot_process, windbots, ygopro, zlib;
var CLIENT_get_authorize_key, CLIENT_get_kick_reconnect_target, CLIENT_heartbeat_register, CLIENT_heartbeat_unregister, CLIENT_import_data, CLIENT_is_able_to_kick_reconnect, CLIENT_is_able_to_reconnect, CLIENT_is_banned_by_mc, CLIENT_is_player, CLIENT_kick, CLIENT_kick_reconnect, CLIENT_pre_reconnect, CLIENT_reconnect, CLIENT_reconnect_register, CLIENT_reconnect_unregister, CLIENT_send_pre_reconnect_info, CLIENT_send_reconnect_info, CLIENT_send_replays, Q, ROOM_all, ROOM_bad_ip, ROOM_ban_player, ROOM_clear_disconnect, ROOM_connected_ip, ROOM_find_by_name, ROOM_find_by_pid, ROOM_find_by_port, ROOM_find_by_title, ROOM_find_or_create_ai, ROOM_find_or_create_by_name, ROOM_find_or_create_random, ROOM_kick, ROOM_player_flee, ROOM_player_get_score, ROOM_player_lose, ROOM_player_win, ROOM_players_oppentlist, ROOM_players_scores, ROOM_unwelcome, ROOM_validate, ReplayParser, ResolveData, Room, SERVER_clear_disconnect, SERVER_kick, SOCKET_flush_data, _, _async, addCallback, athleticChecker, auth, axios, badwords, ban_user, bunyan, challonge, challonge_cache, challonge_queue_callbacks, checkFileExists, createDirectoryIfNotExists, crypto, dataManager, deck_name_match, dialogues, disconnect_list, exec, execFile, fs, geoip, getSeedTimet, get_callback, get_memory_usage, http, httpRequestListener, importOldConfig, import_datas, init, is_challonge_requesting, lflists, loadJSON, loadJSONAsync, loadLFList, loadRemoteData, load_dialogues, load_tips, log, long_resolve_cards, memory_usage, merge, moment, net, netRequestHandler, os, path, qs, real_windbot_server_ip, refresh_challonge_cache, release_disconnect, replaced_index, report_to_big_brother, request, roomlist, setting_change, setting_save, settings, spawn, spawnSync, spawn_windbot, tips, url, users_cache, util, wait_room_start, wait_room_start_arena, windbot_looplimit, windbot_process, ygopro, zlib;
net = require('net');
......@@ -42,6 +42,8 @@
zlib = require('zlib');
axios = require('axios');
bunyan = require('bunyan');
log = global.log = bunyan.createLogger({
......@@ -74,32 +76,79 @@
loadJSON = require('load-json-file').sync;
loadJSONAsync = require('load-json-file');
util = require("util");
Q = require("q");
//heapdump = require 'heapdump'
checkFileExists = async(path) => {
var e;
try {
await fs.promises.access(path);
return true;
} catch (error1) {
e = error1;
return false;
}
};
// 配置
// 导入旧配置
if (!fs.existsSync('./config')) {
fs.mkdirSync('./config');
createDirectoryIfNotExists = async(path) => {
if (!(await checkFileExists(path))) {
return (await fs.promises.mkdir(path, {
recursive: true
}));
}
};
setting_save = global.setting_save = async function(settings) {
var e;
try {
oldconfig = loadJSON('./config.user.json');
await fs.promises.writeFile(settings.file, JSON.stringify(settings, null, 2));
} catch (error1) {
e = error1;
log.warn("setting save fail", e.toString());
}
};
setting_change = global.setting_change = async function(settings, path, val) {
var key, target;
if (_.isString(val)) {
// path should be like "modules:welcome"
log.info("setting changed", path, val);
}
path = path.split(':');
if (path.length === 0) {
settings[path[0]] = val;
} else {
target = settings;
while (path.length > 1) {
key = path.shift();
target = target[key];
}
key = path.shift();
target[key] = val;
}
await setting_save(settings);
};
importOldConfig = async function() {
var e, oldbadwords, oldconfig, olddialogues, oldtips;
try {
oldconfig = (await loadJSONAsync('./config.user.json'));
if (oldconfig.tips) {
oldtips = {};
oldtips.file = './config/tips.json';
oldtips.tips = oldconfig.tips;
fs.writeFileSync(oldtips.file, JSON.stringify(oldtips, null, 2));
await fs.promises.writeFile(oldtips.file, JSON.stringify(oldtips, null, 2));
delete oldconfig.tips;
}
if (oldconfig.dialogues) {
olddialogues = {};
olddialogues.file = './config/dialogues.json';
olddialogues.dialogues = oldconfig.dialogues;
fs.writeFileSync(olddialogues.file, JSON.stringify(olddialogues, null, 2));
await fs.promises.writeFile(olddialogues.file, JSON.stringify(olddialogues, null, 2));
delete oldconfig.dialogues;
}
oldbadwords = {};
......@@ -119,7 +168,7 @@
}
if (!_.isEmpty(oldbadwords)) {
oldbadwords.file = './config/badwords.json';
fs.writeFileSync(oldbadwords.file, JSON.stringify(oldbadwords, null, 2));
await fs.promises.writeFile(oldbadwords.file, JSON.stringify(oldbadwords, null, 2));
delete oldconfig.ban.badword_level0;
delete oldconfig.ban.badword_level1;
delete oldconfig.ban.badword_level2;
......@@ -127,53 +176,126 @@
}
if (!_.isEmpty(oldconfig)) {
// log.info oldconfig
fs.writeFileSync('./config/config.json', JSON.stringify(oldconfig, null, 2));
await fs.promises.writeFile('./config/config.json', JSON.stringify(oldconfig, null, 2));
log.info('imported old config from config.user.json');
}
fs.renameSync('./config.user.json', './config.user.bak');
return (await fs.promises.rename('./config.user.json', './config.user.bak'));
} catch (error1) {
e = error1;
if (e.code !== 'ENOENT') {
log.info(e);
return log.info(e);
}
}
};
setting_save = global.setting_save = async function(settings) {
try {
await fs.promises.writeFile(settings.file, JSON.stringify(settings, null, 2));
} catch (error1) {
e = error1;
log.warn("setting save fail", e.toString());
}
auth = global.auth = require('./ygopro-auth.js');
ygopro = global.ygopro = require('./ygopro.js');
roomlist = null;
settings = {};
tips = null;
dialogues = null;
badwords = null;
lflists = global.lflists = [];
real_windbot_server_ip = null;
long_resolve_cards = [];
ReplayParser = null;
athleticChecker = null;
users_cache = {};
geoip = null;
dataManager = null;
disconnect_list = {}; // {old_client, old_server, room_id, timeout, deckbuf}
challonge = null;
challonge_cache = {
participants: null,
matches: null
};
setting_change = global.setting_change = async function(settings, path, val) {
var key, target;
if (_.isString(val)) {
// path should be like "modules:welcome"
log.info("setting changed", path, val);
challonge_queue_callbacks = {
participants: [],
matches: []
};
is_challonge_requesting = {
participants: null,
matches: null
};
get_callback = function() {};
replaced_index = function() {};
refresh_challonge_cache = function() {};
ResolveData = (function() {
class ResolveData {
constructor(func) {
this.func = func;
}
path = path.split(':');
if (path.length === 0) {
settings[path[0]] = val;
} else {
target = settings;
while (path.length > 1) {
key = path.shift();
target = target[key];
resolve(err, data) {
if (this.resolved) {
return false;
}
key = path.shift();
target[key] = val;
this.resolved = true;
this.func(err, data);
return true;
}
await setting_save(settings);
};
// 读取配置
default_config = loadJSON('./data/default_config.json');
ResolveData.prototype.resolved = false;
return ResolveData;
}).call(this);
if (fs.existsSync('./config/config.json')) {
loadLFList = function(path) {
var date, j, len, list, ref, results;
try {
config = loadJSON('./config/config.json');
ref = fs.promises.readFile(path, 'utf8').match(/!.*/g);
results = [];
for (j = 0, len = ref.length; j < len; j++) {
list = ref[j];
date = list.match(/!([\d\.]+)/);
if (!date) {
continue;
}
results.push(lflists.push({
date: moment(list.match(/!([\d\.]+)/)[1], 'YYYY.MM.DD').utcOffset("-08:00"),
tcg: list.indexOf('TCG') !== -1
}));
}
return results;
} catch (error1) {
}
};
init = async function() {
var AthleticChecker, DataManager, challonge_module_name, challonge_type, chat_color, config, cppversion, defaultConfig, default_data, dns, e, http_server, https, https_server, imported, j, l, len, len1, len2, m, mkdirList, options, pgClient, pg_client, pg_query, plugin_filename, plugin_list, plugin_path, postData, ref, results, windbots;
await createDirectoryIfNotExists("./config");
await importOldConfig();
defaultConfig = (await loadJSONAsync('./data/default_config.json'));
if ((await checkFileExists("./config/config.json"))) {
try {
config = (await loadJSONAsync('./config/config.json'));
} catch (error1) {
e = error1;
console.error("Failed reading config: ", e.toString());
......@@ -182,27 +304,21 @@
} else {
config = {};
}
settings = global.settings = merge(default_config, config, {
settings = global.settings = merge(defaultConfig, config, {
arrayMerge: function(destination, source) {
return source;
}
});
auth = global.auth = require('./ygopro-auth.js');
//import old configs
imported = false;
//reset http.quick_death_rule from true to 1
if (settings.modules.http.quick_death_rule === true) {
settings.modules.http.quick_death_rule = 1;
imported = true;
}
//import the old passwords to new admin user system
if (settings.modules.http.password) {
auth.add_user("olduser", settings.modules.http.password, true, {
await auth.add_user("olduser", settings.modules.http.password, true, {
"get_rooms": true,
"shout": true,
"stop": true,
......@@ -214,9 +330,8 @@
delete settings.modules.http.password;
imported = true;
}
if (settings.modules.tournament_mode.password) {
auth.add_user("tournament", settings.modules.tournament_mode.password, true, {
await auth.add_user("tournament", settings.modules.tournament_mode.password, true, {
"duel_log": true,
"download_replay": true,
"clear_duel_log": true,
......@@ -226,23 +341,20 @@
delete settings.modules.tournament_mode.password;
imported = true;
}
if (settings.modules.pre_util.password) {
auth.add_user("pre", settings.modules.pre_util.password, true, {
await auth.add_user("pre", settings.modules.pre_util.password, true, {
"pre_dashboard": true
});
delete settings.modules.pre_util.password;
imported = true;
}
if (settings.modules.update_util.password) {
auth.add_user("update", settings.modules.update_util.password, true, {
await auth.add_user("update", settings.modules.update_util.password, true, {
"update_dashboard": true
});
delete settings.modules.update_util.password;
imported = true;
}
//import the old enable_priority hostinfo
if (settings.hostinfo.enable_priority || settings.hostinfo.enable_priority === false) {
if (settings.hostinfo.enable_priority) {
......@@ -253,14 +365,12 @@
delete settings.hostinfo.enable_priority;
imported = true;
}
//import the old Challonge api key option
if (settings.modules.challonge.api_key) {
settings.modules.challonge.options.apiKey = settings.modules.challonge.api_key;
delete settings.modules.challonge.api_key;
imported = true;
}
//import the old random_duel.blank_pass_match option
if (settings.modules.random_duel.blank_pass_match === true) {
settings.modules.random_duel.blank_pass_modes = {
......@@ -271,7 +381,6 @@
delete settings.modules.random_duel.blank_pass_match;
imported = true;
}
if (settings.modules.random_duel.blank_pass_match === false) {
settings.modules.random_duel.blank_pass_modes = {
"S": true,
......@@ -281,156 +390,95 @@
delete settings.modules.random_duel.blank_pass_match;
imported = true;
}
//finish
if (imported) {
setting_save(settings);
await setting_save(settings);
}
// 读取数据
default_data = loadJSON('./data/default_data.json');
default_data = (await loadJSONAsync('./data/default_data.json'));
try {
tips = global.tips = loadJSON('./config/tips.json');
tips = global.tips = (await loadJSONAsync('./config/tips.json'));
} catch (error1) {
tips = global.tips = default_data.tips;
setting_save(tips);
await setting_save(tips);
}
try {
dialogues = global.dialogues = loadJSON('./config/dialogues.json');
dialogues = global.dialogues = (await loadJSONAsync('./config/dialogues.json'));
} catch (error1) {
dialogues = global.dialogues = default_data.dialogues;
setting_save(dialogues);
await setting_save(dialogues);
}
try {
badwords = global.badwords = loadJSON('./config/badwords.json');
badwords = global.badwords = (await loadJSONAsync('./config/badwords.json'));
} catch (error1) {
badwords = global.badwords = default_data.badwords;
setting_save(badwords);
await setting_save(badwords);
}
if (settings.modules.chat_color.enabled) {
try {
chat_color = global.chat_color = loadJSON('./config/chat_color.json');
chat_color = global.chat_color = (await loadJSONAsync('./config/chat_color.json'));
} catch (error1) {
chat_color = global.chat_color = default_data.chat_color;
setting_save(chat_color);
await setting_save(chat_color);
}
}
try {
cppversion = parseInt(fs.readFileSync('ygopro/gframe/game.cpp', 'utf8').match(/PRO_VERSION = ([x\dABCDEF]+)/)[1], '16');
setting_change(settings, "version", cppversion);
cppversion = parseInt((await fs.promises.readFile('ygopro/gframe/game.cpp', 'utf8').match(/PRO_VERSION = ([x\dABCDEF]+)/)[1]), '16');
await setting_change(settings, "version", cppversion);
log.info("ygopro version 0x" + settings.version.toString(16), "(from source code)");
} catch (error1) {
//settings.version = settings.version_default
log.info("ygopro version 0x" + settings.version.toString(16), "(from config)");
}
// load the lflist of current date
lflists = global.lflists = [];
try {
ref = fs.readFileSync('ygopro/expansions/lflist.conf', 'utf8').match(/!.*/g);
// expansions/lflist
for (j = 0, len = ref.length; j < len; j++) {
list = ref[j];
date = list.match(/!([\d\.]+)/);
if (!date) {
continue;
}
lflists.push({
date: moment(list.match(/!([\d\.]+)/)[1], 'YYYY.MM.DD').utcOffset("-08:00"),
tcg: list.indexOf('TCG') !== -1
});
}
} catch (error1) {
}
try {
ref1 = fs.readFileSync('ygopro/lflist.conf', 'utf8').match(/!.*/g);
// lflist
for (l = 0, len1 = ref1.length; l < len1; l++) {
list = ref1[l];
date = list.match(/!([\d\.]+)/);
if (!date) {
continue;
}
lflists.push({
date: moment(list.match(/!([\d\.]+)/)[1], 'YYYY.MM.DD').utcOffset("-08:00"),
tcg: list.indexOf('TCG') !== -1
});
}
} catch (error1) {
}
await loadLFList('ygopro/expansions/lflist.conf');
await loadLFList('ygopro/lflist.conf');
if (settings.modules.windbot.enabled) {
windbots = global.windbots = loadJSON(settings.modules.windbot.botlist).windbots;
windbots = global.windbots = (await loadJSONAsync(settings.modules.windbot.botlist).windbots);
real_windbot_server_ip = global.real_windbot_server_ip = settings.modules.windbot.server_ip;
if (!settings.modules.windbot.server_ip.includes("127.0.0.1")) {
dns = require('dns');
dns.lookup(settings.modules.windbot.server_ip, function(err, addr) {
if (!err) {
return real_windbot_server_ip = global.real_windbot_server_ip = addr;
}
});
real_windbot_server_ip = global.real_windbot_server_ip = (await util.promisify(dns.lookup)(settings.modules.windbot.server_ip));
}
}
if (settings.modules.heartbeat_detection.enabled) {
long_resolve_cards = global.long_resolve_cards = loadJSON('./data/long_resolve_cards.json');
long_resolve_cards = global.long_resolve_cards = (await loadJSONAsync('./data/long_resolve_cards.json'));
}
if (settings.modules.tournament_mode.enable_recover) {
ReplayParser = global.ReplayParser = require("./Replay.js");
}
if (settings.modules.athletic_check.enabled) {
AthleticChecker = require("./athletic-check.js").AthleticChecker;
athleticChecker = global.athleticChecker = new AthleticChecker(settings.modules.athletic_check);
}
// 组件
ygopro = global.ygopro = require('./ygopro.js');
if (settings.modules.http.websocket_roomlist) {
roomlist = global.roomlist = require('./roomlist.js');
}
if (settings.modules.i18n.auto_pick) {
geoip = require('geoip-country-lite');
}
// cache users of mycard login
users_cache = {};
if (settings.modules.mysql.enabled) {
DataManager = require('./data-manager/DataManager.js').DataManager;
dataManager = global.dataManager = new DataManager(settings.modules.mysql.db, log);
dataManager.init().then(function() {
return log.info("Database ready.");
});
await dataManager.init();
} else {
log.warn("Some functions may be limited without MySQL .");
if (settings.modules.cloud_replay.enabled) {
settings.modules.cloud_replay.enabled = false;
setting_save(settings);
await setting_save(settings);
log.warn("Cloud replay cannot be enabled because no MySQL.");
}
if (settings.modules.enable_recover.enabled) {
settings.modules.enable_recover.enabled = false;
setting_save(settings);
await setting_save(settings);
log.warn("Recover mode cannot be enabled because no MySQL.");
}
if (settings.modules.chat_color.enabled) {
settings.modules.chat_color.enabled = false;
setting_save(settings);
await setting_save(settings);
log.warn("Chat color cannot be enabled because no MySQL.");
}
}
if (settings.modules.mycard.enabled) {
pgClient = require('pg').Client;
pg_client = global.pg_client = new pgClient(settings.modules.mycard.auth_database);
......@@ -452,61 +500,30 @@
log.info("loading mycard user...");
pg_client.connect();
if (settings.modules.arena_mode.enabled && settings.modules.arena_mode.init_post.enabled) {
request.post({
url: settings.modules.arena_mode.init_post.url,
qs: {
postData = qs.stringify({
ak: settings.modules.arena_mode.init_post.accesskey,
arena: settings.modules.arena_mode.mode
}
}, (error, response, body) => {
if (error) {
log.warn('ARENA INIT POST ERROR', error);
} else {
if (response.statusCode >= 400) {
log.warn('ARENA INIT POST FAIL', response.statusCode, response.statusMessage, body);
}
}
});
try {
await axios.post(settings.modules.arena_mode.init_post.url + "?" + postData, {
responseType: "json"
});
} catch (error1) {
e = error1;
log.warn('ARENA INIT POST ERROR', e);
}
}
ResolveData = (function() {
//else
// log.info 'ARENA INIT POST OK', response.statusCode, response.statusMessage
class ResolveData {
constructor(func) {
this.func = func;
}
resolve(err, data) {
if (this.resolved) {
return false;
}
this.resolved = true;
this.func(err, data);
return true;
}
};
ResolveData.prototype.resolved = false;
return ResolveData;
}).call(this);
if (settings.modules.challonge.enabled) {
challonge_module_name = 'challonge';
if (settings.modules.challonge.use_custom_module) {
challonge_module_name = settings.modules.challonge.use_custom_module;
}
challonge = global.challonge = require(challonge_module_name).createClient(settings.modules.challonge.options);
if (settings.modules.challonge.cache_ttl) {
challonge_cache = {
participants: null,
matches: null
};
}
challonge_queue_callbacks = {
participants: [],
matches: []
......@@ -549,9 +566,9 @@
}
};
};
ref2 = ["participants", "matches"];
for (m = 0, len2 = ref2.length; m < len2; m++) {
challonge_type = ref2[m];
ref = ["participants", "matches"];
for (j = 0, len = ref.length; j < len; j++) {
challonge_type = ref[j];
challonge[challonge_type]._index = replaced_index(challonge_type);
}
challonge.matches._update = function(_data) {
......@@ -570,47 +587,202 @@
}
};
refresh_challonge_cache();
// challonge.participants._index({
// id: settings.modules.challonge.tournament_id,
// callback: (() ->
// challonge.matches._index({
// id: settings.modules.challonge.tournament_id,
// callback: (() ->
// return
// )
// })
// return
// )
// })
if (settings.modules.challonge.cache_ttl) {
setInterval(refresh_challonge_cache, settings.modules.challonge.cache_ttl);
}
}
if (settings.modules.tips.get) {
load_tips();
setInterval(function() {
var l, len1, room;
for (l = 0, len1 = ROOM_all.length; l < len1; l++) {
room = ROOM_all[l];
if (room && room.established) {
if (room.duel_stage === ygopro.constants.DUEL_STAGE.SIDING || room.duel_stage === ygopro.constants.DUEL_STAGE.BEGIN) {
ygopro.stoc_send_random_tip_to_room(room);
}
}
}
}, 30000);
}
if (settings.modules.dialogues.get) {
load_dialogues();
}
if (settings.modules.random_duel.post_match_scores) {
setInterval(function() {
var scores, scores_by_lose, scores_by_win, scores_pair;
scores_pair = _.pairs(ROOM_players_scores);
scores_by_lose = _.sortBy(scores_pair, function(score) {
return score[1].lose;
}).reverse(); // 败场由高到低
scores_by_win = _.sortBy(scores_by_lose, function(score) {
return score[1].win;
}).reverse(); // 然后胜场由低到高,再逆转,就是先排胜场再排败场
scores = _.first(scores_by_win, 10);
//log.info scores
request.post({
url: settings.modules.random_duel.post_match_scores,
form: {
accesskey: settings.modules.random_duel.post_match_accesskey,
rank: JSON.stringify(scores)
}
}, (error, response, body) => {
if (error) {
log.warn('RANDOM SCORE POST ERROR', error);
} else {
if (response.statusCode !== 204 && response.statusCode !== 200) {
log.warn('RANDOM SCORE POST FAIL', response.statusCode, response.statusMessage, body);
}
}
});
//else
// log.info 'RANDOM SCORE POST OK', response.statusCode, response.statusMessage
}, 60000);
}
if (settings.modules.random_duel.enabled) {
setInterval(async function() {
var l, len1, room, time_passed;
for (l = 0, len1 = ROOM_all.length; l < len1; l++) {
room = ROOM_all[l];
if (!(room && room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN && room.random_type && room.last_active_time && room.waiting_for_player && room.get_disconnected_count() === 0 && (!settings.modules.side_timeout || room.duel_stage !== ygopro.constants.DUEL_STAGE.SIDING) && !room.recovered)) {
continue;
}
time_passed = Math.floor((moment() - room.last_active_time) / 1000);
//log.info time_passed
if (time_passed >= settings.modules.random_duel.hang_timeout) {
room.last_active_time = moment();
await ROOM_ban_player(room.waiting_for_player.name, room.waiting_for_player.ip, "${random_ban_reason_AFK}");
room.scores[room.waiting_for_player.name_vpass] = -9;
//log.info room.waiting_for_player.name, room.scores[room.waiting_for_player.name_vpass]
ygopro.stoc_send_chat_to_room(room, `${room.waiting_for_player.name} \${kicked_by_system}`, ygopro.constants.COLORS.RED);
CLIENT_send_replays(room.waiting_for_player, room);
CLIENT_kick(room.waiting_for_player);
} else if (time_passed >= (settings.modules.random_duel.hang_timeout - 20) && !(time_passed % 10)) {
ygopro.stoc_send_chat_to_room(room, `${room.waiting_for_player.name} \${afk_warn_part1}${settings.modules.random_duel.hang_timeout - time_passed}\${afk_warn_part2}`, ygopro.constants.COLORS.RED);
ROOM_unwelcome(room, room.waiting_for_player, "${random_ban_reason_AFK}");
}
}
}, 1000);
}
if (settings.modules.mycard.enabled) {
setInterval(function() {
var l, len1, len2, m, player, room, time_passed, waited_time;
for (l = 0, len1 = ROOM_all.length; l < len1; l++) {
room = ROOM_all[l];
if (!(room && room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN && room.arena && room.last_active_time && room.waiting_for_player && room.get_disconnected_count() === 0 && (!settings.modules.side_timeout || room.duel_stage !== ygopro.constants.DUEL_STAGE.SIDING) && !room.recovered)) {
continue;
}
time_passed = Math.floor((moment() - room.last_active_time) / 1000);
//log.info time_passed
if (time_passed >= settings.modules.random_duel.hang_timeout) {
room.last_active_time = moment();
ygopro.stoc_send_chat_to_room(room, `${room.waiting_for_player.name} \${kicked_by_system}`, ygopro.constants.COLORS.RED);
room.scores[room.waiting_for_player.name_vpass] = -9;
//log.info room.waiting_for_player.name, room.scores[room.waiting_for_player.name_vpass]
CLIENT_send_replays(room.waiting_for_player, room);
CLIENT_kick(room.waiting_for_player);
} else if (time_passed >= (settings.modules.random_duel.hang_timeout - 20) && !(time_passed % 10)) {
ygopro.stoc_send_chat_to_room(room, `${room.waiting_for_player.name} \${afk_warn_part1}${settings.modules.random_duel.hang_timeout - time_passed}\${afk_warn_part2}`, ygopro.constants.COLORS.RED);
}
}
return;
if (true) { // settings.modules.arena_mode.punish_quit_before_match
for (m = 0, len2 = ROOM_all.length; m < len2; m++) {
room = ROOM_all[m];
if (!(room && room.arena && room.duel_stage === ygopro.constants.DUEL_STAGE.BEGIN && room.get_playing_player().length < 2)) {
continue;
}
player = room.get_playing_player()[0];
if (player && player.join_time && !player.arena_quit_free) {
waited_time = moment() - player.join_time;
if (waited_time >= 30000) {
ygopro.stoc_send_chat(player, "${arena_wait_timeout}", ygopro.constants.COLORS.BABYBLUE);
player.arena_quit_free = true;
} else if (waited_time >= 5000 && waited_time < 6000) {
ygopro.stoc_send_chat(player, "${arena_wait_hint}", ygopro.constants.COLORS.BABYBLUE);
}
}
}
}
}, 1000);
}
if (settings.modules.heartbeat_detection.enabled) {
setInterval(function() {
var l, len1, len2, m, player, ref1, room;
for (l = 0, len1 = ROOM_all.length; l < len1; l++) {
room = ROOM_all[l];
if (room && room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN && (room.hostinfo.time_limit === 0 || room.duel_stage !== ygopro.constants.DUEL_STAGE.DUELING) && !room.windbot) {
ref1 = room.get_playing_player();
for (m = 0, len2 = ref1.length; m < len2; m++) {
player = ref1[m];
if (player && (room.duel_stage !== ygopro.constants.DUEL_STAGE.SIDING || player.selected_preduel)) {
CLIENT_heartbeat_register(player, true);
}
}
}
}
}, settings.modules.heartbeat_detection.interval);
}
if (settings.modules.windbot.enabled && settings.modules.windbot.spawn) {
spawn_windbot();
}
setInterval(function() {
var current_time, l, len1, results, room;
current_time = moment();
results = [];
for (l = 0, len1 = ROOM_all.length; l < len1; l++) {
room = ROOM_all[l];
if (!(room && room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN && room.hostinfo.auto_death && !room.auto_death_triggered && current_time - moment(room.start_time) > 60000 * room.hostinfo.auto_death)) {
continue;
}
room.auto_death_triggered = true;
results.push(room.start_death());
}
return results;
}, 1000);
net.createServer(netRequestHandler).listen(settings.port, function() {
log.info("server started", settings.port);
});
if (settings.modules.stop) {
log.info("NOTE: server not open due to config, ", settings.modules.stop);
}
http_server = http.createServer(httpRequestListener);
http_server.listen(settings.modules.http.port);
if (settings.modules.http.ssl.enabled) {
https = require('https');
options = {
cert: (await fs.promises.readFile(settings.modules.http.ssl.cert)),
key: (await fs.promises.readFile(settings.modules.http.ssl.key))
};
https_server = https.createServer(options, httpRequestListener);
if (settings.modules.http.websocket_roomlist && roomlist) {
roomlist.init(https_server, ROOM_all);
}
https_server.listen(settings.modules.http.ssl.port);
}
mkdirList = ["./plugins", settings.modules.tournament_mode.deck_path, settings.modules.tournament_mode.replay_path, settings.modules.tournament_mode.log_save_path, settings.modules.deck_log.local];
for (l = 0, len1 = mkdirList.length; l < len1; l++) {
path = mkdirList[l];
await createDirectoryIfNotExists(path);
}
plugin_list = (await fs.promises.readdir("./plugins"));
results = [];
for (m = 0, len2 = plugin_list.length; m < len2; m++) {
plugin_filename = plugin_list[m];
plugin_path = process.cwd() + "/plugins/" + plugin_filename;
require(plugin_path);
results.push(log.info("Plugin loaded:", plugin_filename));
}
return results;
};
// 获取可用内存
memory_usage = global.memory_usage = 0;
get_memory_usage = get_memory_usage = function() {
var prc_free;
prc_free = exec("free");
prc_free.stdout.on('data', function(data) {
var actualFree, buffers, cached, free, line, lines, new_free, percentUsed, total;
lines = data.toString().split(/\n/g);
line = lines[0].split(/\s+/);
new_free = line[6] === 'available' ? true : false;
line = lines[1].split(/\s+/);
total = parseInt(line[1], 10);
free = parseInt(line[3], 10);
buffers = parseInt(line[5], 10);
if (new_free) {
actualFree = parseInt(line[6], 10);
} else {
cached = parseInt(line[6], 10);
actualFree = free + buffers + cached;
}
percentUsed = parseFloat(((1 - (actualFree / total)) * 100).toFixed(2));
get_memory_usage = global.get_memory_usage = function() {
var percentUsed;
percentUsed = os.freemem() * os.totalmem() * 100;
memory_usage = global.memory_usage = percentUsed;
});
};
get_memory_usage();
......@@ -629,20 +801,20 @@
// ban a user manually and permanently
ban_user = global.ban_user = async function(name) {
var ban, bans, len3, len4, len5, len6, n, o, p, player, playerType, q, ref3, ref4, room;
var ban, bans, j, l, len, len1, len2, len3, m, n, player, playerType, ref, ref1, room;
if (!settings.modules.mysql.enabled) {
throw "MySQL is not enabled";
}
bans = [dataManager.getBan(name, null)];
for (n = 0, len3 = ROOM_all.length; n < len3; n++) {
room = ROOM_all[n];
for (j = 0, len = ROOM_all.length; j < len; j++) {
room = ROOM_all[j];
if (room && room.established) {
ref3 = ["players", "watchers"];
for (o = 0, len4 = ref3.length; o < len4; o++) {
playerType = ref3[o];
ref4 = room[playerType];
for (p = 0, len5 = ref4.length; p < len5; p++) {
player = ref4[p];
ref = ["players", "watchers"];
for (l = 0, len1 = ref.length; l < len1; l++) {
playerType = ref[l];
ref1 = room[playerType];
for (m = 0, len2 = ref1.length; m < len2; m++) {
player = ref1[m];
if (!(player.name === name || bans.find(ban(() => {
return player.ip === ban.ip;
})))) {
......@@ -657,8 +829,8 @@
}
}
}
for (q = 0, len6 = bans.length; q < len6; q++) {
ban = bans[q];
for (n = 0, len3 = bans.length; n < len3; n++) {
ban = bans[n];
await dataManager.banPlayer(ban);
}
};
......@@ -726,56 +898,24 @@
ROOM_players_scores[name].combo = 0;
};
ROOM_player_get_score = global.ROOM_player_get_score = function(player) {
var name, score, total;
name = player.name_vpass;
score = ROOM_players_scores[name];
if (!score) {
return `${player.name} \${random_score_blank}`;
}
total = score.win + score.lose;
if (score.win < 2 && total < 3) {
return `${player.name} \${random_score_not_enough}`;
}
if (score.combo >= 2) {
return `\${random_score_part1}${player.name} \${random_score_part2} ${Math.ceil(score.win / total * 100)}\${random_score_part3} ${Math.ceil(score.flee / total * 100)}\${random_score_part4_combo}${score.combo}\${random_score_part5_combo}`;
} else {
//return player.name + " 的今日战绩:胜率" + Math.ceil(score.win/total*100) + "%,逃跑率" + Math.ceil(score.flee/total*100) + "%," + score.combo + "连胜中!"
return `\${random_score_part1}${player.name} \${random_score_part2} ${Math.ceil(score.win / total * 100)}\${random_score_part3} ${Math.ceil(score.flee / total * 100)}\${random_score_part4}`;
}
};
if (settings.modules.random_duel.post_match_scores) {
setInterval(function() {
var scores, scores_by_lose, scores_by_win, scores_pair;
scores_pair = _.pairs(ROOM_players_scores);
scores_by_lose = _.sortBy(scores_pair, function(score) {
return score[1].lose;
}).reverse(); // 败场由高到低
scores_by_win = _.sortBy(scores_by_lose, function(score) {
return score[1].win;
}).reverse(); // 然后胜场由低到高,再逆转,就是先排胜场再排败场
scores = _.first(scores_by_win, 10);
//log.info scores
request.post({
url: settings.modules.random_duel.post_match_scores,
form: {
accesskey: settings.modules.random_duel.post_match_accesskey,
rank: JSON.stringify(scores)
}
}, (error, response, body) => {
if (error) {
log.warn('RANDOM SCORE POST ERROR', error);
} else {
if (response.statusCode !== 204 && response.statusCode !== 200) {
log.warn('RANDOM SCORE POST FAIL', response.statusCode, response.statusMessage, body);
ROOM_player_get_score = global.ROOM_player_get_score = function(player) {
var name, score, total;
name = player.name_vpass;
score = ROOM_players_scores[name];
if (!score) {
return `${player.name} \${random_score_blank}`;
}
total = score.win + score.lose;
if (score.win < 2 && total < 3) {
return `${player.name} \${random_score_not_enough}`;
}
});
//else
// log.info 'RANDOM SCORE POST OK', response.statusCode, response.statusMessage
}, 60000);
if (score.combo >= 2) {
return `\${random_score_part1}${player.name} \${random_score_part2} ${Math.ceil(score.win / total * 100)}\${random_score_part3} ${Math.ceil(score.flee / total * 100)}\${random_score_part4_combo}${score.combo}\${random_score_part5_combo}`;
} else {
//return player.name + " 的今日战绩:胜率" + Math.ceil(score.win/total*100) + "%,逃跑率" + Math.ceil(score.flee/total*100) + "%," + score.combo + "连胜中!"
return `\${random_score_part1}${player.name} \${random_score_part2} ${Math.ceil(score.win / total * 100)}\${random_score_part3} ${Math.ceil(score.flee / total * 100)}\${random_score_part4}`;
}
};
ROOM_find_or_create_by_name = global.ROOM_find_or_create_by_name = async function(name, player_ip) {
var room, success, uname;
......@@ -956,13 +1096,13 @@
};
ROOM_unwelcome = global.ROOM_unwelcome = function(room, bad_player, reason) {
var len3, n, player, ref3;
var j, len, player, ref;
if (!room) {
return;
}
ref3 = room.players;
for (n = 0, len3 = ref3.length; n < len3; n++) {
player = ref3[n];
ref = room.players;
for (j = 0, len = ref.length; j < len; j++) {
player = ref[j];
if (player && player === bad_player) {
ygopro.stoc_send_chat(player, `\${unwelcome_warn_part1}${reason}\${unwelcome_warn_part2}`, ygopro.constants.COLORS.RED);
} else if (player && player.pos !== 7 && player !== bad_player) {
......@@ -1074,10 +1214,10 @@
};
CLIENT_import_data = global.CLIENT_import_data = function(client, old_client, room) {
var index, key, len3, len4, n, o, player, ref3;
ref3 = room.players;
for (index = n = 0, len3 = ref3.length; n < len3; index = ++n) {
player = ref3[index];
var index, j, key, l, len, len1, player, ref;
ref = room.players;
for (index = j = 0, len = ref.length; j < len; index = ++j) {
player = ref[index];
if (player === old_client) {
room.players[index] = client;
break;
......@@ -1096,8 +1236,8 @@
if (room.determine_firstgo === old_client) {
room.determine_firstgo = client;
}
for (o = 0, len4 = import_datas.length; o < len4; o++) {
key = import_datas[o];
for (l = 0, len1 = import_datas.length; l < len1; l++) {
key = import_datas[l];
client[key] = old_client[key];
}
old_client.had_new_reconnection = true;
......@@ -1136,11 +1276,11 @@
};
CLIENT_is_player = global.CLIENT_is_player = function(client, room) {
var is_player, len3, n, player, ref3;
var is_player, j, len, player, ref;
is_player = false;
ref3 = room.players;
for (n = 0, len3 = ref3.length; n < len3; n++) {
player = ref3[n];
ref = room.players;
for (j = 0, len = ref.length; j < len; j++) {
player = ref[j];
if (client === player) {
is_player = true;
break;
......@@ -1173,13 +1313,13 @@
};
CLIENT_get_kick_reconnect_target = global.CLIENT_get_kick_reconnect_target = function(client, deckbuf) {
var len3, len4, n, o, player, ref3, room;
for (n = 0, len3 = ROOM_all.length; n < len3; n++) {
room = ROOM_all[n];
var j, l, len, len1, player, ref, room;
for (j = 0, len = ROOM_all.length; j < len; j++) {
room = ROOM_all[j];
if (room && room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN && !room.windbot) {
ref3 = room.get_playing_player();
for (o = 0, len4 = ref3.length; o < len4; o++) {
player = ref3[o];
ref = room.get_playing_player();
for (l = 0, len1 = ref.length; l < len1; l++) {
player = ref[l];
if (!player.closed && 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 || _.isEqual(player.start_deckbuf, deckbuf))) {
return player;
}
......@@ -1200,7 +1340,7 @@
};
CLIENT_send_pre_reconnect_info = global.CLIENT_send_pre_reconnect_info = function(client, room, old_client) {
var len3, n, player, ref3, req_pos;
var j, len, player, ref, req_pos;
ygopro.stoc_send_chat(client, "${pre_reconnecting_to_room}", ygopro.constants.COLORS.BABYBLUE);
ygopro.stoc_send(client, 'JOIN_GAME', room.join_game_buffer);
req_pos = old_client.pos;
......@@ -1210,9 +1350,9 @@
ygopro.stoc_send(client, 'TYPE_CHANGE', {
type: req_pos
});
ref3 = room.players;
for (n = 0, len3 = ref3.length; n < len3; n++) {
player = ref3[n];
ref = room.players;
for (j = 0, len = ref.length; j < len; j++) {
player = ref[j];
ygopro.stoc_send(client, 'HS_PLAYER_ENTER', {
name: player.name,
pos: player.pos
......@@ -1329,10 +1469,6 @@
CLIENT_reconnect_unregister(client, true);
};
if (settings.modules.reconnect.enabled) {
disconnect_list = {}; // {old_client, old_server, room_id, timeout, deckbuf}
}
CLIENT_heartbeat_unregister = global.CLIENT_heartbeat_unregister = function(client) {
if (!settings.modules.heartbeat_detection.enabled || !client.heartbeat_timeout) {
return false;
......@@ -1376,15 +1512,15 @@
};
CLIENT_send_replays = global.CLIENT_send_replays = function(client, room) {
var buffer, i, len3, n, ref3;
var buffer, i, j, len, ref;
if (!(settings.modules.replay_delay && !(settings.modules.tournament_mode.enabled && settings.modules.tournament_mode.block_replay_to_player) && room.replays.length && room.hostinfo.mode === 1 && !client.replays_sent && !client.closed)) {
return false;
}
client.replays_sent = true;
i = 0;
ref3 = room.replays;
for (n = 0, len3 = ref3.length; n < len3; n++) {
buffer = ref3[n];
ref = room.replays;
for (j = 0, len = ref.length; j < len; j++) {
buffer = ref[j];
++i;
if (buffer) {
ygopro.stoc_send_chat(client, "${replay_hint_part1}" + i + "${replay_hint_part2}", ygopro.constants.COLORS.BABYBLUE);
......@@ -1395,12 +1531,12 @@
};
SOCKET_flush_data = global.SOCKET_flush_data = function(sk, datas) {
var buffer, len3, n;
var buffer, j, len;
if (!sk || sk.closed) {
return false;
}
for (n = 0, len3 = datas.length; n < len3; n++) {
buffer = datas[n];
for (j = 0, len = datas.length; j < len; j++) {
buffer = datas[j];
sk.write(buffer);
}
datas.splice(0, datas.length);
......@@ -1408,9 +1544,9 @@
};
getSeedTimet = global.getSeedTimet = function(count) {
var curTime, i, n, offset, ref3, ret;
var curTime, i, j, offset, ref, ret;
ret = [];
for (i = n = 0, ref3 = count; (0 <= ref3 ? n < ref3 : n > ref3); i = 0 <= ref3 ? ++n : --n) {
for (i = j = 0, ref = count; (0 <= ref ? j < ref : j > ref); i = 0 <= ref ? ++j : --j) {
curTime = null;
while (!curTime || _.any(ret, function(time) {
return time === curTime.unix();
......@@ -1606,17 +1742,17 @@
}
spawn(firstSeed) {
var i, n, o, param, seeds;
var i, j, l, param, seeds;
param = [0, this.hostinfo.lflist, this.hostinfo.rule, this.hostinfo.mode, this.hostinfo.duel_rule, (this.hostinfo.no_check_deck ? 'T' : 'F'), (this.hostinfo.no_shuffle_deck ? 'T' : 'F'), this.hostinfo.start_lp, this.hostinfo.start_hand, this.hostinfo.draw_count, this.hostinfo.time_limit, this.hostinfo.replay_mode];
if (firstSeed) {
param.push(firstSeed);
seeds = getSeedTimet(2);
for (i = n = 0; n < 2; i = ++n) {
for (i = j = 0; j < 2; i = ++j) {
param.push(seeds[i]);
}
} else {
seeds = getSeedTimet(3);
for (i = o = 0; o < 3; i = ++o) {
for (i = l = 0; l < 3; i = ++l) {
param.push(seeds[i]);
}
}
......@@ -1646,10 +1782,10 @@
this.port = parseInt(data);
_.each(this.players, (player) => {
player.server.connect(this.port, '127.0.0.1', function() {
var buffer, len3, p, ref3;
ref3 = player.pre_establish_buffers;
for (p = 0, len3 = ref3.length; p < len3; p++) {
buffer = ref3[p];
var buffer, len, m, ref;
ref = player.pre_establish_buffers;
for (m = 0, len = ref.length; m < len; m++) {
buffer = ref[m];
player.server.write(buffer);
}
player.established = true;
......@@ -1680,15 +1816,15 @@
}
delete() {
var end_time, formatted_replays, index, len3, log_rep_id, n, name, player_datas, recorder_buffer, ref3, ref4, repbuf, replay_id, room_name, score, score_array, score_form;
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;
if (this.deleted) {
return;
}
//log.info 'room-delete', this.name, ROOM_all.length
score_array = [];
ref3 = this.scores;
for (name in ref3) {
score = ref3[name];
ref = this.scores;
for (name in ref) {
score = ref[name];
score_form = {
name: name.split('$')[0],
score: score,
......@@ -1743,9 +1879,9 @@
score_array[1].score = -5;
}
formatted_replays = [];
ref4 = this.replays;
for (n = 0, len3 = ref4.length; n < len3; n++) {
repbuf = ref4[n];
ref1 = this.replays;
for (j = 0, len = ref1.length; j < len; j++) {
repbuf = ref1[j];
if (repbuf) {
formatted_replays.push(repbuf.toString("base64"));
}
......@@ -1833,6 +1969,7 @@
}
async initialize_recover() {
var e;
this.recover_duel_log = (await dataManager.getDuelLogFromId(this.recover_duel_log_id));
if (!this.recover_duel_log || !fs.existsSync(settings.modules.tournament_mode.replay_path + this.recover_duel_log.replayFileName)) {
this.terminate();
......@@ -1873,14 +2010,14 @@
}
get_disconnected_count() {
var found, len3, n, player, ref3;
var found, j, len, player, ref;
if (!settings.modules.reconnect.enabled) {
return 0;
}
found = 0;
ref3 = this.get_playing_player();
for (n = 0, len3 = ref3.length; n < len3; n++) {
player = ref3[n];
ref = this.get_playing_player();
for (j = 0, len = ref.length; j < len; j++) {
player = ref[j];
if (player.closed) {
found++;
}
......@@ -1930,20 +2067,20 @@
}
send_replays() {
var len3, len4, n, o, player, ref3, ref4;
var j, l, len, len1, player, ref, ref1;
if (!(settings.modules.replay_delay && this.replays.length && this.hostinfo.mode === 1)) {
return false;
}
ref3 = this.players;
for (n = 0, len3 = ref3.length; n < len3; n++) {
player = ref3[n];
ref = this.players;
for (j = 0, len = ref.length; j < len; j++) {
player = ref[j];
if (player) {
CLIENT_send_replays(player, this);
}
}
ref4 = this.watchers;
for (o = 0, len4 = ref4.length; o < len4; o++) {
player = ref4[o];
ref1 = this.watchers;
for (l = 0, len1 = ref1.length; l < len1; l++) {
player = ref1[l];
if (player) {
CLIENT_send_replays(player, this);
}
......@@ -1986,10 +2123,10 @@
roomlist.update(this);
}
client.server.connect(this.port, '127.0.0.1', function() {
var buffer, len3, n, ref3;
ref3 = client.pre_establish_buffers;
for (n = 0, len3 = ref3.length; n < len3; n++) {
buffer = ref3[n];
var buffer, j, len, ref;
ref = client.pre_establish_buffers;
for (j = 0, len = ref.length; j < len; j++) {
buffer = ref[j];
client.server.write(buffer);
}
client.established = true;
......@@ -1999,7 +2136,7 @@
}
disconnect(client, error) {
var index, left_name, len3, len4, n, o, player, ref3, ref4;
var index, j, l, left_name, len, len1, player, ref, ref1;
if (client.had_new_reconnection) {
return;
}
......@@ -2015,18 +2152,18 @@
//log.info(client.name, @duel_stage != ygopro.constants.DUEL_STAGE.BEGIN, @disconnector, @random_type, @players.length)
if (this.arena && this.duel_stage === ygopro.constants.DUEL_STAGE.BEGIN && this.disconnector !== 'server' && !this.arena_score_handled) {
if (settings.modules.arena_mode.punish_quit_before_match && this.players.length === 2 && !client.arena_quit_free) {
ref3 = this.players;
for (n = 0, len3 = ref3.length; n < len3; n++) {
player = ref3[n];
ref = this.players;
for (j = 0, len = ref.length; j < len; j++) {
player = ref[j];
if (player.pos !== 7) {
this.scores[player.name_vpass] = 0;
}
}
this.scores[client.name_vpass] = -9;
} else {
ref4 = this.players;
for (o = 0, len4 = ref4.length; o < len4; o++) {
player = ref4[o];
ref1 = this.players;
for (l = 0, len1 = ref1.length; l < len1; l++) {
player = ref1[l];
if (player.pos !== 7) {
this.scores[player.name_vpass] = -5;
}
......@@ -2140,6 +2277,7 @@
}
terminate() {
var e;
if (this.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN) {
this.scores[this.dueling_players[0].name_vpass] = 0;
this.scores[this.dueling_players[1].name_vpass] = 0;
......@@ -2157,23 +2295,23 @@
}
finish_recover(fail) {
var buffer, len3, n, player, ref3, results;
var buffer, j, len, player, ref, results;
if (fail) {
ygopro.stoc_send_chat_to_room(this, "${recover_fail}", ygopro.constants.COLORS.RED);
return this.terminate();
} else {
ygopro.stoc_send_chat_to_room(this, "${recover_success}", ygopro.constants.COLORS.BABYBLUE);
this.recovering = false;
ref3 = this.get_playing_player();
ref = this.get_playing_player();
results = [];
for (n = 0, len3 = ref3.length; n < len3; n++) {
player = ref3[n];
for (j = 0, len = ref.length; j < len; j++) {
player = ref[j];
results.push((function() {
var len4, o, ref4, results1;
ref4 = this.recover_buffers[player.pos];
var l, len1, ref1, results1;
ref1 = this.recover_buffers[player.pos];
results1 = [];
for (o = 0, len4 = ref4.length; o < len4; o++) {
buffer = ref4[o];
for (l = 0, len1 = ref1.length; l < len1; l++) {
buffer = ref1[l];
results1.push(ygopro.stoc_send(player, "GAME_MSG", buffer));
}
return results1;
......@@ -2206,7 +2344,7 @@
};
// 网络连接
net.createServer(function(client) {
netRequestHandler = function(client) {
var connect_count, server;
client.ip = client.remoteAddress;
client.is_local = client.ip && (client.ip.includes('127.0.0.1') || client.ip.includes(real_windbot_server_ip));
......@@ -2323,7 +2461,7 @@
}
if (settings.modules.cloud_replay.enabled) {
client.open_cloud_replay = async function(replay) {
var buffer, replay_buffer;
var buffer, e, replay_buffer;
if (!replay) {
ygopro.stoc_die(client, "${cloud_replay_no}");
return;
......@@ -2348,7 +2486,7 @@
// 客户端到服务端(ctos)协议分析
client.pre_establish_buffers = new Array();
client.on('data', async function(ctos_buffer) {
var bad_ip_count, buffer, ctos_filter, handle_data, len3, len4, len5, n, o, p, ref3, ref4, ref5, room;
var bad_ip_count, buffer, ctos_filter, handle_data, j, l, len, len1, len2, m, ref, ref1, ref2, room;
if (client.is_post_watcher) {
room = ROOM_all[client.rid];
if (room) {
......@@ -2369,9 +2507,9 @@
return;
}
}
ref3 = handle_data.datas;
for (n = 0, len3 = ref3.length; n < len3; n++) {
buffer = ref3[n];
ref = handle_data.datas;
for (j = 0, len = ref.length; j < len; j++) {
buffer = ref[j];
room.watcher.write(buffer);
}
}
......@@ -2398,15 +2536,15 @@
return;
}
if (client.established) {
ref4 = handle_data.datas;
for (o = 0, len4 = ref4.length; o < len4; o++) {
buffer = ref4[o];
ref1 = handle_data.datas;
for (l = 0, len1 = ref1.length; l < len1; l++) {
buffer = ref1[l];
client.server.write(buffer);
}
} else {
ref5 = handle_data.datas;
for (p = 0, len5 = ref5.length; p < len5; p++) {
buffer = ref5[p];
ref2 = handle_data.datas;
for (m = 0, len2 = ref2.length; m < len2; m++) {
buffer = ref2[m];
client.pre_establish_buffers.push(buffer);
}
}
......@@ -2414,7 +2552,7 @@
});
// 服务端到客户端(stoc)
server.on('data', async function(stoc_buffer) {
var buffer, handle_data, len3, n, ref3;
var buffer, handle_data, j, len, ref;
handle_data = (await ygopro.helper.handleBuffer(stoc_buffer, "STOC", null, {
client: server.client,
server: server
......@@ -2427,20 +2565,14 @@
}
}
if (server.client && !server.client.closed) {
ref3 = handle_data.datas;
for (n = 0, len3 = ref3.length; n < len3; n++) {
buffer = ref3[n];
ref = handle_data.datas;
for (j = 0, len = ref.length; j < len; j++) {
buffer = ref[j];
server.client.write(buffer);
}
}
});
}).listen(settings.port, function() {
log.info("server started", settings.port);
});
if (settings.modules.stop) {
log.info("NOTE: server not open due to config, ", settings.modules.stop);
}
};
deck_name_match = global.deck_name_match = function(deck_name, player_name) {
var parsed_deck_name;
......@@ -2454,7 +2586,7 @@
// 功能模块
// return true to cancel a synchronous message
ygopro.ctos_follow('PLAYER_INFO', true, async function(buffer, info, client, server, datas) {
var banMCRequest, geo, lang, name, name_full, struct, vpass;
var banMCRequest, e, geo, lang, name, name_full, struct, vpass;
// checkmate use username$password, but here don't
// so remove the password
name_full = info.name.split("$");
......@@ -2520,7 +2652,7 @@
});
ygopro.ctos_follow('JOIN_GAME', true, async function(buffer, info, client, server, datas) {
var available_logs, check_buffer_indentity, create_room_with_action, duelLog, exactBan, index, len3, len4, len5, len6, n, name, o, p, pre_room, q, recover_match, ref3, ref4, replay, replay_id, replays, room, struct;
var available_logs, check_buffer_indentity, create_room_with_action, duelLog, exactBan, index, j, l, len, len1, len2, len3, m, n, name, pre_room, recover_match, ref, ref1, replay, replay_id, replays, room, struct;
//log.info info
info.pass = info.pass.trim();
client.pass = info.pass;
......@@ -2534,7 +2666,7 @@
} else if (info.pass.toUpperCase() === "R" && settings.modules.cloud_replay.enabled) {
ygopro.stoc_send_chat(client, "${cloud_replay_hint}", ygopro.constants.COLORS.BABYBLUE);
replays = (await dataManager.getCloudReplaysFromKey(CLIENT_get_authorize_key(client)));
for (index = n = 0, len3 = replays.length; n < len3; index = ++n) {
for (index = j = 0, len = replays.length; j < len; index = ++j) {
replay = replays[index];
ygopro.stoc_send_chat(client, `<${index + 1}> ${replay.getDisplayString()}`, ygopro.constants.COLORS.BABYBLUE);
}
......@@ -2546,8 +2678,8 @@
} else if (info.pass.toUpperCase() === "RC" && settings.modules.tournament_mode.enable_recover) {
ygopro.stoc_send_chat(client, "${recover_replay_hint}", ygopro.constants.COLORS.BABYBLUE);
available_logs = (await dataManager.getDuelLogFromRecoverSearch(client.name_vpass));
for (o = 0, len4 = available_logs.length; o < len4; o++) {
duelLog = available_logs[o];
for (l = 0, len1 = available_logs.length; l < len1; l++) {
duelLog = available_logs[l];
ygopro.stoc_send_chat(client, duelLog.getViewString(), ygopro.constants.COLORS.BABYBLUE);
}
ygopro.stoc_send(client, 'ERROR_MSG', {
......@@ -2590,15 +2722,15 @@
return;
}
check_buffer_indentity = function(buf) {
var checksum, i, p, ref3;
var checksum, i, m, ref;
checksum = 0;
for (i = p = 0, ref3 = buf.length; (0 <= ref3 ? p < ref3 : p > ref3); i = 0 <= ref3 ? ++p : --p) {
for (i = m = 0, ref = buf.length; (0 <= ref ? m < ref : m > ref); i = 0 <= ref ? ++m : --m) {
checksum += buf.readUInt8(i);
}
return (checksum & 0xFF) === 0;
};
create_room_with_action = async function(buffer, decrypted_buffer, match_permit) {
var action, len5, len6, name, opt1, opt2, opt3, options, p, player, q, ref3, ref4, room, room_title, title;
var action, len2, len3, m, n, name, opt1, opt2, opt3, options, player, ref, ref1, room, room_title, title;
if (client.closed) {
return;
}
......@@ -2687,9 +2819,9 @@
}
room = (await ROOM_find_or_create_by_name('M#' + info.pass.slice(8)));
if (room) {
ref3 = room.get_playing_player();
for (p = 0, len5 = ref3.length; p < len5; p++) {
player = ref3[p];
ref = room.get_playing_player();
for (m = 0, len2 = ref.length; m < len2; m++) {
player = ref[m];
if (!(player && player.name === client.name)) {
continue;
}
......@@ -2728,9 +2860,9 @@
ygopro.stoc_send_chat_to_room(room, `${client.name} \${watch_join}`);
room.watchers.push(client);
ygopro.stoc_send_chat(client, "${watch_watching}", ygopro.constants.COLORS.BABYBLUE);
ref4 = room.watcher_buffers;
for (q = 0, len6 = ref4.length; q < len6; q++) {
buffer = ref4[q];
ref1 = room.watcher_buffers;
for (n = 0, len3 = ref1.length; n < len3; n++) {
buffer = ref1[n];
client.write(buffer);
}
} else {
......@@ -2777,7 +2909,7 @@
});
},
get_user: function(done) {
var decrypted_buffer, i, id, len5, p, ref3, secret;
var decrypted_buffer, i, id, len2, m, ref, secret;
if (client.closed) {
done();
return;
......@@ -2785,9 +2917,9 @@
if (id = users_cache[client.name]) {
secret = id % 65535 + 1;
decrypted_buffer = Buffer.allocUnsafe(6);
ref3 = [0, 2, 4];
for (p = 0, len5 = ref3.length; p < len5; p++) {
i = ref3[p];
ref = [0, 2, 4];
for (m = 0, len2 = ref.length; m < len2; m++) {
i = ref[m];
decrypted_buffer.writeUInt16LE(buffer.readUInt16LE(i) ^ secret, i);
}
if (check_buffer_indentity(decrypted_buffer)) {
......@@ -2809,14 +2941,14 @@
},
json: true
}, function(error, response, body) {
var len6, q, ref4;
var len3, n, ref1;
if (!error && body && body.user) {
users_cache[client.name] = body.user.id;
secret = body.user.id % 65535 + 1;
decrypted_buffer = Buffer.allocUnsafe(6);
ref4 = [0, 2, 4];
for (q = 0, len6 = ref4.length; q < len6; q++) {
i = ref4[q];
ref1 = [0, 2, 4];
for (n = 0, len3 = ref1.length; n < len3; n++) {
i = ref1[n];
decrypted_buffer.writeUInt16LE(buffer.readUInt16LE(i) ^ secret, i);
}
if (check_buffer_indentity(decrypted_buffer)) {
......@@ -2864,9 +2996,9 @@
ygopro.stoc_send_chat_to_room(room, `${client.name} \${watch_join}`);
room.watchers.push(client);
ygopro.stoc_send_chat(client, "${watch_watching}", ygopro.constants.COLORS.BABYBLUE);
ref3 = room.watcher_buffers;
for (p = 0, len5 = ref3.length; p < len5; p++) {
buffer = ref3[p];
ref = room.watcher_buffers;
for (m = 0, len2 = ref.length; m < len2; m++) {
buffer = ref[m];
client.write(buffer);
}
} else {
......@@ -2888,7 +3020,7 @@
});
}
}, async function(err, datas) {
var create_room_name, found, k, len6, len7, match, player, q, r, ref4, ref5, ref6, ref7, user;
var create_room_name, found, k, len3, len4, match, n, o, player, ref1, ref2, ref3, ref4, user;
if (client.closed) {
return;
}
......@@ -2898,9 +3030,9 @@
return;
}
found = false;
ref4 = datas.participant_data;
for (k in ref4) {
user = ref4[k];
ref1 = datas.participant_data;
for (k in ref1) {
user = ref1[k];
if (user.participant && user.participant.name && deck_name_match(user.participant.name, client.name)) {
found = user.participant;
break;
......@@ -2912,9 +3044,9 @@
}
client.challonge_info = found;
found = false;
ref5 = datas.match_data;
for (k in ref5) {
match = ref5[k];
ref2 = datas.match_data;
for (k in ref2) {
match = ref2[k];
if (match && match.match && !match.match.winnerId && match.match.state !== "complete" && match.match.player1Id && match.match.player2Id && (match.match.player1Id === client.challonge_info.id || match.match.player2Id === client.challonge_info.id)) {
found = match.match;
break;
......@@ -2949,9 +3081,9 @@
ygopro.stoc_send_chat_to_room(room, `${client.name} \${watch_join}`);
room.watchers.push(client);
ygopro.stoc_send_chat(client, "${watch_watching}", ygopro.constants.COLORS.BABYBLUE);
ref6 = room.watcher_buffers;
for (q = 0, len6 = ref6.length; q < len6; q++) {
buffer = ref6[q];
ref3 = room.watcher_buffers;
for (n = 0, len3 = ref3.length; n < len3; n++) {
buffer = ref3[n];
client.write(buffer);
}
} else {
......@@ -2960,9 +3092,9 @@
} else if (room.hostinfo.no_watch && room.players.length >= (room.hostinfo.mode === 2 ? 4 : 2)) {
ygopro.stoc_die(client, "${watch_denied_room}");
} else {
ref7 = room.get_playing_player();
for (r = 0, len7 = ref7.length; r < len7; r++) {
player = ref7[r];
ref4 = room.get_playing_player();
for (o = 0, len4 = ref4.length; o < len4; o++) {
player = ref4[o];
if (!(player && player !== client && player.challonge_info.id === client.challonge_info.id)) {
continue;
}
......@@ -3037,9 +3169,9 @@
ygopro.stoc_send_chat_to_room(room, `${client.name} \${watch_join}`);
room.watchers.push(client);
ygopro.stoc_send_chat(client, "${watch_watching}", ygopro.constants.COLORS.BABYBLUE);
ref4 = room.watcher_buffers;
for (q = 0, len6 = ref4.length; q < len6; q++) {
buffer = ref4[q];
ref1 = room.watcher_buffers;
for (n = 0, len3 = ref1.length; n < len3; n++) {
buffer = ref1[n];
client.write(buffer);
}
} else {
......@@ -3056,7 +3188,7 @@
});
ygopro.stoc_follow('JOIN_GAME', false, async function(buffer, info, client, server, datas) {
var len3, n, player, recorder, ref3, room, watcher;
var j, len, player, recorder, ref, room, watcher;
//欢迎信息
room = ROOM_all[client.rid];
if (!(room && !client.reconnecting)) {
......@@ -3094,9 +3226,9 @@
//client.score_shown = true
if (settings.modules.random_duel.record_match_scores && room.random_type === 'M') {
ygopro.stoc_send_chat_to_room(room, ROOM_player_get_score(client), ygopro.constants.COLORS.GREEN);
ref3 = room.players;
for (n = 0, len3 = ref3.length; n < len3; n++) {
player = ref3[n];
ref = room.players;
for (j = 0, len = ref.length; j < len; j++) {
player = ref[j];
if (player.pos !== 7 && player !== client) {
ygopro.stoc_send_chat(client, ROOM_player_get_score(player), ygopro.constants.COLORS.GREEN);
}
......@@ -3134,15 +3266,15 @@
ygopro.ctos_send(watcher, 'HS_TOOBSERVER');
});
watcher.on('data', function(data) {
var len4, o, ref4, w;
var l, len1, ref1, w;
room = ROOM_all[client.rid];
if (!room) {
return;
}
room.watcher_buffers.push(data);
ref4 = room.watchers;
for (o = 0, len4 = ref4.length; o < len4; o++) {
w = ref4[o];
ref1 = room.watchers;
for (l = 0, len1 = ref1.length; l < len1; l++) {
w = ref1[l];
if (w) { //a WTF fix
w.write(data);
}
......@@ -3155,31 +3287,12 @@
});
// 登场台词
load_dialogues = global.load_dialogues = async function(callback) {
request({
url: settings.modules.dialogues.get,
json: true
}, function(error, response, body) {
if (_.isString(body)) {
log.warn("dialogues bad json", body);
} else if (error || !body) {
log.warn('dialogues error', error, response);
} else {
setting_change(dialogues, "dialogues", body);
log.info("dialogues loaded", _.size(dialogues.dialogues));
}
if (callback) {
callback(error, body);
}
});
load_dialogues = global.load_dialogues = async function() {
return (await loadRemoteData(dialogues, "dialogues", settings.modules.dialogues.get));
};
if (settings.modules.dialogues.get) {
load_dialogues();
}
ygopro.stoc_follow('GAME_MSG', true, async function(buffer, info, client, server, datas) {
var card, chain, check, count, cpos, deck_found, found, hint_type, i, id, len3, len4, len5, len6, limbo_found, line, loc, max_loop, msg, n, o, oppo_pos, p, phase, player, playertype, pos, ppos, q, r, reason, ref3, ref4, ref5, ref6, ref7, ref8, room, trigger_location, val, win_pos;
var card, chain, check, count, cpos, deck_found, found, hint_type, i, id, j, l, len, len1, len2, len3, limbo_found, line, loc, m, max_loop, msg, n, o, oppo_pos, phase, player, playertype, pos, ppos, reason, ref, ref1, ref2, ref3, ref4, ref5, room, trigger_location, val, win_pos;
room = ROOM_all[client.rid];
if (!(room && !client.reconnecting)) {
return;
......@@ -3356,9 +3469,9 @@
room.turn = 0;
room.duel_stage = ygopro.constants.DUEL_STAGE.END;
if (settings.modules.heartbeat_detection.enabled) {
ref3 = room.players;
for (n = 0, len3 = ref3.length; n < len3; n++) {
player = ref3[n];
ref = room.players;
for (j = 0, len = ref.length; j < len; j++) {
player = ref[j];
player.heartbeat_protected = false;
}
delete room.long_resolve_card;
......@@ -3398,7 +3511,7 @@
if (room.dueling_players[pos].lp < 0) {
room.dueling_players[pos].lp = 0;
}
if ((0 < (ref4 = room.dueling_players[pos].lp) && ref4 <= 100)) {
if ((0 < (ref1 = room.dueling_players[pos].lp) && ref1 <= 100)) {
ygopro.stoc_send_chat_to_room(room, "${lp_low_opponent}", ygopro.constants.COLORS.PINK);
}
}
......@@ -3437,7 +3550,7 @@
if (room.dueling_players[pos].lp < 0) {
room.dueling_players[pos].lp = 0;
}
if ((0 < (ref5 = room.dueling_players[pos].lp) && ref5 <= 100)) {
if ((0 < (ref2 = room.dueling_players[pos].lp) && ref2 <= 100)) {
ygopro.stoc_send_chat_to_room(room, "${lp_low_self}", ygopro.constants.COLORS.PINK);
}
}
......@@ -3478,7 +3591,7 @@
max_loop = 3 + (count - 1) * 7;
deck_found = 0;
limbo_found = 0; // support custom cards which may be in location 0 in KoishiPro or EdoPro
for (i = o = 3, ref6 = max_loop; o <= ref6; i = o += 7) {
for (i = l = 3, ref3 = max_loop; l <= ref3; i = l += 7) {
loc = buffer.readInt8(i + 5);
if ((loc & 0x41) > 0) {
deck_found++;
......@@ -3500,8 +3613,8 @@
if (ygopro.constants.MSG[msg] === 'CHAINING') {
card = buffer.readUInt32LE(1);
found = false;
for (p = 0, len4 = long_resolve_cards.length; p < len4; p++) {
id = long_resolve_cards[p];
for (m = 0, len1 = long_resolve_cards.length; m < len1; m++) {
id = long_resolve_cards[m];
if (!(id === card)) {
continue;
}
......@@ -3526,9 +3639,9 @@
chain = buffer.readInt8(1);
// console.log(2,chain)
if (room.long_resolve_chain[chain]) {
ref7 = room.get_playing_player();
for (q = 0, len5 = ref7.length; q < len5; q++) {
player = ref7[q];
ref4 = room.get_playing_player();
for (n = 0, len2 = ref4.length; n < len2; n++) {
player = ref4[n];
player.heartbeat_protected = true;
}
}
......@@ -3548,9 +3661,9 @@
card = buffer.readUInt32LE(1);
trigger_location = buffer.readUInt8(6);
if (dialogues.dialogues[card] && (ygopro.constants.MSG[msg] !== 'CHAINING' || (trigger_location & 0x8) && client.ready_trap)) {
ref8 = _.lines(dialogues.dialogues[card][Math.floor(Math.random() * dialogues.dialogues[card].length)]);
for (r = 0, len6 = ref8.length; r < len6; r++) {
line = ref8[r];
ref5 = _.lines(dialogues.dialogues[card][Math.floor(Math.random() * dialogues.dialogues[card].length)]);
for (o = 0, len3 = ref5.length; o < len3; o++) {
line = ref5[o];
ygopro.stoc_send_chat(client, line, ygopro.constants.COLORS.PINK);
}
}
......@@ -3575,7 +3688,7 @@
//房间管理
ygopro.ctos_follow('HS_TOOBSERVER', true, async function(buffer, info, client, server, datas) {
var len3, n, player, ref3, room;
var j, len, player, ref, room;
room = ROOM_all[client.rid];
if (!room) {
return;
......@@ -3587,9 +3700,9 @@
if ((!room.arena && !settings.modules.challonge.enabled) || client.is_local) {
return false;
}
ref3 = room.players;
for (n = 0, len3 = ref3.length; n < len3; n++) {
player = ref3[n];
ref = room.players;
for (j = 0, len = ref.length; j < len; j++) {
player = ref[j];
if (player === client) {
ygopro.stoc_send_chat(client, "${cannot_to_observer}", ygopro.constants.COLORS.BABYBLUE);
return true;
......@@ -3599,14 +3712,14 @@
});
ygopro.ctos_follow('HS_KICK', true, async function(buffer, info, client, server, datas) {
var len3, n, player, ref3, room;
var j, len, player, ref, room;
room = ROOM_all[client.rid];
if (!room) {
return;
}
ref3 = room.players;
for (n = 0, len3 = ref3.length; n < len3; n++) {
player = ref3[n];
ref = room.players;
for (j = 0, len = ref.length; j < len; j++) {
player = ref[j];
if (player && player.pos === info.pos && player !== client) {
if (room.arena === "athletic" || settings.modules.challonge.enabled) {
ygopro.stoc_send_chat_to_room(room, `${client.name} \${kicked_by_system}`, ygopro.constants.COLORS.RED);
......@@ -3656,7 +3769,7 @@
});
ygopro.stoc_follow('HS_PLAYER_CHANGE', true, async function(buffer, info, client, server, datas) {
var is_ready, len3, n, p1, p2, player, pos, possibly_max_player, ref3, room;
var is_ready, j, len, p1, p2, player, pos, possibly_max_player, ref, room;
room = ROOM_all[client.rid];
if (!(room && client.pos === 0)) {
return;
......@@ -3665,9 +3778,9 @@
is_ready = (info.status & 0xf) === 9;
room.ready_player_count = 0;
room.ready_player_count_without_host = 0;
ref3 = room.players;
for (n = 0, len3 = ref3.length; n < len3; n++) {
player = ref3[n];
ref = room.players;
for (j = 0, len = ref.length; j < len; j++) {
player = ref[j];
if (player.pos === pos) {
player.is_ready = is_ready;
}
......@@ -3751,7 +3864,7 @@
});
ygopro.stoc_follow('DUEL_END', false, async function(buffer, info, client, server, datas) {
var len3, len4, n, o, player, ref3, ref4, room;
var j, l, len, len1, player, ref, ref1, room;
room = ROOM_all[client.rid];
if (!(room && settings.modules.replay_delay && room.hostinfo.mode === 1)) {
return;
......@@ -3760,16 +3873,16 @@
CLIENT_send_replays(client, room);
if (!room.replays_sent_to_watchers) {
room.replays_sent_to_watchers = true;
ref3 = room.players;
for (n = 0, len3 = ref3.length; n < len3; n++) {
player = ref3[n];
ref = room.players;
for (j = 0, len = ref.length; j < len; j++) {
player = ref[j];
if (player && player.pos > 3) {
CLIENT_send_replays(player, room);
}
}
ref4 = room.watchers;
for (o = 0, len4 = ref4.length; o < len4; o++) {
player = ref4[o];
ref1 = room.watchers;
for (l = 0, len1 = ref1.length; l < len1; l++) {
player = ref1[l];
if (player) {
CLIENT_send_replays(player, room);
}
......@@ -3778,7 +3891,7 @@
});
wait_room_start = async function(room, time) {
var len3, n, player, ref3;
var j, len, player, ref;
if (room && room.duel_stage === ygopro.constants.DUEL_STAGE.BEGIN && room.ready_player_count_without_host >= room.max_player - 1) {
time -= 1;
if (time) {
......@@ -3789,9 +3902,9 @@
wait_room_start(room, time);
}), 1000);
} else {
ref3 = room.players;
for (n = 0, len3 = ref3.length; n < len3; n++) {
player = ref3[n];
ref = room.players;
for (j = 0, len = ref.length; j < len; j++) {
player = ref[j];
if (player && player.is_host) {
await ROOM_ban_player(player.name, player.ip, "${random_ban_reason_zombie}");
ygopro.stoc_send_chat_to_room(room, `${player.name} \${kicked_by_system}`, ygopro.constants.COLORS.RED);
......@@ -3803,14 +3916,14 @@
};
wait_room_start_arena = async function(room) {
var display_name, len3, n, player, ref3;
var display_name, j, len, player, ref;
if (room && room.duel_stage === ygopro.constants.DUEL_STAGE.BEGIN && room.waiting_for_player) {
room.waiting_for_player_time = room.waiting_for_player_time - 1;
if (room.waiting_for_player_time > 0) {
if (!(room.waiting_for_player_time % 5)) {
ref3 = room.players;
for (n = 0, len3 = ref3.length; n < len3; n++) {
player = ref3[n];
ref = room.players;
for (j = 0, len = ref.length; j < len; j++) {
player = ref[j];
if (!(player)) {
continue;
}
......@@ -3842,42 +3955,36 @@
}
};
load_tips = global.load_tips = async function(callback) {
request({
url: settings.modules.tips.get,
json: true
}, function(error, response, body) {
loadRemoteData = global.loadRemoteData = async function(loadObject, name, url) {
var body, e;
try {
body = ((await axios.get(url, {
responseType: "json"
}))).data;
if (_.isString(body)) {
log.warn("tips bad json", body);
} else if (error || !body) {
log.warn('tips error', error, response);
} else {
setting_change(tips, "tips", body);
log.info("tips loaded", tips.tips.length);
log.warn(`${name} bad json`, body);
return false;
}
if (callback) {
callback(error, body);
if (!body) {
log.warn(`${name} empty`, body);
return false;
}
await setting_change(loadObject, name, body);
log.info(`${name} loaded`);
return true;
} catch (error1) {
e = error1;
log.warn(`${name} error`, e);
return false;
}
});
};
if (settings.modules.tips.get) {
load_tips();
setInterval(function() {
var len3, n, room;
for (n = 0, len3 = ROOM_all.length; n < len3; n++) {
room = ROOM_all[n];
if (room && room.established) {
if (room.duel_stage === ygopro.constants.DUEL_STAGE.SIDING || room.duel_stage === ygopro.constants.DUEL_STAGE.BEGIN) {
ygopro.stoc_send_random_tip_to_room(room);
}
}
}
}, 30000);
}
load_tips = global.load_tips = async function() {
return (await loadRemoteData(tips, "tips", settings.modules.tips.get));
};
ygopro.stoc_follow('DUEL_START', false, async function(buffer, info, client, server, datas) {
var deck_arena, deck_name, deck_text, len3, len4, n, o, player, ref3, ref4, room;
var deck_arena, deck_name, deck_text, j, l, len, len1, player, ref, ref1, room;
room = ROOM_all[client.rid];
if (!(room && !client.reconnecting)) {
return;
......@@ -3891,9 +3998,9 @@
}
//room.duels = []
room.dueling_players = [];
ref3 = room.get_playing_player();
for (n = 0, len3 = ref3.length; n < len3; n++) {
player = ref3[n];
ref = room.get_playing_player();
for (j = 0, len = ref.length; j < len; j++) {
player = ref[j];
room.dueling_players[player.pos] = player;
room.scores[player.name_vpass] = 0;
room.player_datas.push({
......@@ -3918,9 +4025,9 @@
}
}
if (settings.modules.hide_name && room.duel_count === 0) {
ref4 = room.get_playing_player();
for (o = 0, len4 = ref4.length; o < len4; o++) {
player = ref4[o];
ref1 = room.get_playing_player();
for (l = 0, len1 = ref1.length; l < len1; l++) {
player = ref1[l];
if (player !== client) {
ygopro.stoc_send(client, 'HS_PLAYER_ENTER', {
name: player.name,
......@@ -4029,7 +4136,7 @@
//else
//log.info 'BIG BROTHER OK', response.statusCode, roomname, body
ygopro.ctos_follow('CHAT', true, async function(buffer, info, client, server, datas) {
var cancel, ccolor, cip, cmd, cmsg, cname, color, cvalue, msg, name, oldmsg, ref3, room, struct, windbot;
var cancel, ccolor, cip, cmd, cmsg, cname, color, cvalue, msg, name, oldmsg, ref, room, struct, windbot;
room = ROOM_all[client.rid];
if (!room) {
return;
......@@ -4114,9 +4221,9 @@
if (cmsg = cmd[1]) {
if (cmsg.toLowerCase() === "help") {
ygopro.stoc_send_chat(client, "${show_color_list}", ygopro.constants.COLORS.BABYBLUE);
ref3 = ygopro.constants.COLORS;
for (cname in ref3) {
cvalue = ref3[cname];
ref = ygopro.constants.COLORS;
for (cname in ref) {
cvalue = ref[cname];
if (cvalue > 10) {
ygopro.stoc_send_chat(client, cname, cvalue);
}
......@@ -4249,7 +4356,7 @@
});
ygopro.ctos_follow('UPDATE_DECK', true, async function(buffer, info, client, server, datas) {
var buff_main, buff_side, card, current_deck, deck, deck_array, deck_main, deck_side, deck_text, deckbuf, decks, found_deck, i, len3, len4, line, n, o, oppo_pos, recover_player_data, recoveredDeck, room, struct, win_pos;
var 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;
if (settings.modules.reconnect.enabled && client.pre_reconnecting) {
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);
......@@ -4280,17 +4387,17 @@
return true;
}
buff_main = (function() {
var n, ref3, results;
var j, ref, results;
results = [];
for (i = n = 0, ref3 = info.mainc; (0 <= ref3 ? n < ref3 : n > ref3); i = 0 <= ref3 ? ++n : --n) {
for (i = j = 0, ref = info.mainc; (0 <= ref ? j < ref : j > ref); i = 0 <= ref ? ++j : --j) {
results.push(info.deckbuf[i]);
}
return results;
})();
buff_side = (function() {
var n, ref3, ref4, results;
var j, ref, ref1, results;
results = [];
for (i = n = ref3 = info.mainc, ref4 = info.mainc + info.sidec; (ref3 <= ref4 ? n < ref4 : n > ref4); i = ref3 <= ref4 ? ++n : --n) {
for (i = j = ref = info.mainc, ref1 = info.mainc + info.sidec; (ref <= ref1 ? j < ref1 : j > ref1); i = ref <= ref1 ? ++j : --j) {
results.push(info.deckbuf[i]);
}
return results;
......@@ -4352,8 +4459,8 @@
buffer = struct.buffer;
found_deck = false;
decks = fs.readdirSync(settings.modules.tournament_mode.deck_path);
for (n = 0, len3 = decks.length; n < len3; n++) {
deck = decks[n];
for (j = 0, len = decks.length; j < len; j++) {
deck = decks[j];
if (deck_name_match(deck, client.name)) {
found_deck = deck;
}
......@@ -4366,8 +4473,8 @@
deck_main = [];
deck_side = [];
current_deck = deck_main;
for (o = 0, len4 = deck_array.length; o < len4; o++) {
line = deck_array[o];
for (l = 0, len1 = deck_array.length; l < len1; l++) {
line = deck_array[l];
if (line.indexOf("!side") >= 0) {
current_deck = deck_side;
}
......@@ -4520,7 +4627,7 @@
});
ygopro.stoc_follow('CHAT', true, async function(buffer, info, client, server, datas) {
var len3, n, pid, player, ref3, room, tcolor, tplayer;
var j, len, pid, player, ref, room, tcolor, tplayer;
room = ROOM_all[client.rid];
pid = info.player;
if (!(room && pid < 4 && settings.modules.chat_color.enabled && (!settings.modules.hide_name || room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN))) {
......@@ -4538,9 +4645,9 @@
pid = 1 - pid;
}
}
ref3 = room.players;
for (n = 0, len3 = ref3.length; n < len3; n++) {
player = ref3[n];
ref = room.players;
for (j = 0, len = ref.length; j < len; j++) {
player = ref[j];
if (player && player.pos === pid) {
tplayer = player;
}
......@@ -4678,7 +4785,7 @@
});
ygopro.stoc_follow('REPLAY', true, async function(buffer, info, client, server, datas) {
var i, len3, len4, n, o, player, playerInfos, ref3, ref4, replay_filename, room;
var i, j, l, len, len1, player, playerInfos, ref, ref1, replay_filename, room;
room = ROOM_all[client.rid];
if (!room) {
return settings.modules.tournament_mode.enabled && settings.modules.tournament_mode.block_replay_to_player || settings.modules.replay_delay;
......@@ -4691,15 +4798,15 @@
if (client.pos === 0) {
replay_filename = moment().format("YYYY-MM-DD HH-mm-ss");
if (room.hostinfo.mode !== 2) {
ref3 = room.dueling_players;
for (i = n = 0, len3 = ref3.length; n < len3; i = ++n) {
player = ref3[i];
ref = room.dueling_players;
for (i = j = 0, len = ref.length; j < len; i = ++j) {
player = ref[i];
replay_filename = replay_filename + (i > 0 ? " VS " : " ") + player.name;
}
} else {
ref4 = room.dueling_players;
for (i = o = 0, len4 = ref4.length; o < len4; i = ++o) {
player = ref4[i];
ref1 = room.dueling_players;
for (i = l = 0, len1 = ref1.length; l < len1; i = ++l) {
player = ref1[i];
replay_filename = replay_filename + (i > 0 ? (i === 2 ? " VS " : " & ") : " ") + player.name;
}
}
......@@ -4738,108 +4845,6 @@
}
});
if (settings.modules.random_duel.enabled) {
setInterval(async function() {
var len3, n, room, time_passed;
for (n = 0, len3 = ROOM_all.length; n < len3; n++) {
room = ROOM_all[n];
if (!(room && room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN && room.random_type && room.last_active_time && room.waiting_for_player && room.get_disconnected_count() === 0 && (!settings.modules.side_timeout || room.duel_stage !== ygopro.constants.DUEL_STAGE.SIDING) && !room.recovered)) {
continue;
}
time_passed = Math.floor((moment() - room.last_active_time) / 1000);
//log.info time_passed
if (time_passed >= settings.modules.random_duel.hang_timeout) {
room.last_active_time = moment();
await ROOM_ban_player(room.waiting_for_player.name, room.waiting_for_player.ip, "${random_ban_reason_AFK}");
room.scores[room.waiting_for_player.name_vpass] = -9;
//log.info room.waiting_for_player.name, room.scores[room.waiting_for_player.name_vpass]
ygopro.stoc_send_chat_to_room(room, `${room.waiting_for_player.name} \${kicked_by_system}`, ygopro.constants.COLORS.RED);
CLIENT_send_replays(room.waiting_for_player, room);
CLIENT_kick(room.waiting_for_player);
} else if (time_passed >= (settings.modules.random_duel.hang_timeout - 20) && !(time_passed % 10)) {
ygopro.stoc_send_chat_to_room(room, `${room.waiting_for_player.name} \${afk_warn_part1}${settings.modules.random_duel.hang_timeout - time_passed}\${afk_warn_part2}`, ygopro.constants.COLORS.RED);
ROOM_unwelcome(room, room.waiting_for_player, "${random_ban_reason_AFK}");
}
}
}, 1000);
}
if (settings.modules.mycard.enabled) {
setInterval(function() {
var len3, len4, n, o, player, room, time_passed, waited_time;
for (n = 0, len3 = ROOM_all.length; n < len3; n++) {
room = ROOM_all[n];
if (!(room && room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN && room.arena && room.last_active_time && room.waiting_for_player && room.get_disconnected_count() === 0 && (!settings.modules.side_timeout || room.duel_stage !== ygopro.constants.DUEL_STAGE.SIDING) && !room.recovered)) {
continue;
}
time_passed = Math.floor((moment() - room.last_active_time) / 1000);
//log.info time_passed
if (time_passed >= settings.modules.random_duel.hang_timeout) {
room.last_active_time = moment();
ygopro.stoc_send_chat_to_room(room, `${room.waiting_for_player.name} \${kicked_by_system}`, ygopro.constants.COLORS.RED);
room.scores[room.waiting_for_player.name_vpass] = -9;
//log.info room.waiting_for_player.name, room.scores[room.waiting_for_player.name_vpass]
CLIENT_send_replays(room.waiting_for_player, room);
CLIENT_kick(room.waiting_for_player);
} else if (time_passed >= (settings.modules.random_duel.hang_timeout - 20) && !(time_passed % 10)) {
ygopro.stoc_send_chat_to_room(room, `${room.waiting_for_player.name} \${afk_warn_part1}${settings.modules.random_duel.hang_timeout - time_passed}\${afk_warn_part2}`, ygopro.constants.COLORS.RED);
}
}
return;
if (true) { // settings.modules.arena_mode.punish_quit_before_match
for (o = 0, len4 = ROOM_all.length; o < len4; o++) {
room = ROOM_all[o];
if (!(room && room.arena && room.duel_stage === ygopro.constants.DUEL_STAGE.BEGIN && room.get_playing_player().length < 2)) {
continue;
}
player = room.get_playing_player()[0];
if (player && player.join_time && !player.arena_quit_free) {
waited_time = moment() - player.join_time;
if (waited_time >= 30000) {
ygopro.stoc_send_chat(player, "${arena_wait_timeout}", ygopro.constants.COLORS.BABYBLUE);
player.arena_quit_free = true;
} else if (waited_time >= 5000 && waited_time < 6000) {
ygopro.stoc_send_chat(player, "${arena_wait_hint}", ygopro.constants.COLORS.BABYBLUE);
}
}
}
}
}, 1000);
}
if (settings.modules.heartbeat_detection.enabled) {
setInterval(function() {
var len3, len4, n, o, player, ref3, room;
for (n = 0, len3 = ROOM_all.length; n < len3; n++) {
room = ROOM_all[n];
if (room && room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN && (room.hostinfo.time_limit === 0 || room.duel_stage !== ygopro.constants.DUEL_STAGE.DUELING) && !room.windbot) {
ref3 = room.get_playing_player();
for (o = 0, len4 = ref3.length; o < len4; o++) {
player = ref3[o];
if (player && (room.duel_stage !== ygopro.constants.DUEL_STAGE.SIDING || player.selected_preduel)) {
CLIENT_heartbeat_register(player, true);
}
}
}
}
}, settings.modules.heartbeat_detection.interval);
}
setInterval(function() {
var current_time, len3, n, results, room;
current_time = moment();
results = [];
for (n = 0, len3 = ROOM_all.length; n < len3; n++) {
room = ROOM_all[n];
if (!(room && room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN && room.hostinfo.auto_death && !room.auto_death_triggered && current_time - moment(room.start_time) > 60000 * room.hostinfo.auto_death)) {
continue;
}
room.auto_death_triggered = true;
results.push(room.start_death());
}
return results;
}, 1000);
// spawn windbot
windbot_looplimit = 0;
......@@ -4883,22 +4888,18 @@
});
};
if (settings.modules.windbot.enabled && settings.modules.windbot.spawn) {
spawn_windbot();
}
global.rebooted = false;
//http
if (settings.modules.http) {
if (true) {
addCallback = function(callback, text) {
if (!callback) {
return text;
}
return callback + "( " + text + " );";
};
requestListener = async function(request, response) {
var archive_args, archive_name, archive_process, check, death_room_found, duellog, err, error, filename, getpath, len3, n, parseQueryString, pass_validated, ref3, roomsjson, u;
httpRequestListener = async function(request, response) {
var archive_args, archive_name, archive_process, check, death_room_found, duellog, e, err, error, filename, getpath, j, len, parseQueryString, pass_validated, ref, roomsjson, success, u;
parseQueryString = true;
u = url.parse(request.url, parseQueryString);
//pass_validated = u.query.pass == settings.modules.http.password
......@@ -4923,11 +4924,11 @@
roommode: room.hostinfo.mode,
needpass: (room.name.indexOf('$') !== -1).toString(),
users: _.sortBy((function() {
var len3, n, ref3, results;
ref3 = room.players;
var j, len, ref, results;
ref = room.players;
results = [];
for (n = 0, len3 = ref3.length; n < len3; n++) {
player = ref3[n];
for (j = 0, len = ref.length; j < len; j++) {
player = ref[j];
if (player.pos != null) {
results.push({
id: (-1).toString(),
......@@ -4974,9 +4975,9 @@
archive_name = moment().format('YYYY-MM-DD HH-mm-ss') + ".zip";
archive_args = ["a", "-mx0", "-y", archive_name];
check = false;
ref3 = (await dataManager.getAllReplayFilenames());
for (n = 0, len3 = ref3.length; n < len3; n++) {
filename = ref3[n];
ref = (await dataManager.getAllReplayFilenames());
for (j = 0, len = ref.length; j < len; j++) {
filename = ref[j];
check = true;
archive_args.push(filename);
}
......@@ -5128,28 +5129,26 @@
response.end(addCallback(u.query.callback, "['密码错误', 0]"));
return;
}
load_tips(function(err) {
success = (await load_tips());
response.writeHead(200);
if (err) {
return response.end(addCallback(u.query.callback, "['tip fail', '" + settings.modules.tips.get + "']"));
if (success) {
response.end(addCallback(u.query.callback, "['tip ok', '" + settings.modules.tips.get + "']"));
} else {
return response.end(addCallback(u.query.callback, "['tip ok', '" + settings.modules.tips.get + "']"));
response.end(addCallback(u.query.callback, "['tip fail', '" + settings.modules.tips.get + "']"));
}
});
} else if (u.query.loaddialogues) {
if (!(await auth.auth(u.query.username, u.query.pass, "change_settings", "change_dialogues"))) {
response.writeHead(200);
response.end(addCallback(u.query.callback, "['密码错误', 0]"));
return;
}
load_dialogues(function(err) {
success = (await load_tips());
response.writeHead(200);
if (err) {
return response.end(addCallback(u.query.callback, "['dialogues fail', '" + settings.modules.dialogues.get + "']"));
if (success) {
response.end(addCallback(u.query.callback, "['dialogue ok', '" + settings.modules.tips.get + "']"));
} else {
return response.end(addCallback(u.query.callback, "['dialogues ok', '" + settings.modules.dialogues.get + "']"));
response.end(addCallback(u.query.callback, "['dialogue fail', '" + settings.modules.tips.get + "']"));
}
});
} else if (u.query.ban) {
if (!(await auth.auth(u.query.username, u.query.pass, "ban_user", "ban_user"))) {
response.writeHead(200);
......@@ -5255,35 +5254,8 @@
response.end();
}
};
http_server = http.createServer(requestListener);
http_server.listen(settings.modules.http.port);
if (settings.modules.http.ssl.enabled) {
https = require('https');
options = {
cert: fs.readFileSync(settings.modules.http.ssl.cert),
key: fs.readFileSync(settings.modules.http.ssl.key)
};
https_server = https.createServer(options, requestListener);
if (settings.modules.http.websocket_roomlist && roomlist) {
roomlist.init(https_server, ROOM_all);
}
https_server.listen(settings.modules.http.ssl.port);
}
}
mkdirList = ["./plugins", settings.modules.tournament_mode.deck_path, settings.modules.tournament_mode.replay_path, settings.modules.tournament_mode.log_save_path, settings.modules.deck_log.local];
if (!fs.existsSync('./plugins')) {
fs.mkdirSync('./plugins');
}
plugin_list = fs.readdirSync("./plugins");
for (n = 0, len3 = plugin_list.length; n < len3; n++) {
plugin_filename = plugin_list[n];
plugin_path = process.cwd() + "/plugins/" + plugin_filename;
require(plugin_path);
log.info("Plugin loaded:", plugin_filename);
}
init();
}).call(this);
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