diff options
| author | Mosder <xmosder12@gmail.com> | 2026-07-20 17:58:02 +0200 |
|---|---|---|
| committer | Mosder <xmosder12@gmail.com> | 2026-07-20 17:58:02 +0200 |
| commit | f73349115edbc75021885eefd33ee33ee504d9a7 (patch) | |
| tree | 5d2d79af731bcbc85d07e9d6dd69f6c836c25a5b | |
| parent | c182f2f4f850589c23b2241e11dab143e1003ff2 (diff) | |
feat: added drif parsing and coloring of items depending on type
| -rw-r--r-- | analyzer/parser/fight_results.c | 144 | ||||
| -rw-r--r-- | analyzer/parser/fight_results.h | 91 | ||||
| -rw-r--r-- | analyzer/render.c | 23 | ||||
| -rw-r--r-- | analyzer/render.h | 7 |
4 files changed, 205 insertions, 60 deletions
diff --git a/analyzer/parser/fight_results.c b/analyzer/parser/fight_results.c index 5cda649..f201fb1 100644 --- a/analyzer/parser/fight_results.c +++ b/analyzer/parser/fight_results.c @@ -14,7 +14,7 @@ void cleanup_fight_results(void *data) { FriendlyResults friendly = fight_results->friendly_results[i]; free(friendly.name); for (size_t j = 0; j < friendly.num_items; j++) - free(friendly.items[j]); + free(friendly.items[j].data); free(friendly.items); } for (size_t i = 0; i < fight_results->num_enemy; i++) { @@ -29,6 +29,47 @@ byte_t *find_fight_results(TCPStream *stream, int offset, int *length) { return start; } +// save to a field in struct depending on the type +void save_to_struct(TypeEnum type, void *field, char *src, size_t src_len) { + char *str = malloc(src_len + 1); + memcpy(str, src, src_len); + str[src_len] = '\0'; + + // parse depending on variable type + switch (type) { + case INT: + sscanf(str, "%d", (int *)field); + free(str); + break; + case FLOAT: + sscanf(str, "%f", (float *)field); + free(str); + break; + case DOUBLE: + sscanf(str, "%lf", (double *)field); + free(str); + break; + case STRING: + *(char **)field = str; + break; + } +} + +// fill struct fields from given data of given length +void get_struct_data(size_t field_count, TypeEnum *field_types, void **field_pointers, char *data_separator, char *data, size_t data_len) { + for (size_t i = 0; i < field_count; i++) { + char *sep = memmem(data, data_len, data_separator, strlen(data_separator)); + size_t len = sep ? sep - data : data_len; + save_to_struct(field_types[i], field_pointers[i], (char *)data, len); + + // update data pointer and length + if (sep) { + data_len -= sep - data + strlen(SEPARATOR_RESULT); + data = sep + strlen(SEPARATOR_RESULT); + } + } +} + void destroy_entity_results(EntityResults results) { free(results.name); free(results.field7); @@ -45,52 +86,14 @@ EntityResults get_entity_results(byte_t *data, size_t length) { EntityResults results; TypeEnum field_types[ENTITY_FIELD_COUNT] = ENTITY_FIELD_TYPES; void *field_pointers[ENTITY_FIELD_COUNT] = ENTITY_FIELD_ADDRESSES(results); - - for (size_t i = 0; i < ENTITY_FIELD_COUNT; i++) { - // get string buffer of given result - byte_t *result_separator = memmem(data, length, SEPARATOR_RESULT, strlen(SEPARATOR_RESULT)); - size_t len = result_separator ? result_separator - data : length; - char *str = malloc(len + 1); - memcpy(str, data, len); - str[len] = '\0'; - - // parse depending on variable type - switch (field_types[i]) { - case INT: - sscanf(str, "%d", (int *)field_pointers[i]); - free(str); - break; - case FLOAT: - sscanf(str, "%f", (float *)field_pointers[i]); - free(str); - break; - case DOUBLE: - sscanf(str, "%lf", (double *)field_pointers[i]); - free(str); - break; - case STRING: - *(char **)field_pointers[i] = str; - break; - } - - // update data pointer and length - if (result_separator) { - length -= result_separator - data + strlen(SEPARATOR_RESULT); - data = result_separator + strlen(SEPARATOR_RESULT); - } - } - + get_struct_data(ENTITY_FIELD_COUNT, field_types, field_pointers, SEPARATOR_RESULT, (char *)data, length); return results; } -char *get_item_name(int item_id) { - return item_id < id_to_item_name_len ? id_to_item_name[item_id] : "null"; -} - -char **expand_items(char **items, size_t *items_capacity, size_t to_fit) { +Item *expand_items(Item *items, size_t *items_capacity, size_t to_fit) { while (*items_capacity < to_fit) *items_capacity <<= 1; - return realloc(items, *items_capacity * sizeof(char *)); + return realloc(items, *items_capacity * sizeof(Item)); } void add_gear(FriendlyResults *results, size_t *items_capacity, char *gear_str) { @@ -101,18 +104,58 @@ void add_gear(FriendlyResults *results, size_t *items_capacity, char *gear_str) if (results->num_items >= *items_capacity) results->items = expand_items(results->items, items_capacity, results->num_items + 1); - results->items[results->num_items++] = strdup(gear_str); + Item item; + item.data = strdup(gear_str); + item.type = RARE; + results->items[results->num_items++] = item; +} + +void destroy_drif(Drif drif) { + free(drif.field1); + free(drif.field4); + free(drif.field11); + free(drif.field12); + free(drif.name); + free(drif.field18); + free(drif.field19); +} + +Drif get_drif(char *data, size_t length) { + Drif drif; + TypeEnum field_types[DRIF_FIELD_COUNT] = DRIF_FIELD_TYPES; + void *field_pointers[DRIF_FIELD_COUNT] = DRIF_FIELD_ADDRESSES(drif); + get_struct_data(DRIF_FIELD_COUNT, field_types, field_pointers, SEPARATOR_DRIF_INFO, data, length); + return drif; } void add_drifs(FriendlyResults *results, size_t *items_capacity, char *drifs_str) { if (strlen(drifs_str) == 0) return; - // TODO: parse - if (results->num_items >= *items_capacity) - results->items = expand_items(results->items, items_capacity, results->num_items + 1); + char *drifs_separator; + do { + drifs_separator = strstr(drifs_str, SEPARATOR_DRIFS); + Drif drif = get_drif(drifs_str, drifs_separator ? drifs_separator - drifs_str : strlen(drifs_str)); - results->items[results->num_items++] = strdup(drifs_str); + // if there are still drifs - modify drifs_str pointer + if (drifs_separator) + drifs_str = drifs_separator + strlen(SEPARATOR_DRIFS); + + // expand if needed + if (results->num_items >= *items_capacity) + results->items = expand_items(results->items, items_capacity, results->num_items + 1); + + Item item; + item.data = strdup(drif.name); + item.type = DRIF; + results->items[results->num_items++] = item; + + destroy_drif(drif); + } while (drifs_separator); +} + +char *get_item_name(int item_id) { + return item_id < id_to_item_name_len ? id_to_item_name[item_id] : "null"; } void add_items(FriendlyResults *results, size_t *items_capacity, char *items_str) { @@ -136,7 +179,10 @@ void add_items(FriendlyResults *results, size_t *items_capacity, char *items_str if (results->num_items >= *items_capacity) results->items = expand_items(results->items, items_capacity, results->num_items + 1); - results->items[results->num_items++] = strdup(buffer); + Item item; + item.data = strdup(buffer); + item.type = NORMAL; + results->items[results->num_items++] = item; } while (items_separator); } @@ -157,7 +203,7 @@ FriendlyResults parse_to_friendly(EntityResults entity_results) { // create items array and add to it gear, drifs and items results.num_items = 0; - results.items = malloc(INIT_ITEMS_CAPACITY * sizeof(char *)); + results.items = malloc(INIT_ITEMS_CAPACITY * sizeof(Item)); size_t items_cap = INIT_ITEMS_CAPACITY; add_gear(&results, &items_cap, entity_results.gear); add_drifs(&results, &items_cap, entity_results.drifs); diff --git a/analyzer/parser/fight_results.h b/analyzer/parser/fight_results.h index 3aadf09..76083ab 100644 --- a/analyzer/parser/fight_results.h +++ b/analyzer/parser/fight_results.h @@ -9,17 +9,16 @@ // Payload structure: // FIGHT_RESULTS_START EntityResults (SEPARATOR_ENTITY EntityResults)* FIGHT_RESULTS_END -// -// EntityResults structure: -// field (SEPARATOR_RESULT field)* -// fields are defined in order in the EntityResults struct - #define FIGHT_RESULTS_START "3;19;" #define FIGHT_RESULTS_END "[--];" #define SEPARATOR_ENTITY "[--]" #define SEPARATOR_RESULT "&" +// EntityResults structure: +// field (SEPARATOR_RESULT field)* +// fields are defined in order in the EntityResults struct #define ENTITY_FIELD_COUNT 35 +// clang-format off #define ENTITY_FIELD_TYPES { \ /* team */ INT, \ /* name */ STRING, \ @@ -94,7 +93,7 @@ &entity_results.field34, \ &entity_results.saturation \ } - +// clang-format on typedef struct { int team; // friend or enemy char *name; @@ -137,6 +136,84 @@ typedef struct { #define INIT_ITEMS_CAPACITY 8 #define SINGLE_ITEM_BUFFER_LEN 128 #define SEPARATOR_ITEMS "[-]" +#define SEPARATOR_DRIFS "???" // TODO: change it to correct one which idk at this moment +#define SEPARATOR_DRIF_INFO "," +// Item struct - for keeping item string and type +typedef enum { NORMAL, DRIF, SYNG, SET, RARE, EPIC } ItemType; +typedef struct { + char *data; + ItemType type; +} Item; + +// Drif structure: +// field (SEPARATOR_DRIF field)* +// fields are defined in order in the Drif struct +#define DRIF_FIELD_COUNT 19 +// clang-format off +#define DRIF_FIELD_TYPES { \ + /* field1 */ STRING, \ + /* field2 */ INT, \ + /* field3 */ INT, \ + /* field4 */ STRING, \ + /* field5 */ INT, \ + /* field6 */ INT, \ + /* field7 */ FLOAT, \ + /* field8 */ FLOAT, \ + /* field9 */ INT, \ + /* field10 */ INT, \ + /* field11 */ STRING, \ + /* field12 */ STRING, \ + /* field13 */ INT, \ + /* field14 */ INT, \ + /* field15 */ INT, \ + /* field16 */ INT, \ + /* name */ STRING, \ + /* field18 */ STRING, \ + /* field19 */ STRING, \ +} +#define DRIF_FIELD_ADDRESSES(drif) {\ + &drif.field1, \ + &drif.field2, \ + &drif.field3, \ + &drif.field4, \ + &drif.field5, \ + &drif.field6, \ + &drif.field7, \ + &drif.field8, \ + &drif.field9, \ + &drif.field10, \ + &drif.field11, \ + &drif.field12, \ + &drif.field13, \ + &drif.field14, \ + &drif.field15, \ + &drif.field16, \ + &drif.name, \ + &drif.field18, \ + &drif.field19, \ +} +// clang-format on +typedef struct { + char *field1; + int field2; + int field3; + char *field4; + int field5; + int field6; + float field7; + float field8; + int field9; + int field10; + char *field11; + char *field12; + int field13; + int field14; + int field15; + int field16; + char *name; // <size>drif <name> + char *field18; + char *field19; +} Drif; // values of field "team" #define TEAM_FRIEND 1 @@ -147,7 +224,7 @@ typedef struct { char *name; int exp; int gold; - char **items; + Item *items; size_t num_items; int level; int psycho; diff --git a/analyzer/render.c b/analyzer/render.c index 402fcb5..28d1673 100644 --- a/analyzer/render.c +++ b/analyzer/render.c @@ -75,6 +75,24 @@ void print_column_names() { printf("\n"); } +int item_type_to_color(ItemType type) { + switch (type) { + case NORMAL: + return COLOR_WHITE; + case DRIF: + return COLOR_YELLOW; + case SYNG: + return COLOR_RED; + case SET: + return COLOR_GREEN; + case RARE: + return COLOR_AQUA; + case EPIC: + return COLOR_PURPLE; + } + return COLOR_WHITE; +} + void print_player_rewards(FriendlyResults results) { char buffers[TABLE_COLUMN_COUNT][TABLE_LINE_WIDTH]; size_t widths[TABLE_COLUMN_COUNT] = TABLE_COLUMN_WIDTHS; @@ -116,12 +134,13 @@ void print_player_rewards(FriendlyResults results) { size_t line_len = 0; for (size_t i = 0; i < results.num_items; i++) { char *sep = i < results.num_items - 1 ? ", " : ""; - size_t item_len = utf8_strlen(results.items[i]) + strlen(sep); + size_t item_len = utf8_strlen(results.items[i].data) + strlen(sep); if (line_len + item_len > TABLE_ITEMS_WIDTH) { printf("%*s" TABLE_LINE_END "\n" TABLE_LINE_START, (int)(TABLE_ITEMS_WIDTH - line_len), ""); line_len = 0; } - printf("%s%s", results.items[i], sep); + print_color(results.items[i].data, item_type_to_color(results.items[i].type)); + printf("%s", sep); line_len += item_len; } printf("%*s" TABLE_LINE_END "\n", (int)(TABLE_ITEMS_WIDTH - line_len), ""); diff --git a/analyzer/render.h b/analyzer/render.h index d54015a..97958d1 100644 --- a/analyzer/render.h +++ b/analyzer/render.h @@ -6,10 +6,11 @@ // ANSI escape sequence colors #define COLOR_RED 91 #define COLOR_GREEN 92 -#define COLOR_WHITE 97 #define COLOR_YELLOW 93 -#define COLOR_AQUA 96 #define COLOR_BLUE 94 +#define COLOR_PURPLE 95 +#define COLOR_AQUA 96 +#define COLOR_WHITE 97 #define TABLE_ROW_SEPARATOR_CHAR '-' @@ -29,6 +30,7 @@ #define TABLE_SATURATION_WIDTH 13 #define TABLE_SPLINTERS_WIDTH 9 +// clang-format off #define TABLE_COLUMN_NAMES {"Nick (LVL)", "EXP", "Gold", "Psycho", "Saturation", "Splinters"} #define TABLE_COLUMN_COLORS {COLOR_WHITE, COLOR_WHITE, COLOR_YELLOW, COLOR_AQUA, COLOR_GREEN, COLOR_BLUE} #define TABLE_COLUMN_WIDTHS { \ @@ -51,6 +53,7 @@ (TABLE_COLUMN_COUNT - 1) * TABLE_LINE_SEPARATOR_WIDTH + \ TABLE_LINE_END_WIDTH \ ) +// clang-format on #define TABLE_ITEMS_WIDTH (TABLE_LINE_WIDTH - TABLE_LINE_START_WIDTH - TABLE_LINE_END_WIDTH) |
