#include "twn_game_object_c.h" #include "twn_engine_context_c.h" #include "twn_filewatch_c.h" #include "twn_util_c.h" #include "twn_util.h" #include "twn_loop_c.h" #include #ifdef _WIN32 #define GAME_OBJECT_NAME "libgame.dll" #else #define GAME_OBJECT_NAME "libgame.so" #endif static void (*game_tick_callback)(void); static void (*game_end_callback)(void); static void *handle = NULL; static void game_object_file_action(char const *path, enum FilewatchAction action) { (void)action; if (action != FILEWATCH_ACTION_FILE_CREATED) return; if (handle) { SDL_UnloadObject(handle); game_tick_callback = NULL; game_end_callback = NULL; handle = NULL; } handle = SDL_LoadObject(path); if (!handle) { CRY_SDL("Hot Reload Error: Cannot open game code shared object"); return; } #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" game_tick_callback = (void (*)(void))SDL_LoadFunction(handle, "game_tick"); if (!game_tick_callback) { CRY("Hot Reload Error", "game_tick_callback() symbol wasn't found"); goto ERR_GETTING_PROC; } game_end_callback = (void (*)(void))SDL_LoadFunction(handle, "game_end"); if (!game_end_callback) { CRY("Hot Reload Error", "game_end_callback() symbol wasn't found"); goto ERR_GETTING_PROC; } #pragma GCC diagnostic pop if (fabsf(0.0f - ctx.game.frame_number) > 0.00001f) { log_info("Game object was reloaded\n"); reset_state(); } return; ERR_GETTING_PROC: SDL_UnloadObject(handle); handle = NULL; game_tick_callback = NULL; game_end_callback = NULL; } void game_object_load(void) { static bool filewatch_attached; if (!filewatch_attached) { char *game_object_path; SDL_asprintf(&game_object_path, "%s%s", ctx.base_dir, GAME_OBJECT_NAME); filewatch_add_file(game_object_path, game_object_file_action); game_object_file_action(game_object_path, FILEWATCH_ACTION_FILE_CREATED); SDL_free(game_object_path); filewatch_attached = true; } } void game_object_unload(void) { game_end_callback(); /* needs to be closed otherwise symbols aren't resolved again */ SDL_UnloadObject(handle); game_tick_callback = NULL; game_end_callback = NULL; handle = NULL; } void game_object_tick(void) { game_tick_callback(); }