You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
58 lines
2.0 KiB
58 lines
2.0 KiB
class_name ChunkLoader |
|
extends Node2D |
|
|
|
@export var load_distance := 3 |
|
@export var unload_distance := 4 |
|
|
|
signal start_tracking(chunk: Chunk) |
|
signal stop_tracking (chunk: Chunk) |
|
|
|
var tracked_chunks: Dictionary[Vector2i, Variant] # value is unused |
|
|
|
# TODO: This is a pretty naive implementation, calling this every |
|
# update regardless of whether or how far the players moved. |
|
func _process(delta: float) -> void: |
|
if not multiplayer.is_server(): return |
|
var loader_chunk_pos := Chunk.pos_from_vec(global_position) |
|
|
|
# All currently tracked chunks start out in this dictionary. |
|
# Ones outside of `unload_distance` are removed in the loop. |
|
var out_of_range: Dictionary[Vector2i, Variant] = tracked_chunks.duplicate() |
|
|
|
var chunk_range := range(-unload_distance, unload_distance + 1) |
|
for x in chunk_range: |
|
for y in chunk_range: |
|
var chunk_pos := loader_chunk_pos + Vector2i(x, y) |
|
out_of_range.erase(chunk_pos) |
|
if tracked_chunks.has(chunk_pos): continue |
|
|
|
# Check to see is chunk is in `load_distance`. |
|
var in_load_range := (absi(x) <= load_distance) and ((absi(y) <= load_distance)) |
|
if not in_load_range: continue # it's not |
|
|
|
var chunk := Game.WORLD.get_or_create_chunk(chunk_pos) |
|
tracked_chunks[chunk_pos] = null |
|
chunk.tracked_by[self] = null |
|
start_tracking.emit(chunk) |
|
|
|
# Untrack any chunks outside of `unload_distance`. |
|
for chunk_pos in out_of_range: _forget(chunk_pos, true) |
|
|
|
func _exit_tree() -> void: |
|
for chunk_pos in tracked_chunks: _forget(chunk_pos, false) |
|
tracked_chunks.clear() |
|
|
|
func _forget(chunk_pos: Vector2i, emit_signal: bool) -> void: |
|
var chunk := Game.WORLD.get_chunk_or_null(chunk_pos) |
|
tracked_chunks.erase(chunk_pos) |
|
chunk.tracked_by.erase(self) |
|
|
|
if emit_signal: |
|
stop_tracking.emit(chunk) |
|
|
|
# FIXME: This is currently the only way a chunk gets removed: |
|
# When a player tracks it and stops tracking it. However, |
|
# there's other ways a chunk may be created. Consider this! |
|
if chunk.tracked_by.is_empty(): |
|
chunk.get_parent().remove_child(chunk) |
|
chunk.queue_free()
|
|
|