Skip to content
This repository was archived by the owner on Aug 20, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
211 changes: 99 additions & 112 deletions src/internal/json/parse_json_state.c
Original file line number Diff line number Diff line change
@@ -1,155 +1,142 @@
#include "core_lib_internal.h"

static void core_static_applyObjToArray(t_obj obj)
static void core_static_updateObj(t_obj *existingObj, json_node *updates)
{
if (game.objects == NULL)
if (updates->type != JSON_TYPE_OBJECT)
{
game.objects = malloc(sizeof(t_obj *) * 1);
if (!game.objects)
{
perror("malloc");
exit(EXIT_FAILURE);
}
game.objects[0] = NULL;
char *updatesFormatted = json_to_string(updates);
printf("Error: Supplied json node is not an array. Got: %s\n", updatesFormatted);
free (updatesFormatted);
return;
}

obj.state = STATE_ALIVE;
if (existingObj->state == STATE_UNINITIALIZED)
existingObj->state = STATE_ALIVE; // units come alive on first update

// 1. LOOP: Id Matching
for (size_t index = 0; game.objects[index] != NULL; index++)
for (int i = 0; updates->array && updates->array[i]; i++)
{
if (game.objects[index]->id != obj.id)
continue;

t_obj *existingObj = game.objects[index];
json_node *property = updates->array[i];

existingObj->type = obj.type;
existingObj->state = STATE_ALIVE;
existingObj->id = obj.id;
existingObj->pos = obj.pos;
existingObj->hp = obj.hp;
switch (obj.type)
// even non-changing properties are included so the function can also fully set all fields of an empty obj
if (strncmp(property->key, "state", 5) == 0)
{
if (strncmp(property->string, "dead", 4) == 0)
existingObj->state = STATE_DEAD;
}
else if (strncmp(property->key, "x", 1) == 0)
existingObj->pos.x = property->number;
else if (strncmp(property->key, "y", 1) == 0)
existingObj->pos.y = property->number;
else if (strncmp(property->key, "hp", 2) == 0)
existingObj->hp = property->number;
else if (strncmp(property->key, "type", 4) == 0)
existingObj->type = property->number;
else if (strncmp(property->key, "id", 2) == 0)
existingObj->id = property->number;
else if (strncmp(property->key, "unit_type", 9) == 0)
existingObj->s_unit.unit_type = property->number;
else if (strncmp(property->key, "teamId", 6) == 0)
{
switch ((int)existingObj->type)
{
case OBJ_CORE: existingObj->s_core.team_id = property->number; break;
case OBJ_UNIT: existingObj->s_unit.team_id = property->number; break;
}
}
else if (strncmp(property->key, "balance", 7) == 0)
{
case OBJ_UNIT:
existingObj->s_unit = obj.s_unit;
break;
case OBJ_CORE:
existingObj->s_core = obj.s_core;
break;
case OBJ_RESOURCE:
case OBJ_MONEY:
existingObj->s_resource_money = obj.s_resource_money;
break;
case OBJ_BOMB:
existingObj->s_bomb = obj.s_bomb;
break;
default:
break;
switch ((int)existingObj->type)
{
case OBJ_CORE: existingObj->s_core.balance = property->number; break;
case OBJ_UNIT: existingObj->s_unit.balance = property->number; break;
case OBJ_MONEY:
case OBJ_RESOURCE: existingObj->s_resource_money.balance = property->number; break;
}
}
else if (strncmp(property->key, "moveCooldown", 12) == 0)
existingObj->s_unit.move_cooldown = property->number;
else if (strncmp(property->key, "countdown", 9) == 0)
existingObj->s_bomb.countdown = property->number;
}
}

return;
static void core_static_applyObjToArray(json_node *new_obj)
{
if (new_obj->type != JSON_TYPE_OBJECT)
return; // empty obj, no updates

long unsigned int new_obj_id = -1;
long unsigned int new_obj_type = -1;
long unsigned int new_obj_team_id = -1;
long unsigned int new_obj_unit_type = -1;

for (int i = 0; new_obj->array && new_obj->array[i]; i++)
{
json_node *parameter = new_obj->array[i];
if (strncmp(parameter->key, "id", 2) == 0)
new_obj_id = parameter->number;
else if (strncmp(parameter->key, "teamId", 6) == 0)
new_obj_team_id = parameter->number;
else if (strncmp(parameter->key, "unit_type", 9) == 0)
new_obj_unit_type = parameter->number;
else if (strncmp(parameter->key, "type", 4) == 0)
new_obj_type = parameter->number;
}

// 2. LOOP: Placeholder matching
for (size_t index = 0; game.objects[index] != NULL; index++)
{
if (obj.type != OBJ_UNIT)
continue;

if ((game.objects[index]->s_unit.unit_type != obj.s_unit.unit_type) || (game.objects[index]->s_unit.team_id != obj.s_unit.team_id))
continue;

t_obj *existingObj = game.objects[index];
existingObj->type = obj.type;
existingObj->state = STATE_ALIVE;
existingObj->id = obj.id;
existingObj->pos = obj.pos;
existingObj->hp = obj.hp;
switch (obj.type)
// Update obj -> id
bool id_match = (game.objects[index]->id == new_obj_id);
// Update uninitialized unit initially
bool spawn_unit_match = (new_obj_type == OBJ_UNIT && \
game.objects[index]->state == STATE_UNINITIALIZED && \
game.objects[index]->s_unit.unit_type == new_obj_unit_type && \
game.objects[index]->s_unit.team_id == new_obj_team_id);
if (id_match || spawn_unit_match)
{
case OBJ_UNIT:
existingObj->s_unit = obj.s_unit;
break;
case OBJ_CORE:
existingObj->s_core = obj.s_core;
break;
case OBJ_RESOURCE:
case OBJ_MONEY:
existingObj->s_resource_money = obj.s_resource_money;
break;
case OBJ_BOMB:
existingObj->s_bomb = obj.s_bomb;
break;
default:
break;
core_static_updateObj(game.objects[index], new_obj);
return;
}
return;
}

if (obj.type == OBJ_UNIT && obj.s_unit.team_id == game.my_team_id)
if (new_obj_type == OBJ_UNIT && new_obj_team_id == game.my_team_id)
{
printf("Error matching team units. This is never supposed to happen. Have you freed something you shouldn't have? Never free t_obj*s, just read them. Troublemaker: [id %lu, unit_type %lu, team %lu]\n", obj.id, obj.s_unit.unit_type, obj.s_unit.team_id);
printf("Error matching team units. This is never supposed to happen. Have you freed something you shouldn't have? Never free t_obj*s, just read them. Troublemaker: [id %lu, unit_type %lu, team %lu]\n", new_obj_id, new_obj_unit_type, new_obj_team_id);
}

// 3. Add to the back
// Add new obj
size_t arrLen = 0;
while (game.objects[arrLen] != NULL)
arrLen++;
game.objects = realloc(game.objects, sizeof(t_obj *) * (arrLen + 2));
game.objects[arrLen + 1] = NULL;
game.objects[arrLen] = malloc(sizeof(t_obj));
t_obj *newObj = game.objects[arrLen];
*newObj = obj;
newObj->state = STATE_ALIVE;
core_static_updateObj(game.objects[arrLen], new_obj);
game.objects[arrLen]->state = STATE_ALIVE;
}

void core_internal_parse_state(char *json)
{
json_node *root = string_to_json(json);

game.elapsed_ticks = (unsigned long)json_find(root, "tick")->number;

json_node *objects = json_find(root, "objects");

if (game.objects != NULL)
for (size_t i = 0; game.objects[i] != NULL; i++)
if (game.objects[i]->state == STATE_ALIVE)
game.objects[i]->state = STATE_DEAD;

for (int i = 0; objects->array != NULL && objects->array[i] != NULL; i++)
if (game.objects == NULL)
{
t_obj readObj;
readObj.id = (unsigned long)json_find(objects->array[i], "id")->number;
readObj.type = (t_obj_type)json_find(objects->array[i], "type")->number;
readObj.pos.x = (unsigned short)json_find(objects->array[i], "x")->number;
readObj.pos.y = (unsigned short)json_find(objects->array[i], "y")->number;
readObj.hp = (unsigned long)json_find(objects->array[i], "hp")->number;

// object-specific fields (wall doesn't have any)
if (readObj.type == OBJ_CORE)
{
readObj.s_core.team_id = (unsigned long)json_find(objects->array[i], "teamId")->number;
readObj.s_core.balance = (unsigned long)json_find(objects->array[i], "balance")->number;
}
if (readObj.type == OBJ_UNIT)
{
readObj.s_unit.unit_type = (unsigned long)json_find(objects->array[i], "unit_type")->number;
readObj.s_unit.team_id = (unsigned long)json_find(objects->array[i], "teamId")->number;
readObj.s_unit.balance = (unsigned long)json_find(objects->array[i], "balance")->number;
readObj.s_unit.move_cooldown = (unsigned long)json_find(objects->array[i], "moveCooldown")->number;
}
if (readObj.type == OBJ_RESOURCE || readObj.type == OBJ_MONEY)
{
readObj.s_resource_money.balance = (unsigned long)json_find(objects->array[i], "balance")->number;
}
if (readObj.type == OBJ_BOMB)
game.objects = malloc(sizeof(t_obj *) * 1);
if (!game.objects)
{
readObj.s_bomb.countdown = (unsigned long)json_find(objects->array[i], "countdown")->number;
perror("malloc");
exit(EXIT_FAILURE);
}

core_static_applyObjToArray(readObj);
game.objects[0] = NULL;
}

game.elapsed_ticks = (unsigned long)json_find(root, "tick")->number;

json_node *objects = json_find(root, "objects");
if (objects && objects->type == JSON_TYPE_ARRAY)
for (int i = 0; objects->array != NULL && objects->array[i] != NULL; i++)
core_static_applyObjToArray(objects->array[i]);

// clean uninitialized units, as the server did not send them
if (game.objects && game.objects[0])
{
Expand Down
2 changes: 1 addition & 1 deletion src/public/get.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ t_obj *core_get_obj_from_pos(t_pos pos)
{
if (game.objects && game.objects[0] != NULL)
for (int i = 0; game.objects[i] != NULL; i++)
if (game.objects[i]->pos.x == pos.x && game.objects[i]->pos.y == pos.y)
if (game.objects[i]->pos.x == pos.x && game.objects[i]->pos.y == pos.y && game.objects[i]->state == STATE_ALIVE)
return (game.objects[i]);
return (NULL);
}
Expand Down
Loading