Created
June 11, 2019 22:47
-
-
Save oelna/4e131be515ded61735c614fc7c98b3d4 to your computer and use it in GitHub Desktop.
Hearthstone decklist decode
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# modified for brevity from https://github.com/HearthSim/python-hearthstone/blob/master/hearthstone/deckstrings.py | |
import base64 | |
from io import BytesIO | |
from typing import IO, List, Tuple | |
DECKSTRING_VERSION = 1 | |
CardList = List[int] | |
CardIncludeList = List[Tuple[int, int]] | |
def _read_varint(stream: IO) -> int: | |
shift = 0 | |
result = 0 | |
while True: | |
c = stream.read(1) | |
if c == "": | |
raise EOFError("Unexpected EOF while reading varint") | |
i = ord(c) | |
result |= (i & 0x7f) << shift | |
shift += 7 | |
if not (i & 0x80): | |
break | |
return result | |
def _write_varint(stream: IO, i: int) -> int: | |
buf = b"" | |
while True: | |
towrite = i & 0x7f | |
i >>= 7 | |
if i: | |
buf += bytes((towrite | 0x80, )) | |
else: | |
buf += bytes((towrite, )) | |
break | |
return stream.write(buf) | |
def parse_deckstring(deckstring) -> Tuple[CardIncludeList, CardList, format]: | |
decoded = base64.b64decode(deckstring) | |
data = BytesIO(decoded) | |
if data.read(1) != b"\0": | |
raise ValueError("Invalid deckstring") | |
version = _read_varint(data) | |
if version != DECKSTRING_VERSION: | |
raise ValueError("Unsupported deckstring version %r" % (version)) | |
format = _read_varint(data) | |
try: | |
format = format | |
except ValueError: | |
raise ValueError("Unsupported FormatType in deckstring %r" % (format)) | |
heroes: CardList = [] | |
num_heroes = _read_varint(data) | |
for i in range(num_heroes): | |
heroes.append(_read_varint(data)) | |
cards: CardIncludeList = [] | |
num_cards_x1 = _read_varint(data) | |
for i in range(num_cards_x1): | |
card_id = _read_varint(data) | |
cards.append((card_id, 1)) | |
num_cards_x2 = _read_varint(data) | |
for i in range(num_cards_x2): | |
card_id = _read_varint(data) | |
cards.append((card_id, 2)) | |
num_cards_xn = _read_varint(data) | |
for i in range(num_cards_xn): | |
card_id = _read_varint(data) | |
count = _read_varint(data) | |
cards.append((card_id, count)) | |
return cards, heroes, format | |
def write_deckstring(cards: CardIncludeList, heroes: CardList, format: format) -> str: | |
data = BytesIO() | |
data.write(b"\0") | |
_write_varint(data, DECKSTRING_VERSION) | |
_write_varint(data, int(format)) | |
if len(heroes) != 1: | |
raise ValueError("Unsupported hero count %i" % (len(heroes))) | |
_write_varint(data, len(heroes)) | |
for hero in heroes: | |
_write_varint(data, hero) | |
cards_x1, cards_x2, cards_xn = trisort_cards(cards) | |
for cardlist in cards_x1, cards_x2: | |
_write_varint(data, len(cardlist)) | |
for cardid, _ in cardlist: | |
_write_varint(data, cardid) | |
_write_varint(data, len(cards_xn)) | |
for cardid, count in cards_xn: | |
_write_varint(data, cardid) | |
_write_varint(data, count) | |
encoded = base64.b64encode(data.getvalue()) | |
return encoded.decode("utf-8") | |
deckstring = 'AAEBAc2xAgjAAe0E7QX3DdYRh6wC8fsCoIADC8kDqwTLBPsMhRDH0wKW6AK0/ALNiQPXiQOfmwMA' | |
print(parse_deckstring(deckstring)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment