From 187d6d32e71aface08c1c486874901ecc9b160c1 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Tue, 16 Apr 2024 12:34:18 +0100 Subject: fix chunkloading and unloading on client --- client/main.ha | 151 ++++++--------------------------------------------------- 1 file changed, 14 insertions(+), 137 deletions(-) (limited to 'client/main.ha') diff --git a/client/main.ha b/client/main.ha index 9b8f92b..0f4b1b8 100644 --- a/client/main.ha +++ b/client/main.ha @@ -7,12 +7,12 @@ use net::dial; use unix::poll; use drawing; -use drawing::{pos,CHUNKSIZE}; +use drawing::{pos,CHUNKSIZE,picture}; use client::paintui; use packet_reader; use packet_reader::{VERSION}; -def NCHUNKS = 16; +def NSURFS = 16; def WIN_H: i32 = 480; def WIN_W: i32 = 640; @@ -27,22 +27,7 @@ export fn main() void = { const wsurf = sdl2::SDL_GetWindowSurface(win)!; - let offs: []pos = []; - for (let x = -1; x < 3; x+=1) for (let y = -1; y < 3; y+=1) - append(offs, (1024*1024+x*CHUNKSIZE,y*CHUNKSIZE)); - - let pictures: []drawing::picture = alloc([],NCHUNKS); - let picture_surfaces: []*sdl2::SDL_Surface = alloc([], NCHUNKS); - for (let i = 0z; i < NCHUNKS; i +=1){ - const surf = sdl2::SDL_CreateRGBSurface(0, - CHUNKSIZE, CHUNKSIZE, 32, 0xff0000, 0xff00, 0xff, 0)!; - append(picture_surfaces, surf); - append(pictures, picture_from_surface(surf, offs[i])); - }; - for (const p &.. pictures) { - drawing::clear_picture(p, 0x00ff00); - drawing::outline_picture(p); - }; + let pmgr = picture_mgr { ... }; // connect to server const conn = match(dial::dial("tcp","localhost","41460")) { @@ -51,6 +36,7 @@ export fn main() void = { fmt::fatal("couldn't connect to server:",net::strerror(err)); }; + // version check let byte = [0u8]; match (io::read(conn, byte)) { case let e: io::error => @@ -60,7 +46,6 @@ export fn main() void = { byte[0], VERSION); }; - const pollfd: [1]poll::pollfd = [ poll::pollfd { fd = conn, events=poll::event::POLLIN, revents = 0 }]; @@ -74,16 +59,14 @@ export fn main() void = { let n = 0; let lasttime = sdl2::SDL_GetTicks(); - let requested_chunks: []pos = []; - // in SCREEN coords let mouse_pos: pos = (0,0); let mouse_down = false; - request_visible_chunks(pictures, conn, camera_pos, &requested_chunks); - const win_pic = picture_from_surface(wsurf, (9,9)); + process_chunk_loadedness(&pmgr, conn, camera_pos); + const win_pic = picture_from_surface(wsurf, (9,9)); for (!quit) { const did_move = do_movement(&camera_pos); @@ -124,13 +107,13 @@ export fn main() void = { match (paintui::tick(&pstate, mouse_pos_world, mouse_down)) { case void => yield; case let op: drawing::op => - drawing::perform(pictures, op); + perform_drawop(&pmgr, op); packet_reader::send(conn, op: packet_reader::packet_drawop)!; }; if (did_move) { packet_reader::send(conn, camera_pos: packet_reader::packet_position)!; - request_visible_chunks(pictures, conn, camera_pos, &requested_chunks); + process_chunk_loadedness(&pmgr, conn, camera_pos); }; const n = poll::poll(pollfd, poll::NONBLOCK)!; @@ -139,36 +122,17 @@ export fn main() void = { for (const packet => packet_reader::next(&packet_reader)!) { match (packet) { case let op: packet_reader::packet_drawop => - drawing::perform(pictures, op); + perform_drawop(&pmgr, op); case let packet: packet_reader::packet_sendchunk => - assert(packet.world_pos.0 % CHUNKSIZE == 0 - && packet.world_pos.1 % CHUNKSIZE == 0, "bad chunk world pos"); - const pic = find_picture_for_chunkdata(camera_pos, packet.world_pos, pictures); - pic.world_pos = packet.world_pos; - pic.d[..len(packet.chunk_data)] = packet.chunk_data[..]; - - for (let i = 0z; i < len(requested_chunks); i += 1) { - const rc = requested_chunks[i]; - if (rc.0 == packet.world_pos.0 && rc.1 == packet.world_pos.1) { - delete(requested_chunks[i]); - fmt::printfln("fulfilling chunk request {},{}", - packet.world_pos.0, packet.world_pos.1)!; - break; - }; - }; - + enact_chunkdata(&pmgr, packet, camera_pos); }; }; }; - drawing::clear_picture(&win_pic, 0xdddddd); - for (let i = 0z; i < len(pictures); i += 1) { - const psurf = picture_surfaces[i]; - const pic = &pictures[i]; - render_picture(pic, psurf, wsurf, camera_pos); - }; + for (const pic &.. pmgr.pictures) + render_picture(pic, wsurf, camera_pos); drawing::circle_hollow(&win_pic, mouse_pos, paintui::sizes[pstate.size_idx]: i32, pstate.color); @@ -185,8 +149,8 @@ fn picture_from_surface(surf: *sdl2::SDL_Surface, world_pos: pos) drawing::pictu world_pos = world_pos, }; -fn render_picture(pic: *drawing::picture, surf: *sdl2::SDL_Surface, winsurf: *sdl2::SDL_Surface, camera_pos: pos) void = { - sdl2::SDL_BlitSurface(surf, null, winsurf, &sdl2::SDL_Rect{ +fn render_picture(pic: *picture_c, winsurf: *sdl2::SDL_Surface, camera_pos: pos) void = { + sdl2::SDL_BlitSurface(pic.surface, null, winsurf, &sdl2::SDL_Rect{ x = pic.world_pos.0 - camera_pos.0, y = pic.world_pos.1 - camera_pos.1, ... })!; }; @@ -216,91 +180,4 @@ fn do_movement(pos: *pos) bool = { return did_move; }; -fn is_picture_visible(camera_pos: pos, pic_pos: pos) bool = { - const s_min: pos = camera_pos; - const s_max: pos = (camera_pos.0 + WIN_W, camera_pos.1 + WIN_H); - const p_min: pos = pic_pos; - const p_max: pos = (pic_pos.0 + CHUNKSIZE: i32, pic_pos.1 + CHUNKSIZE: i32); - return (s_min.0 <= p_max.0 && s_max.0 >= p_min.0) - && (s_min.1 <= p_max.1 && s_max.1 >= p_min.1); -}; - -fn find_picture_for_chunkdata(camera_pos: pos, world_pos: pos, pictures: []drawing::picture) *drawing::picture = { - // if we have one with that exact worldpos, return that - // otherwise find one that isn't visible - - let invisible: nullable *drawing::picture = null; - - for (const pic &.. pictures) { - if (pic.world_pos.0 == world_pos.0 && pic.world_pos.1 == world_pos.1) { - // fmt::printfln("found already pic at {},{}",pic.world_pos.0, pic.world_pos.1)!; - return pic; - }; - if (invisible == null && !is_picture_visible(camera_pos, pic.world_pos)) { - // fmt::printfln("can recycle pic at {},{}",pic.world_pos.0,pic.world_pos.1)!; - invisible = pic; - }; - }; - - match (invisible) { - case null => abort("couldn't find offscreen picture???"); - case let p: *drawing::picture => return p; - }; - -}; - - - -fn floor_div(a: i32, b: i32) i32 = { - if (a < 0) return -1-floor_div(-(a+1),b); - return a / b; -}; -fn find_chunk(pictures: []drawing::picture, world_pos: pos) - nullable *drawing::picture = { - for (const pic &.. pictures) { - if (pic.world_pos.0 == world_pos.0 - && pic.world_pos.1 == world_pos.1) { - return pic; - }; - }; - return null; -}; - -fn request_visible_chunks( - pictures: []drawing::picture, - conn: net::socket, - camera_pos: pos, - requested_chunks: *[]pos, -) void = { - const x0 = CHUNKSIZE*floor_div(camera_pos.0,CHUNKSIZE); - const y0 = CHUNKSIZE*floor_div(camera_pos.1,CHUNKSIZE); - - for (let dx = 0i32; dx < 3; dx += 1) for (let dy = 0i32; dy < 3; dy += 1) { - let world_pos = (x0+CHUNKSIZE*dx, y0+CHUNKSIZE*dy): pos; - - for (const rc .. requested_chunks) { - if (rc.0 == world_pos.0 && rc.1 == world_pos.1) { - fmt::printfln("not requesting {},{} again", rc.0, rc.1)!; - return; - }; - }; - - - if (!is_picture_visible(camera_pos, world_pos)) { - // fmt::printfln("invisible {},{}", world_pos.0, world_pos.1)!; - continue; - }; - // fmt::printfln("visible {},{}, checking availability", world_pos.0, world_pos.1)!; - match (find_chunk(pictures,world_pos)) { - case *drawing::picture => - // fmt::printfln("\talready got that one")!; - yield; - case null => - fmt::printfln("\trequesting {},{}", world_pos.0, world_pos.1)!; - packet_reader::send(conn, world_pos: packet_reader::packet_reqchunk)!; - append(requested_chunks, world_pos); - }; - }; -}; - -- cgit v1.2.3