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
1
Issues
1
List
Boards
Labels
Service Desk
Milestones
Merge Requests
3
Merge Requests
3
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
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
MyCard
srvpro
Commits
c3c66c53
Commit
c3c66c53
authored
May 07, 2020
by
nanahira
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add recover from replay
parent
e592353c
Changes
6
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
869 additions
and
99 deletions
+869
-99
Replay.coffee
Replay.coffee
+196
-0
Replay.js
Replay.js
+293
-0
data/default_config.json
data/default_config.json
+2
-1
data/i18n.json
data/i18n.json
+8
-0
ygopro-server.coffee
ygopro-server.coffee
+162
-44
ygopro-server.js
ygopro-server.js
+208
-54
No files found.
Replay.coffee
0 → 100644
View file @
c3c66c53
lzma
=
require
'lzma'
fs
=
require
'fs'
# Deck = require './Deck.js'
class
replayHeader
@
replayCompressedFlag
=
0x1
@
replayTagFlag
=
0x2
@
replayDecodedFlag
=
0x4
constructor
:
->
@
id
=
0
@
version
=
0
@
flag
=
0
@
seed
=
0
@
dataSizeRaw
=
[]
@
hash
=
0
@
props
=
[]
getDataSize
:
->
@
dataSizeRaw
[
0
]
+
@
dataSizeRaw
[
1
]
*
0x100
+
@
dataSizeRaw
[
2
]
*
0x10000
+
@
dataSizeRaw
[
3
]
*
0x1000000
getIsTag
:
->
@
flag
&
replayHeader
.
replayTagFlag
>
0
getIsCompressed
:
->
@
flag
&
replayHeader
.
replayCompressedFlag
>
0
getLzmaHeader
:
->
bytes
=
[].
concat
(
@
props
[
0
..
4
],
@
dataSizeRaw
,
[
0
,
0
,
0
,
0
])
Buffer
.
from
(
bytes
)
Object
.
defineProperty
replayHeader
.
prototype
,
'dataSize'
,
get
:
@
getDataSize
Object
.
defineProperty
replayHeader
.
prototype
,
'isTag'
,
get
:
@
getIsTag
Object
.
defineProperty
replayHeader
.
prototype
,
'isCompressed'
,
get
:
@
getIsCompressed
class
ReplayReader
constructor
:
(
buffer
)
->
@
pointer
=
0
@
buffer
=
buffer
readByte
:
->
answer
=
@
buffer
.
readUInt8
(
@
pointer
)
@
pointer
+=
1
answer
readByteArray
:
(
length
)
->
answer
=
[]
answer
.
push
@
readByte
()
for
i
in
[
1
..
length
]
answer
readInt8
:
->
answer
=
@
buffer
.
readInt8
(
@
pointer
)
@
pointer
+=
1
answer
readUInt8
:
->
answer
=
@
buffer
.
readUInt8
(
@
pointer
)
@
pointer
+=
1
answer
readInt16
:
->
answer
=
@
buffer
.
readInt16LE
@
pointer
@
pointer
+=
2
answer
readInt32
:
->
answer
=
@
buffer
.
readInt32LE
@
pointer
@
pointer
+=
4
answer
readAll
:
->
answer
=
@
buffer
.
slice
(
@
pointer
)
# @pointer = 0
answer
readString
:
(
length
)
->
if
@
pointer
+
length
>
@
buffer
.
length
return
null
full
=
@
buffer
.
slice
(
@
pointer
,
@
pointer
+
length
).
toString
(
'utf-16le'
)
answer
=
full
.
split
(
"
\u0000
"
)[
0
]
@
pointer
+=
length
answer
readRaw
:
(
length
)
->
if
@
pointer
+
length
>
@
buffer
.
length
return
null
answer
=
@
buffer
.
slice
(
@
pointer
,
@
pointer
+
length
)
@
pointer
+=
length
answer
class
Replay
constructor
:
->
@
header
=
null
@
hostName
=
""
@
clientName
=
""
@
startLp
=
0
@
startHand
=
0
@
drawCount
=
0
@
opt
=
0
@
hostDeck
=
null
@
clientDeck
=
null
@
tagHostName
=
null
@
tagClientName
=
null
@
tagHostDeck
=
null
@
tagClientDeck
=
null
@
responses
=
null
getDecks
:
->
if
@
isTag
[
@
hostDeck
,
@
clientDeck
,
@
tagHostDeck
,
@
tagClientDeck
]
else
[
@
hostDeck
,
@
clientDeck
]
getIsTag
:
->
@
header
==
null
?
false
:
@
header
.
isTag
@
fromFile
:
(
filePath
)
->
Replay
.
fromBuffer
fs
.
readFileSync
filePath
@
fromBuffer
:
(
buffer
)
->
reader
=
new
ReplayReader
buffer
header
=
Replay
.
readHeader
reader
lzmaBuffer
=
Buffer
.
concat
[
header
.
getLzmaHeader
(),
reader
.
readAll
()]
if
header
.
isCompressed
decompressed
=
lzmaBuffer
else
decompressed
=
Buffer
.
from
lzma
.
decompress
lzmaBuffer
reader
=
new
ReplayReader
decompressed
replay
=
Replay
.
readReplay
header
,
reader
replay
@
readHeader
:
(
reader
)
->
header
=
new
replayHeader
()
header
.
id
=
reader
.
readInt32
()
header
.
version
=
reader
.
readInt32
()
header
.
flag
=
reader
.
readInt32
()
header
.
seed
=
reader
.
readInt32
()
header
.
dataSizeRaw
=
reader
.
readByteArray
4
header
.
hash
=
reader
.
readInt32
()
header
.
props
=
reader
.
readByteArray
8
header
@
readReplay
:
(
header
,
reader
)
->
replay
=
new
Replay
()
replay
.
header
=
header
replay
.
hostName
=
reader
.
readString
(
40
)
replay
.
tagHostName
=
reader
.
readString
(
40
)
if
header
.
isTag
replay
.
tagClientName
=
reader
.
readString
(
40
)
if
header
.
isTag
replay
.
clientName
=
reader
.
readString
(
40
)
replay
.
startLp
=
reader
.
readInt32
()
replay
.
startHand
=
reader
.
readInt32
()
replay
.
drawCount
=
reader
.
readInt32
()
replay
.
opt
=
reader
.
readInt32
()
replay
.
hostDeck
=
Replay
.
readDeck
reader
replay
.
tagHostDeck
=
Replay
.
readDeck
reader
if
header
.
isTag
replay
.
tagClientDeck
=
Replay
.
readDeck
reader
if
header
.
isTag
replay
.
clientDeck
=
Replay
.
readDeck
reader
replay
.
responses
=
Replay
.
readResponses
reader
replay
@
readDeck
:
(
reader
)
->
deck
=
{}
deck
.
main
=
Replay
.
readDeckPack
reader
deck
.
ex
=
Replay
.
readDeckPack
reader
deck
@
readDeckPack
:
(
reader
)
->
length
=
reader
.
readInt32
()
answer
=
[]
answer
.
push
reader
.
readInt32
()
for
i
in
[
1
..
length
]
answer
@
readResponses
:
(
reader
)
->
answer
=
[]
while
true
try
length
=
reader
.
readUInt8
()
if
length
>
64
length
=
64
single
=
reader
.
readRaw
(
length
)
if
!
single
break
answer
.
push
(
single
)
catch
break
answer
Object
.
defineProperty
replayHeader
.
prototype
,
'decks'
,
get
:
@
getDecks
Object
.
defineProperty
replayHeader
.
prototype
,
'isTag'
,
get
:
@
getIsTag
module
.
exports
=
Replay
Replay.js
0 → 100644
View file @
c3c66c53
// Generated by CoffeeScript 2.5.1
(
function
()
{
var
Replay
,
ReplayReader
,
fs
,
lzma
,
replayHeader
;
lzma
=
require
(
'
lzma
'
);
fs
=
require
(
'
fs
'
);
replayHeader
=
(
function
()
{
// Deck = require './Deck.js'
class
replayHeader
{
constructor
()
{
this
.
id
=
0
;
this
.
version
=
0
;
this
.
flag
=
0
;
this
.
seed
=
0
;
this
.
dataSizeRaw
=
[];
this
.
hash
=
0
;
this
.
props
=
[];
}
getDataSize
()
{
return
this
.
dataSizeRaw
[
0
]
+
this
.
dataSizeRaw
[
1
]
*
0x100
+
this
.
dataSizeRaw
[
2
]
*
0x10000
+
this
.
dataSizeRaw
[
3
]
*
0x1000000
;
}
getIsTag
()
{
return
this
.
flag
&
replayHeader
.
replayTagFlag
>
0
;
}
getIsCompressed
()
{
return
this
.
flag
&
replayHeader
.
replayCompressedFlag
>
0
;
}
getLzmaHeader
()
{
var
bytes
;
bytes
=
[].
concat
(
this
.
props
.
slice
(
0
,
5
),
this
.
dataSizeRaw
,
[
0
,
0
,
0
,
0
]);
return
Buffer
.
from
(
bytes
);
}
};
replayHeader
.
replayCompressedFlag
=
0x1
;
replayHeader
.
replayTagFlag
=
0x2
;
replayHeader
.
replayDecodedFlag
=
0x4
;
Object
.
defineProperty
(
replayHeader
.
prototype
,
'
dataSize
'
,
{
get
:
replayHeader
.
getDataSize
});
Object
.
defineProperty
(
replayHeader
.
prototype
,
'
isTag
'
,
{
get
:
replayHeader
.
getIsTag
});
Object
.
defineProperty
(
replayHeader
.
prototype
,
'
isCompressed
'
,
{
get
:
replayHeader
.
getIsCompressed
});
return
replayHeader
;
}).
call
(
this
);
ReplayReader
=
class
ReplayReader
{
constructor
(
buffer
)
{
this
.
pointer
=
0
;
this
.
buffer
=
buffer
;
}
readByte
()
{
var
answer
;
answer
=
this
.
buffer
.
readUInt8
(
this
.
pointer
);
this
.
pointer
+=
1
;
return
answer
;
}
readByteArray
(
length
)
{
var
answer
,
i
,
j
,
ref
;
answer
=
[];
for
(
i
=
j
=
1
,
ref
=
length
;
(
1
<=
ref
?
j
<=
ref
:
j
>=
ref
);
i
=
1
<=
ref
?
++
j
:
--
j
)
{
answer
.
push
(
this
.
readByte
());
}
return
answer
;
}
readInt8
()
{
var
answer
;
answer
=
this
.
buffer
.
readInt8
(
this
.
pointer
);
this
.
pointer
+=
1
;
return
answer
;
}
readUInt8
()
{
var
answer
;
answer
=
this
.
buffer
.
readUInt8
(
this
.
pointer
);
this
.
pointer
+=
1
;
return
answer
;
}
readInt16
()
{
var
answer
;
answer
=
this
.
buffer
.
readInt16LE
(
this
.
pointer
);
this
.
pointer
+=
2
;
return
answer
;
}
readInt32
()
{
var
answer
;
answer
=
this
.
buffer
.
readInt32LE
(
this
.
pointer
);
this
.
pointer
+=
4
;
return
answer
;
}
readAll
()
{
var
answer
;
answer
=
this
.
buffer
.
slice
(
this
.
pointer
);
// @pointer = 0
return
answer
;
}
readString
(
length
)
{
var
answer
,
full
;
if
(
this
.
pointer
+
length
>
this
.
buffer
.
length
)
{
return
null
;
}
full
=
this
.
buffer
.
slice
(
this
.
pointer
,
this
.
pointer
+
length
).
toString
(
'
utf-16le
'
);
answer
=
full
.
split
(
"
\
u0000
"
)[
0
];
this
.
pointer
+=
length
;
return
answer
;
}
readRaw
(
length
)
{
var
answer
;
if
(
this
.
pointer
+
length
>
this
.
buffer
.
length
)
{
return
null
;
}
answer
=
this
.
buffer
.
slice
(
this
.
pointer
,
this
.
pointer
+
length
);
this
.
pointer
+=
length
;
return
answer
;
}
};
Replay
=
(
function
()
{
class
Replay
{
constructor
()
{
this
.
header
=
null
;
this
.
hostName
=
""
;
this
.
clientName
=
""
;
this
.
startLp
=
0
;
this
.
startHand
=
0
;
this
.
drawCount
=
0
;
this
.
opt
=
0
;
this
.
hostDeck
=
null
;
this
.
clientDeck
=
null
;
this
.
tagHostName
=
null
;
this
.
tagClientName
=
null
;
this
.
tagHostDeck
=
null
;
this
.
tagClientDeck
=
null
;
this
.
responses
=
null
;
}
getDecks
()
{
if
(
this
.
isTag
)
{
return
[
this
.
hostDeck
,
this
.
clientDeck
,
this
.
tagHostDeck
,
this
.
tagClientDeck
];
}
else
{
return
[
this
.
hostDeck
,
this
.
clientDeck
];
}
}
getIsTag
()
{
var
ref
;
return
(
ref
=
this
.
header
===
null
)
!=
null
?
ref
:
{
false
:
this
.
header
.
isTag
};
}
static
fromFile
(
filePath
)
{
return
Replay
.
fromBuffer
(
fs
.
readFileSync
(
filePath
));
}
static
fromBuffer
(
buffer
)
{
var
decompressed
,
header
,
lzmaBuffer
,
reader
,
replay
;
reader
=
new
ReplayReader
(
buffer
);
header
=
Replay
.
readHeader
(
reader
);
lzmaBuffer
=
Buffer
.
concat
([
header
.
getLzmaHeader
(),
reader
.
readAll
()]);
if
(
header
.
isCompressed
)
{
decompressed
=
lzmaBuffer
;
}
else
{
decompressed
=
Buffer
.
from
(
lzma
.
decompress
(
lzmaBuffer
));
}
reader
=
new
ReplayReader
(
decompressed
);
replay
=
Replay
.
readReplay
(
header
,
reader
);
return
replay
;
}
static
readHeader
(
reader
)
{
var
header
;
header
=
new
replayHeader
();
header
.
id
=
reader
.
readInt32
();
header
.
version
=
reader
.
readInt32
();
header
.
flag
=
reader
.
readInt32
();
header
.
seed
=
reader
.
readInt32
();
header
.
dataSizeRaw
=
reader
.
readByteArray
(
4
);
header
.
hash
=
reader
.
readInt32
();
header
.
props
=
reader
.
readByteArray
(
8
);
return
header
;
}
static
readReplay
(
header
,
reader
)
{
var
replay
;
replay
=
new
Replay
();
replay
.
header
=
header
;
replay
.
hostName
=
reader
.
readString
(
40
);
if
(
header
.
isTag
)
{
replay
.
tagHostName
=
reader
.
readString
(
40
);
}
if
(
header
.
isTag
)
{
replay
.
tagClientName
=
reader
.
readString
(
40
);
}
replay
.
clientName
=
reader
.
readString
(
40
);
replay
.
startLp
=
reader
.
readInt32
();
replay
.
startHand
=
reader
.
readInt32
();
replay
.
drawCount
=
reader
.
readInt32
();
replay
.
opt
=
reader
.
readInt32
();
replay
.
hostDeck
=
Replay
.
readDeck
(
reader
);
if
(
header
.
isTag
)
{
replay
.
tagHostDeck
=
Replay
.
readDeck
(
reader
);
}
if
(
header
.
isTag
)
{
replay
.
tagClientDeck
=
Replay
.
readDeck
(
reader
);
}
replay
.
clientDeck
=
Replay
.
readDeck
(
reader
);
replay
.
responses
=
Replay
.
readResponses
(
reader
);
return
replay
;
}
static
readDeck
(
reader
)
{
var
deck
;
deck
=
{};
deck
.
main
=
Replay
.
readDeckPack
(
reader
);
deck
.
ex
=
Replay
.
readDeckPack
(
reader
);
return
deck
;
}
static
readDeckPack
(
reader
)
{
var
answer
,
i
,
j
,
length
,
ref
;
length
=
reader
.
readInt32
();
answer
=
[];
for
(
i
=
j
=
1
,
ref
=
length
;
(
1
<=
ref
?
j
<=
ref
:
j
>=
ref
);
i
=
1
<=
ref
?
++
j
:
--
j
)
{
answer
.
push
(
reader
.
readInt32
());
}
return
answer
;
}
static
readResponses
(
reader
)
{
var
answer
,
length
,
single
;
answer
=
[];
while
(
true
)
{
try
{
length
=
reader
.
readUInt8
();
if
(
length
>
64
)
{
length
=
64
;
}
single
=
reader
.
readRaw
(
length
);
if
(
!
single
)
{
break
;
}
answer
.
push
(
single
);
}
catch
(
error
)
{
break
;
}
}
return
answer
;
}
};
Object
.
defineProperty
(
replayHeader
.
prototype
,
'
decks
'
,
{
get
:
Replay
.
getDecks
});
Object
.
defineProperty
(
replayHeader
.
prototype
,
'
isTag
'
,
{
get
:
Replay
.
getIsTag
});
return
Replay
;
}).
call
(
this
);
module
.
exports
=
Replay
;
}).
call
(
this
);
data/default_config.json
View file @
c3c66c53
...
...
@@ -168,7 +168,8 @@
"replay_safe"
:
true
,
"replay_path"
:
"./replays/"
,
"replay_archive_tool"
:
"7z"
,
"block_replay_to_player"
:
true
,
"block_replay_to_player"
:
false
,
"enable_recover"
:
true
,
"show_ip"
:
false
,
"show_info"
:
true
,
"log_save_path"
:
"./config/"
,
...
...
data/i18n.json
View file @
c3c66c53
...
...
@@ -30,6 +30,9 @@
"cloud_replay_error"
:
"Replay opening failed."
,
"cloud_replay_playing"
:
"Accessing cloud replay"
,
"cloud_replay_hint"
:
"These are the recent saved replay codes, please enter the replay code at the password column to access it."
,
"recover_replay_hint"
:
"These are the recent duels, please enter the code RC[ID]%[TURN]#[ROOMNAME] at the password column to recover the duel."
,
"recover_hint"
:
"You entered a recover room. Please be ready with your deck on that duel."
,
"recover_start_hint"
:
"Started recovering..."
,
"blank_room_name"
:
"Blank room name is unallowed, please fill in something."
,
"loading_user_info"
:
"Loading user info..."
,
"invalid_password_length"
:
"Password invalid (Invalid Length)"
,
...
...
@@ -342,6 +345,11 @@
"cloud_replay_error"
:
"播放录像出错"
,
"cloud_replay_playing"
:
"正在观看云录像"
,
"cloud_replay_hint"
:
"以下是您近期的云录像,密码处输入 R#录像编号 即可观看"
,
"recover_replay_hint"
:
"以下是您近期进行的决斗,密码处输入 RC决斗编号%回合数#房间号 即可创建复盘房间"
,
"recover_hint"
:
"你进入了一个复盘房间,请使用复盘局的卡组准备。"
,
"recover_start_hint"
:
"开始复盘..."
,
"recover_success"
:
"复盘成功。请耐心等待跳到当前回合。"
,
"recover_fail"
:
"复盘失败。"
,
"blank_room_name"
:
"房间名不能为空,请在主机密码处填写房间名"
,
"loading_user_info"
:
"正在读取用户信息..."
,
"invalid_password_length"
:
"主机密码不正确 (Invalid Length)"
,
...
...
ygopro-server.coffee
View file @
c3c66c53
This diff is collapsed.
Click to expand it.
ygopro-server.js
View file @
c3c66c53
This diff is collapsed.
Click to expand it.
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