nodetimer.h 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. // Luanti
  2. // SPDX-License-Identifier: LGPL-2.1-or-later
  3. // Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. #pragma once
  5. #include "irr_v3d.h"
  6. #include <iostream>
  7. #include <map>
  8. #include <vector>
  9. /*
  10. NodeTimer provides per-node timed callback functionality.
  11. Can be used for:
  12. - Furnaces, to keep the fire burnin'
  13. - "activated" nodes that snap back to their original state
  14. after a fixed amount of time (mesecons buttons, for example)
  15. */
  16. class NodeTimer
  17. {
  18. public:
  19. NodeTimer() = default;
  20. NodeTimer(const v3s16 &position_):
  21. position(position_) {}
  22. NodeTimer(f32 timeout_, f32 elapsed_, v3s16 position_):
  23. timeout(timeout_), elapsed(elapsed_), position(position_) {}
  24. ~NodeTimer() = default;
  25. void serialize(std::ostream &os) const;
  26. void deSerialize(std::istream &is);
  27. f32 timeout = 0.0f;
  28. f32 elapsed = 0.0f;
  29. v3s16 position;
  30. };
  31. /*
  32. List of timers of all the nodes of a block
  33. */
  34. class NodeTimerList
  35. {
  36. public:
  37. NodeTimerList() = default;
  38. ~NodeTimerList() = default;
  39. void serialize(std::ostream &os, u8 map_format_version) const;
  40. void deSerialize(std::istream &is, u8 map_format_version);
  41. // Get timer
  42. NodeTimer get(const v3s16 &p) {
  43. std::map<v3s16, std::multimap<double, NodeTimer>::iterator>::iterator n =
  44. m_iterators.find(p);
  45. if (n == m_iterators.end())
  46. return NodeTimer();
  47. NodeTimer t = n->second->second;
  48. t.elapsed = t.timeout - (n->second->first - m_time);
  49. return t;
  50. }
  51. // Deletes timer
  52. void remove(v3s16 p) {
  53. std::map<v3s16, std::multimap<double, NodeTimer>::iterator>::iterator n =
  54. m_iterators.find(p);
  55. if(n != m_iterators.end()) {
  56. double removed_time = n->second->first;
  57. m_timers.erase(n->second);
  58. m_iterators.erase(n);
  59. // Yes, this is float equality, but it is not a problem
  60. // since we only test equality of floats as an ordered type
  61. // and thus we never lose precision
  62. if (removed_time == m_next_trigger_time) {
  63. if (m_timers.empty())
  64. m_next_trigger_time = -1.;
  65. else
  66. m_next_trigger_time = m_timers.begin()->first;
  67. }
  68. }
  69. }
  70. // Undefined behavior if there already is a timer
  71. void insert(const NodeTimer &timer) {
  72. v3s16 p = timer.position;
  73. double trigger_time = m_time + (double)(timer.timeout - timer.elapsed);
  74. std::multimap<double, NodeTimer>::iterator it = m_timers.emplace(trigger_time, timer);
  75. m_iterators.emplace(p, it);
  76. if (m_next_trigger_time == -1. || trigger_time < m_next_trigger_time)
  77. m_next_trigger_time = trigger_time;
  78. }
  79. // Deletes old timer and sets a new one
  80. inline void set(const NodeTimer &timer) {
  81. remove(timer.position);
  82. insert(timer);
  83. }
  84. // Deletes all timers
  85. void clear() {
  86. m_timers.clear();
  87. m_iterators.clear();
  88. m_next_trigger_time = -1.;
  89. }
  90. // Move forward in time, returns elapsed timers
  91. std::vector<NodeTimer> step(float dtime);
  92. private:
  93. std::multimap<double, NodeTimer> m_timers;
  94. std::map<v3s16, std::multimap<double, NodeTimer>::iterator> m_iterators;
  95. double m_next_trigger_time = -1.0;
  96. double m_time = 0.0;
  97. };