1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
use bytes;
use errors;
use fmt;
use fs;
use io;
use os;
use strings;
use drawing;
use drawing::{pos,CHUNKSIZE};
// 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) = {
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,
};
};
|