Saving and loading chunks actually works now
This commit is contained in:
174
game/world.odin
174
game/world.odin
@@ -4,9 +4,10 @@ import rl "vendor:raylib"
|
||||
import "core:fmt"
|
||||
import "core:os"
|
||||
import "core:path/filepath"
|
||||
import "core:mem"
|
||||
|
||||
CELL_SIZE :: 16
|
||||
CHUNK_SIZE :: 32
|
||||
CHUNK_SIZE :: 5
|
||||
WORLD_DATA_PATH :: "data/worlds"
|
||||
|
||||
World :: struct {
|
||||
@@ -61,105 +62,97 @@ save_world :: proc(w:^World) {
|
||||
}
|
||||
}
|
||||
|
||||
serialize_chunk :: proc(c:^Chunk) -> []byte {
|
||||
data : [dynamic]byte
|
||||
|
||||
// Position
|
||||
pos_bytes := serialize_vec2i(c.position)
|
||||
append(&data, ..pos_bytes[:])
|
||||
|
||||
// Tiles
|
||||
for y in 0..<CHUNK_SIZE {
|
||||
for x in 0..<CHUNK_SIZE {
|
||||
tile_bytes := serialize_tile(c.tiles[x][y])
|
||||
fmt.printfln("Serialized tile size: %v", len(tile_bytes))
|
||||
append(&data, ..tile_bytes[:])
|
||||
}
|
||||
}
|
||||
|
||||
fmt.printfln("Serialized chunk size: %v", len(data)) // Print final serialized size
|
||||
fmt.printfln("Before serialization, Chunk position: %v", c.position)
|
||||
return data[:]
|
||||
}
|
||||
|
||||
|
||||
deserialize_chunk :: proc(data: []byte) -> Chunk {
|
||||
chunk: Chunk
|
||||
|
||||
// Position
|
||||
chunk.position = deserialize_vec2i(data[0:8])
|
||||
|
||||
// Tiles
|
||||
offset := 8
|
||||
tile_size := size_of(Tile)
|
||||
|
||||
// Check total expected size of data
|
||||
expected_size := offset + (CHUNK_SIZE * CHUNK_SIZE * tile_size)
|
||||
if len(data) != expected_size {
|
||||
fmt.printfln("Error: Data size mismatch. Expected size: %v, Actual size: %v", expected_size, len(data))
|
||||
fmt.printfln("Chunk position: %v", chunk.position)
|
||||
|
||||
return chunk // Return empty or invalid chunk to handle the error.
|
||||
}
|
||||
|
||||
for y in 0..<CHUNK_SIZE {
|
||||
for x in 0..<CHUNK_SIZE {
|
||||
start := offset + (y * CHUNK_SIZE + x) * tile_size
|
||||
end := start + tile_size
|
||||
|
||||
fmt.printfln("Start:%v, End:%v", start, end)
|
||||
|
||||
if end > len(data) {
|
||||
fmt.printfln("Out of bounds access. Start:%v, End:%v | Data Length: %v", start, end, len(data))
|
||||
break
|
||||
}
|
||||
|
||||
chunk.tiles[x][y] = deserialize_tile(data[start:end])
|
||||
}
|
||||
}
|
||||
|
||||
fmt.printfln("Expected chunk size: %v | Serialized chunk data size: %v", size_of(Chunk), len(data))
|
||||
|
||||
return chunk
|
||||
}
|
||||
|
||||
|
||||
save_chunk :: proc(c:^Chunk, w:^World) {
|
||||
chunk_dir := fmt.tprintf("%v/%v", w.data_dir, "chunks")
|
||||
if !os.is_dir(chunk_dir) {
|
||||
os.make_directory(chunk_dir)
|
||||
}
|
||||
|
||||
filename := fmt.tprintf("%v/%v_%v.chunk", chunk_dir, c.position.x, c.position.y)
|
||||
|
||||
data := serialize_chunk(c)
|
||||
fmt.printfln("Saving chunk: %v", filename)
|
||||
|
||||
fmt.printfln("Writing chunk data: %v bytes", len(data))
|
||||
data := make([dynamic]u8)
|
||||
|
||||
|
||||
err := os.write_entire_file_or_err(filename, data)
|
||||
// Append Position
|
||||
for byte in transmute([size_of(int)]u8)c.position.x {append(&data, byte)}
|
||||
for byte in transmute([size_of(int)]u8)c.position.y {append(&data, byte)}
|
||||
|
||||
if err != nil {
|
||||
fmt.printfln("Failed to save chunk: %v", err)
|
||||
// Append Tiles
|
||||
for row in &c.tiles {
|
||||
for tile in row {
|
||||
for byte in transmute([size_of(int)]u8)tile.tilemap_pos.x {append(&data, byte)}
|
||||
for byte in transmute([size_of(int)]u8)tile.tilemap_pos.y {append(&data, byte)}
|
||||
for byte in transmute([4]u8)tile.color {append(&data, byte)}
|
||||
for byte in transmute([size_of(TileType)]u8)tile.type {append(&data, byte)}
|
||||
for byte in transmute([size_of(InteractionType)]u8)tile.interaction {append(&data, byte)}
|
||||
for byte in transmute([size_of(ResourceType)]u8)tile.resource {append(&data, byte)}
|
||||
}
|
||||
}
|
||||
|
||||
err := os.write_entire_file_or_err(filename, data[:])
|
||||
|
||||
}
|
||||
|
||||
load_chunk :: proc(pos:Vec2i, w:^World) -> Chunk {
|
||||
chunk_dir := fmt.tprintf("%v/%v", w.data_dir, "chunks")
|
||||
if !os.is_dir(chunk_dir) {
|
||||
|
||||
filename := fmt.tprintf("%v/%v_%v.chunk", chunk_dir, pos.x, pos.y)
|
||||
|
||||
data, err := os.read_entire_file_from_filename_or_err(filename)
|
||||
if err != nil {
|
||||
fmt.printfln("No chunk %v found, generating new chunk", pos)
|
||||
chunk := generate_chunk(pos)
|
||||
save_chunk(&chunk, w)
|
||||
return chunk
|
||||
}
|
||||
|
||||
filename := fmt.tprintf("%v/%v_%v.chunk", chunk_dir, pos.x, pos.y)
|
||||
|
||||
data, err := os.read_entire_file_from_filename_or_err(filename)
|
||||
chunk: Chunk
|
||||
offset := 0
|
||||
|
||||
if err != nil {
|
||||
fmt.printfln("Chunk %v file does not exist, creating new chunk", pos)
|
||||
return generate_chunk(pos)
|
||||
}
|
||||
// Load Position
|
||||
mem.copy(transmute([^]u8)&chunk.position.x, &data[offset], size_of(int))
|
||||
offset += size_of(int)
|
||||
mem.copy(transmute([^]u8)&chunk.position.y, &data[offset], size_of(int))
|
||||
offset += size_of(int)
|
||||
|
||||
|
||||
// // Load Tiles
|
||||
// for row in &chunk.tiles {
|
||||
// for &tile in row {
|
||||
// mem.copy(transmute([^]u8)tile.tilemap_pos.x, &data[offset], size_of(int))
|
||||
// offset += size_of(int)
|
||||
// mem.copy(transmute([^]u8)tile.tilemap_pos.y, &data[offset], size_of(int))
|
||||
// offset += size_of(int)
|
||||
|
||||
// //Color
|
||||
// tile.color = {}
|
||||
|
||||
//
|
||||
// }
|
||||
// }
|
||||
|
||||
// Load tiles
|
||||
for row_index := 0; row_index < len(chunk.tiles); row_index += 1 {
|
||||
for tile_index := 0; tile_index < len(chunk.tiles[row_index]); tile_index += 1 {
|
||||
tile := &chunk.tiles[row_index][tile_index] // Get address of tile
|
||||
mem.copy(&tile.tilemap_pos.x, &data[offset], size_of(int))
|
||||
offset += size_of(int)
|
||||
mem.copy(&tile.tilemap_pos.y, &data[offset], size_of(int))
|
||||
offset += size_of(int)
|
||||
|
||||
// Load color
|
||||
color_temp: [4]u8
|
||||
mem.copy(&color_temp, &data[offset], 4)
|
||||
tile.color = color_temp
|
||||
offset += 4
|
||||
|
||||
mem.copy(&tile.type, &data[offset], size_of(TileType))
|
||||
offset += size_of(TileType)
|
||||
mem.copy(&tile.interaction, &data[offset], size_of(InteractionType))
|
||||
offset += size_of(InteractionType)
|
||||
mem.copy(&tile.resource, &data[offset], size_of(ResourceType))
|
||||
offset += size_of(ResourceType)
|
||||
}
|
||||
}
|
||||
|
||||
return chunk
|
||||
|
||||
return deserialize_chunk(data)
|
||||
}
|
||||
|
||||
unload_chunk :: proc(pos:Vec2i, w:^World) {
|
||||
@@ -170,7 +163,6 @@ unload_chunk :: proc(pos:Vec2i, w:^World) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
generate_chunk :: proc(pos:Vec2i) -> Chunk {
|
||||
chunk := Chunk {position = pos}
|
||||
|
||||
@@ -181,7 +173,7 @@ generate_chunk :: proc(pos:Vec2i) -> Chunk {
|
||||
tilemap_pos = {0,2},
|
||||
interaction = .NOTHING,
|
||||
resource = .NOTHING,
|
||||
color = rl.GREEN
|
||||
color = {0,255,0,255}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -234,6 +226,14 @@ set_chunk_tile :: proc(c:^Chunk, t:Tile, pos:Vec2i) {
|
||||
c.tiles[pos.x][pos.y] = t
|
||||
}
|
||||
|
||||
set_tile :: proc(w:^World, t:Tile, p:Vec2i) {
|
||||
chunk := get_chunk_from_world_pos(w, vec2i_to_vec2(p))
|
||||
|
||||
set_chunk_tile(chunk, t, get_local_chunk_pos(p))
|
||||
|
||||
save_chunk(chunk, w)
|
||||
}
|
||||
|
||||
draw_world :: proc(w:^World) {
|
||||
for chunk_pos, chunk in w.chunks {
|
||||
for x in 0..<CHUNK_SIZE {
|
||||
@@ -244,7 +244,7 @@ draw_world :: proc(w:^World) {
|
||||
pos := rl.Vector2{f32(world_x * CELL_SIZE), f32(world_y * CELL_SIZE)}
|
||||
|
||||
if tile.type != .NOTHING {
|
||||
draw_tile(vec2i_to_vec2(tile.tilemap_pos), pos, tile.color)
|
||||
draw_tile(vec2i_to_vec2(tile.tilemap_pos), pos, rl.Color(tile.color))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user