From 9b4eaeed047c2b202b4449a540832a5361b32cf5 Mon Sep 17 00:00:00 2001 From: Vankata453 <78196474+Vankata453@users.noreply.github.com> Date: Sun, 11 Feb 2024 14:44:27 +0200 Subject: [PATCH] Remove `GameSessionRecorder` (#2755) Removal reasons: * It can be coded better as a whole, utilizing features like PhysFS file reading/writing using `ReaderMapping`/`Writer` (would also prevent security issues, like #2398). * It is made very hidden from the regular user. * I have personally never seen anyone use this feature, or have interest in it. I also do not see any practical use for it currently, other than for TAS-es (tool-assisted speedruns), but for that purpose, there is already special software which can do much more and is better suited for that purpose, like libTAS. Closes #2398. --- src/scripting/functions.cpp | 26 ---- src/scripting/functions.hpp | 12 -- src/scripting/wrapper.cpp | 60 -------- src/supertux/command_line_arguments.cpp | 30 ---- src/supertux/command_line_arguments.hpp | 2 - src/supertux/game_session.cpp | 8 -- src/supertux/game_session.hpp | 7 +- src/supertux/game_session_recorder.cpp | 180 ------------------------ src/supertux/game_session_recorder.hpp | 60 -------- src/supertux/gameconfig.cpp | 2 - src/supertux/gameconfig.hpp | 2 - src/supertux/main.cpp | 9 +- src/supertux/title_screen.hpp | 2 +- 13 files changed, 5 insertions(+), 395 deletions(-) delete mode 100644 src/supertux/game_session_recorder.cpp delete mode 100644 src/supertux/game_session_recorder.hpp diff --git a/src/scripting/functions.cpp b/src/scripting/functions.cpp index d85baf86bd1..115cc0abc20 100644 --- a/src/scripting/functions.cpp +++ b/src/scripting/functions.cpp @@ -459,32 +459,6 @@ void set_game_speed(float speed) ::g_debug.set_game_speed_multiplier(speed); } -void record_demo(const std::string& filename) -{ - if (GameSession::current() == nullptr) - { - log_info << "No game session." << std::endl; - return; - } - GameSession::current()->restart_level(); - GameSession::current()->record_demo(filename); -} - -void play_demo(const std::string& filename) -{ - auto session = GameSession::current(); - if (session == nullptr) - { - log_info << "No game session." << std::endl; - return; - } - // Reset random seed. - g_config->random_seed = session->get_demo_random_seed(filename); - gameRandom.seed(g_config->random_seed); - session->restart_level(); - session->play_demo(filename); -} - void set_title_frame(const std::string& image) { auto title_screen = TitleScreen::current(); diff --git a/src/scripting/functions.hpp b/src/scripting/functions.hpp index 14602bc6850..84322943390 100644 --- a/src/scripting/functions.hpp +++ b/src/scripting/functions.hpp @@ -289,18 +289,6 @@ void set_gamma(float gamma); */ int rand(); -/** - * Records a demo to the given file. - * @param string $filename - */ -void record_demo(const std::string& filename); - -/** - * Plays back a demo from the given file. - * @param string $filename - */ -void play_demo(const std::string& filename); - /** * Sets the frame, displayed on the title screen. * @param string $image diff --git a/src/scripting/wrapper.cpp b/src/scripting/wrapper.cpp index 91f453f5042..43af0024af9 100644 --- a/src/scripting/wrapper.cpp +++ b/src/scripting/wrapper.cpp @@ -12973,52 +12973,6 @@ static SQInteger rand_wrapper(HSQUIRRELVM vm) } -static SQInteger record_demo_wrapper(HSQUIRRELVM vm) -{ - const SQChar* arg0; - if(SQ_FAILED(sq_getstring(vm, 2, &arg0))) { - sq_throwerror(vm, _SC("Argument 1 not a string")); - return SQ_ERROR; - } - - try { - scripting::record_demo(arg0); - - return 0; - - } catch(std::exception& e) { - sq_throwerror(vm, e.what()); - return SQ_ERROR; - } catch(...) { - sq_throwerror(vm, _SC("Unexpected exception while executing function 'record_demo'")); - return SQ_ERROR; - } - -} - -static SQInteger play_demo_wrapper(HSQUIRRELVM vm) -{ - const SQChar* arg0; - if(SQ_FAILED(sq_getstring(vm, 2, &arg0))) { - sq_throwerror(vm, _SC("Argument 1 not a string")); - return SQ_ERROR; - } - - try { - scripting::play_demo(arg0); - - return 0; - - } catch(std::exception& e) { - sq_throwerror(vm, e.what()); - return SQ_ERROR; - } catch(...) { - sq_throwerror(vm, _SC("Unexpected exception while executing function 'play_demo'")); - return SQ_ERROR; - } - -} - static SQInteger set_title_frame_wrapper(HSQUIRRELVM vm) { const SQChar* arg0; @@ -14535,20 +14489,6 @@ void register_supertux_wrapper(HSQUIRRELVM v) throw SquirrelError(v, "Couldn't register function 'rand'"); } - sq_pushstring(v, "record_demo", -1); - sq_newclosure(v, &record_demo_wrapper, 0); - sq_setparamscheck(v, SQ_MATCHTYPEMASKSTRING, ".s"); - if(SQ_FAILED(sq_createslot(v, -3))) { - throw SquirrelError(v, "Couldn't register function 'record_demo'"); - } - - sq_pushstring(v, "play_demo", -1); - sq_newclosure(v, &play_demo_wrapper, 0); - sq_setparamscheck(v, SQ_MATCHTYPEMASKSTRING, ".s"); - if(SQ_FAILED(sq_createslot(v, -3))) { - throw SquirrelError(v, "Couldn't register function 'play_demo'"); - } - sq_pushstring(v, "set_title_frame", -1); sq_newclosure(v, &set_title_frame_wrapper, 0); sq_setparamscheck(v, SQ_MATCHTYPEMASKSTRING, ".s"); diff --git a/src/supertux/command_line_arguments.cpp b/src/supertux/command_line_arguments.cpp index 8e71c17f5d2..45d163e5ca2 100644 --- a/src/supertux/command_line_arguments.cpp +++ b/src/supertux/command_line_arguments.cpp @@ -43,8 +43,6 @@ CommandLineArguments::CommandLineArguments() : music_enabled(), filenames(), enable_script_debugger(), - start_demo(), - record_demo(), tux_spawn_pos(), sector(), spawnpoint(), @@ -125,10 +123,6 @@ CommandLineArguments::print_help(const char* arg0) const << _(" --sector SECTOR Spawn Tux in SECTOR\n") << "\n" << _(" --spawnpoint SPAWNPOINT Spawn Tux at SPAWNPOINT\n") << "\n" << "\n" - << _("Demo Recording Options:") << "\n" - << _(" --record-demo FILE LEVEL Record a demo to FILE") << "\n" - << _(" --play-demo FILE LEVEL Play a recorded demo") << "\n" - << "\n" << _("Directory Options:") << "\n" << _(" --datadir DIR Set the directory for the games datafiles") << "\n" << _(" --userdir DIR Set the directory for user data (savegames, etc.)") << "\n" @@ -319,28 +313,6 @@ CommandLineArguments::parse_args(int argc, char** argv) { music_enabled = false; } - else if (arg == "--play-demo") - { - if (i + 1 >= argc) - { - throw std::runtime_error("Need to specify a demo filename"); - } - else - { - start_demo = argv[++i]; - } - } - else if (arg == "--record-demo") - { - if (i + 1 >= argc) - { - throw std::runtime_error("Need to specify a demo filename"); - } - else - { - record_demo = argv[++i]; - } - } else if (arg == "--spawn-pos") { Vector spawn_pos(0.0f, 0.0f); @@ -427,8 +399,6 @@ CommandLineArguments::merge_into(Config& config) merge_option(sound_enabled) merge_option(music_enabled) merge_option(enable_script_debugger) - merge_option(start_demo) - merge_option(record_demo) merge_option(tux_spawn_pos) merge_option(developer_mode) merge_option(christmas_mode) diff --git a/src/supertux/command_line_arguments.hpp b/src/supertux/command_line_arguments.hpp index 8a7cc111230..6bef6c28632 100644 --- a/src/supertux/command_line_arguments.hpp +++ b/src/supertux/command_line_arguments.hpp @@ -67,8 +67,6 @@ class CommandLineArguments final std::vector filenames; std::optional enable_script_debugger; - std::optional start_demo; - std::optional record_demo; std::optional tux_spawn_pos; std::optional sector; std::optional spawnpoint; diff --git a/src/supertux/game_session.cpp b/src/supertux/game_session.cpp index 02f59891150..392f43e77b7 100644 --- a/src/supertux/game_session.cpp +++ b/src/supertux/game_session.cpp @@ -48,7 +48,6 @@ GameSession::GameSession(const std::string& levelfile_, Savegame& savegame, Statistics* statistics, bool preserve_music) : - GameSessionRecorder(), reset_button(false), reset_checkpoint_button(false), m_prevent_death(false), @@ -234,8 +233,6 @@ GameSession::restart_level(bool after_death, bool preserve_music) it++; } - start_recording(); - return (0); } @@ -446,8 +443,6 @@ GameSession::update(float dt_sec, const Controller& controller) // design choice, if you prefer it not to animate when paused, add `if (!m_game_pause)`). m_level->m_stats.update_timers(dt_sec); - process_events(); - // Unpause the game if the menu has been closed. if (m_game_pause && !MenuManager::instance().is_active()) { ScreenManager::current()->set_speed(m_speed_before_pause); @@ -480,9 +475,6 @@ GameSession::update(float dt_sec, const Controller& controller) m_currentsector = sector; m_currentsector->play_looping_sounds(); - if (is_playing_demo()) - reset_demo_controller(); - m_newsector = ""; m_newspawnpoint = ""; } diff --git a/src/supertux/game_session.hpp b/src/supertux/game_session.hpp index 39e758b4be6..634e37b1fc5 100644 --- a/src/supertux/game_session.hpp +++ b/src/supertux/game_session.hpp @@ -17,6 +17,9 @@ #ifndef HEADER_SUPERTUX_SUPERTUX_GAME_SESSION_HPP #define HEADER_SUPERTUX_SUPERTUX_GAME_SESSION_HPP +#include "supertux/screen.hpp" +#include "util/currenton.hpp" + #include #include #include @@ -27,12 +30,9 @@ #include "squirrel/squirrel_scheduler.hpp" #include "squirrel/squirrel_util.hpp" #include "supertux/game_object.hpp" -#include "supertux/game_session_recorder.hpp" #include "supertux/player_status.hpp" -#include "supertux/screen.hpp" #include "supertux/sequence.hpp" #include "supertux/timer.hpp" -#include "util/currenton.hpp" #include "video/surface_ptr.hpp" class CodeController; @@ -46,7 +46,6 @@ class Savegame; /** Screen that runs a Level, where Players run and jump through Sectors. */ class GameSession final : public Screen, - public GameSessionRecorder, public Currenton { private: diff --git a/src/supertux/game_session_recorder.cpp b/src/supertux/game_session_recorder.cpp deleted file mode 100644 index 3cd195823a9..00000000000 --- a/src/supertux/game_session_recorder.cpp +++ /dev/null @@ -1,180 +0,0 @@ -// SuperTux -// Copyright (C) 2017 Tobias Markus -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -#include "supertux/game_session_recorder.hpp" - -#include - -#include "control/input_manager.hpp" -#include "math/random.hpp" -#include "object/player.hpp" -#include "supertux/game_session.hpp" -#include "supertux/gameconfig.hpp" -#include "supertux/globals.hpp" -#include "supertux/sector.hpp" -#include "util/log.hpp" - -GameSessionRecorder::GameSessionRecorder() : - m_capture_file(), - m_capture_demo_stream(), - m_playback_demo_stream(), - m_demo_controller(), - m_playing(false) -{ -} - -GameSessionRecorder::~GameSessionRecorder() -{ -} - -void -GameSessionRecorder::start_recording() -{ - if (!m_capture_file.empty()) { - int newSeed = 0; // Next run uses a new seed - while (newSeed == 0) // which is the next non-zero random num. - newSeed = gameRandom.rand(); - g_config->random_seed = newSeed; - gameRandom.seed(g_config->random_seed); - log_info << "Next run uses random seed " << g_config->random_seed <good()) { - std::stringstream msg; - msg << "Couldn't open demo file '" << filename << "' for writing."; - throw std::runtime_error(msg.str()); - } - m_capture_file = filename; - - char buf[30]; // Save the seed in the demo file. - snprintf(buf, sizeof(buf), "random_seed=%10d", g_config->random_seed); - for (int i = 0; i == 0 || buf[i-1]; i++) - m_capture_demo_stream->put(buf[i]); -} - -int -GameSessionRecorder::get_demo_random_seed(const std::string& filename) const -{ - std::unique_ptr test_stream(new std::ifstream(filename.c_str())); - if (test_stream->good()) - { - char buf[30]; // Recall the seed from the demo file. - int seed; - - for (int i=0; i<30 && (i==0 || buf[i-1]); i++) - test_stream->get(buf[i]); - - if (sscanf(buf, "random_seed=%10d", &seed) == 1) - { - log_info << "Random seed " << seed << " from demo file." << std::endl; - return seed; - } - else - { - log_info << "Demo file contains no random number." << std::endl; - } - } - return 0; -} - -void -GameSessionRecorder::play_demo(const std::string& filename) -{ - m_playing = true; - - m_playback_demo_stream.reset(); - m_demo_controller.reset(); - - m_playback_demo_stream.reset(new std::ifstream(filename.c_str())); - if (!m_playback_demo_stream->good()) { - std::stringstream msg; - msg << "Couldn't open demo file '" << filename << "' for reading."; - throw std::runtime_error(msg.str()); - } - - reset_demo_controller(); - - // Skip over random seed, if it exists in the file. - char buf[30]; // Ascii decimal seed. - int seed; - for (int i=0; i<30 && (i==0 || buf[i-1]); i++) - m_playback_demo_stream->get(buf[i]); - if (sscanf(buf, "random_seed=%010d", &seed) != 1) - m_playback_demo_stream->seekg(0); // Old style w/o seed, restart at beg. - - m_playing = false; -} - -void -GameSessionRecorder::reset_demo_controller() -{ - if (!m_demo_controller) { - m_demo_controller.reset(new CodeController()); - } - - auto game_session = GameSession::current(); - assert(game_session != nullptr); - // FIXME: How is this going to be handled? - Player& player = *(game_session->get_current_sector().get_players()[0]); - player.set_controller(m_demo_controller.get()); -} - -void -GameSessionRecorder::process_events() -{ - // Playback a demo? - if (m_playback_demo_stream != nullptr) - { - m_demo_controller->update(); - - char left, right, up, down, jump, action; - - m_playback_demo_stream->get(left); - m_playback_demo_stream->get(right); - m_playback_demo_stream->get(up); - m_playback_demo_stream->get(down); - m_playback_demo_stream->get(jump); - m_playback_demo_stream->get(action); - - m_demo_controller->press(Control::LEFT, left != 0); - m_demo_controller->press(Control::RIGHT, right != 0); - m_demo_controller->press(Control::UP, up != 0); - m_demo_controller->press(Control::DOWN, down != 0); - m_demo_controller->press(Control::JUMP, jump != 0); - m_demo_controller->press(Control::ACTION, action != 0); - } - - // Save input for demo? - if (m_capture_demo_stream != nullptr) - { - Controller& controller = InputManager::current()->get_controller(); - - m_capture_demo_stream->put(controller.hold(Control::LEFT)); - m_capture_demo_stream->put(controller.hold(Control::RIGHT)); - m_capture_demo_stream->put(controller.hold(Control::UP)); - m_capture_demo_stream->put(controller.hold(Control::DOWN)); - m_capture_demo_stream->put(controller.hold(Control::JUMP)); - m_capture_demo_stream->put(controller.hold(Control::ACTION)); - } -} - -/* EOF */ diff --git a/src/supertux/game_session_recorder.hpp b/src/supertux/game_session_recorder.hpp deleted file mode 100644 index d6c4d8a7c7f..00000000000 --- a/src/supertux/game_session_recorder.hpp +++ /dev/null @@ -1,60 +0,0 @@ -// SuperTux -// Copyright (C) 2017 Tobias Markus -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -#ifndef HEADER_SUPERTUX_SUPERTUX_GAME_SESSION_RECORDER_HPP -#define HEADER_SUPERTUX_SUPERTUX_GAME_SESSION_RECORDER_HPP - -#include -#include - -#include "control/codecontroller.hpp" - -class GameSessionRecorder -{ -public: - GameSessionRecorder(); - virtual ~GameSessionRecorder(); - - void start_recording(); - void record_demo(const std::string& filename); - int get_demo_random_seed(const std::string& filename) const; - void play_demo(const std::string& filename); - void process_events(); - - /** Re-sets the demo controller in case the sector (and thus the - Player instance) changes. */ - void reset_demo_controller(); - - bool is_playing_demo() const { return m_playing; } - -private: - void capture_demo_step(); - -private: - std::string m_capture_file; - std::unique_ptr m_capture_demo_stream; - std::unique_ptr m_playback_demo_stream; - std::unique_ptr m_demo_controller; - bool m_playing; - -private: - GameSessionRecorder(const GameSessionRecorder&) = delete; - GameSessionRecorder& operator=(const GameSessionRecorder&) = delete; -}; - -#endif - -/* EOF */ diff --git a/src/supertux/gameconfig.cpp b/src/supertux/gameconfig.cpp index ebd10571ce7..d09c8279b5f 100644 --- a/src/supertux/gameconfig.cpp +++ b/src/supertux/gameconfig.cpp @@ -61,8 +61,6 @@ Config::Config() : music_volume(50), random_seed(0), // Set by time(), by default (unless in config). enable_script_debugger(false), - start_demo(), - record_demo(), tux_spawn_pos(), locale(), keyboard_config(), diff --git a/src/supertux/gameconfig.hpp b/src/supertux/gameconfig.hpp index 7e853f5661b..83e96385997 100644 --- a/src/supertux/gameconfig.hpp +++ b/src/supertux/gameconfig.hpp @@ -73,8 +73,6 @@ class Config final int random_seed; bool enable_script_debugger; - std::string start_demo; - std::string record_demo; /** this variable is set if tux should spawn somewhere which isn't the "main" spawn point*/ std::optional tux_spawn_pos; diff --git a/src/supertux/main.cpp b/src/supertux/main.cpp index 26084961ed5..acc2a775c09 100644 --- a/src/supertux/main.cpp +++ b/src/supertux/main.cpp @@ -607,10 +607,8 @@ Main::launch_game(const CommandLineArguments& args) } else { // launch game - std::unique_ptr session ( - new GameSession(filename, *m_savegame)); + std::unique_ptr session = std::make_unique(filename, *m_savegame); - g_config->random_seed = session->get_demo_random_seed(g_config->start_demo); gameRandom.seed(g_config->random_seed); graphicsRandom.seed(0); @@ -633,11 +631,6 @@ Main::launch_game(const CommandLineArguments& args) session->get_current_sector().get_players()[0]->set_pos(*g_config->tux_spawn_pos); } - if (!g_config->start_demo.empty()) - session->play_demo(g_config->start_demo); - - if (!g_config->record_demo.empty()) - session->record_demo(g_config->record_demo); m_screen_manager->push_screen(std::move(session)); } } diff --git a/src/supertux/title_screen.hpp b/src/supertux/title_screen.hpp index d6813a0249c..21fac102f66 100644 --- a/src/supertux/title_screen.hpp +++ b/src/supertux/title_screen.hpp @@ -24,10 +24,10 @@ #include +#include "control/codecontroller.hpp" #include "supertux/fadetoblack.hpp" #include "video/surface_ptr.hpp" -class CodeController; class GameSession; class Savegame; class Sector;