aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMosder <xmosder12@gmail.com>2026-07-13 19:39:06 +0200
committerMosder <xmosder12@gmail.com>2026-07-13 19:39:06 +0200
commit2a45b1096325ac6743787b6f60fef4800223b2a6 (patch)
tree382bd561706ecc1d71b4db2d69e67a51b1b0a566
parent32bb25cc2666809759371436a6450574b00c0e6d (diff)
feat: added basic parsing of fight results data
-rw-r--r--analyzer/analyzer.c32
-rw-r--r--analyzer/parser/fight_results.c130
-rw-r--r--analyzer/parser/fight_results.h76
-rw-r--r--analyzer/parser/parser_defs.h5
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;