From 0190f9b077dcb2b8cb41c622dd91ffc1e04dacac Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Thu, 26 Jul 2012 22:06:45 +0300 Subject: Experimental-ish rollback functionality --- src/rollback.cpp | 293 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 293 insertions(+) create mode 100644 src/rollback.cpp (limited to 'src/rollback.cpp') diff --git a/src/rollback.cpp b/src/rollback.cpp new file mode 100644 index 000000000..3fe791050 --- /dev/null +++ b/src/rollback.cpp @@ -0,0 +1,293 @@ +/* +Minetest-c55 +Copyright (C) 2012 celeron55, Perttu Ahola + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "rollback.h" +#include +#include +#include +#include "log.h" +#include "mapnode.h" +#include "gamedef.h" +#include "nodedef.h" +#include "util/serialize.h" +#include "util/string.h" +#include "strfnd.h" +#include "inventorymanager.h" // deserializing InventoryLocations + +#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" + +class RollbackManager: public IRollbackManager +{ +public: + // IRollbackManager interface + + void reportAction(const RollbackAction &action_) + { + // Ignore if not important + if(!action_.isImportant(m_gamedef)) + return; + RollbackAction action = action_; + action.unix_time = time(0); + action.actor = m_current_actor; + infostream<<"RollbackManager::reportAction():" + <<" time="<::const_iterator + i = m_action_todisk_buffer.begin(); + i != m_action_todisk_buffer.end(); i++) + { + // Do not save stuff that does not have an actor + if(i->actor == "") + continue; + of<unix_time; + of<<" "; + of<actor); + of<<" "; + std::string action_s = i->toString(); + of<= 100) + flush(); + } + + bool readFile(std::list &dst) + { + // Load whole file to memory + std::ifstream f(m_filepath.c_str(), std::ios::in); + if(!f.good()){ + errorstream<<"RollbackManager::readFile(): Could not open " + <<"file for reading: \""< getEntriesSince(int first_time) + { + infostream<<"RollbackManager::getEntriesSince("< action_buffer; + // Use the latest buffer if it is long enough + if(!m_action_latest_buffer.empty() && + m_action_latest_buffer.begin()->unix_time <= first_time){ + action_buffer = m_action_latest_buffer; + } + else + { + // Save all remaining stuff + flush(); + // Load whole file to memory + bool good = readFile(action_buffer); + if(!good){ + errorstream<<"RollbackManager::getEntriesSince(): Failed to" + <<" open file; using data in memory."< action_buffer = getEntriesSince(first_time); + + std::list result; + + for(std::list::const_reverse_iterator + i = action_buffer.rbegin(); + i != action_buffer.rend(); i++) + { + if(i->unix_time < first_time) + break; + + // Find position of action or continue + v3s16 action_p; + + if(i->type == RollbackAction::TYPE_SET_NODE) + { + action_p = i->p; + } + else if(i->type == RollbackAction::TYPE_MODIFY_INVENTORY_STACK) + { + InventoryLocation loc; + loc.deSerialize(i->inventory_location); + if(loc.type != InventoryLocation::NODEMETA) + continue; + action_p = loc.p; + } + else + continue; + + if(range == 0){ + if(action_p != p) + continue; + } else { + if(abs(action_p.X - p.X) > range || + abs(action_p.Y - p.Y) > range || + abs(action_p.Z - p.Z) > range) + continue; + } + + if(act_p) + *act_p = action_p; + if(act_seconds) + *act_seconds = cur_time - i->unix_time; + return i->actor; + } + return ""; + } + + std::list getRevertActions(const std::string &actor_filter, + int seconds) + { + infostream<<"RollbackManager::getRevertActions("< action_buffer = getEntriesSince(first_time); + + std::list result; + + for(std::list::const_reverse_iterator + i = action_buffer.rbegin(); + i != action_buffer.rend(); i++) + { + if(i->unix_time < first_time) + break; + if(i->actor != actor_filter) + continue; + const RollbackAction &action = *i; + /*infostream<<"RollbackManager::revertAction(): Should revert" + <<" time="<