mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-12-21 11:59:37 -06:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea2ef0aea3 | ||
|
|
202ac1e204 |
100
dCommon/Amf3.h
100
dCommon/Amf3.h
@@ -41,13 +41,12 @@ template <typename ValueType>
|
|||||||
class AMFValue : public AMFBaseValue {
|
class AMFValue : public AMFBaseValue {
|
||||||
public:
|
public:
|
||||||
AMFValue() = default;
|
AMFValue() = default;
|
||||||
AMFValue(const ValueType value) : m_Data{ value } {}
|
AMFValue(const ValueType value) { m_Data = value; }
|
||||||
virtual ~AMFValue() override = default;
|
virtual ~AMFValue() override = default;
|
||||||
|
|
||||||
[[nodiscard]] constexpr eAmf GetValueType() const noexcept override;
|
[[nodiscard]] constexpr eAmf GetValueType() const noexcept override;
|
||||||
|
|
||||||
[[nodiscard]] const ValueType& GetValue() const { return m_Data; }
|
[[nodiscard]] const ValueType& GetValue() const { return m_Data; }
|
||||||
|
|
||||||
void SetValue(const ValueType value) { m_Data = value; }
|
void SetValue(const ValueType value) { m_Data = value; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -55,7 +54,7 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Explicit template class instantiations
|
// Explicit template class instantiations
|
||||||
template class AMFValue<std::nullptr_t>;
|
template class AMFValue<std::nullptr_t>;
|
||||||
template class AMFValue<bool>;
|
template class AMFValue<bool>;
|
||||||
template class AMFValue<int32_t>;
|
template class AMFValue<int32_t>;
|
||||||
template class AMFValue<uint32_t>;
|
template class AMFValue<uint32_t>;
|
||||||
@@ -111,7 +110,7 @@ public:
|
|||||||
[[nodiscard]] constexpr eAmf GetValueType() const noexcept override { return eAmf::Array; }
|
[[nodiscard]] constexpr eAmf GetValueType() const noexcept override { return eAmf::Array; }
|
||||||
|
|
||||||
~AMFArrayValue() override {
|
~AMFArrayValue() override {
|
||||||
for (const auto* valueToDelete : GetDense()) {
|
for (auto valueToDelete : GetDense()) {
|
||||||
if (valueToDelete) {
|
if (valueToDelete) {
|
||||||
delete valueToDelete;
|
delete valueToDelete;
|
||||||
valueToDelete = nullptr;
|
valueToDelete = nullptr;
|
||||||
@@ -128,12 +127,12 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Returns the Associative portion of the object
|
* Returns the Associative portion of the object
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] inline const AMFAssociative& GetAssociative() const noexcept { return m_Associative; }
|
[[nodiscard]] inline const AMFAssociative& GetAssociative() const noexcept { return this->associative; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the dense portion of the object
|
* Returns the dense portion of the object
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] inline const AMFDense& GetDense() const noexcept { return m_Dense; }
|
[[nodiscard]] inline const AMFDense& GetDense() const noexcept { return this->dense; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inserts an AMFValue into the associative portion with the given key.
|
* Inserts an AMFValue into the associative portion with the given key.
|
||||||
@@ -151,12 +150,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
template <typename ValueType>
|
template <typename ValueType>
|
||||||
[[maybe_unused]] std::pair<AMFValue<ValueType>*, bool> Insert(const std::string& key, const ValueType value) {
|
[[maybe_unused]] std::pair<AMFValue<ValueType>*, bool> Insert(const std::string& key, const ValueType value) {
|
||||||
const auto element = m_Associative.find(key);
|
auto element = associative.find(key);
|
||||||
AMFValue<ValueType>* val = nullptr;
|
AMFValue<ValueType>* val = nullptr;
|
||||||
bool found = true;
|
bool found = true;
|
||||||
if (element == m_Associative.cend()) {
|
if (element == associative.end()) {
|
||||||
val = new AMFValue<ValueType>(value);
|
val = new AMFValue<ValueType>(value);
|
||||||
m_Associative.emplace(key, val);
|
associative.insert(std::make_pair(key, val));
|
||||||
} else {
|
} else {
|
||||||
val = dynamic_cast<AMFValue<ValueType>*>(element->second);
|
val = dynamic_cast<AMFValue<ValueType>*>(element->second);
|
||||||
found = false;
|
found = false;
|
||||||
@@ -166,12 +165,12 @@ public:
|
|||||||
|
|
||||||
// Associates an array with a string key
|
// Associates an array with a string key
|
||||||
[[maybe_unused]] std::pair<AMFBaseValue*, bool> Insert(const std::string& key) {
|
[[maybe_unused]] std::pair<AMFBaseValue*, bool> Insert(const std::string& key) {
|
||||||
const auto element = m_Associative.find(key);
|
auto element = associative.find(key);
|
||||||
AMFArrayValue* val = nullptr;
|
AMFArrayValue* val = nullptr;
|
||||||
bool found = true;
|
bool found = true;
|
||||||
if (element == m_Associative.cend()) {
|
if (element == associative.end()) {
|
||||||
val = new AMFArrayValue();
|
val = new AMFArrayValue();
|
||||||
m_Associative.emplace(key, val);
|
associative.insert(std::make_pair(key, val));
|
||||||
} else {
|
} else {
|
||||||
val = dynamic_cast<AMFArrayValue*>(element->second);
|
val = dynamic_cast<AMFArrayValue*>(element->second);
|
||||||
found = false;
|
found = false;
|
||||||
@@ -183,13 +182,13 @@ public:
|
|||||||
[[maybe_unused]] std::pair<AMFBaseValue*, bool> Insert(const size_t index) {
|
[[maybe_unused]] std::pair<AMFBaseValue*, bool> Insert(const size_t index) {
|
||||||
AMFArrayValue* val = nullptr;
|
AMFArrayValue* val = nullptr;
|
||||||
bool inserted = false;
|
bool inserted = false;
|
||||||
if (index >= m_Dense.size()) {
|
if (index >= dense.size()) {
|
||||||
m_Dense.resize(index + 1);
|
dense.resize(index + 1);
|
||||||
val = new AMFArrayValue();
|
val = new AMFArrayValue();
|
||||||
m_Dense.at(index) = val;
|
dense.at(index) = val;
|
||||||
inserted = true;
|
inserted = true;
|
||||||
}
|
}
|
||||||
return std::make_pair(dynamic_cast<AMFArrayValue*>(m_Dense.at(index)), inserted);
|
return std::make_pair(dynamic_cast<AMFArrayValue*>(dense.at(index)), inserted);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -206,13 +205,13 @@ public:
|
|||||||
[[maybe_unused]] std::pair<AMFValue<ValueType>*, bool> Insert(const size_t index, const ValueType value) {
|
[[maybe_unused]] std::pair<AMFValue<ValueType>*, bool> Insert(const size_t index, const ValueType value) {
|
||||||
AMFValue<ValueType>* val = nullptr;
|
AMFValue<ValueType>* val = nullptr;
|
||||||
bool inserted = false;
|
bool inserted = false;
|
||||||
if (index >= m_Dense.size()) {
|
if (index >= this->dense.size()) {
|
||||||
m_Dense.resize(index + 1);
|
this->dense.resize(index + 1);
|
||||||
val = new AMFValue<ValueType>(value);
|
val = new AMFValue<ValueType>(value);
|
||||||
m_Dense.at(index) = val;
|
this->dense.at(index) = val;
|
||||||
inserted = true;
|
inserted = true;
|
||||||
}
|
}
|
||||||
return std::make_pair(dynamic_cast<AMFValue<ValueType>*>(m_Dense.at(index)), inserted);
|
return std::make_pair(dynamic_cast<AMFValue<ValueType>*>(this->dense.at(index)), inserted);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -225,12 +224,12 @@ public:
|
|||||||
* @param value The value to insert
|
* @param value The value to insert
|
||||||
*/
|
*/
|
||||||
void Insert(const std::string& key, AMFBaseValue* const value) {
|
void Insert(const std::string& key, AMFBaseValue* const value) {
|
||||||
const auto element = m_Associative.find(key);
|
auto element = associative.find(key);
|
||||||
if (element != m_Associative.cend() && element->second) {
|
if (element != associative.end() && element->second) {
|
||||||
delete element->second;
|
delete element->second;
|
||||||
element->second = value;
|
element->second = value;
|
||||||
} else {
|
} else {
|
||||||
m_Associative.emplace(key, value);
|
associative.insert(std::make_pair(key, value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,13 +243,13 @@ public:
|
|||||||
* @param value The value to insert
|
* @param value The value to insert
|
||||||
*/
|
*/
|
||||||
void Insert(const size_t index, AMFBaseValue* const value) {
|
void Insert(const size_t index, AMFBaseValue* const value) {
|
||||||
if (index < m_Dense.size()) {
|
if (index < dense.size()) {
|
||||||
const AMFDense::const_iterator itr = m_Dense.cbegin() + index;
|
AMFDense::iterator itr = dense.begin() + index;
|
||||||
if (*itr) delete m_Dense.at(index);
|
if (*itr) delete dense.at(index);
|
||||||
} else {
|
} else {
|
||||||
m_Dense.resize(index + 1);
|
dense.resize(index + 1);
|
||||||
}
|
}
|
||||||
m_Dense.at(index) = value;
|
dense.at(index) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -265,7 +264,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
template <typename ValueType>
|
template <typename ValueType>
|
||||||
[[maybe_unused]] inline AMFValue<ValueType>* Push(const ValueType value) {
|
[[maybe_unused]] inline AMFValue<ValueType>* Push(const ValueType value) {
|
||||||
return Insert(m_Dense.size(), value).first;
|
return Insert(this->dense.size(), value).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -276,10 +275,10 @@ public:
|
|||||||
* @param key The key to remove from the associative portion
|
* @param key The key to remove from the associative portion
|
||||||
*/
|
*/
|
||||||
void Remove(const std::string& key, const bool deleteValue = true) {
|
void Remove(const std::string& key, const bool deleteValue = true) {
|
||||||
const AMFAssociative::const_iterator it = m_Associative.find(key);
|
AMFAssociative::iterator it = this->associative.find(key);
|
||||||
if (it != m_Associative.cend()) {
|
if (it != this->associative.end()) {
|
||||||
if (deleteValue) delete it->second;
|
if (deleteValue) delete it->second;
|
||||||
m_Associative.erase(it);
|
this->associative.erase(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,24 +286,27 @@ public:
|
|||||||
* Pops the last element in the dense portion, deleting it in the process.
|
* Pops the last element in the dense portion, deleting it in the process.
|
||||||
*/
|
*/
|
||||||
void Remove(const size_t index) {
|
void Remove(const size_t index) {
|
||||||
if (!m_Dense.empty() && index < m_Dense.size()) {
|
if (!this->dense.empty() && index < this->dense.size()) {
|
||||||
const auto itr = m_Dense.cbegin() + index;
|
auto itr = this->dense.begin() + index;
|
||||||
if (*itr) delete (*itr);
|
if (*itr) delete (*itr);
|
||||||
m_Dense.erase(itr);
|
this->dense.erase(itr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pop() {
|
void Pop() {
|
||||||
if (!m_Dense.empty()) Remove(m_Dense.size() - 1);
|
if (!this->dense.empty()) Remove(this->dense.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] AMFArrayValue* GetArray(const std::string& key) const {
|
[[nodiscard]] AMFArrayValue* GetArray(const std::string& key) const {
|
||||||
const AMFAssociative::const_iterator it = m_Associative.find(key);
|
AMFAssociative::const_iterator it = this->associative.find(key);
|
||||||
return it != m_Associative.cend() ? dynamic_cast<AMFArrayValue*>(it->second) : nullptr;
|
if (it != this->associative.end()) {
|
||||||
|
return dynamic_cast<AMFArrayValue*>(it->second);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] AMFArrayValue* GetArray(const size_t index) const {
|
[[nodiscard]] AMFArrayValue* GetArray(const size_t index) const {
|
||||||
return index < m_Dense.size() ? dynamic_cast<AMFArrayValue*>(m_Dense.at(index)) : nullptr;
|
return index >= this->dense.size() ? nullptr : dynamic_cast<AMFArrayValue*>(this->dense.at(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
[[maybe_unused]] inline AMFArrayValue* InsertArray(const std::string& key) {
|
[[maybe_unused]] inline AMFArrayValue* InsertArray(const std::string& key) {
|
||||||
@@ -316,7 +318,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
[[maybe_unused]] inline AMFArrayValue* PushArray() {
|
[[maybe_unused]] inline AMFArrayValue* PushArray() {
|
||||||
return static_cast<AMFArrayValue*>(Insert(m_Dense.size()).first);
|
return static_cast<AMFArrayValue*>(Insert(this->dense.size()).first);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -330,16 +332,16 @@ public:
|
|||||||
*/
|
*/
|
||||||
template <typename AmfType>
|
template <typename AmfType>
|
||||||
[[nodiscard]] AMFValue<AmfType>* Get(const std::string& key) const {
|
[[nodiscard]] AMFValue<AmfType>* Get(const std::string& key) const {
|
||||||
const AMFAssociative::const_iterator it = m_Associative.find(key);
|
AMFAssociative::const_iterator it = this->associative.find(key);
|
||||||
return it != m_Associative.cend() ?
|
return it != this->associative.end() ?
|
||||||
dynamic_cast<AMFValue<AmfType>*>(it->second) :
|
dynamic_cast<AMFValue<AmfType>*>(it->second) :
|
||||||
nullptr;
|
nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get from the array but dont cast it
|
// Get from the array but dont cast it
|
||||||
[[nodiscard]] AMFBaseValue* Get(const std::string& key) const {
|
[[nodiscard]] AMFBaseValue* Get(const std::string& key) const {
|
||||||
const AMFAssociative::const_iterator it = m_Associative.find(key);
|
AMFAssociative::const_iterator it = this->associative.find(key);
|
||||||
return it != m_Associative.cend() ? it->second : nullptr;
|
return it != this->associative.end() ? it->second : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -353,27 +355,27 @@ public:
|
|||||||
*/
|
*/
|
||||||
template <typename AmfType>
|
template <typename AmfType>
|
||||||
[[nodiscard]] AMFValue<AmfType>* Get(const size_t index) const {
|
[[nodiscard]] AMFValue<AmfType>* Get(const size_t index) const {
|
||||||
return index < m_Dense.size() ?
|
return index < this->dense.size() ?
|
||||||
dynamic_cast<AMFValue<AmfType>*>(m_Dense.at(index)) :
|
dynamic_cast<AMFValue<AmfType>*>(this->dense.at(index)) :
|
||||||
nullptr;
|
nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get from the dense but dont cast it
|
// Get from the dense but dont cast it
|
||||||
[[nodiscard]] AMFBaseValue* Get(const size_t index) const {
|
[[nodiscard]] AMFBaseValue* Get(const size_t index) const {
|
||||||
return index < m_Dense.size() ? m_Dense.at(index) : nullptr;
|
return index < this->dense.size() ? this->dense.at(index) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* The associative portion. These values are key'd with strings to an AMFValue.
|
* The associative portion. These values are key'd with strings to an AMFValue.
|
||||||
*/
|
*/
|
||||||
AMFAssociative m_Associative;
|
AMFAssociative associative;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The dense portion. These AMFValue's are stored one after
|
* The dense portion. These AMFValue's are stored one after
|
||||||
* another with the most recent addition being at the back.
|
* another with the most recent addition being at the back.
|
||||||
*/
|
*/
|
||||||
AMFDense m_Dense;
|
AMFDense dense;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__AMF3__H__
|
#endif //!__AMF3__H__
|
||||||
|
|||||||
@@ -294,50 +294,28 @@ std::u16string GeneralUtils::ReadWString(RakNet::BitStream* inStream) {
|
|||||||
|
|
||||||
std::vector<std::string> GeneralUtils::GetSqlFileNamesFromFolder(const std::string& folder) {
|
std::vector<std::string> GeneralUtils::GetSqlFileNamesFromFolder(const std::string& folder) {
|
||||||
// Because we dont know how large the initial number before the first _ is we need to make it a map like so.
|
// Because we dont know how large the initial number before the first _ is we need to make it a map like so.
|
||||||
std::map<uint32_t, std::string> filenames{};
|
std::map<uint32_t, std::string> filenames{};
|
||||||
for (auto& t : std::filesystem::directory_iterator(folder)) {
|
for (auto& t : std::filesystem::directory_iterator(folder)) {
|
||||||
auto filename = t.path().filename().string();
|
auto filename = t.path().filename().string();
|
||||||
auto index = std::stoi(GeneralUtils::SplitString(filename, '_').at(0));
|
auto index = std::stoi(GeneralUtils::SplitString(filename, '_').at(0));
|
||||||
filenames.insert(std::make_pair(index, filename));
|
filenames.insert(std::make_pair(index, filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now sort the map by the oldest migration.
|
// Now sort the map by the oldest migration.
|
||||||
std::vector<std::string> sortedFiles{};
|
std::vector<std::string> sortedFiles{};
|
||||||
auto fileIterator = filenames.begin();
|
auto fileIterator = filenames.begin();
|
||||||
std::map<uint32_t, std::string>::iterator oldest = filenames.begin();
|
std::map<uint32_t, std::string>::iterator oldest = filenames.begin();
|
||||||
while (!filenames.empty()) {
|
while (!filenames.empty()) {
|
||||||
if (fileIterator == filenames.end()) {
|
if (fileIterator == filenames.end()) {
|
||||||
sortedFiles.push_back(oldest->second);
|
sortedFiles.push_back(oldest->second);
|
||||||
filenames.erase(oldest);
|
filenames.erase(oldest);
|
||||||
fileIterator = filenames.begin();
|
fileIterator = filenames.begin();
|
||||||
oldest = filenames.begin();
|
oldest = filenames.begin();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (oldest->first > fileIterator->first) oldest = fileIterator;
|
if (oldest->first > fileIterator->first) oldest = fileIterator;
|
||||||
fileIterator++;
|
fileIterator++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sortedFiles;
|
return sortedFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DARKFLAME_PLATFORM_MACOS
|
|
||||||
|
|
||||||
// MacOS floating-point parse function specializations
|
|
||||||
namespace GeneralUtils::details {
|
|
||||||
template <>
|
|
||||||
[[nodiscard]] float _parse<float>(const std::string_view str, size_t& parseNum) {
|
|
||||||
return std::stof(std::string{ str }, &parseNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
[[nodiscard]] double _parse<double>(const std::string_view str, size_t& parseNum) {
|
|
||||||
return std::stod(std::string{ str }, &parseNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
[[nodiscard]] long double _parse<long double>(const std::string_view str, size_t& parseNum) {
|
|
||||||
return std::stold(std::string{ str }, &parseNum);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -168,10 +168,25 @@ namespace GeneralUtils {
|
|||||||
|
|
||||||
#ifdef DARKFLAME_PLATFORM_MACOS
|
#ifdef DARKFLAME_PLATFORM_MACOS
|
||||||
|
|
||||||
// MacOS floating-point parse helper function specializations
|
// Anonymous namespace containing MacOS floating-point parse function specializations
|
||||||
namespace details {
|
namespace {
|
||||||
template <std::floating_point T>
|
template <std::floating_point T>
|
||||||
[[nodiscard]] T _parse(const std::string_view str, size_t& parseNum);
|
[[nodiscard]] T Parse(const std::string_view str, size_t* parseNum);
|
||||||
|
|
||||||
|
template <>
|
||||||
|
[[nodiscard]] float Parse<float>(const std::string_view str, size_t* parseNum) {
|
||||||
|
return std::stof(std::string{ str }, parseNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
[[nodiscard]] double Parse<double>(const std::string_view str, size_t* parseNum) {
|
||||||
|
return std::stod(std::string{ str }, parseNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
[[nodiscard]] long double Parse<long double>(const std::string_view str, size_t* parseNum) {
|
||||||
|
return std::stold(std::string{ str }, parseNum);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -181,10 +196,9 @@ namespace GeneralUtils {
|
|||||||
* @returns An std::optional containing the desired value if it is equivalent to the string
|
* @returns An std::optional containing the desired value if it is equivalent to the string
|
||||||
*/
|
*/
|
||||||
template <std::floating_point T>
|
template <std::floating_point T>
|
||||||
[[nodiscard]] std::optional<T> TryParse(const std::string_view str) noexcept
|
[[nodiscard]] std::optional<T> TryParse(const std::string_view str) noexcept try {
|
||||||
try {
|
|
||||||
size_t parseNum;
|
size_t parseNum;
|
||||||
const T result = details::_parse<T>(str, parseNum);
|
const T result = Parse<T>(str, &parseNum);
|
||||||
const bool isParsed = str.length() == parseNum;
|
const bool isParsed = str.length() == parseNum;
|
||||||
|
|
||||||
return isParsed ? result : std::optional<T>{};
|
return isParsed ? result : std::optional<T>{};
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ enum class eReplicaComponentType : uint32_t {
|
|||||||
INTERACTION_MANAGER,
|
INTERACTION_MANAGER,
|
||||||
DONATION_VENDOR,
|
DONATION_VENDOR,
|
||||||
COMBAT_MEDIATOR,
|
COMBAT_MEDIATOR,
|
||||||
ACHIEVEMENT_VENDOR,
|
COMMENDATION_VENDOR,
|
||||||
GATE_RUSH_CONTROL,
|
GATE_RUSH_CONTROL,
|
||||||
RAIL_ACTIVATOR,
|
RAIL_ACTIVATOR,
|
||||||
ROLLER,
|
ROLLER,
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
#ifndef __EVENDORTRANSACTIONRESULT__
|
|
||||||
#define __EVENDORTRANSACTIONRESULT__
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
enum class eVendorTransactionResult : uint32_t {
|
|
||||||
SELL_SUCCESS = 0,
|
|
||||||
SELL_FAIL,
|
|
||||||
PURCHASE_SUCCESS,
|
|
||||||
PURCHASE_FAIL,
|
|
||||||
DONATION_FAIL,
|
|
||||||
DONATION_FULL
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // !__EVENDORTRANSACTIONRESULT__
|
|
||||||
@@ -79,6 +79,7 @@ void CDMissionsTable::LoadValuesFromDatabase() {
|
|||||||
entries.push_back(entry);
|
entries.push_back(entry);
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
tableData.finalize();
|
tableData.finalize();
|
||||||
|
|
||||||
Default.id = -1;
|
Default.id = -1;
|
||||||
@@ -117,12 +118,3 @@ const CDMissions& CDMissionsTable::GetByMissionID(uint32_t missionID, bool& foun
|
|||||||
return Default;
|
return Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::set<int32_t> CDMissionsTable::GetMissionsForReward(LOT lot) {
|
|
||||||
std::set<int32_t> toReturn {};
|
|
||||||
for (const auto& entry : GetEntries()) {
|
|
||||||
if (lot == entry.reward_item1 || lot == entry.reward_item2 || lot == entry.reward_item3 || lot == entry.reward_item4) {
|
|
||||||
toReturn.insert(entry.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -70,9 +70,6 @@ public:
|
|||||||
|
|
||||||
const CDMissions& GetByMissionID(uint32_t missionID, bool& found) const;
|
const CDMissions& GetByMissionID(uint32_t missionID, bool& found) const;
|
||||||
|
|
||||||
const std::set<int32_t> GetMissionsForReward(LOT lot);
|
|
||||||
|
|
||||||
|
|
||||||
static CDMissions Default;
|
static CDMissions Default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,6 @@
|
|||||||
#include "CollectibleComponent.h"
|
#include "CollectibleComponent.h"
|
||||||
#include "ItemComponent.h"
|
#include "ItemComponent.h"
|
||||||
#include "GhostComponent.h"
|
#include "GhostComponent.h"
|
||||||
#include "AchievementVendorComponent.h"
|
|
||||||
|
|
||||||
// Table includes
|
// Table includes
|
||||||
#include "CDComponentsRegistryTable.h"
|
#include "CDComponentsRegistryTable.h"
|
||||||
@@ -616,8 +615,6 @@ void Entity::Initialize() {
|
|||||||
AddComponent<VendorComponent>();
|
AddComponent<VendorComponent>();
|
||||||
} else if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::DONATION_VENDOR, -1) != -1)) {
|
} else if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::DONATION_VENDOR, -1) != -1)) {
|
||||||
AddComponent<DonationVendorComponent>();
|
AddComponent<DonationVendorComponent>();
|
||||||
} else if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ACHIEVEMENT_VENDOR, -1) != -1)) {
|
|
||||||
AddComponent<AchievementVendorComponent>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_VENDOR, -1) != -1) {
|
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_VENDOR, -1) != -1) {
|
||||||
@@ -1194,11 +1191,6 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType
|
|||||||
donationVendorComponent->Serialize(outBitStream, bIsInitialUpdate);
|
donationVendorComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
AchievementVendorComponent* achievementVendorComponent;
|
|
||||||
if (TryGetComponent(eReplicaComponentType::ACHIEVEMENT_VENDOR, achievementVendorComponent)) {
|
|
||||||
achievementVendorComponent->Serialize(outBitStream, bIsInitialUpdate);
|
|
||||||
}
|
|
||||||
|
|
||||||
BouncerComponent* bouncerComponent;
|
BouncerComponent* bouncerComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::BOUNCER, bouncerComponent)) {
|
if (TryGetComponent(eReplicaComponentType::BOUNCER, bouncerComponent)) {
|
||||||
bouncerComponent->Serialize(outBitStream, bIsInitialUpdate);
|
bouncerComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
|
|||||||
@@ -1,72 +0,0 @@
|
|||||||
#include "AchievementVendorComponent.h"
|
|
||||||
#include "MissionComponent.h"
|
|
||||||
#include "InventoryComponent.h"
|
|
||||||
#include "eMissionState.h"
|
|
||||||
#include "CDComponentsRegistryTable.h"
|
|
||||||
#include "CDItemComponentTable.h"
|
|
||||||
#include "eVendorTransactionResult.h"
|
|
||||||
#include "CheatDetection.h"
|
|
||||||
#include "UserManager.h"
|
|
||||||
#include "CDMissionsTable.h"
|
|
||||||
|
|
||||||
bool AchievementVendorComponent::SellsItem(Entity* buyer, const LOT lot) {
|
|
||||||
auto* missionComponent = buyer->GetComponent<MissionComponent>();
|
|
||||||
if (!missionComponent) return false;
|
|
||||||
|
|
||||||
if (m_PlayerPurchasableItems[buyer->GetObjectID()].contains(lot)){
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
CDMissionsTable* missionsTable = CDClientManager::GetTable<CDMissionsTable>();
|
|
||||||
const auto missions = missionsTable->GetMissionsForReward(lot);
|
|
||||||
for (const auto mission : missions) {
|
|
||||||
if (missionComponent->GetMissionState(mission) == eMissionState::COMPLETE) {
|
|
||||||
m_PlayerPurchasableItems[buyer->GetObjectID()].insert(lot);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AchievementVendorComponent::Buy(Entity* buyer, LOT lot, uint32_t count) {
|
|
||||||
// get the item Comp from the item LOT
|
|
||||||
CDComponentsRegistryTable* compRegistryTable = CDClientManager::GetTable<CDComponentsRegistryTable>();
|
|
||||||
CDItemComponentTable* itemComponentTable = CDClientManager::GetTable<CDItemComponentTable>();
|
|
||||||
int itemCompID = compRegistryTable->GetByIDAndType(lot, eReplicaComponentType::ITEM);
|
|
||||||
CDItemComponent itemComp = itemComponentTable->GetItemComponentByID(itemCompID);
|
|
||||||
uint32_t costLOT = itemComp.commendationLOT;
|
|
||||||
|
|
||||||
if (costLOT == -1 || !SellsItem(buyer, lot)) {
|
|
||||||
auto* user = UserManager::Instance()->GetUser(buyer->GetSystemAddress());
|
|
||||||
CheatDetection::ReportCheat(user, buyer->GetSystemAddress(), "Attempted to buy item %i from achievement vendor %i that is not purchasable", lot, m_Parent->GetLOT());
|
|
||||||
GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_FAIL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* inventoryComponent = buyer->GetComponent<InventoryComponent>();
|
|
||||||
if (!inventoryComponent) {
|
|
||||||
GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_FAIL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (costLOT == 13763) { // Faction Token Proxy
|
|
||||||
auto* missionComponent = buyer->GetComponent<MissionComponent>();
|
|
||||||
if (!missionComponent) return;
|
|
||||||
|
|
||||||
if (missionComponent->GetMissionState(545) == eMissionState::COMPLETE) costLOT = 8318; // "Assembly Token"
|
|
||||||
if (missionComponent->GetMissionState(556) == eMissionState::COMPLETE) costLOT = 8321; // "Venture League Token"
|
|
||||||
if (missionComponent->GetMissionState(567) == eMissionState::COMPLETE) costLOT = 8319; // "Sentinels Token"
|
|
||||||
if (missionComponent->GetMissionState(578) == eMissionState::COMPLETE) costLOT = 8320; // "Paradox Token"
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint32_t altCurrencyCost = itemComp.commendationCost * count;
|
|
||||||
if (inventoryComponent->GetLotCount(costLOT) < altCurrencyCost) {
|
|
||||||
GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_FAIL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
inventoryComponent->RemoveItem(costLOT, altCurrencyCost);
|
|
||||||
inventoryComponent->AddItem(lot, count, eLootSourceType::VENDOR);
|
|
||||||
GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_SUCCESS);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
#ifndef __ACHIEVEMENTVENDORCOMPONENT__H__
|
|
||||||
#define __ACHIEVEMENTVENDORCOMPONENT__H__
|
|
||||||
|
|
||||||
#include "VendorComponent.h"
|
|
||||||
#include "eReplicaComponentType.h"
|
|
||||||
#include <set>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
class Entity;
|
|
||||||
|
|
||||||
class AchievementVendorComponent final : public VendorComponent {
|
|
||||||
public:
|
|
||||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::ACHIEVEMENT_VENDOR;
|
|
||||||
AchievementVendorComponent(Entity* parent) : VendorComponent(parent) {};
|
|
||||||
bool SellsItem(Entity* buyer, const LOT lot);
|
|
||||||
void Buy(Entity* buyer, LOT lot, uint32_t count);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::map<LWOOBJID,std::set<LOT>> m_PlayerPurchasableItems;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif //!__ACHIEVEMENTVENDORCOMPONENT__H__
|
|
||||||
@@ -208,8 +208,9 @@ void BuffComponent::ApplyBuff(const int32_t id, const float duration, const LWOO
|
|||||||
void BuffComponent::RemoveBuff(int32_t id, bool fromUnEquip, bool removeImmunity, bool ignoreRefCount) {
|
void BuffComponent::RemoveBuff(int32_t id, bool fromUnEquip, bool removeImmunity, bool ignoreRefCount) {
|
||||||
const auto& iter = m_Buffs.find(id);
|
const auto& iter = m_Buffs.find(id);
|
||||||
|
|
||||||
// If the buff is already scheduled to be removed, don't do it again
|
if (iter == m_Buffs.end()) {
|
||||||
if (iter == m_Buffs.end() || m_BuffsToRemove.contains(id)) return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ignoreRefCount && !iter->second.cancelOnRemoveBuff) {
|
if (!ignoreRefCount && !iter->second.cancelOnRemoveBuff) {
|
||||||
iter->second.refCount--;
|
iter->second.refCount--;
|
||||||
@@ -221,7 +222,7 @@ void BuffComponent::RemoveBuff(int32_t id, bool fromUnEquip, bool removeImmunity
|
|||||||
|
|
||||||
GameMessages::SendRemoveBuff(m_Parent, fromUnEquip, removeImmunity, id);
|
GameMessages::SendRemoveBuff(m_Parent, fromUnEquip, removeImmunity, id);
|
||||||
|
|
||||||
m_BuffsToRemove.insert(id);
|
m_BuffsToRemove.push_back(id);
|
||||||
|
|
||||||
RemoveBuffEffect(id);
|
RemoveBuffEffect(id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ private:
|
|||||||
std::map<int32_t, Buff> m_Buffs;
|
std::map<int32_t, Buff> m_Buffs;
|
||||||
|
|
||||||
// Buffs to remove at the end of the update frame.
|
// Buffs to remove at the end of the update frame.
|
||||||
std::set<int32_t> m_BuffsToRemove;
|
std::vector<int32_t> m_BuffsToRemove;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parameters (=effects) for each buff
|
* Parameters (=effects) for each buff
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
set(DGAME_DCOMPONENTS_SOURCES
|
set(DGAME_DCOMPONENTS_SOURCES
|
||||||
"AchievementVendorComponent.cpp"
|
|
||||||
"ActivityComponent.cpp"
|
"ActivityComponent.cpp"
|
||||||
"BaseCombatAIComponent.cpp"
|
"BaseCombatAIComponent.cpp"
|
||||||
"BouncerComponent.cpp"
|
"BouncerComponent.cpp"
|
||||||
|
|||||||
@@ -8,11 +8,6 @@
|
|||||||
#include "CDLootMatrixTable.h"
|
#include "CDLootMatrixTable.h"
|
||||||
#include "CDLootTableTable.h"
|
#include "CDLootTableTable.h"
|
||||||
#include "CDItemComponentTable.h"
|
#include "CDItemComponentTable.h"
|
||||||
#include "InventoryComponent.h"
|
|
||||||
#include "Character.h"
|
|
||||||
#include "eVendorTransactionResult.h"
|
|
||||||
#include "UserManager.h"
|
|
||||||
#include "CheatDetection.h"
|
|
||||||
|
|
||||||
VendorComponent::VendorComponent(Entity* parent) : Component(parent) {
|
VendorComponent::VendorComponent(Entity* parent) : Component(parent) {
|
||||||
m_HasStandardCostItems = false;
|
m_HasStandardCostItems = false;
|
||||||
@@ -156,60 +151,3 @@ void VendorComponent::HandleMrReeCameras(){
|
|||||||
m_Inventory.push_back(SoldItem(camera, 0));
|
m_Inventory.push_back(SoldItem(camera, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void VendorComponent::Buy(Entity* buyer, LOT lot, uint32_t count) {
|
|
||||||
|
|
||||||
if (!SellsItem(lot)) {
|
|
||||||
auto* user = UserManager::Instance()->GetUser(buyer->GetSystemAddress());
|
|
||||||
CheatDetection::ReportCheat(user, buyer->GetSystemAddress(), "Attempted to buy item %i from achievement vendor %i that is not purchasable", lot, m_Parent->GetLOT());
|
|
||||||
GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_FAIL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* inventoryComponent = buyer->GetComponent<InventoryComponent>();
|
|
||||||
if (!inventoryComponent) {
|
|
||||||
GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_FAIL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
CDComponentsRegistryTable* compRegistryTable = CDClientManager::GetTable<CDComponentsRegistryTable>();
|
|
||||||
CDItemComponentTable* itemComponentTable = CDClientManager::GetTable<CDItemComponentTable>();
|
|
||||||
int itemCompID = compRegistryTable->GetByIDAndType(lot, eReplicaComponentType::ITEM);
|
|
||||||
CDItemComponent itemComp = itemComponentTable->GetItemComponentByID(itemCompID);
|
|
||||||
|
|
||||||
// Extra currency that needs to be deducted in case of crafting
|
|
||||||
auto craftingCurrencies = CDItemComponentTable::ParseCraftingCurrencies(itemComp);
|
|
||||||
for (const auto& [crafintCurrencyLOT, crafintCurrencyCount]: craftingCurrencies) {
|
|
||||||
if (inventoryComponent->GetLotCount(crafintCurrencyLOT) < (crafintCurrencyCount * count)) {
|
|
||||||
GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_FAIL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const auto& [crafintCurrencyLOT, crafintCurrencyCount]: craftingCurrencies) {
|
|
||||||
inventoryComponent->RemoveItem(crafintCurrencyLOT, crafintCurrencyCount * count);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
float buyScalar = GetBuyScalar();
|
|
||||||
const auto coinCost = static_cast<uint32_t>(std::floor((itemComp.baseValue * buyScalar) * count));
|
|
||||||
|
|
||||||
Character* character = buyer->GetCharacter();
|
|
||||||
if (!character || character->GetCoins() < coinCost) {
|
|
||||||
GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_FAIL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Inventory::IsValidItem(itemComp.currencyLOT)) {
|
|
||||||
const uint32_t altCurrencyCost = std::floor(itemComp.altCurrencyCost * buyScalar) * count;
|
|
||||||
if (inventoryComponent->GetLotCount(itemComp.currencyLOT) < altCurrencyCost) {
|
|
||||||
GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_FAIL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
inventoryComponent->RemoveItem(itemComp.currencyLOT, altCurrencyCost);
|
|
||||||
}
|
|
||||||
|
|
||||||
character->SetCoins(character->GetCoins() - (coinCost), eLootSourceType::VENDOR);
|
|
||||||
inventoryComponent->AddItem(lot, count, eLootSourceType::VENDOR);
|
|
||||||
GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_SUCCESS);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -47,7 +47,6 @@ public:
|
|||||||
m_DirtyVendor = true;
|
m_DirtyVendor = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Buy(Entity* buyer, LOT lot, uint32_t count);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetupMaxCustomVendor();
|
void SetupMaxCustomVendor();
|
||||||
|
|||||||
@@ -78,7 +78,6 @@
|
|||||||
#include "LevelProgressionComponent.h"
|
#include "LevelProgressionComponent.h"
|
||||||
#include "DonationVendorComponent.h"
|
#include "DonationVendorComponent.h"
|
||||||
#include "GhostComponent.h"
|
#include "GhostComponent.h"
|
||||||
#include "AchievementVendorComponent.h"
|
|
||||||
|
|
||||||
// Message includes:
|
// Message includes:
|
||||||
#include "dZoneManager.h"
|
#include "dZoneManager.h"
|
||||||
@@ -98,7 +97,6 @@
|
|||||||
#include "ePetAbilityType.h"
|
#include "ePetAbilityType.h"
|
||||||
#include "ActivityManager.h"
|
#include "ActivityManager.h"
|
||||||
#include "PlayerManager.h"
|
#include "PlayerManager.h"
|
||||||
#include "eVendorTransactionResult.h"
|
|
||||||
|
|
||||||
#include "CDComponentsRegistryTable.h"
|
#include "CDComponentsRegistryTable.h"
|
||||||
#include "CDObjectsTable.h"
|
#include "CDObjectsTable.h"
|
||||||
@@ -1325,14 +1323,15 @@ void GameMessages::SendVendorStatusUpdate(Entity* entity, const SystemAddress& s
|
|||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameMessages::SendVendorTransactionResult(Entity* entity, const SystemAddress& sysAddr, eVendorTransactionResult result) {
|
void GameMessages::SendVendorTransactionResult(Entity* entity, const SystemAddress& sysAddr) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
CMSGHEADER;
|
CMSGHEADER;
|
||||||
|
|
||||||
|
int iResult = 0x02; // success, seems to be the only relevant one
|
||||||
|
|
||||||
bitStream.Write(entity->GetObjectID());
|
bitStream.Write(entity->GetObjectID());
|
||||||
bitStream.Write(eGameMessageType::VENDOR_TRANSACTION_RESULT);
|
bitStream.Write(eGameMessageType::VENDOR_TRANSACTION_RESULT);
|
||||||
bitStream.Write(result);
|
bitStream.Write(iResult);
|
||||||
|
|
||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
}
|
}
|
||||||
@@ -4665,27 +4664,94 @@ void GameMessages::HandleBuyFromVendor(RakNet::BitStream* inStream, Entity* enti
|
|||||||
if (!user) return;
|
if (!user) return;
|
||||||
Entity* player = Game::entityManager->GetEntity(user->GetLoggedInChar());
|
Entity* player = Game::entityManager->GetEntity(user->GetLoggedInChar());
|
||||||
if (!player) return;
|
if (!player) return;
|
||||||
|
|
||||||
// handle buying normal items
|
|
||||||
auto* vendorComponent = entity->GetComponent<VendorComponent>();
|
|
||||||
if (vendorComponent) {
|
|
||||||
vendorComponent->Buy(player, item, count);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle buying achievement items
|
auto* propertyVendorComponent = static_cast<PropertyVendorComponent*>(entity->GetComponent(eReplicaComponentType::PROPERTY_VENDOR));
|
||||||
auto* achievementVendorComponent = entity->GetComponent<AchievementVendorComponent>();
|
|
||||||
if (achievementVendorComponent) {
|
|
||||||
achievementVendorComponent->Buy(player, item, count);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle buying properties
|
if (propertyVendorComponent != nullptr) {
|
||||||
auto* propertyVendorComponent = entity->GetComponent<PropertyVendorComponent>();
|
|
||||||
if (propertyVendorComponent) {
|
|
||||||
propertyVendorComponent->OnBuyFromVendor(player, bConfirmed, item, count);
|
propertyVendorComponent->OnBuyFromVendor(player, bConfirmed, item, count);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto isCommendationVendor = entity->GetLOT() == 13806;
|
||||||
|
|
||||||
|
auto* vend = entity->GetComponent<VendorComponent>();
|
||||||
|
if (!vend && !isCommendationVendor) return;
|
||||||
|
|
||||||
|
auto* inv = player->GetComponent<InventoryComponent>();
|
||||||
|
if (!inv) return;
|
||||||
|
|
||||||
|
if (!isCommendationVendor && !vend->SellsItem(item)) {
|
||||||
|
LOG("User %llu %s tried to buy an item %i from a vendor when they do not sell said item", player->GetObjectID(), user->GetUsername().c_str(), item);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CDComponentsRegistryTable* compRegistryTable = CDClientManager::GetTable<CDComponentsRegistryTable>();
|
||||||
|
CDItemComponentTable* itemComponentTable = CDClientManager::GetTable<CDItemComponentTable>();
|
||||||
|
|
||||||
|
int itemCompID = compRegistryTable->GetByIDAndType(item, eReplicaComponentType::ITEM);
|
||||||
|
CDItemComponent itemComp = itemComponentTable->GetItemComponentByID(itemCompID);
|
||||||
|
|
||||||
|
Character* character = player->GetCharacter();
|
||||||
|
if (!character) return;
|
||||||
|
|
||||||
|
// Extra currency that needs to be deducted in case of crafting
|
||||||
|
auto craftingCurrencies = CDItemComponentTable::ParseCraftingCurrencies(itemComp);
|
||||||
|
for (const auto& craftingCurrency : craftingCurrencies) {
|
||||||
|
inv->RemoveItem(craftingCurrency.first, craftingCurrency.second * count);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isCommendationVendor) {
|
||||||
|
if (itemComp.commendationLOT != 13763) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* missionComponent = player->GetComponent<MissionComponent>();
|
||||||
|
|
||||||
|
if (missionComponent == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOT tokenId = -1;
|
||||||
|
|
||||||
|
if (missionComponent->GetMissionState(545) == eMissionState::COMPLETE) tokenId = 8318; // "Assembly Token"
|
||||||
|
if (missionComponent->GetMissionState(556) == eMissionState::COMPLETE) tokenId = 8321; // "Venture League Token"
|
||||||
|
if (missionComponent->GetMissionState(567) == eMissionState::COMPLETE) tokenId = 8319; // "Sentinels Token"
|
||||||
|
if (missionComponent->GetMissionState(578) == eMissionState::COMPLETE) tokenId = 8320; // "Paradox Token"
|
||||||
|
|
||||||
|
const uint32_t altCurrencyCost = itemComp.commendationCost * count;
|
||||||
|
|
||||||
|
if (inv->GetLotCount(tokenId) < altCurrencyCost) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
inv->RemoveItem(tokenId, altCurrencyCost);
|
||||||
|
|
||||||
|
inv->AddItem(item, count, eLootSourceType::VENDOR);
|
||||||
|
} else {
|
||||||
|
float buyScalar = vend->GetBuyScalar();
|
||||||
|
|
||||||
|
const auto coinCost = static_cast<uint32_t>(std::floor((itemComp.baseValue * buyScalar) * count));
|
||||||
|
|
||||||
|
if (character->GetCoins() < coinCost) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Inventory::IsValidItem(itemComp.currencyLOT)) {
|
||||||
|
const uint32_t altCurrencyCost = std::floor(itemComp.altCurrencyCost * buyScalar) * count;
|
||||||
|
|
||||||
|
if (inv->GetLotCount(itemComp.currencyLOT) < altCurrencyCost) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
inv->RemoveItem(itemComp.currencyLOT, altCurrencyCost);
|
||||||
|
}
|
||||||
|
|
||||||
|
character->SetCoins(character->GetCoins() - (coinCost), eLootSourceType::VENDOR);
|
||||||
|
inv->AddItem(item, count, eLootSourceType::VENDOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
GameMessages::SendVendorTransactionResult(entity, sysAddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameMessages::HandleSellToVendor(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) {
|
void GameMessages::HandleSellToVendor(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) {
|
||||||
@@ -4719,10 +4785,7 @@ void GameMessages::HandleSellToVendor(RakNet::BitStream* inStream, Entity* entit
|
|||||||
CDItemComponent itemComp = itemComponentTable->GetItemComponentByID(itemCompID);
|
CDItemComponent itemComp = itemComponentTable->GetItemComponentByID(itemCompID);
|
||||||
|
|
||||||
// Items with a base value of 0 or max int are special items that should not be sold if they're not sub items
|
// Items with a base value of 0 or max int are special items that should not be sold if they're not sub items
|
||||||
if (itemComp.baseValue == 0 || itemComp.baseValue == UINT_MAX) {
|
if (itemComp.baseValue == 0 || itemComp.baseValue == UINT_MAX) return;
|
||||||
GameMessages::SendVendorTransactionResult(entity, sysAddr, eVendorTransactionResult::SELL_FAIL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
float sellScalar = vend->GetSellScalar();
|
float sellScalar = vend->GetSellScalar();
|
||||||
if (Inventory::IsValidItem(itemComp.currencyLOT)) {
|
if (Inventory::IsValidItem(itemComp.currencyLOT)) {
|
||||||
@@ -4730,9 +4793,11 @@ void GameMessages::HandleSellToVendor(RakNet::BitStream* inStream, Entity* entit
|
|||||||
inv->AddItem(itemComp.currencyLOT, std::floor(altCurrency), eLootSourceType::VENDOR); // Return alt currencies like faction tokens.
|
inv->AddItem(itemComp.currencyLOT, std::floor(altCurrency), eLootSourceType::VENDOR); // Return alt currencies like faction tokens.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//inv->RemoveItem(count, -1, iObjID);
|
||||||
inv->MoveItemToInventory(item, eInventoryType::VENDOR_BUYBACK, count, true, false, true);
|
inv->MoveItemToInventory(item, eInventoryType::VENDOR_BUYBACK, count, true, false, true);
|
||||||
character->SetCoins(std::floor(character->GetCoins() + (static_cast<uint32_t>(itemComp.baseValue * sellScalar) * count)), eLootSourceType::VENDOR);
|
character->SetCoins(std::floor(character->GetCoins() + (static_cast<uint32_t>(itemComp.baseValue * sellScalar) * count)), eLootSourceType::VENDOR);
|
||||||
GameMessages::SendVendorTransactionResult(entity, sysAddr, eVendorTransactionResult::SELL_SUCCESS);
|
//Game::entityManager->SerializeEntity(player); // so inventory updates
|
||||||
|
GameMessages::SendVendorTransactionResult(entity, sysAddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameMessages::HandleBuybackFromVendor(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) {
|
void GameMessages::HandleBuybackFromVendor(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) {
|
||||||
@@ -4774,16 +4839,16 @@ void GameMessages::HandleBuybackFromVendor(RakNet::BitStream* inStream, Entity*
|
|||||||
const auto cost = static_cast<uint32_t>(std::floor(((itemComp.baseValue * sellScalar) * count)));
|
const auto cost = static_cast<uint32_t>(std::floor(((itemComp.baseValue * sellScalar) * count)));
|
||||||
|
|
||||||
if (character->GetCoins() < cost) {
|
if (character->GetCoins() < cost) {
|
||||||
GameMessages::SendVendorTransactionResult(entity, sysAddr, eVendorTransactionResult::PURCHASE_FAIL);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Inventory::IsValidItem(itemComp.currencyLOT)) {
|
if (Inventory::IsValidItem(itemComp.currencyLOT)) {
|
||||||
const uint32_t altCurrencyCost = std::floor(itemComp.altCurrencyCost * sellScalar) * count;
|
const uint32_t altCurrencyCost = std::floor(itemComp.altCurrencyCost * sellScalar) * count;
|
||||||
|
|
||||||
if (inv->GetLotCount(itemComp.currencyLOT) < altCurrencyCost) {
|
if (inv->GetLotCount(itemComp.currencyLOT) < altCurrencyCost) {
|
||||||
GameMessages::SendVendorTransactionResult(entity, sysAddr, eVendorTransactionResult::PURCHASE_FAIL);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
inv->RemoveItem(itemComp.currencyLOT, altCurrencyCost);
|
inv->RemoveItem(itemComp.currencyLOT, altCurrencyCost);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4791,7 +4856,7 @@ void GameMessages::HandleBuybackFromVendor(RakNet::BitStream* inStream, Entity*
|
|||||||
inv->MoveItemToInventory(item, Inventory::FindInventoryTypeForLot(item->GetLot()), count, true, false);
|
inv->MoveItemToInventory(item, Inventory::FindInventoryTypeForLot(item->GetLot()), count, true, false);
|
||||||
character->SetCoins(character->GetCoins() - cost, eLootSourceType::VENDOR);
|
character->SetCoins(character->GetCoins() - cost, eLootSourceType::VENDOR);
|
||||||
//Game::entityManager->SerializeEntity(player); // so inventory updates
|
//Game::entityManager->SerializeEntity(player); // so inventory updates
|
||||||
GameMessages::SendVendorTransactionResult(entity, sysAddr, eVendorTransactionResult::PURCHASE_SUCCESS);
|
GameMessages::SendVendorTransactionResult(entity, sysAddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameMessages::HandleParseChatMessage(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) {
|
void GameMessages::HandleParseChatMessage(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) {
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ enum class eUseItemResponse : uint32_t;
|
|||||||
enum class eQuickBuildFailReason : uint32_t;
|
enum class eQuickBuildFailReason : uint32_t;
|
||||||
enum class eQuickBuildState : uint32_t;
|
enum class eQuickBuildState : uint32_t;
|
||||||
enum class BehaviorSlot : int32_t;
|
enum class BehaviorSlot : int32_t;
|
||||||
enum class eVendorTransactionResult : uint32_t;
|
|
||||||
|
|
||||||
namespace GameMessages {
|
namespace GameMessages {
|
||||||
class PropertyDataMessage;
|
class PropertyDataMessage;
|
||||||
@@ -136,7 +135,7 @@ namespace GameMessages {
|
|||||||
|
|
||||||
void SendVendorOpenWindow(Entity* entity, const SystemAddress& sysAddr);
|
void SendVendorOpenWindow(Entity* entity, const SystemAddress& sysAddr);
|
||||||
void SendVendorStatusUpdate(Entity* entity, const SystemAddress& sysAddr, bool bUpdateOnly = false);
|
void SendVendorStatusUpdate(Entity* entity, const SystemAddress& sysAddr, bool bUpdateOnly = false);
|
||||||
void SendVendorTransactionResult(Entity* entity, const SystemAddress& sysAddr, eVendorTransactionResult result);
|
void SendVendorTransactionResult(Entity* entity, const SystemAddress& sysAddr);
|
||||||
|
|
||||||
void SendRemoveItemFromInventory(Entity* entity, const SystemAddress& sysAddr, LWOOBJID iObjID, LOT templateID, int inventoryType, uint32_t stackCount, uint32_t stackRemaining);
|
void SendRemoveItemFromInventory(Entity* entity, const SystemAddress& sysAddr, LWOOBJID iObjID, LOT templateID, int inventoryType, uint32_t stackCount, uint32_t stackRemaining);
|
||||||
void SendConsumeClientItem(Entity* entity, bool bSuccess, LWOOBJID item);
|
void SendConsumeClientItem(Entity* entity, bool bSuccess, LWOOBJID item);
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ void AuthPackets::SendHandshake(dServer* server, const SystemAddress& sysAddr, c
|
|||||||
if (serverType == ServerType::Auth) bitStream.Write(ServiceId::Auth);
|
if (serverType == ServerType::Auth) bitStream.Write(ServiceId::Auth);
|
||||||
else if (serverType == ServerType::World) bitStream.Write(ServiceId::World);
|
else if (serverType == ServerType::World) bitStream.Write(ServiceId::World);
|
||||||
else bitStream.Write(ServiceId::General);
|
else bitStream.Write(ServiceId::General);
|
||||||
bitStream.Write<uint64_t>(215523405360);
|
bitStream.Write<uint32_t>(774909490);
|
||||||
|
|
||||||
server->Send(&bitStream, sysAddr, false);
|
server->Send(&bitStream, sysAddr, false);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user