1 /* 2 Minetest 3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com> 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU Lesser General Public License as published by 7 the Free Software Foundation; either version 2.1 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public License along 16 with this program; if not, write to the Free Software Foundation, Inc., 17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 */ 19 20 #pragma once 21 22 #include "irr_v3d.h" 23 #include <iostream> 24 #include <map> 25 #include <vector> 26 27 /* 28 NodeTimer provides per-node timed callback functionality. 29 Can be used for: 30 - Furnaces, to keep the fire burnin' 31 - "activated" nodes that snap back to their original state 32 after a fixed amount of time (mesecons buttons, for example) 33 */ 34 35 class NodeTimer 36 { 37 public: 38 NodeTimer() = default; NodeTimer(const v3s16 & position_)39 NodeTimer(const v3s16 &position_): 40 position(position_) {} NodeTimer(f32 timeout_,f32 elapsed_,v3s16 position_)41 NodeTimer(f32 timeout_, f32 elapsed_, v3s16 position_): 42 timeout(timeout_), elapsed(elapsed_), position(position_) {} 43 ~NodeTimer() = default; 44 45 void serialize(std::ostream &os) const; 46 void deSerialize(std::istream &is); 47 48 f32 timeout = 0.0f; 49 f32 elapsed = 0.0f; 50 v3s16 position; 51 }; 52 53 /* 54 List of timers of all the nodes of a block 55 */ 56 57 class NodeTimerList 58 { 59 public: 60 NodeTimerList() = default; 61 ~NodeTimerList() = default; 62 63 void serialize(std::ostream &os, u8 map_format_version) const; 64 void deSerialize(std::istream &is, u8 map_format_version); 65 66 // Get timer get(const v3s16 & p)67 NodeTimer get(const v3s16 &p) { 68 std::map<v3s16, std::multimap<double, NodeTimer>::iterator>::iterator n = 69 m_iterators.find(p); 70 if (n == m_iterators.end()) 71 return NodeTimer(); 72 NodeTimer t = n->second->second; 73 t.elapsed = t.timeout - (n->second->first - m_time); 74 return t; 75 } 76 // Deletes timer remove(v3s16 p)77 void remove(v3s16 p) { 78 std::map<v3s16, std::multimap<double, NodeTimer>::iterator>::iterator n = 79 m_iterators.find(p); 80 if(n != m_iterators.end()) { 81 double removed_time = n->second->first; 82 m_timers.erase(n->second); 83 m_iterators.erase(n); 84 // Yes, this is float equality, but it is not a problem 85 // since we only test equality of floats as an ordered type 86 // and thus we never lose precision 87 if (removed_time == m_next_trigger_time) { 88 if (m_timers.empty()) 89 m_next_trigger_time = -1.; 90 else 91 m_next_trigger_time = m_timers.begin()->first; 92 } 93 } 94 } 95 // Undefined behaviour if there already is a timer insert(NodeTimer timer)96 void insert(NodeTimer timer) { 97 v3s16 p = timer.position; 98 double trigger_time = m_time + (double)(timer.timeout - timer.elapsed); 99 std::multimap<double, NodeTimer>::iterator it = 100 m_timers.insert(std::pair<double, NodeTimer>( 101 trigger_time, timer 102 )); 103 m_iterators.insert( 104 std::pair<v3s16, std::multimap<double, NodeTimer>::iterator>(p, it)); 105 if (m_next_trigger_time == -1. || trigger_time < m_next_trigger_time) 106 m_next_trigger_time = trigger_time; 107 } 108 // Deletes old timer and sets a new one set(const NodeTimer & timer)109 inline void set(const NodeTimer &timer) { 110 remove(timer.position); 111 insert(timer); 112 } 113 // Deletes all timers clear()114 void clear() { 115 m_timers.clear(); 116 m_iterators.clear(); 117 m_next_trigger_time = -1.; 118 } 119 120 // Move forward in time, returns elapsed timers 121 std::vector<NodeTimer> step(float dtime); 122 123 private: 124 std::multimap<double, NodeTimer> m_timers; 125 std::map<v3s16, std::multimap<double, NodeTimer>::iterator> m_iterators; 126 double m_next_trigger_time = -1.0; 127 double m_time = 0.0; 128 }; 129