mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-12-16 20:24:39 -06:00
Compare commits
6 Commits
EmosewaMC-
...
feat-rewar
| Author | SHA1 | Date | |
|---|---|---|---|
| 3d0ba3c5cf | |||
| 0cb64d3209 | |||
| 4deabca780 | |||
| 913105fc31 | |||
| e1325b1e0f | |||
| 138dc0fab6 |
@@ -94,6 +94,8 @@ int main(int argc, char** argv) {
|
||||
uint32_t framesSinceMasterDisconnect = 0;
|
||||
uint32_t framesSinceLastSQLPing = 0;
|
||||
|
||||
AuthPackets::LoadClaimCodes();
|
||||
|
||||
while (!Game::shouldShutdown) {
|
||||
//Check if we're still connected to master:
|
||||
if (!Game::server->GetIsConnectedToMaster()) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
#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();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <cstdint>
|
||||
|
||||
// CPPLinq
|
||||
#ifdef _WIN32
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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.
|
||||
|
||||
13
dDatabase/GameDatabase/ITables/IAccountsRewardCodes.h
Normal file
13
dDatabase/GameDatabase/ITables/IAccountsRewardCodes.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#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__
|
||||
@@ -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.
|
||||
|
||||
17
dDatabase/GameDatabase/MySQL/Tables/AccountsRewardCodes.cpp
Normal file
17
dDatabase/GameDatabase/MySQL/Tables/AccountsRewardCodes.cpp
Normal 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;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
set(DDATABASES_DATABASES_MYSQL_TABLES_SOURCES
|
||||
"Accounts.cpp"
|
||||
"AccountsRewardCodes.cpp"
|
||||
"ActivityLog.cpp"
|
||||
"BugReports.cpp"
|
||||
"CharInfo.cpp"
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
#include "Amf3.h"
|
||||
#include "eGameMasterLevel.h"
|
||||
#include "eGameActivity.h"
|
||||
#include "User.h"
|
||||
#include "Database.h"
|
||||
#include "CDRewardCodesTable.h"
|
||||
#include "Mail.h"
|
||||
#include <ctime>
|
||||
|
||||
CharacterComponent::CharacterComponent(Entity* parent, Character* character) : Component(parent) {
|
||||
@@ -74,10 +78,14 @@ CharacterComponent::~CharacterComponent() {
|
||||
void CharacterComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
|
||||
|
||||
if (bIsInitialUpdate) {
|
||||
outBitStream->Write0();
|
||||
outBitStream->Write0();
|
||||
outBitStream->Write0();
|
||||
outBitStream->Write0();
|
||||
outBitStream->Write(m_ClaimCodes[0] != 0);
|
||||
if (m_ClaimCodes[0] != 0) outBitStream->Write(m_ClaimCodes[0]);
|
||||
outBitStream->Write(m_ClaimCodes[1] != 0);
|
||||
if (m_ClaimCodes[1] != 0) outBitStream->Write(m_ClaimCodes[1]);
|
||||
outBitStream->Write(m_ClaimCodes[2] != 0);
|
||||
if (m_ClaimCodes[2] != 0) outBitStream->Write(m_ClaimCodes[2]);
|
||||
outBitStream->Write(m_ClaimCodes[3] != 0);
|
||||
if (m_ClaimCodes[3] != 0) outBitStream->Write(m_ClaimCodes[3]);
|
||||
|
||||
outBitStream->Write(m_Character->GetHairColor());
|
||||
outBitStream->Write(m_Character->GetHairStyle());
|
||||
@@ -186,6 +194,13 @@ void CharacterComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
||||
SetReputation(0);
|
||||
}
|
||||
|
||||
character->QueryUnsigned64Attribute("co", &m_ClaimCodes[0]);
|
||||
character->QueryUnsigned64Attribute("co1", &m_ClaimCodes[1]);
|
||||
character->QueryUnsigned64Attribute("co2", &m_ClaimCodes[2]);
|
||||
character->QueryUnsigned64Attribute("co3", &m_ClaimCodes[3]);
|
||||
|
||||
AwardClaimCodes();
|
||||
|
||||
character->QueryInt64Attribute("ls", &m_Uscore);
|
||||
|
||||
// Load the statistics
|
||||
@@ -308,6 +323,11 @@ void CharacterComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_ClaimCodes[0] != 0) character->SetAttribute("co", m_ClaimCodes[0]);
|
||||
if (m_ClaimCodes[1] != 0) character->SetAttribute("co1", m_ClaimCodes[1]);
|
||||
if (m_ClaimCodes[2] != 0) character->SetAttribute("co2", m_ClaimCodes[2]);
|
||||
if (m_ClaimCodes[3] != 0) character->SetAttribute("co3", m_ClaimCodes[3]);
|
||||
|
||||
character->SetAttribute("ls", m_Uscore);
|
||||
// Custom attribute to keep track of reputation.
|
||||
character->SetAttribute("rpt", GetReputation());
|
||||
@@ -738,3 +758,31 @@ void CharacterComponent::UpdateClientMinimap(bool showFaction, std::string ventu
|
||||
arrayToSend.Insert(ventureVisionType, showFaction);
|
||||
GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent ? m_Parent->GetSystemAddress() : UNASSIGNED_SYSTEM_ADDRESS, "SetFactionVisibility", arrayToSend);
|
||||
}
|
||||
|
||||
void CharacterComponent::AwardClaimCodes() {
|
||||
if (!m_Parent) return;
|
||||
auto* user = m_Parent->GetParentUser();
|
||||
if (!user) return;
|
||||
|
||||
auto rewardCodes = Database::Get()->GetRewardCodesByAccountID(user->GetAccountID());
|
||||
if (rewardCodes.empty()) return;
|
||||
|
||||
auto* cdrewardCodes = CDClientManager::Instance().GetTable<CDRewardCodesTable>();
|
||||
for (auto const rewardCode: rewardCodes){
|
||||
LOG_DEBUG("Processing RewardCode %i", rewardCode);
|
||||
const uint32_t rewardCodeIndex = rewardCode >> 6;
|
||||
const uint32_t bitIndex = rewardCode % 64;
|
||||
if (GeneralUtils::CheckBit(m_ClaimCodes[rewardCodeIndex], bitIndex)) continue;
|
||||
m_ClaimCodes[rewardCodeIndex] = GeneralUtils::SetBit(m_ClaimCodes[rewardCodeIndex], bitIndex);
|
||||
|
||||
// Don't send it on this one since it's default and the mail doesn't make sense
|
||||
if (rewardCode == 30) continue;
|
||||
|
||||
auto attachmentLOT = cdrewardCodes->GetAttachmentLOT(rewardCode);
|
||||
std::ostringstream subject;
|
||||
subject << "%[RewardCodes_" << rewardCode << "_subjectText]";
|
||||
std::ostringstream body;
|
||||
body << "%[RewardCodes_" << rewardCode << "_bodyText]";
|
||||
Mail::SendMail(LWOOBJID_EMPTY, "%[MAIL_SYSTEM_NOTIFICATION]", m_Parent, subject.str(), body.str(), attachmentLOT, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "CDMissionsTable.h"
|
||||
#include "tinyxml2.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
#include <array>
|
||||
|
||||
enum class eGameActivity : uint32_t;
|
||||
|
||||
@@ -566,6 +567,10 @@ private:
|
||||
LWOOBJID m_LastRocketItemID = LWOOBJID_EMPTY;
|
||||
|
||||
LWOOBJID m_CurrentInteracting = LWOOBJID_EMPTY;
|
||||
|
||||
std::array<uint64_t, 4> m_ClaimCodes{};
|
||||
|
||||
void AwardClaimCodes();
|
||||
};
|
||||
|
||||
#endif // CHARACTERCOMPONENT_H
|
||||
|
||||
@@ -83,6 +83,7 @@
|
||||
#include "eChatInternalMessageType.h"
|
||||
#include "eMasterMessageType.h"
|
||||
|
||||
#include "CDRewardCodesTable.h"
|
||||
#include "CDObjectsTable.h"
|
||||
#include "CDZoneTableTable.h"
|
||||
|
||||
@@ -1895,6 +1896,13 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
|
||||
}
|
||||
}
|
||||
|
||||
if (chatCommand == "setrewardcode" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() == 1) {
|
||||
auto* cdrewardCodes = CDClientManager::Instance().GetTable<CDRewardCodesTable>();
|
||||
|
||||
auto id = cdrewardCodes->GetCodeID(args[0]);
|
||||
if (id != -1) Database::Get()->InsertRewardCode(user->GetAccountID(), id);
|
||||
}
|
||||
|
||||
if (chatCommand == "inspect" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 1) {
|
||||
Entity* closest = nullptr;
|
||||
|
||||
|
||||
@@ -29,6 +29,22 @@
|
||||
#include "eMasterMessageType.h"
|
||||
#include "eGameMasterLevel.h"
|
||||
|
||||
namespace {
|
||||
std::vector<uint32_t> claimCodes;
|
||||
}
|
||||
|
||||
void AuthPackets::LoadClaimCodes() {
|
||||
if(!claimCodes.empty()) return;
|
||||
auto rcstring = Game::config->GetValue("rewardcodes");
|
||||
auto codestrings = GeneralUtils::SplitString(rcstring, ',');
|
||||
for(auto const &codestring: codestrings){
|
||||
uint32_t code = -1;
|
||||
if(GeneralUtils::TryParse(codestring, code) && code != -1){
|
||||
claimCodes.push_back(code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AuthPackets::HandleHandshake(dServer* server, Packet* packet) {
|
||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||
uint64_t header = inStream.Read(header);
|
||||
@@ -129,6 +145,10 @@ void AuthPackets::HandleLoginRequest(dServer* server, Packet* packet) {
|
||||
AuthPackets::SendLoginResponse(server, system, eLoginResponse::SUCCESS, "", zoneIP, zonePort, username);
|
||||
});
|
||||
}
|
||||
|
||||
for(auto const code: claimCodes){
|
||||
Database::Get()->InsertRewardCode(accountInfo->id, code);
|
||||
}
|
||||
}
|
||||
|
||||
void AuthPackets::SendLoginResponse(dServer* server, const SystemAddress& sysAddr, eLoginResponse responseCode, const std::string& errorMsg, const std::string& wServerIP, uint16_t wServerPort, std::string username) {
|
||||
|
||||
@@ -15,6 +15,8 @@ namespace AuthPackets {
|
||||
|
||||
void HandleLoginRequest(dServer* server, Packet* packet);
|
||||
void SendLoginResponse(dServer* server, const SystemAddress& sysAddr, eLoginResponse responseCode, const std::string& errorMsg, const std::string& wServerIP, uint16_t wServerPort, std::string username);
|
||||
void LoadClaimCodes();
|
||||
|
||||
}
|
||||
|
||||
#endif // AUTHPACKETS_H
|
||||
|
||||
@@ -1033,9 +1033,8 @@ void HandlePacket(Packet* packet) {
|
||||
Game::entityManager->ConstructAllEntities(packet->systemAddress);
|
||||
|
||||
auto* characterComponent = player->GetComponent<CharacterComponent>();
|
||||
if (characterComponent) {
|
||||
player->GetComponent<CharacterComponent>()->RocketUnEquip(player);
|
||||
}
|
||||
if (!characterComponent) return;
|
||||
characterComponent->RocketUnEquip(player);
|
||||
|
||||
// Do charxml fixes here
|
||||
auto* levelComponent = player->GetComponent<LevelProgressionComponent>();
|
||||
|
||||
@@ -112,6 +112,7 @@ These commands are primarily for development and testing. The usage of many of t
|
||||
|setfaction|`/setfaction <faction id>`|Clears the users current factions and sets it|8|
|
||||
|addfaction|`/addfaction <faction id>`|Add the faction to the users list of factions|8|
|
||||
|getfactions|`/getfactions`|Shows the player's factions|8|
|
||||
|setrewardcode|`/setrewardcode <code>`|Sets the rewardcode for the account you are logged into if it's a valid rewardcode, See cdclient table `RewardCodes`|8|
|
||||
## Detailed `/inspect` Usage
|
||||
|
||||
`/inspect <component> (-m <waypoint> | -a <animation> | -s | -p | -f (faction) | -t)`
|
||||
|
||||
5
migrations/dlu/14_reward_codes.sql
Normal file
5
migrations/dlu/14_reward_codes.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
CREATE TABLE IF NOT EXISTS accounts_rewardcodes (
|
||||
account_id INT NOT NULL REFERENCES accounts(id) ON DELETE CASCADE,
|
||||
rewardcode INT NOT NULL,
|
||||
PRIMARY KEY (account_id, rewardcode)
|
||||
);
|
||||
@@ -4,3 +4,11 @@ port=1001
|
||||
# 0 or 1, should ignore playkeys
|
||||
# If 1 everyone with an account will be able to login, regardless of if they have a key or not
|
||||
dont_use_keys=0
|
||||
|
||||
# list of rewardcodes to set on the accounts by default
|
||||
# ex: 30,1,0,3
|
||||
# See RewardCodes in the CDclient for what codes exist
|
||||
# Default 4,30
|
||||
# 4 allows LEGOClub access
|
||||
# 30 makes the client not consume bricks when in bbb mode
|
||||
rewardcodes=4,30
|
||||
|
||||
Reference in New Issue
Block a user