<commit_before>#include <inttypes.h>
#include <stdlib.h>
#include <shadowdive/stringparser.h>

#include "game/settings.h"
#include "video/video.h"
#include "audio/sink.h"
#include "audio/sound.h"
#include "audio/music.h"
#include "resources/ids.h"
#include "game/protos/player.h"
#include "game/protos/object.h"
#include "utils/string.h"
#include "utils/log.h"

// --------------------- Helpers ---------------------

static int clamp(int val, int min, int max) {
    if(val > max) return max;
    if(val < min) return min;
    return val;
}

static float clampf(float val, float min, float max) {
    if(val > max) return max;
    if(val < min) return min;
    return val;
}

// ---------------- Private callbacks ---------------- 

void cmd_tickjump(object *obj, int tick) {
    obj->animation_state.ticks = tick;
}

void cmd_music_off() {
    music_stop();
}

void cmd_music_on(int music) {
    // 0 is special case; stops playback
    if(music == 0) {
        music_stop();
        return;
    }

    // Find file we want to play
    char filename[64];
    switch(music) {
        case 0: music_stop(); break;
        case 1: get_filename_by_id(PSM_END, filename); break;
        case 2: get_filename_by_id(PSM_MENU, filename); break;
        case 3: get_filename_by_id(PSM_ARENA0, filename); break;
        case 4: get_filename_by_id(PSM_ARENA1, filename); break;
        case 5: get_filename_by_id(PSM_ARENA2, filename); break;
        case 6: get_filename_by_id(PSM_ARENA3, filename); break;
        case 7: get_filename_by_id(PSM_ARENA4, filename); break;
    }
    music_play(filename);
    music_set_volume(settings_get()->sound.music_vol/10.0f);
}

// ---------------- Private functions ---------------- 

int isset(sd_stringparser_frame *frame, const char *tag) {
    const sd_stringparser_tag_value *v;
    sd_stringparser_get_tag(frame->parser, frame->id, tag, &v);
    return v->is_set;
}

int get(sd_stringparser_frame *frame, const char *tag) {
    const sd_stringparser_tag_value *v;
    sd_stringparser_get_tag(frame->parser, frame->id, tag, &v);
    return v->value;
}

float dist(float a, float b) {
    return abs((a < b ? a : b) - (a > b ? a : b)) * (a < b ? 1 : -1);
}

void player_clear_frame(object *obj) {
    player_sprite_state *s = &obj->sprite_state;
    s->blendmode = BLEND_ALPHA;
    s->flipmode = FLIP_NONE;
    s->method_flags = 0;
    s->blend_start = 0;
    s->blend_finish = 0;
    s->timer = 0;
    s->duration = 0;

    s->pal_begin = 0;
    s->pal_end = 0;
    s->pal_ref_index = 0;
    s->pal_start_index = 0;
    s->pal_entry_count = 0;
}

// ---------------- Public functions ---------------- 

void player_create(object *obj) {
    obj->animation_state.reverse = 0;
    obj->animation_state.end_frame = UINT32_MAX;
    obj->animation_state.ticks = 1;
    obj->animation_state.finished = 0;
    obj->animation_state.repeat = 0;
    obj->animation_state.enemy_x = 0;
    obj->animation_state.enemy_y = 0;
    obj->animation_state.spawn = NULL;
    obj->animation_state.spawn_userdata = NULL;
    obj->animation_state.destroy = NULL;
    obj->animation_state.destroy_userdata = NULL;
    obj->animation_state.parser = NULL;
    obj->animation_state.previous = -1;
    obj->slide_state.timer = 0;
    obj->slide_state.vel = vec2f_create(0,0);
    player_clear_frame(obj);
}

void player_free(object *obj) {
    if(obj->animation_state.parser != NULL) {
        sd_stringparser_delete(obj->animation_state.parser);
    }
}

void player_reload_with_str(object *obj, const char* custom_str) {
    // Unload old parser, if any
    if(obj->animation_state.parser != NULL) {
        sd_stringparser_delete(obj->animation_state.parser);
        obj->animation_state.parser = NULL;
    }

    // Load new parser
    obj->animation_state.parser = sd_stringparser_create();
    sd_stringparser_set_string(
        obj->animation_state.parser, 
        custom_str);

    // Peek parameters
    sd_stringparser_frame param;
    sd_stringparser_peek(obj->animation_state.parser, 0, &param);
    
    // Set initial position for sprite
    if(isset(&param, "x=")) {
        obj->pos.x = get(&param, "x=");
    }
    if(isset(&param, "y=")) {
        obj->pos.y = get(&param, "y=");
    }

    // Set player state<commit_msg>only create the stringparser once to avoid unnecessary dynamic allocations every tick<commit_after>#include <inttypes.h>
#include <stdlib.h>
#include <shadowdive/stringparser.h>

#include "game/settings.h"
#include "video/video.h"
#include "audio/sink.h"
#include "audio/sound.h"
#include "audio/music.h"
#include "resources/ids.h"
#include "game/protos/player.h"
#include "game/protos/object.h"
#include "utils/string.h"
#include "utils/log.h"

// --------------------- Helpers ---------------------

static int clamp(int val, int min, int max) {
    if(val > max) return max;
    if(val < min) return min;
    return val;
}

static float clampf(float val, float min, float max) {
    if(val > max) return max;
    if(val < min) return min;
    return val;
}

// ---------------- Private callbacks ---------------- 

void cmd_tickjump(object *obj, int tick) {
    obj->animation_state.ticks = tick;
}

void cmd_music_off() {
    music_stop();
}

void cmd_music_on(int music) {
    // 0 is special case; stops playback
    if(music == 0) {
        music_stop();
        return;
    }

    // Find file we want to play
    char filename[64];
    switch(music) {
        case 0: music_stop(); break;
        case 1: get_filename_by_id(PSM_END, filename); break;
        case 2: get_filename_by_id(PSM_MENU, filename); break;
        case 3: get_filename_by_id(PSM_ARENA0, filename); break;
        case 4: get_filename_by_id(PSM_ARENA1, filename); break;
        case 5: get_filename_by_id(PSM_ARENA2, filename); break;
        case 6: get_filename_by_id(PSM_ARENA3, filename); break;
        case 7: get_filename_by_id(PSM_ARENA4, filename); break;
    }
    music_play(filename);
    music_set_volume(settings_get()->sound.music_vol/10.0f);
}

// ---------------- Private functions ---------------- 

int isset(sd_stringparser_frame *frame, const char *tag) {
    const sd_stringparser_tag_value *v;
    sd_stringparser_get_tag(frame->parser, frame->id, tag, &v);
    return v->is_set;
}

int get(sd_stringparser_frame *frame, const char *tag) {
    const sd_stringparser_tag_value *v;
    sd_stringparser_get_tag(frame->parser, frame->id, tag, &v);
    return v->value;
}

float dist(float a, float b) {
    return abs((a < b ? a : b) - (a > b ? a : b)) * (a < b ? 1 : -1);
}

void player_clear_frame(object *obj) {
    player_sprite_state *s = &obj->sprite_state;
    s->blendmode = BLEND_ALPHA;
    s->flipmode = FLIP_NONE;
    s->method_flags = 0;
    s->blend_start = 0;
    s->blend_finish = 0;
    s->timer = 0;
    s->duration = 0;

    s->pal_begin = 0;
    s->pal_end = 0;
    s->pal_ref_index = 0;
    s->pal_start_index = 0;
    s->pal_entry_count = 0;
}

// ---------------- Public functions ---------------- 

void player_create(object *obj) {
    obj->animation_state.reverse = 0;
    obj->animation_state.end_frame = UINT32_MAX;
    obj->animation_state.ticks = 1;
    obj->animation_state.finished = 0;
    obj->animation_state.repeat = 0;
    obj->animation_state.enemy_x = 0;
    obj->animation_state.enemy_y = 0;
    obj->animation_state.spawn = NULL;
    obj->animation_state.spawn_userdata = NULL;
    obj->animation_state.destroy = NULL;
    obj->animation_state.destroy_userdata = NULL;
    obj->animation_state.parser = NULL;
    obj->animation_state.previous = -1;
    obj->animation_state.parser = sd_stringparser_create();
    obj->slide_state.timer = 0;
    obj->slide_state.vel = vec2f_create(0,0);
    player_clear_frame(obj);
}

void player_free(object *obj) {
    if(obj->animation_state.parser != NULL) {
        sd_stringparser_delete(obj->animation_state.parser);
    }
}

void player_reload_with_str(object *obj, const char* custom_str) {
    // Load new animation string
    sd_stringparser_set_string(
        obj->animation_state.parser, 
        custom_str);

    // Peek parameters
    sd_stringparser_frame param;
    sd_stringparser_peek(obj->animation_state.parser, 0, &param);
    
    // Set initial position for sprite
    if(isset(&param, "x=")) {
        obj->pos.x = get(&param, "x=");
    }
    if(isset(&param, "y=")) {
        obj->pos.y = get(&param, "y=");
    }

    // Set player state
{'fraction_non_alphanumeric': 0.16235854675402026, 'fraction_numerical': 0.010958904109589041, 'mean_word_length': 2.8008148483476685, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 104, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7116391', 'n_tokens_mistral': 3017, 'n_tokens_neox': 2907, 'n_words': 619}