summaryrefslogblamecommitdiffstats
path: root/world/chunk/ChunkLoader.gd
blob: 0ea422a0264df957bfb3a9bd7073e93888fd29a8 (plain) (tree)
1
2
3
4
5
6
7



                
                                                   
                      
                     




                               
                
                  










                                            




                                                                     
 


                                         
                                


                                                                                            

                                  
                                                

                               










                                             
                    






                                                                                                   

                                                

                                                              
                                       



                                     

                                                                         
                                              
                                       
                                      



                                                                             


                                                  
                                      
                                  

                       








                                              

                                      
                             
                  






                                  

                                  




                                                               



                                                                                                                          


                                                 


                        
                                             





                                                         
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