partially done work on total source tree rework, separation of engine context and game context, generalization of renderer for different backends as well as web platform target

This commit is contained in:
2024-09-16 09:07:01 +03:00
parent ca0305feab
commit 551d60ef85
59 changed files with 2892 additions and 890 deletions

View File

@ -0,0 +1,142 @@
#include "townengine/twn_game_object.h"
#include "townengine/context.h"
#include <x-watcher.h>
#include <SDL2/SDL.h>
#include <dlfcn.h>
#define GAME_OBJECT_PATH "./libgame.so"
#define MODIFIED_TICKS_MERGED 10
static void (*game_tick_callback)(void);
static void (*game_end_callback)(void);
static x_watcher *watcher;
static void *handle = NULL;
static uint64_t last_tick_modified;
static bool loaded_after_modification = true;
static SDL_mutex *lock;
static void load_game_object(void) {
/* needs to be closed otherwise symbols aren't resolved again */
if (handle) {
dlclose(handle);
handle = NULL;
game_tick_callback = NULL;
game_end_callback = NULL;
}
void *new_handle = dlopen(GAME_OBJECT_PATH, RTLD_LAZY);
if (!new_handle) {
log_critical("Hot Reload Error: Cannot open game code shared object (%s)", dlerror());
goto ERR_OPENING_SO;
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
game_tick_callback = (void (*)(void))dlsym(new_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))dlsym(new_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
handle = new_handle;
if (ctx.tick_count != 0)
log_info("Game object was reloaded\n");
return;
ERR_GETTING_PROC:
dlclose(new_handle);
game_tick_callback = NULL;
game_end_callback = NULL;
ERR_OPENING_SO:
SDL_UnlockMutex(lock);
}
static void watcher_callback(XWATCHER_FILE_EVENT event,
const char *path,
int context,
void *data)
{
(void)context;
(void)path;
(void)data;
switch(event) {
case XWATCHER_FILE_MODIFIED:
SDL_LockMutex(lock);
last_tick_modified = ctx.tick_count;
loaded_after_modification = false;
SDL_UnlockMutex(lock);
break;
default:
break;
}
}
void game_object_load(void) {
watcher = xWatcher_create();
xWatcher_reference dir;
dir.path = GAME_OBJECT_PATH;
dir.callback_func = watcher_callback;
xWatcher_appendFile(watcher, &dir);
xWatcher_start(watcher);
lock = SDL_CreateMutex();
load_game_object();
}
void game_object_unload(void) {
game_end_callback();
xWatcher_destroy(watcher);
watcher = NULL;
dlclose(handle);
handle = NULL;
game_tick_callback = NULL;
game_end_callback = NULL;
SDL_DestroyMutex(lock);
}
bool game_object_try_reloading(void) {
bool result = false;
/* only load the modified library after some time, as compilers make a lot of modifications */
SDL_LockMutex(lock);
if (ctx.tick_count - last_tick_modified > MODIFIED_TICKS_MERGED &&
!loaded_after_modification) {
load_game_object();
loaded_after_modification = true;
result = true;
} SDL_UnlockMutex(lock);
return result;
}
void game_object_tick(void) {
game_tick_callback();
}

View File

@ -0,0 +1,21 @@
#include "townengine/twn_game_object.h"
#include "townengine/game_api.h"
void game_object_load(void) {
}
void game_object_unload(void) {
game_end();
}
bool game_object_try_reloading(void) {
return false;
}
void game_object_tick(void) {
game_tick();
}

View File

@ -0,0 +1,88 @@
#include "townengine/twn_game_object.h"
#include "townengine/context.h"
#include <errhandlingapi.h>
#include <libloaderapi.h>
#define GAME_OBJECT_PATH "libgame.dll"
static void (*game_tick_callback)(void);
static void (*game_end_callback)(void);
static void *handle = NULL;
static void load_game_object(void) {
/* needs to be closed otherwise symbols aren't resolved again */
if (handle) {
FreeLibrary(handle);
handle = NULL;
game_tick_callback = NULL;
game_end_callback = NULL;
}
void *new_handle = LoadLibraryA(GAME_OBJECT_PATH);
if (!new_handle) {
log_critical("Hot Reload Error: Cannot open game code shared object (%s)", GetLastError());
goto ERR_OPENING_SO;
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
game_tick_callback = (void (*)(void))GetProcAddress(new_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))GetProcAddress(new_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
handle = new_handle;
if (ctx.tick_count != 0)
log_info("Game object was reloaded\n");
return;
ERR_GETTING_PROC:
FreeLibrary(new_handle);
game_tick_callback = NULL;
game_end_callback = NULL;
ERR_OPENING_SO:
die_abruptly();
}
void game_object_load(void) {
load_game_object();
}
void game_object_unload(void) {
game_end_callback();
FreeLibrary(handle);
handle = NULL;
game_tick_callback = NULL;
game_end_callback = NULL;
}
/* doesn't support reloading because of problems with file watching */
bool game_object_try_reloading(void) {
return false;
}
void game_object_tick(void) {
game_tick_callback();
}