Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
S
srvpro
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nanahira
srvpro
Commits
04888860
Commit
04888860
authored
Nov 15, 2020
by
nanahira
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
rework server init
parent
de15fb02
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
1387 additions
and
1426 deletions
+1387
-1426
ygopro-auth.coffee
ygopro-auth.coffee
+2
-2
ygopro-auth.js
ygopro-auth.js
+2
-2
ygopro-server.coffee
ygopro-server.coffee
+502
-513
ygopro-server.js
ygopro-server.js
+881
-909
No files found.
ygopro-auth.coffee
View file @
04888860
...
...
@@ -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
...
...
ygopro-auth.js
View file @
04888860
...
...
@@ -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
"
);
...
...
ygopro-server.coffee
View file @
04888860
...
...
@@ -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
)
->
net
RequestHandler
=
(
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
)
->
load
RemoteData
=
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
+
" );"
r
equestListener
=
(
request
,
response
)
->
httpR
equestListener
=
(
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
.
dialogue
s
.
get
+
"']"
))
if
success
response
.
end
(
addCallback
(
u
.
query
.
callback
,
"['dialogue ok', '"
+
settings
.
modules
.
tip
s
.
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
()
ygopro-server.js
View file @
04888860
// 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
,
windbot
s
,
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_proces
s
,
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
\d
ABCDEF
]
+
)
/
)[
1
]
,
'
16
'
);
setting_change
(
settings
,
"
version
"
,
cppversion
);
cppversion
=
parseInt
((
await
fs
.
promises
.
readFile
(
'
ygopro/gframe/game.cpp
'
,
'
utf8
'
).
match
(
/PRO_VERSION =
([
x
\d
ABCDEF
]
+
)
/
)[
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
)
{
ref
3
=
[
"
players
"
,
"
watchers
"
];
for
(
o
=
0
,
len4
=
ref3
.
length
;
o
<
len4
;
o
++
)
{
playerType
=
ref
3
[
o
];
ref
4
=
room
[
playerType
];
for
(
p
=
0
,
len5
=
ref4
.
length
;
p
<
len5
;
p
++
)
{
player
=
ref
4
[
p
];
ref
=
[
"
players
"
,
"
watchers
"
];
for
(
l
=
0
,
len1
=
ref
.
length
;
l
<
len1
;
l
++
)
{
playerType
=
ref
[
l
];
ref
1
=
room
[
playerType
];
for
(
m
=
0
,
len2
=
ref1
.
length
;
m
<
len2
;
m
++
)
{
player
=
ref
1
[
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
;
}
ref
3
=
room
.
players
;
for
(
n
=
0
,
len3
=
ref3
.
length
;
n
<
len3
;
n
++
)
{
player
=
ref
3
[
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
;
ref
3
=
room
.
players
;
for
(
index
=
n
=
0
,
len3
=
ref3
.
length
;
n
<
len3
;
index
=
++
n
)
{
player
=
ref
3
[
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
;
ref
3
=
room
.
players
;
for
(
n
=
0
,
len3
=
ref3
.
length
;
n
<
len3
;
n
++
)
{
player
=
ref
3
[
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
)
{
ref
3
=
room
.
get_playing_player
();
for
(
o
=
0
,
len4
=
ref3
.
length
;
o
<
len4
;
o
++
)
{
player
=
ref
3
[
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
});
ref
3
=
room
.
players
;
for
(
n
=
0
,
len3
=
ref3
.
length
;
n
<
len3
;
n
++
)
{
player
=
ref
3
[
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
;
ref
3
=
room
.
replays
;
for
(
n
=
0
,
len3
=
ref3
.
length
;
n
<
len3
;
n
++
)
{
buffer
=
ref
3
[
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
,
le
n
;
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
,
len
3
,
p
,
ref3
;
ref
3
=
player
.
pre_establish_buffers
;
for
(
p
=
0
,
len3
=
ref3
.
length
;
p
<
len3
;
p
++
)
{
buffer
=
ref
3
[
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
=
[];
ref
3
=
this
.
scores
;
for
(
name
in
ref
3
)
{
score
=
ref
3
[
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
=
[];
ref
4
=
this
.
replays
;
for
(
n
=
0
,
len3
=
ref4
.
length
;
n
<
len3
;
n
++
)
{
repbuf
=
ref
4
[
n
];
ref
1
=
this
.
replays
;
for
(
j
=
0
,
len
=
ref1
.
length
;
j
<
len
;
j
++
)
{
repbuf
=
ref
1
[
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
;
ref
3
=
this
.
get_playing_player
();
for
(
n
=
0
,
len3
=
ref3
.
length
;
n
<
len3
;
n
++
)
{
player
=
ref
3
[
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
;
}
ref
3
=
this
.
players
;
for
(
n
=
0
,
len3
=
ref3
.
length
;
n
<
len3
;
n
++
)
{
player
=
ref
3
[
n
];
ref
=
this
.
players
;
for
(
j
=
0
,
len
=
ref
.
length
;
j
<
len
;
j
++
)
{
player
=
ref
[
j
];
if
(
player
)
{
CLIENT_send_replays
(
player
,
this
);
}
}
ref
4
=
this
.
watchers
;
for
(
o
=
0
,
len4
=
ref4
.
length
;
o
<
len4
;
o
++
)
{
player
=
ref
4
[
o
];
ref
1
=
this
.
watchers
;
for
(
l
=
0
,
len1
=
ref1
.
length
;
l
<
len1
;
l
++
)
{
player
=
ref
1
[
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
;
ref
3
=
client
.
pre_establish_buffers
;
for
(
n
=
0
,
len3
=
ref3
.
length
;
n
<
len3
;
n
++
)
{
buffer
=
ref
3
[
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
)
{
ref
3
=
this
.
players
;
for
(
n
=
0
,
len3
=
ref3
.
length
;
n
<
len3
;
n
++
)
{
player
=
ref
3
[
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
{
ref
4
=
this
.
players
;
for
(
o
=
0
,
len4
=
ref4
.
length
;
o
<
len4
;
o
++
)
{
player
=
ref
4
[
o
];
ref
1
=
this
.
players
;
for
(
l
=
0
,
len1
=
ref1
.
length
;
l
<
len1
;
l
++
)
{
player
=
ref
1
[
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
;
ref
3
=
this
.
get_playing_player
();
ref
=
this
.
get_playing_player
();
results
=
[];
for
(
n
=
0
,
len3
=
ref3
.
length
;
n
<
len3
;
n
++
)
{
player
=
ref
3
[
n
];
for
(
j
=
0
,
len
=
ref
.
length
;
j
<
len
;
j
++
)
{
player
=
ref
[
j
];
results
.
push
((
function
()
{
var
l
en4
,
o
,
ref4
,
results1
;
ref
4
=
this
.
recover_buffers
[
player
.
pos
];
var
l
,
len1
,
ref1
,
results1
;
ref
1
=
this
.
recover_buffers
[
player
.
pos
];
results1
=
[];
for
(
o
=
0
,
len4
=
ref4
.
length
;
o
<
len4
;
o
++
)
{
buffer
=
ref
4
[
o
];
for
(
l
=
0
,
len1
=
ref1
.
length
;
l
<
len1
;
l
++
)
{
buffer
=
ref
1
[
l
];
results1
.
push
(
ygopro
.
stoc_send
(
player
,
"
GAME_MSG
"
,
buffer
));
}
return
results1
;
...
...
@@ -2206,7 +2344,7 @@
};
// 网络连接
net
.
createServer
(
function
(
client
)
{
net
RequestHandler
=
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
;
}
}
ref
3
=
handle_data
.
datas
;
for
(
n
=
0
,
len3
=
ref3
.
length
;
n
<
len3
;
n
++
)
{
buffer
=
ref
3
[
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
)
{
ref
4
=
handle_data
.
datas
;
for
(
o
=
0
,
len4
=
ref4
.
length
;
o
<
len4
;
o
++
)
{
buffer
=
ref
4
[
o
];
ref
1
=
handle_data
.
datas
;
for
(
l
=
0
,
len1
=
ref1
.
length
;
l
<
len1
;
l
++
)
{
buffer
=
ref
1
[
l
];
client
.
server
.
write
(
buffer
);
}
}
else
{
ref
5
=
handle_data
.
datas
;
for
(
p
=
0
,
len5
=
ref5
.
length
;
p
<
len5
;
p
++
)
{
buffer
=
ref
5
[
p
];
ref
2
=
handle_data
.
datas
;
for
(
m
=
0
,
len2
=
ref2
.
length
;
m
<
len2
;
m
++
)
{
buffer
=
ref
2
[
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
)
{
ref
3
=
handle_data
.
datas
;
for
(
n
=
0
,
len3
=
ref3
.
length
;
n
<
len3
;
n
++
)
{
buffer
=
ref
3
[
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
,
len
5
,
len6
,
name
,
opt1
,
opt2
,
opt3
,
options
,
p
,
player
,
q
,
ref3
,
ref4
,
room
,
room_title
,
title
;
var
action
,
len
2
,
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
)
{
ref
3
=
room
.
get_playing_player
();
for
(
p
=
0
,
len5
=
ref3
.
length
;
p
<
len5
;
p
++
)
{
player
=
ref
3
[
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
);
ref
4
=
room
.
watcher_buffers
;
for
(
q
=
0
,
len6
=
ref4
.
length
;
q
<
len6
;
q
++
)
{
buffer
=
ref
4
[
q
];
ref
1
=
room
.
watcher_buffers
;
for
(
n
=
0
,
len3
=
ref1
.
length
;
n
<
len3
;
n
++
)
{
buffer
=
ref
1
[
n
];
client
.
write
(
buffer
);
}
}
else
{
...
...
@@ -2777,7 +2909,7 @@
});
},
get_user
:
function
(
done
)
{
var
decrypted_buffer
,
i
,
id
,
len
5
,
p
,
ref3
,
secret
;
var
decrypted_buffer
,
i
,
id
,
len
2
,
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
);
ref
3
=
[
0
,
2
,
4
];
for
(
p
=
0
,
len5
=
ref3
.
length
;
p
<
len5
;
p
++
)
{
i
=
ref
3
[
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
len
6
,
q
,
ref4
;
var
len
3
,
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
);
ref
4
=
[
0
,
2
,
4
];
for
(
q
=
0
,
len6
=
ref4
.
length
;
q
<
len6
;
q
++
)
{
i
=
ref
4
[
q
];
ref
1
=
[
0
,
2
,
4
];
for
(
n
=
0
,
len3
=
ref1
.
length
;
n
<
len3
;
n
++
)
{
i
=
ref
1
[
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
);
ref
3
=
room
.
watcher_buffers
;
for
(
p
=
0
,
len5
=
ref3
.
length
;
p
<
len5
;
p
++
)
{
buffer
=
ref
3
[
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
,
len
6
,
len7
,
match
,
player
,
q
,
r
,
ref4
,
ref5
,
ref6
,
ref7
,
user
;
var
create_room_name
,
found
,
k
,
len
3
,
len4
,
match
,
n
,
o
,
player
,
ref1
,
ref2
,
ref3
,
ref4
,
user
;
if
(
client
.
closed
)
{
return
;
}
...
...
@@ -2898,9 +3030,9 @@
return
;
}
found
=
false
;
ref
4
=
datas
.
participant_data
;
for
(
k
in
ref
4
)
{
user
=
ref
4
[
k
];
ref
1
=
datas
.
participant_data
;
for
(
k
in
ref
1
)
{
user
=
ref
1
[
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
;
ref
5
=
datas
.
match_data
;
for
(
k
in
ref
5
)
{
match
=
ref
5
[
k
];
ref
2
=
datas
.
match_data
;
for
(
k
in
ref
2
)
{
match
=
ref
2
[
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
);
ref
6
=
room
.
watcher_buffers
;
for
(
q
=
0
,
len6
=
ref6
.
length
;
q
<
len6
;
q
++
)
{
buffer
=
ref
6
[
q
];
ref
3
=
room
.
watcher_buffers
;
for
(
n
=
0
,
len3
=
ref3
.
length
;
n
<
len3
;
n
++
)
{
buffer
=
ref
3
[
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
{
ref
7
=
room
.
get_playing_player
();
for
(
r
=
0
,
len7
=
ref7
.
length
;
r
<
len7
;
r
++
)
{
player
=
ref
7
[
r
];
ref
4
=
room
.
get_playing_player
();
for
(
o
=
0
,
len4
=
ref4
.
length
;
o
<
len4
;
o
++
)
{
player
=
ref
4
[
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
);
ref
4
=
room
.
watcher_buffers
;
for
(
q
=
0
,
len6
=
ref4
.
length
;
q
<
len6
;
q
++
)
{
buffer
=
ref
4
[
q
];
ref
1
=
room
.
watcher_buffers
;
for
(
n
=
0
,
len3
=
ref1
.
length
;
n
<
len3
;
n
++
)
{
buffer
=
ref
1
[
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
);
ref
3
=
room
.
players
;
for
(
n
=
0
,
len3
=
ref3
.
length
;
n
<
len3
;
n
++
)
{
player
=
ref
3
[
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
l
en4
,
o
,
ref4
,
w
;
var
l
,
len1
,
ref1
,
w
;
room
=
ROOM_all
[
client
.
rid
];
if
(
!
room
)
{
return
;
}
room
.
watcher_buffers
.
push
(
data
);
ref
4
=
room
.
watchers
;
for
(
o
=
0
,
len4
=
ref4
.
length
;
o
<
len4
;
o
++
)
{
w
=
ref
4
[
o
];
ref
1
=
room
.
watchers
;
for
(
l
=
0
,
len1
=
ref1
.
length
;
l
<
len1
;
l
++
)
{
w
=
ref
1
[
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
)
{
ref
3
=
room
.
players
;
for
(
n
=
0
,
len3
=
ref3
.
length
;
n
<
len3
;
n
++
)
{
player
=
ref
3
[
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
<
(
ref
4
=
room
.
dueling_players
[
pos
].
lp
)
&&
ref4
<=
100
))
{
if
((
0
<
(
ref
1
=
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
<
(
ref
5
=
room
.
dueling_players
[
pos
].
lp
)
&&
ref5
<=
100
))
{
if
((
0
<
(
ref
2
=
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
])
{
ref
7
=
room
.
get_playing_player
();
for
(
q
=
0
,
len5
=
ref7
.
length
;
q
<
len5
;
q
++
)
{
player
=
ref
7
[
q
];
ref
4
=
room
.
get_playing_player
();
for
(
n
=
0
,
len2
=
ref4
.
length
;
n
<
len2
;
n
++
)
{
player
=
ref
4
[
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
))
{
ref
8
=
_
.
lines
(
dialogues
.
dialogues
[
card
][
Math
.
floor
(
Math
.
random
()
*
dialogues
.
dialogues
[
card
].
length
)]);
for
(
r
=
0
,
len6
=
ref8
.
length
;
r
<
len6
;
r
++
)
{
line
=
ref
8
[
r
];
ref
5
=
_
.
lines
(
dialogues
.
dialogues
[
card
][
Math
.
floor
(
Math
.
random
()
*
dialogues
.
dialogues
[
card
].
length
)]);
for
(
o
=
0
,
len3
=
ref5
.
length
;
o
<
len3
;
o
++
)
{
line
=
ref
5
[
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
;
}
ref
3
=
room
.
players
;
for
(
n
=
0
,
len3
=
ref3
.
length
;
n
<
len3
;
n
++
)
{
player
=
ref
3
[
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
;
}
ref
3
=
room
.
players
;
for
(
n
=
0
,
len3
=
ref3
.
length
;
n
<
len3
;
n
++
)
{
player
=
ref
3
[
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
;
ref
3
=
room
.
players
;
for
(
n
=
0
,
len3
=
ref3
.
length
;
n
<
len3
;
n
++
)
{
player
=
ref
3
[
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
;
ref
3
=
room
.
players
;
for
(
n
=
0
,
len3
=
ref3
.
length
;
n
<
len3
;
n
++
)
{
player
=
ref
3
[
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
);
}
}
ref
4
=
room
.
watchers
;
for
(
o
=
0
,
len4
=
ref4
.
length
;
o
<
len4
;
o
++
)
{
player
=
ref
4
[
o
];
ref
1
=
room
.
watchers
;
for
(
l
=
0
,
len1
=
ref1
.
length
;
l
<
len1
;
l
++
)
{
player
=
ref
1
[
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
{
ref
3
=
room
.
players
;
for
(
n
=
0
,
len3
=
ref3
.
length
;
n
<
len3
;
n
++
)
{
player
=
ref
3
[
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
))
{
ref
3
=
room
.
players
;
for
(
n
=
0
,
len3
=
ref3
.
length
;
n
<
len3
;
n
++
)
{
player
=
ref
3
[
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
=
[];
ref
3
=
room
.
get_playing_player
();
for
(
n
=
0
,
len3
=
ref3
.
length
;
n
<
len3
;
n
++
)
{
player
=
ref
3
[
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
)
{
ref
4
=
room
.
get_playing_player
();
for
(
o
=
0
,
len4
=
ref4
.
length
;
o
<
len4
;
o
++
)
{
player
=
ref
4
[
o
];
ref
1
=
room
.
get_playing_player
();
for
(
l
=
0
,
len1
=
ref1
.
length
;
l
<
len1
;
l
++
)
{
player
=
ref
1
[
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
,
ref
3
,
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
);
ref
3
=
ygopro
.
constants
.
COLORS
;
for
(
cname
in
ref
3
)
{
cvalue
=
ref
3
[
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
;
}
}
ref
3
=
room
.
players
;
for
(
n
=
0
,
len3
=
ref3
.
length
;
n
<
len3
;
n
++
)
{
player
=
ref
3
[
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
)
{
ref
3
=
room
.
dueling_players
;
for
(
i
=
n
=
0
,
len3
=
ref3
.
length
;
n
<
len3
;
i
=
++
n
)
{
player
=
ref
3
[
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
{
ref
4
=
room
.
dueling_players
;
for
(
i
=
o
=
0
,
len4
=
ref4
.
length
;
o
<
len4
;
i
=
++
o
)
{
player
=
ref
4
[
i
];
ref
1
=
room
.
dueling_players
;
for
(
i
=
l
=
0
,
len1
=
ref1
.
length
;
l
<
len1
;
i
=
++
l
)
{
player
=
ref
1
[
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
+
"
);
"
;
};
r
equestListener
=
async
function
(
request
,
response
)
{
var
archive_args
,
archive_name
,
archive_process
,
check
,
death_room_found
,
duellog
,
e
rr
,
error
,
filename
,
getpath
,
len3
,
n
,
parseQueryString
,
pass_validated
,
ref3
,
roomsjson
,
u
;
httpR
equestListener
=
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
;
ref
3
=
room
.
players
;
var
j
,
len
,
ref
,
results
;
ref
=
room
.
players
;
results
=
[];
for
(
n
=
0
,
len3
=
ref3
.
length
;
n
<
len3
;
n
++
)
{
player
=
ref
3
[
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
;
ref
3
=
(
await
dataManager
.
getAllReplayFilenames
());
for
(
n
=
0
,
len3
=
ref3
.
length
;
n
<
len3
;
n
++
)
{
filename
=
ref
3
[
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
.
dialogue
s
.
get
+
"
']
"
));
if
(
success
)
{
response
.
end
(
addCallback
(
u
.
query
.
callback
,
"
['dialogue ok', '
"
+
settings
.
modules
.
tip
s
.
get
+
"
']
"
));
}
else
{
return
response
.
end
(
addCallback
(
u
.
query
.
callback
,
"
['dialogues ok', '
"
+
settings
.
modules
.
dialogue
s
.
get
+
"
']
"
));
response
.
end
(
addCallback
(
u
.
query
.
callback
,
"
['dialogue fail', '
"
+
settings
.
modules
.
tip
s
.
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
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment