owner_registry.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. #include "owner_registry.h"
  2. #include <QDebug>
  3. #include <array>
  4. #include <cstddef>
  5. #include <qjsonarray.h>
  6. #include <qjsonobject.h>
  7. #include <qjsonvalue.h>
  8. #include <qnamespace.h>
  9. #include <qstringliteral.h>
  10. #include <string>
  11. #include <vector>
  12. namespace {
  13. auto owner_type_to_string(Game::Systems::OwnerType type) -> QString {
  14. using Game::Systems::OwnerType;
  15. switch (type) {
  16. case OwnerType::Player:
  17. return QStringLiteral("player");
  18. case OwnerType::AI:
  19. return QStringLiteral("ai");
  20. case OwnerType::Neutral:
  21. default:
  22. return QStringLiteral("neutral");
  23. }
  24. }
  25. auto owner_typeFromString(const QString &value) -> Game::Systems::OwnerType {
  26. using Game::Systems::OwnerType;
  27. if (value.compare(QStringLiteral("player"), Qt::CaseInsensitive) == 0) {
  28. return OwnerType::Player;
  29. }
  30. if (value.compare(QStringLiteral("ai"), Qt::CaseInsensitive) == 0) {
  31. return OwnerType::AI;
  32. }
  33. return OwnerType::Neutral;
  34. }
  35. auto color_to_json(const std::array<float, 3> &color) -> QJsonArray {
  36. QJsonArray array;
  37. array.append(color[0]);
  38. array.append(color[1]);
  39. array.append(color[2]);
  40. return array;
  41. }
  42. auto color_from_json(const QJsonArray &array) -> std::array<float, 3> {
  43. std::array<float, 3> color{0.8F, 0.9F, 1.0F};
  44. if (array.size() >= 3) {
  45. color[0] = static_cast<float>(array.at(0).toDouble());
  46. color[1] = static_cast<float>(array.at(1).toDouble());
  47. color[2] = static_cast<float>(array.at(2).toDouble());
  48. }
  49. return color;
  50. }
  51. } // namespace
  52. namespace Game::Systems {
  53. auto OwnerRegistry::instance() -> OwnerRegistry & {
  54. static OwnerRegistry inst;
  55. return inst;
  56. }
  57. void OwnerRegistry::clear() {
  58. m_owners.clear();
  59. m_owner_id_to_index.clear();
  60. m_next_owner_id = 1;
  61. m_local_player_id = 1;
  62. }
  63. auto OwnerRegistry::register_owner(OwnerType type,
  64. const std::string &name) -> int {
  65. int const owner_id = m_next_owner_id++;
  66. OwnerInfo info;
  67. info.owner_id = owner_id;
  68. info.type = type;
  69. info.name = name.empty() ? ("Owner" + std::to_string(owner_id)) : name;
  70. switch (owner_id) {
  71. case 1:
  72. info.color = {0.20F, 0.55F, 1.00F};
  73. break;
  74. case 2:
  75. info.color = {1.00F, 0.30F, 0.30F};
  76. break;
  77. case 3:
  78. info.color = {0.20F, 0.80F, 0.40F};
  79. break;
  80. case 4:
  81. info.color = {1.00F, 0.80F, 0.20F};
  82. break;
  83. default:
  84. info.color = {0.8F, 0.9F, 1.0F};
  85. break;
  86. }
  87. size_t const index = m_owners.size();
  88. m_owners.push_back(info);
  89. m_owner_id_to_index[owner_id] = index;
  90. return owner_id;
  91. }
  92. void OwnerRegistry::register_owner_with_id(int owner_id, OwnerType type,
  93. const std::string &name) {
  94. if (m_owner_id_to_index.find(owner_id) != m_owner_id_to_index.end()) {
  95. return;
  96. }
  97. OwnerInfo info;
  98. info.owner_id = owner_id;
  99. info.type = type;
  100. info.name = name.empty() ? ("Owner" + std::to_string(owner_id)) : name;
  101. switch (owner_id) {
  102. case 1:
  103. info.color = {0.20F, 0.55F, 1.00F};
  104. break;
  105. case 2:
  106. info.color = {1.00F, 0.30F, 0.30F};
  107. break;
  108. case 3:
  109. info.color = {0.20F, 0.80F, 0.40F};
  110. break;
  111. case 4:
  112. info.color = {1.00F, 0.80F, 0.20F};
  113. break;
  114. default:
  115. info.color = {0.8F, 0.9F, 1.0F};
  116. break;
  117. }
  118. size_t const index = m_owners.size();
  119. m_owners.push_back(info);
  120. m_owner_id_to_index[owner_id] = index;
  121. if (owner_id >= m_next_owner_id) {
  122. m_next_owner_id = owner_id + 1;
  123. }
  124. }
  125. void OwnerRegistry::set_local_player_id(int player_id) {
  126. m_local_player_id = player_id;
  127. }
  128. auto OwnerRegistry::get_local_player_id() const -> int {
  129. return m_local_player_id;
  130. }
  131. auto OwnerRegistry::is_player(int owner_id) const -> bool {
  132. auto it = m_owner_id_to_index.find(owner_id);
  133. if (it == m_owner_id_to_index.end()) {
  134. return false;
  135. }
  136. return m_owners[it->second].type == OwnerType::Player;
  137. }
  138. auto OwnerRegistry::is_ai(int owner_id) const -> bool {
  139. auto it = m_owner_id_to_index.find(owner_id);
  140. if (it == m_owner_id_to_index.end()) {
  141. return false;
  142. }
  143. return m_owners[it->second].type == OwnerType::AI;
  144. }
  145. auto OwnerRegistry::get_owner_type(int owner_id) const -> OwnerType {
  146. auto it = m_owner_id_to_index.find(owner_id);
  147. if (it == m_owner_id_to_index.end()) {
  148. return OwnerType::Neutral;
  149. }
  150. return m_owners[it->second].type;
  151. }
  152. auto OwnerRegistry::get_owner_name(int owner_id) const -> std::string {
  153. auto it = m_owner_id_to_index.find(owner_id);
  154. if (it == m_owner_id_to_index.end()) {
  155. return "Unknown";
  156. }
  157. return m_owners[it->second].name;
  158. }
  159. auto OwnerRegistry::get_all_owners() const -> const std::vector<OwnerInfo> & {
  160. return m_owners;
  161. }
  162. auto OwnerRegistry::get_player_owner_ids() const -> std::vector<int> {
  163. std::vector<int> result;
  164. for (const auto &owner : m_owners) {
  165. if (owner.type == OwnerType::Player) {
  166. result.push_back(owner.owner_id);
  167. }
  168. }
  169. return result;
  170. }
  171. auto OwnerRegistry::get_ai_owner_ids() const -> std::vector<int> {
  172. std::vector<int> result;
  173. for (const auto &owner : m_owners) {
  174. if (owner.type == OwnerType::AI) {
  175. result.push_back(owner.owner_id);
  176. }
  177. }
  178. return result;
  179. }
  180. void OwnerRegistry::set_owner_team(int owner_id, int team_id) {
  181. auto it = m_owner_id_to_index.find(owner_id);
  182. if (it != m_owner_id_to_index.end()) {
  183. m_owners[it->second].team_id = team_id;
  184. }
  185. }
  186. auto OwnerRegistry::get_owner_team(int owner_id) const -> int {
  187. auto it = m_owner_id_to_index.find(owner_id);
  188. if (it == m_owner_id_to_index.end()) {
  189. return 0;
  190. }
  191. return m_owners[it->second].team_id;
  192. }
  193. auto OwnerRegistry::are_allies(int owner_id1, int owner_id2) const -> bool {
  194. if (owner_id1 == owner_id2) {
  195. return true;
  196. }
  197. int const team1 = get_owner_team(owner_id1);
  198. int const team2 = get_owner_team(owner_id2);
  199. if (team1 == 0 || team2 == 0) {
  200. return false;
  201. }
  202. bool const result = (team1 == team2);
  203. return result;
  204. }
  205. auto OwnerRegistry::are_enemies(int owner_id1, int owner_id2) const -> bool {
  206. if (owner_id1 == owner_id2) {
  207. return false;
  208. }
  209. if (are_allies(owner_id1, owner_id2)) {
  210. return false;
  211. }
  212. return true;
  213. }
  214. auto OwnerRegistry::get_allies_of(int owner_id) const -> std::vector<int> {
  215. std::vector<int> result;
  216. int const my_team = get_owner_team(owner_id);
  217. if (my_team == 0) {
  218. return result;
  219. }
  220. for (const auto &owner : m_owners) {
  221. if (owner.owner_id != owner_id && owner.team_id == my_team) {
  222. result.push_back(owner.owner_id);
  223. }
  224. }
  225. return result;
  226. }
  227. auto OwnerRegistry::get_enemies_of(int owner_id) const -> std::vector<int> {
  228. std::vector<int> result;
  229. for (const auto &owner : m_owners) {
  230. if (are_enemies(owner_id, owner.owner_id)) {
  231. result.push_back(owner.owner_id);
  232. }
  233. }
  234. return result;
  235. }
  236. void OwnerRegistry::set_owner_color(int owner_id, float r, float g, float b) {
  237. auto it = m_owner_id_to_index.find(owner_id);
  238. if (it != m_owner_id_to_index.end()) {
  239. m_owners[it->second].color = {r, g, b};
  240. }
  241. }
  242. auto OwnerRegistry::get_owner_color(int owner_id) const
  243. -> std::array<float, 3> {
  244. auto it = m_owner_id_to_index.find(owner_id);
  245. if (it != m_owner_id_to_index.end()) {
  246. return m_owners[it->second].color;
  247. }
  248. return {0.8F, 0.9F, 1.0F};
  249. }
  250. auto OwnerRegistry::to_json() const -> QJsonObject {
  251. QJsonObject root;
  252. root["nextOwnerId"] = m_next_owner_id;
  253. root["localPlayerId"] = m_local_player_id;
  254. QJsonArray owners_array;
  255. for (const auto &owner : m_owners) {
  256. QJsonObject owner_obj;
  257. owner_obj["owner_id"] = owner.owner_id;
  258. owner_obj["type"] = owner_type_to_string(owner.type);
  259. owner_obj["name"] = QString::fromStdString(owner.name);
  260. owner_obj["team_id"] = owner.team_id;
  261. owner_obj["color"] = color_to_json(owner.color);
  262. owners_array.append(owner_obj);
  263. }
  264. root["owners"] = owners_array;
  265. return root;
  266. }
  267. void OwnerRegistry::from_json(const QJsonObject &json) {
  268. clear();
  269. m_next_owner_id = json["nextOwnerId"].toInt(1);
  270. m_local_player_id = json["localPlayerId"].toInt(1);
  271. const auto owners_array = json["owners"].toArray();
  272. m_owners.reserve(owners_array.size());
  273. for (const auto &value : owners_array) {
  274. const auto owner_obj = value.toObject();
  275. OwnerInfo info;
  276. info.owner_id = owner_obj["owner_id"].toInt();
  277. info.type = owner_typeFromString(owner_obj["type"].toString());
  278. info.name = owner_obj["name"].toString().toStdString();
  279. info.team_id = owner_obj["team_id"].toInt(0);
  280. if (owner_obj.contains("color")) {
  281. info.color = color_from_json(owner_obj["color"].toArray());
  282. }
  283. const size_t index = m_owners.size();
  284. m_owners.push_back(info);
  285. m_owner_id_to_index[info.owner_id] = index;
  286. }
  287. for (const auto &owner : m_owners) {
  288. if (owner.owner_id >= m_next_owner_id) {
  289. m_next_owner_id = owner.owner_id + 1;
  290. }
  291. }
  292. }
  293. } // namespace Game::Systems