extends SceneTree # Headless gameplay test: run with # godot --headless -s res://tests/test_map_building_markers.gd # Forgejo issue #11: a building the player has placed must appear on the # world map. Without it the map showed explored chunks, planets and the # fleet, but nothing the player had actually built - so there was no way to # find your own base again once you had flown away from it. # # Buildings are not tied to a chunk (they are placed freely in space), so # they cannot ride along with the chunk markers and need their own pass. # # --headless has no GPU and draws no pixels, so this cannot assert on what # was rendered. It asserts on building_markers(), the step that turns # GameState.buildings into map-local marker data, which is the part that # _draw() then simply stamps out. # # Verifies: # 1. no buildings -> no markers (so a passing count is not just "always 3") # 2. every placed building produces exactly one marker # 3. markers land at the building's world position scaled into map space # 4. the three building types are told apart by colour, rather than all # being drawn as the same anonymous dot var scene: Node var game_state: Node var map_content: Node2D var stage: int = 0 const MOTHERSHIP_AT: Vector2 = Vector2(2000.0, -1200.0) const CRAFTER_AT: Vector2 = Vector2(-800.0, 400.0) const COMMAND_AT: Vector2 = Vector2(150.0, 3000.0) func _initialize() -> void: game_state = root.get_node("GameState") game_state.buildings.clear() game_state.extractors.clear() scene = load("res://world/Main.tscn").instantiate() root.add_child(scene) map_content = scene.get_node("UI/WorldMap/MapContent") func _process(_delta: float) -> bool: match stage: 0: # Nothing built yet: the map must show no building markers at all. var empty: Array = map_content.building_markers() if not empty.is_empty(): print("TEST_MAP_BUILDING_MARKERS: FAIL (%d markers with nothing built)" % empty.size()) quit(1) return true game_state.add_building(GameState.BUILDING_MOTHERSHIP, MOTHERSHIP_AT) game_state.add_building(GameState.BUILDING_SHIP_CRAFTER, CRAFTER_AT) game_state.add_building(GameState.BUILDING_COMMAND_CENTER, COMMAND_AT) stage = 1 return false 1: var markers: Array = map_content.building_markers() print("markers=%d for %d buildings" % [markers.size(), game_state.buildings.size()]) if markers.size() != 3: print("TEST_MAP_BUILDING_MARKERS: FAIL (expected one marker per building)") quit(1) return true var scale: float = map_content.WORLD_TO_LOCAL var expected: Dictionary = { GameState.BUILDING_MOTHERSHIP: MOTHERSHIP_AT * scale, GameState.BUILDING_SHIP_CRAFTER: CRAFTER_AT * scale, GameState.BUILDING_COMMAND_CENTER: COMMAND_AT * scale, } var colours: Array = [] for m in markers: if not expected.has(m.type): print("TEST_MAP_BUILDING_MARKERS: FAIL (unexpected marker type %s)" % m.type) quit(1) return true var want: Vector2 = expected[m.type] if m.position.distance_to(want) > 0.001: print("%s marker at %s, expected %s" % [m.type, m.position, want]) print("TEST_MAP_BUILDING_MARKERS: FAIL (marker is not where the building is)") quit(1) return true colours.append(m.color) # Three buildings drawn in one indistinguishable colour would # satisfy every check above and still be useless to read. if colours[0] == colours[1] or colours[1] == colours[2] or colours[0] == colours[2]: print("colours=%s" % [colours]) print("TEST_MAP_BUILDING_MARKERS: FAIL (building types are not visually distinct)") quit(1) return true print("all 3 markers positioned correctly, colours distinct: %s" % [colours]) print("TEST_MAP_BUILDING_MARKERS: PASS") quit(0) return true return false