diff options
Diffstat (limited to 'src/client.c')
-rw-r--r-- | src/client.c | 149 |
1 files changed, 102 insertions, 47 deletions
diff --git a/src/client.c b/src/client.c index 207dc97..964e91f 100644 --- a/src/client.c +++ b/src/client.c @@ -30,6 +30,9 @@ typedef struct { chunk map; node *map_swap; vec2 player_pos; + char *termbuf_buf; + size_t termbuf_size; + FILE *termbuf; } client; void gfx_alt_buffer(bool enable) @@ -38,79 +41,129 @@ void gfx_alt_buffer(bool enable) printf("\e[?1049h\e[?25l"); else printf("\e[?1049l\e[?25h"); + fflush(stdout); } -void gfx_clear_effects() +void gfx_clear_effects(client *c) { - printf("\e[0m"); + fprintf(c->termbuf, "\e[0m"); } -void gfx_set_color(color c, bool bg) +void gfx_set_color(client *c, color col, bool bg) { - printf("\e[%u;2;%u;%u;%um", bg ? 48 : 38, c.r, c.g, c.b); + fprintf(c->termbuf, "\e[%u;2;%u;%u;%um", bg ? 48 : 38, col.r, col.g, col.b); } -void gfx_clear() +void gfx_clear(client *c) { - printf("\e[2J"); + fprintf(c->termbuf, "\e[2J"); } -void gfx_render_node(client *c, vec2 pos, node *n) +#define C color_from_u32 +#define DISPLAY_BG(X) (node_display) { X, { 0 }, NULL } +#define DISPLAY(...) (node_display) { __VA_ARGS__ } +#define DISPLAY_ERR DISPLAY(C(0xff0000), C(0x000000), " ?") + +typedef struct { + color bg; + color fg; + char *texture; +} node_display; + +bool gfx_rock_bg(node *n, color *c) { - if (!n->present) { - gfx_set_color(color_from_u32(0x555555), true); - gfx_set_color(color_from_u32(0xffffff), false); - printf(" ?"); - return; + switch (n->z) { + case 1: *c = C(0x595959); return true; + case 2: *c = C(0x484848); return true; + case 3: *c = C(0x373737); return true; + default: return false; } +} - gfx_set_color(n->col, true); +color gfx_grass_bg(vec2 pos) +{ + return C(0x00880d); +} - if (vec2_eq(pos, c->player_pos)) { - printf("🥺"); - return; - } +bool gfx_water_wave(vec2 pos) +{ + return true; +} + +node_display gfx_render_node(client *c, vec2 pos, node *n) +{ + if (!n->present) + return DISPLAY(C(0x555555), C(0xffffff), " ?"); - // 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; + case N_VALLEY_FLOWER: + case N_MOUNTAIN_FLOWER: { + node_display d = {0}; + if (n->type == N_VALLEY_FLOWER) + d.bg = gfx_grass_bg(pos); + else if (!gfx_rock_bg(n, &d.bg)) + return DISPLAY_ERR; + switch (n->variant) { + case FLOWER_ROSE: d.texture = "🌹"; break; + case FLOWER_HIBISCUS: d.texture = "🌺"; break; + case FLOWER_SUNFLOWER: d.texture = "🌻"; break; + case FLOWER_DANDELION: d.texture = "🌼"; break; + case FLOWER_TULIP: d.texture = "🌷"; break; + default: return DISPLAY_ERR; + } + return d; + } + case N_ROCK: { + node_display d = {0}; + if (!gfx_rock_bg(n, &d.bg)) + return DISPLAY_ERR; + return d; + } + case N_WATER: return DISPLAY(C(0x00c6ff), C(0x0d79de), + n->variant && gfx_water_wave(pos) ? " ~" : NULL); + case N_GRASS: return DISPLAY(gfx_grass_bg(pos), C(0x1c571e), n->variant ? " M" : NULL); + case N_SAND: return DISPLAY(C(0xded485), C(0xe3a112), n->variant ? " ~" : NULL); + case N_NEEDLE_TREE: return DISPLAY_BG(C(0x015100)); + case N_PATH: return DISPLAY_BG(C(0xa09700)); + case N_PLANK: return DISPLAY_BG(C(0x5c3b12)); + case N_BIG_TREE: return DISPLAY_BG(C(0x016300)); + default: return DISPLAY_ERR; } - - printf(" "); } +#undef C +#undef DISPLAY +#undef DISPLAY_ERR void gfx_render(client *c, uint64_t dtime) { - gfx_clear(); - printf("\e[H"); - printf("%.*s\n", PSTR(c->server_motd)); + rewind(c->termbuf); + gfx_clear(c); + fprintf(c->termbuf, "\e[H"); + fprintf(c->termbuf, "%.*s\n", PSTR(c->server_motd)); for (size_t i = 0; i < c->players.len; i++) - printf("%.*s\n", PSTR(c->players.data[i].name)); + fprintf(c->termbuf, "%.*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++) { 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)); + vec2 pos = vec2_add(c->map.bounds.pos, CVEC2(off)); + + node_display dis = gfx_render_node(c, pos, chunk_index(c->map, off)); + gfx_set_color(c, dis.bg, true); + if (vec2_eq(pos, c->player_pos)) { + fprintf(c->termbuf, "🙂"); + } else if (dis.texture) { + gfx_set_color(c, dis.fg, false); + fprintf(c->termbuf, "%s", dis.texture); + } else { + fprintf(c->termbuf, " "); + } } - gfx_clear_effects(); - printf("\n"); + gfx_clear_effects(c); + fprintf(c->termbuf, "\n"); } + fflush(c->termbuf); + fwrite(c->termbuf_buf, 1, ftell(c->termbuf), stdout); fflush(stdout); } @@ -135,8 +188,10 @@ void client_exit(client *c, int ret) peer_free(&c->conn); tcsetattr(STDIN_FILENO, TCSANOW, &c->oldtio); + + fclose(c->termbuf); + free(c->termbuf_buf); gfx_alt_buffer(false); - fflush(stdout); exit(ret); } @@ -314,7 +369,7 @@ int main(int argc, char **argv) str server_name = S("server"); peer_init(&c.conn, socket, &server_name); - setvbuf(stdout, NULL, _IOFBF, 0); + c.termbuf = open_memstream(&c.termbuf_buf, &c.termbuf_size); gfx_alt_buffer(true); SEND_PKT(c.conn, SPKT_HI, @@ -326,7 +381,7 @@ int main(int argc, char **argv) c.map_swap = malloc(c.map.bounds.size.x * c.map.bounds.size.y * sizeof(node)); ticker t; - ticker_init(&t, NANOS/60); + ticker_init(&t, NANOS/30); for (;;) { struct pollfd fds[2]; |