| #include <string.h> |
| #include <stdlib.h> |
| #include <stdio.h> |
| |
| enum colum { |
| ENTITYSTAT_COLUM_WORLD, |
| ENTITYSTAT_COLUM_ID, |
| ENTITYSTAT_COLUM_TYPE, |
| ENTITYSTAT_COLUM_NAME, |
| ENTITYSTAT_COLUM_LOCATION, |
| ENTITYSTAT_COLUM_ROTATION, |
| ENTITYSTAT_COLUM_IS_ON_GROUND, |
| ENTITYSTAT_COLUM_IS_DEAD, |
| ENTITYSTAT_COLUM_WIDTH, |
| ENTITYSTAT_COLUM_HEIGHT, |
| ENTITYSTAT_COLUM_CHUNK, |
| ENTITYSTAT_COLUM_UUID, |
| ENTITYSTAT_COLUM_MAX_HEALTH, |
| ENTITYSTAT_COLUM_HEALTH, |
| ENTITYSTAT_COLUM_PERCENTAGE_HEALTH, |
| ENTITYSTAT_COLUM_IDLE_TIME, |
| ENTITYSTAT_COLUM_ATTACK_TARGET_ID, |
| }; |
| |
| static const struct colum_name_header_map_entry { |
| enum colum id; |
| const char *name; |
| const char *default_header_name; |
| } colum_name_header_map[] = { |
| { ENTITYSTAT_COLUM_WORLD, "world", "WORLD" }, |
| { ENTITYSTAT_COLUM_ID, "id", "ENTITY ID" }, |
| { ENTITYSTAT_COLUM_TYPE, "type", "TYPE" }, |
| { ENTITYSTAT_COLUM_NAME, "name", "DISPLAY NAME" }, |
| { ENTITYSTAT_COLUM_LOCATION, "location", "LOCATION" }, |
| { ENTITYSTAT_COLUM_ROTATION, "rotation", "ROTATION" }, |
| { ENTITYSTAT_COLUM_IS_ON_GROUND, "isonground", "IS ON GROUND" }, |
| { ENTITYSTAT_COLUM_IS_DEAD, "isdead", "IS DEAD" }, |
| { ENTITYSTAT_COLUM_WIDTH, "width", "WIDTH" }, |
| { ENTITYSTAT_COLUM_HEIGHT, "height", "HEIGHT" }, |
| { ENTITYSTAT_COLUM_CHUNK, "chunk", "CHUNK" }, |
| { ENTITYSTAT_COLUM_UUID, "uuid", "UUID" }, |
| { ENTITYSTAT_COLUM_MAX_HEALTH, "maxhealth", "MAX HEALTH" }, |
| { ENTITYSTAT_COLUM_HEALTH, "health", "THEALTH" }, |
| { ENTITYSTAT_COLUM_PERCENTAGE_HEALTH, "phealth", "%HEALTH" }, |
| { ENTITYSTAT_COLUM_IDLE_TIME, "idletime", "IDLE TIME" }, |
| { ENTITYSTAT_COLUM_ATTACK_TARGET_ID, "attacktarget", "ATTACK TARGET ID" }, |
| { -1, NULL, NULL } |
| }; |
| |
| struct format_configure_node { |
| enum colum colum; |
| const char *header_name; |
| }; |
| static const struct format_configure_node default_format_configuration[] = { |
| { ENTITYSTAT_COLUM_WORLD }, |
| { ENTITYSTAT_COLUM_ID }, |
| { ENTITYSTAT_COLUM_TYPE }, |
| { ENTITYSTAT_COLUM_NAME }, |
| { ENTITYSTAT_COLUM_LOCATION }, |
| { -1 } |
| }; |
| static struct format_configure_node *format_configuration; |
| static unsigned int custom_colum_count; |
| |
| static void add_colum(struct format_configure_node config) { |
| format_configuration = realloc(format_configuration, sizeof(struct format_configure_node) * (custom_colum_count + 2)); |
| if(!format_configuration) { |
| fputs("Out of memory\n", stderr); |
| exit(1); |
| } |
| format_configuration[custom_colum_count++] = config; |
| format_configuration[custom_colum_count] = (struct format_configure_node){ -1, NULL }; |
| } |
| |
| static enum colum get_colum(const char *name) { |
| const struct colum_name_header_map_entry *e = colum_name_header_map; |
| while(e->id != (enum colum)-1) { |
| if(strcmp(e->name, name) == 0) return e->id; |
| e++; |
| } |
| return -1; |
| } |
| |
| int entitystat_set_output_format(const char *format) { |
| if(!*format) { |
| fputs("output format specification cannot be empty\n", stderr); |
| return -1; |
| } |
| char *colum_name; |
| enum colum colum; |
| const char *p = format; |
| while(1) switch(*p) { |
| case 0: |
| case '=': |
| case ',': |
| colum_name = malloc(p - format + 1); |
| if(!colum_name) { |
| fputs("Out of memory\n", stderr); |
| exit(1); |
| } |
| memcpy(colum_name, format, p - format); |
| colum_name[p - format] = 0; |
| colum = get_colum(colum_name); |
| if(colum == (enum colum)-1) { |
| fprintf(stderr, "Unknown colum '%s'\n", colum_name); |
| return -1; |
| } |
| add_colum((struct format_configure_node){ colum, *p == '=' ? p + 1 : NULL }); |
| if(*p != ',') return 0; |
| format = p + 1; |
| // Fallthrough |
| default: |
| p++; |
| break; |
| } |
| } |