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->pending_load = false;
tmp->pending_start = false;
tmp->pending_stop = false;
tmp->pending_unload = false;
tmp->next = NULL;
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) {
struct Gamestate *gs = FindGamestate(game, name);
if (gs) {
if (gs->loaded) {
if (gs->loaded && !gs->pending_unload) {
PrintConsole(game, "Gamestate \"%s\" already loaded.", name);
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) {
struct Gamestate *gs = FindGamestate(game, name);
if (gs) {
if (gs->pending_load) {
gs->pending_load = false;
PrintConsole(game, "Canceling loading of gamestate \"%s\".", name);
return;
}
if (!gs->loaded) {
PrintConsole(game, "Gamestate \"%s\" already unloaded.", name);
return;
}
if (gs->started) gs->pending_start=true;
gs->pending_load = true;
if (gs->started) gs->pending_stop=true;
gs->pending_unload = true;
PrintConsole(game, "Gamestate \"%s\" marked to be UNLOADED.", name);
} else {
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) {
struct Gamestate *gs = FindGamestate(game, name);
if (gs) {
if (gs->started) {
if (gs->started && !gs->pending_stop) {
PrintConsole(game, "Gamestate \"%s\" already started.", name);
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) {
struct Gamestate *gs = FindGamestate(game, name);
if (gs) {
if (gs->pending_start) {
gs->pending_start = false;
PrintConsole(game, "Canceling starting of gamestate \"%s\".", name);
return;
}
if (!gs->started) {
PrintConsole(game, "Gamestate \"%s\" already stopped.", name);
return;
}
gs->pending_start = true;
gs->pending_stop = true;
PrintConsole(game, "Gamestate \"%s\" marked to be STOPPED.", name);
} else {
PrintConsole(game, "Tried to stop nonexisitent gamestate \"%s\"", name);

View file

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

View file

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