Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
S
srvpro2
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
srvpro2
Commits
2d537ea0
Commit
2d537ea0
authored
Feb 14, 2026
by
nanahira
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fixup comments
parent
58d57563
Pipeline
#43216
failed with stages
in 72 minutes and 32 seconds
Changes
7
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
88 additions
and
11 deletions
+88
-11
README.md
README.md
+11
-3
config.example.yaml
config.example.yaml
+1
-1
src/client/ip-resolver.ts
src/client/ip-resolver.ts
+3
-3
src/config.ts
src/config.ts
+33
-1
src/feats/reconnect.ts
src/feats/reconnect.ts
+3
-2
src/room/room.ts
src/room/room.ts
+2
-1
src/utility/parse-config-boolean.ts
src/utility/parse-config-boolean.ts
+35
-0
No files found.
README.md
View file @
2d537ea0
...
@@ -97,14 +97,22 @@ npm start
...
@@ -97,14 +97,22 @@ npm start
## 🔧 Configuration
## 🔧 Configuration
Key configuration options (see
`config.example.yaml`
for full list):
Configuration meaning source of truth:
-
`src/config.ts`
is the canonical place for all config keys and their meanings.
-
Use the comments in
`src/config.ts`
to understand what each field does.
-
`config.example.yaml`
is generated from
`src/config.ts`
defaults for quick editing.
-
All config values are loaded as strings; follow each field's format note in
`src/config.ts`
.
-
Format examples used in
`src/config.ts`
: comma-separated lists, integer strings, and explicit time units (
`ms`
or
`s`
).
Commonly used options:
-
`WELCOME`
: Welcome message shown to players joining rooms
-
`WELCOME`
: Welcome message shown to players joining rooms
-
`RECONNECT_TIMEOUT`
: Disconnect timeout before reconnect expires (default: 180000ms)
-
`RECONNECT_TIMEOUT`
: Disconnect timeout before reconnect expires (default: 180000ms)
-
`
NO_RECONNECT`
: Set to disable reconnect feature
-
`
ENABLE_RECONNECT`
: Reconnect feature switch (default enabled)
-
Standard YGOPro settings (port, timeout, banlist, etc.)
-
Standard YGOPro settings (port, timeout, banlist, etc.)
After modifying
`src/config.ts`
, regenerate the example config:
After modifying
defaults in
`src/config.ts`
, regenerate the example config:
```
bash
```
bash
npm run gen:config-example
npm run gen:config-example
```
```
...
...
config.example.yaml
View file @
2d537ea0
...
@@ -20,7 +20,7 @@ DECK_SIDE_MAX: "15"
...
@@ -20,7 +20,7 @@ DECK_SIDE_MAX: "15"
DECK_MAX_COPIES
:
"
3"
DECK_MAX_COPIES
:
"
3"
OCGCORE_DEBUG_LOG
:
"
"
OCGCORE_DEBUG_LOG
:
"
"
WELCOME
:
"
"
WELCOME
:
"
"
NO_RECONNECT
:
"
"
ENABLE_RECONNECT
:
"
1
"
RECONNECT_TIMEOUT
:
"
180000"
RECONNECT_TIMEOUT
:
"
180000"
HOSTINFO_LFLIST
:
"
0"
HOSTINFO_LFLIST
:
"
0"
HOSTINFO_RULE
:
"
0"
HOSTINFO_RULE
:
"
0"
...
...
src/client/ip-resolver.ts
View file @
2d537ea0
...
@@ -2,6 +2,7 @@ import { Context } from '../app';
...
@@ -2,6 +2,7 @@ import { Context } from '../app';
import
{
Client
}
from
'
./client
'
;
import
{
Client
}
from
'
./client
'
;
import
*
as
ipaddr
from
'
ipaddr.js
'
;
import
*
as
ipaddr
from
'
ipaddr.js
'
;
import
{
convertStringArray
}
from
'
../utility/convert-string-array
'
;
import
{
convertStringArray
}
from
'
../utility/convert-string-array
'
;
import
{
parseConfigBoolean
}
from
'
../utility/parse-config-boolean
'
;
export
class
IpResolver
{
export
class
IpResolver
{
private
logger
=
this
.
ctx
.
createLogger
(
'
IpResolver
'
);
private
logger
=
this
.
ctx
.
createLogger
(
'
IpResolver
'
);
...
@@ -110,9 +111,8 @@ export class IpResolver {
...
@@ -110,9 +111,8 @@ export class IpResolver {
client
.
isLocal
=
isLocal
;
client
.
isLocal
=
isLocal
;
// Increment count for new IP
// Increment count for new IP
const
noConnectCountLimit
=
this
.
ctx
.
getConfig
(
const
noConnectCountLimit
=
parseConfigBoolean
(
'
NO_CONNECT_COUNT_LIMIT
'
,
this
.
ctx
.
getConfig
(
'
NO_CONNECT_COUNT_LIMIT
'
,
''
),
''
,
);
);
let
connectCount
=
this
.
connectedIpCount
.
get
(
newIp
)
||
0
;
let
connectCount
=
this
.
connectedIpCount
.
get
(
newIp
)
||
0
;
...
...
src/config.ts
View file @
2d537ea0
...
@@ -8,30 +8,62 @@ export type HostinfoOptions = {
...
@@ -8,30 +8,62 @@ export type HostinfoOptions = {
};
};
export
const
defaultConfig
=
{
export
const
defaultConfig
=
{
// Bind address. Use '::' to listen on all IPv4/IPv6 interfaces.
HOST
:
'
::
'
,
HOST
:
'
::
'
,
// Main server port for YGOPro clients. Format: integer string.
PORT
:
'
7911
'
,
PORT
:
'
7911
'
,
// Redis connection URL. Format: URL string. Empty means disabled.
REDIS_URL
:
''
,
REDIS_URL
:
''
,
// Log level. Format: lowercase string (e.g. info/debug/warn/error).
LOG_LEVEL
:
'
info
'
,
LOG_LEVEL
:
'
info
'
,
// WebSocket port. Format: integer string. '0' means do not open a separate WS port.
WS_PORT
:
'
0
'
,
WS_PORT
:
'
0
'
,
// SSL certificate directory path. Format: filesystem path string.
SSL_PATH
:
''
,
SSL_PATH
:
''
,
// SSL certificate file name. Format: file name string.
SSL_CERT
:
''
,
SSL_CERT
:
''
,
// SSL private key file name. Format: file name string.
SSL_KEY
:
''
,
SSL_KEY
:
''
,
// Trusted proxies for real IP parsing. Format: comma-separated CIDR list.
TRUSTED_PROXIES
:
'
127.0.0.0/8,::1/128
'
,
TRUSTED_PROXIES
:
'
127.0.0.0/8,::1/128
'
,
// Disable per-IP connection count limit.
// Boolean parse rule (default false): ''/'0'/'false'/'null' => false, otherwise true.
NO_CONNECT_COUNT_LIMIT
:
''
,
NO_CONNECT_COUNT_LIMIT
:
''
,
// Restrict accepted YGOPro version. Format: version string; empty means no restriction.
YGOPRO_VERSION
:
''
,
YGOPRO_VERSION
:
''
,
// Additional accepted versions. Format: comma-separated version strings.
ALT_VERSIONS
:
''
,
ALT_VERSIONS
:
''
,
// Proxy URL for outbound HTTP(S) requests.
// Format: proxy URL string (e.g. http://127.0.0.1:7890). Empty means no proxy.
USE_PROXY
:
''
,
USE_PROXY
:
''
,
// YGOPro resource directory (scripts, DB, etc.). Format: filesystem path string.
YGOPRO_PATH
:
'
./ygopro
'
,
YGOPRO_PATH
:
'
./ygopro
'
,
// Extra script directory. Format: filesystem path string. Empty means disabled.
EXTRA_SCRIPT_PATH
:
''
,
EXTRA_SCRIPT_PATH
:
''
,
// Main deck minimum size. Format: integer string.
DECK_MAIN_MIN
:
'
40
'
,
DECK_MAIN_MIN
:
'
40
'
,
// Main deck maximum size. Format: integer string.
DECK_MAIN_MAX
:
'
60
'
,
DECK_MAIN_MAX
:
'
60
'
,
// Extra deck maximum size. Format: integer string.
DECK_EXTRA_MAX
:
'
15
'
,
DECK_EXTRA_MAX
:
'
15
'
,
// Side deck maximum size. Format: integer string.
DECK_SIDE_MAX
:
'
15
'
,
DECK_SIDE_MAX
:
'
15
'
,
// Max copies per card name. Format: integer string.
DECK_MAX_COPIES
:
'
3
'
,
DECK_MAX_COPIES
:
'
3
'
,
// Enable ocgcore debug logs.
// Boolean parse rule (default false): ''/'0'/'false'/'null' => false, otherwise true.
OCGCORE_DEBUG_LOG
:
''
,
OCGCORE_DEBUG_LOG
:
''
,
// Welcome message sent when players join. Format: plain string.
WELCOME
:
''
,
WELCOME
:
''
,
NO_RECONNECT
:
''
,
// Enable reconnect feature.
// Boolean parse rule (default true): only '0'/'false'/'null' => false, otherwise true.
// Note: with default-true parsing, empty string is treated as true.
ENABLE_RECONNECT
:
'
1
'
,
// Reconnect timeout after disconnect. Format: integer string in milliseconds (ms).
RECONNECT_TIMEOUT
:
'
180000
'
,
RECONNECT_TIMEOUT
:
'
180000
'
,
// Room hostinfo defaults expanded into HOSTINFO_* keys.
// Format: each HOSTINFO_* value is a string; numeric fields use integer strings.
// Unit note: HOSTINFO_TIME_LIMIT is in seconds (s).
...(
Object
.
fromEntries
(
...(
Object
.
fromEntries
(
Object
.
entries
(
DefaultHostinfo
).
map
(([
key
,
value
])
=>
[
Object
.
entries
(
DefaultHostinfo
).
map
(([
key
,
value
])
=>
[
`HOSTINFO_
${
key
.
toUpperCase
()}
`
,
`HOSTINFO_
${
key
.
toUpperCase
()}
`
,
...
...
src/feats/reconnect.ts
View file @
2d537ea0
...
@@ -30,6 +30,7 @@ import { RoomManager } from '../room/room-manager';
...
@@ -30,6 +30,7 @@ import { RoomManager } from '../room/room-manager';
import
{
getSpecificFields
}
from
'
../utility/metadata
'
;
import
{
getSpecificFields
}
from
'
../utility/metadata
'
;
import
{
YGOProCtosDisconnect
}
from
'
../utility/ygopro-ctos-disconnect
'
;
import
{
YGOProCtosDisconnect
}
from
'
../utility/ygopro-ctos-disconnect
'
;
import
{
isUpdateDeckPayloadEqual
}
from
'
../utility/deck-compare
'
;
import
{
isUpdateDeckPayloadEqual
}
from
'
../utility/deck-compare
'
;
import
{
parseConfigBoolean
}
from
'
../utility/parse-config-boolean
'
;
interface
DisconnectInfo
{
interface
DisconnectInfo
{
roomName
:
string
;
roomName
:
string
;
...
@@ -59,8 +60,8 @@ export class Reconnect {
...
@@ -59,8 +60,8 @@ export class Reconnect {
);
// 超时时间,单位:毫秒(默认 180000ms = 3分钟)
);
// 超时时间,单位:毫秒(默认 180000ms = 3分钟)
constructor
(
private
ctx
:
Context
)
{
constructor
(
private
ctx
:
Context
)
{
// 检查是否
禁用断线重连
// 检查是否
启用断线重连(默认启用)
if
(
this
.
ctx
.
getConfig
(
'
NO_RECONNECT
'
,
''
))
{
if
(
!
parseConfigBoolean
(
this
.
ctx
.
getConfig
(
'
ENABLE_RECONNECT
'
,
''
),
true
))
{
return
;
return
;
}
}
...
...
src/room/room.ts
View file @
2d537ea0
...
@@ -89,6 +89,7 @@ import { shuffleDecksBySeed } from '../utility/shuffle-decks-by-seed';
...
@@ -89,6 +89,7 @@ import { shuffleDecksBySeed } from '../utility/shuffle-decks-by-seed';
import
{
isUpdateMessage
}
from
'
../utility/is-update-message
'
;
import
{
isUpdateMessage
}
from
'
../utility/is-update-message
'
;
import
{
getMessageIdentifier
}
from
'
../utility/get-message-identifier
'
;
import
{
getMessageIdentifier
}
from
'
../utility/get-message-identifier
'
;
import
{
canIncreaseTime
}
from
'
../utility/can-increase-time
'
;
import
{
canIncreaseTime
}
from
'
../utility/can-increase-time
'
;
import
{
parseConfigBoolean
}
from
'
../utility/parse-config-boolean
'
;
import
{
TimerState
}
from
'
./timer-state
'
;
import
{
TimerState
}
from
'
./timer-state
'
;
import
{
makeArray
}
from
'
aragami/dist/src/utility/utility
'
;
import
{
makeArray
}
from
'
aragami/dist/src/utility/utility
'
;
...
@@ -1267,7 +1268,7 @@ export class Room {
...
@@ -1267,7 +1268,7 @@ export class Room {
this
.
ocgcore
.
message$
.
subscribe
((
msg
)
=>
{
this
.
ocgcore
.
message$
.
subscribe
((
msg
)
=>
{
if
(
if
(
msg
.
type
===
OcgcoreMessageType
.
DebugMessage
&&
msg
.
type
===
OcgcoreMessageType
.
DebugMessage
&&
!
this
.
ctx
.
getConfig
(
'
OCGCORE_DEBUG_LOG
'
,
''
)
!
parseConfigBoolean
(
this
.
ctx
.
getConfig
(
'
OCGCORE_DEBUG_LOG
'
,
''
)
)
)
{
)
{
return
;
return
;
}
}
...
...
src/utility/parse-config-boolean.ts
0 → 100644
View file @
2d537ea0
export
function
parseConfigBoolean
(
value
:
unknown
,
defaultValue
=
false
,
):
boolean
{
if
(
typeof
value
===
'
boolean
'
)
{
return
value
;
}
if
(
typeof
value
===
'
number
'
)
{
return
value
!==
0
;
}
if
(
typeof
value
===
'
string
'
)
{
const
normalized
=
value
.
trim
().
toLowerCase
();
if
(
defaultValue
)
{
return
!
(
normalized
===
'
0
'
||
normalized
===
'
false
'
||
normalized
===
'
null
'
);
}
return
!
(
normalized
===
''
||
normalized
===
'
0
'
||
normalized
===
'
false
'
||
normalized
===
'
null
'
);
}
if
(
value
==
null
)
{
return
defaultValue
;
}
return
Boolean
(
value
);
}
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