From c95e947d90a02091aef4e63693ce3205fdfba3b6 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Sat, 13 Apr 2024 22:59:07 +0100 Subject: move things --- server/save_load.ha | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 server/save_load.ha (limited to 'server/save_load.ha') diff --git a/server/save_load.ha b/server/save_load.ha new file mode 100644 index 0000000..cf82a0d --- /dev/null +++ b/server/save_load.ha @@ -0,0 +1,96 @@ +use bytes; +use errors; +use fmt; +use fs; +use io; +use os; +use strings; + +use drawing; +use drawing::{pos}; + +// caller should free return value +fn filename_from_world_pos(pos: pos) str = + fmt::asprintf("./c.{}.{}.ppm",pos.0,pos.1); + +fn save_world(state: *server_state) (void | fs::error) = { + fmt::printfln("saving world!")!; + for (const pic &.. state.pictures) { + const filename = filename_from_world_pos(pic.world_pos); + fmt::printfln("\t-> {}",filename)!; + defer free(filename); + + const mode = fs::mode::USER_RW | fs::mode::GROUP_RW; + const file = os::create(filename, mode)?; + defer io::close(file): void; + + fmt::fprintf(file, "P6\n{} {}\n{}\n", pic.w, pic.h, 255)?; + + let buf: []u8 = alloc([0...],3*pic.w*pic.h); + defer free(buf); + for (let i = 0z; i < pic.w * pic.h; i += 1) { + const px = pic.d[i]; + buf[3*i ] = ((px>>16)&0xff): u8; + buf[3*i+1] = ((px>>8) &0xff): u8; + buf[3*i+2] = ((px) &0xff): u8; + }; + io::writeall(file, buf)?; + }; + +}; + +fn new_picture(world_pos: pos) drawing::picture = { + let picture_buf: []u32 = alloc([0xffffff...], CHUNKSIZE*CHUNKSIZE); + return drawing::picture { + w = CHUNKSIZE, + h = CHUNKSIZE, + d = picture_buf: *[*]u32, + world_pos = world_pos, + }; +}; + +type bad_header = !void; + +// loads the chunk at the given position from the filesystem, +// or, if no file is found, creates a fresh new chunk +fn load_picture_from_file(world_pos: pos) (drawing::picture | fs::error | bad_header) = { + const filename = filename_from_world_pos(world_pos); + defer free(filename); + const file = match (os::open(filename)) { + case let f: io::file => yield f; + case errors::noentry => return new_picture(world_pos); + case let e: fs::error => return e; + }; + fmt::printfln("reading from {}",filename)!; + defer { + fmt::printfln("closing {}",filename)!; + match (io::close(file)) { + case let err: io::error => fmt::println("error",io::strerror(err))!; + case => yield; + }; + }; + + const header = fmt::asprintf("P6\n{} {}\n{}\n",CHUNKSIZE,CHUNKSIZE,255); + defer free(header); + const header_bytes = strings::toutf8(header); + let header_buf: []u8 = alloc([0...],len(header_bytes)); + defer free(header_buf); + io::readall(file, header_buf)?; + if (!bytes::equal(header_buf, header_bytes)) return bad_header; + + let file_buf: []u8 = alloc([0...], 3*CHUNKSIZE*CHUNKSIZE); + defer free(file_buf); + io::readall(file, file_buf)?; + let picture_buf: []u32 = alloc([0...], CHUNKSIZE*CHUNKSIZE); + for (let i = 0z; i < len(picture_buf); i += 1) { + picture_buf[i] = (file_buf[3*i]:u32<<16) + |(file_buf[3*i+1]:u32<<8) + |(file_buf[3*i+2]:u32); + }; + return drawing::picture { + w = CHUNKSIZE, + h = CHUNKSIZE, + d = picture_buf: *[*]u32, + world_pos = world_pos, + }; +}; -- cgit v1.2.3