class_name Chunk extends Node2D const SIZE := 32 # blocks ## Emitted once after a chunk has been marked dirty. signal clean var chunk_pos: Vector2i var dirty := false var tracked_by: Dictionary[ChunkLoader, Variant] # value is unused func get_players_tracking() -> Array[Player]: var result: Array[Player] for chunk_loader in tracked_by: var player := chunk_loader.get_parent() as Player if player: result.append(player) return result func _init(chunk_pos: Vector2i) -> void: self.chunk_pos = chunk_pos name = "Chunk %s" % chunk_pos position = (Vector2(chunk_pos) + Vector2.ONE / 2) * (Block.SIZE * SIZE) func _process(delta: float) -> void: if not dirty: return clean.emit() dirty = false static func load(buffer: StreamBuffer) -> Chunk: var chunk_pos := buffer.read_vector2i_16() var chunk := Chunk.new(chunk_pos) var layer_count := buffer.read_int8() for i in layer_count: var layer_name := buffer.read_string() var layer := Layers.load(layer_name, buffer) chunk.add_child(layer) return chunk func save(buffer: StreamBuffer) -> void: buffer.write_vector2i_16(chunk_pos) buffer.write_int8(get_child_count()) for layer in get_children(): buffer.write_string(layer.name) layer.save(buffer) func get_layer_or_null(script: GDScript) -> Node: var layer_name := str(script.get_global_name()) var layer := get_node_or_null(layer_name) return layer func get_or_create_layer(script: GDScript) -> Node: var layer_name := str(script.get_global_name()) var layer := get_node_or_null(layer_name) if layer: return layer # We actually want to create is the inner "Layer" script. var layer_script: GDScript = script.get_script_constant_map().get("Layer") layer = layer_script.new() layer.name = layer_name add_child(layer) return layer ## Returns the chunk position as a `Vector2i` from the given global position. static func pos_from_vec(pos: Vector2) -> Vector2i: return Vector2i((pos / (Block.SIZE * SIZE)).floor()) ## Returns the global position at the center of the chunk with the given position. static func pos_to_center(chunk_pos: Vector2i) -> Vector2: return (Vector2(chunk_pos) + Vector2.ONE / 2) * (Block.SIZE * SIZE) ## Creates an integer index from a chunk-local block position that can be used to index into an array. static func array_index(local_pos: Vector2i) -> int: assert((local_pos.x >= 0) and (local_pos.x < Chunk.SIZE)) assert((local_pos.y >= 0) and (local_pos.y < Chunk.SIZE)) # Using `posmod` ensures `local_pos` is valid, and this returns a valid index. return posmod(local_pos.x, Chunk.SIZE) + posmod(local_pos.y, Chunk.SIZE) * Chunk.SIZE