Skip to content

Instantly share code, notes, and snippets.

@oelna
Created June 11, 2019 22:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oelna/4e131be515ded61735c614fc7c98b3d4 to your computer and use it in GitHub Desktop.
Save oelna/4e131be515ded61735c614fc7c98b3d4 to your computer and use it in GitHub Desktop.
Hearthstone decklist decode
#!/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