use bufio; use fmt; use net; use net::tcp; use net::ip; use io; use os; use fs; use strings; use time; use time::date; use time::chrono; use unix::poll; use drawing; use drawing::{pos}; use packet_reader; def PORT: u16 = 41460; type conn = net::socket; def CHUNKSIZE = 512; export fn main() void = { // create 4 pictures. later we will have more pictures // but for now there are just 4, and they are at fixed positions const offs: [_]pos = [ (0,0), (0,CHUNKSIZE), (CHUNKSIZE,0), (CHUNKSIZE,CHUNKSIZE), ]; let pictures: []drawing::picture = alloc([],len(offs)); for (let i = 0z; i < len(offs); i +=1){ append(pictures, drawing::picture { w = CHUNKSIZE, h = CHUNKSIZE, d = alloc([0...],CHUNKSIZE*CHUNKSIZE: size): *[*]u32, world_pos = offs[i], }); }; for (const p &.. pictures) drawing::clear_picture(p, 0xffffff); const listener = tcp::listen(ip::ANY_V4, PORT)!; loop(listener, pictures); }; def save_interval = 5 * time::SECOND; fn save_world(pictures: []drawing::picture) void = { fmt::printfln("saving world!")!; for (const pic &.. pictures) { const filename = fmt::asprintf("./c.{}.{}.ppm",pic.world_pos.0, pic.world_pos.1); fmt::printfln("\t-> {}",filename)!; defer free(filename); const mode = fs::mode::USER_RW | fs::mode::GROUP_RW; const file = os::create(filename, mode)!; defer { fmt::printfln("\t. {}",filename)!; io::close(file)!; }; const header = fmt::asprintf("P6\n{} {}\n{}\n", pic.w, pic.h, 255); defer free(header); io::writeall(file, strings::toutf8(header))!; for (let i = 0z; i < pic.w * pic.h; i += 1) { const px = pic.d[i]; io::writeall(file, [(px&0xff): u8, ((px>>8)&0xff): u8, ((px>>16)&0xff): u8])!; }; }; }; fn loop(listener: net::socket, pictures: []drawing::picture) void = { // pollfds[0] is the listener // pollfds[n>0] corresponds to packet_readers[n-1] let pollfds: []poll::pollfd = alloc([ poll::pollfd { fd = listener, events = poll::event::POLLIN, revents = 0 }]); let packet_readers: []packet_reader::packet_reader = []; let now = time::now(time::clock::MONOTONIC); let next = time::add(now, save_interval); for (true) { fmt::println("poll.")!; const timeout = time::diff(now, next); poll::poll(pollfds, timeout)!; now = time::now(time::clock::MONOTONIC); if (time::compare(now, next) >= 0) { save_world(pictures); next = time::add(now, save_interval); }; if (0 != pollfds[0].revents & poll::event::POLLIN) { fmt::println("new conn")!; const new_conn = tcp::accept(pollfds[0].fd)!; fmt::println("a")!; append(pollfds, poll::pollfd { fd = new_conn, events = poll::event::POLLIN, revents = 0 }); append(packet_readers, packet_reader::new()); fmt::printfln("there are now {},{} conns.",len(pollfds),len(packet_readers))!; }; for (let i = 1z; i < len(pollfds); i += 1) { if (0 != pollfds[i].revents & poll::event::POLLIN) { match (packet_reader::read(&packet_readers[i-1], pollfds[i].fd)) { case void => let j = 1; for (const packet_bytes => packet_reader::next(&packet_readers[i-1])) { fmt::printf("#{}:{} got {:2}",i,j,len(packet_bytes))!; j += 1; for (let byte .. packet_bytes) fmt::printf(" {:x}",byte)!; const op = drawing::deser_op(packet_bytes) as drawing::op_circle; drawing::perform(pictures, op); fmt::printfln("\t({:+6},{:+6})",op.0,op.1)!; for (let k = 1z; k < len(pollfds); k += 1) { if (k == i) continue; fmt::printfln("\t -> #{}",k)!; io::writeall(pollfds[k].fd, packet_bytes)!; }; }; case let err: io::error => fmt::printfln("#{} error: {}",i,io::strerror(err))!; delete(pollfds[i]); delete(packet_readers[i-1]); i -= 1; case io::EOF => fmt::printfln("#{} disconnect",i)!; delete(pollfds[i]); delete(packet_readers[i-1]); i -= 1; }; }; }; }; };