Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Y
ygopro-deck-encode
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
MyCard
ygopro-deck-encode
Commits
3dd42f5b
Commit
3dd42f5b
authored
May 21, 2025
by
nanahira
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add fromUpdateDeckPayload
parent
2126ac5a
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
163 additions
and
18 deletions
+163
-18
README.md
README.md
+4
-0
index.ts
index.ts
+27
-1
src/utils.ts
src/utils.ts
+113
-17
tests/sample.spec.ts
tests/sample.spec.ts
+19
-0
No files found.
README.md
View file @
3dd42f5b
...
@@ -23,6 +23,10 @@ const ygomobileDeckUrl = deck.toYGOMobileDeckURL(); // YGOMobile Deck URL
...
@@ -23,6 +23,10 @@ const ygomobileDeckUrl = deck.toYGOMobileDeckURL(); // YGOMobile Deck URL
const
yetAnotherDeck3
=
YGOProDeck
.
fromYGOMobileDeckURL
(
ygomobileDeckUrl
);
// decode it back
const
yetAnotherDeck3
=
YGOProDeck
.
fromYGOMobileDeckURL
(
ygomobileDeckUrl
);
// decode it back
const
updateDeckPayload
=
deck
.
toUpdateDeckPayload
();
// payload for MSG_UPDATE_DECK
const
updateDeckPayload
=
deck
.
toUpdateDeckPayload
();
// payload for MSG_UPDATE_DECK
// decode it back, but a callback is needed for check if it's extra deck
// use SQLite3 is recommended
// by default, it would assume everything is main deck
const
yetAnotherDeck4
=
YGOProDeck
.
fromUpdateDeckPayload
(
updateDeckPayload
,
(
code
,
i
,
mainc
)
=>
i
>=
mainc
-
15
);
```
```
...
...
index.ts
View file @
3dd42f5b
import
{
fromBase64Url
,
toBase64Url
}
from
'
./src/base64
'
;
import
{
fromBase64Url
,
toBase64Url
}
from
'
./src/base64
'
;
import
{
BufferWriter
,
countItems
}
from
'
./src/utils
'
;
import
{
Buffer
Reader
,
Buffer
Writer
,
countItems
}
from
'
./src/utils
'
;
import
{
fromYdkeURL
,
toYdkeURL
}
from
'
./src/ydke
'
;
import
{
fromYdkeURL
,
toYdkeURL
}
from
'
./src/ydke
'
;
import
{
fromYGOMobileDeckURL
,
toYGOMobileDeckURL
}
from
'
./src/ygom
'
;
import
{
fromYGOMobileDeckURL
,
toYGOMobileDeckURL
}
from
'
./src/ygom
'
;
...
@@ -105,6 +105,32 @@ export default class YGOProDeck {
...
@@ -105,6 +105,32 @@ export default class YGOProDeck {
return
new
YGOProDeck
().
fromYdkString
(
str
);
return
new
YGOProDeck
().
fromYdkString
(
str
);
}
}
fromUpdateDeckPayload
(
buf
:
Uint8Array
,
isExtraDeckCard
:
(
code
:
number
,
i
:
number
,
mainc
:
number
)
=>
boolean
=
()
=>
false
)
{
const
reader
=
new
BufferReader
(
buf
);
const
mainc
=
reader
.
readUint32LE
();
const
sidec
=
reader
.
readUint32LE
();
this
.
main
=
[];
this
.
extra
=
[];
this
.
side
=
[];
for
(
let
i
=
0
;
i
<
mainc
;
i
++
)
{
const
id
=
reader
.
readUint32LE
();
if
(
isExtraDeckCard
(
id
,
i
,
mainc
))
{
this
.
extra
.
push
(
id
);
}
else
{
this
.
main
.
push
(
id
);
}
}
for
(
let
i
=
0
;
i
<
sidec
;
i
++
)
{
const
id
=
reader
.
readUint32LE
();
this
.
side
.
push
(
id
);
}
return
this
;
}
static
fromUpdateDeckPayload
(
buf
:
Uint8Array
,
isExtraDeckCard
:
(
code
:
number
)
=>
boolean
=
()
=>
false
)
{
return
new
YGOProDeck
().
fromUpdateDeckPayload
(
buf
,
isExtraDeckCard
);
}
toUpdateDeckPayload
()
{
toUpdateDeckPayload
()
{
const
cards
=
[...
this
.
main
,
...
this
.
extra
,
...
this
.
side
];
const
cards
=
[...
this
.
main
,
...
this
.
extra
,
...
this
.
side
];
const
writer
=
new
BufferWriter
(
cards
.
length
*
4
+
8
)
const
writer
=
new
BufferWriter
(
cards
.
length
*
4
+
8
)
...
...
src/utils.ts
View file @
3dd42f5b
...
@@ -5,50 +5,146 @@ export function countItems<T>(arr: T[]) {
...
@@ -5,50 +5,146 @@ export function countItems<T>(arr: T[]) {
}
}
return
map
;
return
map
;
}
}
abstract
class
BufferCursor
{
export
class
BufferWriter
{
buffer
:
Uint8Array
;
buffer
:
Uint8Array
;
pointer
=
0
;
pointer
=
0
;
constructor
(
bufOrLength
:
Uint8Array
|
number
)
{
if
(
typeof
bufOrLength
===
'
number
'
)
{
this
.
buffer
=
new
Uint8Array
(
bufOrLength
);
}
else
{
this
.
buffer
=
bufOrLength
;
}
}
/**
* 安全地将 pointer 向前移动指定字节数。
* @param bytes 要移动的字节数
* @returns 原来 pointer 的值
* @throws RangeError 如果越界
*/
protected
increasePointer
(
bytes
:
number
):
number
{
const
old
=
this
.
pointer
;
const
next
=
old
+
bytes
;
if
(
next
>
this
.
buffer
.
length
)
{
throw
new
RangeError
(
`Pointer overflow: tried to move to
${
next
}
, but buffer length is
${
this
.
buffer
.
length
}
`
);
}
this
.
pointer
=
next
;
return
old
;
}
}
export
class
BufferWriter
extends
BufferCursor
{
constructor
(
length
:
number
)
{
constructor
(
length
:
number
)
{
this
.
buffer
=
new
Uint8Array
(
length
);
super
(
length
);
}
}
writeUint32LE
(
value
:
number
)
{
writeUint32LE
(
value
:
number
)
{
this
.
buffer
[
this
.
pointer
++
]
=
value
&
0xff
;
const
idx
=
this
.
increasePointer
(
4
);
this
.
buffer
[
this
.
pointer
++
]
=
(
value
>>>
8
)
&
0xff
;
this
.
buffer
[
idx
]
=
value
&
0xff
;
this
.
buffer
[
this
.
pointer
++
]
=
(
value
>>>
16
)
&
0xff
;
this
.
buffer
[
idx
+
1
]
=
(
value
>>>
8
)
&
0xff
;
this
.
buffer
[
this
.
pointer
++
]
=
(
value
>>>
24
)
&
0xff
;
this
.
buffer
[
idx
+
2
]
=
(
value
>>>
16
)
&
0xff
;
this
.
buffer
[
idx
+
3
]
=
(
value
>>>
24
)
&
0xff
;
return
this
;
return
this
;
}
}
writeUint32BE
(
value
:
number
)
{
writeUint32BE
(
value
:
number
)
{
this
.
buffer
[
this
.
pointer
++
]
=
(
value
>>>
24
)
&
0xff
;
const
idx
=
this
.
increasePointer
(
4
);
this
.
buffer
[
this
.
pointer
++
]
=
(
value
>>>
16
)
&
0xff
;
this
.
buffer
[
idx
]
=
(
value
>>>
24
)
&
0xff
;
this
.
buffer
[
this
.
pointer
++
]
=
(
value
>>>
8
)
&
0xff
;
this
.
buffer
[
idx
+
1
]
=
(
value
>>>
16
)
&
0xff
;
this
.
buffer
[
this
.
pointer
++
]
=
value
&
0xff
;
this
.
buffer
[
idx
+
2
]
=
(
value
>>>
8
)
&
0xff
;
this
.
buffer
[
idx
+
3
]
=
value
&
0xff
;
return
this
;
return
this
;
}
}
writeUint16LE
(
value
:
number
)
{
writeUint16LE
(
value
:
number
)
{
this
.
buffer
[
this
.
pointer
++
]
=
value
&
0xff
;
const
idx
=
this
.
increasePointer
(
2
);
this
.
buffer
[
this
.
pointer
++
]
=
(
value
>>>
8
)
&
0xff
;
this
.
buffer
[
idx
]
=
value
&
0xff
;
this
.
buffer
[
idx
+
1
]
=
(
value
>>>
8
)
&
0xff
;
return
this
;
return
this
;
}
}
writeUint16BE
(
value
:
number
)
{
writeUint16BE
(
value
:
number
)
{
this
.
buffer
[
this
.
pointer
++
]
=
(
value
>>>
8
)
&
0xff
;
const
idx
=
this
.
increasePointer
(
2
);
this
.
buffer
[
this
.
pointer
++
]
=
value
&
0xff
;
this
.
buffer
[
idx
]
=
(
value
>>>
8
)
&
0xff
;
this
.
buffer
[
idx
+
1
]
=
value
&
0xff
;
return
this
;
return
this
;
}
}
writeUint8
(
value
:
number
)
{
writeUint8
(
value
:
number
)
{
this
.
buffer
[
this
.
pointer
++
]
=
value
&
0xff
;
const
idx
=
this
.
increasePointer
(
1
);
this
.
buffer
[
idx
]
=
value
&
0xff
;
return
this
;
return
this
;
}
}
writeString
(
str
:
string
)
{
writeString
(
str
:
string
)
{
for
(
let
i
=
0
;
i
<
str
.
length
;
i
++
)
{
for
(
let
i
=
0
;
i
<
str
.
length
;
i
++
)
{
this
.
buffer
[
this
.
pointer
++
]
=
str
.
charCodeAt
(
i
);
const
idx
=
this
.
increasePointer
(
1
);
this
.
buffer
[
idx
]
=
str
.
charCodeAt
(
i
);
}
}
return
this
;
return
this
;
}
}
}
}
export
class
BufferReader
extends
BufferCursor
{
constructor
(
buf
:
Uint8Array
)
{
super
(
buf
);
}
readUint32LE
():
number
{
const
idx
=
this
.
increasePointer
(
4
);
const
b
=
this
.
buffer
;
// >>>0 保证无符号输出
return
(
(
b
[
idx
]
)
|
(
b
[
idx
+
1
]
<<
8
)
|
(
b
[
idx
+
2
]
<<
16
)
|
(
b
[
idx
+
3
]
<<
24
)
)
>>>
0
;
}
readUint32BE
():
number
{
const
idx
=
this
.
increasePointer
(
4
);
const
b
=
this
.
buffer
;
return
(
(
b
[
idx
]
<<
24
)
|
(
b
[
idx
+
1
]
<<
16
)
|
(
b
[
idx
+
2
]
<<
8
)
|
(
b
[
idx
+
3
]
)
)
>>>
0
;
}
readUint16LE
():
number
{
const
idx
=
this
.
increasePointer
(
2
);
const
b
=
this
.
buffer
;
return
(
b
[
idx
]
|
(
b
[
idx
+
1
]
<<
8
));
}
readUint16BE
():
number
{
const
idx
=
this
.
increasePointer
(
2
);
const
b
=
this
.
buffer
;
return
((
b
[
idx
]
<<
8
)
|
b
[
idx
+
1
]);
}
readUint8
():
number
{
const
idx
=
this
.
increasePointer
(
1
);
return
this
.
buffer
[
idx
];
}
readString
(
length
:
number
):
string
{
let
s
=
''
;
for
(
let
i
=
0
;
i
<
length
;
i
++
)
{
const
idx
=
this
.
increasePointer
(
1
);
s
+=
String
.
fromCharCode
(
this
.
buffer
[
idx
]);
}
return
s
;
}
readRemaining
():
Uint8Array
{
const
remaining
=
this
.
buffer
.
length
-
this
.
pointer
;
const
idx
=
this
.
increasePointer
(
remaining
);
return
this
.
buffer
.
subarray
(
idx
,
this
.
buffer
.
length
);
}
}
tests/sample.spec.ts
View file @
3dd42f5b
import
YGOProDeck
from
'
..
'
;
import
YGOProDeck
from
'
..
'
;
import
{
BufferReader
}
from
'
../src/utils
'
;
const
deck
=
new
YGOProDeck
();
const
deck
=
new
YGOProDeck
();
deck
.
main
.
push
(
123
);
deck
.
main
.
push
(
123
);
...
@@ -86,4 +87,22 @@ describe('Sample test.', () => {
...
@@ -86,4 +87,22 @@ describe('Sample test.', () => {
expect
(
decoded
.
extra
).
toStrictEqual
(
deck
.
extra
);
expect
(
decoded
.
extra
).
toStrictEqual
(
deck
.
extra
);
expect
(
decoded
.
side
).
toStrictEqual
(
deck
.
side
);
expect
(
decoded
.
side
).
toStrictEqual
(
deck
.
side
);
});
});
it
(
'
should encode and decode update deck payload
'
,
()
=>
{
const
uri
=
'
http://deck.ourygo.top?name=%E7%99%BD%E9%93%B6%E5%9F%8E%E7%A0%81&ygotype=deck&v=1&d=J-xK4Mka02AuEAMf2dV6mj7aRemuJNQJK8BwrcEYh0MqOJqBJSgYqUwxPEVhOG8R18WWVKmzkT-xEdwxbmGVkkOdrVIpufaYI3Hs8oOrcya8Bi40h9G79iFW80rq-o6P-AHsusPY5nmvHLol0DIqEykESVlf6VSbxVJp-j7XZtTE0XvmJW80rqH28R4rgyRovOusVJzbutenYFBA_cyK6d3UWcQkJQlLjaroWavH-INFA56k5DQNWOQ1gpvxrKVBLgEk1olpolKmSgriramLlgtBK1EQ6C6oi94ZyHe7N6T7mqE6peds7mahrORP6A
'
;
const
deck
=
new
YGOProDeck
().
fromYGOMobileDeckURL
(
uri
);
const
updateDeckPayload
=
deck
.
toUpdateDeckPayload
();
const
bufferReader
=
new
BufferReader
(
updateDeckPayload
);
const
mainc
=
bufferReader
.
readUint32LE
();
const
sidec
=
bufferReader
.
readUint32LE
();
expect
(
mainc
).
toBe
(
58
+
15
);
expect
(
sidec
).
toBe
(
15
);
const
deckAgain
=
new
YGOProDeck
().
fromUpdateDeckPayload
(
updateDeckPayload
,
(
id
,
i
,
mainc
)
=>
i
>=
58
);
expect
(
deckAgain
.
main
).
toHaveLength
(
58
);
expect
(
deckAgain
.
extra
).
toHaveLength
(
15
);
expect
(
deckAgain
.
side
).
toHaveLength
(
15
);
expect
(
deckAgain
.
main
).
toStrictEqual
(
deck
.
main
);
expect
(
deckAgain
.
extra
).
toStrictEqual
(
deck
.
extra
);
expect
(
deckAgain
.
side
).
toStrictEqual
(
deck
.
side
);
})
});
});
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