diff options
-rw-r--r-- | client.c | 71 |
1 files changed, 70 insertions, 1 deletions
diff --git a/client.c b/client.c index 9e7ab5d..652542c 100644 --- a/client.c +++ b/client.c @@ -37,6 +37,8 @@ #define err(...) do { endwin(); err(__VA_ARGS__); } while(0) #define errx(...) do { endwin(); errx(__VA_ARGS__); } while (0) +#define DIV_ROUND(a, b) (((a) + (b) / 2) / (b)) + #define CTRL(ch) ((ch) ^ 0x40) enum { ESC = 0x1B, @@ -152,7 +154,60 @@ static void serverCursor(struct ServerMessage msg) { } } +static const uint8_t MAP_X = (CELL_COLS / 2) - (3 * MAP_COLS / 2); +static const uint8_t MAP_Y = (CELL_ROWS / 2) - (MAP_ROWS / 2); + +static const wchar_t MAP_CELLS[5] = L" ░▒▓█"; +static const uint8_t MAP_COLORS[] = { + COLOR_BLUE, COLOR_CYAN, COLOR_GREEN, COLOR_YELLOW, COLOR_RED, +}; + static void serverMap(void) { + int t = MAP_Y - 1; + int l = MAP_X - 1; + int b = MAP_Y + MAP_ROWS; + int r = MAP_X + 3 * MAP_COLS; + color_set(colorPair(COLOR_WHITE), NULL); + mvhline(t, MAP_X, ACS_HLINE, 3 * MAP_COLS); + mvhline(b, MAP_X, ACS_HLINE, 3 * MAP_COLS); + mvvline(MAP_Y, l, ACS_VLINE, MAP_ROWS); + mvvline(MAP_Y, r, ACS_VLINE, MAP_ROWS); + mvaddch(t, l, ACS_ULCORNER); + mvaddch(t, r, ACS_URCORNER); + mvaddch(b, l, ACS_LLCORNER); + mvaddch(b, r, ACS_LRCORNER); + color_set(0, NULL); + + struct Map map; + ssize_t size = recv(client, &map, sizeof(map), 0); + if (size < 0) err(EX_IOERR, "recv"); + if ((size_t)size < sizeof(map)) errx(EX_PROTOCOL, "truncated map"); + + if (0 == map.max.modifyCount) return; + if (0 == map.now - map.min.createTime) return; + + for (uint8_t y = 0; y < MAP_ROWS; ++y) { + for (uint8_t x = 0; x < MAP_COLS; ++x) { + struct Meta meta = map.meta[y][x]; + + uint32_t count = DIV_ROUND( + (ARRAY_LEN(MAP_CELLS) - 1) * meta.modifyCount, + map.max.modifyCount + ); + uint32_t time = DIV_ROUND( + (ARRAY_LEN(MAP_COLORS) - 1) * (meta.modifyTime - map.min.createTime), + map.now - map.min.createTime + ); + if (!meta.modifyTime) time = 0; + + wchar_t cell = MAP_CELLS[count]; + uint8_t color = MAP_COLORS[time]; + wchar_t tile[] = { cell, cell, cell, L'\0' }; + attr_set(colorAttr(color), colorPair(color), NULL); + mvaddwstr(MAP_Y + y, MAP_X + 3 * x, tile); + } + } + attr_set(A_NORMAL, 0, NULL); } static void readMessage(void) { @@ -207,6 +262,7 @@ static struct { enum { MODE_NORMAL, MODE_HELP, + MODE_MAP, MODE_DIRECTION, MODE_INSERT, MODE_REPLACE, @@ -235,6 +291,11 @@ static void modeHelp(void) { drawTile(HELP); input.mode = MODE_HELP; } +static void modeMap(void) { + curs_set(0); + clientMap(); + input.mode = MODE_MAP; +} static void modeNormal(void) { curs_set(1); move(cellY, cellX); @@ -394,6 +455,7 @@ static void inputNormal(wchar_t ch) { } break; case '?': modeHelp(); + break; case 'm': modeMap(); break; case 'R': modeDraw(); break; case 'r': modeReplace(); cellCopy(); break; case 'I': modeDirection(); @@ -408,6 +470,12 @@ static void inputHelp(wchar_t ch) { modeNormal(); } +static void inputMap(wchar_t ch) { + (void)ch; + drawTile(&tile); + modeNormal(); +} + static void inputDirection(wchar_t ch) { switch (ch) { break; case ESC: modeNormal(); @@ -477,8 +545,9 @@ static void readInput(void) { return; } switch (input.mode) { - break; case MODE_HELP: inputHelp(ch); break; case MODE_NORMAL: inputNormal(ch); + break; case MODE_HELP: inputHelp(ch); + break; case MODE_MAP: inputMap(ch); break; case MODE_DRAW: inputDraw(ch); break; case MODE_REPLACE: inputReplace(ch); break; case MODE_DIRECTION: inputDirection(ch); |