unlocks_runtime.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #include "unlocks_runtime.h"
  2. #include <limits>
  3. #include <mutex>
  4. #include <shared_mutex>
  5. #include "../investment/store_internal.h"
  6. namespace sunrise::state::unlocks {
  7. namespace store = investment::store;
  8. /** Replaces the saved unlock banks in one transaction. */
  9. void publish(const Table& table) noexcept {
  10. (void)store::write_unlocks(table);
  11. }
  12. /** @return A call-local copy of the saved banks. */
  13. Table get() noexcept {
  14. Table table;
  15. if (!store::read_unlocks(table)) {
  16. table = {};
  17. }
  18. return table;
  19. }
  20. /** Reads the requested character's banks and the shared account banks together. */
  21. bool snapshot(Table& output, int characterSlot) noexcept {
  22. return store::read_unlocks(output, characterSlot);
  23. }
  24. /** Clears the saved banks for the active account and selected character. */
  25. void clear() noexcept {
  26. (void)store::write_unlocks(Table{});
  27. }
  28. /** Applies one mutation and reports success only after its database commit. */
  29. bool mutate(void* context, void (*apply)(void*, Table&) noexcept) noexcept {
  30. if (apply == nullptr) {
  31. return false;
  32. }
  33. store::Transaction transaction;
  34. Table table;
  35. if (!transaction.ready() || !store::read_unlocks(table)) {
  36. return false;
  37. }
  38. apply(context, table);
  39. return store::write_unlocks(table) && transaction.commit();
  40. }
  41. /** Reads one saved accountFlags entry. */
  42. bool account_flag_set(std::uint16_t index) noexcept {
  43. std::int32_t value = 0;
  44. const bool loaded =
  45. index < kAccountFlagCapacity && store::read_unlock(store::Bank::accountFlags, index, value);
  46. return loaded && value == kFlagSet;
  47. }
  48. /** Reads one saved characterObjectFlags entry. */
  49. bool character_object_flag_set(std::uint16_t index) noexcept {
  50. std::int32_t value = 0;
  51. const bool loaded = index < kCharacterObjectFlagCapacity
  52. && store::read_unlock(store::Bank::characterObjectFlags, index, value);
  53. return loaded && value == kFlagSet;
  54. }
  55. /** Reads one saved objectiveValues entry. */
  56. std::int32_t objective_value(std::uint16_t index) noexcept {
  57. std::int32_t value = 0;
  58. const bool loaded = index < kObjectiveValueCapacity
  59. && store::read_unlock(store::Bank::objectiveValues, index, value);
  60. return loaded ? value : 0;
  61. }
  62. /** Reads one saved accountProgressions entry. */
  63. std::int32_t account_progression(std::uint16_t definitionIndex) noexcept {
  64. std::int32_t value = 0;
  65. const bool loaded =
  66. definitionIndex < build_data::progressions::kDefinitionCapacity
  67. && store::read_unlock(store::Bank::accountProgressions, definitionIndex, value);
  68. return loaded ? value : 0;
  69. }
  70. /** Saves one bounded accountFlags entry. */
  71. bool set_account_flag(std::uint16_t index, std::uint8_t value) noexcept {
  72. return index < kAccountFlagCapacity
  73. && store::write_unlock(store::Bank::accountFlags, index, value);
  74. }
  75. /** Saves one bounded objectiveValues entry. */
  76. bool set_objective_value(std::uint16_t index, std::int32_t value) noexcept {
  77. return index < kObjectiveValueCapacity
  78. && store::write_unlock(store::Bank::objectiveValues, index, value);
  79. }
  80. /** Saves one bounded characterObjectFlags entry. */
  81. bool set_character_object_flag(std::uint16_t index, std::uint8_t value) noexcept {
  82. return index < kCharacterObjectFlagCapacity
  83. && store::write_unlock(store::Bank::characterObjectFlags, index, value);
  84. }
  85. /** Saves one bounded characterObjectValues entry. */
  86. bool set_character_object_value(std::uint16_t index, std::int32_t value) noexcept {
  87. return index < kCharacterObjectValueCapacity
  88. && store::write_unlock(store::Bank::characterObjectValues, index, value);
  89. }
  90. /** Saves one bounded accountProgressions entry. */
  91. bool set_account_progression(std::uint16_t definitionIndex, std::int32_t value) noexcept {
  92. return definitionIndex < build_data::progressions::kDefinitionCapacity
  93. && store::write_unlock(store::Bank::accountProgressions, definitionIndex, value);
  94. }
  95. /** Adds to an objective under the same transaction that guards overflow. */
  96. bool add_objective_value(std::uint16_t index, std::int32_t amount) noexcept {
  97. store::Transaction transaction;
  98. std::int32_t value = 0;
  99. if (!transaction.ready() || index >= kObjectiveValueCapacity
  100. || !store::read_unlock(store::Bank::objectiveValues, index, value)
  101. || (amount > 0 && value > (std::numeric_limits<std::int32_t>::max)() - amount)
  102. || (amount < 0 && value < (std::numeric_limits<std::int32_t>::min)() - amount)) {
  103. return false;
  104. }
  105. return store::write_unlock(store::Bank::objectiveValues, index, value + amount)
  106. && transaction.commit();
  107. }
  108. } // namespace sunrise::state::unlocks