diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 651e05b308..0600488c13 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -1057,10 +1057,6 @@ anticheat_flags (Anticheat flags) flags digging,interaction,movement digging,int # Increase the value if players experience stuttery movement. anticheat_movement_tolerance (Anticheat movement tolerance) float 1.0 1.0 -# If enabled, actions are recorded for rollback. -# This option is only read when server starts. -enable_rollback_recording (Rollback recording) bool false - [**Client-side Modding] # Restricts the access of certain client-side functions on servers. @@ -2249,6 +2245,11 @@ kick_msg_crash (Crash message) string This server has experienced an internal er # Set this to true if your server is set up to restart automatically. ask_reconnect_on_crash (Ask to reconnect after crash) bool false +# If enabled, node and inventory actions are recorded for rollback. +# This option is only read on server start. Note that the engine will not +# automatically clean old entries from the rollback database. +enable_rollback_recording (Rollback recording) bool false + [**Server/Env Performance] [server] # Length of a server tick (the interval at which everything is generally updated), diff --git a/src/rollback_interface.h b/src/rollback_interface.h index 0a41895fdc..123c3323ad 100644 --- a/src/rollback_interface.h +++ b/src/rollback_interface.h @@ -22,12 +22,15 @@ struct RollbackNode int param2 = 0; std::string meta; - bool operator == (const RollbackNode &other) + bool operator == (const RollbackNode &other) const { return (name == other.name && param1 == other.param1 && param2 == other.param2 && meta == other.meta); } - bool operator != (const RollbackNode &other) { return !(*this == other); } + bool operator != (const RollbackNode &other) const + { + return !(*this == other); + } RollbackNode() = default; @@ -37,15 +40,16 @@ struct RollbackNode struct RollbackAction { - enum Type{ + enum Type : u8 { TYPE_NOTHING, TYPE_SET_NODE, TYPE_MODIFY_INVENTORY_STACK, - } type = TYPE_NOTHING; + }; time_t unix_time = 0; std::string actor; bool actor_is_guess = false; + Type type = TYPE_NOTHING; v3s16 p; RollbackNode n_old; diff --git a/src/server/rollback.cpp b/src/server/rollback.cpp index 43ca70bb3a..61830ee08d 100644 --- a/src/server/rollback.cpp +++ b/src/server/rollback.cpp @@ -17,7 +17,7 @@ #include "sqlite3.h" #include "filesys.h" -#define POINTS_PER_NODE (16.0) +#define POINTS_PER_NODE (16.0f) #define SQLRES(f, good) \ if ((f) != (good)) {\ @@ -44,11 +44,11 @@ public: return *this; } - int id; + int id = 0; }; struct ActionRow { - int id; + int id = 0; int actor; time_t timestamp; int type; @@ -231,7 +231,6 @@ bool RollbackManager::createTables() "CREATE INDEX IF NOT EXISTS `actionIndex` ON `action`(`x`,`y`,`z`,`timestamp`,`actor`);\n" "CREATE INDEX IF NOT EXISTS `actionTimestampActorIndex` ON `action`(`timestamp`,`actor`);\n", NULL, NULL, NULL)); - verbosestream << "SQL Rollback: SQLite3 database structure was created" << std::endl; return true; } @@ -241,13 +240,10 @@ bool RollbackManager::initDatabase() { verbosestream << "RollbackManager: Database connection setup" << std::endl; - bool needs_create = !fs::PathExists(database_path); SQLOK(sqlite3_open_v2(database_path.c_str(), &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL)); - if (needs_create) { - createTables(); - } + createTables(); SQLOK(sqlite3_prepare_v2(db, "INSERT INTO `action` (\n" @@ -362,7 +358,7 @@ bool RollbackManager::initDatabase() } SQLOK(sqlite3_reset(stmt_knownNode_select)); - return needs_create; + return true; } @@ -522,7 +518,6 @@ ActionRow RollbackManager::actionRowFromRollbackAction(const RollbackAction & ac { ActionRow row; - row.id = 0; row.actor = getActorId(action.actor); row.timestamp = action.unix_time; row.type = action.type; @@ -589,7 +584,7 @@ const std::list RollbackManager::rollbackActionsFromActionRows( break; default: - throw ("W.T.F."); + assert(false); break; } @@ -667,12 +662,10 @@ float RollbackManager::getSuspectNearness(bool is_guess, v3s16 suspect_p, f -= 1 * (action_t - suspect_t); // If is a guess, halve the points if (is_guess) { - f *= 0.5; + f /= 2; } // Limit to 0 - if (f < 0) { - f = 0; - } + f = MYMAX(f, 0); return f; } @@ -730,12 +723,11 @@ std::string RollbackManager::getSuspect(v3s16 p, float nearness_shortcut, if (!current_actor.empty()) { return current_actor; } - int cur_time = time(0); + time_t cur_time = time(0); time_t first_time = cur_time - (100 - min_nearness); RollbackAction likely_suspect; float likely_suspect_nearness = 0; - for (std::list::const_reverse_iterator - i = action_latest_buffer.rbegin(); + for (auto i = action_latest_buffer.rbegin(); i != action_latest_buffer.rend(); ++i) { if (i->unix_time < first_time) { break; @@ -795,15 +787,20 @@ void RollbackManager::addAction(const RollbackAction & action) if (action_todisk_buffer.size() >= 500) { flush(); } + // Cut off latest log sometimes + while (action_latest_buffer.size() >= 500) { + action_latest_buffer.pop_front(); + } } std::list RollbackManager::getNodeActors(v3s16 pos, int range, time_t seconds, int limit) { - flush(); time_t cur_time = time(0); time_t first_time = cur_time - seconds; + flush(); + return getActionsSince_range(first_time, pos, range, limit); } diff --git a/src/server/rollback.h b/src/server/rollback.h index c085b73135..887f862ce3 100644 --- a/src/server/rollback.h +++ b/src/server/rollback.h @@ -9,6 +9,7 @@ #include "rollback_interface.h" #include #include +#include #include "sqlite3.h" class IGameDef; @@ -16,7 +17,7 @@ class IGameDef; struct ActionRow; struct Entity; -class RollbackManager: public IRollbackManager +class RollbackManager final : public IRollbackManager { public: RollbackManager(const std::string & world_path, IGameDef * gamedef); @@ -67,20 +68,20 @@ private: std::string current_actor; bool current_actor_is_guess = false; - std::list action_todisk_buffer; - std::list action_latest_buffer; + std::vector action_todisk_buffer; + std::deque action_latest_buffer; std::string database_path; - sqlite3 * db; - sqlite3_stmt * stmt_insert; - sqlite3_stmt * stmt_replace; - sqlite3_stmt * stmt_select; - sqlite3_stmt * stmt_select_range; - sqlite3_stmt * stmt_select_withActor; - sqlite3_stmt * stmt_knownActor_select; - sqlite3_stmt * stmt_knownActor_insert; - sqlite3_stmt * stmt_knownNode_select; - sqlite3_stmt * stmt_knownNode_insert; + sqlite3 *db = nullptr; + sqlite3_stmt *stmt_insert = nullptr; + sqlite3_stmt *stmt_replace = nullptr; + sqlite3_stmt *stmt_select = nullptr; + sqlite3_stmt *stmt_select_range = nullptr; + sqlite3_stmt *stmt_select_withActor = nullptr; + sqlite3_stmt *stmt_knownActor_select = nullptr; + sqlite3_stmt *stmt_knownActor_insert = nullptr; + sqlite3_stmt *stmt_knownNode_select = nullptr; + sqlite3_stmt *stmt_knownNode_insert = nullptr; std::vector knownActors; std::vector knownNodes;