Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Y
ygopro2
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
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
hex
ygopro2
Commits
81bac10e
Commit
81bac10e
authored
Feb 07, 2026
by
hex
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Replay: keep .yrp3d playback; export decks from embedded .yrp
parent
1cd5d12a
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
156 additions
and
213 deletions
+156
-213
Assets/SibylSystem/selectReplay/selectReplay.cs
Assets/SibylSystem/selectReplay/selectReplay.cs
+156
-213
No files found.
Assets/SibylSystem/selectReplay/selectReplay.cs
View file @
81bac10e
using
System
;
using
System.Collections.Generic
;
using
System.IO
;
using
System.Text
.RegularExpressions
;
using
System.Text
;
using
UnityEngine
;
using
YGOSharp.OCGWrapper.Enums
;
public
class
selectReplay
:
WindowServantSP
{
...
...
@@ -64,8 +65,6 @@ public class selectReplay : WindowServantSP
KF_replay
(
superScrollView
.
selectedString
);
}
PrecyOcg
precy
;
private
void
onGod
()
{
if
(!
superScrollView
.
Selected
())
...
...
@@ -76,7 +75,7 @@ public class selectReplay : WindowServantSP
{
return
;
}
KF_replay
(
superScrollView
.
selectedString
,
true
);
RMSshow_none
(
InterString
.
Get
(
"旧录像上帝视角已移除(仅支持联机对战与 .yrp3d 录像)。"
)
);
}
private
void
onSort
()
...
...
@@ -132,219 +131,182 @@ public class selectReplay : WindowServantSP
);
}
byte
[]
getYRPbuffer
(
string
path
)
private
void
onYdk
(
)
{
if
(
path
.
Substring
(
path
.
Length
-
4
,
4
)
==
".yrp"
)
if
(
!
superScrollView
.
Selected
()
)
{
return
File
.
ReadAllBytes
(
path
)
;
return
;
}
byte
[]
returnValue
=
null
;
try
string
yrp3dPath
=
"replay/"
+
superScrollView
.
selectedString
+
".yrp3d"
;
if
(!
File
.
Exists
(
yrp3dPath
))
{
var
collection
=
TcpHelper
.
readPackagesInRecord
(
path
);
foreach
(
var
item
in
collection
)
{
// Debug.Log(item.Fuction);
if
(
item
.
Fuction
==
(
int
)
YGOSharp
.
OCGWrapper
.
Enums
.
GameMessage
.
sibyl_replay
)
{
returnValue
=
item
.
Data
.
reader
.
ReadToEnd
();
break
;
}
}
RMSshow_none
(
InterString
.
Get
(
"录像没有录制完整。"
));
return
;
}
catch
(
Exception
e
)
if
(!
TryGetEmbeddedYrpFromYrp3d
(
yrp3dPath
,
out
byte
[]
yrpBytes
))
{
// Debug.Log(e);
RMSshow_none
(
InterString
.
Get
(
"该录像不包含可提取的卡组信息。"
));
return
;
}
if
(!
TryParseDecksFromYrp
(
yrpBytes
,
out
List
<
List
<
int
>>
mainDecks
,
out
List
<
List
<
int
>>
extraDecks
))
{
RMSshow_none
(
InterString
.
Get
(
"录像没有录制完整。"
));
return
;
}
if
(
mainDecks
.
Count
==
0
||
mainDecks
.
Count
!=
extraDecks
.
Count
)
{
RMSshow_none
(
InterString
.
Get
(
"该录像不包含可提取的卡组信息。"
));
return
;
}
// Debug.Log(returnValue);
return
returnValue
;
}
Percy
.
YRP
getYRP
(
byte
[]
buffer
)
{
Percy
.
YRP
returnValue
=
new
Percy
.
YRP
();
try
{
BinaryReader
reader
=
new
BinaryReader
(
new
MemoryStream
(
buffer
));
returnValue
.
ID
=
reader
.
ReadInt32
();
returnValue
.
Version
=
reader
.
ReadInt32
();
returnValue
.
Flag
=
reader
.
ReadInt32
();
returnValue
.
Seed
=
reader
.
ReadUInt32
();
returnValue
.
DataSize
=
reader
.
ReadInt32
();
returnValue
.
Hash
=
reader
.
ReadInt32
();
returnValue
.
Props
=
reader
.
ReadBytes
(
8
);
if
(
returnValue
.
ID
==
0x32707279
)
// REPLAY_ID_YRP2
{
for
(
int
i
=
0
;
i
<
8
;
i
++)
{
reader
.
ReadUInt32
();
// returnValue.SeedsV2[i] = reader.ReadUInt32();
}
for
(
int
i
=
0
;
i
<
4
;
i
++)
// other flags, unused for now
{
reader
.
ReadUInt32
();
}
}
Directory
.
CreateDirectory
(
"deck"
);
}
catch
(
Exception
)
{
RMSshow_none
(
InterString
.
Get
(
"写入失败!请检查文件夹权限。"
));
return
;
}
byte
[]
raw
=
reader
.
ReadToEnd
();
if
((
returnValue
.
Flag
&
0x1
)
>
0
)
for
(
int
i
=
0
;
i
<
mainDecks
.
Count
;
i
++)
{
var
builder
=
new
StringBuilder
();
builder
.
Append
(
"#created by ygopro2\r\n#main\r\n"
);
for
(
int
j
=
0
;
j
<
mainDecks
[
i
].
Count
;
j
++)
{
SevenZip
.
Compression
.
LZMA
.
Decoder
lzma
=
new
SevenZip
.
Compression
.
LZMA
.
Decoder
();
lzma
.
SetDecoderProperties
(
returnValue
.
Props
);
MemoryStream
decompressed
=
new
MemoryStream
();
lzma
.
Code
(
new
MemoryStream
(
raw
),
decompressed
,
raw
.
LongLength
,
returnValue
.
DataSize
,
null
);
raw
=
decompressed
.
ToArray
();
builder
.
Append
(
mainDecks
[
i
][
j
]).
Append
(
"\r\n"
);
}
reader
=
new
BinaryReader
(
new
MemoryStream
(
raw
)
);
if
((
returnValue
.
Flag
&
0x2
)
>
0
)
builder
.
Append
(
"#extra\r\n"
);
for
(
int
j
=
0
;
j
<
extraDecks
[
i
].
Count
;
j
++
)
{
Program
.
I
().
room
.
mode
=
2
;
returnValue
.
playerData
.
Add
(
new
Percy
.
YRP
.
PlayerData
());
returnValue
.
playerData
.
Add
(
new
Percy
.
YRP
.
PlayerData
());
returnValue
.
playerData
.
Add
(
new
Percy
.
YRP
.
PlayerData
());
returnValue
.
playerData
.
Add
(
new
Percy
.
YRP
.
PlayerData
());
returnValue
.
playerData
[
0
].
name
=
reader
.
ReadUnicode
(
20
);
returnValue
.
playerData
[
1
].
name
=
reader
.
ReadUnicode
(
20
);
returnValue
.
playerData
[
2
].
name
=
reader
.
ReadUnicode
(
20
);
returnValue
.
playerData
[
3
].
name
=
reader
.
ReadUnicode
(
20
);
returnValue
.
StartLp
=
reader
.
ReadInt32
();
returnValue
.
StartHand
=
reader
.
ReadInt32
();
returnValue
.
DrawCount
=
reader
.
ReadInt32
();
returnValue
.
opt
=
reader
.
ReadInt32
();
Program
.
I
().
ocgcore
.
MasterRule
=
returnValue
.
opt
>>
16
;
for
(
int
i
=
0
;
i
<
4
;
i
++)
{
int
count
=
reader
.
ReadInt32
();
for
(
int
i2
=
0
;
i2
<
count
;
i2
++)
{
returnValue
.
playerData
[
i
].
main
.
Add
(
reader
.
ReadInt32
());
}
count
=
reader
.
ReadInt32
();
for
(
int
i2
=
0
;
i2
<
count
;
i2
++)
{
returnValue
.
playerData
[
i
].
extra
.
Add
(
reader
.
ReadInt32
());
}
}
builder
.
Append
(
extraDecks
[
i
][
j
]).
Append
(
"\r\n"
);
}
else
string
path
=
"deck/"
+
superScrollView
.
selectedString
+
"_"
+
(
i
+
1
).
ToString
()
+
".ydk"
;
try
{
returnValue
.
playerData
.
Add
(
new
Percy
.
YRP
.
PlayerData
());
returnValue
.
playerData
.
Add
(
new
Percy
.
YRP
.
PlayerData
());
returnValue
.
playerData
[
0
].
name
=
reader
.
ReadUnicode
(
20
);
returnValue
.
playerData
[
1
].
name
=
reader
.
ReadUnicode
(
20
);
returnValue
.
StartLp
=
reader
.
ReadInt32
();
returnValue
.
StartHand
=
reader
.
ReadInt32
();
returnValue
.
DrawCount
=
reader
.
ReadInt32
();
returnValue
.
opt
=
reader
.
ReadInt32
();
Program
.
I
().
ocgcore
.
MasterRule
=
returnValue
.
opt
>>
16
;
for
(
int
i
=
0
;
i
<
2
;
i
++)
{
int
count
=
reader
.
ReadInt32
();
for
(
int
i2
=
0
;
i2
<
count
;
i2
++)
{
returnValue
.
playerData
[
i
].
main
.
Add
(
reader
.
ReadInt32
());
}
count
=
reader
.
ReadInt32
();
for
(
int
i2
=
0
;
i2
<
count
;
i2
++)
{
returnValue
.
playerData
[
i
].
extra
.
Add
(
reader
.
ReadInt32
());
}
}
File
.
WriteAllText
(
path
,
builder
.
ToString
());
RMSshow_none
(
InterString
.
Get
(
"卡组入库:[?]"
,
path
));
}
while
(
reader
.
BaseStream
.
Position
<
reader
.
BaseStream
.
Length
)
catch
(
Exception
)
{
returnValue
.
gameData
.
Add
(
reader
.
ReadBytes
(
reader
.
ReadByte
()));
RMSshow_none
(
InterString
.
Get
(
"写入失败!请检查文件夹权限。"
));
return
;
}
}
catch
(
Exception
e
)
{
// Debug.Log(e);
}
return
returnValue
;
}
private
void
onY
dk
()
private
void
onY
rp
()
{
if
(!
superScrollView
.
Selected
())
RMSshow_none
(
InterString
.
Get
(
"导出 .yrp 功能已移除(仅支持联机对战与 .yrp3d 录像)。"
));
}
private
static
bool
TryGetEmbeddedYrpFromYrp3d
(
string
yrp3dPath
,
out
byte
[]
yrpBytes
)
{
yrpBytes
=
null
;
List
<
Package
>
collection
=
TcpHelper
.
readPackagesInRecord
(
yrp3dPath
);
for
(
int
i
=
0
;
i
<
collection
.
Count
;
i
++)
{
return
;
if
(
collection
[
i
].
Fuction
==
(
int
)
GameMessage
.
sibyl_replay
)
{
yrpBytes
=
collection
[
i
].
Data
.
get
();
return
yrpBytes
!=
null
&&
yrpBytes
.
Length
>
0
;
}
}
return
false
;
}
private
static
bool
TryParseDecksFromYrp
(
byte
[]
yrpBytes
,
out
List
<
List
<
int
>>
mainDecks
,
out
List
<
List
<
int
>>
extraDecks
)
{
mainDecks
=
null
;
extraDecks
=
null
;
try
{
Percy
.
YRP
yrp
;
i
f
(
File
.
Exists
(
"replay/"
+
superScrollView
.
selectedString
))
{
yrp
=
getYRP
(
File
.
ReadAllBytes
(
"replay/"
+
superScrollView
.
selectedString
)
);
}
else
{
yrp
=
getYRP
(
getYRPbuffer
(
"replay/"
+
superScrollView
.
selectedString
+
".yrp3d"
)
);
}
for
(
int
i
=
0
;
i
<
yrp
.
playerData
.
Count
;
i
++)
var
headerReader
=
new
BinaryReader
(
new
MemoryStream
(
yrpBytes
))
;
i
nt
id
=
headerReader
.
ReadInt32
();
headerReader
.
ReadInt32
();
// version
int
flag
=
headerReader
.
ReadInt32
(
);
headerReader
.
ReadUInt32
();
// seed
int
dataSize
=
headerReader
.
ReadInt32
();
headerReader
.
ReadInt32
();
// hash
byte
[]
props
=
headerReader
.
ReadBytes
(
8
);
if
(
id
==
0x32707279
)
// REPLAY_ID_YRP2
{
string
value
=
"#created by ygopro2\r\n#main\r\n"
;
for
(
int
i2
=
0
;
i2
<
yrp
.
playerData
[
i
].
main
.
Count
;
i2
++)
for
(
int
i
=
0
;
i
<
8
;
i
++)
{
value
+=
yrp
.
playerData
[
i
].
main
[
i2
].
ToString
()
+
"\r\n"
;
headerReader
.
ReadUInt32
()
;
}
value
+=
"#extra\r\n"
;
for
(
int
i2
=
0
;
i2
<
yrp
.
playerData
[
i
].
extra
.
Count
;
i2
++)
for
(
int
i
=
0
;
i
<
4
;
i
++)
{
value
+=
yrp
.
playerData
[
i
].
extra
[
i2
].
ToString
()
+
"\r\n"
;
headerReader
.
ReadUInt32
()
;
}
string
name
=
"deck/"
+
superScrollView
.
selectedString
+
"_"
+
(
i
+
1
).
ToString
()
+
".ydk"
;
File
.
WriteAllText
(
name
,
value
);
RMSshow_none
(
InterString
.
Get
(
"卡组入库:[?]"
,
name
));
}
if
(
yrp
.
playerData
.
Count
==
0
)
byte
[]
raw
=
headerReader
.
ReadToEnd
();
if
((
flag
&
0x1
)
>
0
)
{
RMSshow_none
(
InterString
.
Get
(
"录像没有录制完整。"
));
var
lzma
=
new
SevenZip
.
Compression
.
LZMA
.
Decoder
();
lzma
.
SetDecoderProperties
(
props
);
using
(
var
decompressed
=
new
MemoryStream
())
{
lzma
.
Code
(
new
MemoryStream
(
raw
),
decompressed
,
raw
.
LongLength
,
dataSize
,
null
);
raw
=
decompressed
.
ToArray
();
}
}
}
catch
(
Exception
e
)
{
// UnityEngine.Debug.Log(e);
RMSshow_none
(
InterString
.
Get
(
"录像没有录制完整。"
));
}
}
private
void
onYrp
()
{
if
(!
superScrollView
.
Selected
())
{
return
;
}
try
{
if
(
File
.
Exists
(
"replay/"
+
superScrollView
.
selectedString
+
".yrp3d"
))
var
reader
=
new
BinaryReader
(
new
MemoryStream
(
raw
));
int
playerCount
=
((
flag
&
0x2
)
>
0
)
?
4
:
2
;
for
(
int
i
=
0
;
i
<
playerCount
;
i
++)
{
File
.
WriteAllBytes
(
"replay/"
+
superScrollView
.
selectedString
+
".yrp"
,
getYRPbuffer
(
"replay/"
+
superScrollView
.
selectedString
+
".yrp3d"
)
);
RMSshow_none
(
InterString
.
Get
(
"录像入库:[?]"
,
"replay/"
+
superScrollView
.
selectedString
+
".yrp"
)
);
printFile
();
reader
.
ReadUnicode
(
20
);
}
else
reader
.
ReadInt32
();
// StartLp
reader
.
ReadInt32
();
// StartHand
reader
.
ReadInt32
();
// DrawCount
reader
.
ReadInt32
();
// opt
mainDecks
=
new
List
<
List
<
int
>>(
playerCount
);
extraDecks
=
new
List
<
List
<
int
>>(
playerCount
);
for
(
int
i
=
0
;
i
<
playerCount
;
i
++)
{
RMSshow_none
(
InterString
.
Get
(
"录像没有录制完整。"
));
int
mainCount
=
reader
.
ReadInt32
();
var
main
=
new
List
<
int
>(
Mathf
.
Max
(
mainCount
,
0
));
for
(
int
j
=
0
;
j
<
mainCount
;
j
++)
{
main
.
Add
(
reader
.
ReadInt32
());
}
int
extraCount
=
reader
.
ReadInt32
();
var
extra
=
new
List
<
int
>(
Mathf
.
Max
(
extraCount
,
0
));
for
(
int
j
=
0
;
j
<
extraCount
;
j
++)
{
extra
.
Add
(
reader
.
ReadInt32
());
}
mainDecks
.
Add
(
main
);
extraDecks
.
Add
(
extra
);
}
return
true
;
}
catch
(
Exception
)
{
RMSshow_none
(
InterString
.
Get
(
"录像没有录制完整。"
));
mainDecks
=
null
;
extraDecks
=
null
;
return
false
;
}
}
...
...
@@ -461,44 +423,22 @@ public class selectReplay : WindowServantSP
{
if
(
god
)
{
RMSshow_none
(
InterString
.
Get
(
"您正在观看旧版的录像(上帝视角),不保证稳定性。"
)
);
if
(
precy
!=
null
)
precy
.
dispose
();
precy
=
new
PrecyOcg
();
var
collections
=
TcpHelper
.
getPackages
(
precy
.
ygopro
.
getYRP3dBuffer
(
getYRP
(
getYRPbuffer
(
"replay/"
+
name
+
".yrp3d"
))
)
);
pushCollection
(
collections
);
}
else
{
var
collection
=
TcpHelper
.
readPackagesInRecord
(
"replay/"
+
name
+
".yrp3d"
);
pushCollection
(
collection
);
RMSshow_none
(
InterString
.
Get
(
"旧录像上帝视角已移除(仅支持 .yrp3d 录像播放)。"
));
return
;
}
var
collection
=
TcpHelper
.
readPackagesInRecord
(
"replay/"
+
name
+
".yrp3d"
);
pushCollection
(
collection
);
return
;
}
else
if
(
name
.
Length
>
4
&&
name
.
Substring
(
name
.
Length
-
4
,
4
)
==
".yrp"
)
{
if
(
name
.
Length
>
4
&&
name
.
Substring
(
name
.
Length
-
4
,
4
)
==
".yrp"
)
if
(
File
.
Exists
(
"replay/"
+
name
)
)
{
if
(
File
.
Exists
(
"replay/"
+
name
))
{
RMSshow_none
(
InterString
.
Get
(
"您正在观看旧版的录像(上帝视角),不保证稳定性。"
)
);
if
(
precy
!=
null
)
precy
.
dispose
();
precy
=
new
PrecyOcg
();
var
collections
=
TcpHelper
.
getPackages
(
precy
.
ygopro
.
getYRP3dBuffer
(
getYRP
(
File
.
ReadAllBytes
(
"replay/"
+
name
)))
);
pushCollection
(
collections
);
}
RMSshow_none
(
InterString
.
Get
(
"旧版 .yrp 录像播放已移除(仅支持 .yrp3d)。"
));
return
;
}
}
RMSshow_none
(
InterString
.
Get
(
"录像没有录制完整。"
));
}
catch
(
Exception
)
{
...
...
@@ -527,6 +467,16 @@ public class selectReplay : WindowServantSP
public
override
void
show
()
{
base
.
show
();
var
godButton
=
UIHelper
.
getByName
(
gameObject
,
"god_"
);
if
(
godButton
!=
null
)
{
godButton
.
SetActive
(
false
);
}
var
yrpButton
=
UIHelper
.
getByName
(
gameObject
,
"yrp_"
);
if
(
yrpButton
!=
null
)
{
yrpButton
.
SetActive
(
false
);
}
printFile
();
Program
.
charge
();
}
...
...
@@ -556,13 +506,6 @@ public class selectReplay : WindowServantSP
fileInfos
[
i
].
Name
.
Substring
(
0
,
fileInfos
[
i
].
Name
.
Length
-
6
)
);
}
if
(
fileInfos
[
i
].
Name
.
Length
>
4
&&
fileInfos
[
i
].
Name
.
Substring
(
fileInfos
[
i
].
Name
.
Length
-
4
,
4
)
==
".yrp"
)
{
superScrollView
.
add
(
fileInfos
[
i
].
Name
);
}
}
}
}
...
...
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