]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/rollback.cpp
Lazy sunday typo fixing. s/unban_player_of_ip/unban_player_or_ip/g
[dragonfireclient.git] / src / rollback.cpp
index 3fe79105039dd1c55ff83f4310559378ca14296d..fe1d59d0cac201d57960dd7ea3cfc9165dc34d8d 100644 (file)
@@ -1,6 +1,6 @@
 /*
-Minetest-c55
-Copyright (C) 2012 celeron55, Perttu Ahola <celeron55@gmail.com>
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
 
 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
@@ -28,10 +28,36 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "util/serialize.h"
 #include "util/string.h"
 #include "strfnd.h"
+#include "util/numeric.h"
 #include "inventorymanager.h" // deserializing InventoryLocations
 
 #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
 
+#define POINTS_PER_NODE (16.0)
+
+// Get nearness factor for subject's action for this action
+// Return value: 0 = impossible, >0 = factor
+static float getSuspectNearness(bool is_guess, v3s16 suspect_p, int suspect_t,
+               v3s16 action_p, int action_t)
+{
+       // Suspect cannot cause things in the past
+       if(action_t < suspect_t)
+               return 0; // 0 = cannot be
+       // Start from 100
+       int f = 100;
+       // Distance (1 node = -x points)
+       f -= POINTS_PER_NODE * intToFloat(suspect_p, 1).getDistanceFrom(intToFloat(action_p, 1));
+       // Time (1 second = -x points)
+       f -= 1 * (action_t - suspect_t);
+       // If is a guess, halve the points
+       if(is_guess)
+               f *= 0.5;
+       // Limit to 0
+       if(f < 0)
+               f = 0;
+       return f;
+}
+
 class RollbackManager: public IRollbackManager
 {
 public:
@@ -44,10 +70,23 @@ class RollbackManager: public IRollbackManager
                        return;
                RollbackAction action = action_;
                action.unix_time = time(0);
+               // Figure out actor
                action.actor = m_current_actor;
+               action.actor_is_guess = m_current_actor_is_guess;
+               // If actor is not known, find out suspect or cancel
+               if(action.actor.empty()){
+                       v3s16 p;
+                       if(!action.getPosition(&p))
+                               return;
+                       action.actor = getSuspect(p, 83, 1);
+                       if(action.actor.empty())
+                               return;
+                       action.actor_is_guess = true;
+               }
                infostream<<"RollbackManager::reportAction():"
                                <<" time="<<action.unix_time
                                <<" actor=\""<<action.actor<<"\""
+                               <<(action.actor_is_guess?" (guess)":"")
                                <<" action="<<action.toString()
                                <<std::endl;
                addAction(action);
@@ -56,9 +95,49 @@ class RollbackManager: public IRollbackManager
        {
                return m_current_actor;
        }
-       void setActor(const std::string &actor)
+       bool isActorGuess()
+       {
+               return m_current_actor_is_guess;
+       }
+       void setActor(const std::string &actor, bool is_guess)
        {
                m_current_actor = actor;
+               m_current_actor_is_guess = is_guess;
+       }
+       std::string getSuspect(v3s16 p, float nearness_shortcut, float min_nearness)
+       {
+               if(m_current_actor != "")
+                       return m_current_actor;
+               int cur_time = time(0);
+               int first_time = cur_time - (100-min_nearness);
+               RollbackAction likely_suspect;
+               float likely_suspect_nearness = 0;
+               for(std::list<RollbackAction>::const_reverse_iterator
+                               i = m_action_latest_buffer.rbegin();
+                               i != m_action_latest_buffer.rend(); i++)
+               {
+                       if(i->unix_time < first_time)
+                               break;
+                       if(i->actor == "")
+                               continue;
+                       // Find position of suspect or continue
+                       v3s16 suspect_p;
+                       if(!i->getPosition(&suspect_p))
+                               continue;
+                       float f = getSuspectNearness(i->actor_is_guess, suspect_p,
+                                       i->unix_time, p, cur_time);
+                       if(f >= min_nearness && f > likely_suspect_nearness){
+                               likely_suspect_nearness = f;
+                               likely_suspect = *i;
+                               if(likely_suspect_nearness >= nearness_shortcut)
+                                       break;
+                       }
+               }
+               // No likely suspect was found
+               if(likely_suspect_nearness == 0)
+                       return "";
+               // Likely suspect was found
+               return likely_suspect.actor;
        }
        void flush()
        {
@@ -80,8 +159,12 @@ class RollbackManager: public IRollbackManager
                        of<<" ";
                        of<<serializeJsonString(i->actor);
                        of<<" ";
-                       std::string action_s = i->toString();
-                       of<<action_s<<std::endl;
+                       of<<i->toString();
+                       if(i->actor_is_guess){
+                               of<<" ";
+                               of<<"actor_is_guess";
+                       }
+                       of<<std::endl;
                }
                m_action_todisk_buffer.clear();
        }
@@ -90,7 +173,8 @@ class RollbackManager: public IRollbackManager
 
        RollbackManager(const std::string &filepath, IGameDef *gamedef):
                m_filepath(filepath),
-               m_gamedef(gamedef)
+               m_gamedef(gamedef),
+               m_current_actor_is_guess(false)
        {
                infostream<<"RollbackManager::RollbackManager("<<filepath<<")"
                                <<std::endl;
@@ -209,20 +293,7 @@ class RollbackManager: public IRollbackManager
 
                        // 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
+                       if(!i->getPosition(&action_p))
                                continue;
 
                        if(range == 0){
@@ -281,6 +352,7 @@ class RollbackManager: public IRollbackManager
        std::string m_filepath;
        IGameDef *m_gamedef;
        std::string m_current_actor;
+       bool m_current_actor_is_guess;
        std::list<RollbackAction> m_action_todisk_buffer;
        std::list<RollbackAction> m_action_latest_buffer;
 };