mirror of
https://gitlab.com/dosowisko.net/libsuperderpy.git
synced 2025-02-01 11:06:44 +01:00
add ability to manually register gamestate API
This commit is contained in:
parent
1afc4a3f31
commit
4aad8fabac
4 changed files with 82 additions and 56 deletions
|
@ -45,6 +45,7 @@ SYMBOL_INTERNAL struct Gamestate* AddNewGamestate(struct Game *game, const char*
|
||||||
tmp->pending_stop = false;
|
tmp->pending_stop = false;
|
||||||
tmp->pending_unload = false;
|
tmp->pending_unload = false;
|
||||||
tmp->next = NULL;
|
tmp->next = NULL;
|
||||||
|
tmp->api = NULL;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +60,19 @@ SYMBOL_INTERNAL struct Gamestate* FindGamestate(struct Game *game, const char* n
|
||||||
return NULL;
|
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) {
|
SYMBOL_EXPORT void LoadGamestate(struct Game *game, const char* name) {
|
||||||
struct Gamestate *gs = FindGamestate(game, name);
|
struct Gamestate *gs = FindGamestate(game, name);
|
||||||
if (gs) {
|
if (gs) {
|
||||||
|
|
|
@ -25,16 +25,7 @@
|
||||||
|
|
||||||
struct Game;
|
struct Game;
|
||||||
|
|
||||||
struct Gamestate {
|
struct Gamestate_API {
|
||||||
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 {
|
|
||||||
void (*Gamestate_Draw)(struct Game *game, void* data);
|
void (*Gamestate_Draw)(struct Game *game, void* data);
|
||||||
void (*Gamestate_Logic)(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);
|
void (*Gamestate_Reload)(struct Game *game, void* data);
|
||||||
|
|
||||||
int *Gamestate_ProgressCount;
|
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 LoadGamestate(struct Game *game, const char* name);
|
||||||
void UnloadGamestate(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 StartGamestate(struct Game *game, const char* name);
|
||||||
void StopGamestate(struct Game *game, const char* name);
|
void StopGamestate(struct Game *game, const char* name);
|
||||||
void PauseGamestate(struct Game *game, const char* name);
|
void PauseGamestate(struct Game *game, const char* name);
|
||||||
|
|
|
@ -30,7 +30,7 @@ SYMBOL_INTERNAL void DrawGamestates(struct Game *game) {
|
||||||
while (tmp) {
|
while (tmp) {
|
||||||
if ((tmp->loaded) && (tmp->started)) {
|
if ((tmp->loaded) && (tmp->started)) {
|
||||||
game->_priv.current_gamestate = tmp;
|
game->_priv.current_gamestate = tmp;
|
||||||
(*tmp->api.Gamestate_Draw)(game, tmp->data);
|
(*tmp->api->Gamestate_Draw)(game, tmp->data);
|
||||||
}
|
}
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ SYMBOL_INTERNAL void LogicGamestates(struct Game *game) {
|
||||||
while (tmp) {
|
while (tmp) {
|
||||||
if ((tmp->loaded) && (tmp->started) && (!tmp->paused)) {
|
if ((tmp->loaded) && (tmp->started) && (!tmp->paused)) {
|
||||||
game->_priv.current_gamestate = tmp;
|
game->_priv.current_gamestate = tmp;
|
||||||
(*tmp->api.Gamestate_Logic)(game, tmp->data);
|
(*tmp->api->Gamestate_Logic)(game, tmp->data);
|
||||||
}
|
}
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ SYMBOL_INTERNAL void EventGamestates(struct Game *game, ALLEGRO_EVENT *ev) {
|
||||||
while (tmp) {
|
while (tmp) {
|
||||||
if ((tmp->loaded) && (tmp->started) && (!tmp->paused)) {
|
if ((tmp->loaded) && (tmp->started) && (!tmp->paused)) {
|
||||||
game->_priv.current_gamestate = tmp;
|
game->_priv.current_gamestate = tmp;
|
||||||
(*tmp->api.Gamestate_ProcessEvent)(game, tmp->data, ev);
|
(*tmp->api->Gamestate_ProcessEvent)(game, tmp->data, ev);
|
||||||
}
|
}
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ SYMBOL_INTERNAL void PauseGamestates(struct Game *game) {
|
||||||
while (tmp) {
|
while (tmp) {
|
||||||
if ((tmp->loaded) && (tmp->started)) {
|
if ((tmp->loaded) && (tmp->started)) {
|
||||||
game->_priv.current_gamestate = tmp;
|
game->_priv.current_gamestate = tmp;
|
||||||
(*tmp->api.Gamestate_Pause)(game, tmp->data);
|
(*tmp->api->Gamestate_Pause)(game, tmp->data);
|
||||||
}
|
}
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ SYMBOL_INTERNAL void ResumeGamestates(struct Game *game) {
|
||||||
while (tmp) {
|
while (tmp) {
|
||||||
if ((tmp->loaded) && (tmp->started)) {
|
if ((tmp->loaded) && (tmp->started)) {
|
||||||
game->_priv.current_gamestate = tmp;
|
game->_priv.current_gamestate = tmp;
|
||||||
(*tmp->api.Gamestate_Resume)(game, tmp->data);
|
(*tmp->api->Gamestate_Resume)(game, tmp->data);
|
||||||
}
|
}
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
}
|
}
|
||||||
|
@ -131,9 +131,9 @@ SYMBOL_INTERNAL void GamestateProgress(struct Game *game) {
|
||||||
struct Gamestate *tmp = game->_priv.tmp_gamestate.tmp;
|
struct Gamestate *tmp = game->_priv.tmp_gamestate.tmp;
|
||||||
game->_priv.tmp_gamestate.p++;
|
game->_priv.tmp_gamestate.p++;
|
||||||
DrawGamestates(game);
|
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);
|
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);
|
if (tmp->showLoading) (*game->_priv.loading.Draw)(game, game->_priv.loading.data, progress);
|
||||||
DrawConsole(game);
|
DrawConsole(game);
|
||||||
if (al_get_time() - game->_priv.tmp_gamestate.t >= 1/60.0) {
|
if (al_get_time() - game->_priv.tmp_gamestate.t >= 1/60.0) {
|
||||||
|
|
|
@ -246,7 +246,7 @@ SYMBOL_EXPORT int libsuperderpy_run(struct Game *game) {
|
||||||
if (tmp->pending_stop) {
|
if (tmp->pending_stop) {
|
||||||
PrintConsole(game, "Stopping gamestate \"%s\"...", tmp->name);
|
PrintConsole(game, "Stopping gamestate \"%s\"...", tmp->name);
|
||||||
game->_priv.current_gamestate = tmp;
|
game->_priv.current_gamestate = tmp;
|
||||||
(*tmp->api.Gamestate_Stop)(game, tmp->data);
|
(*tmp->api->Gamestate_Stop)(game, tmp->data);
|
||||||
tmp->started = false;
|
tmp->started = false;
|
||||||
tmp->pending_stop = false;
|
tmp->pending_stop = false;
|
||||||
}
|
}
|
||||||
|
@ -268,43 +268,46 @@ SYMBOL_EXPORT int libsuperderpy_run(struct Game *game) {
|
||||||
tmp->loaded = false;
|
tmp->loaded = false;
|
||||||
tmp->pending_unload = false;
|
tmp->pending_unload = false;
|
||||||
game->_priv.current_gamestate = tmp;
|
game->_priv.current_gamestate = tmp;
|
||||||
(*tmp->api.Gamestate_Unload)(game, tmp->data);
|
(*tmp->api->Gamestate_Unload)(game, tmp->data);
|
||||||
dlclose(tmp->handle);
|
|
||||||
tmp->handle = NULL;
|
|
||||||
al_start_timer(game->_priv.timer);
|
al_start_timer(game->_priv.timer);
|
||||||
}
|
}
|
||||||
if (tmp->pending_load) {
|
if (tmp->pending_load) {
|
||||||
PrintConsole(game, "Loading gamestate \"%s\"...", tmp->name);
|
|
||||||
al_stop_timer(game->_priv.timer);
|
al_stop_timer(game->_priv.timer);
|
||||||
// TODO: take proper game name
|
|
||||||
|
if (!tmp->api) {
|
||||||
|
PrintConsole(game, "Opening gamestate \"%s\"...", tmp->name);
|
||||||
char libname[1024];
|
char libname[1024];
|
||||||
snprintf(libname, 1024, "libsuperderpy-%s-%s" LIBRARY_EXTENSION, game->name, tmp->name);
|
snprintf(libname, 1024, "libsuperderpy-%s-%s" LIBRARY_EXTENSION, game->name, tmp->name);
|
||||||
tmp->handle = dlopen(libname,RTLD_NOW);
|
tmp->handle = dlopen(libname,RTLD_NOW);
|
||||||
if (!tmp->handle) {
|
if (!tmp->handle) {
|
||||||
//PrintConsole(&game, "Error while loading gamestate \"%s\": %s", tmp->name, dlerror());
|
FatalError(game, false, "Error while opening gamestate \"%s\": %s", tmp->name, dlerror());
|
||||||
FatalError(game, false, "Error while loading gamestate \"%s\": %s", tmp->name, dlerror());
|
|
||||||
|
|
||||||
tmp->pending_load = false;
|
tmp->pending_load = false;
|
||||||
tmp->pending_start = false;
|
tmp->pending_start = false;
|
||||||
} else {
|
} 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;
|
#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_Draw = dlsym(tmp->handle, "Gamestate_Draw"))) { GS_ERROR; }
|
||||||
if (!(tmp->api.Gamestate_Logic = dlsym(tmp->handle, "Gamestate_Logic"))) { 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_Load = dlsym(tmp->handle, "Gamestate_Load"))) { GS_ERROR; }
|
||||||
if (!(tmp->api.Gamestate_Start = dlsym(tmp->handle, "Gamestate_Start"))) { 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_Pause = dlsym(tmp->handle, "Gamestate_Pause"))) { GS_ERROR; }
|
||||||
if (!(tmp->api.Gamestate_Resume = dlsym(tmp->handle, "Gamestate_Resume"))) { 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_Stop = dlsym(tmp->handle, "Gamestate_Stop"))) { GS_ERROR; }
|
||||||
if (!(tmp->api.Gamestate_Unload = dlsym(tmp->handle, "Gamestate_Unload"))) { 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_ProcessEvent = dlsym(tmp->handle, "Gamestate_ProcessEvent"))) { GS_ERROR; }
|
||||||
if (!(tmp->api.Gamestate_Reload = dlsym(tmp->handle, "Gamestate_Reload"))) { 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_ProgressCount = dlsym(tmp->handle, "Gamestate_ProgressCount"))) { GS_ERROR; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tmp->api) {
|
||||||
|
PrintConsole(game, "Loading gamestate \"%s\"...", tmp->name);
|
||||||
game->_priv.tmp_gamestate.p = 0;
|
game->_priv.tmp_gamestate.p = 0;
|
||||||
|
|
||||||
DrawGamestates(game);
|
DrawGamestates(game);
|
||||||
|
@ -318,7 +321,7 @@ SYMBOL_EXPORT int libsuperderpy_run(struct Game *game) {
|
||||||
}
|
}
|
||||||
game->_priv.tmp_gamestate.tmp = tmp;
|
game->_priv.tmp_gamestate.tmp = tmp;
|
||||||
game->_priv.current_gamestate = 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++;
|
game->_priv.tmp_gamestate.loaded++;
|
||||||
|
|
||||||
tmp->loaded = true;
|
tmp->loaded = true;
|
||||||
|
@ -338,7 +341,7 @@ SYMBOL_EXPORT int libsuperderpy_run(struct Game *game) {
|
||||||
PrintConsole(game, "Starting gamestate \"%s\"...", tmp->name);
|
PrintConsole(game, "Starting gamestate \"%s\"...", tmp->name);
|
||||||
al_stop_timer(game->_priv.timer);
|
al_stop_timer(game->_priv.timer);
|
||||||
game->_priv.current_gamestate = tmp;
|
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);
|
al_start_timer(game->_priv.timer);
|
||||||
tmp->started = true;
|
tmp->started = true;
|
||||||
tmp->pending_start = false;
|
tmp->pending_start = false;
|
||||||
|
@ -429,17 +432,23 @@ SYMBOL_EXPORT void libsuperderpy_destroy(struct Game *game) {
|
||||||
if (tmp->started) {
|
if (tmp->started) {
|
||||||
PrintConsole(game, "Stopping gamestate \"%s\"...", tmp->name);
|
PrintConsole(game, "Stopping gamestate \"%s\"...", tmp->name);
|
||||||
game->_priv.current_gamestate = tmp;
|
game->_priv.current_gamestate = tmp;
|
||||||
(*tmp->api.Gamestate_Stop)(game, tmp->data);
|
(*tmp->api->Gamestate_Stop)(game, tmp->data);
|
||||||
tmp->started = false;
|
tmp->started = false;
|
||||||
}
|
}
|
||||||
if (tmp->loaded) {
|
if (tmp->loaded) {
|
||||||
PrintConsole(game, "Unloading gamestate \"%s\"...", tmp->name);
|
PrintConsole(game, "Unloading gamestate \"%s\"...", tmp->name);
|
||||||
game->_priv.current_gamestate = tmp;
|
game->_priv.current_gamestate = tmp;
|
||||||
(*tmp->api.Gamestate_Unload)(game, tmp->data);
|
(*tmp->api->Gamestate_Unload)(game, tmp->data);
|
||||||
dlclose(tmp->handle);
|
|
||||||
tmp->loaded = false;
|
tmp->loaded = false;
|
||||||
}
|
}
|
||||||
|
if (tmp->handle) {
|
||||||
|
PrintConsole(game, "Closing gamestate \"%s\"...", tmp->name);
|
||||||
|
dlclose(tmp->handle);
|
||||||
|
}
|
||||||
free(tmp->name);
|
free(tmp->name);
|
||||||
|
if (tmp->api) {
|
||||||
|
free(tmp->api);
|
||||||
|
}
|
||||||
pom = tmp->next;
|
pom = tmp->next;
|
||||||
free(tmp);
|
free(tmp);
|
||||||
tmp=pom;
|
tmp=pom;
|
||||||
|
|
Loading…
Reference in a new issue