add ability to manually register gamestate API

This commit is contained in:
Sebastian Krzyszkowiak 2016-08-20 03:02:39 +02:00
parent 1afc4a3f31
commit 4aad8fabac
4 changed files with 82 additions and 56 deletions

View file

@ -45,6 +45,7 @@ SYMBOL_INTERNAL struct Gamestate* AddNewGamestate(struct Game *game, const char*
tmp->pending_stop = false;
tmp->pending_unload = false;
tmp->next = NULL;
tmp->api = NULL;
return tmp;
}
@ -59,6 +60,19 @@ SYMBOL_INTERNAL struct Gamestate* FindGamestate(struct Game *game, const char* n
return NULL;
}
SYMBOL_EXPORT void RegisterGamestate(struct Game *game, const char* name, struct Gamestate_API *api) {
struct Gamestate *gs = FindGamestate(game, name);
if (!gs) {
gs = AddNewGamestate(game, name);
}
if (gs->api) {
PrintConsole(game, "Trying to register already registered gamestate \"%s\"!", name);
return;
}
gs->api = api;
PrintConsole(game, "Gamestate \"%s\" registered.", name);
}
SYMBOL_EXPORT void LoadGamestate(struct Game *game, const char* name) {
struct Gamestate *gs = FindGamestate(game, name);
if (gs) {

View file

@ -25,16 +25,7 @@
struct Game;
struct Gamestate {
char* name;
void* handle;
bool loaded, pending_load, pending_unload;
bool started, pending_start, pending_stop;
bool showLoading;
bool paused;
struct Gamestate* next;
void* data;
struct {
struct Gamestate_API {
void (*Gamestate_Draw)(struct Game *game, void* data);
void (*Gamestate_Logic)(struct Game *game, void* data);
@ -49,11 +40,23 @@ struct Gamestate {
void (*Gamestate_Reload)(struct Game *game, void* data);
int *Gamestate_ProgressCount;
} api;
};
struct Gamestate {
char* name;
void* handle;
bool loaded, pending_load, pending_unload;
bool started, pending_start, pending_stop;
bool showLoading;
bool paused;
struct Gamestate *next;
void* data;
struct Gamestate_API *api;
};
void LoadGamestate(struct Game *game, const char* name);
void UnloadGamestate(struct Game *game, const char* name);
void RegisterGamestate(struct Game *game, const char* name, struct Gamestate_API *api);
void StartGamestate(struct Game *game, const char* name);
void StopGamestate(struct Game *game, const char* name);
void PauseGamestate(struct Game *game, const char* name);

View file

@ -30,7 +30,7 @@ SYMBOL_INTERNAL void DrawGamestates(struct Game *game) {
while (tmp) {
if ((tmp->loaded) && (tmp->started)) {
game->_priv.current_gamestate = tmp;
(*tmp->api.Gamestate_Draw)(game, tmp->data);
(*tmp->api->Gamestate_Draw)(game, tmp->data);
}
tmp = tmp->next;
}
@ -41,7 +41,7 @@ SYMBOL_INTERNAL void LogicGamestates(struct Game *game) {
while (tmp) {
if ((tmp->loaded) && (tmp->started) && (!tmp->paused)) {
game->_priv.current_gamestate = tmp;
(*tmp->api.Gamestate_Logic)(game, tmp->data);
(*tmp->api->Gamestate_Logic)(game, tmp->data);
}
tmp = tmp->next;
}
@ -52,7 +52,7 @@ SYMBOL_INTERNAL void EventGamestates(struct Game *game, ALLEGRO_EVENT *ev) {
while (tmp) {
if ((tmp->loaded) && (tmp->started) && (!tmp->paused)) {
game->_priv.current_gamestate = tmp;
(*tmp->api.Gamestate_ProcessEvent)(game, tmp->data, ev);
(*tmp->api->Gamestate_ProcessEvent)(game, tmp->data, ev);
}
tmp = tmp->next;
}
@ -63,7 +63,7 @@ SYMBOL_INTERNAL void PauseGamestates(struct Game *game) {
while (tmp) {
if ((tmp->loaded) && (tmp->started)) {
game->_priv.current_gamestate = tmp;
(*tmp->api.Gamestate_Pause)(game, tmp->data);
(*tmp->api->Gamestate_Pause)(game, tmp->data);
}
tmp = tmp->next;
}
@ -75,7 +75,7 @@ SYMBOL_INTERNAL void ResumeGamestates(struct Game *game) {
while (tmp) {
if ((tmp->loaded) && (tmp->started)) {
game->_priv.current_gamestate = tmp;
(*tmp->api.Gamestate_Resume)(game, tmp->data);
(*tmp->api->Gamestate_Resume)(game, tmp->data);
}
tmp = tmp->next;
}
@ -131,9 +131,9 @@ SYMBOL_INTERNAL void GamestateProgress(struct Game *game) {
struct Gamestate *tmp = game->_priv.tmp_gamestate.tmp;
game->_priv.tmp_gamestate.p++;
DrawGamestates(game);
float progressCount = *(tmp->api.Gamestate_ProgressCount) ? (float)*(tmp->api.Gamestate_ProgressCount) : 1;
float progressCount = *(tmp->api->Gamestate_ProgressCount) ? (float)*(tmp->api->Gamestate_ProgressCount) : 1;
float progress = ((game->_priv.tmp_gamestate.p / progressCount) / (float)game->_priv.tmp_gamestate.toLoad) + (game->_priv.tmp_gamestate.loaded/(float)game->_priv.tmp_gamestate.toLoad);
if (game->config.debug) PrintConsole(game, "[%s] Progress: %d% (%d/%d)", tmp->name, (int)(progress*100), game->_priv.tmp_gamestate.p, *(tmp->api.Gamestate_ProgressCount));
if (game->config.debug) PrintConsole(game, "[%s] Progress: %d% (%d/%d)", tmp->name, (int)(progress*100), game->_priv.tmp_gamestate.p, *(tmp->api->Gamestate_ProgressCount));
if (tmp->showLoading) (*game->_priv.loading.Draw)(game, game->_priv.loading.data, progress);
DrawConsole(game);
if (al_get_time() - game->_priv.tmp_gamestate.t >= 1/60.0) {

View file

@ -246,7 +246,7 @@ SYMBOL_EXPORT int libsuperderpy_run(struct Game *game) {
if (tmp->pending_stop) {
PrintConsole(game, "Stopping gamestate \"%s\"...", tmp->name);
game->_priv.current_gamestate = tmp;
(*tmp->api.Gamestate_Stop)(game, tmp->data);
(*tmp->api->Gamestate_Stop)(game, tmp->data);
tmp->started = false;
tmp->pending_stop = false;
}
@ -268,43 +268,46 @@ SYMBOL_EXPORT int libsuperderpy_run(struct Game *game) {
tmp->loaded = false;
tmp->pending_unload = false;
game->_priv.current_gamestate = tmp;
(*tmp->api.Gamestate_Unload)(game, tmp->data);
dlclose(tmp->handle);
tmp->handle = NULL;
(*tmp->api->Gamestate_Unload)(game, tmp->data);
al_start_timer(game->_priv.timer);
}
if (tmp->pending_load) {
PrintConsole(game, "Loading gamestate \"%s\"...", tmp->name);
al_stop_timer(game->_priv.timer);
// TODO: take proper game name
if (!tmp->api) {
PrintConsole(game, "Opening gamestate \"%s\"...", tmp->name);
char libname[1024];
snprintf(libname, 1024, "libsuperderpy-%s-%s" LIBRARY_EXTENSION, game->name, tmp->name);
tmp->handle = dlopen(libname,RTLD_NOW);
if (!tmp->handle) {
//PrintConsole(&game, "Error while loading gamestate \"%s\": %s", tmp->name, dlerror());
FatalError(game, false, "Error while loading gamestate \"%s\": %s", tmp->name, dlerror());
FatalError(game, false, "Error while opening gamestate \"%s\": %s", tmp->name, dlerror());
tmp->pending_load = false;
tmp->pending_start = false;
} else {
tmp->api = malloc(sizeof(struct Gamestate_API));
#define GS_ERROR FatalError(game, false, "Error on resolving gamestate symbol: %s", dlerror()); tmp->pending_load = false; tmp->pending_start = false; tmp=tmp->next; continue;
if (!(tmp->api.Gamestate_Draw = dlsym(tmp->handle, "Gamestate_Draw"))) { GS_ERROR; }
if (!(tmp->api.Gamestate_Logic = dlsym(tmp->handle, "Gamestate_Logic"))) { GS_ERROR; }
if (!(tmp->api->Gamestate_Draw = dlsym(tmp->handle, "Gamestate_Draw"))) { GS_ERROR; }
if (!(tmp->api->Gamestate_Logic = dlsym(tmp->handle, "Gamestate_Logic"))) { GS_ERROR; }
if (!(tmp->api.Gamestate_Load = dlsym(tmp->handle, "Gamestate_Load"))) { GS_ERROR; }
if (!(tmp->api.Gamestate_Start = dlsym(tmp->handle, "Gamestate_Start"))) { GS_ERROR; }
if (!(tmp->api.Gamestate_Pause = dlsym(tmp->handle, "Gamestate_Pause"))) { GS_ERROR; }
if (!(tmp->api.Gamestate_Resume = dlsym(tmp->handle, "Gamestate_Resume"))) { GS_ERROR; }
if (!(tmp->api.Gamestate_Stop = dlsym(tmp->handle, "Gamestate_Stop"))) { GS_ERROR; }
if (!(tmp->api.Gamestate_Unload = dlsym(tmp->handle, "Gamestate_Unload"))) { GS_ERROR; }
if (!(tmp->api->Gamestate_Load = dlsym(tmp->handle, "Gamestate_Load"))) { GS_ERROR; }
if (!(tmp->api->Gamestate_Start = dlsym(tmp->handle, "Gamestate_Start"))) { GS_ERROR; }
if (!(tmp->api->Gamestate_Pause = dlsym(tmp->handle, "Gamestate_Pause"))) { GS_ERROR; }
if (!(tmp->api->Gamestate_Resume = dlsym(tmp->handle, "Gamestate_Resume"))) { GS_ERROR; }
if (!(tmp->api->Gamestate_Stop = dlsym(tmp->handle, "Gamestate_Stop"))) { GS_ERROR; }
if (!(tmp->api->Gamestate_Unload = dlsym(tmp->handle, "Gamestate_Unload"))) { GS_ERROR; }
if (!(tmp->api.Gamestate_ProcessEvent = dlsym(tmp->handle, "Gamestate_ProcessEvent"))) { GS_ERROR; }
if (!(tmp->api.Gamestate_Reload = dlsym(tmp->handle, "Gamestate_Reload"))) { GS_ERROR; }
if (!(tmp->api.Gamestate_ProgressCount = dlsym(tmp->handle, "Gamestate_ProgressCount"))) { GS_ERROR; }
if (!(tmp->api->Gamestate_ProcessEvent = dlsym(tmp->handle, "Gamestate_ProcessEvent"))) { GS_ERROR; }
if (!(tmp->api->Gamestate_Reload = dlsym(tmp->handle, "Gamestate_Reload"))) { GS_ERROR; }
if (!(tmp->api->Gamestate_ProgressCount = dlsym(tmp->handle, "Gamestate_ProgressCount"))) { GS_ERROR; }
}
}
if (tmp->api) {
PrintConsole(game, "Loading gamestate \"%s\"...", tmp->name);
game->_priv.tmp_gamestate.p = 0;
DrawGamestates(game);
@ -318,7 +321,7 @@ SYMBOL_EXPORT int libsuperderpy_run(struct Game *game) {
}
game->_priv.tmp_gamestate.tmp = tmp;
game->_priv.current_gamestate = tmp;
tmp->data = (*tmp->api.Gamestate_Load)(game, &GamestateProgress);
tmp->data = (*tmp->api->Gamestate_Load)(game, &GamestateProgress);
game->_priv.tmp_gamestate.loaded++;
tmp->loaded = true;
@ -338,7 +341,7 @@ SYMBOL_EXPORT int libsuperderpy_run(struct Game *game) {
PrintConsole(game, "Starting gamestate \"%s\"...", tmp->name);
al_stop_timer(game->_priv.timer);
game->_priv.current_gamestate = tmp;
(*tmp->api.Gamestate_Start)(game, tmp->data);
(*tmp->api->Gamestate_Start)(game, tmp->data);
al_start_timer(game->_priv.timer);
tmp->started = true;
tmp->pending_start = false;
@ -429,17 +432,23 @@ SYMBOL_EXPORT void libsuperderpy_destroy(struct Game *game) {
if (tmp->started) {
PrintConsole(game, "Stopping gamestate \"%s\"...", tmp->name);
game->_priv.current_gamestate = tmp;
(*tmp->api.Gamestate_Stop)(game, tmp->data);
(*tmp->api->Gamestate_Stop)(game, tmp->data);
tmp->started = false;
}
if (tmp->loaded) {
PrintConsole(game, "Unloading gamestate \"%s\"...", tmp->name);
game->_priv.current_gamestate = tmp;
(*tmp->api.Gamestate_Unload)(game, tmp->data);
dlclose(tmp->handle);
(*tmp->api->Gamestate_Unload)(game, tmp->data);
tmp->loaded = false;
}
if (tmp->handle) {
PrintConsole(game, "Closing gamestate \"%s\"...", tmp->name);
dlclose(tmp->handle);
}
free(tmp->name);
if (tmp->api) {
free(tmp->api);
}
pom = tmp->next;
free(tmp);
tmp=pom;