summaryrefslogtreecommitdiff
path: root/src/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/client.c')
-rw-r--r--src/client.c137
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;
}
}