@tool extends Node3D @export var clear_chunks: bool @export var generate_chunks: bool @export var chunk_size: int @export var world_size: Vector3i var chunks = {} @export var world_seed: int @export var noise_frequency: float @export var noise_threshold: float @export var cave_noise_frequency: float @export var cave_noise_threshold: float var noise var cave_noise var chunks_tagged_for_regen = [] var chunk_prototype = preload("res://chunk.tscn") func _ready() -> void: generate_chunks = true func _process(delta: float) -> void: if clear_chunks: clear_chunks = false clearChunks() if generate_chunks: noise = FastNoiseLite.new() noise.frequency = noise_frequency noise.seed = world_seed cave_noise = FastNoiseLite.new() cave_noise.frequency = cave_noise_frequency cave_noise.seed = world_seed generateChunks() generate_chunks = false for chunk in chunks_tagged_for_regen: chunk.generate_chunk() chunks_tagged_for_regen.clear() func clearChunks(): print("clearing chunk...") var children = get_children() for child in children: child.free() func generateChunks(): for x in range(world_size.x): for y in range(world_size.y): for z in range(world_size.z): generateChunk(Vector3i(x * chunk_size, y * chunk_size, z * chunk_size)) await Engine.get_main_loop().process_frame func generateChunk(pos: Vector3i): var chunk = chunk_prototype.instantiate() chunk.position = pos add_child(chunk) chunks[pos] = chunk chunk.init_blocks(chunk_size, pos) chunk.generate_chunk() func SetBlockAtPosition(pos: Vector3i, block_type: Block.BlockType): var chunk_pos = worldPosToChunkPos(pos) var local_pos = pos - chunk_pos if chunks.has(chunk_pos): chunks[chunk_pos].SetBlockAtPosition(local_pos, block_type) chunks_tagged_for_regen.append(chunks[chunk_pos]) var adjacent_chunks_masks = getAdjacentChunksFromBlockPos(local_pos) for adjacent_chunk_mask in adjacent_chunks_masks: var adjacent_chunk_pos = chunk_pos + adjacent_chunk_mask * chunk_size if chunks.has(adjacent_chunk_pos): chunks_tagged_for_regen.append(chunks[adjacent_chunk_pos]) func getAdjacentChunksFromBlockPos(pos: Vector3i): var chunk_masks = [] #adjacent to chunk on left if pos.x == 0: chunk_masks.append(Vector3i(-1, 0, 0)) # chunk below if pos.y == 0: chunk_masks.append(Vector3i(0, -1, 0)) # chunk behind if pos.z == 0: chunk_masks.append(Vector3i(0, 0, -1)) # chunk on the right if pos.x == chunk_size -1: chunk_masks.append(Vector3i(1, 0, 0)) # chunk above if pos.y == chunk_size -1: chunk_masks.append(Vector3i(0, 1, 0)) # chunk on the right if pos.z == chunk_size -1: chunk_masks.append(Vector3i(0, 0, 1)) return chunk_masks func worldPosToChunkPos(pos: Vector3i): return (pos / chunk_size) * chunk_size func GetBlock(pos: Vector3i, from_noise = false): var chunk_pos = worldPosToChunkPos(pos) var local_pos = pos - chunk_pos # there is air at edges of world if pos.x < 0 or pos.y < 0 or pos.z < 0 or pos.x >= world_size.x * chunk_size or pos.y >= world_size.y * chunk_size or pos.z >= world_size.z * chunk_size: return Block.BlockType.Air if not from_noise: if chunks.has(chunk_pos): return chunks[chunk_pos].GetBlockAtPosition(local_pos) # if ((noise.get_noise_2d(pos.x, pos.z) + 1) * chunk_size > pos.y + noise_threshold * 10) and (cave_noise.get_noise_3d(pos.x, pos.y, pos.z) > cave_noise_threshold): return Block.BlockType.Dirt else: return Block.BlockType.Air