]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/nodetimer.h
Patch built-in Lua to fix miscompile on Android (#12347)
[dragonfireclient.git] / src / nodetimer.h
index f8d3e1c5799ee50d0d4c3cfaac05ad0d71478cfc..40e54ccc569221e5e679965423d63ad5a38561ab 100644 (file)
@@ -1,6 +1,6 @@
 /*
-Minetest-c55
-Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
+Minetest
+Copyright (C) 2010-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
@@ -17,12 +17,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
-#ifndef NODETIMER_HEADER
-#define NODETIMER_HEADER
+#pragma once
 
-#include "irrlichttypes_bloated.h"
+#include "irr_v3d.h"
 #include <iostream>
 #include <map>
+#include <vector>
 
 /*
        NodeTimer provides per-node timed callback functionality.
@@ -35,16 +35,19 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 class NodeTimer
 {
 public:
-       NodeTimer(): timeout(0.), elapsed(0.) {}
-       NodeTimer(f32 timeout_, f32 elapsed_):
-               timeout(timeout_), elapsed(elapsed_) {}
-       ~NodeTimer() {}
-       
+       NodeTimer() = default;
+       NodeTimer(const v3s16 &position_):
+               position(position_) {}
+       NodeTimer(f32 timeout_, f32 elapsed_, v3s16 position_):
+               timeout(timeout_), elapsed(elapsed_), position(position_) {}
+       ~NodeTimer() = default;
+
        void serialize(std::ostream &os) const;
        void deSerialize(std::istream &is);
-       
-       f32 timeout;
-       f32 elapsed;
+
+       f32 timeout = 0.0f;
+       f32 elapsed = 0.0f;
+       v3s16 position;
 };
 
 /*
@@ -54,38 +57,72 @@ class NodeTimer
 class NodeTimerList
 {
 public:
-       NodeTimerList() {}
-       ~NodeTimerList() {}
-       
-       void serialize(std::ostream &os) const;
-       void deSerialize(std::istream &is);
-       
+       NodeTimerList() = default;
+       ~NodeTimerList() = default;
+
+       void serialize(std::ostream &os, u8 map_format_version) const;
+       void deSerialize(std::istream &is, u8 map_format_version);
+
        // Get timer
-       NodeTimer get(v3s16 p){
-               std::map<v3s16, NodeTimer>::iterator n = m_data.find(p);
-               if(n == m_data.end())
+       NodeTimer get(const v3s16 &p) {
+               std::map<v3s16, std::multimap<double, NodeTimer>::iterator>::iterator n =
+                       m_iterators.find(p);
+               if (n == m_iterators.end())
                        return NodeTimer();
-               return n->second;
+               NodeTimer t = n->second->second;
+               t.elapsed = t.timeout - (n->second->first - m_time);
+               return t;
        }
        // Deletes timer
-       void remove(v3s16 p){
-               m_data.erase(p);
+       void remove(v3s16 p) {
+               std::map<v3s16, std::multimap<double, NodeTimer>::iterator>::iterator n =
+                       m_iterators.find(p);
+               if(n != m_iterators.end()) {
+                       double removed_time = n->second->first;
+                       m_timers.erase(n->second);
+                       m_iterators.erase(n);
+                       // Yes, this is float equality, but it is not a problem
+                       // since we only test equality of floats as an ordered type
+                       // and thus we never lose precision
+                       if (removed_time == m_next_trigger_time) {
+                               if (m_timers.empty())
+                                       m_next_trigger_time = -1.;
+                               else
+                                       m_next_trigger_time = m_timers.begin()->first;
+                       }
+               }
+       }
+       // Undefined behaviour if there already is a timer
+       void insert(NodeTimer timer) {
+               v3s16 p = timer.position;
+               double trigger_time = m_time + (double)(timer.timeout - timer.elapsed);
+               std::multimap<double, NodeTimer>::iterator it =
+                       m_timers.insert(std::pair<double, NodeTimer>(
+                               trigger_time, timer
+                       ));
+               m_iterators.insert(
+                       std::pair<v3s16, std::multimap<double, NodeTimer>::iterator>(p, it));
+               if (m_next_trigger_time == -1. || trigger_time < m_next_trigger_time)
+                       m_next_trigger_time = trigger_time;
        }
        // Deletes old timer and sets a new one
-       void set(v3s16 p, NodeTimer t){
-               m_data[p] = t;
+       inline void set(const NodeTimer &timer) {
+               remove(timer.position);
+               insert(timer);
        }
        // Deletes all timers
-       void clear(){
-               m_data.clear();
+       void clear() {
+               m_timers.clear();
+               m_iterators.clear();
+               m_next_trigger_time = -1.;
        }
 
-       // A step in time. Returns map of elapsed timers.
-       std::map<v3s16, NodeTimer> step(float dtime);
+       // Move forward in time, returns elapsed timers
+       std::vector<NodeTimer> step(float dtime);
 
 private:
-       std::map<v3s16, NodeTimer> m_data;
+       std::multimap<double, NodeTimer> m_timers;
+       std::map<v3s16, std::multimap<double, NodeTimer>::iterator> m_iterators;
+       double m_next_trigger_time = -1.0;
+       double m_time = 0.0;
 };
-
-#endif
-