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