summaryrefslogtreecommitdiffstats
path: root/world/chunk/ChunkLoader.gd
diff options
context:
space:
mode:
Diffstat (limited to 'world/chunk/ChunkLoader.gd')
-rw-r--r--world/chunk/ChunkLoader.gd131
1 files changed, 131 insertions, 0 deletions
diff --git a/world/chunk/ChunkLoader.gd b/world/chunk/ChunkLoader.gd
new file mode 100644
index 0000000..0ea422a
--- /dev/null
+++ b/world/chunk/ChunkLoader.gd
@@ -0,0 +1,131 @@
+extends Node
+
+var world = null
+
+var Chunk = preload("res://world/chunk/Chunk.tscn")
+var loaded_chunks = {}
+var freed_chunks = {}
+var chunk_thread = Thread.new()
+var mtx = Mutex.new()
+var sgnl = Semaphore.new()
+var exit = false
+var chunk_to_load = null
+var chunk_to_len
+var chunk_to_dummy
+
+func _ready():
+ chunk_thread.start(self, "chunk_loader")
+
+func _exit_tree():
+ mtx.lock()
+ exit = true
+ sgnl.post()
+ mtx.unlock()
+ chunk_thread.wait_to_finish()
+
+func v2_coords(coords:Vector3):
+ return Vector2(coords.x,coords.z)
+
+func chunk_coords(coords:Vector2):
+ return coords.snapped(Vector2(world.chunk_size,world.chunk_size))
+
+func v3_coords(coords:Vector2):
+ return Vector3(coords.x,0.0,coords.y)
+
+func free_chunk(coords:Vector2):
+ var monument = ChunkGen.get_monument_at_chunk(coords)
+ if monument != null && monument.loaded_chunk != null && monument.loaded_chunk == coords:
+ return
+ if !loaded_chunks.has(coords):
+ return
+ freed_chunks[coords] = loaded_chunks[coords]
+ loaded_chunks.erase(coords)
+
+func clean_chunks():
+ var cleaned = {}
+ for chunk in freed_chunks.keys():
+ var c = freed_chunks[chunk].get_ref()
+ if c == null:
+ cleaned[chunk] = c
+ continue
+ c.queue_free()
+ for chunk in cleaned.keys():
+ freed_chunks.erase(chunk)
+
+func chunk_update():
+ var chunks = {}
+ var gen_center = -v2_coords(world.get_node("Chunks").transform.origin)
+ var gen_radius = world.lod_distance
+ var gen_radius_rounded = stepify(gen_radius, world.chunk_size)
+ for x in range(-gen_radius_rounded, gen_radius_rounded+world.chunk_size, world.chunk_size):
+ for y in range(-gen_radius_rounded, gen_radius_rounded+world.chunk_size, world.chunk_size):
+ var gen_coords = Vector2(x,y)
+ var coords_len = gen_coords.length()
+ if coords_len > gen_radius:
+ continue
+ var coords = chunk_coords(gen_coords + gen_center)
+ chunks[coords] = coords_len
+ var closest_unloaded_chunk = null
+ var closest_len = 0.0
+ for chunk in chunks.keys():
+ if !loaded_chunks.has(chunk):
+ var chunk_len = chunks[chunk]
+ if closest_unloaded_chunk == null || closest_len > chunk_len:
+ closest_unloaded_chunk = chunk
+ closest_len = chunk_len
+ if closest_unloaded_chunk != null:
+ var dummy = false
+ var monument = ChunkGen.get_monument_at_chunk(closest_unloaded_chunk)
+ if monument != null && monument.loaded_chunk != null:
+ dummy = true
+ mtx.lock()
+ if chunk_to_load == null:
+ chunk_to_load = closest_unloaded_chunk
+ chunk_to_len = closest_len
+ chunk_to_dummy = dummy
+ sgnl.post()
+ mtx.unlock()
+ for monument in ChunkGen.monuments:
+ if monument.loaded_chunk != null:
+ var loaded = false
+ for chunk in chunks.keys():
+ if monument.chunks.has(chunk):
+ loaded = true
+ break
+ if !loaded:
+ monument.loaded_chunk = null
+ for chunk in loaded_chunks.keys():
+ if !chunks.has(chunk):
+ free_chunk(chunk)
+ clean_chunks()
+
+func chunk_loader():
+ while true:
+ sgnl.wait()
+ mtx.lock()
+ var x = exit
+ var coords = chunk_to_load
+ var lod = chunk_to_len
+ var dummy = chunk_to_dummy
+ mtx.unlock()
+ if x:
+ break
+ var chunk = Chunk.instance()
+ chunk.transform.origin = Vector3(coords.x,0.0,coords.y)
+ lod -= world.chunk_size
+ var tmp = world.get_node("Chunk")
+ chunk.lod = tmp.LOD.CLOSE if lod <= world.lod_close else tmp.LOD.MID if lod <= world.lod_mid else tmp.LOD.DISTANCE
+ ChunkGen.gen_chunk(chunk,dummy)
+ self.call_deferred("finish_chunk", chunk)
+
+func finish_chunk(chunk):
+ mtx.lock()
+ chunk_to_load = null
+ mtx.unlock()
+ world.get_node("Chunks").add_child(chunk)
+ var coords = v2_coords(chunk.transform.origin)
+ loaded_chunks[coords] = weakref(chunk)
+ var monument = ChunkGen.get_monument_at_chunk(coords)
+ if monument != null:
+ if monument.loaded_chunk == null:
+ monument.loaded_chunk = coords