extends Node2D # Entity renderer — manages entity sprites under the Entities node # Creates/updates/removes ColorRect children based on entity data # Entity format (from Protocol): {entity_id, x, y, z, kind: {variant, data}} const TILE_SIZE: int = 32 const ENTITY_SIZE: int = 24 const ENTITY_OFFSET: float = (TILE_SIZE - ENTITY_SIZE) / 2.0 # center within tile var entity_nodes: Dictionary = {} # entity_id -> Node2D mapping func _ready() -> void: print("EntityRenderer: Initialized") # Update entities from snapshot data func update_entities(entities: Array) -> void: var active_ids: Array = [] # Create or update entities for entity_data in entities: if not entity_data.has("entity_id"): continue var entity_id = entity_data.entity_id active_ids.append(entity_id) # Create entity node if it doesn't exist if not entity_nodes.has(entity_id): _create_entity_node(entity_id, entity_data) else: _update_entity_node(entity_id, entity_data) # Remove entities that are no longer visible var ids_to_remove: Array = [] for entity_id in entity_nodes.keys(): if entity_id not in active_ids: ids_to_remove.append(entity_id) for entity_id in ids_to_remove: _remove_entity_node(entity_id) # Create a new entity node (placeholder visual) func _create_entity_node(entity_id: int, entity_data: Dictionary) -> void: var entity_node = ColorRect.new() entity_node.name = "Entity_" + str(entity_id) entity_node.size = Vector2(ENTITY_SIZE, ENTITY_SIZE) entity_node.pivot_offset = Vector2(ENTITY_SIZE / 2.0, ENTITY_SIZE / 2.0) # Color based on entity kind (from Protocol decoded format) var kind_variant: String = entity_data.get("kind", {}).get("variant", "") match kind_variant: "Npc": entity_node.color = Color(0.3, 0.6, 0.9) # Blue for NPCs "Player": entity_node.color = Color(0.88, 0.91, 1.0) # Light blue for player _: entity_node.color = Color(0.8, 0.8, 0.8) # Gray for unknown add_child(entity_node) entity_nodes[entity_id] = entity_node _update_entity_node(entity_id, entity_data) # Update an existing entity node func _update_entity_node(entity_id: int, entity_data: Dictionary) -> void: if not entity_nodes.has(entity_id): return var entity_node = entity_nodes[entity_id] # Update position from x, y fields (Protocol format), centered within tile if entity_data.has("x") and entity_data.has("y"): entity_node.position = Vector2( entity_data.x * TILE_SIZE + ENTITY_OFFSET, entity_data.y * TILE_SIZE + ENTITY_OFFSET ) # Remove an entity node func _remove_entity_node(entity_id: int) -> void: if not entity_nodes.has(entity_id): return var entity_node = entity_nodes[entity_id] entity_node.queue_free() entity_nodes.erase(entity_id)