blob: 5b1c2c037d1c5a4e7786a10e169f981bfbbf5b18 (
plain) (
tree)
|
|
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 && monument.loaded_chunk == null:
monument.loaded_chunk = coords
|