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/server.cpp | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 107 insertions(+), 1 deletion(-) (limited to 'src/server.cpp') diff --git a/src/server.cpp b/src/server.cpp index 21c936e69..a868a0425 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -54,6 +54,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/string.h" #include "util/pointedthing.h" #include "util/mathconstants.h" +#include "rollback.h" #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" @@ -934,6 +935,8 @@ Server::Server( m_env(NULL), m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this), m_banmanager(path_world+DIR_DELIM+"ipban.txt"), + m_rollback(NULL), + m_rollback_sink_enabled(true), m_lua(NULL), m_itemdef(createItemDefManager()), m_nodedef(createNodeDefManager()), @@ -973,6 +976,10 @@ Server::Server( infostream<<"- config: "<getName()); + /* Note: Always set inventory not sent, to repair cases where the client made a bad prediction. @@ -2949,6 +2961,12 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) return; } + /* + If something goes wrong, this player is to blame + */ + RollbackScopeActor rollback_scope(m_rollback, + std::string("player:")+player->getName()); + /* 0: start digging or punch object */ @@ -3204,8 +3222,23 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) fields[fieldname] = fieldvalue; } + // If something goes wrong, this player is to blame + RollbackScopeActor rollback_scope(m_rollback, + std::string("player:")+player->getName()); + + // Check the target node for rollback data; leave others unnoticed + RollbackNode rn_old(&m_env->getMap(), p, this); + scriptapi_node_on_receive_fields(m_lua, p, formname, fields, playersao); + + // Report rollback data + RollbackNode rn_new(&m_env->getMap(), p, this); + if(rollback() && rn_new != rn_old){ + RollbackAction action; + action.setSetNode(p, rn_old, rn_new); + rollback()->reportAction(action); + } } else if(command == TOSERVER_INVENTORY_FIELDS) { @@ -4522,6 +4555,73 @@ Inventory* Server::createDetachedInventory(const std::string &name) return inv; } +class BoolScopeSet +{ +public: + BoolScopeSet(bool *dst, bool val): + m_dst(dst) + { + m_orig_state = *m_dst; + *m_dst = val; + } + ~BoolScopeSet() + { + *m_dst = m_orig_state; + } +private: + bool *m_dst; + bool m_orig_state; +}; + +// actions: time-reversed list +// Return value: success/failure +bool Server::rollbackRevertActions(const std::list &actions, + std::list *log) +{ + infostream<<"Server::rollbackRevertActions(len="<getMap()); + // Disable rollback report sink while reverting + BoolScopeSet rollback_scope_disable(&m_rollback_sink_enabled, false); + + // Fail if no actions to handle + if(actions.empty()){ + log->push_back("Nothing to do."); + return false; + } + + int num_tried = 0; + int num_failed = 0; + + for(std::list::const_iterator + i = actions.begin(); + i != actions.end(); i++) + { + const RollbackAction &action = *i; + num_tried++; + bool success = action.applyRevert(map, this, this); + if(!success){ + num_failed++; + std::ostringstream os; + os<<"Revert of step ("<push_back(os.str()); + }else{ + std::ostringstream os; + os<<"Succesfully reverted step ("<push_back(os.str()); + } + } + + infostream<<"Map::rollbackRevertActions(): "<