gamestates: handle unload/load and stop/start cycles in one tick correctly

This commit is contained in:
Sebastian Krzyszkowiak 2016-08-13 20:03:58 +02:00
parent 8087ad1afc
commit 676ae31613
3 changed files with 27 additions and 14 deletions

View file

@ -42,6 +42,8 @@ SYMBOL_INTERNAL struct Gamestate* AddNewGamestate(struct Game *game) {
tmp->started = false; tmp->started = false;
tmp->pending_load = false; tmp->pending_load = false;
tmp->pending_start = false; tmp->pending_start = false;
tmp->pending_stop = false;
tmp->pending_unload = false;
tmp->next = NULL; tmp->next = NULL;
return tmp; return tmp;
} }
@ -60,7 +62,7 @@ SYMBOL_INTERNAL struct Gamestate* FindGamestate(struct Game *game, const char* n
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) {
if (gs->loaded) { if (gs->loaded && !gs->pending_unload) {
PrintConsole(game, "Gamestate \"%s\" already loaded.", name); PrintConsole(game, "Gamestate \"%s\" already loaded.", name);
return; return;
} }
@ -77,12 +79,17 @@ SYMBOL_EXPORT void LoadGamestate(struct Game *game, const char* name) {
SYMBOL_EXPORT void UnloadGamestate(struct Game *game, const char* name) { SYMBOL_EXPORT void UnloadGamestate(struct Game *game, const char* name) {
struct Gamestate *gs = FindGamestate(game, name); struct Gamestate *gs = FindGamestate(game, name);
if (gs) { if (gs) {
if (gs->pending_load) {
gs->pending_load = false;
PrintConsole(game, "Canceling loading of gamestate \"%s\".", name);
return;
}
if (!gs->loaded) { if (!gs->loaded) {
PrintConsole(game, "Gamestate \"%s\" already unloaded.", name); PrintConsole(game, "Gamestate \"%s\" already unloaded.", name);
return; return;
} }
if (gs->started) gs->pending_start=true; if (gs->started) gs->pending_stop=true;
gs->pending_load = true; gs->pending_unload = true;
PrintConsole(game, "Gamestate \"%s\" marked to be UNLOADED.", name); PrintConsole(game, "Gamestate \"%s\" marked to be UNLOADED.", name);
} else { } else {
PrintConsole(game, "Tried to unload nonexisitent gamestate \"%s\"", name); PrintConsole(game, "Tried to unload nonexisitent gamestate \"%s\"", name);
@ -92,7 +99,7 @@ SYMBOL_EXPORT void UnloadGamestate(struct Game *game, const char* name) {
SYMBOL_EXPORT void StartGamestate(struct Game *game, const char* name) { SYMBOL_EXPORT void StartGamestate(struct Game *game, const char* name) {
struct Gamestate *gs = FindGamestate(game, name); struct Gamestate *gs = FindGamestate(game, name);
if (gs) { if (gs) {
if (gs->started) { if (gs->started && !gs->pending_stop) {
PrintConsole(game, "Gamestate \"%s\" already started.", name); PrintConsole(game, "Gamestate \"%s\" already started.", name);
return; return;
} }
@ -106,11 +113,16 @@ SYMBOL_EXPORT void StartGamestate(struct Game *game, const char* name) {
SYMBOL_EXPORT void StopGamestate(struct Game *game, const char* name) { SYMBOL_EXPORT void StopGamestate(struct Game *game, const char* name) {
struct Gamestate *gs = FindGamestate(game, name); struct Gamestate *gs = FindGamestate(game, name);
if (gs) { if (gs) {
if (gs->pending_start) {
gs->pending_start = false;
PrintConsole(game, "Canceling starting of gamestate \"%s\".", name);
return;
}
if (!gs->started) { if (!gs->started) {
PrintConsole(game, "Gamestate \"%s\" already stopped.", name); PrintConsole(game, "Gamestate \"%s\" already stopped.", name);
return; return;
} }
gs->pending_start = true; gs->pending_stop = true;
PrintConsole(game, "Gamestate \"%s\" marked to be STOPPED.", name); PrintConsole(game, "Gamestate \"%s\" marked to be STOPPED.", name);
} else { } else {
PrintConsole(game, "Tried to stop nonexisitent gamestate \"%s\"", name); PrintConsole(game, "Tried to stop nonexisitent gamestate \"%s\"", name);

View file

@ -28,8 +28,8 @@ struct Game;
struct Gamestate { struct Gamestate {
char* name; char* name;
void* handle; void* handle;
bool loaded, pending_load; bool loaded, pending_load, pending_unload;
bool started, pending_start; bool started, pending_start, pending_stop;
bool showLoading; bool showLoading;
bool paused; bool paused;
struct Gamestate* next; struct Gamestate* next;

View file

@ -238,14 +238,14 @@ SYMBOL_EXPORT int libsuperderpy_run(struct Game *game) {
// FIXME: move to function // FIXME: move to function
// TODO: support dependences // TODO: support dependences
while (tmp) { while (tmp) {
if ((tmp->pending_start) && (tmp->started)) { if (tmp->pending_stop) {
PrintConsole(game, "Stopping gamestate \"%s\"...", tmp->name); PrintConsole(game, "Stopping gamestate \"%s\"...", tmp->name);
(*tmp->api.Gamestate_Stop)(game, tmp->data); (*tmp->api.Gamestate_Stop)(game, tmp->data);
tmp->started = false; tmp->started = false;
tmp->pending_start = false; tmp->pending_stop = false;
} }
if ((tmp->pending_load) && (!tmp->loaded)) game->_priv.cur_gamestate.toLoad++; if (tmp->pending_load) game->_priv.cur_gamestate.toLoad++;
tmp=tmp->next; tmp=tmp->next;
} }
@ -256,16 +256,17 @@ SYMBOL_EXPORT int libsuperderpy_run(struct Game *game) {
game->_priv.cur_gamestate.t = -1; game->_priv.cur_gamestate.t = -1;
while (tmp) { while (tmp) {
if ((tmp->pending_load) && (tmp->loaded)) { if (tmp->pending_unload) {
PrintConsole(game, "Unloading gamestate \"%s\"...", tmp->name); PrintConsole(game, "Unloading gamestate \"%s\"...", tmp->name);
al_stop_timer(game->_priv.timer); al_stop_timer(game->_priv.timer);
tmp->loaded = false; tmp->loaded = false;
tmp->pending_load = false; tmp->pending_unload = false;
(*tmp->api.Gamestate_Unload)(game, tmp->data); (*tmp->api.Gamestate_Unload)(game, tmp->data);
dlclose(tmp->handle); dlclose(tmp->handle);
tmp->handle = NULL; tmp->handle = NULL;
al_start_timer(game->_priv.timer); al_start_timer(game->_priv.timer);
} else if ((tmp->pending_load) && (!tmp->loaded)) { }
if (tmp->pending_load) {
PrintConsole(game, "Loading gamestate \"%s\"...", tmp->name); PrintConsole(game, "Loading gamestate \"%s\"...", tmp->name);
al_stop_timer(game->_priv.timer); al_stop_timer(game->_priv.timer);
// TODO: take proper game name // TODO: take proper game name
@ -326,7 +327,7 @@ SYMBOL_EXPORT int libsuperderpy_run(struct Game *game) {
while (tmp) { while (tmp) {
if ((tmp->pending_start) && (!tmp->started) && (tmp->loaded)) { if ((tmp->pending_start) && (tmp->loaded)) {
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);
(*tmp->api.Gamestate_Start)(game, tmp->data); (*tmp->api.Gamestate_Start)(game, tmp->data);