From 591232eba1809643df1f4a6075ff9581b8bb2f7a Mon Sep 17 00:00:00 2001 From: Lizzy Fleckenstein Date: Sat, 13 Jul 2024 12:51:05 +0200 Subject: move headers to src Signed-off-by: Lizzy Fleckenstein --- include/array.h | 21 ------- include/chunk.h | 24 -------- include/content.h | 177 ------------------------------------------------------ include/net.h | 63 ------------------- include/ser.h | 51 ---------------- include/sig.h | 13 ---- include/str.h | 61 ------------------- include/ticker.h | 23 ------- include/vec.h | 68 --------------------- meson.build | 4 -- src/array.h | 21 +++++++ src/chunk.h | 24 ++++++++ src/content.h | 177 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/net.h | 63 +++++++++++++++++++ src/ser.h | 51 ++++++++++++++++ src/sig.h | 13 ++++ src/str.h | 61 +++++++++++++++++++ src/ticker.h | 23 +++++++ src/vec.h | 68 +++++++++++++++++++++ 19 files changed, 501 insertions(+), 505 deletions(-) delete mode 100644 include/array.h delete mode 100644 include/chunk.h delete mode 100644 include/content.h delete mode 100644 include/net.h delete mode 100644 include/ser.h delete mode 100644 include/sig.h delete mode 100644 include/str.h delete mode 100644 include/ticker.h delete mode 100644 include/vec.h create mode 100644 src/array.h create mode 100644 src/chunk.h create mode 100644 src/content.h create mode 100644 src/net.h create mode 100644 src/ser.h create mode 100644 src/sig.h create mode 100644 src/str.h create mode 100644 src/ticker.h create mode 100644 src/vec.h diff --git a/include/array.h b/include/array.h deleted file mode 100644 index 9affdde..0000000 --- a/include/array.h +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Lizzy Fleckenstein -// -// SPDX-License-Identifier: AGPL-3.0-or-later - -#ifndef ARRAY_H -#define ARRAY_H - -#include -#include -#include - -#define len(X) (sizeof X / sizeof *X) -#define array(T) struct { size_t len; T *data; } -#define arraybuf(T) struct { size_t cap; size_t len; T *data; } - -#define ARR_REMOVE(A, P) memmove((P), (P)+1, sizeof *(P) * (--(A).len - ((P) - (A).data))); -#define ARR_APPEND(A) (((A).cap == (A).len) \ - ? (A).data = realloc((A).data, sizeof *(A).data * ((A).cap = (A).cap ? (A).cap * 2 : 1)) \ - : NULL, &((A).data)[(A).len++]) - -#endif diff --git a/include/chunk.h b/include/chunk.h deleted file mode 100644 index 420211f..0000000 --- a/include/chunk.h +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Lizzy Fleckenstein -// -// SPDX-License-Identifier: AGPL-3.0-or-later - -#ifndef CHUNK_H -#define CHUNK_H - -#include -#include "vec.h" -#include "content.h" - -typedef struct { - uint32_t pitch; - box2 bounds; - node *data; -} chunk; - -chunk chunk_alloc(box2 b); -node *chunk_index(chunk c, uvec2 v); -node *chunk_index_abs(chunk c, vec2 v); -void chunk_copy(chunk dst, chunk src); -void chunk_clear(chunk c); - -#endif diff --git a/include/content.h b/include/content.h deleted file mode 100644 index ef27e22..0000000 --- a/include/content.h +++ /dev/null @@ -1,177 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Lizzy Fleckenstein -// -// SPDX-License-Identifier: AGPL-3.0-or-later - -#ifndef CONTENT_H -#define CONTENT_H - -#include -#include -#include "ser.h" -#include "vec.h" - -#define SIGHT_RANGE 15 -#define PKT_NODES_MAX (50*50) - -typedef enum : uint16_t { - N_BIG_TREE = 0, - N_NEEDLE_TREE, - N_ROCK, - N_WATER, - N_PLANK, - N_PATH, - N_GRASS, - N_SAND, -} node_type; - -#define ser_node_type ser_u16 -#define deser_node_type deser_u16 - -typedef struct { - uint8_t r, g, b; -} color; - -[[maybe_unused]] static void ser_color(strbuf *w, color c) -{ - ser_u8(w, c.r); - ser_u8(w, c.g); - ser_u8(w, c.b); -} - -[[maybe_unused]] static bool deser_color(str *r, color *c) -{ - return deser_u8(r, &c->r) && deser_u8(r, &c->g) && deser_u8(r, &c->b); -} - -[[maybe_unused]] static uint32_t color_to_u32(color c) -{ - return ((uint32_t) c.b) | (((uint32_t) c.g) << 8) | (((uint32_t) c.r) << 16); -} - -[[maybe_unused]] static color color_from_u32(uint32_t u) -{ - return (color) { (u >> 16) & 0xFF, (u >> 8) & 0xFF, u & 0xFF }; -} - -typedef enum : uint8_t { - FLOWER_ROSE = 0, - FLOWER_HIBISCUS, - FLOWER_SUNFLOWER, - FLOWER_TULIP, - FLOWER_DANDELION, // im in a field of dandelions... - FLOWER_COUNT, -} flower_type; - -#define ser_flower_type ser_u8 -#define deser_flower_type deser_u8 - -typedef struct { - bool present; - node_type type; - int8_t z; // for rocks, indicates rock level - color col; - uint8_t variant; -} node; - -[[maybe_unused]] static void ser_node(strbuf *w, node *n) -{ - bool present = n != NULL && n->present; - ser_bool(w, present); - if (!present) - return; - ser_node_type(w, n->type); - ser_i8(w, n->z); - ser_color(w, n->col); - ser_u8(w, n->variant); -} - -[[maybe_unused]] static bool deser_node(str *r, node *n) -{ - if (!deser_bool(r, &n->present)) return false; - if (!n->present) return true; - - return deser_node_type(r, &n->type) - && deser_i8(r, &n->z) - && deser_color(r, &n->col) - && deser_u8(r, &n->variant); -} - -typedef enum : uint8_t { - DIR_RIGHT = 0, - DIR_UP, - DIR_LEFT, - DIR_DOWN, -} dir; - -#define ser_dir ser_u8 -#define deser_dir deser_u8 - -[[maybe_unused]] static vec2 dir_to_vec2(dir d) -{ - switch (d) { - case DIR_RIGHT: return VEC2(1, 0); - case DIR_UP: return VEC2(0, -1); - case DIR_LEFT: return VEC2(-1, 0); - case DIR_DOWN: return VEC2(0, 1); - default: return VEC2(0, 0); - } -} - -typedef enum : uint8_t { - FAIL_WRONG_PASS = 0, - FAIL_ALREADY_ONLINE, -} fail_reason; - -#define ser_fail_reason ser_u8 -#define deser_fail_reason deser_u8 - -typedef uint64_t entity_id; -#define ser_entity_id ser_u64 -#define deser_entity_id deser_u64 - -typedef enum : uint16_t { - ENTITY_PLAYER = 0, - ENTITY_FLOWER, -} entity_type; - -#define ser_entity_type ser_u16 -#define deser_entity_type deser_u16 - -typedef enum : uint8_t { - ENTITY_ADD = 0, // type - ENTITY_REMOVE, - ENTITY_MOVE, // x y - ENTITY_CMD_COUNT, -} entity_cmd; - -#define ser_entity_cmd ser_u8 -#define deser_entity_cmd deser_u8 - -typedef struct { - entity_id id; - entity_type type; - vec2 pos; - union { - flower_type flower; - }; -} entity; - -enum : uint16_t { - CPKT_HI = 0, // len motd - CPKT_FAIL, // fail_reason - CPKT_PLAYERS, // len [len name id] - CPKT_ENTITY, // len [entity_id command] - CPKT_NODES, // box2 [node] - CPKT_RESET_MAP, -}; - -enum : uint16_t { - SPKT_HI = 0, // len name len password - SPKT_MOVE, // dir -}; - -typedef uint16_t pkt_type; -#define ser_pkt_type ser_u16 -#define deser_pkt_type deser_u16 - -#endif diff --git a/include/net.h b/include/net.h deleted file mode 100644 index 08c566a..0000000 --- a/include/net.h +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Lizzy Fleckenstein -// -// SPDX-License-Identifier: AGPL-3.0-or-later - -#ifndef NET_H -#define NET_H - -#include -#include -#include -#include -#include -#include -#include -#include "str.h" -#include "ser.h" -#include "content.h" - -#define SET_NONBLOCK(X) fcntl((X), F_SETFL, fcntl((X), F_GETFL, 0) | O_NONBLOCK) - -#define PEER_INBUFFER_SIZE 0x100000 // 1MB -#define PEER_OUTBUFFER_SIZE 0x200000 // 2MB - -typedef uint32_t pkt_header; - -typedef struct { - int socket; - bool disco; - str *name; - struct { - bool header; - size_t len; - size_t promised; - uint8_t *buffer; - } in; - // TODO: ring buffer - struct { - size_t avail; - size_t cursor; - uint8_t *buffer; - } out; -} peer; - -#define SEND_PKT(CONN, TYPE, ...) \ - { strbuf pkt = NILSBUF; \ - ser_pkt_type(&pkt, TYPE); \ - __VA_ARGS__ \ - if (!peer_send(&(CONN), pkt.data, pkt.len)) \ - fprintf(stderr, "failed to send " #TYPE " to %.*s\n", PSTR(*(CONN).name)); \ - free(pkt.data); } - -void invalid_pkt(peer *p, str pkt); - -int socket_create(const char *host, const char *port, bool server); -int socket_accept(int accept_fd); - -void peer_init(peer *p, int socket, str *name); -void peer_free(peer *p); -struct pollfd peer_prepare(peer *p); -str peer_recv(peer *p, struct pollfd pfd); -bool peer_send(peer *p, void *data, size_t len); - -#endif diff --git a/include/ser.h b/include/ser.h deleted file mode 100644 index 374e5d9..0000000 --- a/include/ser.h +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Lizzy Fleckenstein -// -// SPDX-License-Identifier: AGPL-3.0-or-later - -#ifndef SER_H -#define SER_H - -#include -#include -#include -#include "str.h" - -// ser - -void ser_bytes(strbuf *w, void *x, size_t len); - -void ser_bool(strbuf *w, bool x); -void ser_str(strbuf *w, str x); - -void ser_u8(strbuf *w, uint8_t x); -void ser_i8(strbuf *w, int8_t x); - -void ser_u16(strbuf *w, uint16_t x); -void ser_i16(strbuf *w, int16_t x); - -void ser_u32(strbuf *w, uint32_t x); -void ser_i32(strbuf *w, int32_t x); - -void ser_u64(strbuf *w, uint64_t x); -void ser_i64(strbuf *w, int64_t x); - -// deser - -bool deser_bytes(str *r, void *buf, size_t len); - -bool deser_bool(str *r, bool *buf); -bool deser_str(str *r, str *buf); // returns slice! - -bool deser_u8(str *r, uint8_t *buf); -bool deser_i8(str *r, int8_t *buf); - -bool deser_u16(str *r, uint16_t *buf); -bool deser_i16(str *r, int16_t *buf); - -bool deser_u32(str *r, uint32_t *buf); -bool deser_i32(str *r, int32_t *buf); - -bool deser_u64(str *r, uint64_t *buf); -bool deser_i64(str *r, int64_t *buf); - -#endif diff --git a/include/sig.h b/include/sig.h deleted file mode 100644 index c7e1e42..0000000 --- a/include/sig.h +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Lizzy Fleckenstein -// -// SPDX-License-Identifier: AGPL-3.0-or-later - -#ifndef SIG_H -#define SIG_H - -#include - -extern bool signal_stop; -void signal_setup(); - -#endif diff --git a/include/str.h b/include/str.h deleted file mode 100644 index 5b3e04c..0000000 --- a/include/str.h +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Lizzy Fleckenstein -// -// SPDX-License-Identifier: AGPL-3.0-or-later - -#ifndef STR_H -#define STR_H - -#include -#include -#include "array.h" - -// string library taken from cuddlesOS: -// https://github.com/cuddlesOS/cuddles/blob/master/stage3/string.c - -typedef array(char) str; -#define NILS ((str) { 0, NULL }) -#define S(X) ((str) { len(X)-1, X }) -#define PSTR(X) (int) (X).len, (X).data - -typedef arraybuf(char) strbuf; -#define NILSBUF ((strbuf) { 0, 0, NULL }) - -// return if two strings are equal -bool str_eq(str s1, str s2); - -// compares two strings by length and ASCII values. return value: -// < 0 if s1 < s2 -// = 0 if s1 = s2 -// > 0 if s1 > s2 -int str_cmp(str s1, str s2); - -// returns index of first of occurrence in s of any of the chars in tokens -// returns length of s if not found -size_t str_find(str s, str tokens); - -// this is a splitting function -// returns the next non-empty substring of *s that is delimited by the tokens in sep -// the returned string does not contain any of the separators -// returns an emtpy string when end is reached -// advances s to after the substring plus first delimiting token -str str_walk(str *s, str sep); - -// advances the string while its first token matches any of the chars in tokens -// this can be used to consume whitespace, for example -str str_eat(str s, str tokens); - -// advances the string s by x chars, increasing the data pointer and decreasing the length -// note: this is not bounds checked -str str_advance(str s, size_t x); - -// returns true if s starts with start -bool str_start(str s, str start); - -// construct a str from a \0 terminated string at runtime -// avoid this for literals: use the S macro instead without a runtime cost -str str_intro(char *c); - -// copy a string to the heap -str str_clone(str s); - -#endif diff --git a/include/ticker.h b/include/ticker.h deleted file mode 100644 index f6387c4..0000000 --- a/include/ticker.h +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Lizzy Fleckenstein -// -// SPDX-License-Identifier: AGPL-3.0-or-later - -#ifndef TICKER_H -#define TICKER_H - -#include -#include -#include - -#define NANOS 1000000000 - -typedef struct { - struct timespec timestamp; - uint64_t freq_nanos; -} ticker; - -void ticker_init(ticker *t, uint64_t f); -bool ticker_tick(ticker *t, uint64_t *dtime); -int ticker_timeout(ticker *t); - -#endif diff --git a/include/vec.h b/include/vec.h deleted file mode 100644 index d2d9e31..0000000 --- a/include/vec.h +++ /dev/null @@ -1,68 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Lizzy Fleckenstein -// -// SPDX-License-Identifier: AGPL-3.0-or-later - -#ifndef VEC_H -#define VEC_H - -#include -#include -#include "ser.h" - -#define VECFN [[maybe_unused]] static - -#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) -#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) -#define CHKSUB(A, B) ((A) > (B) ? (A) - (B) : 0) - -#define CAST(T, V) ((T) { (V).x, (V).y }) - -#define MKVEC(V, B, S, SER) \ -typedef struct { S x; S y; } V; \ -typedef struct { V pos; uvec2 size; } B; \ -VECFN V V##_add(V a, V b) { return (V) { a.x+b.x, a.y+b.y }; } \ -VECFN V V##_sub(V a, V b) { return (V) { a.x-b.x, a.y-b.y }; } \ -VECFN V V##_mul(V v, S s) { return (V) { v.x*s, v.y*s }; } \ -VECFN V V##_div(V v, S s) { return (V) { v.x/s, v.y/s }; } \ -VECFN uvec2 V##_chksub(V a, V b) { return (uvec2) { CHKSUB(a.x, b.x), CHKSUB(a.y, b.y) }; } \ -VECFN V V##_min(V a, V b) { return (V) { MIN(a.x, b.x), MIN(a.y, b.y) }; } \ -VECFN V V##_max(V a, V b) { return (V) { MAX(a.x, b.x), MAX(a.y, b.y) }; } \ -VECFN bool V##_eq(V a, V b) { return a.x == b.x && a.y == b.y; } \ -VECFN bool V##_le(V a, V b) { return a.x <= b.x && a.y <= b.y; } \ -VECFN bool V##_lt(V a, V b) { return a.x < b.x && a.y < b.y; } \ -VECFN V V##_zero() { return (V) { 0, 0 }; } \ -VECFN bool V##_iszero(V v) { return V##_eq(v, V##_zero()); } \ -VECFN void ser_##V(strbuf *w, V v) { ser_##SER(w, v.x); ser_##SER(w, v.y); } \ -VECFN bool deser_##V(str *r, V *v) { return deser_##SER(r, &v->x) && deser_##SER(r, &v->y); } \ -VECFN void ser_##B(strbuf *w, B b) { ser_##V(w, b.pos); ser_uvec2(w, b.size); } \ -VECFN bool deser_##B(str *r, B *b) { return deser_##V(r, &b->pos) && deser_uvec2(r, &b->size); } \ -VECFN V B##_upper(B b) { return V##_add(b.pos, CAST(V, b.size)); } \ -VECFN B B##_overlap(B a, B b) { V base = V##_max(a.pos, b.pos); \ - return (B) { base, V##_chksub(V##_min(B##_upper(a), B##_upper(b)), base) }; } \ -VECFN bool B##_empty(B b) { return b.size.x == 0 || b.size.y == 0; } \ -VECFN bool B##_contains(B b, V v) { return V##_le(b.pos, v) && V##_lt(v, B##_upper(b)); } \ -VECFN B B##_around(V center, uint32_t radius) { uint32_t diam = radius*2+1; \ - return (B) { V##_sub(center, (V) { radius, radius }), (uvec2) { diam, diam } }; } - -MKVEC(uvec2, ubox2, uint32_t, u32) -MKVEC(vec2, box2, int32_t, i32) - -#define VEC2(X, Y) ((vec2) { (X), (Y) }) -#define UVEC2(X, Y) ((uvec2) { (X), (Y) }) - -#define CUVEC2(V) ((uvec2) { (V).x, (V).y }) -#define CVEC2(V) ((vec2) { (V).x, (V).y }) - -VECFN vec2 vec2_neg(vec2 v) -{ - return VEC2(-v.x, -v.y); -} - -#undef MKVEC -#undef VECFN -#undef MIN -#undef MAX -#undef CHKSUB -#undef CAST - -#endif diff --git a/meson.build b/meson.build index 21f603d..e683f12 100644 --- a/meson.build +++ b/meson.build @@ -19,14 +19,11 @@ src = [ 'src/chunk.c', ] -include = 'include/' - executable('sillyserver', sources: [ src, 'src/server.c', ], - include_directories: include, dependencies: [ deps, dependency('libpng'), @@ -39,7 +36,6 @@ executable('sillyclient', src, 'src/client.c', ], - include_directories: include, dependencies: deps, install: true, ) diff --git a/src/array.h b/src/array.h new file mode 100644 index 0000000..9affdde --- /dev/null +++ b/src/array.h @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: 2024 Lizzy Fleckenstein +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +#ifndef ARRAY_H +#define ARRAY_H + +#include +#include +#include + +#define len(X) (sizeof X / sizeof *X) +#define array(T) struct { size_t len; T *data; } +#define arraybuf(T) struct { size_t cap; size_t len; T *data; } + +#define ARR_REMOVE(A, P) memmove((P), (P)+1, sizeof *(P) * (--(A).len - ((P) - (A).data))); +#define ARR_APPEND(A) (((A).cap == (A).len) \ + ? (A).data = realloc((A).data, sizeof *(A).data * ((A).cap = (A).cap ? (A).cap * 2 : 1)) \ + : NULL, &((A).data)[(A).len++]) + +#endif diff --git a/src/chunk.h b/src/chunk.h new file mode 100644 index 0000000..420211f --- /dev/null +++ b/src/chunk.h @@ -0,0 +1,24 @@ +// SPDX-FileCopyrightText: 2024 Lizzy Fleckenstein +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +#ifndef CHUNK_H +#define CHUNK_H + +#include +#include "vec.h" +#include "content.h" + +typedef struct { + uint32_t pitch; + box2 bounds; + node *data; +} chunk; + +chunk chunk_alloc(box2 b); +node *chunk_index(chunk c, uvec2 v); +node *chunk_index_abs(chunk c, vec2 v); +void chunk_copy(chunk dst, chunk src); +void chunk_clear(chunk c); + +#endif diff --git a/src/content.h b/src/content.h new file mode 100644 index 0000000..ef27e22 --- /dev/null +++ b/src/content.h @@ -0,0 +1,177 @@ +// SPDX-FileCopyrightText: 2024 Lizzy Fleckenstein +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +#ifndef CONTENT_H +#define CONTENT_H + +#include +#include +#include "ser.h" +#include "vec.h" + +#define SIGHT_RANGE 15 +#define PKT_NODES_MAX (50*50) + +typedef enum : uint16_t { + N_BIG_TREE = 0, + N_NEEDLE_TREE, + N_ROCK, + N_WATER, + N_PLANK, + N_PATH, + N_GRASS, + N_SAND, +} node_type; + +#define ser_node_type ser_u16 +#define deser_node_type deser_u16 + +typedef struct { + uint8_t r, g, b; +} color; + +[[maybe_unused]] static void ser_color(strbuf *w, color c) +{ + ser_u8(w, c.r); + ser_u8(w, c.g); + ser_u8(w, c.b); +} + +[[maybe_unused]] static bool deser_color(str *r, color *c) +{ + return deser_u8(r, &c->r) && deser_u8(r, &c->g) && deser_u8(r, &c->b); +} + +[[maybe_unused]] static uint32_t color_to_u32(color c) +{ + return ((uint32_t) c.b) | (((uint32_t) c.g) << 8) | (((uint32_t) c.r) << 16); +} + +[[maybe_unused]] static color color_from_u32(uint32_t u) +{ + return (color) { (u >> 16) & 0xFF, (u >> 8) & 0xFF, u & 0xFF }; +} + +typedef enum : uint8_t { + FLOWER_ROSE = 0, + FLOWER_HIBISCUS, + FLOWER_SUNFLOWER, + FLOWER_TULIP, + FLOWER_DANDELION, // im in a field of dandelions... + FLOWER_COUNT, +} flower_type; + +#define ser_flower_type ser_u8 +#define deser_flower_type deser_u8 + +typedef struct { + bool present; + node_type type; + int8_t z; // for rocks, indicates rock level + color col; + uint8_t variant; +} node; + +[[maybe_unused]] static void ser_node(strbuf *w, node *n) +{ + bool present = n != NULL && n->present; + ser_bool(w, present); + if (!present) + return; + ser_node_type(w, n->type); + ser_i8(w, n->z); + ser_color(w, n->col); + ser_u8(w, n->variant); +} + +[[maybe_unused]] static bool deser_node(str *r, node *n) +{ + if (!deser_bool(r, &n->present)) return false; + if (!n->present) return true; + + return deser_node_type(r, &n->type) + && deser_i8(r, &n->z) + && deser_color(r, &n->col) + && deser_u8(r, &n->variant); +} + +typedef enum : uint8_t { + DIR_RIGHT = 0, + DIR_UP, + DIR_LEFT, + DIR_DOWN, +} dir; + +#define ser_dir ser_u8 +#define deser_dir deser_u8 + +[[maybe_unused]] static vec2 dir_to_vec2(dir d) +{ + switch (d) { + case DIR_RIGHT: return VEC2(1, 0); + case DIR_UP: return VEC2(0, -1); + case DIR_LEFT: return VEC2(-1, 0); + case DIR_DOWN: return VEC2(0, 1); + default: return VEC2(0, 0); + } +} + +typedef enum : uint8_t { + FAIL_WRONG_PASS = 0, + FAIL_ALREADY_ONLINE, +} fail_reason; + +#define ser_fail_reason ser_u8 +#define deser_fail_reason deser_u8 + +typedef uint64_t entity_id; +#define ser_entity_id ser_u64 +#define deser_entity_id deser_u64 + +typedef enum : uint16_t { + ENTITY_PLAYER = 0, + ENTITY_FLOWER, +} entity_type; + +#define ser_entity_type ser_u16 +#define deser_entity_type deser_u16 + +typedef enum : uint8_t { + ENTITY_ADD = 0, // type + ENTITY_REMOVE, + ENTITY_MOVE, // x y + ENTITY_CMD_COUNT, +} entity_cmd; + +#define ser_entity_cmd ser_u8 +#define deser_entity_cmd deser_u8 + +typedef struct { + entity_id id; + entity_type type; + vec2 pos; + union { + flower_type flower; + }; +} entity; + +enum : uint16_t { + CPKT_HI = 0, // len motd + CPKT_FAIL, // fail_reason + CPKT_PLAYERS, // len [len name id] + CPKT_ENTITY, // len [entity_id command] + CPKT_NODES, // box2 [node] + CPKT_RESET_MAP, +}; + +enum : uint16_t { + SPKT_HI = 0, // len name len password + SPKT_MOVE, // dir +}; + +typedef uint16_t pkt_type; +#define ser_pkt_type ser_u16 +#define deser_pkt_type deser_u16 + +#endif diff --git a/src/net.h b/src/net.h new file mode 100644 index 0000000..08c566a --- /dev/null +++ b/src/net.h @@ -0,0 +1,63 @@ +// SPDX-FileCopyrightText: 2024 Lizzy Fleckenstein +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +#ifndef NET_H +#define NET_H + +#include +#include +#include +#include +#include +#include +#include +#include "str.h" +#include "ser.h" +#include "content.h" + +#define SET_NONBLOCK(X) fcntl((X), F_SETFL, fcntl((X), F_GETFL, 0) | O_NONBLOCK) + +#define PEER_INBUFFER_SIZE 0x100000 // 1MB +#define PEER_OUTBUFFER_SIZE 0x200000 // 2MB + +typedef uint32_t pkt_header; + +typedef struct { + int socket; + bool disco; + str *name; + struct { + bool header; + size_t len; + size_t promised; + uint8_t *buffer; + } in; + // TODO: ring buffer + struct { + size_t avail; + size_t cursor; + uint8_t *buffer; + } out; +} peer; + +#define SEND_PKT(CONN, TYPE, ...) \ + { strbuf pkt = NILSBUF; \ + ser_pkt_type(&pkt, TYPE); \ + __VA_ARGS__ \ + if (!peer_send(&(CONN), pkt.data, pkt.len)) \ + fprintf(stderr, "failed to send " #TYPE " to %.*s\n", PSTR(*(CONN).name)); \ + free(pkt.data); } + +void invalid_pkt(peer *p, str pkt); + +int socket_create(const char *host, const char *port, bool server); +int socket_accept(int accept_fd); + +void peer_init(peer *p, int socket, str *name); +void peer_free(peer *p); +struct pollfd peer_prepare(peer *p); +str peer_recv(peer *p, struct pollfd pfd); +bool peer_send(peer *p, void *data, size_t len); + +#endif diff --git a/src/ser.h b/src/ser.h new file mode 100644 index 0000000..374e5d9 --- /dev/null +++ b/src/ser.h @@ -0,0 +1,51 @@ +// SPDX-FileCopyrightText: 2024 Lizzy Fleckenstein +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +#ifndef SER_H +#define SER_H + +#include +#include +#include +#include "str.h" + +// ser + +void ser_bytes(strbuf *w, void *x, size_t len); + +void ser_bool(strbuf *w, bool x); +void ser_str(strbuf *w, str x); + +void ser_u8(strbuf *w, uint8_t x); +void ser_i8(strbuf *w, int8_t x); + +void ser_u16(strbuf *w, uint16_t x); +void ser_i16(strbuf *w, int16_t x); + +void ser_u32(strbuf *w, uint32_t x); +void ser_i32(strbuf *w, int32_t x); + +void ser_u64(strbuf *w, uint64_t x); +void ser_i64(strbuf *w, int64_t x); + +// deser + +bool deser_bytes(str *r, void *buf, size_t len); + +bool deser_bool(str *r, bool *buf); +bool deser_str(str *r, str *buf); // returns slice! + +bool deser_u8(str *r, uint8_t *buf); +bool deser_i8(str *r, int8_t *buf); + +bool deser_u16(str *r, uint16_t *buf); +bool deser_i16(str *r, int16_t *buf); + +bool deser_u32(str *r, uint32_t *buf); +bool deser_i32(str *r, int32_t *buf); + +bool deser_u64(str *r, uint64_t *buf); +bool deser_i64(str *r, int64_t *buf); + +#endif diff --git a/src/sig.h b/src/sig.h new file mode 100644 index 0000000..c7e1e42 --- /dev/null +++ b/src/sig.h @@ -0,0 +1,13 @@ +// SPDX-FileCopyrightText: 2024 Lizzy Fleckenstein +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +#ifndef SIG_H +#define SIG_H + +#include + +extern bool signal_stop; +void signal_setup(); + +#endif diff --git a/src/str.h b/src/str.h new file mode 100644 index 0000000..5b3e04c --- /dev/null +++ b/src/str.h @@ -0,0 +1,61 @@ +// SPDX-FileCopyrightText: 2024 Lizzy Fleckenstein +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +#ifndef STR_H +#define STR_H + +#include +#include +#include "array.h" + +// string library taken from cuddlesOS: +// https://github.com/cuddlesOS/cuddles/blob/master/stage3/string.c + +typedef array(char) str; +#define NILS ((str) { 0, NULL }) +#define S(X) ((str) { len(X)-1, X }) +#define PSTR(X) (int) (X).len, (X).data + +typedef arraybuf(char) strbuf; +#define NILSBUF ((strbuf) { 0, 0, NULL }) + +// return if two strings are equal +bool str_eq(str s1, str s2); + +// compares two strings by length and ASCII values. return value: +// < 0 if s1 < s2 +// = 0 if s1 = s2 +// > 0 if s1 > s2 +int str_cmp(str s1, str s2); + +// returns index of first of occurrence in s of any of the chars in tokens +// returns length of s if not found +size_t str_find(str s, str tokens); + +// this is a splitting function +// returns the next non-empty substring of *s that is delimited by the tokens in sep +// the returned string does not contain any of the separators +// returns an emtpy string when end is reached +// advances s to after the substring plus first delimiting token +str str_walk(str *s, str sep); + +// advances the string while its first token matches any of the chars in tokens +// this can be used to consume whitespace, for example +str str_eat(str s, str tokens); + +// advances the string s by x chars, increasing the data pointer and decreasing the length +// note: this is not bounds checked +str str_advance(str s, size_t x); + +// returns true if s starts with start +bool str_start(str s, str start); + +// construct a str from a \0 terminated string at runtime +// avoid this for literals: use the S macro instead without a runtime cost +str str_intro(char *c); + +// copy a string to the heap +str str_clone(str s); + +#endif diff --git a/src/ticker.h b/src/ticker.h new file mode 100644 index 0000000..f6387c4 --- /dev/null +++ b/src/ticker.h @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: 2024 Lizzy Fleckenstein +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +#ifndef TICKER_H +#define TICKER_H + +#include +#include +#include + +#define NANOS 1000000000 + +typedef struct { + struct timespec timestamp; + uint64_t freq_nanos; +} ticker; + +void ticker_init(ticker *t, uint64_t f); +bool ticker_tick(ticker *t, uint64_t *dtime); +int ticker_timeout(ticker *t); + +#endif diff --git a/src/vec.h b/src/vec.h new file mode 100644 index 0000000..d2d9e31 --- /dev/null +++ b/src/vec.h @@ -0,0 +1,68 @@ +// SPDX-FileCopyrightText: 2024 Lizzy Fleckenstein +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +#ifndef VEC_H +#define VEC_H + +#include +#include +#include "ser.h" + +#define VECFN [[maybe_unused]] static + +#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) +#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) +#define CHKSUB(A, B) ((A) > (B) ? (A) - (B) : 0) + +#define CAST(T, V) ((T) { (V).x, (V).y }) + +#define MKVEC(V, B, S, SER) \ +typedef struct { S x; S y; } V; \ +typedef struct { V pos; uvec2 size; } B; \ +VECFN V V##_add(V a, V b) { return (V) { a.x+b.x, a.y+b.y }; } \ +VECFN V V##_sub(V a, V b) { return (V) { a.x-b.x, a.y-b.y }; } \ +VECFN V V##_mul(V v, S s) { return (V) { v.x*s, v.y*s }; } \ +VECFN V V##_div(V v, S s) { return (V) { v.x/s, v.y/s }; } \ +VECFN uvec2 V##_chksub(V a, V b) { return (uvec2) { CHKSUB(a.x, b.x), CHKSUB(a.y, b.y) }; } \ +VECFN V V##_min(V a, V b) { return (V) { MIN(a.x, b.x), MIN(a.y, b.y) }; } \ +VECFN V V##_max(V a, V b) { return (V) { MAX(a.x, b.x), MAX(a.y, b.y) }; } \ +VECFN bool V##_eq(V a, V b) { return a.x == b.x && a.y == b.y; } \ +VECFN bool V##_le(V a, V b) { return a.x <= b.x && a.y <= b.y; } \ +VECFN bool V##_lt(V a, V b) { return a.x < b.x && a.y < b.y; } \ +VECFN V V##_zero() { return (V) { 0, 0 }; } \ +VECFN bool V##_iszero(V v) { return V##_eq(v, V##_zero()); } \ +VECFN void ser_##V(strbuf *w, V v) { ser_##SER(w, v.x); ser_##SER(w, v.y); } \ +VECFN bool deser_##V(str *r, V *v) { return deser_##SER(r, &v->x) && deser_##SER(r, &v->y); } \ +VECFN void ser_##B(strbuf *w, B b) { ser_##V(w, b.pos); ser_uvec2(w, b.size); } \ +VECFN bool deser_##B(str *r, B *b) { return deser_##V(r, &b->pos) && deser_uvec2(r, &b->size); } \ +VECFN V B##_upper(B b) { return V##_add(b.pos, CAST(V, b.size)); } \ +VECFN B B##_overlap(B a, B b) { V base = V##_max(a.pos, b.pos); \ + return (B) { base, V##_chksub(V##_min(B##_upper(a), B##_upper(b)), base) }; } \ +VECFN bool B##_empty(B b) { return b.size.x == 0 || b.size.y == 0; } \ +VECFN bool B##_contains(B b, V v) { return V##_le(b.pos, v) && V##_lt(v, B##_upper(b)); } \ +VECFN B B##_around(V center, uint32_t radius) { uint32_t diam = radius*2+1; \ + return (B) { V##_sub(center, (V) { radius, radius }), (uvec2) { diam, diam } }; } + +MKVEC(uvec2, ubox2, uint32_t, u32) +MKVEC(vec2, box2, int32_t, i32) + +#define VEC2(X, Y) ((vec2) { (X), (Y) }) +#define UVEC2(X, Y) ((uvec2) { (X), (Y) }) + +#define CUVEC2(V) ((uvec2) { (V).x, (V).y }) +#define CVEC2(V) ((vec2) { (V).x, (V).y }) + +VECFN vec2 vec2_neg(vec2 v) +{ + return VEC2(-v.x, -v.y); +} + +#undef MKVEC +#undef VECFN +#undef MIN +#undef MAX +#undef CHKSUB +#undef CAST + +#endif -- cgit v1.2.3