aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMosder <xmosder12@gmail.com>2026-07-20 17:58:02 +0200
committerMosder <xmosder12@gmail.com>2026-07-20 17:58:02 +0200
commitf73349115edbc75021885eefd33ee33ee504d9a7 (patch)
tree5d2d79af731bcbc85d07e9d6dd69f6c836c25a5b
parentc182f2f4f850589c23b2241e11dab143e1003ff2 (diff)
feat: added drif parsing and coloring of items depending on type
-rw-r--r--analyzer/parser/fight_results.c144
-rw-r--r--analyzer/parser/fight_results.h91
-rw-r--r--analyzer/render.c23
-rw-r--r--analyzer/render.h7
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)