node_catalog.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #include "node_catalog.h"
  2. #include "../../../core/logging/log.h"
  3. #include <cstdio>
  4. #include <array>
  5. #include "../../unlocks/definition.h"
  6. #include "../table.h"
  7. namespace sunrise::state::build_data::nodes {
  8. namespace {
  9. Lock g_lock;
  10. Table<Definition, kDefinitionCapacity> g_definitions;
  11. } // namespace
  12. /** Clears every generated node definition under the catalog lock. */
  13. void clear() noexcept {
  14. const Lock::Exclusive guard(g_lock);
  15. g_definitions.clear();
  16. }
  17. /** Checks that the definitions are dense and in native index order. */
  18. bool valid(std::span<const Definition> definitions) noexcept {
  19. if (definitions.empty() || definitions.size() > kDefinitionCapacity) {
  20. return false;
  21. }
  22. for (std::size_t row = 0; row < definitions.size(); ++row) {
  23. if (definitions[row].definitionIndex != row
  24. || definitions[row].childCount > kChildCapacity) {
  25. return false;
  26. }
  27. }
  28. return true;
  29. }
  30. /** Replaces the generated node definitions in one step. */
  31. bool replace(std::span<const Definition> definitions) noexcept {
  32. if (!valid(definitions)) {
  33. return false;
  34. }
  35. const Lock::Exclusive guard(g_lock);
  36. return g_definitions.replace(definitions);
  37. }
  38. /** Runs one callable over every node that drives a value slot. */
  39. void for_each_driving(void* context,
  40. void (*visit)(void* context, const Definition& definition)) noexcept {
  41. if (visit == nullptr) {
  42. return;
  43. }
  44. const Lock::Shared guard(g_lock);
  45. for (const Definition& definition : g_definitions.rows()) {
  46. if (definition.childCount != 0 && definition.valueIndex != kUnavailableValueIndex) {
  47. visit(context, definition);
  48. }
  49. }
  50. }
  51. /** Copies every row in native node order. */
  52. bool snapshot(std::span<Definition> output, std::size_t& count) noexcept {
  53. const Lock::Shared guard(g_lock);
  54. return g_definitions.snapshot(output, count);
  55. }
  56. /** @return Number of generated node definitions, read under the lock. */
  57. std::size_t count() noexcept {
  58. const Lock::Shared guard(g_lock);
  59. return g_definitions.count();
  60. }
  61. /** Sets the visibility gate of every lore book category. */
  62. std::size_t apply_visibility(std::span<std::uint8_t> accountFlags) noexcept {
  63. const Lock::Shared guard(g_lock);
  64. std::size_t set = 0;
  65. for (const Definition& node : g_definitions.rows()) {
  66. if (node.definitionIndex < kLoreNodeFirst || node.definitionIndex > kLoreNodeLast
  67. || node.visibilityFlagIndex == kUnavailableFlagIndex
  68. || static_cast<std::size_t>(node.visibilityFlagIndex) >= accountFlags.size()) {
  69. continue;
  70. }
  71. accountFlags[node.visibilityFlagIndex] = unlocks::kFlagSet;
  72. ++set;
  73. }
  74. return set;
  75. }
  76. /** Sets the character scoped visibility gates of the lore book categories. */
  77. std::size_t apply_character_visibility(std::span<std::byte> characterFlags) noexcept {
  78. const Lock::Shared guard(g_lock);
  79. std::size_t set = 0;
  80. for (const Definition& node : g_definitions.rows()) {
  81. if (node.definitionIndex < kLoreNodeFirst || node.definitionIndex > kLoreNodeLast
  82. || node.visibilityCharacterFlagIndex == kUnavailableFlagIndex
  83. || static_cast<std::size_t>(node.visibilityCharacterFlagIndex)
  84. >= characterFlags.size()) {
  85. continue;
  86. }
  87. characterFlags[node.visibilityCharacterFlagIndex] =
  88. static_cast<std::byte>(unlocks::kFlagSet);
  89. ++set;
  90. }
  91. // TEMPORARY: say whether the character scoped gates are actually being written. This is the one
  92. // fix in the batch never confirmed to land, and a silent no-op looks identical to a wrong index.
  93. std::array<char, 160> line{};
  94. const int written = std::snprintf(line.data(), line.size(),
  95. "ev=charvis set=%zu bank=%zu", set, characterFlags.size());
  96. if (written > 0) {
  97. core::log::write(core::log::Channel::state, core::log::Level::info,
  98. {line.data(), static_cast<std::size_t>(written)});
  99. }
  100. return set;
  101. }
  102. } // namespace sunrise::state::build_data::nodes