permafeats.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. #ifndef __PERMAFEATS_H
  2. #define __PERMAFEATS_H
  3. #include <list>
  4. #include <mutex>
  5. #include "common.h"
  6. #include "worldkey.h"
  7. namespace permafeats {
  8. typedef std::pair<unsigned int, unsigned int> pt;
  9. using key_t = worldkey::key_t;
  10. struct tristate_t {
  11. int v;
  12. tristate_t() : v(-1) {}
  13. tristate_t(bool _v) : v(_v ? 1 : 0) {}
  14. bool is(bool x) const {
  15. return (v >= 0 && (x ? v == 1 : v == 0));
  16. }
  17. bool set() const {
  18. return (v >= 0);
  19. }
  20. void set(tristate_t x) {
  21. if (x.v >= 0)
  22. v = x.v;
  23. }
  24. };
  25. struct Features {
  26. static const size_t NUMBER = 300;
  27. struct terrain_t {
  28. tag_t feat;
  29. tristate_t walk;
  30. tristate_t water;
  31. tristate_t label;
  32. std::string text;
  33. };
  34. struct q_t {
  35. std::list< std::pair<pt, terrain_t> > l;
  36. size_t size;
  37. q_t() : size(0) {}
  38. };
  39. std::unordered_map<key_t, q_t> data;
  40. std::mutex mutex;
  41. size_t max_level_feats;
  42. Features() : max_level_feats(NUMBER) {}
  43. void _append(const key_t& key, const pt& xy,
  44. tag_t feat, tristate_t walk, tristate_t water, tristate_t label, const std::string& text) {
  45. auto& m = data[key];
  46. if (m.size > 0 && m.l.back().first == xy) {
  47. terrain_t& last = m.l.back().second;
  48. if (!feat.null()) {
  49. last.feat = feat;
  50. }
  51. last.walk.set(walk);
  52. last.water.set(water);
  53. last.label.set(label);
  54. if (label.is(true)) {
  55. last.text = text;
  56. }
  57. } else {
  58. m.l.push_back(std::make_pair(xy, terrain_t{feat, walk, water, label, text}));
  59. ++m.size;
  60. while (m.size > max_level_feats) {
  61. m.l.pop_front();
  62. --m.size;
  63. }
  64. }
  65. }
  66. template <typename PLAYER>
  67. void add(const PLAYER& p, unsigned int x, unsigned int y,
  68. tag_t feat, tristate_t walk, tristate_t water, tristate_t label, const std::string& text = "") {
  69. key_t key(p);
  70. pt xy(x, y);
  71. std::unique_lock<std::mutex> l(mutex);
  72. _append(key, xy, feat, walk, water, label, text);
  73. serialize::Sink sink("permafeats.dat", true);
  74. serialize::write(sink, key);
  75. serialize::write(sink, xy);
  76. serialize::write(sink, feat);
  77. serialize::write(sink, walk.v);
  78. serialize::write(sink, water.v);
  79. serialize::write(sink, label.v);
  80. if (label.is(true)) {
  81. serialize::write(sink, text);
  82. }
  83. }
  84. template <typename PLAYER>
  85. void add(const PLAYER& p, unsigned int x, unsigned int y, tag_t feat) {
  86. add(p, x, y, feat, tristate_t(), tristate_t(), tristate_t());
  87. }
  88. template <typename PLAYER>
  89. void add(const PLAYER& p, unsigned int x, unsigned int y, bool walk, bool water) {
  90. add(p, x, y, tag_t(), walk, water, tristate_t());
  91. }
  92. template <typename PLAYER>
  93. void add(const PLAYER& p, unsigned int x, unsigned int y, const std::string& label) {
  94. add(p, x, y, tag_t(), tristate_t(), tristate_t(), tristate_t(!label.empty()), label);
  95. }
  96. template <typename PLAYER>
  97. void add(const PLAYER& p, tag_t feat) {
  98. add(p, p.px, p.py, feat);
  99. }
  100. template <typename PLAYER>
  101. void add(const PLAYER& p, bool walk, bool water) {
  102. add(p, p.px, p.py, walk, water);
  103. }
  104. template <typename PLAYER>
  105. void add(const PLAYER& p, const std::string& label) {
  106. add(p, p.px, p.py, label);
  107. }
  108. void load(size_t _max = NUMBER) {
  109. max_level_feats = _max;
  110. try {
  111. serialize::Source source("permafeats.dat");
  112. while (1) {
  113. try {
  114. key_t key;
  115. pt xy;
  116. tag_t tag;
  117. serialize::read(source, key);
  118. serialize::read(source, xy);
  119. serialize::read(source, tag);
  120. tristate_t walk;
  121. tristate_t water;
  122. tristate_t label;
  123. serialize::read(source, walk.v);
  124. serialize::read(source, water.v);
  125. serialize::read(source, label.v);
  126. std::string text;
  127. if (label.is(true)) {
  128. serialize::read(source, text);
  129. }
  130. _append(key, xy, tag, walk, water, label, text);
  131. } catch (...) {
  132. break;
  133. }
  134. }
  135. } catch (...) {
  136. }
  137. }
  138. template <typename PLAYER>
  139. std::vector< std::pair<pt,terrain_t> > get(const PLAYER& p) {
  140. std::vector< std::pair<pt,terrain_t> > ret;
  141. std::unique_lock<std::mutex> l(mutex);
  142. const auto& i = data.find(key_t(p));
  143. if (i != data.end()) {
  144. ret.assign(i->second.l.begin(), i->second.l.end());
  145. }
  146. return ret;
  147. }
  148. };
  149. Features& features() {
  150. static Features ret;
  151. return ret;
  152. }
  153. }
  154. #endif