Program Listing for File player_look.c

Return to documentation for file (server/game_events/player_look.c)

#include <stddef.h>
#include <stdint.h>
#include <string.h>

#include "client/client.h"
#include "handler.h"
#include "server.h"

static const char *RES_NAMES[RES_COUNT] = {
    "food", "linemate", "deraumere", "sibur", "mendiane", "phiras", "thystame"
};

static constexpr const size_t TIER_MAX = 8;
static constexpr const size_t TIER_MAX_AREA = (TIER_MAX + 1) * (TIER_MAX + 1);

static
void rotate(int8_t delta[2], uint8_t direction)
{
    switch (direction) {
        case OR_NORTH:
            delta[1] = -delta[1];
            break;
        case OR_EAST:
            break;
        case OR_SOUTH:
            delta[0] = -delta[0];
            break;
        case OR_WEST:
            delta[0] = -delta[0];
            delta[1] = -delta[1];
            break;
        default:
            return;
    }
}

static
void fill_coords(
    uint8_t coords[][2], size_t, server_t *srv, client_state_t *cs)
{
    int8_t delta[2];
    size_t idx = 0;

    for (uint8_t l = 0; l < cs->tier + 1; l++) {
        for (int i = -l; i < l + 1; i++) {
            delta[0] = i;
            delta[1] = l;
            rotate(delta, cs->orientation);
            coords[idx][0] = cs->x + delta[0] + srv->map_width;
            coords[idx][1] = cs->y + delta[1] + srv->map_height;
            coords[idx][0] %= srv->map_width;
            coords[idx][1] %= srv->map_height;
            idx++;
        }
    }
}

static
uint16_t count_player_on_tile(
    server_t *srv, uint8_t x, uint8_t y)
{
    uint16_t count = 0;

    for (size_t i = srv->cm.idx_of_players; i < srv->cm.count; i++) {
        if (srv->cm.clients[i].x == x && srv->cm.clients[i].y == y) {
            count++;
        }
    }
    return count;
}

static
void serialize_item_on_tite(
    server_t *srv, client_state_t *cs,
    const uint8_t coords[2], bool prev)
{
    inventory_t *tile = &srv->map[coords[1]][coords[0]];

    for (size_t i = 0; i < RES_COUNT; i++) {
        if (tile->qnts[i] == 0)
            continue;
        for (size_t j = 0; j < tile->qnts[i]; j++) {
            append_to_output(srv, cs, prev ? " " : "");
            vappend_to_output(srv, cs, "%s", RES_NAMES[i]);
            prev = true;
        }
    }
}

static
void serialiaze_tile(
    server_t *srv, client_state_t *cs, uint8_t coords[][2], size_t idx)
{
    bool has_prev = false;
    uint16_t players_on_tile =
        count_player_on_tile(srv, coords[idx][0], coords[idx][1]);

    for (size_t i = 0; i < players_on_tile; i++) {
        vappend_to_output(srv, cs, "%splayer", has_prev ? " " : "");
        has_prev = true;
    }
    for (size_t i = 0; i < srv->eggs.nmemb; i++) {
        if (srv->eggs.buff[i].x != coords[idx][0]
            || srv->eggs.buff[i].y != coords[idx][1])
            continue;
        vappend_to_output(srv, cs, "%segg", has_prev ? " " : "");
        has_prev = true;
    }
    serialize_item_on_tite(srv, cs, coords[idx], has_prev);
}

bool player_look_handler(server_t *srv, const event_t *event)
{
    client_state_t *cs = event_get_client(srv, event);
    uint8_t coords[TIER_MAX_AREA][2];
    uint8_t view;

    if (cs == nullptr)
        return false;
    view = (cs->tier + 1) * (cs->tier + 1);
    fill_coords(coords, view, srv, cs);
    append_to_output(srv, cs, "[ ");
    for (size_t i = 0; i < view; i++) {
        if (i != 0)
            append_to_output(srv, cs, ", ");
        serialiaze_tile(srv, cs, coords, i);
    }
    append_to_output(srv, cs, " ]\n");
    return true;
}