feat: reward codes

this is for giving rewards across characters as the did in live.
Tested that the default config works
Tested that all claim codes work
Tested that saving and loading claim codes work
Tested that mail sends correctly
This commit is contained in:
Aaron Kimbre
2023-11-19 01:28:07 -06:00
parent 8e84cafdfa
commit 138dc0fab6
19 changed files with 219 additions and 8 deletions

View File

@@ -37,6 +37,7 @@
#include "CDPropertyTemplateTable.h"
#include "CDFeatureGatingTable.h"
#include "CDRailActivatorComponent.h"
#include "CDRewardCodesTable.h"
// Uncomment this to cache the full cdclient database into memory. This will make the server load faster, but will use more memory.
// A vanilla CDClient takes about 46MB of memory + the regular world data.
@@ -82,6 +83,7 @@ CDClientManager::CDClientManager() {
CDRailActivatorComponentTable::Instance().LoadValuesFromDatabase();
CDRarityTableTable::Instance().LoadValuesFromDatabase();
CDRebuildComponentTable::Instance().LoadValuesFromDatabase();
CDRewardCodesTable::Instance().LoadValuesFromDatabase();
CDRewardsTable::Instance().LoadValuesFromDatabase();
CDScriptComponentTable::Instance().LoadValuesFromDatabase();
CDSkillBehaviorTable::Instance().LoadValuesFromDatabase();

View File

@@ -0,0 +1,53 @@
#include "CDRewardCodesTable.h"
void CDRewardCodesTable::LoadValuesFromDatabase() {
// First, get the size of the table
unsigned int size = 0;
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM RewardCodes");
while (!tableSize.eof()) {
size = tableSize.getIntField(0, 0);
tableSize.nextRow();
}
tableSize.finalize();
// Reserve the size
this->entries.reserve(size);
// Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM RewardCodes");
while (!tableData.eof()) {
CDRewardCode entry;
entry.id = tableData.getIntField("id", -1);
entry.code = tableData.getStringField("code", "");
entry.attachmentLOT = tableData.getIntField("attachmentLOT", -1);
UNUSED_COLUMN(entry.locStatus = tableData.getIntField("locStatus", -1));
UNUSED_COLUMN(entry.gate_version = tableData.getStringField("gate_version", ""));
this->entries.push_back(entry);
tableData.nextRow();
}
tableData.finalize();
}
const std::vector<CDRewardCode>& CDRewardCodesTable::GetEntries() const {
return this->entries;
}
LOT CDRewardCodesTable::GetAttachmentLOT(uint32_t rewardCodeId) const {
for (auto const &entry : this->entries){
if (rewardCodeId == entry.id) return entry.attachmentLOT;
}
return LOT_NULL;
}
uint32_t CDRewardCodesTable::GetCodeID(std::string code) const {
for (auto const &entry : this->entries){
if (code == entry.code) return entry.id;
}
return -1;
}

View File

@@ -0,0 +1,25 @@
#pragma once
// Custom Classes
#include "CDTable.h"
struct CDRewardCode {
uint32_t id;
std::string code;
LOT attachmentLOT;
UNUSED(uint32_t locStatus);
UNUSED(std::string gate_version);
};
class CDRewardCodesTable : public CDTable<CDRewardCodesTable> {
private:
std::vector<CDRewardCode> entries;
public:
void LoadValuesFromDatabase();
const std::vector<CDRewardCode>& GetEntries() const;
LOT GetAttachmentLOT(uint32_t rewardCodeId) const;
uint32_t GetCodeID(std::string code) const;
};

View File

@@ -8,6 +8,7 @@
#include <string>
#include <vector>
#include <map>
#include <cstdint>
// CPPLinq
#ifdef _WIN32

View File

@@ -31,6 +31,7 @@ set(DDATABASE_CDCLIENTDATABASE_CDCLIENTTABLES_SOURCES "CDActivitiesTable.cpp"
"CDRailActivatorComponent.cpp"
"CDRarityTableTable.cpp"
"CDRebuildComponentTable.cpp"
"CDRewardCodesTable.cpp"
"CDRewardsTable.cpp"
"CDScriptComponentTable.cpp"
"CDSkillBehaviorTable.cpp"

View File

@@ -21,6 +21,7 @@
#include "ICharInfo.h"
#include "IAccounts.h"
#include "IActivityLog.h"
#include "IAccountsRewardCodes.h"
namespace sql {
class Statement;
@@ -38,7 +39,7 @@ class GameDatabase :
public IMail, public ICommandLog, public IPlayerCheatDetections, public IBugReports,
public IPropertyContents, public IProperty, public IPetNames, public ICharXml,
public IMigrationHistory, public IUgc, public IFriends, public ICharInfo,
public IAccounts, public IActivityLog {
public IAccounts, public IActivityLog, public IAccountsRewardCodes {
public:
virtual ~GameDatabase() = default;
// TODO: These should be made private.

View File

@@ -0,0 +1,12 @@
#ifndef __IACCOUNTSREWARDCODES__H__
#define __IACCOUNTSREWARDCODES__H__
#include <cstdint>
#include <vector>
class IAccountsRewardCodes {
public:
virtual void InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) = 0;
virtual std::vector<uint32_t> GetRewardCodesByAccountID(const uint32_t account_id) = 0;
};
#endif //!__IACCOUNTSREWARDCODES__H__

View File

@@ -103,6 +103,8 @@ public:
std::optional<uint32_t> GetDonationTotal(const uint32_t activityId) override;
std::optional<bool> IsPlaykeyActive(const int32_t playkeyId) override;
std::vector<IUgc::Model> GetUgcModels(const LWOOBJID& propertyId) override;
void InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) override;
std::vector<uint32_t> GetRewardCodesByAccountID(const uint32_t account_id) override;
private:
// Generic query functions that can be used for any query.

View File

@@ -0,0 +1,17 @@
#include "MySQLDatabase.h"
void MySQLDatabase::InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) {
ExecuteInsert("INSERT IGNORE INTO accounts_rewardcodes (account_id, rewardcode) VALUES (?, ?);", account_id, reward_code);
}
std::vector<uint32_t> MySQLDatabase::GetRewardCodesByAccountID(const uint32_t account_id) {
auto result = ExecuteSelect("SELECT rewardcode FROM accounts_rewardcodes WHERE account_id = ?;", account_id);
std::vector<uint32_t> toReturn;
toReturn.reserve(result->rowsCount());
while (result->next()) {
toReturn.push_back(result->getUInt("rewardcode"));
}
return toReturn;
}

View File

@@ -1,5 +1,6 @@
set(DDATABASES_DATABASES_MYSQL_TABLES_SOURCES
"Accounts.cpp"
"AccountsRewardCodes.cpp"
"ActivityLog.cpp"
"BugReports.cpp"
"CharInfo.cpp"