Reorganize global replay code

Theoretically, the scenario and character editors could also have replay systems
This commit is contained in:
2024-06-13 13:22:39 -06:00
committed by Celtic Minstrel
parent 196c5d784a
commit 56169abaf5
6 changed files with 99 additions and 87 deletions

View File

@@ -26,15 +26,4 @@ struct effect_pat_type {
unsigned short pattern[9][9];
};
// Input recording system
namespace ticpp { class Element; }
using ticpp::Element;
extern bool recording;
extern bool replaying;
extern bool init_action_log(std::string command, std::string file);
extern void record_action(std::string action_type, std::string inner_text);
extern Element* pop_next_action(std::string expected_action_type="");
#endif

View File

@@ -1,8 +1,8 @@
#include "boe.global.hpp"
#include "tools/replay.hpp"
#include "universe/universe.hpp"
#include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/lexical_cast.hpp>
#include <unordered_map>
@@ -220,81 +220,6 @@ static void init_ui() {
init_buttons();
}
// Input recording system
#include <ctime>
#include <iomanip>
bool recording = false;
bool replaying = false;
using namespace ticpp;
Document log_document;
std::string log_file;
bool init_action_log(std::string command, std::string file) {
if (command == "record") {
// If a filename is given, use it as a base, but insert a timestamp for uniqueness.
if (file.empty())
file = "BoE";
if (boost::ends_with(file, ".xml"))
file = file.substr(0, file.length() - 4);
// Get a time stamp
std::time_t t = time(nullptr);
auto tm = *std::localtime(&t);
std::ostringstream stream;
stream << file << std::put_time(&tm, "_%d-%m-%Y_%H-%M-%S") << ".xml";
log_file = stream.str();
try {
Element root_element("actions");
log_document.InsertEndChild(root_element);
log_document.SaveFile(log_file);
recording = true;
std::cout << "Recording this session: " << log_file << std::endl;
} catch(...) {
std::cout << "Failed to write to file " << log_file << std::endl;
}
return true;
}
else if (command == "replay") {
try {
log_document.LoadFile(file);
replaying = true;
} catch(...) {
std::cout << "Failed to load file " << file << std::endl;
}
return true;
}
return false;
}
void record_action(std::string action_type, std::string inner_text) {
Element* root = log_document.FirstChildElement();
Element next_action(action_type);
Text action_text(inner_text);
next_action.InsertEndChild(action_text);
root->InsertEndChild(next_action);
log_document.SaveFile(log_file);
}
Element* pop_next_action(std::string expected_action_type) {
Element* root = log_document.FirstChildElement();
Element* next_action = root->FirstChildElement();
if (expected_action_type != "" && next_action->Value() != expected_action_type) {
std::ostringstream stream;
stream << "Replay error! Expected '" << expected_action_type << "' action next";
throw stream.str();
}
Element* clone = next_action->Clone()->ToElement();
root->RemoveChild(next_action);
return clone;
}
void process_args(int argc, char* argv[]) {
// Command line usage:
// "Blades of Exile" # basic launch

View File

@@ -6,6 +6,7 @@ tools = Split("""
framerate_limiter.cpp
drawable_manager.cpp
keymods.cpp
replay.cpp
../location.cpp
../mathutil.cpp
../porting.cpp
@@ -20,6 +21,7 @@ tools = Split("""
../fileio/tarball.cpp
../fileio/tagfile.cpp
../fileio/gzstream/gzstream.cpp
../fileio/xml-parser/ticpp.cpp
""") + Glob("../fileio/resmgr/*.cpp") + Glob("../gfx/*.cpp") + Glob("../scenario/*.cpp")
if str(platform) == "darwin":

View File

@@ -1,6 +1,7 @@
#include "prefs.hpp"
#include "game/boe.global.hpp"
#include "tools/replay.hpp"
#include "ticpp.h"
#include <map>
#include <string>

78
src/tools/replay.cpp Normal file
View File

@@ -0,0 +1,78 @@
#include "replay.hpp"
// Input recording system
#include "ticpp.h"
#include <ctime>
#include <iomanip>
#include <boost/algorithm/string/predicate.hpp>
bool recording = false;
bool replaying = false;
using namespace ticpp;
Document log_document;
std::string log_file;
bool init_action_log(std::string command, std::string file) {
if (command == "record") {
// If a filename is given, use it as a base, but insert a timestamp for uniqueness.
if (file.empty())
file = "BoE";
if (boost::ends_with(file, ".xml"))
file = file.substr(0, file.length() - 4);
// Get a time stamp
std::time_t t = time(nullptr);
auto tm = *std::localtime(&t);
std::ostringstream stream;
stream << file << std::put_time(&tm, "_%d-%m-%Y_%H-%M-%S") << ".xml";
log_file = stream.str();
try {
Element root_element("actions");
log_document.InsertEndChild(root_element);
log_document.SaveFile(log_file);
recording = true;
std::cout << "Recording this session: " << log_file << std::endl;
} catch(...) {
std::cout << "Failed to write to file " << log_file << std::endl;
}
return true;
}
else if (command == "replay") {
try {
log_document.LoadFile(file);
replaying = true;
} catch(...) {
std::cout << "Failed to load file " << file << std::endl;
}
return true;
}
return false;
}
void record_action(std::string action_type, std::string inner_text) {
Element* root = log_document.FirstChildElement();
Element next_action(action_type);
Text action_text(inner_text);
next_action.InsertEndChild(action_text);
root->InsertEndChild(next_action);
log_document.SaveFile(log_file);
}
Element* pop_next_action(std::string expected_action_type) {
Element* root = log_document.FirstChildElement();
Element* next_action = root->FirstChildElement();
if (expected_action_type != "" && next_action->Value() != expected_action_type) {
std::ostringstream stream;
stream << "Replay error! Expected '" << expected_action_type << "' action next";
throw stream.str();
}
Element* clone = next_action->Clone()->ToElement();
root->RemoveChild(next_action);
return clone;
}

17
src/tools/replay.hpp Normal file
View File

@@ -0,0 +1,17 @@
#ifndef REPLAY_GLOBAL_H
#define REPLAY_GLOBAL_H
#include "boe.global.hpp"
// Input recording system
namespace ticpp { class Element; }
using ticpp::Element;
extern bool recording;
extern bool replaying;
extern bool init_action_log(std::string command, std::string file);
extern void record_action(std::string action_type, std::string inner_text);
extern Element* pop_next_action(std::string expected_action_type="");
#endif