aboutsummaryrefslogtreecommitdiff
path: root/server/save_load.ha
diff options
context:
space:
mode:
authorubq323 <ubq323@ubq323.website>2024-04-13 22:59:07 +0100
committerubq323 <ubq323@ubq323.website>2024-04-13 22:59:07 +0100
commitc95e947d90a02091aef4e63693ce3205fdfba3b6 (patch)
tree933a136be180f88741ec89960882ebe494477e1e /server/save_load.ha
parent53e2a1d2e8a110b30dd47f0a47574625286e4ff5 (diff)
move things
Diffstat (limited to 'server/save_load.ha')
-rw-r--r--server/save_load.ha96
1 files changed, 96 insertions, 0 deletions
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,
+ };
+};