| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- #include <memory>
- #include <mutex>
- #include <new>
- #include "../../state/build_data/runtime.h"
- #include "../../state/investment/store_internal.h"
- #include "core/logging/log.h"
- #include "internal.h"
- namespace sunrise::server::bap {
- namespace {
- /** Grants and retires one earned reward in the same database transaction. */
- bool commit_world_reward(const WorldRewardRequest& request) noexcept {
- state::investment::store::Transaction transaction;
- if (!transaction.ready()) {
- return false;
- }
- bool committed = false;
- if (request.kind == WorldRewardKind::item) {
- if (state::item_grant_route(request.itemDefinitionIndex) == state::ItemGrantRoute::quest) {
- state::PendingItemAcquisition acquisition;
- committed = request.quantity == 1
- && state::prepare_item_acquisition_for_item(request.itemDefinitionIndex,
- acquisition)
- && state::commit_item_acquisition(acquisition);
- } else {
- const std::unique_ptr<state::PendingRecordRewardGrant> grant(
- new (std::nothrow) state::PendingRecordRewardGrant);
- const char* reason = "reward_allocation";
- committed = grant && request.quantity > 0
- && state::prepare_item_reward(request.itemDefinitionIndex,
- static_cast<std::uint32_t>(request.quantity),
- *grant,
- &reason);
- if (committed) {
- reason = "inventory_commit";
- committed = state::commit_record_reward(*grant);
- }
- if (!committed) {
- report_reward_refusal("world_settle", request.itemDefinitionIndex, reason);
- }
- }
- } else {
- state::PendingProfileItemAcquisition acquisition;
- committed = state::prepare_profile_item_acquisition_for_item(
- request.itemDefinitionIndex, request.quantity, acquisition)
- && state::commit_profile_item_acquisition(acquisition);
- }
- return committed && complete_world_reward(request.id) && transaction.commit();
- }
- /** Saves the reward under its stable definition hash and earning character. */
- bool enqueue_world_reward(std::uint16_t definitionIndex,
- std::int32_t quantity,
- WorldRewardKind kind) noexcept {
- state::build_data::items::Definition definition;
- if (!state::build_data::find_item_definition_index(definitionIndex, definition)
- || !state::investment::store::enqueue_reward(
- definition.definitionHash, quantity, static_cast<std::uint8_t>(kind))) {
- return false;
- }
- if (!has_active_family4_peer()) {
- settle_world_reward();
- }
- return true;
- }
- } // namespace
- void report_reward_refusal(const char* stage, std::uint16_t index, const char* reason) noexcept {
- core::log::writef(core::log::Channel::server,
- core::log::Level::warn,
- "ev=reward stage=%s index=%u result=refused reason=%s",
- stage,
- static_cast<unsigned>(index),
- reason != nullptr ? reason : "unknown");
- }
- /** Saves one item reward before its pickup presentation is queued. */
- bool arm_world_item_acquisition(std::uint16_t itemDefinitionIndex) noexcept {
- return enqueue_world_reward(itemDefinitionIndex, 1, WorldRewardKind::item);
- }
- /** Saves a profile material reward before its pickup presentation is queued. */
- bool arm_world_profile_item_acquisition(std::uint16_t itemDefinitionIndex,
- std::int32_t quantity) noexcept {
- return quantity > 0
- && enqueue_world_reward(itemDefinitionIndex, quantity, WorldRewardKind::profileItem);
- }
- /** Restores the oldest reward belonging to the selected character. */
- bool current_world_reward(WorldRewardRequest& request) noexcept {
- request = {};
- state::investment::store::PendingReward saved;
- state::build_data::items::Definition definition;
- if (!state::investment::store::next_reward(saved)
- || !state::build_data::find_item_definition_hash(saved.definitionHash, definition)) {
- return false;
- }
- request.id = saved.id;
- request.quantity = saved.quantity;
- request.itemDefinitionIndex = definition.definitionIndex;
- request.kind = static_cast<WorldRewardKind>(saved.kind);
- return true;
- }
- /** Acknowledges exactly the reward whose inventory grant is being committed. */
- bool complete_world_reward(std::uint64_t id) noexcept {
- return state::investment::store::complete_reward(id);
- }
- /** A failed grant stays saved for a later attempt. */
- void settle_world_reward() noexcept {
- WorldRewardRequest request;
- if (current_world_reward(request) && commit_world_reward(request)) {
- arm_account_resync_everywhere();
- }
- }
- /** Shutdown may grant ready rewards; rewards for other characters stay in the database. */
- void drain_world_rewards() noexcept {
- WorldRewardRequest request;
- while (current_world_reward(request)) {
- if (!commit_world_reward(request)) {
- break;
- }
- }
- }
- } // namespace sunrise::server::bap
|