1
0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-06-16 09:38:29 +02:00

Do not close game if custom level has assets issues

It's quite rude to close the game entirely if there is trouble with
assets. Instead, just unload the assets and gracefully return to the
title screen.
This commit is contained in:
Misa 2021-08-06 20:57:34 -07:00 committed by Ethan Lee
parent ed9cb4ca6d
commit 8dc5d69ef3
12 changed files with 118 additions and 46 deletions

View File

@ -473,7 +473,9 @@ void FILESYSTEM_loadZip(const char* filename)
}
}
void FILESYSTEM_mountAssets(const char* path)
void FILESYSTEM_unmountAssets(void);
bool FILESYSTEM_mountAssets(const char* path)
{
char filename[MAX_PATH];
char zip_data[MAX_PATH];
@ -504,10 +506,10 @@ void FILESYSTEM_mountAssets(const char* path)
if (!FILESYSTEM_mountAssetsFrom(zip_data))
{
return;
return false;
}
graphics.reloadresources();
MAYBE_FAIL(graphics.reloadresources());
}
else if (zip_normal != NULL && endsWith(zip_normal, ".zip"))
{
@ -515,10 +517,10 @@ void FILESYSTEM_mountAssets(const char* path)
if (!FILESYSTEM_mountAssetsFrom(zip_normal))
{
return;
return false;
}
graphics.reloadresources();
MAYBE_FAIL(graphics.reloadresources());
}
else if (FILESYSTEM_exists(dir))
{
@ -526,15 +528,21 @@ void FILESYSTEM_mountAssets(const char* path)
if (!FILESYSTEM_mountAssetsFrom(dir))
{
return;
return false;
}
graphics.reloadresources();
MAYBE_FAIL(graphics.reloadresources());
}
else
{
puts("Custom asset directory does not exist");
}
return true;
fail:
FILESYSTEM_unmountAssets();
return false;
}
void FILESYSTEM_unmountAssets(void)

View File

@ -19,7 +19,7 @@ bool FILESYSTEM_isFile(const char* filename);
bool FILESYSTEM_isMounted(const char* filename);
void FILESYSTEM_loadZip(const char* filename);
void FILESYSTEM_mountAssets(const char *path);
bool FILESYSTEM_mountAssets(const char *path);
void FILESYSTEM_unmountAssets(void);
bool FILESYSTEM_isAssetMounted(const char* filename);

View File

@ -6477,6 +6477,9 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
option("silence");
menuyoff = 10;
break;
case Menu::errorloadinglevel:
option("ok");
break;
}
// Automatically center the menu. We must check the width of the menu with the initial horizontal spacing.

View File

@ -35,6 +35,7 @@ namespace Menu
youwannaquit,
errornostart,
errorsavingsettings,
errorloadinglevel,
graphicoptions,
ed_settings,
ed_desc,

View File

@ -151,6 +151,9 @@ void Graphics::init(void)
tiles2_mounted = false;
minimap_mounted = false;
#endif
SDL_zeroa(error);
SDL_zeroa(error_title);
}
void Graphics::destroy(void)
@ -314,24 +317,15 @@ void Graphics::updatetitlecolours(void)
else if (grphx.im_##tilesheet->w % tile_square != 0 \
|| grphx.im_##tilesheet->h % tile_square != 0) \
{ \
const char* error = "Error: %s.png dimensions not exact multiples of %i!"; \
char message[128]; \
const char* error_title = "Error with %s.png"; \
char message_title[128]; \
static const char error_fmt[] = "%s.png dimensions not exact multiples of %i!"; \
static const char error_title_fmt[] = "Error with %s.png"; \
\
SDL_snprintf(message, sizeof(message), error, #tilesheet, tile_square); \
SDL_snprintf(message_title, sizeof(message_title), error_title, #tilesheet); \
SDL_snprintf(error, sizeof(error), error_fmt, #tilesheet, tile_square); \
SDL_snprintf(error_title, sizeof(error_title), error_title_fmt, #tilesheet); \
\
puts(message); \
puts(error); \
\
SDL_ShowSimpleMessageBox( \
SDL_MESSAGEBOX_ERROR, \
message_title, \
message, \
NULL \
); \
\
VVV_exit(1); \
return false; \
}
#define PROCESS_TILESHEET_RENAME(tilesheet, vector, tile_square, extra_code) \
@ -363,7 +357,7 @@ void Graphics::updatetitlecolours(void)
#define PROCESS_TILESHEET(tilesheet, tile_square, extra_code) \
PROCESS_TILESHEET_RENAME(tilesheet, tilesheet, tile_square, extra_code)
void Graphics::Makebfont(void)
bool Graphics::Makebfont(void)
{
PROCESS_TILESHEET(bfont, 8,
{
@ -391,6 +385,8 @@ void Graphics::Makebfont(void)
{
font_positions.clear();
}
return true;
}
int Graphics::bfontlen(uint32_t ch)
@ -405,23 +401,29 @@ int Graphics::bfontlen(uint32_t ch)
}
}
void Graphics::MakeTileArray(void)
bool Graphics::MakeTileArray(void)
{
PROCESS_TILESHEET(tiles, 8, {})
PROCESS_TILESHEET(tiles2, 8, {})
PROCESS_TILESHEET(tiles3, 8, {})
PROCESS_TILESHEET(entcolours, 8, {})
return true;
}
void Graphics::maketelearray(void)
bool Graphics::maketelearray(void)
{
PROCESS_TILESHEET_RENAME(teleporter, tele, 96, {})
return true;
}
void Graphics::MakeSpriteArray(void)
bool Graphics::MakeSpriteArray(void)
{
PROCESS_TILESHEET(sprites, 32, {})
PROCESS_TILESHEET(flipsprites, 32, {})
return true;
}
#undef PROCESS_TILESHEET
@ -3486,17 +3488,17 @@ bool Graphics::onscreen(int t)
return (t >= -40 && t <= 280);
}
void Graphics::reloadresources(void)
bool Graphics::reloadresources(void)
{
grphx.destroy();
grphx.init();
destroy();
MakeTileArray();
MakeSpriteArray();
maketelearray();
Makebfont();
MAYBE_FAIL(MakeTileArray());
MAYBE_FAIL(MakeSpriteArray());
MAYBE_FAIL(maketelearray());
MAYBE_FAIL(Makebfont());
images.clear();
@ -3528,6 +3530,11 @@ void Graphics::reloadresources(void)
tiles2_mounted = FILESYSTEM_isAssetMounted("graphics/tiles2.png");
minimap_mounted = FILESYSTEM_isAssetMounted("graphics/minimap.png");
#endif
return true;
fail:
return false;
}
Uint32 Graphics::crewcolourreal(int t)

View File

@ -26,7 +26,7 @@ public:
int bfontlen(uint32_t ch);
int font_idx(uint32_t ch);
void Makebfont(void);
bool Makebfont(void);
void drawhuetile(int x, int y, int t);
void huetilesetcol(int t);
@ -34,11 +34,11 @@ public:
void drawgravityline(int t);
void MakeTileArray(void);
bool MakeTileArray(void);
void MakeSpriteArray(void);
bool MakeSpriteArray(void);
void maketelearray(void);
bool maketelearray(void);
void drawcoloredtile(int x, int y, int t, int r, int g, int b);
@ -222,7 +222,7 @@ public:
bool onscreen(int t);
void reloadresources(void);
bool reloadresources(void);
#ifndef NO_CUSTOM_LEVELS
bool tiles1_mounted;
bool tiles2_mounted;
@ -357,6 +357,9 @@ public:
bool kludgeswnlinewidth;
Uint32 crewcolourreal(int t);
char error[128];
char error_title[128]; /* for SDL_ShowSimpleMessageBox */
};
#ifndef GRAPHICS_DEFINITION

View File

@ -1727,6 +1727,11 @@ static void menuactionpress(void)
game.returnmenu();
map.nexttowercolour();
break;
case Menu::errorloadinglevel:
music.playef(11);
game.returnmenu();
map.nexttowercolour();
break;
default:
break;
}

View File

@ -1387,6 +1387,10 @@ static void menurender(void)
case Menu::errorsavingsettings:
graphics.Print( -1, 95, "ERROR: Could not save settings file!", tr, tg, tb, true);
break;
case Menu::errorloadinglevel:
graphics.bigprint(-1, 45, "ERROR", tr, tg, tb, true);
graphics.PrintWrap(-1, 65, graphics.error, tr, tg, tb, true, 10, 304);
break;
default:
break;
}

View File

@ -2634,6 +2634,14 @@ void scriptclass::resetgametomenu(void)
game.createmenu(Menu::gameover);
}
static void gotoerrorloadinglevel(void)
{
game.createmenu(Menu::errorloadinglevel);
graphics.fademode = 4; /* start fade in */
music.currentsong = -1; /* otherwise music.play won't work */
music.play(6); /* title screen music */
}
void scriptclass::startgamemode( int t )
{
switch(t)
@ -3152,7 +3160,11 @@ void scriptclass::startgamemode( int t )
//Initilise the level
//First up, find the start point
std::string filename = std::string(ed.ListOfMetaData[game.playcustomlevel].filename);
ed.load(filename);
if (!ed.load(filename))
{
gotoerrorloadinglevel();
break;
}
ed.findstartpoint();
game.gamestate = GAMEMODE;
@ -3190,7 +3202,11 @@ void scriptclass::startgamemode( int t )
//Initilise the level
//First up, find the start point
std::string filename = std::string(ed.ListOfMetaData[game.playcustomlevel].filename);
ed.load(filename);
if (!ed.load(filename))
{
gotoerrorloadinglevel();
break;
}
ed.findstartpoint();
game.gamestate = GAMEMODE;

View File

@ -78,6 +78,15 @@ void _VVV_between(
# define VVV_fallthrough do { } while (false) /* fallthrough */
#endif
#define MAYBE_FAIL(expr) \
do \
{ \
if (!expr) \
{ \
goto fail; \
} \
} \
while (false)
//helperClass
class UtilityClass

View File

@ -1748,6 +1748,11 @@ void editorclass::switch_enemy(const bool reversed /*= false*/)
bool editorclass::load(std::string& _path)
{
tinyxml2::XMLDocument doc;
tinyxml2::XMLHandle hDoc(&doc);
tinyxml2::XMLElement* pElem;
tinyxml2::XMLHandle hRoot(NULL);
reset();
static const char *levelDir = "levels/";
@ -1759,14 +1764,13 @@ bool editorclass::load(std::string& _path)
FILESYSTEM_unmountAssets();
if (game.cliplaytest && game.playassets != "")
{
FILESYSTEM_mountAssets(game.playassets.c_str());
MAYBE_FAIL(FILESYSTEM_mountAssets(game.playassets.c_str()));
}
else
{
FILESYSTEM_mountAssets(_path.c_str());
MAYBE_FAIL(FILESYSTEM_mountAssets(_path.c_str()));
}
tinyxml2::XMLDocument doc;
if (!FILESYSTEM_loadTiXml2Document(_path.c_str(), doc))
{
printf("No level %s to load :(\n", _path.c_str());
@ -1775,9 +1779,6 @@ bool editorclass::load(std::string& _path)
loaded_filepath = _path;
tinyxml2::XMLHandle hDoc(&doc);
tinyxml2::XMLElement* pElem;
tinyxml2::XMLHandle hRoot(NULL);
version = 0;
{
@ -2040,6 +2041,9 @@ next:
version=2;
return true;
fail:
return false;
}
bool editorclass::save(std::string& _path)

View File

@ -483,7 +483,19 @@ int main(int argc, char *argv[])
game.init();
// This loads music too...
graphics.reloadresources();
if (!graphics.reloadresources())
{
/* Something wrong with the default assets? We can't use them to
* display the error message, and we have to bail. */
SDL_ShowSimpleMessageBox(
SDL_MESSAGEBOX_ERROR,
graphics.error_title,
graphics.error,
NULL
);
VVV_exit(1);
}
game.gamestate = PRELOADER;