diff options
| author | Mosder <xmosder12@gmail.com> | 2026-07-13 19:39:06 +0200 |
|---|---|---|
| committer | Mosder <xmosder12@gmail.com> | 2026-07-13 19:39:06 +0200 |
| commit | 2a45b1096325ac6743787b6f60fef4800223b2a6 (patch) | |
| tree | 382bd561706ecc1d71b4db2d69e67a51b1b0a566 | |
| parent | 32bb25cc2666809759371436a6450574b00c0e6d (diff) | |
feat: added basic parsing of fight results data
| -rw-r--r-- | analyzer/analyzer.c | 32 | ||||
| -rw-r--r-- | analyzer/parser/fight_results.c | 130 | ||||
| -rw-r--r-- | analyzer/parser/fight_results.h | 76 | ||||
| -rw-r--r-- | analyzer/parser/parser_defs.h | 5 |
4 files changed, 237 insertions, 6 deletions
diff --git a/analyzer/analyzer.c b/analyzer/analyzer.c index 5997c6d..03ecd2a 100644 --- a/analyzer/analyzer.c +++ b/analyzer/analyzer.c @@ -1,6 +1,7 @@ #include "analyzer.h" #include <stdlib.h> +#include <string.h> #include "parser/parser.h" #include "utils/tcp.h" @@ -35,12 +36,41 @@ void analyzer_loop(TCPStream *stream, pcap_t *pcap_handle, void (*parsed_data_ha } } +// prints fight resutls +void print_fight_results(FightResults results) { + printf("Enemies:\n\t"); + for (size_t i = 0; i < results.num_enemy; i++) { + EnemyResults enemy = results.enemy_results[i]; + printf("%s (%d)%s", enemy.name, enemy.level, i < results.num_enemy - 1 ? ", " : "\n"); + } + printf("Player rewards:\n"); + for (size_t i = 0; i < results.num_friendly; i++) { + FriendlyResults friendly = results.friendly_results[i]; + printf("\t%s (%d):\n", friendly.name, friendly.level); + printf("\t\texp: %d\n", friendly.exp); + printf("\t\tgold: %d\n", friendly.gold); + if (friendly.psycho > 0) + printf("\t\tpsycho: %d\n", friendly.psycho); + if (strlen(friendly.items) > 0) + printf("\t\titems: %s\n", friendly.items); + if (strlen(friendly.gear) > 0) + printf("\t\tgear: %s\n", friendly.gear); + if (strlen(friendly.drifs) > 0) + printf("\t\tdrifs: %s\n", friendly.drifs); + if (friendly.splinters > 0) + printf("\t\tsplinters: %d\n", friendly.splinters); + if (friendly.saturation > 0) + printf("\t\tsaturation: %d (%s)\n", friendly.saturation, friendly.saturation_type); + } + printf("\n"); +} + // file analyzer parsed data handler void file_parsed_data_handler(ParsedData *parsed_data, size_t n_parsed_data) { for (size_t i = 0; i < n_parsed_data; i++) { switch (parsed_data[i].data_type) { case TYPE_FIGHT_RESULTS: - printf("Fight results\n"); + print_fight_results(*(FightResults *)parsed_data[i].data); break; } } diff --git a/analyzer/parser/fight_results.c b/analyzer/parser/fight_results.c index 8275af2..4fbb0f8 100644 --- a/analyzer/parser/fight_results.c +++ b/analyzer/parser/fight_results.c @@ -25,15 +25,135 @@ byte_t *find_fight_results(TCPStream *stream, int offset, int *length) { return start; } +void destroy_entity_results(EntityResults results) { + free(results.name); + free(results.field7); + free(results.gear); + free(results.items); + free(results.drifs); + free(results.field29); + free(results.field34); + free(results.saturation); +} + +// get entity results from the string +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); + } + } + + return results; +} + +// parse EntityResults to FriendlyResults +FriendlyResults parse_to_friendly(EntityResults entity_results) { + FriendlyResults results; + + results.name = strdup(entity_results.name); + results.exp = entity_results.exp; + results.gold = entity_results.gold; + // TODO: parse that to more readable format + results.gear = strdup(entity_results.gear); + // TODO: parse that to more readable format, determine types from ids + results.items = strdup(entity_results.items); + results.level = entity_results.level; + results.psycho = entity_results.psycho; + // TODO: parse that to more readable format + results.drifs = strdup(entity_results.drifs); + results.splinters = entity_results.splinters; + + results.saturation = 0; + if (strlen(entity_results.saturation) > 0) { + int saturation_id; + sscanf(entity_results.saturation, "%d,%d", &saturation_id, &results.saturation); + // TODO: determine type + results.saturation_type = "typ"; + } + + return results; +} + +// parse EntityResults to EnemyResults +EnemyResults parse_to_enemy(EntityResults entity_results) { + EnemyResults results; + + results.name = strdup(entity_results.name); + results.level = entity_results.level; + + return results; +} + ParsedData parse_fight_results(byte_t *data, size_t length) { ParsedData parsed_data; parsed_data.data_type = TYPE_FIGHT_RESULTS; - // TODO: actually parse that data - printf("len=%zu\n%.*s\n----------------\n", length, (int)length, data); + // ignore start and end indicators + data += strlen(FIGHT_RESULTS_START); + length -= strlen(FIGHT_RESULTS_START) + strlen(FIGHT_RESULTS_END); + + FightResults *results = malloc(sizeof(FightResults)); + results->num_friendly = 0; + results->num_enemy = 0; + + byte_t *entity_separator; + do { + // get generic entity results + entity_separator = memmem(data, length, SEPARATOR_ENTITY, strlen(SEPARATOR_ENTITY)); + EntityResults entity_results = get_entity_results(data, entity_separator ? entity_separator - data : length); + + // depending on team - parse it into friendly or enemy results + switch (entity_results.team) { + case TEAM_FRIEND: + results->friendly_results[(results->num_friendly)++] = parse_to_friendly(entity_results); + break; + case TEAM_ENEMY: + results->enemy_results[results->num_enemy++] = parse_to_enemy(entity_results); + break; + } + destroy_entity_results(entity_results); + + // if there are still entities - modify data pointer and length + if (entity_separator) { + length -= entity_separator - data + strlen(SEPARATOR_ENTITY); + data = entity_separator + strlen(SEPARATOR_ENTITY); + } + } while (entity_separator); - parsed_data.data = NULL; - parsed_data.data_cleanup = NULL; - // parsed_data.data_cleanup = cleanup_fight_results; + parsed_data.data = results; + parsed_data.data_cleanup = cleanup_fight_results; return parsed_data; } diff --git a/analyzer/parser/fight_results.h b/analyzer/parser/fight_results.h index d8064ca..2712638 100644 --- a/analyzer/parser/fight_results.h +++ b/analyzer/parser/fight_results.h @@ -16,6 +16,82 @@ #define SEPARATOR_ENTITY "[--]" #define SEPARATOR_RESULT "&" +#define ENTITY_FIELD_COUNT 35 +#define ENTITY_FIELD_TYPES { \ + /* team */ INT, \ + /* name */ STRING, \ + /* exp */ INT, \ + /* field4 */ FLOAT, \ + /* gold */ INT, \ + /* field6 */ FLOAT, \ + /* field7 */ STRING, \ + /* gear */ STRING, \ + /* field9 */ INT, \ + /* items */ STRING, \ + /* field11 */ INT, \ + /* field12 */ INT, \ + /* field13 */ FLOAT, \ + /* field14 */ FLOAT, \ + /* field15 */ FLOAT, \ + /* level */ INT, \ + /* field17 */ DOUBLE, \ + /* field18 */ FLOAT, \ + /* field19 */ INT, \ + /* field20 */ INT, \ + /* field21 */ FLOAT, \ + /* field22 */ FLOAT, \ + /* field23 */ INT, \ + /* field24 */ INT, \ + /* psycho */ INT, \ + /* drifs */ STRING, \ + /* splinters */ INT, \ + /* field28 */ INT, \ + /* field29 */ STRING, \ + /* field30 */ INT, \ + /* field31 */ INT, \ + /* field32 */ INT, \ + /* field33 */ INT, \ + /* field34 */ STRING, \ + /* saturation */ STRING \ +} +#define ENTITY_FIELD_ADDRESSES(entity_results) {\ + &entity_results.team, \ + &entity_results.name, \ + &entity_results.exp, \ + &entity_results.field4, \ + &entity_results.gold, \ + &entity_results.field6, \ + &entity_results.field7, \ + &entity_results.gear, \ + &entity_results.field9, \ + &entity_results.items, \ + &entity_results.field11, \ + &entity_results.field12, \ + &entity_results.field13, \ + &entity_results.field14, \ + &entity_results.field15, \ + &entity_results.level, \ + &entity_results.field17, \ + &entity_results.field18, \ + &entity_results.field19, \ + &entity_results.field20, \ + &entity_results.field21, \ + &entity_results.field22, \ + &entity_results.field23, \ + &entity_results.field24, \ + &entity_results.psycho, \ + &entity_results.drifs, \ + &entity_results.splinters, \ + &entity_results.field28, \ + &entity_results.field29, \ + &entity_results.field30, \ + &entity_results.field31, \ + &entity_results.field32, \ + &entity_results.field33, \ + &entity_results.field34, \ + &entity_results.saturation \ +} + #ifndef ENTITY_RESULTS_DEFINED #define ENTITY_RESULTS_DEFINED typedef struct { diff --git a/analyzer/parser/parser_defs.h b/analyzer/parser/parser_defs.h index f99c2f3..b76b7e6 100644 --- a/analyzer/parser/parser_defs.h +++ b/analyzer/parser/parser_defs.h @@ -3,6 +3,11 @@ #include "../utils/tcp.h" +#ifndef TYPE_ENUM_DEFINED +#define TYPE_ENUM_DEFINED +typedef enum { INT, FLOAT, DOUBLE, STRING } TypeEnum; +#endif + #ifndef RESULTS_ENUM_DEFINED #define RESULTS_ENUM_DEFINED typedef enum { TYPE_FIGHT_RESULTS } ResultsEnum; |
