Skip to content

Commit

Permalink
fix: store transfer history
Browse files Browse the repository at this point in the history
  • Loading branch information
murilo09 committed Aug 21, 2024
1 parent 481c634 commit 3938189
Show file tree
Hide file tree
Showing 10 changed files with 135 additions and 30 deletions.
18 changes: 18 additions & 0 deletions src/account/account.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,24 @@ void Account::registerCoinTransaction(const uint8_t &transactionType, const uint
}
}

void Account::registerStoreTransaction(const uint8_t &type, const uint32_t &amount, const uint8_t &coinType, const std::string &description, const time_t &time) {
if (!m_accLoaded) {
return;
}

if (description.empty()) {
return;
}

if (!g_accountRepository().registerStoreTransaction(m_account.id, type, amount, coinType, description, time)) {

Check warning on line 174 in src/account/account.cpp

View workflow job for this annotation

GitHub Actions / Qodana for C/C++

narrowing-conversions

narrowing conversion from 'uint32_t' (aka 'unsigned int') to signed type 'int32_t' (aka 'int') is implementation-defined
g_logger().error(
"Failed to register transaction: 'account:[{}], transaction "
"type:[{}], coins:[{}], coin type:[{}], description:[{}], time:[{}]",
m_account.id, type, amount, type, description, time
);
}
}

[[nodiscard]] uint32_t Account::getID() const {
return m_account.id;
};
Expand Down
11 changes: 11 additions & 0 deletions src/account/account.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,17 @@ class Account {
*/
void registerCoinTransaction(const uint8_t &transactionType, const uint8_t &type, const uint32_t &amount, const std::string &detail);

/**
* @brief Registers a store transaction.
*
* @param type Type of history entry
* @param coinType Type of the coin
* @param amount Amount of coins to be registered
* @param description Detail of the transaction
* @param time Time of the transaction
*/
void registerStoreTransaction(const uint8_t &type, const uint32_t &amount, const uint8_t &coinType, const std::string &description, const time_t &time);

/***************************************************************************
* Account Load/Save
**************************************************************************/
Expand Down
9 changes: 9 additions & 0 deletions src/account/account_repository.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ class AccountRepository {
const uint8_t &coinType,
const std::string &description
) = 0;

virtual bool registerStoreTransaction(
const uint32_t &id,
uint8_t type,
int32_t amount,
const uint8_t &coinType,
const std::string &description,
const time_t &time
) = 0;
};

constexpr auto g_accountRepository = AccountRepository::getInstance;
36 changes: 36 additions & 0 deletions src/account/account_repository_db.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,42 @@ bool AccountRepositoryDB::registerCoinsTransaction(
return successful;
};

bool AccountRepositoryDB::registerStoreTransaction(
const uint32_t &id,
uint8_t type,
int32_t amount,
const uint8_t &coinType,
const std::string &description,
const time_t &time
) {

bool successful = g_database().executeQuery(
fmt::format(
"INSERT INTO `store_history` (`account_id`, `description`, `coin_amount`, `coin_type`, `type`, `time`) VALUES ({}, {}, {}, {}, {}, {})",
id,
g_database().escapeString(description),
amount,
coinType,
type,
time
)
);

if (!successful) {
g_logger().error(
"Error registering coin transaction! account_id:[{}], type:[{}], coin_type:[{}], coins:[{}], description:[{}], time:[{}]",
id,
type,
coinType,
amount,
g_database().escapeString(description),
time
);
}

return successful;
};

bool AccountRepositoryDB::loadAccountPlayers(AccountInfo &acc) {
auto result = g_database().storeQuery(
fmt::format("SELECT `name`, `deletion` FROM `players` WHERE `account_id` = {} ORDER BY `name` ASC", acc.id)
Expand Down
9 changes: 9 additions & 0 deletions src/account/account_repository_db.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@ class AccountRepositoryDB final : public AccountRepository {
const std::string &description
) override;

bool registerStoreTransaction(
const uint32_t &id,
uint8_t type,
int32_t amount,
const uint8_t &coinType,
const std::string &description,
const time_t &time
) override;

private:
const std::map<uint8_t, std::string> coinTypeToColumn;
bool load(const std::string &query, AccountInfo &acc);
Expand Down
6 changes: 3 additions & 3 deletions src/creatures/players/player.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,9 @@ struct ForgeHistory {
struct StoreHistory {
time_t createdAt;

uint16_t coinAmount = 0;
uint16_t coinType = 0;
uint16_t historyType = 0;
int32_t coinAmount = 0;
uint8_t coinType = 0;
uint8_t historyType = 0;

std::string description;
};
Expand Down
62 changes: 42 additions & 20 deletions src/game/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10293,12 +10293,9 @@ void Game::playerCoinTransfer(uint32_t playerId, std::string receptorName, uint3
return;
}

std::shared_ptr<Player> playerReceptor = getPlayerByName(receptorName);
std::shared_ptr<Player> playerReceptor = getPlayerByName(receptorName, true);
if (!playerReceptor) {
playerReceptor = std::make_shared<Player>(nullptr);
if (!IOLoginData::loadPlayerByName(playerReceptor, receptorName)) {
return;
}
return;
}

if (playerDonator == playerReceptor || playerDonator->getAccount() == playerReceptor->getAccount()) {
Expand All @@ -10312,13 +10309,39 @@ void Game::playerCoinTransfer(uint32_t playerId, std::string receptorName, uint3
}

std::string historyDesc = fmt::format("{} gifted to {}", playerDonator->getName(), playerReceptor->getName());
playerDonator->getAccount()->removeCoins(enumToValue(CoinType::Transferable), static_cast<uint32_t>(coinAmount), historyDesc);
playerReceptor->getAccount()->addCoins(enumToValue(CoinType::Transferable), static_cast<uint32_t>(coinAmount), historyDesc);
playerDonator->getAccount()->removeCoins(enumToValue(CoinType::Transferable), coinAmount, historyDesc);
playerReceptor->getAccount()->addCoins(enumToValue(CoinType::Transferable), coinAmount, historyDesc);

StoreHistory tempHistory;
tempHistory.description = historyDesc;
tempHistory.coinType = enumToValue(CoinType::Transferable);

Check warning on line 10317 in src/game/game.cpp

View workflow job for this annotation

GitHub Actions / Qodana for C/C++

misra-cpp2008-5-0-12

MISRA 5-0-12: signed char and unsigned char type shall only be used for the storage and use of numeric values
tempHistory.historyType = enumToValue(HistoryTypes_t::NONE);

Check warning on line 10318 in src/game/game.cpp

View workflow job for this annotation

GitHub Actions / Qodana for C/C++

misra-cpp2008-5-0-12

MISRA 5-0-12: signed char and unsigned char type shall only be used for the storage and use of numeric values
tempHistory.coinAmount = static_cast<int32_t>(coinAmount * -1);
tempHistory.createdAt = getTimeNow();

playerDonator->setStoreHistory(tempHistory);

if (playerReceptor->isOffline()) {
IOLoginData::savePlayer(playerReceptor);
std::shared_ptr<Player> newPlayerReceptor;
const auto playersAccountVector = getPlayersByAccount(playerReceptor->getAccount());
for (const auto player : playersAccountVector) {
if (player->isOnline()) {
newPlayerReceptor = player;
g_logger().warn("{}", newPlayerReceptor->name);
}
}

if (newPlayerReceptor) {
tempHistory.coinAmount = coinAmount;

Check warning on line 10335 in src/game/game.cpp

View workflow job for this annotation

GitHub Actions / Qodana for C/C++

narrowing-conversions

narrowing conversion from 'uint32_t' (aka 'unsigned int') to signed type 'int32_t' (aka 'int') is implementation-defined
newPlayerReceptor->sendCoinBalance();
newPlayerReceptor->setStoreHistory(tempHistory);
} else {
playerReceptor->getAccount()->registerStoreTransaction(tempHistory.historyType, coinAmount, tempHistory.coinType, historyDesc, tempHistory.createdAt);
}
} else {
tempHistory.coinAmount = coinAmount;

Check warning on line 10342 in src/game/game.cpp

View workflow job for this annotation

GitHub Actions / Qodana for C/C++

narrowing-conversions

narrowing conversion from 'uint32_t' (aka 'unsigned int') to signed type 'int32_t' (aka 'int') is implementation-defined
playerReceptor->sendCoinBalance();
playerReceptor->setStoreHistory(tempHistory);
}

playerDonator->openStore();
Expand Down Expand Up @@ -10623,7 +10646,7 @@ void Game::playerBuyStoreOffer(uint32_t playerId, const Offer* offer, std::strin
StoreHistory tempHistory;

tempHistory.description = offer->getOfferName();
tempHistory.coinAmount = offerPrice;
tempHistory.coinAmount = static_cast<int32_t>(offerPrice * -1);
tempHistory.createdAt = getTimeNow();

player->sendStoreSuccess(returnmessage);
Expand Down Expand Up @@ -10756,27 +10779,26 @@ bool Game::processNameChangeOffer(std::shared_ptr<Player> player, std::string &n
trimString(newName);

auto isValidName = validateName(newName);

if (isValidName != VALID) {
return false;
}

std::ostringstream query;
Database &db = Database::getInstance();
query << "SELECT `id` FROM `player` WHERE `name` = " << db.escapeString(newName);
if (db.storeQuery(query.str())) {
return false;
}
capitalizeWords(newName);

if (g_monsters().getMonsterType(newName)) {
if (g_monsters().getMonsterType(newName, true)) {

Check warning on line 10788 in src/game/game.cpp

View workflow job for this annotation

GitHub Actions / Qodana for C/C++

branch-clone

repeated branch body in conditional chain
return false;
} else if (getNpcByName(newName)) {
return false;
}

capitalizeWords(newName);
query << "UPDATE `players` SET `name` = " << db.escapeString(newName) << "WHERE `id` = " << player->getGUID();
if (!db.executeQuery(query.str())) {
Database &db = Database::getInstance();
DBResult_ptr result = db.storeQuery(fmt::format("SELECT `id` FROM `players` WHERE `name` = {}", db.escapeString(newName)));
if (result) {
return false;
}

std::string query = fmt::format("UPDATE `players` SET `name` = {} WHERE `id` = {}", db.escapeString(newName), player->getGUID());
if (!db.executeQuery(query)) {
return false;

Check warning on line 10802 in src/game/game.cpp

View workflow job for this annotation

GitHub Actions / Qodana for C/C++

simplify-boolean-expr

redundant boolean literal in conditional return statement
}

Expand Down
6 changes: 3 additions & 3 deletions src/io/functions/iologindata_load_player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -840,9 +840,9 @@ void IOLoginDataLoad::loadPlayerStoreHistory(std::shared_ptr<Player> player, DBR
do {
StoreHistory history;
history.description = result->getString("description");
history.coinAmount = result->getNumber<int16_t>("coin_amount");
history.coinType = result->getNumber<uint16_t>("coin_type");
history.historyType = result->getNumber<uint16_t>("type");
history.coinAmount = result->getNumber<int32_t>("coin_amount");
history.coinType = result->getNumber<uint8_t>("coin_type");
history.historyType = result->getNumber<uint8_t>("type");
history.createdAt = result->getNumber<time_t>("time");
player->setStoreHistory(history);
} while (result->next());
Expand Down
4 changes: 2 additions & 2 deletions src/io/functions/iologindata_save_player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -740,8 +740,8 @@ bool IOLoginDataSave::savePlayerStoreHistory(std::shared_ptr<Player> player) {
query << player->getAccountId() << ','
<< descriptionString << ','
<< historyEntry.coinAmount << ','
<< historyEntry.coinType << ','
<< historyEntry.historyType << ','
<< static_cast<uint16_t>(historyEntry.coinType) << ','
<< static_cast<uint16_t>(historyEntry.historyType) << ','
<< historyEntry.createdAt;

if (!insertQuery.addRow(query)) {
Expand Down
4 changes: 2 additions & 2 deletions src/server/network/protocol/protocolgame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9239,10 +9239,10 @@ void ProtocolGame::sendStoreHistory(uint32_t page) {

if (historyPageToSend > 0) {
for (const auto &history : historyPerPage) {
msg.add<uint32_t>(0x00);
msg.add<uint32_t>(0x00); // Id?

msg.add<uint32_t>(static_cast<uint32_t>(history.createdAt));
msg.addByte(0x00);
msg.addByte(history.historyType);
msg.add<int32_t>(history.coinAmount);

msg.addByte(history.coinType);
Expand Down

0 comments on commit 3938189

Please sign in to comment.