From d3eaceebe43cbb6b85125f73fbef3cf2241fe452 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Mon, 15 Apr 2024 20:19:25 +0100 Subject: add stroke drawop and refactor drawop ser/deser a bit --- client/main.ha | 5 ++- drawing/drawing.ha | 1 - drawing/op.ha | 97 ++++++++++++++++++++++++++++++++++++++++++++---------- server/main.ha | 3 +- todo | 1 + 5 files changed, 83 insertions(+), 24 deletions(-) diff --git a/client/main.ha b/client/main.ha index 4c70892..9b8f92b 100644 --- a/client/main.ha +++ b/client/main.ha @@ -45,7 +45,7 @@ export fn main() void = { }; // connect to server - const conn = match(dial::dial("tcp","ubq323.website","41460")) { + const conn = match(dial::dial("tcp","localhost","41460")) { case let c: net::socket => yield c; case let err: net::error => fmt::fatal("couldn't connect to server:",net::strerror(err)); @@ -139,8 +139,7 @@ export fn main() void = { for (const packet => packet_reader::next(&packet_reader)!) { match (packet) { case let op: packet_reader::packet_drawop => - const opc = op as drawing::op_circle; - drawing::perform(pictures, opc); + drawing::perform(pictures, 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"); diff --git a/drawing/drawing.ha b/drawing/drawing.ha index 54a877b..063577d 100644 --- a/drawing/drawing.ha +++ b/drawing/drawing.ha @@ -100,7 +100,6 @@ export fn circle_hollow(picture: *picture, c: pos, r: i32, color: u32) void = { }; export fn perform(pictures: []picture, op: op) void = { match (op) { - case op_other => abort("oopsy"); case let o: op_circle => const x = o.pos.0, y=o.pos.1; const r = o.radius; diff --git a/drawing/op.ha b/drawing/op.ha index 532fd75..aa7fac4 100644 --- a/drawing/op.ha +++ b/drawing/op.ha @@ -3,33 +3,94 @@ use endian; export type op_circle = struct { pos: pos, + color: u32, radius: u8, - color: u32 }; -export type op_other = void; +export type op_stroke = struct { + pos0: pos, + pos1: pos, + color: u32, + radius: u8, + count: u8, +}; -export type op = (op_circle| op_other); +export type op = (op_circle | op_stroke); +type op_type = enum u8 { + CIRCLE, + STROKE, +}; -def SER_LEN: size = 13; +export type deser_fail = !void; // return value must be freed... for now. ehh -export fn ser_op(op: op) []u8 = { - const opc = op as op_circle; - let buf: []u8 = alloc([0...],SER_LEN); - endian::leputu32(buf[0..4], opc.pos.0: u32); - endian::leputu32(buf[4..8], opc.pos.1: u32); - endian::leputu32(buf[8..12], opc.color: u32); - buf[12] = opc.radius; - return buf; +export fn ser_op(op: op) []u8 = match (op) { + case let opc: op_circle => yield ser_op_circle(opc); + case let ops: op_stroke => yield ser_op_stroke(ops); +}; + +export fn deser_op(bytes: []u8) (op | deser_fail) = switch (bytes[0]) { + case op_type::CIRCLE => yield deser_op_circle(bytes)?; + case op_type::STROKE => yield deser_op_stroke(bytes)?; + case => yield deser_fail; }; -export fn deser_op(bytes: []u8) op = { - assert(len(bytes) == SER_LEN, "wrong length somehow"); + +fn ser_pos(bytes: []u8, pos: pos) void = { + endian::leputu32(bytes[0..4], pos.0: u32); + endian::leputu32(bytes[4..8], pos.1: u32); +}; +fn deser_pos(bytes: []u8) pos = ( + endian::legetu32(bytes[0..4]): i32, + endian::legetu32(bytes[4..8]): i32 +); + + +def SER_LEN_CIRCLE = 14; +// type:1 pos: 8 color: 4, radius:1 +fn ser_op_circle(opc: op_circle) []u8 = { + let buf: []u8 = alloc([0...],SER_LEN_CIRCLE); + buf[0] = op_type::CIRCLE; + let payload = buf[1..]; + + ser_pos(payload[0..8], opc.pos); + endian::leputu32(payload[8..12], opc.color: u32); + payload[12] = opc.radius; + return buf; +}; +fn deser_op_circle(bytes: []u8) (op_circle|deser_fail) = { + if (len(bytes) != SER_LEN_CIRCLE) return deser_fail; + let payload = bytes[1..]; return op_circle { - pos = (endian::legetu32(bytes[0..4]): i32, - endian::legetu32(bytes[4..8]): i32), - color = endian::legetu32(bytes[8..12]), - radius = bytes[12], + pos = deser_pos(payload[0..8]), + color = endian::legetu32(payload[8..12]), + radius = payload[12], + }; +}; + +def SER_LEN_STROKE = 23; +// type:1 pos0:8 pos1:8 color:4 radius:1 count:1 +fn ser_op_stroke(ops: op_stroke) []u8 = { + let buf: []u8 = alloc([0...], SER_LEN_STROKE); + buf[0] = op_type::STROKE; + let payload = buf[1..]; + + ser_pos(payload[0..8], ops.pos0); + ser_pos(payload[8..16], ops.pos1); + endian::leputu32(payload[16..20], ops.color); + payload[20] = ops.radius; + payload[21] = ops.count; + return buf; +}; +fn deser_op_stroke(bytes: []u8) (op_stroke|deser_fail) = { + if (len(bytes) != SER_LEN_STROKE) return deser_fail; + let payload = bytes[1..]; + return op_stroke { + pos0 = deser_pos(payload[0..8]), + pos1 = deser_pos(payload[8..16]), + color = endian::legetu32(payload[16..20]), + radius = payload[20], + count = payload[21], }; }; + diff --git a/server/main.ha b/server/main.ha index cf8e720..2043a1d 100644 --- a/server/main.ha +++ b/server/main.ha @@ -197,10 +197,9 @@ fn handle_packet( const conn = &state.connections[conn_idx]; match (packet) { case let op: packet_reader::packet_drawop => - const opc = op as drawing::op_circle; // fmt::printfln("#{}: drawop ({:+6},{:+6}) r{}", // conn_idx,opc.pos.0,opc.pos.1, opc.radius)!; - drawing::perform(state.pictures, opc); + drawing::perform(state.pictures, op); for (let other_idx = 0z; other_idx < len(state.connections); other_idx += 1) diff --git a/todo b/todo index 111b85b..105a3ca 100644 --- a/todo +++ b/todo @@ -1,2 +1,3 @@ smooth brush strokes rle compression +more elegant solution to big packets than just having a giant buffer -- cgit v1.2.3