1
0
Fork 0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-12-23 01:59:43 +01: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 filename[MAX_PATH];
char zip_data[MAX_PATH]; char zip_data[MAX_PATH];
@ -504,10 +506,10 @@ void FILESYSTEM_mountAssets(const char* path)
if (!FILESYSTEM_mountAssetsFrom(zip_data)) if (!FILESYSTEM_mountAssetsFrom(zip_data))
{ {
return; return false;
} }
graphics.reloadresources(); MAYBE_FAIL(graphics.reloadresources());
} }
else if (zip_normal != NULL && endsWith(zip_normal, ".zip")) else if (zip_normal != NULL && endsWith(zip_normal, ".zip"))
{ {
@ -515,10 +517,10 @@ void FILESYSTEM_mountAssets(const char* path)
if (!FILESYSTEM_mountAssetsFrom(zip_normal)) if (!FILESYSTEM_mountAssetsFrom(zip_normal))
{ {
return; return false;
} }
graphics.reloadresources(); MAYBE_FAIL(graphics.reloadresources());
} }
else if (FILESYSTEM_exists(dir)) else if (FILESYSTEM_exists(dir))
{ {
@ -526,15 +528,21 @@ void FILESYSTEM_mountAssets(const char* path)
if (!FILESYSTEM_mountAssetsFrom(dir)) if (!FILESYSTEM_mountAssetsFrom(dir))
{ {
return; return false;
} }
graphics.reloadresources(); MAYBE_FAIL(graphics.reloadresources());
} }
else else
{ {
puts("Custom asset directory does not exist"); puts("Custom asset directory does not exist");
} }
return true;
fail:
FILESYSTEM_unmountAssets();
return false;
} }
void FILESYSTEM_unmountAssets(void) void FILESYSTEM_unmountAssets(void)

View file

@ -19,7 +19,7 @@ bool FILESYSTEM_isFile(const char* filename);
bool FILESYSTEM_isMounted(const char* filename); bool FILESYSTEM_isMounted(const char* filename);
void FILESYSTEM_loadZip(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); void FILESYSTEM_unmountAssets(void);
bool FILESYSTEM_isAssetMounted(const char* filename); bool FILESYSTEM_isAssetMounted(const char* filename);

View file

@ -6477,6 +6477,9 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
option("silence"); option("silence");
menuyoff = 10; menuyoff = 10;
break; break;
case Menu::errorloadinglevel:
option("ok");
break;
} }
// Automatically center the menu. We must check the width of the menu with the initial horizontal spacing. // 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, youwannaquit,
errornostart, errornostart,
errorsavingsettings, errorsavingsettings,
errorloadinglevel,
graphicoptions, graphicoptions,
ed_settings, ed_settings,
ed_desc, ed_desc,

View file

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

View file

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

View file

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

View file

@ -1387,6 +1387,10 @@ static void menurender(void)
case Menu::errorsavingsettings: case Menu::errorsavingsettings:
graphics.Print( -1, 95, "ERROR: Could not save settings file!", tr, tg, tb, true); graphics.Print( -1, 95, "ERROR: Could not save settings file!", tr, tg, tb, true);
break; 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: default:
break; break;
} }

View file

@ -2634,6 +2634,14 @@ void scriptclass::resetgametomenu(void)
game.createmenu(Menu::gameover); 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 ) void scriptclass::startgamemode( int t )
{ {
switch(t) switch(t)
@ -3152,7 +3160,11 @@ void scriptclass::startgamemode( int t )
//Initilise the level //Initilise the level
//First up, find the start point //First up, find the start point
std::string filename = std::string(ed.ListOfMetaData[game.playcustomlevel].filename); std::string filename = std::string(ed.ListOfMetaData[game.playcustomlevel].filename);
ed.load(filename); if (!ed.load(filename))
{
gotoerrorloadinglevel();
break;
}
ed.findstartpoint(); ed.findstartpoint();
game.gamestate = GAMEMODE; game.gamestate = GAMEMODE;
@ -3190,7 +3202,11 @@ void scriptclass::startgamemode( int t )
//Initilise the level //Initilise the level
//First up, find the start point //First up, find the start point
std::string filename = std::string(ed.ListOfMetaData[game.playcustomlevel].filename); std::string filename = std::string(ed.ListOfMetaData[game.playcustomlevel].filename);
ed.load(filename); if (!ed.load(filename))
{
gotoerrorloadinglevel();
break;
}
ed.findstartpoint(); ed.findstartpoint();
game.gamestate = GAMEMODE; game.gamestate = GAMEMODE;

View file

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

View file

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

View file

@ -483,7 +483,19 @@ int main(int argc, char *argv[])
game.init(); game.init();
// This loads music too... // 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; game.gamestate = PRELOADER;