aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorubq323 <ubq323@ubq323.website>2024-04-15 20:19:25 +0100
committerubq323 <ubq323@ubq323.website>2024-04-15 20:19:25 +0100
commitd3eaceebe43cbb6b85125f73fbef3cf2241fe452 (patch)
tree64902701cb24bf0715364e8fddd534de1bc97190
parente19852c958838688481422ed3ddd953d2dcd4309 (diff)
add stroke drawop and refactor drawop ser/deser a bit
-rw-r--r--client/main.ha5
-rw-r--r--drawing/drawing.ha1
-rw-r--r--drawing/op.ha97
-rw-r--r--server/main.ha3
-rw-r--r--todo1
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