diff --git a/game/scripts/main.gd b/game/scripts/main.gd index 39e6aed..67bd0bc 100644 --- a/game/scripts/main.gd +++ b/game/scripts/main.gd @@ -62,9 +62,9 @@ var _joining := "" ## The host's accepted guests when _process last looked. A new one ends a ## pause. var _known_guests := 0 -## Tiles whose burst of chips the own figure showed when it hit them, until -## the core reports that hit. Their burst is not shown a second time. -var _own_hits: Dictionary[Vector2i, bool] = {} +## How many own hits on each tile showed their burst of chips at once and +## are not reported by the core yet. Their burst is not shown a second time. +var _own_hits: Dictionary[Vector2i, int] = {} func _ready() -> void: @@ -310,6 +310,7 @@ func _on_notice(notice: Dictionary) -> void: resyncs += 1 _keep_diverged_recording() map_view.reload() + _own_hits.clear() hud.show_stone(session.item_count(GwSession.ITEM_STONE)) hud.flash("RESYNCED") else: @@ -409,7 +410,7 @@ func _apply(events: Array[Dictionary]) -> void: map_view.refresh_tile(tile) # The own hits showed their burst when they were made. if event["player"] == local: - _own_hits.erase(tile) + _own_hit_reported(tile) else: map_view.hit(tile) "tile_changed": @@ -417,7 +418,9 @@ func _apply(events: Array[Dictionary]) -> void: map_view.refresh_tile(tile) # The core does not say whose hit broke the tile; an own hit # showed its burst already. - if not _own_hits.erase(tile): + if _own_hits.has(tile): + _own_hits.erase(tile) + else: map_view.hit(tile) "item_gained": if event["player"] == local: @@ -465,7 +468,16 @@ func dig_at(tile: Vector2i) -> void: _next_dig_tick = session.tick() + GwSession.DIG_COOLDOWN_TICKS if MapView.SOLID.has(session.terrain_at(tile.x, tile.y)): map_view.hit(tile) - _own_hits[tile] = true + _own_hits[tile] = _own_hits.get(tile, 0) + 1 + + +## Counts one own hit on `tile` as reported by the core. +func _own_hit_reported(tile: Vector2i) -> void: + var left: int = _own_hits.get(tile, 0) - 1 + if left > 0: + _own_hits[tile] = left + else: + _own_hits.erase(tile) ## Writes the running world as the save. Returns false if nothing was diff --git a/game/tests/test_main.gd b/game/tests/test_main.gd index 45c51c9..f8222e2 100644 --- a/game/tests/test_main.gd +++ b/game/tests/test_main.gd @@ -406,3 +406,22 @@ func test_an_own_hit_that_breaks_the_rock_shows_its_burst_only_once() -> void: check_eq(main.session.terrain_at(rock.x, rock.y), GwSession.TERRAIN_GROUND, "three own hits break the rock") check_eq(main.map_view.burst_count(), 3, "one burst per own hit, none more when the rock breaks") _clean_up([directory]) + + +func test_own_hits_reported_late_show_no_second_burst() -> void: + var directory := TestFiles.temporary_dir("late") + var main := _start_main(directory) + main.play(false) + var rock: Vector2i = main.session.spawn_point() + Vector2i(7, -2) + main.dig_at(rock) + main._next_dig_tick = 0 + main.dig_at(rock) + # As for a guest: the report of the first hit comes after the second hit, + # and the second hit breaks the rock. + var reports: Array[Dictionary] = [ + {"type": "tile_hit", "player": main.session.local_player(), "x": rock.x, "y": rock.y}, + {"type": "tile_changed", "x": rock.x, "y": rock.y}, + ] + main._apply(reports) + check_eq(main.map_view.burst_count(), 2, "two own hits, two bursts") + _clean_up([directory])