diff --git a/dCommon/AMFDeserialize.cpp b/dCommon/AMFDeserialize.cpp index df4a7cb6e..9eee1f120 100644 --- a/dCommon/AMFDeserialize.cpp +++ b/dCommon/AMFDeserialize.cpp @@ -1,77 +1,81 @@ #include "AMFDeserialize.h" -#include "AMFFormat.h" +#include + +#include "Amf3.h" /** * AMF3 Reference document https://rtmp.veriskope.com/pdf/amf3-file-format-spec.pdf * AMF3 Deserializer written by EmosewaMC */ -AMFValue* AMFDeserialize::Read(RakNet::BitStream* inStream) { +AMFBaseValue* AMFDeserialize::Read(RakNet::BitStream* inStream) { if (!inStream) return nullptr; - AMFValue* returnValue = nullptr; + AMFBaseValue* returnValue = nullptr; // Read in the value type from the bitStream - int8_t marker; - inStream->Read(marker); + uint8_t i; + inStream->Read(i); + if (i > static_cast(eAmf::Dictionary)) return nullptr; + eAmf marker = static_cast(i); // Based on the typing, create the value associated with that and return the base value class switch (marker) { - case AMFValueType::AMFUndefined: { - returnValue = new AMFUndefinedValue(); + case eAmf::Undefined: { + returnValue = new AMFBaseValue(); break; } - case AMFValueType::AMFNull: { + case eAmf::Null: { returnValue = new AMFNullValue(); break; } - case AMFValueType::AMFFalse: { - returnValue = new AMFFalseValue(); + case eAmf::False: { + returnValue = new AMFBoolValue(false); break; } - case AMFValueType::AMFTrue: { - returnValue = new AMFTrueValue(); + case eAmf::True: { + returnValue = new AMFBoolValue(true); break; } - case AMFValueType::AMFInteger: { + case eAmf::Integer: { returnValue = ReadAmfInteger(inStream); break; } - case AMFValueType::AMFDouble: { + case eAmf::Double: { returnValue = ReadAmfDouble(inStream); break; } - case AMFValueType::AMFString: { + case eAmf::String: { returnValue = ReadAmfString(inStream); break; } - case AMFValueType::AMFArray: { + case eAmf::Array: { returnValue = ReadAmfArray(inStream); break; } - // TODO We do not need these values, but if someone wants to implement them - // then please do so and add the corresponding unit tests. - case AMFValueType::AMFXMLDoc: - case AMFValueType::AMFDate: - case AMFValueType::AMFObject: - case AMFValueType::AMFXML: - case AMFValueType::AMFByteArray: - case AMFValueType::AMFVectorInt: - case AMFValueType::AMFVectorUInt: - case AMFValueType::AMFVectorDouble: - case AMFValueType::AMFVectorObject: - case AMFValueType::AMFDictionary: { - throw static_cast(marker); + // These values are unimplemented in the live client and will remain unimplemented + // unless someone modifies the client to allow serializing of these values. + case eAmf::XMLDoc: + case eAmf::Date: + case eAmf::Object: + case eAmf::XML: + case eAmf::ByteArray: + case eAmf::VectorInt: + case eAmf::VectorUInt: + case eAmf::VectorDouble: + case eAmf::VectorObject: + case eAmf::Dictionary: { + throw marker; break; } default: - throw static_cast(marker); + throw std::invalid_argument("Invalid AMF3 marker" + std::to_string(static_cast(marker))); break; } return returnValue; @@ -99,7 +103,7 @@ uint32_t AMFDeserialize::ReadU29(RakNet::BitStream* inStream) { return actualNumber; } -std::string AMFDeserialize::ReadString(RakNet::BitStream* inStream) { +const std::string AMFDeserialize::ReadString(RakNet::BitStream* inStream) { auto length = ReadU29(inStream); // Check if this is a reference bool isReference = length % 2 == 1; @@ -113,48 +117,39 @@ std::string AMFDeserialize::ReadString(RakNet::BitStream* inStream) { return value; } else { // Length is a reference to a previous index - use that as the read in value - return accessedElements[length]; + return accessedElements.at(length); } } -AMFValue* AMFDeserialize::ReadAmfDouble(RakNet::BitStream* inStream) { - auto doubleValue = new AMFDoubleValue(); +AMFBaseValue* AMFDeserialize::ReadAmfDouble(RakNet::BitStream* inStream) { double value; inStream->Read(value); - doubleValue->SetDoubleValue(value); - return doubleValue; + return new AMFDoubleValue(value); } -AMFValue* AMFDeserialize::ReadAmfArray(RakNet::BitStream* inStream) { +AMFBaseValue* AMFDeserialize::ReadAmfArray(RakNet::BitStream* inStream) { auto arrayValue = new AMFArrayValue(); // Read size of dense array auto sizeOfDenseArray = (ReadU29(inStream) >> 1); - - // Then read Key'd portion + // Then read associative portion while (true) { auto key = ReadString(inStream); - // No more values when we encounter an empty string + // No more associative values when we encounter an empty string key if (key.size() == 0) break; - arrayValue->InsertValue(key, Read(inStream)); + arrayValue->Insert(key, Read(inStream)); } - // Finally read dense portion for (uint32_t i = 0; i < sizeOfDenseArray; i++) { - arrayValue->PushBackValue(Read(inStream)); + arrayValue->Insert(i, Read(inStream)); } - return arrayValue; } -AMFValue* AMFDeserialize::ReadAmfString(RakNet::BitStream* inStream) { - auto stringValue = new AMFStringValue(); - stringValue->SetStringValue(ReadString(inStream)); - return stringValue; +AMFBaseValue* AMFDeserialize::ReadAmfString(RakNet::BitStream* inStream) { + return new AMFStringValue(ReadString(inStream)); } -AMFValue* AMFDeserialize::ReadAmfInteger(RakNet::BitStream* inStream) { - auto integerValue = new AMFIntegerValue(); - integerValue->SetIntegerValue(ReadU29(inStream)); - return integerValue; +AMFBaseValue* AMFDeserialize::ReadAmfInteger(RakNet::BitStream* inStream) { + return new AMFIntValue(ReadU29(inStream)); } diff --git a/dCommon/AMFDeserialize.h b/dCommon/AMFDeserialize.h index a49cdcd2c..5e2729eb4 100644 --- a/dCommon/AMFDeserialize.h +++ b/dCommon/AMFDeserialize.h @@ -5,7 +5,8 @@ #include #include -class AMFValue; +class AMFBaseValue; + class AMFDeserialize { public: /** @@ -14,7 +15,7 @@ class AMFDeserialize { * @param inStream inStream to read value from. * @return Returns an AMFValue with all the information from the bitStream in it. */ - AMFValue* Read(RakNet::BitStream* inStream); + AMFBaseValue* Read(RakNet::BitStream* inStream); private: /** * @brief Private method to read a U29 integer from a bitstream @@ -30,7 +31,7 @@ class AMFDeserialize { * @param inStream bitStream to read data from * @return The read string */ - std::string ReadString(RakNet::BitStream* inStream); + const std::string ReadString(RakNet::BitStream* inStream); /** * @brief Read an AMFDouble value from a bitStream @@ -38,7 +39,7 @@ class AMFDeserialize { * @param inStream bitStream to read data from * @return Double value represented as an AMFValue */ - AMFValue* ReadAmfDouble(RakNet::BitStream* inStream); + AMFBaseValue* ReadAmfDouble(RakNet::BitStream* inStream); /** * @brief Read an AMFArray from a bitStream @@ -46,7 +47,7 @@ class AMFDeserialize { * @param inStream bitStream to read data from * @return Array value represented as an AMFValue */ - AMFValue* ReadAmfArray(RakNet::BitStream* inStream); + AMFBaseValue* ReadAmfArray(RakNet::BitStream* inStream); /** * @brief Read an AMFString from a bitStream @@ -54,7 +55,7 @@ class AMFDeserialize { * @param inStream bitStream to read data from * @return String value represented as an AMFValue */ - AMFValue* ReadAmfString(RakNet::BitStream* inStream); + AMFBaseValue* ReadAmfString(RakNet::BitStream* inStream); /** * @brief Read an AMFInteger from a bitStream @@ -62,7 +63,7 @@ class AMFDeserialize { * @param inStream bitStream to read data from * @return Integer value represented as an AMFValue */ - AMFValue* ReadAmfInteger(RakNet::BitStream* inStream); + AMFBaseValue* ReadAmfInteger(RakNet::BitStream* inStream); /** * List of strings read so far saved to be read by reference. diff --git a/dCommon/AMFFormat.cpp b/dCommon/AMFFormat.cpp deleted file mode 100644 index 4407b29cb..000000000 --- a/dCommon/AMFFormat.cpp +++ /dev/null @@ -1,156 +0,0 @@ -#include "AMFFormat.h" - -// AMFInteger -void AMFIntegerValue::SetIntegerValue(uint32_t value) { - this->value = value; -} - -uint32_t AMFIntegerValue::GetIntegerValue() { - return this->value; -} - -// AMFDouble -void AMFDoubleValue::SetDoubleValue(double value) { - this->value = value; -} - -double AMFDoubleValue::GetDoubleValue() { - return this->value; -} - -// AMFString -void AMFStringValue::SetStringValue(const std::string& value) { - this->value = value; -} - -std::string AMFStringValue::GetStringValue() { - return this->value; -} - -// AMFXMLDoc -void AMFXMLDocValue::SetXMLDocValue(const std::string& value) { - this->xmlData = value; -} - -std::string AMFXMLDocValue::GetXMLDocValue() { - return this->xmlData; -} - -// AMFDate -void AMFDateValue::SetDateValue(uint64_t value) { - this->millisecondTimestamp = value; -} - -uint64_t AMFDateValue::GetDateValue() { - return this->millisecondTimestamp; -} - -// AMFArray Insert Value -void AMFArrayValue::InsertValue(const std::string& key, AMFValue* value) { - this->associative.insert(std::make_pair(key, value)); -} - -// AMFArray Remove Value -void AMFArrayValue::RemoveValue(const std::string& key) { - _AMFArrayMap_::iterator it = this->associative.find(key); - if (it != this->associative.end()) { - this->associative.erase(it); - } -} - -// AMFArray Get Associative Iterator Begin -_AMFArrayMap_::iterator AMFArrayValue::GetAssociativeIteratorValueBegin() { - return this->associative.begin(); -} - -// AMFArray Get Associative Iterator End -_AMFArrayMap_::iterator AMFArrayValue::GetAssociativeIteratorValueEnd() { - return this->associative.end(); -} - -// AMFArray Push Back Value -void AMFArrayValue::PushBackValue(AMFValue* value) { - this->dense.push_back(value); -} - -// AMFArray Pop Back Value -void AMFArrayValue::PopBackValue() { - this->dense.pop_back(); -} - -// AMFArray Get Dense List Size -uint32_t AMFArrayValue::GetDenseValueSize() { - return (uint32_t)this->dense.size(); -} - -// AMFArray Get Dense Iterator Begin -_AMFArrayList_::iterator AMFArrayValue::GetDenseIteratorBegin() { - return this->dense.begin(); -} - -// AMFArray Get Dense Iterator End -_AMFArrayList_::iterator AMFArrayValue::GetDenseIteratorEnd() { - return this->dense.end(); -} - -AMFArrayValue::~AMFArrayValue() { - for (auto valueToDelete : GetDenseArray()) { - if (valueToDelete) delete valueToDelete; - } - for (auto valueToDelete : GetAssociativeMap()) { - if (valueToDelete.second) delete valueToDelete.second; - } -} - -// AMFObject Constructor -AMFObjectValue::AMFObjectValue(std::vector> traits) { - this->traits.reserve(traits.size()); - std::vector>::iterator it = traits.begin(); - while (it != traits.end()) { - this->traits.insert(std::make_pair(it->first, std::make_pair(it->second, new AMFNullValue()))); - it++; - } -} - -// AMFObject Set Value -void AMFObjectValue::SetTraitValue(const std::string& trait, AMFValue* value) { - if (value) { - _AMFObjectTraits_::iterator it = this->traits.find(trait); - if (it != this->traits.end()) { - if (it->second.first == value->GetValueType()) { - it->second.second = value; - } - } - } -} - -// AMFObject Get Value -AMFValue* AMFObjectValue::GetTraitValue(const std::string& trait) { - _AMFObjectTraits_::iterator it = this->traits.find(trait); - if (it != this->traits.end()) { - return it->second.second; - } - - return nullptr; -} - -// AMFObject Get Trait Iterator Begin -_AMFObjectTraits_::iterator AMFObjectValue::GetTraitsIteratorBegin() { - return this->traits.begin(); -} - -// AMFObject Get Trait Iterator End -_AMFObjectTraits_::iterator AMFObjectValue::GetTraitsIteratorEnd() { - return this->traits.end(); -} - -// AMFObject Get Trait Size -uint32_t AMFObjectValue::GetTraitArrayCount() { - return (uint32_t)this->traits.size(); -} - -AMFObjectValue::~AMFObjectValue() { - for (auto valueToDelete = GetTraitsIteratorBegin(); valueToDelete != GetTraitsIteratorEnd(); valueToDelete++) { - if (valueToDelete->second.second) delete valueToDelete->second.second; - } -} diff --git a/dCommon/AMFFormat.h b/dCommon/AMFFormat.h deleted file mode 100644 index 6e479ef6b..000000000 --- a/dCommon/AMFFormat.h +++ /dev/null @@ -1,413 +0,0 @@ -#pragma once - -// Custom Classes -#include "dCommonVars.h" - -// C++ -#include -#include - -/*! - \file AMFFormat.hpp - \brief A class for managing AMF values - */ - -class AMFValue; // Forward declaration - -// Definitions -#define _AMFArrayMap_ std::unordered_map -#define _AMFArrayList_ std::vector - -#define _AMFObjectTraits_ std::unordered_map> -#define _AMFObjectDynamicTraits_ std::unordered_map - -//! An enum for each AMF value type -enum AMFValueType : unsigned char { - AMFUndefined = 0x00, //!< An undefined AMF Value - AMFNull = 0x01, //!< A null AMF value - AMFFalse = 0x02, //!< A false AMF value - AMFTrue = 0x03, //!< A true AMF value - AMFInteger = 0x04, //!< An integer AMF value - AMFDouble = 0x05, //!< A double AMF value - AMFString = 0x06, //!< A string AMF value - AMFXMLDoc = 0x07, //!< An XML Doc AMF value - AMFDate = 0x08, //!< A date AMF value - AMFArray = 0x09, //!< An array AMF value - AMFObject = 0x0A, //!< An object AMF value - AMFXML = 0x0B, //!< An XML AMF value - AMFByteArray = 0x0C, //!< A byte array AMF value - AMFVectorInt = 0x0D, //!< An integer vector AMF value - AMFVectorUInt = 0x0E, //!< An unsigned integer AMF value - AMFVectorDouble = 0x0F, //!< A double vector AMF value - AMFVectorObject = 0x10, //!< An object vector AMF value - AMFDictionary = 0x11 //!< A dictionary AMF value -}; - -//! An enum for the object value types -enum AMFObjectValueType : unsigned char { - AMFObjectAnonymous = 0x01, - AMFObjectTyped = 0x02, - AMFObjectDynamic = 0x03, - AMFObjectExternalizable = 0x04 -}; - -//! The base AMF value class -class AMFValue { -public: - //! Returns the AMF value type - /*! - \return The AMF value type - */ - virtual AMFValueType GetValueType() = 0; - virtual ~AMFValue() {}; -}; - -//! A typedef for a pointer to an AMF value -typedef AMFValue* NDGFxValue; - - -// The various AMF value types - -//! The undefined value AMF type -class AMFUndefinedValue : public AMFValue { -private: - //! Returns the AMF value type - /*! - \return The AMF value type - */ - AMFValueType GetValueType() { return ValueType; } -public: - static const AMFValueType ValueType = AMFUndefined; -}; - -//! The null value AMF type -class AMFNullValue : public AMFValue { -private: - //! Returns the AMF value type - /*! - \return The AMF value type - */ - AMFValueType GetValueType() { return ValueType; } -public: - static const AMFValueType ValueType = AMFNull; -}; - -//! The false value AMF type -class AMFFalseValue : public AMFValue { -private: - //! Returns the AMF value type - /*! - \return The AMF value type - */ - AMFValueType GetValueType() { return ValueType; } -public: - static const AMFValueType ValueType = AMFFalse; -}; - -//! The true value AMF type -class AMFTrueValue : public AMFValue { -private: - //! Returns the AMF value type - /*! - \return The AMF value type - */ - AMFValueType GetValueType() { return ValueType; } -public: - static const AMFValueType ValueType = AMFTrue; -}; - -//! The integer value AMF type -class AMFIntegerValue : public AMFValue { -private: - uint32_t value; //!< The value of the AMF type - - //! Returns the AMF value type - /*! - \return The AMF value type - */ - AMFValueType GetValueType() { return ValueType; } - -public: - static const AMFValueType ValueType = AMFInteger; - //! Sets the integer value - /*! - \param value The value to set - */ - void SetIntegerValue(uint32_t value); - - //! Gets the integer value - /*! - \return The integer value - */ - uint32_t GetIntegerValue(); -}; - -//! The double value AMF type -class AMFDoubleValue : public AMFValue { -private: - double value; //!< The value of the AMF type - - //! Returns the AMF value type - /*! - \return The AMF value type - */ - AMFValueType GetValueType() { return ValueType; } - -public: - static const AMFValueType ValueType = AMFDouble; - //! Sets the double value - /*! - \param value The value to set to - */ - void SetDoubleValue(double value); - - //! Gets the double value - /*! - \return The double value - */ - double GetDoubleValue(); -}; - -//! The string value AMF type -class AMFStringValue : public AMFValue { -private: - std::string value; //!< The value of the AMF type - - //! Returns the AMF value type - /*! - \return The AMF value type - */ - AMFValueType GetValueType() { return ValueType; } - -public: - static const AMFValueType ValueType = AMFString; - //! Sets the string value - /*! - \param value The string value to set to - */ - void SetStringValue(const std::string& value); - - //! Gets the string value - /*! - \return The string value - */ - std::string GetStringValue(); -}; - -//! The XML doc value AMF type -class AMFXMLDocValue : public AMFValue { -private: - std::string xmlData; //!< The value of the AMF type - - //! Returns the AMF value type - /*! - \return The AMF value type - */ - AMFValueType GetValueType() { return ValueType; } - -public: - static const AMFValueType ValueType = AMFXMLDoc; - //! Sets the XML Doc value - /*! - \param value The value to set to - */ - void SetXMLDocValue(const std::string& value); - - //! Gets the XML Doc value - /*! - \return The XML Doc value - */ - std::string GetXMLDocValue(); -}; - -//! The date value AMF type -class AMFDateValue : public AMFValue { -private: - uint64_t millisecondTimestamp; //!< The time in milliseconds since the ephoch - - //! Returns the AMF value type - /*! - \return The AMF value type - */ - AMFValueType GetValueType() { return ValueType; } - -public: - static const AMFValueType ValueType = AMFDate; - //! Sets the date time - /*! - \param value The value to set to - */ - void SetDateValue(uint64_t value); - - //! Gets the date value - /*! - \return The date value in milliseconds since the epoch - */ - uint64_t GetDateValue(); -}; - -//! The array value AMF type -// This object will manage it's own memory map and list. Do not delete its values. -class AMFArrayValue : public AMFValue { -private: - _AMFArrayMap_ associative; //!< The array map (associative part) - _AMFArrayList_ dense; //!< The array list (dense part) - - //! Returns the AMF value type - /*! - \return The AMF value type - */ - AMFValueType GetValueType() override { return ValueType; } - -public: - static const AMFValueType ValueType = AMFArray; - - ~AMFArrayValue() override; - //! Inserts an item into the array map for a specific key - /*! - \param key The key to set - \param value The value to add - */ - void InsertValue(const std::string& key, AMFValue* value); - - //! Removes an item for a specific key - /*! - \param key The key to remove - */ - void RemoveValue(const std::string& key); - - //! Finds an AMF value - /*! - \return The AMF value if found, nullptr otherwise - */ - template - T* FindValue(const std::string& key) const { - _AMFArrayMap_::const_iterator it = this->associative.find(key); - if (it != this->associative.end() && T::ValueType == it->second->GetValueType()) { - return dynamic_cast(it->second); - } - - return nullptr; - }; - - //! Returns where the associative iterator begins - /*! - \return Where the array map iterator begins - */ - _AMFArrayMap_::iterator GetAssociativeIteratorValueBegin(); - - //! Returns where the associative iterator ends - /*! - \return Where the array map iterator ends - */ - _AMFArrayMap_::iterator GetAssociativeIteratorValueEnd(); - - //! Pushes back a value into the array list - /*! - \param value The value to push back - */ - void PushBackValue(AMFValue* value); - - //! Pops back the last value in the array list - void PopBackValue(); - - //! Gets the count of the dense list - /*! - \return The dense list size - */ - uint32_t GetDenseValueSize(); - - //! Gets a specific value from the list for the specified index - /*! - \param index The index to get - */ - template - T* GetValueAt(uint32_t index) { - if (index >= this->dense.size()) return nullptr; - AMFValue* foundValue = this->dense.at(index); - return T::ValueType == foundValue->GetValueType() ? dynamic_cast(foundValue) : nullptr; - }; - - //! Returns where the dense iterator begins - /*! - \return Where the iterator begins - */ - _AMFArrayList_::iterator GetDenseIteratorBegin(); - - //! Returns where the dense iterator ends - /*! - \return Where the iterator ends - */ - _AMFArrayList_::iterator GetDenseIteratorEnd(); - - //! Returns the associative map - /*! - \return The associative map - */ - _AMFArrayMap_ GetAssociativeMap() { return this->associative; }; - - //! Returns the dense array - /*! - \return The dense array - */ - _AMFArrayList_ GetDenseArray() { return this->dense; }; -}; - -//! The anonymous object value AMF type -class AMFObjectValue : public AMFValue { -private: - _AMFObjectTraits_ traits; //!< The object traits - - //! Returns the AMF value type - /*! - \return The AMF value type - */ - AMFValueType GetValueType() override { return ValueType; } - ~AMFObjectValue() override; - -public: - static const AMFValueType ValueType = AMFObject; - //! Constructor - /*! - \param traits The traits to set - */ - AMFObjectValue(std::vector> traits); - - //! Gets the object value type - /*! - \return The object value type - */ - virtual AMFObjectValueType GetObjectValueType() { return AMFObjectAnonymous; } - - //! Sets the value of a trait - /*! - \param trait The trait to set the value for - \param value The AMF value to set - */ - void SetTraitValue(const std::string& trait, AMFValue* value); - - //! Gets a trait value - /*! - \param trait The trait to get the value for - \return The trait value - */ - AMFValue* GetTraitValue(const std::string& trait); - - //! Gets the beginning of the object traits iterator - /*! - \return The AMF trait array iterator begin - */ - _AMFObjectTraits_::iterator GetTraitsIteratorBegin(); - - //! Gets the end of the object traits iterator - /*! - \return The AMF trait array iterator begin - */ - _AMFObjectTraits_::iterator GetTraitsIteratorEnd(); - - //! Gets the amount of traits - /*! - \return The amount of traits - */ - uint32_t GetTraitArrayCount(); -}; diff --git a/dCommon/AMFFormat_BitStream.cpp b/dCommon/AMFFormat_BitStream.cpp deleted file mode 100644 index dcb9197dc..000000000 --- a/dCommon/AMFFormat_BitStream.cpp +++ /dev/null @@ -1,259 +0,0 @@ -#include "AMFFormat_BitStream.h" - -// Writes an AMFValue pointer to a RakNet::BitStream -template<> -void RakNet::BitStream::Write(AMFValue* value) { - if (value != nullptr) { - AMFValueType type = value->GetValueType(); - - switch (type) { - case AMFUndefined: { - AMFUndefinedValue* v = (AMFUndefinedValue*)value; - this->Write(*v); - break; - } - - case AMFNull: { - AMFNullValue* v = (AMFNullValue*)value; - this->Write(*v); - break; - } - - case AMFFalse: { - AMFFalseValue* v = (AMFFalseValue*)value; - this->Write(*v); - break; - } - - case AMFTrue: { - AMFTrueValue* v = (AMFTrueValue*)value; - this->Write(*v); - break; - } - - case AMFInteger: { - AMFIntegerValue* v = (AMFIntegerValue*)value; - this->Write(*v); - break; - } - - case AMFDouble: { - AMFDoubleValue* v = (AMFDoubleValue*)value; - this->Write(*v); - break; - } - - case AMFString: { - AMFStringValue* v = (AMFStringValue*)value; - this->Write(*v); - break; - } - - case AMFXMLDoc: { - AMFXMLDocValue* v = (AMFXMLDocValue*)value; - this->Write(*v); - break; - } - - case AMFDate: { - AMFDateValue* v = (AMFDateValue*)value; - this->Write(*v); - break; - } - - case AMFArray: { - this->Write((AMFArrayValue*)value); - break; - } - case AMFObject: - case AMFXML: - case AMFByteArray: - case AMFVectorInt: - case AMFVectorUInt: - case AMFVectorDouble: - case AMFVectorObject: - case AMFDictionary: - break; - } - } -} - -/** - * A private function to write an value to a RakNet::BitStream - * RakNet writes in the correct byte order - do not reverse this. - */ -void WriteUInt29(RakNet::BitStream* bs, uint32_t v) { - unsigned char b4 = (unsigned char)v; - if (v < 0x00200000) { - b4 = b4 & 0x7F; - if (v > 0x7F) { - unsigned char b3; - v = v >> 7; - b3 = ((unsigned char)(v)) | 0x80; - if (v > 0x7F) { - unsigned char b2; - v = v >> 7; - b2 = ((unsigned char)(v)) | 0x80; - bs->Write(b2); - } - - bs->Write(b3); - } - } else { - unsigned char b1; - unsigned char b2; - unsigned char b3; - - v = v >> 8; - b3 = ((unsigned char)(v)) | 0x80; - v = v >> 7; - b2 = ((unsigned char)(v)) | 0x80; - v = v >> 7; - b1 = ((unsigned char)(v)) | 0x80; - - bs->Write(b1); - bs->Write(b2); - bs->Write(b3); - } - - bs->Write(b4); -} - -/** - * Writes a flag number to a RakNet::BitStream - * RakNet writes in the correct byte order - do not reverse this. - */ -void WriteFlagNumber(RakNet::BitStream* bs, uint32_t v) { - v = (v << 1) | 0x01; - WriteUInt29(bs, v); -} - -/** - * Writes an AMFString to a RakNet::BitStream - * - * RakNet writes in the correct byte order - do not reverse this. - */ -void WriteAMFString(RakNet::BitStream* bs, const std::string& str) { - WriteFlagNumber(bs, (uint32_t)str.size()); - bs->Write(str.c_str(), (uint32_t)str.size()); -} - -/** - * Writes an U16 to a bitstream - * - * RakNet writes in the correct byte order - do not reverse this. - */ -void WriteAMFU16(RakNet::BitStream* bs, uint16_t value) { - bs->Write(value); -} - -/** - * Writes an U32 to a bitstream - * - * RakNet writes in the correct byte order - do not reverse this. - */ -void WriteAMFU32(RakNet::BitStream* bs, uint32_t value) { - bs->Write(value); -} - -/** - * Writes an U64 to a bitstream - * - * RakNet writes in the correct byte order - do not reverse this. - */ -void WriteAMFU64(RakNet::BitStream* bs, uint64_t value) { - bs->Write(value); -} - - -// Writes an AMFUndefinedValue to BitStream -template<> -void RakNet::BitStream::Write(AMFUndefinedValue value) { - this->Write(AMFUndefined); -} - -// Writes an AMFNullValue to BitStream -template<> -void RakNet::BitStream::Write(AMFNullValue value) { - this->Write(AMFNull); -} - -// Writes an AMFFalseValue to BitStream -template<> -void RakNet::BitStream::Write(AMFFalseValue value) { - this->Write(AMFFalse); -} - -// Writes an AMFTrueValue to BitStream -template<> -void RakNet::BitStream::Write(AMFTrueValue value) { - this->Write(AMFTrue); -} - -// Writes an AMFIntegerValue to BitStream -template<> -void RakNet::BitStream::Write(AMFIntegerValue value) { - this->Write(AMFInteger); - WriteUInt29(this, value.GetIntegerValue()); -} - -// Writes an AMFDoubleValue to BitStream -template<> -void RakNet::BitStream::Write(AMFDoubleValue value) { - this->Write(AMFDouble); - double d = value.GetDoubleValue(); - WriteAMFU64(this, *((unsigned long long*) & d)); -} - -// Writes an AMFStringValue to BitStream -template<> -void RakNet::BitStream::Write(AMFStringValue value) { - this->Write(AMFString); - std::string v = value.GetStringValue(); - WriteAMFString(this, v); -} - -// Writes an AMFXMLDocValue to BitStream -template<> -void RakNet::BitStream::Write(AMFXMLDocValue value) { - this->Write(AMFXMLDoc); - std::string v = value.GetXMLDocValue(); - WriteAMFString(this, v); -} - -// Writes an AMFDateValue to BitStream -template<> -void RakNet::BitStream::Write(AMFDateValue value) { - this->Write(AMFDate); - uint64_t date = value.GetDateValue(); - WriteAMFU64(this, date); -} - -// Writes an AMFArrayValue to BitStream -template<> -void RakNet::BitStream::Write(AMFArrayValue* value) { - this->Write(AMFArray); - uint32_t denseSize = value->GetDenseValueSize(); - WriteFlagNumber(this, denseSize); - - _AMFArrayMap_::iterator it = value->GetAssociativeIteratorValueBegin(); - _AMFArrayMap_::iterator end = value->GetAssociativeIteratorValueEnd(); - - while (it != end) { - WriteAMFString(this, it->first); - this->Write(it->second); - it++; - } - - this->Write(AMFNull); - - if (denseSize > 0) { - _AMFArrayList_::iterator it2 = value->GetDenseIteratorBegin(); - _AMFArrayList_::iterator end2 = value->GetDenseIteratorEnd(); - - while (it2 != end2) { - this->Write(*it2); - it2++; - } - } -} diff --git a/dCommon/AMFFormat_BitStream.h b/dCommon/AMFFormat_BitStream.h deleted file mode 100644 index caa493375..000000000 --- a/dCommon/AMFFormat_BitStream.h +++ /dev/null @@ -1,92 +0,0 @@ -#pragma once - -// Custom Classes -#include "AMFFormat.h" - -// RakNet -#include - -/*! - \file AMFFormat_BitStream.h - \brief A class that implements native writing of AMF values to RakNet::BitStream - */ - - // We are using the RakNet namespace -namespace RakNet { - //! Writes an AMFValue pointer to a RakNet::BitStream - /*! - \param value The value to write - */ - template <> - void RakNet::BitStream::Write(AMFValue* value); - - //! Writes an AMFUndefinedValue to a RakNet::BitStream - /*! - \param value The value to write - */ - template <> - void RakNet::BitStream::Write(AMFUndefinedValue value); - - //! Writes an AMFNullValue to a RakNet::BitStream - /*! - \param value The value to write - */ - template <> - void RakNet::BitStream::Write(AMFNullValue value); - - //! Writes an AMFFalseValue to a RakNet::BitStream - /*! - \param value The value to write - */ - template <> - void RakNet::BitStream::Write(AMFFalseValue value); - - //! Writes an AMFTrueValue to a RakNet::BitStream - /*! - \param value The value to write - */ - template <> - void RakNet::BitStream::Write(AMFTrueValue value); - - //! Writes an AMFIntegerValue to a RakNet::BitStream - /*! - \param value The value to write - */ - template <> - void RakNet::BitStream::Write(AMFIntegerValue value); - - //! Writes an AMFDoubleValue to a RakNet::BitStream - /*! - \param value The value to write - */ - template <> - void RakNet::BitStream::Write(AMFDoubleValue value); - - //! Writes an AMFStringValue to a RakNet::BitStream - /*! - \param value The value to write - */ - template <> - void RakNet::BitStream::Write(AMFStringValue value); - - //! Writes an AMFXMLDocValue to a RakNet::BitStream - /*! - \param value The value to write - */ - template <> - void RakNet::BitStream::Write(AMFXMLDocValue value); - - //! Writes an AMFDateValue to a RakNet::BitStream - /*! - \param value The value to write - */ - template <> - void RakNet::BitStream::Write(AMFDateValue value); - - //! Writes an AMFArrayValue to a RakNet::BitStream - /*! - \param value The value to write - */ - template <> - void RakNet::BitStream::Write(AMFArrayValue* value); -} // namespace RakNet diff --git a/dCommon/Amf3.h b/dCommon/Amf3.h new file mode 100644 index 000000000..4dba039ff --- /dev/null +++ b/dCommon/Amf3.h @@ -0,0 +1,368 @@ +#ifndef __AMF3__H__ +#define __AMF3__H__ + +#include "dCommonVars.h" +#include "dLogger.h" +#include "Game.h" + +#include +#include + +enum class eAmf : uint8_t { + Undefined = 0x00, // An undefined AMF Value + Null = 0x01, // A null AMF value + False = 0x02, // A false AMF value + True = 0x03, // A true AMF value + Integer = 0x04, // An integer AMF value + Double = 0x05, // A double AMF value + String = 0x06, // A string AMF value + XMLDoc = 0x07, // Unused in the live client and cannot be serialized without modification. An XML Doc AMF value + Date = 0x08, // Unused in the live client and cannot be serialized without modification. A date AMF value + Array = 0x09, // An array AMF value + Object = 0x0A, // Unused in the live client and cannot be serialized without modification. An object AMF value + XML = 0x0B, // Unused in the live client and cannot be serialized without modification. An XML AMF value + ByteArray = 0x0C, // Unused in the live client and cannot be serialized without modification. A byte array AMF value + VectorInt = 0x0D, // Unused in the live client and cannot be serialized without modification. An integer vector AMF value + VectorUInt = 0x0E, // Unused in the live client and cannot be serialized without modification. An unsigned integer AMF value + VectorDouble = 0x0F, // Unused in the live client and cannot be serialized without modification. A double vector AMF value + VectorObject = 0x10, // Unused in the live client and cannot be serialized without modification. An object vector AMF value + Dictionary = 0x11 // Unused in the live client and cannot be serialized without modification. A dictionary AMF value +}; + +class AMFBaseValue { +public: + virtual eAmf GetValueType() { return eAmf::Undefined; }; + AMFBaseValue() {}; + virtual ~AMFBaseValue() {}; +}; + +template +class AMFValue : public AMFBaseValue { +public: + AMFValue() {}; + AMFValue(ValueType value) { SetValue(value); }; + virtual ~AMFValue() override {}; + + eAmf GetValueType() override { return eAmf::Undefined; }; + + const ValueType& GetValue() { return data; }; + void SetValue(ValueType value) { data = value; }; +protected: + ValueType data; +}; + +// As a string this is much easier to write and read from a BitStream. +template<> +class AMFValue : public AMFBaseValue { +public: + AMFValue() {}; + AMFValue(const char* value) { SetValue(std::string(value)); }; + virtual ~AMFValue() override {}; + + eAmf GetValueType() override { return eAmf::String; }; + + const std::string& GetValue() { return data; }; + void SetValue(std::string value) { data = value; }; +protected: + std::string data; +}; + +typedef AMFValue AMFNullValue; +typedef AMFValue AMFBoolValue; +typedef AMFValue AMFIntValue; +typedef AMFValue AMFStringValue; +typedef AMFValue AMFDoubleValue; + +template<> inline eAmf AMFValue::GetValueType() { return eAmf::Null; }; +template<> inline eAmf AMFValue::GetValueType() { return this->data ? eAmf::True : eAmf::False; }; +template<> inline eAmf AMFValue::GetValueType() { return eAmf::Integer; }; +template<> inline eAmf AMFValue::GetValueType() { return eAmf::Integer; }; +template<> inline eAmf AMFValue::GetValueType() { return eAmf::String; }; +template<> inline eAmf AMFValue::GetValueType() { return eAmf::Double; }; + +/** + * The AMFArrayValue object holds 2 types of lists: + * An associative list where a key maps to a value + * A Dense list where elements are stored back to back + * + * Objects that are Registered are owned by this object + * and are not to be deleted by a caller. + */ +class AMFArrayValue : public AMFBaseValue { + + typedef std::unordered_map AMFAssociative; + typedef std::vector AMFDense; + +public: + eAmf GetValueType() override { return eAmf::Array; }; + + ~AMFArrayValue() override { + for (auto valueToDelete : GetDense()) { + if (valueToDelete) { + delete valueToDelete; + valueToDelete = nullptr; + } + } + for (auto valueToDelete : GetAssociative()) { + if (valueToDelete.second) { + delete valueToDelete.second; + valueToDelete.second = nullptr; + } + } + }; + + /** + * Returns the Associative portion of the object + */ + inline AMFAssociative& GetAssociative() { return this->associative; }; + + /** + * Returns the dense portion of the object + */ + inline AMFDense& GetDense() { return this->dense; }; + + /** + * Inserts an AMFValue into the associative portion with the given key. + * If a duplicate is attempted to be inserted, it is ignored and the + * first value with that key is kept in the map. + * + * These objects are not to be deleted by the caller as they are owned by + * the AMFArray object which manages its own memory. + * + * @param key The key to associate with the value + * @param value The value to insert + * + * @return The inserted element if the type matched, + * or nullptr if a key existed and was not the same type + */ + template + std::pair*, bool> Insert(const std::string& key, ValueType value) { + auto element = associative.find(key); + AMFValue* val = nullptr; + bool found = true; + if (element == associative.end()) { + val = new AMFValue(value); + associative.insert(std::make_pair(key, val)); + } else { + val = dynamic_cast*>(element->second); + found = false; + } + return std::make_pair(val, found); + }; + + // Associates an array with a string key + std::pair Insert(const std::string& key) { + auto element = associative.find(key); + AMFArrayValue* val = nullptr; + bool found = true; + if (element == associative.end()) { + val = new AMFArrayValue(); + associative.insert(std::make_pair(key, val)); + } else { + val = dynamic_cast(element->second); + found = false; + } + return std::make_pair(val, found); + }; + + // Associates an array with an integer key + std::pair Insert(const uint32_t& index) { + AMFArrayValue* val = nullptr; + bool inserted = false; + if (index >= dense.size()) { + dense.resize(index + 1); + val = new AMFArrayValue(); + dense.at(index) = val; + inserted = true; + } + return std::make_pair(dynamic_cast(dense.at(index)), inserted); + }; + + /** + * @brief Inserts an AMFValue into the AMFArray key'd by index. + * Attempting to insert the same key to the same value twice overwrites + * the previous value with the new one. + * + * @param index The index to associate with the value + * @param value The value to insert + * @return The inserted element, or nullptr if the type did not match + * what was at the index. + */ + template + std::pair*, bool> Insert(const uint32_t& index, ValueType value) { + AMFValue* val = nullptr; + bool inserted = false; + if (index >= this->dense.size()) { + this->dense.resize(index + 1); + val = new AMFValue(value); + this->dense.at(index) = val; + inserted = true; + } + return std::make_pair(dynamic_cast*>(this->dense.at(index)), inserted); + }; + + /** + * Inserts an AMFValue into the associative portion with the given key. + * If a duplicate is attempted to be inserted, it replaces the original + * + * The inserted element is now owned by this object and is not to be deleted + * + * @param key The key to associate with the value + * @param value The value to insert + */ + void Insert(const std::string& key, AMFBaseValue* value) { + auto element = associative.find(key); + if (element != associative.end() && element->second) { + delete element->second; + element->second = value; + } else { + associative.insert(std::make_pair(key, value)); + } + }; + + /** + * Inserts an AMFValue into the associative portion with the given index. + * If a duplicate is attempted to be inserted, it replaces the original + * + * The inserted element is now owned by this object and is not to be deleted + * + * @param key The key to associate with the value + * @param value The value to insert + */ + void Insert(const uint32_t index, AMFBaseValue* value) { + if (index < dense.size()) { + AMFDense::iterator itr = dense.begin() + index; + if (*itr) delete dense.at(index); + } else { + dense.resize(index + 1); + } + dense.at(index) = value; + }; + + /** + * Pushes an AMFValue into the back of the dense portion. + * + * These objects are not to be deleted by the caller as they are owned by + * the AMFArray object which manages its own memory. + * + * @param value The value to insert + * + * @return The inserted pointer, or nullptr should the key already be in use. + */ + template + inline AMFValue* Push(ValueType value) { + return Insert(this->dense.size(), value).first; + }; + + /** + * Removes the key from the associative portion + * + * The pointer removed is now no longer managed by this container + * + * @param key The key to remove from the associative portion + */ + void Remove(const std::string& key, bool deleteValue = true) { + AMFAssociative::iterator it = this->associative.find(key); + if (it != this->associative.end()) { + if (deleteValue) delete it->second; + this->associative.erase(it); + } + } + + /** + * Pops the last element in the dense portion, deleting it in the process. + */ + void Remove(const uint32_t index) { + if (!this->dense.empty() && index < this->dense.size()) { + auto itr = this->dense.begin() + index; + if (*itr) delete (*itr); + this->dense.erase(itr); + } + } + + void Pop() { + if (!this->dense.empty()) Remove(this->dense.size() - 1); + } + + AMFArrayValue* GetArray(const std::string& key) { + AMFAssociative::const_iterator it = this->associative.find(key); + if (it != this->associative.end()) { + return dynamic_cast(it->second); + } + return nullptr; + }; + + AMFArrayValue* GetArray(const uint32_t index) { + return index >= this->dense.size() ? nullptr : dynamic_cast(this->dense.at(index)); + }; + + inline AMFArrayValue* InsertArray(const std::string& key) { + return static_cast(Insert(key).first); + }; + + inline AMFArrayValue* InsertArray(const uint32_t index) { + return static_cast(Insert(index).first); + }; + + inline AMFArrayValue* PushArray() { + return static_cast(Insert(this->dense.size()).first); + }; + + /** + * Gets an AMFValue by the key from the associative portion and converts it + * to the AmfValue template type. If the key did not exist, it is inserted. + * + * @tparam The target object type + * @param key The key to lookup + * + * @return The AMFValue + */ + template + AMFValue* Get(const std::string& key) const { + AMFAssociative::const_iterator it = this->associative.find(key); + return it != this->associative.end() ? + dynamic_cast*>(it->second) : + nullptr; + }; + + // Get from the array but dont cast it + AMFBaseValue* Get(const std::string& key) const { + AMFAssociative::const_iterator it = this->associative.find(key); + return it != this->associative.end() ? it->second : nullptr; + }; + + /** + * @brief Get an AMFValue object at a position in the dense portion. + * Gets an AMFValue by the index from the dense portion and converts it + * to the AmfValue template type. If the index did not exist, it is inserted. + * + * @tparam The target object type + * @param index The index to get + * @return The casted object, or nullptr. + */ + template + AMFValue* Get(uint32_t index) const { + std::cout << (index < this->dense.size()) << std::endl; + return index < this->dense.size() ? + dynamic_cast*>(this->dense.at(index)) : + nullptr; + }; + + // Get from the dense but dont cast it + AMFBaseValue* Get(const uint32_t index) const { + return index < this->dense.size() ? this->dense.at(index) : nullptr; + }; +private: + /** + * The associative portion. These values are key'd with strings to an AMFValue. + */ + AMFAssociative associative; + + /** + * The dense portion. These AMFValue's are stored one after + * another with the most recent addition being at the back. + */ + AMFDense dense; +}; + +#endif //!__AMF3__H__ diff --git a/dCommon/AmfSerialize.cpp b/dCommon/AmfSerialize.cpp new file mode 100644 index 000000000..79ba5e2d5 --- /dev/null +++ b/dCommon/AmfSerialize.cpp @@ -0,0 +1,184 @@ +#include "AmfSerialize.h" + +#include "Game.h" +#include "dLogger.h" + +// Writes an AMFValue pointer to a RakNet::BitStream +template<> +void RakNet::BitStream::Write(AMFBaseValue& value) { + eAmf type = value.GetValueType(); + this->Write(type); + switch (type) { + case eAmf::Integer: { + this->Write(*static_cast(&value)); + break; + } + + case eAmf::Double: { + this->Write(*static_cast(&value)); + break; + } + + case eAmf::String: { + this->Write(*static_cast(&value)); + break; + } + + case eAmf::Array: { + this->Write(*static_cast(&value)); + break; + } + default: { + Game::logger->Log("AmfSerialize", "Encountered unwritable AMFType %i!", type); + } + case eAmf::Undefined: + case eAmf::Null: + case eAmf::False: + case eAmf::True: + case eAmf::Date: + case eAmf::Object: + case eAmf::XML: + case eAmf::XMLDoc: + case eAmf::ByteArray: + case eAmf::VectorInt: + case eAmf::VectorUInt: + case eAmf::VectorDouble: + case eAmf::VectorObject: + case eAmf::Dictionary: + break; + } +} + +/** + * A private function to write an value to a RakNet::BitStream + * RakNet writes in the correct byte order - do not reverse this. + */ +void WriteUInt29(RakNet::BitStream* bs, uint32_t v) { + unsigned char b4 = (unsigned char)v; + if (v < 0x00200000) { + b4 = b4 & 0x7F; + if (v > 0x7F) { + unsigned char b3; + v = v >> 7; + b3 = ((unsigned char)(v)) | 0x80; + if (v > 0x7F) { + unsigned char b2; + v = v >> 7; + b2 = ((unsigned char)(v)) | 0x80; + bs->Write(b2); + } + + bs->Write(b3); + } + } else { + unsigned char b1; + unsigned char b2; + unsigned char b3; + + v = v >> 8; + b3 = ((unsigned char)(v)) | 0x80; + v = v >> 7; + b2 = ((unsigned char)(v)) | 0x80; + v = v >> 7; + b1 = ((unsigned char)(v)) | 0x80; + + bs->Write(b1); + bs->Write(b2); + bs->Write(b3); + } + + bs->Write(b4); +} + +/** + * Writes a flag number to a RakNet::BitStream + * RakNet writes in the correct byte order - do not reverse this. + */ +void WriteFlagNumber(RakNet::BitStream* bs, uint32_t v) { + v = (v << 1) | 0x01; + WriteUInt29(bs, v); +} + +/** + * Writes an AMFString to a RakNet::BitStream + * + * RakNet writes in the correct byte order - do not reverse this. + */ +void WriteAMFString(RakNet::BitStream* bs, const std::string& str) { + WriteFlagNumber(bs, (uint32_t)str.size()); + bs->Write(str.c_str(), (uint32_t)str.size()); +} + +/** + * Writes an U16 to a bitstream + * + * RakNet writes in the correct byte order - do not reverse this. + */ +void WriteAMFU16(RakNet::BitStream* bs, uint16_t value) { + bs->Write(value); +} + +/** + * Writes an U32 to a bitstream + * + * RakNet writes in the correct byte order - do not reverse this. + */ +void WriteAMFU32(RakNet::BitStream* bs, uint32_t value) { + bs->Write(value); +} + +/** + * Writes an U64 to a bitstream + * + * RakNet writes in the correct byte order - do not reverse this. + */ +void WriteAMFU64(RakNet::BitStream* bs, uint64_t value) { + bs->Write(value); +} + +// Writes an AMFIntegerValue to BitStream +template<> +void RakNet::BitStream::Write(AMFIntValue& value) { + WriteUInt29(this, value.GetValue()); +} + +// Writes an AMFDoubleValue to BitStream +template<> +void RakNet::BitStream::Write(AMFDoubleValue& value) { + double d = value.GetValue(); + WriteAMFU64(this, *reinterpret_cast(&d)); +} + +// Writes an AMFStringValue to BitStream +template<> +void RakNet::BitStream::Write(AMFStringValue& value) { + WriteAMFString(this, value.GetValue()); +} + +// Writes an AMFArrayValue to BitStream +template<> +void RakNet::BitStream::Write(AMFArrayValue& value) { + uint32_t denseSize = value.GetDense().size(); + WriteFlagNumber(this, denseSize); + + auto it = value.GetAssociative().begin(); + auto end = value.GetAssociative().end(); + + while (it != end) { + WriteAMFString(this, it->first); + this->Write(*it->second); + it++; + } + + this->Write(eAmf::Null); + + if (denseSize > 0) { + auto it2 = value.GetDense().begin(); + auto end2 = value.GetDense().end(); + + while (it2 != end2) { + this->Write(**it2); + it2++; + } + } +} diff --git a/dCommon/AmfSerialize.h b/dCommon/AmfSerialize.h new file mode 100644 index 000000000..9a6f56f28 --- /dev/null +++ b/dCommon/AmfSerialize.h @@ -0,0 +1,50 @@ +#pragma once + +// Custom Classes +#include "Amf3.h" + +// RakNet +#include + +/*! + \file AmfSerialize.h + \brief A class that implements native writing of AMF values to RakNet::BitStream + */ + + // We are using the RakNet namespace +namespace RakNet { + //! Writes an AMFValue pointer to a RakNet::BitStream + /*! + \param value The value to write + */ + template <> + void RakNet::BitStream::Write(AMFBaseValue& value); + + //! Writes an AMFIntegerValue to a RakNet::BitStream + /*! + \param value The value to write + */ + template <> + void RakNet::BitStream::Write(AMFIntValue& value); + + //! Writes an AMFDoubleValue to a RakNet::BitStream + /*! + \param value The value to write + */ + template <> + void RakNet::BitStream::Write(AMFDoubleValue& value); + + //! Writes an AMFStringValue to a RakNet::BitStream + /*! + \param value The value to write + */ + template <> + void RakNet::BitStream::Write(AMFStringValue& value); + + //! Writes an AMFArrayValue to a RakNet::BitStream + /*! + \param value The value to write + */ + template <> + void RakNet::BitStream::Write(AMFArrayValue& value); +} // namespace RakNet diff --git a/dCommon/CMakeLists.txt b/dCommon/CMakeLists.txt index 549acfb2c..2517c0484 100644 --- a/dCommon/CMakeLists.txt +++ b/dCommon/CMakeLists.txt @@ -1,6 +1,6 @@ -set(DCOMMON_SOURCES "AMFFormat.cpp" +set(DCOMMON_SOURCES "AMFDeserialize.cpp" - "AMFFormat_BitStream.cpp" + "AmfSerialize.cpp" "BinaryIO.cpp" "dConfig.cpp" "Diagnostics.cpp" diff --git a/dGame/dComponents/CharacterComponent.cpp b/dGame/dComponents/CharacterComponent.cpp index 82ad5507c..32fe564c7 100644 --- a/dGame/dComponents/CharacterComponent.cpp +++ b/dGame/dComponents/CharacterComponent.cpp @@ -13,7 +13,7 @@ #include "VehiclePhysicsComponent.h" #include "GameMessages.h" #include "Item.h" -#include "AMFFormat.h" +#include "Amf3.h" #include "eGameMasterLevel.h" #include "eGameActivity.h" @@ -734,6 +734,6 @@ void CharacterComponent::RemoveVentureVisionEffect(std::string ventureVisionType void CharacterComponent::UpdateClientMinimap(bool showFaction, std::string ventureVisionType) const { if (!m_Parent) return; AMFArrayValue arrayToSend; - arrayToSend.InsertValue(ventureVisionType, showFaction ? static_cast(new AMFTrueValue()) : static_cast(new AMFFalseValue())); - GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent ? m_Parent->GetSystemAddress() : UNASSIGNED_SYSTEM_ADDRESS, "SetFactionVisibility", &arrayToSend); + arrayToSend.Insert(ventureVisionType, showFaction); + GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent ? m_Parent->GetSystemAddress() : UNASSIGNED_SYSTEM_ADDRESS, "SetFactionVisibility", arrayToSend); } diff --git a/dGame/dComponents/DestroyableComponent.cpp b/dGame/dComponents/DestroyableComponent.cpp index 7e7d44aa2..01ebf5c10 100644 --- a/dGame/dComponents/DestroyableComponent.cpp +++ b/dGame/dComponents/DestroyableComponent.cpp @@ -4,8 +4,8 @@ #include "Game.h" #include "dConfig.h" -#include "AMFFormat.h" -#include "AMFFormat_BitStream.h" +#include "Amf3.h" +#include "AmfSerialize.h" #include "GameMessages.h" #include "User.h" #include "CDClientManager.h" @@ -245,16 +245,12 @@ void DestroyableComponent::SetMaxHealth(float value, bool playAnim) { if (playAnim) { // Now update the player bar if (!m_Parent->GetParentUser()) return; - AMFStringValue* amount = new AMFStringValue(); - amount->SetStringValue(std::to_string(difference)); - AMFStringValue* type = new AMFStringValue(); - type->SetStringValue("health"); AMFArrayValue args; - args.InsertValue("amount", amount); - args.InsertValue("type", type); + args.Insert("amount", std::to_string(difference)); + args.Insert("type", "health"); - GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent->GetParentUser()->GetSystemAddress(), "MaxPlayerBarUpdate", &args); + GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent->GetParentUser()->GetSystemAddress(), "MaxPlayerBarUpdate", args); } EntityManager::Instance()->SerializeEntity(m_Parent); @@ -290,16 +286,12 @@ void DestroyableComponent::SetMaxArmor(float value, bool playAnim) { if (playAnim) { // Now update the player bar if (!m_Parent->GetParentUser()) return; - AMFStringValue* amount = new AMFStringValue(); - amount->SetStringValue(std::to_string(value)); - AMFStringValue* type = new AMFStringValue(); - type->SetStringValue("armor"); AMFArrayValue args; - args.InsertValue("amount", amount); - args.InsertValue("type", type); + args.Insert("amount", std::to_string(value)); + args.Insert("type", "armor"); - GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent->GetParentUser()->GetSystemAddress(), "MaxPlayerBarUpdate", &args); + GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent->GetParentUser()->GetSystemAddress(), "MaxPlayerBarUpdate", args); } EntityManager::Instance()->SerializeEntity(m_Parent); @@ -334,16 +326,12 @@ void DestroyableComponent::SetMaxImagination(float value, bool playAnim) { if (playAnim) { // Now update the player bar if (!m_Parent->GetParentUser()) return; - AMFStringValue* amount = new AMFStringValue(); - amount->SetStringValue(std::to_string(difference)); - AMFStringValue* type = new AMFStringValue(); - type->SetStringValue("imagination"); AMFArrayValue args; - args.InsertValue("amount", amount); - args.InsertValue("type", type); + args.Insert("amount", std::to_string(difference)); + args.Insert("type", "imagination"); - GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent->GetParentUser()->GetSystemAddress(), "MaxPlayerBarUpdate", &args); + GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent->GetParentUser()->GetSystemAddress(), "MaxPlayerBarUpdate", args); } EntityManager::Instance()->SerializeEntity(m_Parent); } diff --git a/dGame/dComponents/MissionComponent.cpp b/dGame/dComponents/MissionComponent.cpp index 0ae0f07ec..8f61c1aaf 100644 --- a/dGame/dComponents/MissionComponent.cpp +++ b/dGame/dComponents/MissionComponent.cpp @@ -13,7 +13,7 @@ #include "InventoryComponent.h" #include "GameMessages.h" #include "Game.h" -#include "AMFFormat.h" +#include "Amf3.h" #include "dZoneManager.h" #include "Mail.h" #include "MissionPrerequisites.h" diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 5da9a3c4b..bff917d8a 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -11,7 +11,7 @@ #include "CharacterComponent.h" #include "UserManager.h" #include "dLogger.h" -#include "AMFFormat.h" +#include "Amf3.h" #include "eObjectBits.h" #include "eGameMasterLevel.h" @@ -36,12 +36,9 @@ void PropertyEntranceComponent::OnUse(Entity* entity) { AMFArrayValue args; - auto* state = new AMFStringValue(); - state->SetStringValue("property_menu"); + args.Insert("state", "property_menu"); - args.InsertValue("state", state); - - GameMessages::SendUIMessageServerToSingleClient(entity, entity->GetSystemAddress(), "pushGameState", &args); + GameMessages::SendUIMessageServerToSingleClient(entity, entity->GetSystemAddress(), "pushGameState", args); } void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index, bool returnToZone, const SystemAddress& sysAddr) { diff --git a/dGame/dComponents/RenderComponent.h b/dGame/dComponents/RenderComponent.h index de8b2907b..e09ec22d7 100644 --- a/dGame/dComponents/RenderComponent.h +++ b/dGame/dComponents/RenderComponent.h @@ -6,7 +6,7 @@ #include #include -#include "AMFFormat.h" +#include "Amf3.h" #include "Component.h" #include "eReplicaComponentType.h" diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 165876ff9..be57bce3b 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -28,7 +28,7 @@ #include "eUnequippableActiveType.h" #include "eMovementPlatformState.h" #include "LeaderboardManager.h" -#include "AMFFormat.h" +#include "Amf3.h" #include "Loot.h" #include "eRacingTaskParam.h" #include "eMissionTaskType.h" @@ -87,7 +87,7 @@ #include "AMFDeserialize.h" #include "eBlueprintSaveResponseType.h" #include "eAninmationFlags.h" -#include "AMFFormat_BitStream.h" +#include "AmfSerialize.h" #include "eReplicaComponentType.h" #include "eClientMessageType.h" #include "eGameMessageType.h" @@ -596,14 +596,14 @@ void GameMessages::SendModifyLEGOScore(Entity* entity, const SystemAddress& sysA SEND_PACKET; } -void GameMessages::SendUIMessageServerToSingleClient(Entity* entity, const SystemAddress& sysAddr, const std::string& message, AMFValue* args) { +void GameMessages::SendUIMessageServerToSingleClient(Entity* entity, const SystemAddress& sysAddr, const std::string& message, AMFBaseValue& args) { CBITSTREAM; CMSGHEADER; bitStream.Write(entity->GetObjectID()); bitStream.Write((uint16_t)eGameMessageType::UI_MESSAGE_SERVER_TO_SINGLE_CLIENT); - bitStream.Write(args); + bitStream.Write(args); uint32_t strMessageNameLength = message.size(); bitStream.Write(strMessageNameLength); @@ -614,7 +614,7 @@ void GameMessages::SendUIMessageServerToSingleClient(Entity* entity, const Syste SEND_PACKET; } -void GameMessages::SendUIMessageServerToAllClients(const std::string& message, AMFValue* args) { +void GameMessages::SendUIMessageServerToAllClients(const std::string& message, AMFBaseValue& args) { CBITSTREAM; CMSGHEADER; @@ -622,7 +622,7 @@ void GameMessages::SendUIMessageServerToAllClients(const std::string& message, A bitStream.Write(empty); bitStream.Write((uint16_t)eGameMessageType::UI_MESSAGE_SERVER_TO_ALL_CLIENTS); - bitStream.Write(args); + bitStream.Write(args); uint32_t strMessageNameLength = message.size(); bitStream.Write(strMessageNameLength); @@ -2486,8 +2486,8 @@ void GameMessages::SendUnSmash(Entity* entity, LWOOBJID builderID, float duratio void GameMessages::HandleControlBehaviors(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { AMFDeserialize reader; - std::unique_ptr amfArguments(reader.Read(inStream)); - if (amfArguments->GetValueType() != AMFValueType::AMFArray) return; + std::unique_ptr amfArguments(reader.Read(inStream)); + if (amfArguments->GetValueType() != eAmf::Array) return; uint32_t commandLength{}; inStream->Read(commandLength); diff --git a/dGame/dGameMessages/GameMessages.h b/dGame/dGameMessages/GameMessages.h index 94b24b650..7e7a8f708 100644 --- a/dGame/dGameMessages/GameMessages.h +++ b/dGame/dGameMessages/GameMessages.h @@ -12,7 +12,7 @@ #include "eLootSourceType.h" #include "Brick.h" -class AMFValue; +class AMFBaseValue; class Entity; class Item; class NiQuaternion; @@ -88,8 +88,8 @@ namespace GameMessages { void NotifyLevelRewards(LWOOBJID objectID, const SystemAddress& sysAddr, int level, bool sending_rewards); void SendModifyLEGOScore(Entity* entity, const SystemAddress& sysAddr, int64_t score, eLootSourceType sourceType); - void SendUIMessageServerToSingleClient(Entity* entity, const SystemAddress& sysAddr, const std::string& message, AMFValue* args); - void SendUIMessageServerToAllClients(const std::string& message, AMFValue* args); + void SendUIMessageServerToSingleClient(Entity* entity, const SystemAddress& sysAddr, const std::string& message, AMFBaseValue& args); + void SendUIMessageServerToAllClients(const std::string& message, AMFBaseValue& args); void SendPlayEmbeddedEffectOnAllClientsNearObject(Entity* entity, std::u16string effectName, const LWOOBJID& fromObjectID, float radius); void SendPlayFXEffect(Entity* entity, int32_t effectID, const std::u16string& effectType, const std::string& name, LWOOBJID secondary, float priority = 1, float scale = 1, bool serialize = true); diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/Action.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/Action.cpp index 7da286b0b..eabe76b74 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviorMessages/Action.cpp +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/Action.cpp @@ -12,19 +12,19 @@ Action::Action(AMFArrayValue* arguments) { valueParameterName = ""; valueParameterString = ""; valueParameterDouble = 0.0; - for (auto& typeValueMap : arguments->GetAssociativeMap()) { + for (auto& typeValueMap : arguments->GetAssociative()) { if (typeValueMap.first == "Type") { - if (typeValueMap.second->GetValueType() != AMFValueType::AMFString) continue; - type = static_cast(typeValueMap.second)->GetStringValue(); + if (typeValueMap.second->GetValueType() != eAmf::String) continue; + type = static_cast(typeValueMap.second)->GetValue(); } else { valueParameterName = typeValueMap.first; // Message is the only known string parameter if (valueParameterName == "Message") { - if (typeValueMap.second->GetValueType() != AMFValueType::AMFString) continue; - valueParameterString = static_cast(typeValueMap.second)->GetStringValue(); + if (typeValueMap.second->GetValueType() != eAmf::String) continue; + valueParameterString = static_cast(typeValueMap.second)->GetValue(); } else { - if (typeValueMap.second->GetValueType() != AMFValueType::AMFDouble) continue; - valueParameterDouble = static_cast(typeValueMap.second)->GetDoubleValue(); + if (typeValueMap.second->GetValueType() != eAmf::Double) continue; + valueParameterDouble = static_cast(typeValueMap.second)->GetValue(); } } } diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/ActionContext.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/ActionContext.cpp index 480eef455..c2ba2eebd 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviorMessages/ActionContext.cpp +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/ActionContext.cpp @@ -2,7 +2,7 @@ #include -#include "AMFFormat.h" +#include "Amf3.h" ActionContext::ActionContext() { stripId = 0; @@ -17,15 +17,15 @@ ActionContext::ActionContext(AMFArrayValue* arguments, std::string customStateKe } BehaviorState ActionContext::GetBehaviorStateFromArgument(AMFArrayValue* arguments, const std::string& key) { - auto* stateIDValue = arguments->FindValue(key); + auto* stateIDValue = arguments->Get(key); if (!stateIDValue) throw std::invalid_argument("Unable to find behavior state from argument \"" + key + "\""); - return static_cast(stateIDValue->GetDoubleValue()); + return static_cast(stateIDValue->GetValue()); } StripId ActionContext::GetStripIdFromArgument(AMFArrayValue* arguments, const std::string& key) { - auto* stripIdValue = arguments->FindValue(key); + auto* stripIdValue = arguments->Get(key); if (!stripIdValue) throw std::invalid_argument("Unable to find strip ID from argument \"" + key + "\""); - return static_cast(stripIdValue->GetDoubleValue()); + return static_cast(stripIdValue->GetValue()); } diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddActionMessage.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddActionMessage.cpp index 4fc7f82b6..986729090 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddActionMessage.cpp +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddActionMessage.cpp @@ -4,7 +4,7 @@ AddActionMessage::AddActionMessage(AMFArrayValue* arguments) : BehaviorMessageBa actionContext = ActionContext(arguments); actionIndex = GetActionIndexFromArgument(arguments); - auto* actionValue = arguments->FindValue("action"); + auto* actionValue = arguments->GetArray("action"); if (!actionValue) return; action = Action(actionValue); diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddMessage.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddMessage.cpp index 4f2123b4b..badee2c25 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddMessage.cpp +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddMessage.cpp @@ -2,10 +2,10 @@ AddMessage::AddMessage(AMFArrayValue* arguments) : BehaviorMessageBase(arguments) { behaviorIndex = 0; - auto* behaviorIndexValue = arguments->FindValue("BehaviorIndex"); + auto* behaviorIndexValue = arguments->Get("BehaviorIndex"); if (!behaviorIndexValue) return; - behaviorIndex = static_cast(behaviorIndexValue->GetDoubleValue()); + behaviorIndex = static_cast(behaviorIndexValue->GetValue()); Game::logger->LogDebug("AddMessage", "behaviorId %i index %i", behaviorId, behaviorIndex); } diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddStripMessage.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddStripMessage.cpp index c4729c575..261b3462b 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddStripMessage.cpp +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddStripMessage.cpp @@ -4,17 +4,16 @@ AddStripMessage::AddStripMessage(AMFArrayValue* arguments) : BehaviorMessageBase(arguments) { actionContext = ActionContext(arguments); - position = StripUiPosition(arguments); - auto* strip = arguments->FindValue("strip"); + auto* strip = arguments->GetArray("strip"); if (!strip) return; - auto* actions = strip->FindValue("actions"); + auto* actions = strip->GetArray("actions"); if (!actions) return; - for (uint32_t actionNumber = 0; actionNumber < actions->GetDenseValueSize(); actionNumber++) { - auto* actionValue = actions->GetValueAt(actionNumber); + for (uint32_t actionNumber = 0; actionNumber < actions->GetDense().size(); actionNumber++) { + auto* actionValue = actions->GetArray(actionNumber); if (!actionValue) continue; actionsToAdd.push_back(Action(actionValue)); diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/BehaviorMessageBase.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/BehaviorMessageBase.cpp index b3d98d51c..3286504a2 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviorMessages/BehaviorMessageBase.cpp +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/BehaviorMessageBase.cpp @@ -1,6 +1,6 @@ #include "BehaviorMessageBase.h" -#include "AMFFormat.h" +#include "Amf3.h" #include "BehaviorStates.h" #include "dCommonVars.h" @@ -11,12 +11,12 @@ BehaviorMessageBase::BehaviorMessageBase(AMFArrayValue* arguments) { int32_t BehaviorMessageBase::GetBehaviorIdFromArgument(AMFArrayValue* arguments) { const auto* key = "BehaviorID"; - auto* behaviorIDValue = arguments->FindValue(key); + auto* behaviorIDValue = arguments->Get(key); int32_t behaviorID = -1; - if (behaviorIDValue) { - behaviorID = std::stoul(behaviorIDValue->GetStringValue()); - } else if (!arguments->FindValue(key)) { + if (behaviorIDValue && behaviorIDValue->GetValueType() == eAmf::String) { + behaviorID = std::stoul(behaviorIDValue->GetValue()); + } else if (arguments->Get(key)->GetValueType() != eAmf::Undefined) { throw std::invalid_argument("Unable to find behavior ID"); } @@ -24,10 +24,10 @@ int32_t BehaviorMessageBase::GetBehaviorIdFromArgument(AMFArrayValue* arguments) } uint32_t BehaviorMessageBase::GetActionIndexFromArgument(AMFArrayValue* arguments, const std::string& keyName) { - auto* actionIndexAmf = arguments->FindValue(keyName); + auto* actionIndexAmf = arguments->Get(keyName); if (!actionIndexAmf) { throw std::invalid_argument("Unable to find actionIndex"); } - return static_cast(actionIndexAmf->GetDoubleValue()); + return static_cast(actionIndexAmf->GetValue()); } diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/BehaviorMessageBase.h b/dGame/dPropertyBehaviors/ControlBehaviorMessages/BehaviorMessageBase.h index 13b00a35d..8771286c3 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviorMessages/BehaviorMessageBase.h +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/BehaviorMessageBase.h @@ -4,7 +4,7 @@ #include #include -#include "AMFFormat.h" +#include "Amf3.h" #include "dCommonVars.h" #include "Game.h" diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/MoveToInventoryMessage.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/MoveToInventoryMessage.cpp index 927000761..5b61ee32f 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviorMessages/MoveToInventoryMessage.cpp +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/MoveToInventoryMessage.cpp @@ -1,9 +1,9 @@ #include "MoveToInventoryMessage.h" MoveToInventoryMessage::MoveToInventoryMessage(AMFArrayValue* arguments) : BehaviorMessageBase(arguments) { - auto* behaviorIndexValue = arguments->FindValue("BehaviorIndex"); + auto* behaviorIndexValue = arguments->Get("BehaviorIndex"); if (!behaviorIndexValue) return; - behaviorIndex = static_cast(behaviorIndexValue->GetDoubleValue()); + behaviorIndex = static_cast(behaviorIndexValue->GetValue()); Game::logger->LogDebug("MoveToInventoryMessage", "behaviorId %i behaviorIndex %i", behaviorId, behaviorIndex); } diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/RenameMessage.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/RenameMessage.cpp index 0ea3b6d65..a1c2abbc8 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviorMessages/RenameMessage.cpp +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/RenameMessage.cpp @@ -1,9 +1,9 @@ #include "RenameMessage.h" RenameMessage::RenameMessage(AMFArrayValue* arguments) : BehaviorMessageBase(arguments) { - auto* nameAmf = arguments->FindValue("Name"); + auto* nameAmf = arguments->Get("Name"); if (!nameAmf) return; - name = nameAmf->GetStringValue(); + name = nameAmf->GetValue(); Game::logger->LogDebug("RenameMessage", "behaviorId %i n %s", behaviorId, name.c_str()); } diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/StripUiPosition.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/StripUiPosition.cpp index 4ddccc55e..de612b452 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviorMessages/StripUiPosition.cpp +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/StripUiPosition.cpp @@ -1,6 +1,6 @@ #include "StripUiPosition.h" -#include "AMFFormat.h" +#include "Amf3.h" StripUiPosition::StripUiPosition() { xPosition = 0.0; @@ -10,13 +10,13 @@ StripUiPosition::StripUiPosition() { StripUiPosition::StripUiPosition(AMFArrayValue* arguments, std::string uiKeyName) { xPosition = 0.0; yPosition = 0.0; - auto* uiArray = arguments->FindValue(uiKeyName); + auto* uiArray = arguments->GetArray(uiKeyName); if (!uiArray) return; - auto* xPositionValue = uiArray->FindValue("x"); - auto* yPositionValue = uiArray->FindValue("y"); + auto* xPositionValue = uiArray->Get("x"); + auto* yPositionValue = uiArray->Get("y"); if (!xPositionValue || !yPositionValue) return; - yPosition = yPositionValue->GetDoubleValue(); - xPosition = xPositionValue->GetDoubleValue(); + yPosition = yPositionValue->GetValue(); + xPosition = xPositionValue->GetValue(); } diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/UpdateActionMessage.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/UpdateActionMessage.cpp index 53e2d570c..23a0050d5 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviorMessages/UpdateActionMessage.cpp +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/UpdateActionMessage.cpp @@ -5,7 +5,7 @@ UpdateActionMessage::UpdateActionMessage(AMFArrayValue* arguments) : BehaviorMessageBase(arguments) { actionContext = ActionContext(arguments); - auto* actionValue = arguments->FindValue("action"); + auto* actionValue = arguments->GetArray("action"); if (!actionValue) return; action = Action(actionValue); diff --git a/dGame/dPropertyBehaviors/ControlBehaviors.cpp b/dGame/dPropertyBehaviors/ControlBehaviors.cpp index dfb22b59e..d8a062ca5 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviors.cpp +++ b/dGame/dPropertyBehaviors/ControlBehaviors.cpp @@ -1,6 +1,6 @@ #include "ControlBehaviors.h" -#include "AMFFormat.h" +#include "Amf3.h" #include "Entity.h" #include "Game.h" #include "GameMessages.h" @@ -43,11 +43,11 @@ void ControlBehaviors::RequestUpdatedID(int32_t behaviorID, ModelComponent* mode // AMFArrayValue args; // AMFStringValue* behaviorIDString = new AMFStringValue(); - // behaviorIDString->SetStringValue(std::to_string(persistentId)); + // behaviorIDString->SetValue(std::to_string(persistentId)); // args.InsertValue("behaviorID", behaviorIDString); // AMFStringValue* objectIDAsString = new AMFStringValue(); - // objectIDAsString->SetStringValue(std::to_string(modelComponent->GetParent()->GetObjectID())); + // objectIDAsString->SetValue(std::to_string(modelComponent->GetParent()->GetObjectID())); // args.InsertValue("objectID", objectIDAsString); // GameMessages::SendUIMessageServerToSingleClient(modelOwner, sysAddr, "UpdateBehaviorID", &args); @@ -63,8 +63,6 @@ void ControlBehaviors::SendBehaviorListToClient(Entity* modelEntity, const Syste AMFArrayValue behaviorsToSerialize; - AMFArrayValue* behaviors = new AMFArrayValue(); // Empty for now - /** * The behaviors AMFArray will have up to 5 elements in the dense portion. * Each element in the dense portion will be made up of another AMFArray @@ -75,20 +73,17 @@ void ControlBehaviors::SendBehaviorListToClient(Entity* modelEntity, const Syste * "name": The name of the behavior formatted as an AMFString */ - behaviorsToSerialize.InsertValue("behaviors", behaviors); - - AMFStringValue* amfStringValueForObjectID = new AMFStringValue(); - amfStringValueForObjectID->SetStringValue(std::to_string(modelComponent->GetParent()->GetObjectID())); + behaviorsToSerialize.Insert("behaviors"); + behaviorsToSerialize.Insert("objectID", std::to_string(modelComponent->GetParent()->GetObjectID())); - behaviorsToSerialize.InsertValue("objectID", amfStringValueForObjectID); - GameMessages::SendUIMessageServerToSingleClient(modelOwner, sysAddr, "UpdateBehaviorList", &behaviorsToSerialize); + GameMessages::SendUIMessageServerToSingleClient(modelOwner, sysAddr, "UpdateBehaviorList", behaviorsToSerialize); } void ControlBehaviors::ModelTypeChanged(AMFArrayValue* arguments, ModelComponent* ModelComponent) { - auto* modelTypeAmf = arguments->FindValue("ModelType"); + auto* modelTypeAmf = arguments->Get("ModelType"); if (!modelTypeAmf) return; - uint32_t modelType = static_cast(modelTypeAmf->GetDoubleValue()); + uint32_t modelType = static_cast(modelTypeAmf->GetValue()); //TODO Update the model type here } @@ -179,7 +174,7 @@ void ControlBehaviors::SendBehaviorBlocksToClient(ModelComponent* modelComponent // AMFArrayValue* state = new AMFArrayValue(); // AMFDoubleValue* stateAsDouble = new AMFDoubleValue(); - // stateAsDouble->SetDoubleValue(it->first); + // stateAsDouble->SetValue(it->first); // state->InsertValue("id", stateAsDouble); // AMFArrayValue* strips = new AMFArrayValue(); @@ -189,16 +184,16 @@ void ControlBehaviors::SendBehaviorBlocksToClient(ModelComponent* modelComponent // AMFArrayValue* thisStrip = new AMFArrayValue(); // AMFDoubleValue* stripID = new AMFDoubleValue(); - // stripID->SetDoubleValue(strip->first); + // stripID->SetValue(strip->first); // thisStrip->InsertValue("id", stripID); // AMFArrayValue* uiArray = new AMFArrayValue(); // AMFDoubleValue* yPosition = new AMFDoubleValue(); - // yPosition->SetDoubleValue(strip->second->GetYPosition()); + // yPosition->SetValue(strip->second->GetYPosition()); // uiArray->InsertValue("y", yPosition); // AMFDoubleValue* xPosition = new AMFDoubleValue(); - // xPosition->SetDoubleValue(strip->second->GetXPosition()); + // xPosition->SetValue(strip->second->GetXPosition()); // uiArray->InsertValue("x", xPosition); // thisStrip->InsertValue("ui", uiArray); @@ -211,19 +206,19 @@ void ControlBehaviors::SendBehaviorBlocksToClient(ModelComponent* modelComponent // AMFArrayValue* thisAction = new AMFArrayValue(); // AMFStringValue* actionName = new AMFStringValue(); - // actionName->SetStringValue(behaviorAction->actionName); + // actionName->SetValue(behaviorAction->actionName); // thisAction->InsertValue("Type", actionName); // if (behaviorAction->parameterValueString != "") // { // AMFStringValue* valueAsString = new AMFStringValue(); - // valueAsString->SetStringValue(behaviorAction->parameterValueString); + // valueAsString->SetValue(behaviorAction->parameterValueString); // thisAction->InsertValue(behaviorAction->parameterName, valueAsString); // } // else if (behaviorAction->parameterValueDouble != 0.0) // { // AMFDoubleValue* valueAsDouble = new AMFDoubleValue(); - // valueAsDouble->SetDoubleValue(behaviorAction->parameterValueDouble); + // valueAsDouble->SetValue(behaviorAction->parameterValueDouble); // thisAction->InsertValue(behaviorAction->parameterName, valueAsDouble); // } // stripSerialize->PushBackValue(thisAction); @@ -237,11 +232,11 @@ void ControlBehaviors::SendBehaviorBlocksToClient(ModelComponent* modelComponent // behaviorInfo.InsertValue("states", stateSerialize); // AMFStringValue* objectidAsString = new AMFStringValue(); - // objectidAsString->SetStringValue(std::to_string(targetObjectID)); + // objectidAsString->SetValue(std::to_string(targetObjectID)); // behaviorInfo.InsertValue("objectID", objectidAsString); // AMFStringValue* behaviorIDAsString = new AMFStringValue(); - // behaviorIDAsString->SetStringValue(std::to_string(behaviorID)); + // behaviorIDAsString->SetValue(std::to_string(behaviorID)); // behaviorInfo.InsertValue("BehaviorID", behaviorIDAsString); // GameMessages::SendUIMessageServerToSingleClient(modelOwner, sysAddr, "UpdateBehaviorBlocks", &behaviorInfo); @@ -275,10 +270,9 @@ void ControlBehaviors::MoveToInventory(ModelComponent* modelComponent, const Sys // This closes the UI menu should it be open while the player is removing behaviors AMFArrayValue args; - AMFFalseValue* stateToPop = new AMFFalseValue(); - args.InsertValue("visible", stateToPop); + args.Insert("visible", false); - GameMessages::SendUIMessageServerToSingleClient(modelOwner, modelOwner->GetParentUser()->GetSystemAddress(), "ToggleBehaviorEditor", &args); + GameMessages::SendUIMessageServerToSingleClient(modelOwner, modelOwner->GetParentUser()->GetSystemAddress(), "ToggleBehaviorEditor", args); MoveToInventoryMessage moveToInventoryMessage(arguments); diff --git a/dGame/dUtilities/SlashCommandHandler.cpp b/dGame/dUtilities/SlashCommandHandler.cpp index 16db62a67..e8915d277 100644 --- a/dGame/dUtilities/SlashCommandHandler.cpp +++ b/dGame/dUtilities/SlashCommandHandler.cpp @@ -69,7 +69,7 @@ #include "BinaryPathFinder.h" #include "dConfig.h" #include "eBubbleType.h" -#include "AMFFormat.h" +#include "Amf3.h" #include "MovingPlatformComponent.h" #include "eMissionState.h" #include "TriggerComponent.h" @@ -251,26 +251,20 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit { AMFArrayValue args; - auto* state = new AMFStringValue(); - state->SetStringValue("Story"); + args.Insert("state", "Story"); - args.InsertValue("state", state); - - GameMessages::SendUIMessageServerToSingleClient(entity, entity->GetSystemAddress(), "pushGameState", &args); + GameMessages::SendUIMessageServerToSingleClient(entity, entity->GetSystemAddress(), "pushGameState", args); } entity->AddCallbackTimer(0.5f, [customText, entity]() { AMFArrayValue args; - auto* text = new AMFStringValue(); - text->SetStringValue(customText); - - args.InsertValue("visible", new AMFTrueValue()); - args.InsertValue("text", text); + args.Insert("visible", true); + args.Insert("text", customText); Game::logger->Log("SlashCommandHandler", "Sending %s", customText.c_str()); - GameMessages::SendUIMessageServerToSingleClient(entity, entity->GetSystemAddress(), "ToggleStoryBox", &args); + GameMessages::SendUIMessageServerToSingleClient(entity, entity->GetSystemAddress(), "ToggleStoryBox", args); }); return; @@ -530,12 +524,11 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit } if (chatCommand == "setuistate" && args.size() == 1 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) { - AMFStringValue* value = new AMFStringValue(); - value->SetStringValue(args[0]); + AMFArrayValue uiState; - AMFArrayValue args; - args.InsertValue("state", value); - GameMessages::SendUIMessageServerToSingleClient(entity, sysAddr, "pushGameState", &args); + uiState.Insert("state", args.at(0)); + + GameMessages::SendUIMessageServerToSingleClient(entity, sysAddr, "pushGameState", uiState); ChatPackets::SendSystemMessage(sysAddr, u"Switched UI state."); @@ -543,11 +536,11 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit } if (chatCommand == "toggle" && args.size() == 1 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) { - AMFTrueValue* value = new AMFTrueValue(); - AMFArrayValue amfArgs; - amfArgs.InsertValue("visible", value); - GameMessages::SendUIMessageServerToSingleClient(entity, sysAddr, args[0], &amfArgs); + + amfArgs.Insert("visible", true); + + GameMessages::SendUIMessageServerToSingleClient(entity, sysAddr, args[0], amfArgs); ChatPackets::SendSystemMessage(sysAddr, u"Toggled UI state."); @@ -1617,7 +1610,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit if ((chatCommand == "debugui") && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) { ChatPackets::SendSystemMessage(sysAddr, u"Opening UIDebugger..."); AMFArrayValue args; - GameMessages::SendUIMessageServerToSingleClient(entity, sysAddr, "ToggleUIDebugger;", nullptr); + GameMessages::SendUIMessageServerToSingleClient(entity, sysAddr, "ToggleUIDebugger;", args); } if ((chatCommand == "boost") && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) { @@ -2023,15 +2016,11 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit void SlashCommandHandler::SendAnnouncement(const std::string& title, const std::string& message) { AMFArrayValue args; - auto* titleValue = new AMFStringValue(); - titleValue->SetStringValue(title); - auto* messageValue = new AMFStringValue(); - messageValue->SetStringValue(message); - args.InsertValue("title", titleValue); - args.InsertValue("message", messageValue); + args.Insert("title", title); + args.Insert("message", message); - GameMessages::SendUIMessageServerToAllClients("ToggleAnnounce", &args); + GameMessages::SendUIMessageServerToAllClients("ToggleAnnounce", args); //Notify chat about it CBITSTREAM; diff --git a/dMasterServer/MasterServer.cpp b/dMasterServer/MasterServer.cpp index bc0937c25..7af235a4c 100644 --- a/dMasterServer/MasterServer.cpp +++ b/dMasterServer/MasterServer.cpp @@ -335,7 +335,6 @@ int main(int argc, char** argv) { Game::im->GetInstance(0, false, 0); Game::im->GetInstance(1000, false, 0); - StartAuthServer(); } diff --git a/dScripts/02_server/Map/AM/AmConsoleTeleportServer.cpp b/dScripts/02_server/Map/AM/AmConsoleTeleportServer.cpp index f3931e0da..0627b27a6 100644 --- a/dScripts/02_server/Map/AM/AmConsoleTeleportServer.cpp +++ b/dScripts/02_server/Map/AM/AmConsoleTeleportServer.cpp @@ -1,6 +1,6 @@ #include "AmConsoleTeleportServer.h" #include "ChooseYourDestinationNsToNt.h" -#include "AMFFormat.h" +#include "Amf3.h" void AmConsoleTeleportServer::OnStartup(Entity* self) { self->SetVar(u"teleportAnim", m_TeleportAnim); diff --git a/dScripts/02_server/Map/General/BankInteractServer.cpp b/dScripts/02_server/Map/General/BankInteractServer.cpp index b96187cf1..9b5634917 100644 --- a/dScripts/02_server/Map/General/BankInteractServer.cpp +++ b/dScripts/02_server/Map/General/BankInteractServer.cpp @@ -1,24 +1,24 @@ #include "BankInteractServer.h" #include "GameMessages.h" #include "Entity.h" -#include "AMFFormat.h" +#include "Amf3.h" void BankInteractServer::OnUse(Entity* self, Entity* user) { AMFArrayValue args; - AMFStringValue* bank = new AMFStringValue(); - bank->SetStringValue("bank"); - args.InsertValue("state", bank); - GameMessages::SendUIMessageServerToSingleClient(user, user->GetSystemAddress(), "pushGameState", &args); + args.Insert("state", "bank"); + + GameMessages::SendUIMessageServerToSingleClient(user, user->GetSystemAddress(), "pushGameState", args); } void BankInteractServer::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2, int32_t param3) { if (args == "ToggleBank") { AMFArrayValue args; - args.InsertValue("visible", new AMFFalseValue()); - GameMessages::SendUIMessageServerToSingleClient(sender, sender->GetSystemAddress(), "ToggleBank", &args); + args.Insert("visible", false); + + GameMessages::SendUIMessageServerToSingleClient(sender, sender->GetSystemAddress(), "ToggleBank", args); GameMessages::SendNotifyClientObject(self->GetObjectID(), u"CloseBank", 0, 0, LWOOBJID_EMPTY, "", sender->GetSystemAddress()); } diff --git a/dScripts/02_server/Map/General/MailBoxServer.cpp b/dScripts/02_server/Map/General/MailBoxServer.cpp index c2534f3ef..53f3b3a26 100644 --- a/dScripts/02_server/Map/General/MailBoxServer.cpp +++ b/dScripts/02_server/Map/General/MailBoxServer.cpp @@ -1,19 +1,20 @@ #include "MailBoxServer.h" -#include "AMFFormat.h" +#include "Amf3.h" #include "GameMessages.h" +#include "Entity.h" void MailBoxServer::OnUse(Entity* self, Entity* user) { - AMFStringValue* value = new AMFStringValue(); - value->SetStringValue("Mail"); AMFArrayValue args; - args.InsertValue("state", value); - GameMessages::SendUIMessageServerToSingleClient(user, user->GetSystemAddress(), "pushGameState", &args); + + args.Insert("state", "Mail"); + + GameMessages::SendUIMessageServerToSingleClient(user, user->GetSystemAddress(), "pushGameState", args); } void MailBoxServer::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2, int32_t param3) { if (args == "toggleMail") { AMFArrayValue args; - args.InsertValue("visible", new AMFFalseValue()); - GameMessages::SendUIMessageServerToSingleClient(sender, sender->GetSystemAddress(), "ToggleMail", &args); + args.Insert("visible", false); + GameMessages::SendUIMessageServerToSingleClient(sender, sender->GetSystemAddress(), "ToggleMail", args); } } diff --git a/dScripts/02_server/Map/General/StoryBoxInteractServer.cpp b/dScripts/02_server/Map/General/StoryBoxInteractServer.cpp index 2683ddd46..9a1a4908b 100644 --- a/dScripts/02_server/Map/General/StoryBoxInteractServer.cpp +++ b/dScripts/02_server/Map/General/StoryBoxInteractServer.cpp @@ -2,7 +2,8 @@ #include "Character.h" #include "GameMessages.h" #include "dServer.h" -#include "AMFFormat.h" +#include "Amf3.h" +#include "Entity.h" void StoryBoxInteractServer::OnUse(Entity* self, Entity* user) { if (self->GetVar(u"hasCustomText")) { @@ -11,24 +12,18 @@ void StoryBoxInteractServer::OnUse(Entity* self, Entity* user) { { AMFArrayValue args; - auto* state = new AMFStringValue(); - state->SetStringValue("Story"); + args.Insert("state", "Story"); - args.InsertValue("state", state); - - GameMessages::SendUIMessageServerToSingleClient(user, user->GetSystemAddress(), "pushGameState", &args); + GameMessages::SendUIMessageServerToSingleClient(user, user->GetSystemAddress(), "pushGameState", args); } user->AddCallbackTimer(0.1f, [user, customText]() { AMFArrayValue args; - auto* text = new AMFStringValue(); - text->SetStringValue(customText); - - args.InsertValue("visible", new AMFTrueValue()); - args.InsertValue("text", text); + args.Insert("visible", true); + args.Insert("text", customText); - GameMessages::SendUIMessageServerToSingleClient(user, user->GetSystemAddress(), "ToggleStoryBox", &args); + GameMessages::SendUIMessageServerToSingleClient(user, user->GetSystemAddress(), "ToggleStoryBox", args); }); return; diff --git a/dScripts/02_server/Map/NS/NsLegoClubDoor.cpp b/dScripts/02_server/Map/NS/NsLegoClubDoor.cpp index 56a213b81..d7ee5fed0 100644 --- a/dScripts/02_server/Map/NS/NsLegoClubDoor.cpp +++ b/dScripts/02_server/Map/NS/NsLegoClubDoor.cpp @@ -1,7 +1,7 @@ #include "NsLegoClubDoor.h" #include "dZoneManager.h" #include "GameMessages.h" -#include "AMFFormat.h" +#include "Amf3.h" void NsLegoClubDoor::OnStartup(Entity* self) { self->SetVar(u"currentZone", (int32_t)dZoneManager::Instance()->GetZoneID().GetMapID()); @@ -12,116 +12,56 @@ void NsLegoClubDoor::OnStartup(Entity* self) { args = {}; - AMFStringValue* callbackClient = new AMFStringValue(); - callbackClient->SetStringValue(std::to_string(self->GetObjectID())); - args.InsertValue("callbackClient", callbackClient); + args.Insert("callbackClient", std::to_string(self->GetObjectID())); + args.Insert("strIdentifier", "choiceDoor"); + args.Insert("title", "%[UI_CHOICE_DESTINATION]"); - AMFStringValue* strIdentifier = new AMFStringValue(); - strIdentifier->SetStringValue("choiceDoor"); - args.InsertValue("strIdentifier", strIdentifier); - - AMFStringValue* title = new AMFStringValue(); - title->SetStringValue("%[UI_CHOICE_DESTINATION]"); - args.InsertValue("title", title); - - AMFArrayValue* choiceOptions = new AMFArrayValue(); + AMFArrayValue* choiceOptions = args.InsertArray("options"); { - AMFArrayValue* nsArgs = new AMFArrayValue(); - - AMFStringValue* image = new AMFStringValue(); - image->SetStringValue("textures/ui/zone_thumnails/Nimbus_Station.dds"); - nsArgs->InsertValue("image", image); - - AMFStringValue* caption = new AMFStringValue(); - caption->SetStringValue("%[UI_CHOICE_NS]"); - nsArgs->InsertValue("caption", caption); - - AMFStringValue* identifier = new AMFStringValue(); - identifier->SetStringValue("zoneID_1200"); - nsArgs->InsertValue("identifier", identifier); - - AMFStringValue* tooltipText = new AMFStringValue(); - tooltipText->SetStringValue("%[UI_CHOICE_NS_HOVER]"); - nsArgs->InsertValue("tooltipText", tooltipText); + AMFArrayValue* nsArgs = choiceOptions->PushArray(); - choiceOptions->PushBackValue(nsArgs); + nsArgs->Insert("image", "textures/ui/zone_thumnails/Nimbus_Station.dds"); + nsArgs->Insert("caption", "%[UI_CHOICE_NS]"); + nsArgs->Insert("identifier", "zoneID_1200"); + nsArgs->Insert("tooltipText", "%[UI_CHOICE_NS_HOVER]"); } { - AMFArrayValue* ntArgs = new AMFArrayValue(); + AMFArrayValue* ntArgs = choiceOptions->PushArray(); - AMFStringValue* image = new AMFStringValue(); - image->SetStringValue("textures/ui/zone_thumnails/Nexus_Tower.dds"); - ntArgs->InsertValue("image", image); - - AMFStringValue* caption = new AMFStringValue(); - caption->SetStringValue("%[UI_CHOICE_NT]"); - ntArgs->InsertValue("caption", caption); - - AMFStringValue* identifier = new AMFStringValue(); - identifier->SetStringValue("zoneID_1900"); - ntArgs->InsertValue("identifier", identifier); - - AMFStringValue* tooltipText = new AMFStringValue(); - tooltipText->SetStringValue("%[UI_CHOICE_NT_HOVER]"); - ntArgs->InsertValue("tooltipText", tooltipText); - - choiceOptions->PushBackValue(ntArgs); + ntArgs->Insert("image", "textures/ui/zone_thumnails/Nexus_Tower.dds"); + ntArgs->Insert("caption", "%[UI_CHOICE_NT]"); + ntArgs->Insert("identifier", "zoneID_1900"); + ntArgs->Insert("tooltipText", "%[UI_CHOICE_NT_HOVER]"); } options = choiceOptions; - - args.InsertValue("options", choiceOptions); } void NsLegoClubDoor::OnUse(Entity* self, Entity* user) { auto* player = user; if (CheckChoice(self, player)) { - AMFArrayValue* multiArgs = new AMFArrayValue(); + AMFArrayValue multiArgs; - AMFStringValue* callbackClient = new AMFStringValue(); - callbackClient->SetStringValue(std::to_string(self->GetObjectID())); - multiArgs->InsertValue("callbackClient", callbackClient); - - AMFStringValue* strIdentifier = new AMFStringValue(); - strIdentifier->SetStringValue("choiceDoor"); - multiArgs->InsertValue("strIdentifier", strIdentifier); - - AMFStringValue* title = new AMFStringValue(); - title->SetStringValue("%[UI_CHOICE_DESTINATION]"); - multiArgs->InsertValue("title", title); - - multiArgs->InsertValue("options", options); + multiArgs.Insert("callbackClient", std::to_string(self->GetObjectID())); + multiArgs.Insert("strIdentifier", "choiceDoor"); + multiArgs.Insert("title", "%[UI_CHOICE_DESTINATION]"); + multiArgs.Insert("options", static_cast(options)); GameMessages::SendUIMessageServerToSingleClient(player, player->GetSystemAddress(), "QueueChoiceBox", multiArgs); - } else if (self->GetVar(u"currentZone") != m_ChoiceZoneID) { - AMFArrayValue* multiArgs = new AMFArrayValue(); - - AMFStringValue* state = new AMFStringValue(); - state->SetStringValue("Lobby"); - multiArgs->InsertValue("state", state); - - AMFArrayValue* context = new AMFArrayValue(); - AMFStringValue* user = new AMFStringValue(); - user->SetStringValue(std::to_string(player->GetObjectID())); - context->InsertValue("user", user); - - AMFStringValue* callbackObj = new AMFStringValue(); - callbackObj->SetStringValue(std::to_string(self->GetObjectID())); - context->InsertValue("callbackObj", callbackObj); - - AMFStringValue* helpVisible = new AMFStringValue(); - helpVisible->SetStringValue("show"); - context->InsertValue("HelpVisible", helpVisible); - - AMFStringValue* type = new AMFStringValue(); - type->SetStringValue("Lego_Club_Valid"); - context->InsertValue("type", type); - - multiArgs->InsertValue("context", context); + multiArgs.Remove("options", false); // We do not want the local amf to delete the options! + } else if (self->GetVar(u"currentZone") != m_ChoiceZoneID) { + AMFArrayValue multiArgs; + multiArgs.Insert("state", "Lobby"); + + AMFArrayValue* context = multiArgs.InsertArray("context"); + context->Insert("user", std::to_string(player->GetObjectID())); + context->Insert("callbackObj", std::to_string(self->GetObjectID())); + context->Insert("HelpVisible", "show"); + context->Insert("type", "Lego_Club_Valid"); GameMessages::SendUIMessageServerToSingleClient(player, player->GetSystemAddress(), "pushGameState", multiArgs); } else { diff --git a/dScripts/02_server/Map/NS/NsLegoClubDoor.h b/dScripts/02_server/Map/NS/NsLegoClubDoor.h index db1dcae4f..5b25ba6d0 100644 --- a/dScripts/02_server/Map/NS/NsLegoClubDoor.h +++ b/dScripts/02_server/Map/NS/NsLegoClubDoor.h @@ -2,7 +2,7 @@ #include "CppScripts.h" #include "ChooseYourDestinationNsToNt.h" #include "BaseConsoleTeleportServer.h" -#include "AMFFormat.h" +#include "Amf3.h" class NsLegoClubDoor : public CppScripts::Script, ChooseYourDestinationNsToNt, BaseConsoleTeleportServer { diff --git a/dScripts/02_server/Map/NS/NsLupTeleport.cpp b/dScripts/02_server/Map/NS/NsLupTeleport.cpp index 9cd4359b8..74f8ace16 100644 --- a/dScripts/02_server/Map/NS/NsLupTeleport.cpp +++ b/dScripts/02_server/Map/NS/NsLupTeleport.cpp @@ -1,7 +1,7 @@ #include "NsLupTeleport.h" #include "dZoneManager.h" #include "GameMessages.h" -#include "AMFFormat.h" +#include "Amf3.h" void NsLupTeleport::OnStartup(Entity* self) { self->SetVar(u"currentZone", (int32_t)dZoneManager::Instance()->GetZoneID().GetMapID()); @@ -12,72 +12,36 @@ void NsLupTeleport::OnStartup(Entity* self) { args = {}; - AMFStringValue* callbackClient = new AMFStringValue(); - callbackClient->SetStringValue(std::to_string(self->GetObjectID())); - args.InsertValue("callbackClient", callbackClient); + args.Insert("callbackClient", std::to_string(self->GetObjectID())); + args.Insert("strIdentifier", "choiceDoor"); + args.Insert("title", "%[UI_CHOICE_DESTINATION]"); - AMFStringValue* strIdentifier = new AMFStringValue(); - strIdentifier->SetStringValue("choiceDoor"); - args.InsertValue("strIdentifier", strIdentifier); - - AMFStringValue* title = new AMFStringValue(); - title->SetStringValue("%[UI_CHOICE_DESTINATION]"); - args.InsertValue("title", title); - - AMFArrayValue* choiceOptions = new AMFArrayValue(); + AMFArrayValue* choiceOptions = args.InsertArray("options"); { - AMFArrayValue* nsArgs = new AMFArrayValue(); - - AMFStringValue* image = new AMFStringValue(); - image->SetStringValue("textures/ui/zone_thumnails/Nimbus_Station.dds"); - nsArgs->InsertValue("image", image); - - AMFStringValue* caption = new AMFStringValue(); - caption->SetStringValue("%[UI_CHOICE_NS]"); - nsArgs->InsertValue("caption", caption); - - AMFStringValue* identifier = new AMFStringValue(); - identifier->SetStringValue("zoneID_1200"); - nsArgs->InsertValue("identifier", identifier); - - AMFStringValue* tooltipText = new AMFStringValue(); - tooltipText->SetStringValue("%[UI_CHOICE_NS_HOVER]"); - nsArgs->InsertValue("tooltipText", tooltipText); + AMFArrayValue* nsArgs = choiceOptions->PushArray(); - choiceOptions->PushBackValue(nsArgs); + nsArgs->Insert("image", "textures/ui/zone_thumnails/Nimbus_Station.dds"); + nsArgs->Insert("caption", "%[UI_CHOICE_NS]"); + nsArgs->Insert("identifier", "zoneID_1200"); + nsArgs->Insert("tooltipText", "%[UI_CHOICE_NS_HOVER]"); } { - AMFArrayValue* ntArgs = new AMFArrayValue(); + AMFArrayValue* ntArgs = choiceOptions->PushArray(); - AMFStringValue* image = new AMFStringValue(); - image->SetStringValue("textures/ui/zone_thumnails/Nexus_Tower.dds"); - ntArgs->InsertValue("image", image); - - AMFStringValue* caption = new AMFStringValue(); - caption->SetStringValue("%[UI_CHOICE_NT]"); - ntArgs->InsertValue("caption", caption); - - AMFStringValue* identifier = new AMFStringValue(); - identifier->SetStringValue("zoneID_1900"); - ntArgs->InsertValue("identifier", identifier); - - AMFStringValue* tooltipText = new AMFStringValue(); - tooltipText->SetStringValue("%[UI_CHOICE_NT_HOVER]"); - ntArgs->InsertValue("tooltipText", tooltipText); - - choiceOptions->PushBackValue(ntArgs); + ntArgs->Insert("image", "textures/ui/zone_thumnails/Nexus_Tower.dds"); + ntArgs->Insert("caption", "%[UI_CHOICE_NT]"); + ntArgs->Insert("identifier", "zoneID_1900"); + ntArgs->Insert("tooltipText", "%[UI_CHOICE_NT_HOVER]"); } - - args.InsertValue("options", choiceOptions); } void NsLupTeleport::OnUse(Entity* self, Entity* user) { auto* player = user; if (CheckChoice(self, player)) { - GameMessages::SendUIMessageServerToSingleClient(player, player->GetSystemAddress(), "QueueChoiceBox", &args); + GameMessages::SendUIMessageServerToSingleClient(player, player->GetSystemAddress(), "QueueChoiceBox", args); } else { BaseOnUse(self, player); } diff --git a/dScripts/02_server/Map/NS/NsLupTeleport.h b/dScripts/02_server/Map/NS/NsLupTeleport.h index 28bab016c..385e92c77 100644 --- a/dScripts/02_server/Map/NS/NsLupTeleport.h +++ b/dScripts/02_server/Map/NS/NsLupTeleport.h @@ -2,7 +2,7 @@ #include "CppScripts.h" #include "ChooseYourDestinationNsToNt.h" #include "BaseConsoleTeleportServer.h" -#include "AMFFormat.h" +#include "Amf3.h" class NsLupTeleport : public CppScripts::Script, ChooseYourDestinationNsToNt, BaseConsoleTeleportServer { diff --git a/dScripts/02_server/Map/NT/NtConsoleTeleportServer.cpp b/dScripts/02_server/Map/NT/NtConsoleTeleportServer.cpp index 324a2fc04..8ba697ce5 100644 --- a/dScripts/02_server/Map/NT/NtConsoleTeleportServer.cpp +++ b/dScripts/02_server/Map/NT/NtConsoleTeleportServer.cpp @@ -1,6 +1,6 @@ #include "NtConsoleTeleportServer.h" #include "Entity.h" -#include "AMFFormat.h" +#include "Amf3.h" void NtConsoleTeleportServer::OnStartup(Entity* self) { self->SetVar(u"teleportAnim", m_TeleportAnim); diff --git a/dScripts/02_server/Map/Property/PropertyBankInteract.cpp b/dScripts/02_server/Map/Property/PropertyBankInteract.cpp index 9e727f39c..282dce6cd 100644 --- a/dScripts/02_server/Map/Property/PropertyBankInteract.cpp +++ b/dScripts/02_server/Map/Property/PropertyBankInteract.cpp @@ -1,7 +1,8 @@ #include "PropertyBankInteract.h" #include "EntityManager.h" #include "GameMessages.h" -#include "AMFFormat.h" +#include "Amf3.h" +#include "Entity.h" void PropertyBankInteract::OnStartup(Entity* self) { auto* zoneControl = EntityManager::Instance()->GetZoneControlEntity(); @@ -20,11 +21,10 @@ void PropertyBankInteract::OnPlayerLoaded(Entity* self, Entity* player) { void PropertyBankInteract::OnUse(Entity* self, Entity* user) { AMFArrayValue args; - auto* value = new AMFStringValue(); - value->SetStringValue("bank"); - args.InsertValue("state", value); - GameMessages::SendUIMessageServerToSingleClient(user, user->GetSystemAddress(), "pushGameState", &args); + args.Insert("state", "bank"); + + GameMessages::SendUIMessageServerToSingleClient(user, user->GetSystemAddress(), "pushGameState", args); GameMessages::SendNotifyClientObject(self->GetObjectID(), u"OpenBank", 0, 0, LWOOBJID_EMPTY, "", user->GetSystemAddress()); @@ -34,9 +34,10 @@ void PropertyBankInteract::OnFireEventServerSide(Entity* self, Entity* sender, s int32_t param2, int32_t param3) { if (args == "ToggleBank") { AMFArrayValue amfArgs; - amfArgs.InsertValue("visible", new AMFFalseValue()); - GameMessages::SendUIMessageServerToSingleClient(sender, sender->GetSystemAddress(), "ToggleBank", &amfArgs); + amfArgs.Insert("visible", false); + + GameMessages::SendUIMessageServerToSingleClient(sender, sender->GetSystemAddress(), "ToggleBank", amfArgs); GameMessages::SendNotifyClientObject(self->GetObjectID(), u"CloseBank", 0, 0, LWOOBJID_EMPTY, "", sender->GetSystemAddress()); diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index 5dabce1c2..186259609 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -60,7 +60,7 @@ #include "AssetManager.h" #include "LevelProgressionComponent.h" #include "eBlueprintSaveResponseType.h" -#include "AMFFormat.h" +#include "Amf3.h" #include "NiPoint3.h" #include "eServerDisconnectIdentifiers.h" #include "eObjectBits.h" @@ -598,15 +598,11 @@ void HandlePacketChat(Packet* packet) { //Send to our clients: AMFArrayValue args; - auto* titleValue = new AMFStringValue(); - titleValue->SetStringValue(title.c_str()); - auto* messageValue = new AMFStringValue(); - messageValue->SetStringValue(msg.c_str()); - args.InsertValue("title", titleValue); - args.InsertValue("message", messageValue); + args.Insert("title", title); + args.Insert("message", msg); - GameMessages::SendUIMessageServerToAllClients("ToggleAnnounce", &args); + GameMessages::SendUIMessageServerToAllClients("ToggleAnnounce", args); break; } diff --git a/tests/dCommonTests/AMFDeserializeTests.cpp b/tests/dCommonTests/AMFDeserializeTests.cpp index b679ea78e..5a9d91e61 100644 --- a/tests/dCommonTests/AMFDeserializeTests.cpp +++ b/tests/dCommonTests/AMFDeserializeTests.cpp @@ -3,14 +3,17 @@ #include #include "AMFDeserialize.h" -#include "AMFFormat.h" +#include "Amf3.h" + +#include "Game.h" +#include "dLogger.h" /** * Helper method that all tests use to get their respective AMF. */ -std::unique_ptr ReadFromBitStream(RakNet::BitStream* bitStream) { +AMFBaseValue* ReadFromBitStream(RakNet::BitStream* bitStream) { AMFDeserialize deserializer; - std::unique_ptr returnValue(deserializer.Read(bitStream)); + AMFBaseValue* returnValue(deserializer.Read(bitStream)); return returnValue; } @@ -18,10 +21,10 @@ std::unique_ptr ReadFromBitStream(RakNet::BitStream* bitStream) { * @brief Test reading an AMFUndefined value from a BitStream. */ TEST(dCommonTests, AMFDeserializeAMFUndefinedTest) { - CBITSTREAM + CBITSTREAM; bitStream.Write(0x00); - std::unique_ptr res(ReadFromBitStream(&bitStream)); - ASSERT_EQ(res->GetValueType(), AMFValueType::AMFUndefined); + std::unique_ptr res(ReadFromBitStream(&bitStream)); + ASSERT_EQ(res->GetValueType(), eAmf::Undefined); } /** @@ -29,54 +32,54 @@ TEST(dCommonTests, AMFDeserializeAMFUndefinedTest) { * */ TEST(dCommonTests, AMFDeserializeAMFNullTest) { - CBITSTREAM + CBITSTREAM; bitStream.Write(0x01); - std::unique_ptr res(ReadFromBitStream(&bitStream)); - ASSERT_EQ(res->GetValueType(), AMFValueType::AMFNull); + std::unique_ptr res(ReadFromBitStream(&bitStream)); + ASSERT_EQ(res->GetValueType(), eAmf::Null); } /** * @brief Test reading an AMFFalse value from a BitStream. */ TEST(dCommonTests, AMFDeserializeAMFFalseTest) { - CBITSTREAM + CBITSTREAM; bitStream.Write(0x02); - std::unique_ptr res(ReadFromBitStream(&bitStream)); - ASSERT_EQ(res->GetValueType(), AMFValueType::AMFFalse); + std::unique_ptr res(ReadFromBitStream(&bitStream)); + ASSERT_EQ(res->GetValueType(), eAmf::False); } /** * @brief Test reading an AMFTrue value from a BitStream. */ TEST(dCommonTests, AMFDeserializeAMFTrueTest) { - CBITSTREAM + CBITSTREAM; bitStream.Write(0x03); - std::unique_ptr res(ReadFromBitStream(&bitStream)); - ASSERT_EQ(res->GetValueType(), AMFValueType::AMFTrue); + std::unique_ptr res(ReadFromBitStream(&bitStream)); + ASSERT_EQ(res->GetValueType(), eAmf::True); } /** * @brief Test reading an AMFInteger value from a BitStream. */ TEST(dCommonTests, AMFDeserializeAMFIntegerTest) { - CBITSTREAM + CBITSTREAM; { bitStream.Write(0x04); // 127 == 01111111 bitStream.Write(127); - std::unique_ptr res(ReadFromBitStream(&bitStream)); - ASSERT_EQ(res->GetValueType(), AMFValueType::AMFInteger); + std::unique_ptr res(ReadFromBitStream(&bitStream)); + ASSERT_EQ(res->GetValueType(), eAmf::Integer); // Check that the max value of a byte can be read correctly - ASSERT_EQ(static_cast(res.get())->GetIntegerValue(), 127); + ASSERT_EQ(static_cast(res.get())->GetValue(), 127); } bitStream.Reset(); { bitStream.Write(0x04); bitStream.Write(UINT32_MAX); - std::unique_ptr res(ReadFromBitStream(&bitStream)); - ASSERT_EQ(res->GetValueType(), AMFValueType::AMFInteger); + std::unique_ptr res(ReadFromBitStream(&bitStream)); + ASSERT_EQ(res->GetValueType(), eAmf::Integer); // Check that we can read the maximum value correctly - ASSERT_EQ(static_cast(res.get())->GetIntegerValue(), 536870911); + ASSERT_EQ(static_cast(res.get())->GetValue(), 536870911); } bitStream.Reset(); { @@ -87,10 +90,10 @@ TEST(dCommonTests, AMFDeserializeAMFIntegerTest) { bitStream.Write(255); // 127 == 01111111 bitStream.Write(127); - std::unique_ptr res(ReadFromBitStream(&bitStream)); - ASSERT_EQ(res->GetValueType(), AMFValueType::AMFInteger); + std::unique_ptr res(ReadFromBitStream(&bitStream)); + ASSERT_EQ(res->GetValueType(), eAmf::Integer); // Check that short max can be read correctly - ASSERT_EQ(static_cast(res.get())->GetIntegerValue(), UINT16_MAX); + ASSERT_EQ(static_cast(res.get())->GetValue(), UINT16_MAX); } bitStream.Reset(); { @@ -99,10 +102,10 @@ TEST(dCommonTests, AMFDeserializeAMFIntegerTest) { bitStream.Write(255); // 127 == 01111111 bitStream.Write(127); - std::unique_ptr res(ReadFromBitStream(&bitStream)); - ASSERT_EQ(res->GetValueType(), AMFValueType::AMFInteger); + std::unique_ptr res(ReadFromBitStream(&bitStream)); + ASSERT_EQ(res->GetValueType(), eAmf::Integer); // Check that 2 byte max can be read correctly - ASSERT_EQ(static_cast(res.get())->GetIntegerValue(), 16383); + ASSERT_EQ(static_cast(res.get())->GetValue(), 16383); } } @@ -110,42 +113,42 @@ TEST(dCommonTests, AMFDeserializeAMFIntegerTest) { * @brief Test reading an AMFDouble value from a BitStream. */ TEST(dCommonTests, AMFDeserializeAMFDoubleTest) { - CBITSTREAM + CBITSTREAM; bitStream.Write(0x05); bitStream.Write(25346.4f); - std::unique_ptr res(ReadFromBitStream(&bitStream)); - ASSERT_EQ(res->GetValueType(), AMFValueType::AMFDouble); - ASSERT_EQ(static_cast(res.get())->GetDoubleValue(), 25346.4f); + std::unique_ptr res(ReadFromBitStream(&bitStream)); + ASSERT_EQ(res->GetValueType(), eAmf::Double); + ASSERT_EQ(static_cast(res.get())->GetValue(), 25346.4f); } /** * @brief Test reading an AMFString value from a BitStream. */ TEST(dCommonTests, AMFDeserializeAMFStringTest) { - CBITSTREAM + CBITSTREAM; bitStream.Write(0x06); bitStream.Write(0x0F); std::string toWrite = "stateID"; for (auto e : toWrite) bitStream.Write(e); - std::unique_ptr res(ReadFromBitStream(&bitStream)); - ASSERT_EQ(res->GetValueType(), AMFValueType::AMFString); - ASSERT_EQ(static_cast(res.get())->GetStringValue(), "stateID"); + std::unique_ptr res(ReadFromBitStream(&bitStream)); + ASSERT_EQ(res->GetValueType(), eAmf::String); + ASSERT_EQ(static_cast(res.get())->GetValue(), "stateID"); } /** * @brief Test reading an AMFArray value from a BitStream. */ TEST(dCommonTests, AMFDeserializeAMFArrayTest) { - CBITSTREAM + CBITSTREAM; // Test empty AMFArray bitStream.Write(0x09); bitStream.Write(0x01); bitStream.Write(0x01); { - std::unique_ptr res(ReadFromBitStream(&bitStream)); - ASSERT_EQ(res->GetValueType(), AMFValueType::AMFArray); - ASSERT_EQ(static_cast(res.get())->GetAssociativeMap().size(), 0); - ASSERT_EQ(static_cast(res.get())->GetDenseArray().size(), 0); + std::unique_ptr res(ReadFromBitStream(&bitStream)); + ASSERT_EQ(res->GetValueType(), eAmf::Array); + ASSERT_EQ(static_cast(res.get())->GetAssociative().size(), 0); + ASSERT_EQ(static_cast(res.get())->GetDense().size(), 0); } bitStream.Reset(); // Test a key'd value and dense value @@ -161,32 +164,32 @@ TEST(dCommonTests, AMFDeserializeAMFArrayTest) { bitStream.Write(0x0B); for (auto e : "10447") if (e != '\0') bitStream.Write(e); { - std::unique_ptr res(ReadFromBitStream(&bitStream)); - ASSERT_EQ(res->GetValueType(), AMFValueType::AMFArray); - ASSERT_EQ(static_cast(res.get())->GetAssociativeMap().size(), 1); - ASSERT_EQ(static_cast(res.get())->GetDenseArray().size(), 1); - ASSERT_EQ(static_cast(res.get())->FindValue("BehaviorID")->GetStringValue(), "10447"); - ASSERT_EQ(static_cast(res.get())->GetValueAt(0)->GetStringValue(), "10447"); + std::unique_ptr res(ReadFromBitStream(&bitStream)); + ASSERT_EQ(res->GetValueType(), eAmf::Array); + ASSERT_EQ(static_cast(res.get())->GetAssociative().size(), 1); + ASSERT_EQ(static_cast(res.get())->GetDense().size(), 1); + ASSERT_EQ(static_cast(res.get())->Get("BehaviorID")->GetValue(), "10447"); + ASSERT_EQ(static_cast(res.get())->Get(0)->GetValue(), "10447"); } } /** - * @brief This test checks that if we recieve an unimplemented AMFValueType + * @brief This test checks that if we recieve an unimplemented eAmf * we correctly throw an error and can actch it. * Yes this leaks memory. */ TEST(dCommonTests, AMFDeserializeUnimplementedValuesTest) { - std::vector unimplementedValues = { - AMFValueType::AMFXMLDoc, - AMFValueType::AMFDate, - AMFValueType::AMFObject, - AMFValueType::AMFXML, - AMFValueType::AMFByteArray, - AMFValueType::AMFVectorInt, - AMFValueType::AMFVectorUInt, - AMFValueType::AMFVectorDouble, - AMFValueType::AMFVectorObject, - AMFValueType::AMFDictionary + std::vector unimplementedValues = { + eAmf::XMLDoc, + eAmf::Date, + eAmf::Object, + eAmf::XML, + eAmf::ByteArray, + eAmf::VectorInt, + eAmf::VectorUInt, + eAmf::VectorDouble, + eAmf::VectorObject, + eAmf::Dictionary }; // Run unimplemented tests to check that errors are thrown if // unimplemented AMF values are attempted to be parsed. @@ -202,16 +205,16 @@ TEST(dCommonTests, AMFDeserializeUnimplementedValuesTest) { fileStream.close(); - for (auto amfValueType : unimplementedValues) { + for (auto value : unimplementedValues) { RakNet::BitStream testBitStream; for (auto element : baseBitStream) { testBitStream.Write(element); } - testBitStream.Write(amfValueType); + testBitStream.Write(value); bool caughtException = false; try { ReadFromBitStream(&testBitStream); - } catch (AMFValueType unimplementedValueType) { + } catch (eAmf unimplementedValueType) { caughtException = true; } @@ -235,116 +238,116 @@ TEST(dCommonTests, AMFDeserializeLivePacketTest) { testFileStream.close(); - auto resultFromFn = ReadFromBitStream(&testBitStream); + std::unique_ptr resultFromFn(ReadFromBitStream(&testBitStream)); auto result = static_cast(resultFromFn.get()); // Test the outermost array - ASSERT_EQ(result->FindValue("BehaviorID")->GetStringValue(), "10447"); - ASSERT_EQ(result->FindValue("objectID")->GetStringValue(), "288300744895913279"); + ASSERT_EQ(result->Get("BehaviorID")->GetValue(), "10447"); + ASSERT_EQ(result->Get("objectID")->GetValue(), "288300744895913279"); // Test the execution state array - auto executionState = result->FindValue("executionState"); + auto executionState = result->GetArray("executionState"); ASSERT_NE(executionState, nullptr); - auto strips = executionState->FindValue("strips")->GetDenseArray(); + auto strips = executionState->GetArray("strips")->GetDense(); ASSERT_EQ(strips.size(), 1); auto stripsPosition0 = dynamic_cast(strips[0]); - auto actionIndex = stripsPosition0->FindValue("actionIndex"); + auto actionIndex = stripsPosition0->Get("actionIndex"); - ASSERT_EQ(actionIndex->GetDoubleValue(), 0.0f); + ASSERT_EQ(actionIndex->GetValue(), 0.0f); - auto stripIdExecution = stripsPosition0->FindValue("id"); + auto stripIdExecution = stripsPosition0->Get("id"); - ASSERT_EQ(stripIdExecution->GetDoubleValue(), 0.0f); + ASSERT_EQ(stripIdExecution->GetValue(), 0.0f); - auto stateIDExecution = executionState->FindValue("stateID"); + auto stateIdExecution = executionState->Get("stateID"); - ASSERT_EQ(stateIDExecution->GetDoubleValue(), 0.0f); + ASSERT_EQ(stateIdExecution->GetValue(), 0.0f); - auto states = result->FindValue("states")->GetDenseArray(); + auto states = result->GetArray("states")->GetDense(); ASSERT_EQ(states.size(), 1); auto firstState = dynamic_cast(states[0]); - auto stateID = firstState->FindValue("id"); + auto stateID = firstState->Get("id"); - ASSERT_EQ(stateID->GetDoubleValue(), 0.0f); + ASSERT_EQ(stateID->GetValue(), 0.0f); - auto stripsInState = firstState->FindValue("strips")->GetDenseArray(); + auto stripsInState = firstState->GetArray("strips")->GetDense(); ASSERT_EQ(stripsInState.size(), 1); auto firstStrip = dynamic_cast(stripsInState[0]); - auto actionsInFirstStrip = firstStrip->FindValue("actions")->GetDenseArray(); + auto actionsInFirstStrip = firstStrip->GetArray("actions")->GetDense(); ASSERT_EQ(actionsInFirstStrip.size(), 3); - auto actionID = firstStrip->FindValue("id"); + auto actionID = firstStrip->Get("id"); - ASSERT_EQ(actionID->GetDoubleValue(), 0.0f); + ASSERT_EQ(actionID->GetValue(), 0.0f); - auto uiArray = firstStrip->FindValue("ui"); + auto uiArray = firstStrip->GetArray("ui"); - auto xPos = uiArray->FindValue("x"); - auto yPos = uiArray->FindValue("y"); + auto xPos = uiArray->Get("x"); + auto yPos = uiArray->Get("y"); - ASSERT_EQ(xPos->GetDoubleValue(), 103.0f); - ASSERT_EQ(yPos->GetDoubleValue(), 82.0f); + ASSERT_EQ(xPos->GetValue(), 103.0f); + ASSERT_EQ(yPos->GetValue(), 82.0f); - auto stripId = firstStrip->FindValue("id"); + auto stripId = firstStrip->Get("id"); - ASSERT_EQ(stripId->GetDoubleValue(), 0.0f); + ASSERT_EQ(stripId->GetValue(), 0.0f); auto firstAction = dynamic_cast(actionsInFirstStrip[0]); - auto firstType = firstAction->FindValue("Type"); + auto firstType = firstAction->Get("Type"); - ASSERT_EQ(firstType->GetStringValue(), "OnInteract"); + ASSERT_EQ(firstType->GetValue(), "OnInteract"); - auto firstCallback = firstAction->FindValue("__callbackID__"); + auto firstCallback = firstAction->Get("__callbackID__"); - ASSERT_EQ(firstCallback->GetStringValue(), ""); + ASSERT_EQ(firstCallback->GetValue(), ""); auto secondAction = dynamic_cast(actionsInFirstStrip[1]); - auto secondType = secondAction->FindValue("Type"); + auto secondType = secondAction->Get("Type"); - ASSERT_EQ(secondType->GetStringValue(), "FlyUp"); + ASSERT_EQ(secondType->GetValue(), "FlyUp"); - auto secondCallback = secondAction->FindValue("__callbackID__"); + auto secondCallback = secondAction->Get("__callbackID__"); - ASSERT_EQ(secondCallback->GetStringValue(), ""); + ASSERT_EQ(secondCallback->GetValue(), ""); - auto secondDistance = secondAction->FindValue("Distance"); + auto secondDistance = secondAction->Get("Distance"); - ASSERT_EQ(secondDistance->GetDoubleValue(), 25.0f); + ASSERT_EQ(secondDistance->GetValue(), 25.0f); auto thirdAction = dynamic_cast(actionsInFirstStrip[2]); - auto thirdType = thirdAction->FindValue("Type"); + auto thirdType = thirdAction->Get("Type"); - ASSERT_EQ(thirdType->GetStringValue(), "FlyDown"); + ASSERT_EQ(thirdType->GetValue(), "FlyDown"); - auto thirdCallback = thirdAction->FindValue("__callbackID__"); + auto thirdCallback = thirdAction->Get("__callbackID__"); - ASSERT_EQ(thirdCallback->GetStringValue(), ""); + ASSERT_EQ(thirdCallback->GetValue(), ""); - auto thirdDistance = thirdAction->FindValue("Distance"); + auto thirdDistance = thirdAction->Get("Distance"); - ASSERT_EQ(thirdDistance->GetDoubleValue(), 25.0f); + ASSERT_EQ(thirdDistance->GetValue(), 25.0f); } /** * @brief Tests that having no BitStream returns a nullptr. */ TEST(dCommonTests, AMFDeserializeNullTest) { - auto result = ReadFromBitStream(nullptr); + std::unique_ptr result(ReadFromBitStream(nullptr)); ASSERT_EQ(result.get(), nullptr); } @@ -361,25 +364,25 @@ TEST(dCommonTests, AMFBadConversionTest) { testFileStream.close(); - auto resultFromFn = ReadFromBitStream(&testBitStream); + std::unique_ptr resultFromFn(ReadFromBitStream(&testBitStream)); auto result = static_cast(resultFromFn.get()); // Actually a string value. - ASSERT_EQ(result->FindValue("BehaviorID"), nullptr); + ASSERT_EQ(result->Get("BehaviorID"), nullptr); // Does not exist in the associative portion - ASSERT_EQ(result->FindValue("DOES_NOT_EXIST"), nullptr); + ASSERT_EQ(result->Get("DOES_NOT_EXIST"), nullptr); - result->PushBackValue(new AMFTrueValue()); + result->Push(true); // Exists and is correct type - ASSERT_NE(result->GetValueAt(0), nullptr); + ASSERT_NE(result->Get(0), nullptr); // Value exists but is wrong typing - ASSERT_EQ(result->GetValueAt(0), nullptr); + ASSERT_EQ(result->Get(0), nullptr); // Value is out of bounds - ASSERT_EQ(result->GetValueAt(1), nullptr); + ASSERT_EQ(result->Get(1), nullptr); } /** diff --git a/tests/dCommonTests/Amf3Tests.cpp b/tests/dCommonTests/Amf3Tests.cpp new file mode 100644 index 000000000..a51fe4ba4 --- /dev/null +++ b/tests/dCommonTests/Amf3Tests.cpp @@ -0,0 +1,116 @@ +#include + +#include + +#include "Amf3.h" + +TEST(dCommonTests, AMF3AssociativeArrayTest) { + + AMFArrayValue array; + array.Insert("true", true); + array.Insert("false", false); + + // test associative can insert values + ASSERT_EQ(array.GetAssociative().size(), 2); + ASSERT_EQ(array.Get("true")->GetValueType(), eAmf::True); + ASSERT_EQ(array.Get("false")->GetValueType(), eAmf::False); + + // Test associative can remove values + array.Remove("true"); + ASSERT_EQ(array.GetAssociative().size(), 1); + ASSERT_EQ(array.Get("true"), nullptr); + ASSERT_EQ(array.Get("false")->GetValueType(), eAmf::False); + + array.Remove("false"); + ASSERT_EQ(array.GetAssociative().size(), 0); + ASSERT_EQ(array.Get("true"), nullptr); + ASSERT_EQ(array.Get("false"), nullptr); + + // Test that multiple of the same key respect only the first element of that key + array.Insert("true", true); + array.Insert("true", false); + ASSERT_EQ(array.GetAssociative().size(), 1); + ASSERT_EQ(array.Get("true")->GetValueType(), eAmf::True); + array.Remove("true"); + + // Now test the dense portion + // Get some out of bounds values and cast to incorrect template types + array.Push(true); + array.Push(false); + + ASSERT_EQ(array.GetDense().size(), 2); + ASSERT_EQ(array.Get(0)->GetValueType(), eAmf::True); + ASSERT_EQ(array.Get(0), nullptr); + ASSERT_EQ(array.Get(1)->GetValueType(), eAmf::False); + ASSERT_EQ(array.Get(155), nullptr); + + array.Pop(); + + ASSERT_EQ(array.GetDense().size(), 1); + ASSERT_EQ(array.Get(0)->GetValueType(), eAmf::True); + ASSERT_EQ(array.Get(0), nullptr); + ASSERT_EQ(array.Get(1), nullptr); + + array.Pop(); + + ASSERT_EQ(array.GetDense().size(), 0); + ASSERT_EQ(array.Get(0), nullptr); + ASSERT_EQ(array.Get(0), nullptr); + ASSERT_EQ(array.Get(1), nullptr); +} + +TEST(dCommonTests, AMF3InsertionAssociativeTest) { + AMFArrayValue array; + array.Insert("CString", "string"); + array.Insert("String", std::string("string")); + array.Insert("False", false); + array.Insert("True", true); + array.Insert("Integer", 42U); + array.Insert("Double", 42.0); + array.InsertArray("Array"); + array.Insert>("Undefined", {}); + array.Insert("Null", nullptr); + + std::cout << "test" << std::endl; + ASSERT_EQ(array.Get("CString")->GetValueType(), eAmf::String); + std::cout << "test" << std::endl; + ASSERT_EQ(array.Get("String")->GetValueType(), eAmf::String); + std::cout << "test" << std::endl; + ASSERT_EQ(array.Get("False")->GetValueType(), eAmf::False); + std::cout << "test" << std::endl; + ASSERT_EQ(array.Get("True")->GetValueType(), eAmf::True); + std::cout << "test" << std::endl; + ASSERT_EQ(array.Get("Integer")->GetValueType(), eAmf::Integer); + std::cout << "test" << std::endl; + ASSERT_EQ(array.Get("Double")->GetValueType(), eAmf::Double); + std::cout << "test" << std::endl; + ASSERT_EQ(array.GetArray("Array")->GetValueType(), eAmf::Array); + std::cout << "test" << std::endl; + ASSERT_EQ(array.Get("Null")->GetValueType(), eAmf::Null); + std::cout << "test" << std::endl; + ASSERT_EQ(array.Get>("Undefined")->GetValueType(), eAmf::Undefined); + std::cout << "test" << std::endl; +} + +TEST(dCommonTests, AMF3InsertionDenseTest) { + AMFArrayValue array; + array.Push("string"); + array.Push("CString"); + array.Push(false); + array.Push(true); + array.Push(42U); + array.Push(42.0); + array.PushArray(); + array.Push(nullptr); + array.Push>({}); + + ASSERT_EQ(array.Get(0)->GetValueType(), eAmf::String); + ASSERT_EQ(array.Get(1)->GetValueType(), eAmf::String); + ASSERT_EQ(array.Get(2)->GetValueType(), eAmf::False); + ASSERT_EQ(array.Get(3)->GetValueType(), eAmf::True); + ASSERT_EQ(array.Get(4)->GetValueType(), eAmf::Integer); + ASSERT_EQ(array.Get(5)->GetValueType(), eAmf::Double); + ASSERT_EQ(array.GetArray(6)->GetValueType(), eAmf::Array); + ASSERT_EQ(array.Get(7)->GetValueType(), eAmf::Null); + ASSERT_EQ(array.Get>(8)->GetValueType(), eAmf::Undefined); +} diff --git a/tests/dCommonTests/CMakeLists.txt b/tests/dCommonTests/CMakeLists.txt index 444afbdde..a345863d8 100644 --- a/tests/dCommonTests/CMakeLists.txt +++ b/tests/dCommonTests/CMakeLists.txt @@ -1,5 +1,6 @@ set(DCOMMONTEST_SOURCES "AMFDeserializeTests.cpp" + "Amf3Tests.cpp" "HeaderSkipTest.cpp" "TestLDFFormat.cpp" "TestNiPoint3.cpp" diff --git a/tests/dGameTests/dGameMessagesTests/GameMessageTests.cpp b/tests/dGameTests/dGameMessagesTests/GameMessageTests.cpp index 631f0d2db..047f56d65 100644 --- a/tests/dGameTests/dGameMessagesTests/GameMessageTests.cpp +++ b/tests/dGameTests/dGameMessagesTests/GameMessageTests.cpp @@ -1,5 +1,5 @@ #include "Action.h" -#include "AMFFormat.h" +#include "Amf3.h" #include "AMFDeserialize.h" #include "GameMessages.h" #include "GameDependencies.h" @@ -40,8 +40,8 @@ class GameMessageTests: public GameDependenciesTest { } AMFArrayValue* ReadArrayFromBitStream(RakNet::BitStream* inStream) { AMFDeserialize des; - AMFValue* readArray = des.Read(inStream); - EXPECT_EQ(readArray->GetValueType(), AMFValueType::AMFArray); + AMFBaseValue* readArray = des.Read(inStream); + EXPECT_EQ(readArray->GetValueType(), eAmf::Array); return static_cast(readArray); } };