From 94b2ebd55c2a507cfa1a8463f91c6cfceed917f3 Mon Sep 17 00:00:00 2001 From: leo60228 Date: Thu, 9 Apr 2020 12:03:24 -0700 Subject: [PATCH] Implement command-line playtesting (#163) --- desktop_version/src/FileSystemUtils.cpp | 26 ++++++++ desktop_version/src/Game.cpp | 16 +++++ desktop_version/src/Game.h | 7 +++ desktop_version/src/main.cpp | 81 ++++++++++++++++++++++++- 4 files changed, 129 insertions(+), 1 deletion(-) diff --git a/desktop_version/src/FileSystemUtils.cpp b/desktop_version/src/FileSystemUtils.cpp index 3ad39abf..307a4432 100644 --- a/desktop_version/src/FileSystemUtils.cpp +++ b/desktop_version/src/FileSystemUtils.cpp @@ -7,6 +7,10 @@ #include #include +#include +#include +#include + #include #include @@ -144,6 +148,28 @@ char *FILESYSTEM_getUserLevelDirectory() void FILESYSTEM_loadFileToMemory(const char *name, unsigned char **mem, size_t *len, bool addnull) { + if (strcmp(name, "levels/special/stdin.vvvvvv") == 0) { + // this isn't *technically* necessary when piping directly from a file, but checking for that is annoying + static std::vector STDIN_BUFFER; + static bool STDIN_LOADED = false; + if (!STDIN_LOADED) { + std::istreambuf_iterator begin(std::cin), end; + STDIN_BUFFER.assign(begin, end); + STDIN_BUFFER.push_back(0); // there's no observable change in behavior if addnull is always true, but not vice versa + STDIN_LOADED = true; + } + + size_t length = STDIN_BUFFER.size() - 1; + if (len != NULL) { + *len = length; + } + + ++length; + *mem = static_cast(malloc(length)); // STDIN_BUFFER.data() causes double-free + std::copy(STDIN_BUFFER.begin(), STDIN_BUFFER.end(), reinterpret_cast(*mem)); + return; + } + PHYSFS_File *handle = PHYSFS_openRead(name); if (handle == NULL) { diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp index c3d2aa6a..13b37bf4 100644 --- a/desktop_version/src/Game.cpp +++ b/desktop_version/src/Game.cpp @@ -373,6 +373,13 @@ void Game::init(void) skipfakeload = false; + cliplaytest = false; + playx = 0; + playy = 0; + playrx = 0; + playry = 0; + playgc = 0; + /* Terry's Patrons... */ superpatrons.push_back("Anders Ekermo"); superpatrons.push_back("Andreas K|mper"); @@ -5154,6 +5161,15 @@ void Game::loadquick() void Game::customloadquick(std::string savfile) { + if (cliplaytest) { + savex = playx; + savey = savey; + saverx = playrx; + savery = playry; + savegc = playgc; + return; + } + std::string levelfile = savfile.substr(7); TiXmlDocument doc; if (!FILESYSTEM_loadTiXmlDocument(("saves/"+levelfile+".vvv").c_str(), &doc)) return; diff --git a/desktop_version/src/Game.h b/desktop_version/src/Game.h index b0cb8ec0..ccac8ab9 100644 --- a/desktop_version/src/Game.h +++ b/desktop_version/src/Game.h @@ -314,6 +314,13 @@ public: std::vector controllerButton_esc; bool skipfakeload; + + bool cliplaytest; + int playx; + int playy; + int playrx; + int playry; + int playgc; }; extern Game game; diff --git a/desktop_version/src/main.cpp b/desktop_version/src/main.cpp index cec7eb73..289be756 100644 --- a/desktop_version/src/main.cpp +++ b/desktop_version/src/main.cpp @@ -44,6 +44,17 @@ KeyPoll key; mapclass map; entityclass obj; +bool startinplaytest = false; +bool savefileplaytest = false; +int savex = 0; +int savey = 0; +int saverx = 0; +int savery = 0; +int savegc = 0; +int savemusic = 0; + +std::string playtestname; + int main(int argc, char *argv[]) { char* baseDir = NULL; @@ -59,6 +70,40 @@ int main(int argc, char *argv[]) } else if (strcmp(argv[i], "-assets") == 0) { ++i; assetsPath = argv[i]; + } else if (strcmp(argv[i], "-playing") == 0 || strcmp(argv[i], "-p") == 0) { + if (i + 1 < argc) { + startinplaytest = true; + i++; + playtestname = std::string("levels/"); + playtestname.append(argv[i]); + playtestname.append(std::string(".vvvvvv")); + } else { + printf("-playing option requires one argument.\n"); + return 1; + } + } else if (strcmp(argv[i], "-playx") == 0 || + strcmp(argv[i], "-playy") == 0 || + strcmp(argv[i], "-playrx") == 0 || + strcmp(argv[i], "-playry") == 0 || + strcmp(argv[i], "-playgc") == 0 || + strcmp(argv[i], "-playmusic") == 0) { + if (i + 1 < argc) { + savefileplaytest = true; + int v = std::atoi(argv[i+1]); + if (strcmp(argv[i], "-playx") == 0) savex = v; + else if (strcmp(argv[i], "-playy") == 0) savey = v; + else if (strcmp(argv[i], "-playrx") == 0) saverx = v; + else if (strcmp(argv[i], "-playry") == 0) savery = v; + else if (strcmp(argv[i], "-playgc") == 0) savegc = v; + else if (strcmp(argv[i], "-playmusic") == 0) savemusic = v; + i++; + } else { + printf("-playing option requires one argument.\n"); + return 1; + } + } + if (std::string(argv[i]) == "-renderer") { + SDL_SetHintWithPriority(SDL_HINT_RENDER_DRIVER, argv[2], SDL_HINT_OVERRIDE); } } @@ -152,7 +197,6 @@ int main(int argc, char *argv[]) FillRect(graphics.footerbuffer, SDL_MapRGB(fmt, 0, 0, 0)); graphics.Makebfont(); - graphics.foregroundBuffer = SDL_CreateRGBSurface(SDL_SWSURFACE ,320 ,240 ,fmt->BitsPerPixel,fmt->Rmask,fmt->Gmask,fmt->Bmask,fmt->Amask ); SDL_SetSurfaceBlendMode(graphics.foregroundBuffer, SDL_BLENDMODE_NONE); @@ -229,6 +273,41 @@ int main(int argc, char *argv[]) obj.init(); + if (startinplaytest) { + game.levelpage = 0; + game.playcustomlevel = 0; + + ed.directoryList.clear(); + ed.directoryList.push_back(playtestname); + + LevelMetaData meta; + if (ed.getLevelMetaData(playtestname, meta)) { + ed.ListOfMetaData.clear(); + ed.ListOfMetaData.push_back(meta); + } else { + printf("Level not found\n"); + return 1; + } + + game.loadcustomlevelstats(); + game.customleveltitle=ed.ListOfMetaData[game.playcustomlevel].title; + game.customlevelfilename=ed.ListOfMetaData[game.playcustomlevel].filename; + if (savefileplaytest) { + game.playx = savex; + game.playy = savey; + game.playrx = saverx; + game.playry = savery; + game.playgc = savegc; + game.cliplaytest = true; + music.play(savemusic); + script.startgamemode(23); + } else { + script.startgamemode(22); + } + + graphics.fademode = 0; + } + volatile Uint32 time, timePrev = 0; game.infocus = true; key.isActive = true;