diff options
author | Lizzy Fleckenstein <lizzy@vlhl.dev> | 2024-06-23 20:07:44 +0200 |
---|---|---|
committer | Lizzy Fleckenstein <lizzy@vlhl.dev> | 2024-06-23 20:07:44 +0200 |
commit | 3be565f4e8ee1610aae5b0945185b4012f026c87 (patch) | |
tree | e24cb1320ea236c90bb3c81a1398677c1c9c8177 /src/client.c | |
parent | bf3c2eb3509076251b16ded45f8ceb4be60ae98b (diff) |
implement movement
Signed-off-by: Lizzy Fleckenstein <lizzy@vlhl.dev>
Diffstat (limited to 'src/client.c')
-rw-r--r-- | src/client.c | 137 |
1 files changed, 103 insertions, 34 deletions
diff --git a/src/client.c b/src/client.c index 79a012d..207dc97 100644 --- a/src/client.c +++ b/src/client.c @@ -16,7 +16,7 @@ typedef struct { str name; - uint64_t id; + entity_id id; } player; typedef struct { @@ -24,7 +24,7 @@ typedef struct { struct termios oldtio; str name; str pass; - uint64_t self_id; + entity_id self_id; array(player) players; str server_motd; chunk map; @@ -55,6 +55,46 @@ void gfx_clear() printf("\e[2J"); } +void gfx_render_node(client *c, vec2 pos, node *n) +{ + if (!n->present) { + gfx_set_color(color_from_u32(0x555555), true); + gfx_set_color(color_from_u32(0xffffff), false); + printf(" ?"); + return; + } + + gfx_set_color(n->col, true); + + if (vec2_eq(pos, c->player_pos)) { + printf("🥺"); + return; + } + + // TODO: persistence + switch (n->type) { + case N_GRASS: if (rand() % 10 == 0) { + gfx_set_color(color_from_u32(0x1c571e), false); + printf(" M"); + return; + } break; + case N_WATER: if (rand() % 10 == 0) { + gfx_set_color(color_from_u32(0x0d79de), false); + printf(" ~"); + return; + } break; + case N_SAND: if (rand() % 15 == 0) { + gfx_set_color(color_from_u32(0xe3a112), false); + printf(" ~"); + return; + } break; + default: break; + } + + printf(" "); +} + + void gfx_render(client *c, uint64_t dtime) { gfx_clear(); @@ -64,15 +104,9 @@ void gfx_render(client *c, uint64_t dtime) printf("%.*s\n", PSTR(c->players.data[i].name)); for (size_t y = 0; y < c->map.bounds.size.y; y++) { for (size_t x = 0; x < c->map.bounds.size.y; x++) { - node *n = chunk_index(c->map, UVEC2(x, y)); - if (!n->present) { - gfx_set_color(color_from_u32(0x555555), true); - gfx_set_color(color_from_u32(0xffffff), false); - printf("??"); - } else { - gfx_set_color(n->col, true); - printf(" "); - } + uvec2 off = UVEC2(x, y); + vec2 p = vec2_add(c->map.bounds.pos, CVEC2(off)); + gfx_render_node(c, p, chunk_index(c->map, off)); } gfx_clear_effects(); printf("\n"); @@ -107,48 +141,50 @@ void client_exit(client *c, int ret) exit(ret); } -void handle_input(client *c, char ch) +dir dir_from_key(char ch) { - ch = tolower(ch); switch (ch) { - case 'q': client_exit(c, EXIT_SUCCESS); break; - default: break; + case 'w': return DIR_UP; + case 'a': return DIR_LEFT; + case 's': return DIR_DOWN; + case 'd': return DIR_RIGHT; + default: return 4; } } +void handle_input(client *c, char ch) +{ + ch = tolower(ch); + + dir move; + if ((move = dir_from_key(ch)) != 4) + SEND_PKT(c->conn, SPKT_MOVE, ser_dir(&pkt, move);) +} + void map_set_center(client *c, vec2 center) { + vec2 pos = vec2_sub(center, CVEC2(uvec2_div(c->map.bounds.size, 2))); + + if (vec2_eq(c->map.bounds.pos, pos)) + return; + chunk old = c->map; c->map.data = c->map_swap; - c->map.bounds.pos = center; + c->map.bounds.pos = pos; c->map_swap = old.data; chunk_clear(c->map); chunk_copy(c->map, old); } -bool deser_color(str *r, color *c) -{ - return deser_u8(r, &c->r) && deser_u8(r, &c->g) && deser_u8(r, &c->b); -} - -bool deser_node(str *r, node *n) -{ - if (!deser_bool(r, &n->present)) return false; - if (!n->present) return true; - - return deser_i8(r, &n->z) - && deser_color(r, &n->col); -} - bool handle_nodes(str *pkt, client *c) { chunk ch; if (!deser_vec2(pkt, &ch.bounds.pos)) return false; if (!deser_uvec2(pkt, &ch.bounds.size)) return false; - if (ch.bounds.size.x * ch.bounds.size.y > NODES_PKT_MAX) return false; + if (ch.bounds.size.x * ch.bounds.size.y > PKT_NODES_MAX) return false; node nodes[ch.bounds.size.x * ch.bounds.size.y]; ch.pitch = ch.bounds.size.y; @@ -181,7 +217,7 @@ bool handle_players(str *pkt, client *c) for (c->players.len = 0; c->players.len < len; c->players.len++) { player *p = &c->players.data[c->players.len]; if (!deser_str(pkt, &p->name)) return false; - if (!deser_u64(pkt, &p->id)) return false; + if (!deser_entity_id(pkt, &p->id)) return false; if (str_eq(p->name, c->name)) c->self_id = p->id; p->name = str_clone(p->name); @@ -189,15 +225,47 @@ bool handle_players(str *pkt, client *c) return true; } -bool handle_hi(str *w, client *c) +bool handle_hi(str *pkt, client *c) { str motd; - if (!deser_str(w, &motd)) return false; + if (!deser_str(pkt, &motd)) return false; c->server_motd = str_clone(motd); return true; } +bool handle_entity(str *pkt, client *c) +{ + uint16_t num; + if (!deser_u16(pkt, &num)) return false; + for (uint16_t i = 0; i < num; i++) { + entity_id id; + entity_cmd cmd; + + if (!deser_entity_id(pkt, &id)) return false; + if (!deser_entity_cmd(pkt, &cmd)) return false; + + switch (cmd) { + case ENTITY_ADD: { + entity_type type; + if (!deser_entity_type(pkt, &type)) return false; + } break; + case ENTITY_REMOVE: break; + case ENTITY_MOVE: + vec2 pos; + if (!deser_vec2(pkt, &pos)) return false; + + if (id == c->self_id) + map_set_center(c, c->player_pos = pos); + + break; + default: return false; + } + } + + return true; +} + bool handle_pkt(client *c, str pkt) { pkt_type type; @@ -209,6 +277,7 @@ bool handle_pkt(client *c, str pkt) case CPKT_PLAYERS: return handle_players(&pkt, c); case CPKT_RESET_MAP: return handle_reset_map(&pkt, c); case CPKT_NODES: return handle_nodes(&pkt, c); + case CPKT_ENTITY: return handle_entity(&pkt, c); default: return false; } } |