Skip to content

Commit 3f601f4

Browse files
committed
Add support for Battlegrounds
This involves supporting games with an entity id that is not 1.
1 parent dac0a09 commit 3f601f4

4 files changed

Lines changed: 46 additions & 36 deletions

File tree

hslog/packets.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,9 @@ class CreateGame(Packet):
110110
power_type = PowerType.CREATE_GAME
111111

112112
class Player:
113-
def __init__(self, ts, id, player_id, hi, lo):
113+
def __init__(self, ts, entity, player_id, hi, lo):
114114
self.ts = ts
115-
self.entity = id
115+
self.entity = entity
116116
self.player_id = player_id
117117
self.hi = hi
118118
self.lo = lo

hslog/parser.py

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,6 @@
1313
from .utils import parse_enum, parse_tag
1414

1515

16-
def parse_entity_id(entity):
17-
if entity.isdigit():
18-
return int(entity)
19-
20-
if entity == tokens.GAME_ENTITY:
21-
# GameEntity is always 1
22-
return 1
23-
24-
sre = tokens.ENTITY_RE.match(entity)
25-
if sre:
26-
id = sre.groups()[0]
27-
return int(id)
28-
29-
3016
def parse_initial_tag(data):
3117
"""
3218
Parse \a data, a line formatted as tag=FOO value=BAR
@@ -121,9 +107,7 @@ def handle_data(self, ts, data):
121107
sre = tokens.GAME_ENTITY_RE.match(data)
122108
if not sre:
123109
raise RegexParsingError(data)
124-
id, = sre.groups()
125-
if int(id) != 1:
126-
raise ParsingError("GameEntity ID: Expected 1, got %r" % (id))
110+
self.register_game(ts, *sre.groups())
127111
elif opcode == "Player":
128112
self.flush()
129113
sre = tokens.PLAYER_ENTITY_RE.match(data)
@@ -255,10 +239,6 @@ def new_packet_tree(self, ts):
255239
# Messages
256240
def create_game(self, ts):
257241
self.new_packet_tree(ts)
258-
entity_id = 1
259-
self._game_packet = self._entity_packet = packets.CreateGame(ts, entity_id)
260-
self.register_packet(self._game_packet)
261-
return self._game_packet
262242

263243
def block_start(
264244
self, ts, entity, type, index, effectid, effectindex, target, suboption, trigger_keyword
@@ -298,29 +278,27 @@ def full_entity(self, ts, id, card_id):
298278
if self._creating_game:
299279
# First packet after create game should always be a FULL_ENTITY
300280
self._creating_game = False
301-
# It should always have ID 4
302-
if id != 4:
303-
raise ParsingError("Expected entity 4 after creating game, got %r" % (id))
304281

305-
# While we're at it, we check if we got an abnormal amount of players
282+
# Check if we got an abnormal amount of players
306283
player_count = len(self._game_packet.players)
307-
if player_count != 2:
308-
raise ParsingError("Expected exactly 2 players, got %r" % (player_count))
284+
if player_count < 2:
285+
msg = "Expected at least 2 players before the first entity, got %r"
286+
raise ParsingError(msg % (player_count))
309287

310288
return self._entity_packet
311289

312290
def full_entity_update(self, ts, entity, card_id):
313-
id = parse_entity_id(entity)
291+
id = self.parse_entity_id(entity)
314292
return self.full_entity(ts, id, card_id)
315293

316294
def show_entity(self, ts, entity, card_id):
317-
id = parse_entity_id(entity)
295+
id = self.parse_entity_id(entity)
318296
self._entity_packet = packets.ShowEntity(ts, id, card_id)
319297
self.register_packet(self._entity_packet)
320298
return self._entity_packet
321299

322300
def hide_entity(self, ts, entity, tag, value):
323-
id = parse_entity_id(entity)
301+
id = self.parse_entity_id(entity)
324302
tag, value = parse_tag(tag, value)
325303
if tag != GameTag.ZONE:
326304
raise ParsingError("HIDE_ENTITY got non-zone tag (%r)" % (tag))
@@ -337,7 +315,7 @@ def change_entity(self, ts, entity, card_id):
337315
def meta_data(self, ts, meta, data, info_count):
338316
meta = parse_enum(MetaDataType, meta)
339317
if meta == MetaDataType.JOUST:
340-
data = parse_entity_id(data)
318+
data = self.parse_entity_id(data)
341319
count = int(info_count)
342320
self._metadata_node = packets.MetaData(ts, meta, data, count)
343321
self.register_packet(self._metadata_node)
@@ -738,11 +716,23 @@ def register_packet(self, packet, node=None):
738716
self._packets._packet_counter += 1
739717
packet.packet_id = self._packets._packet_counter
740718

719+
def parse_entity_id(self, entity):
720+
if entity.isdigit():
721+
return int(entity)
722+
723+
if entity == tokens.GAME_ENTITY:
724+
return int(self._game_packet.entity)
725+
726+
sre = tokens.ENTITY_RE.match(entity)
727+
if sre:
728+
id = sre.groups()[0]
729+
return int(id)
730+
741731
def parse_entity_or_player(self, entity):
742732
if entity == "-1":
743733
return
744734

745-
id = parse_entity_id(entity)
735+
id = self.parse_entity_id(entity)
746736
if id is None:
747737
# Only case where an id is None is if it's a Player name
748738
id = self._packets.manager.get_player_by_name(entity)
@@ -751,6 +741,14 @@ def parse_entity_or_player(self, entity):
751741
def parse_method(self, m):
752742
return "%s.%s" % (self._game_state_processor, m)
753743

744+
def register_game(self, ts, id):
745+
id = int(id)
746+
# Use the timestamp from CREATE_GAME because it's earlier
747+
ts = self._packets.ts
748+
self._game_packet = self._entity_packet = packets.CreateGame(ts, id)
749+
self.register_packet(self._game_packet)
750+
return self._game_packet
751+
754752
def register_player(self, ts, id, player_id, hi, lo):
755753
id = int(id)
756754
player_id = int(player_id)

tests/test_logs.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,18 @@ def test_20457(parser):
3232
assert game.game.players[1].name == "Heigan l'Impuro"
3333

3434

35+
@pytest.mark.regression_suite
36+
def test_battlegrounds(parser):
37+
with open(logfile("36393_battlegrounds.power.log")) as f:
38+
parser.read(f)
39+
40+
assert len(parser.games) == 1
41+
packet_tree = parser.games[0]
42+
exporter = EntityTreeExporter(packet_tree)
43+
game = exporter.export()
44+
assert game.game.players[0].name == "BehEh#1355"
45+
46+
3547
@pytest.mark.regression_suite
3648
def test_change_def(parser):
3749
with open(logfile("20457_def_change.power.log")) as f:

tests/test_main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from hslog import LogParser
1212
from hslog.exceptions import ParsingError
1313
from hslog.export import FriendlyPlayerExporter
14-
from hslog.parser import parse_entity_id, parse_initial_tag
14+
from hslog.parser import parse_initial_tag
1515

1616
from .data import (
1717
CONTROLLER_CHANGE, EMPTY_GAME, FULL_ENTITY, INITIAL_GAME, INVALID_GAME,
@@ -244,7 +244,7 @@ def test_tag_change_unknown_entity_format():
244244
entity_format = (
245245
"[name=UNKNOWN ENTITY [cardType=INVALID] id=24 zone=DECK zonePos=0 cardId= player=1]"
246246
)
247-
id = parse_entity_id(entity_format)
247+
id = parser.parse_entity_id(entity_format)
248248
assert id == 24
249249

250250
data = "TAG_CHANGE Entity=%s tag=ZONE value=HAND" % (entity_format)

0 commit comments

Comments
 (0)