From 53877a0bc35be5114b8e4e4ee296b8a449deb523 Mon Sep 17 00:00:00 2001 From: jadebenn Date: Mon, 18 Nov 2024 20:45:24 -0600 Subject: [PATCH] refactor: Rewrite AMF and property behavior logic to use smart pointers, references, and string_views over raw pointers and std::string& (#1452) * Rewrite AMF and behavior logic to use smart pointers, references, and string_views over raw pointers and std::string& * fix m_BehaviorID initialization * Fix BlockDefinition member naming * remove redundant reset()s * Replace UB forward template declarations with header include * remove unneeded comment * remove non-const ref getters * simplify default behavior id initialization * Fix invalidated use of Getter to set a value * Update AddStripMessage.cpp - change push_back to emplace_back * fix pointer to ref conversion mistake (should not have directly grabbed from the other branch commit) * deref * VERY experimental testing of forward declaration of templates - probably will revert * Revert changes (as expected) * Update BlockDefinition.h - remove extraneous semicolons * Update BlockDefinition.h - remove linebreak * Update Amf3.h member naming scheme * fix duplicated code * const iterators * const pointers * reviving this branch * update read switch cases --- .editorconfig | 2 +- dCommon/AMFDeserialize.cpp | 89 +++++++----------- dCommon/AMFDeserialize.h | 14 +-- dCommon/Amf3.h | 91 +++++++------------ dCommon/GeneralUtils.h | 23 +++++ dGame/dComponents/ModelComponent.h | 4 +- dGame/dGameMessages/GameMessages.cpp | 2 +- dGame/dPropertyBehaviors/BlockDefinition.cpp | 2 +- dGame/dPropertyBehaviors/BlockDefinition.h | 6 +- .../ControlBehaviorMessages/Action.cpp | 6 +- .../ControlBehaviorMessages/Action.h | 6 +- .../ControlBehaviorMessages/ActionContext.cpp | 10 +- .../ControlBehaviorMessages/ActionContext.h | 8 +- .../AddActionMessage.cpp | 2 +- .../AddStripMessage.cpp | 2 +- .../BehaviorMessageBase.cpp | 4 +- .../BehaviorMessageBase.h | 2 +- .../ControlBehaviorMessages/RenameMessage.h | 2 +- .../StripUiPosition.cpp | 2 +- .../ControlBehaviorMessages/StripUiPosition.h | 2 +- .../UpdateActionMessage.cpp | 2 +- dGame/dPropertyBehaviors/ControlBehaviors.cpp | 14 +-- dGame/dPropertyBehaviors/ControlBehaviors.h | 4 +- tests/dCommonTests/AMFDeserializeTests.cpp | 15 ++- .../dGameMessagesTests/GameMessageTests.cpp | 67 ++++++++++---- 25 files changed, 200 insertions(+), 181 deletions(-) diff --git a/.editorconfig b/.editorconfig index ebdfa7ac..a63178f1 100644 --- a/.editorconfig +++ b/.editorconfig @@ -73,4 +73,4 @@ cpp_space_around_assignment_operator=insert cpp_space_pointer_reference_alignment=left cpp_space_around_ternary_operator=insert cpp_wrap_preserve_blocks=one_liners -cpp_indent_comment=fasle +cpp_indent_comment=false diff --git a/dCommon/AMFDeserialize.cpp b/dCommon/AMFDeserialize.cpp index 130ebc4a..884a0784 100644 --- a/dCommon/AMFDeserialize.cpp +++ b/dCommon/AMFDeserialize.cpp @@ -9,73 +9,54 @@ * AMF3 Deserializer written by EmosewaMC */ -AMFBaseValue* AMFDeserialize::Read(RakNet::BitStream& inStream) { - AMFBaseValue* returnValue = nullptr; +std::unique_ptr AMFDeserialize::Read(RakNet::BitStream& inStream) { // Read in the value type from the bitStream eAmf marker; inStream.Read(marker); // Based on the typing, create the value associated with that and return the base value class switch (marker) { - case eAmf::Undefined: { - returnValue = new AMFBaseValue(); - break; - } - - case eAmf::Null: { - returnValue = new AMFNullValue(); - break; - } - - case eAmf::False: { - returnValue = new AMFBoolValue(false); - break; - } - - case eAmf::True: { - returnValue = new AMFBoolValue(true); - break; - } - - case eAmf::Integer: { - returnValue = ReadAmfInteger(inStream); - break; - } - - case eAmf::Double: { - returnValue = ReadAmfDouble(inStream); - break; - } - - case eAmf::String: { - returnValue = ReadAmfString(inStream); - break; - } - - case eAmf::Array: { - returnValue = ReadAmfArray(inStream); - break; - } + case eAmf::Undefined: + return std::make_unique(); + case eAmf::Null: + return std::make_unique(); + case eAmf::False: + return std::make_unique(false); + case eAmf::True: + return std::make_unique(true); + case eAmf::Integer: + return ReadAmfInteger(inStream); + case eAmf::Double: + return ReadAmfDouble(inStream); + case eAmf::String: + return ReadAmfString(inStream); + case eAmf::Array: + return ReadAmfArray(inStream); // 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: + [[fallthrough]]; case eAmf::Date: + [[fallthrough]]; case eAmf::Object: + [[fallthrough]]; case eAmf::XML: + [[fallthrough]]; case eAmf::ByteArray: + [[fallthrough]]; case eAmf::VectorInt: + [[fallthrough]]; case eAmf::VectorUInt: + [[fallthrough]]; case eAmf::VectorDouble: + [[fallthrough]]; case eAmf::VectorObject: - case eAmf::Dictionary: { + [[fallthrough]]; + case eAmf::Dictionary: throw marker; - break; - } default: throw std::invalid_argument("Invalid AMF3 marker" + std::to_string(static_cast(marker))); - break; } - return returnValue; } uint32_t AMFDeserialize::ReadU29(RakNet::BitStream& inStream) { @@ -118,14 +99,14 @@ const std::string AMFDeserialize::ReadString(RakNet::BitStream& inStream) { } } -AMFBaseValue* AMFDeserialize::ReadAmfDouble(RakNet::BitStream& inStream) { +std::unique_ptr AMFDeserialize::ReadAmfDouble(RakNet::BitStream& inStream) { double value; inStream.Read(value); - return new AMFDoubleValue(value); + return std::make_unique(value); } -AMFBaseValue* AMFDeserialize::ReadAmfArray(RakNet::BitStream& inStream) { - auto arrayValue = new AMFArrayValue(); +std::unique_ptr AMFDeserialize::ReadAmfArray(RakNet::BitStream& inStream) { + auto arrayValue = std::make_unique(); // Read size of dense array const auto sizeOfDenseArray = (ReadU29(inStream) >> 1); @@ -143,10 +124,10 @@ AMFBaseValue* AMFDeserialize::ReadAmfArray(RakNet::BitStream& inStream) { return arrayValue; } -AMFBaseValue* AMFDeserialize::ReadAmfString(RakNet::BitStream& inStream) { - return new AMFStringValue(ReadString(inStream)); +std::unique_ptr AMFDeserialize::ReadAmfString(RakNet::BitStream& inStream) { + return std::make_unique(ReadString(inStream)); } -AMFBaseValue* AMFDeserialize::ReadAmfInteger(RakNet::BitStream& inStream) { - return new AMFIntValue(ReadU29(inStream)); +std::unique_ptr AMFDeserialize::ReadAmfInteger(RakNet::BitStream& inStream) { + return std::make_unique(ReadU29(inStream)); // NOTE: NARROWING CONVERSION FROM UINT TO INT. IS THIS INTENDED? } diff --git a/dCommon/AMFDeserialize.h b/dCommon/AMFDeserialize.h index e204976d..dc8a21a8 100644 --- a/dCommon/AMFDeserialize.h +++ b/dCommon/AMFDeserialize.h @@ -1,12 +1,12 @@ #pragma once +#include "Amf3.h" #include "BitStream.h" +#include #include #include -class AMFBaseValue; - class AMFDeserialize { public: /** @@ -15,7 +15,7 @@ public: * @param inStream inStream to read value from. * @return Returns an AMFValue with all the information from the bitStream in it. */ - AMFBaseValue* Read(RakNet::BitStream& inStream); + std::unique_ptr Read(RakNet::BitStream& inStream); private: /** * @brief Private method to read a U29 integer from a bitstream @@ -39,7 +39,7 @@ private: * @param inStream bitStream to read data from * @return Double value represented as an AMFValue */ - AMFBaseValue* ReadAmfDouble(RakNet::BitStream& inStream); + static std::unique_ptr ReadAmfDouble(RakNet::BitStream& inStream); /** * @brief Read an AMFArray from a bitStream @@ -47,7 +47,7 @@ private: * @param inStream bitStream to read data from * @return Array value represented as an AMFValue */ - AMFBaseValue* ReadAmfArray(RakNet::BitStream& inStream); + std::unique_ptr ReadAmfArray(RakNet::BitStream& inStream); /** * @brief Read an AMFString from a bitStream @@ -55,7 +55,7 @@ private: * @param inStream bitStream to read data from * @return String value represented as an AMFValue */ - AMFBaseValue* ReadAmfString(RakNet::BitStream& inStream); + std::unique_ptr ReadAmfString(RakNet::BitStream& inStream); /** * @brief Read an AMFInteger from a bitStream @@ -63,7 +63,7 @@ private: * @param inStream bitStream to read data from * @return Integer value represented as an AMFValue */ - AMFBaseValue* ReadAmfInteger(RakNet::BitStream& inStream); + static std::unique_ptr ReadAmfInteger(RakNet::BitStream& inStream); /** * List of strings read so far saved to be read by reference. diff --git a/dCommon/Amf3.h b/dCommon/Amf3.h index 9fe728c0..21a3c0c7 100644 --- a/dCommon/Amf3.h +++ b/dCommon/Amf3.h @@ -105,27 +105,14 @@ using AMFDoubleValue = AMFValue; * and are not to be deleted by a caller. */ class AMFArrayValue : public AMFBaseValue { - using AMFAssociative = std::unordered_map; - using AMFDense = std::vector; + using AMFAssociative = + std::unordered_map, GeneralUtils::transparent_string_hash, std::equal_to<>>; + + using AMFDense = std::vector>; public: [[nodiscard]] constexpr eAmf GetValueType() const noexcept override { return eAmf::Array; } - ~AMFArrayValue() override { - for (const 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 */ @@ -151,30 +138,32 @@ public: * or nullptr if a key existed and was not the same type */ template - [[maybe_unused]] std::pair*, bool> Insert(const std::string& key, const ValueType value) { + [[maybe_unused]] std::pair*, bool> Insert(const std::string_view key, const ValueType value) { const auto element = m_Associative.find(key); AMFValue* val = nullptr; bool found = true; if (element == m_Associative.cend()) { - val = new AMFValue(value); - m_Associative.emplace(key, val); + auto newVal = std::make_unique>(value); + val = newVal.get(); + m_Associative.emplace(key, std::move(newVal)); } else { - val = dynamic_cast*>(element->second); + val = dynamic_cast*>(element->second.get()); found = false; } return std::make_pair(val, found); } // Associates an array with a string key - [[maybe_unused]] std::pair Insert(const std::string& key) { + [[maybe_unused]] std::pair Insert(const std::string_view key) { const auto element = m_Associative.find(key); AMFArrayValue* val = nullptr; bool found = true; if (element == m_Associative.cend()) { - val = new AMFArrayValue(); - m_Associative.emplace(key, val); + auto newVal = std::make_unique(); + val = newVal.get(); + m_Associative.emplace(key, std::move(newVal)); } else { - val = dynamic_cast(element->second); + val = dynamic_cast(element->second.get()); found = false; } return std::make_pair(val, found); @@ -182,15 +171,13 @@ public: // Associates an array with an integer key [[maybe_unused]] std::pair Insert(const size_t index) { - AMFArrayValue* val = nullptr; bool inserted = false; if (index >= m_Dense.size()) { m_Dense.resize(index + 1); - val = new AMFArrayValue(); - m_Dense.at(index) = val; + m_Dense.at(index) = std::make_unique(); inserted = true; } - return std::make_pair(dynamic_cast(m_Dense.at(index)), inserted); + return std::make_pair(dynamic_cast(m_Dense.at(index).get()), inserted); } /** @@ -205,15 +192,13 @@ public: */ template [[maybe_unused]] std::pair*, bool> Insert(const size_t index, const ValueType value) { - AMFValue* val = nullptr; bool inserted = false; if (index >= m_Dense.size()) { m_Dense.resize(index + 1); - val = new AMFValue(value); - m_Dense.at(index) = val; + m_Dense.at(index) = std::make_unique>(value); inserted = true; } - return std::make_pair(dynamic_cast*>(m_Dense.at(index)), inserted); + return std::make_pair(dynamic_cast*>(m_Dense.at(index).get()), inserted); } /** @@ -225,13 +210,12 @@ public: * @param key The key to associate with the value * @param value The value to insert */ - void Insert(const std::string& key, AMFBaseValue* const value) { + void Insert(const std::string_view key, std::unique_ptr value) { const auto element = m_Associative.find(key); if (element != m_Associative.cend() && element->second) { - delete element->second; - element->second = value; + element->second = std::move(value); } else { - m_Associative.emplace(key, value); + m_Associative.emplace(key, std::move(value)); } } @@ -244,14 +228,11 @@ public: * @param key The key to associate with the value * @param value The value to insert */ - void Insert(const size_t index, AMFBaseValue* const value) { - if (index < m_Dense.size()) { - const AMFDense::const_iterator itr = m_Dense.cbegin() + index; - if (*itr) delete m_Dense.at(index); - } else { + void Insert(const size_t index, std::unique_ptr value) { + if (index >= m_Dense.size()) { m_Dense.resize(index + 1); } - m_Dense.at(index) = value; + m_Dense.at(index) = std::move(value); } /** @@ -279,8 +260,7 @@ public: void Remove(const std::string& key, const bool deleteValue = true) { const AMFAssociative::const_iterator it = m_Associative.find(key); if (it != m_Associative.cend()) { - if (deleteValue) delete it->second; - m_Associative.erase(it); + if (deleteValue) m_Associative.erase(it); } } @@ -290,7 +270,6 @@ public: void Remove(const size_t index) { if (!m_Dense.empty() && index < m_Dense.size()) { const auto itr = m_Dense.cbegin() + index; - if (*itr) delete (*itr); m_Dense.erase(itr); } } @@ -299,16 +278,16 @@ public: if (!m_Dense.empty()) Remove(m_Dense.size() - 1); } - [[nodiscard]] AMFArrayValue* GetArray(const std::string& key) const { + [[nodiscard]] AMFArrayValue* GetArray(const std::string_view key) const { const AMFAssociative::const_iterator it = m_Associative.find(key); - return it != m_Associative.cend() ? dynamic_cast(it->second) : nullptr; + return it != m_Associative.cend() ? dynamic_cast(it->second.get()) : nullptr; } [[nodiscard]] AMFArrayValue* GetArray(const size_t index) const { - return index < m_Dense.size() ? dynamic_cast(m_Dense.at(index)) : nullptr; + return index < m_Dense.size() ? dynamic_cast(m_Dense.at(index).get()) : nullptr; } - [[maybe_unused]] inline AMFArrayValue* InsertArray(const std::string& key) { + [[maybe_unused]] inline AMFArrayValue* InsertArray(const std::string_view key) { return static_cast(Insert(key).first); } @@ -330,17 +309,17 @@ public: * @return The AMFValue */ template - [[nodiscard]] AMFValue* Get(const std::string& key) const { + [[nodiscard]] AMFValue* Get(const std::string_view key) const { const AMFAssociative::const_iterator it = m_Associative.find(key); return it != m_Associative.cend() ? - dynamic_cast*>(it->second) : + dynamic_cast*>(it->second.get()) : nullptr; } // Get from the array but dont cast it - [[nodiscard]] AMFBaseValue* Get(const std::string& key) const { + [[nodiscard]] AMFBaseValue* Get(const std::string_view key) const { const AMFAssociative::const_iterator it = m_Associative.find(key); - return it != m_Associative.cend() ? it->second : nullptr; + return it != m_Associative.cend() ? it->second.get() : nullptr; } /** @@ -355,13 +334,13 @@ public: template [[nodiscard]] AMFValue* Get(const size_t index) const { return index < m_Dense.size() ? - dynamic_cast*>(m_Dense.at(index)) : + dynamic_cast*>(m_Dense.at(index).get()) : nullptr; } // Get from the dense but dont cast it [[nodiscard]] AMFBaseValue* Get(const size_t index) const { - return index < m_Dense.size() ? m_Dense.at(index) : nullptr; + return index < m_Dense.size() ? m_Dense.at(index).get() : nullptr; } private: diff --git a/dCommon/GeneralUtils.h b/dCommon/GeneralUtils.h index 0a8d15c1..2c93b656 100644 --- a/dCommon/GeneralUtils.h +++ b/dCommon/GeneralUtils.h @@ -129,6 +129,29 @@ namespace GeneralUtils { std::vector GetSqlFileNamesFromFolder(const std::string_view folder); + /** + * Transparent string hasher - used to allow string_view key lookups for maps storing std::string keys + * https://www.reddit.com/r/cpp_questions/comments/12xw3sn/find_stdstring_view_in_unordered_map_with/jhki225/ + * https://godbolt.org/z/789xv8Eeq + */ + template + struct overload : Bases... { + using is_transparent = void; + using Bases::operator() ... ; + }; + + struct char_pointer_hash { + auto operator()(const char* const ptr) const noexcept { + return std::hash{}(ptr); + } + }; + + using transparent_string_hash = overload< + std::hash, + std::hash, + char_pointer_hash + >; + // Concept constraining to enum types template concept Enum = std::is_enum_v; diff --git a/dGame/dComponents/ModelComponent.h b/dGame/dComponents/ModelComponent.h index 9e23eafb..12ef7744 100644 --- a/dGame/dComponents/ModelComponent.h +++ b/dGame/dComponents/ModelComponent.h @@ -66,8 +66,8 @@ public: template void HandleControlBehaviorsMsg(const AMFArrayValue& args) { static_assert(std::is_base_of_v, "Msg must be a BehaviorMessageBase"); - Msg msg(args); - for (auto& behavior : m_Behaviors) { + Msg msg{ args }; + for (auto&& behavior : m_Behaviors) { if (behavior.GetBehaviorId() == msg.GetBehaviorId()) { behavior.HandleMsg(msg); return; diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 5d7dcfb5..fc77e690 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -2492,7 +2492,7 @@ 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{ static_cast(reader.Read(inStream)) }; + std::unique_ptr amfArguments{ static_cast(reader.Read(inStream).release()) }; if (amfArguments->GetValueType() != eAmf::Array) return; uint32_t commandLength{}; diff --git a/dGame/dPropertyBehaviors/BlockDefinition.cpp b/dGame/dPropertyBehaviors/BlockDefinition.cpp index e67a90d8..17378423 100644 --- a/dGame/dPropertyBehaviors/BlockDefinition.cpp +++ b/dGame/dPropertyBehaviors/BlockDefinition.cpp @@ -2,7 +2,7 @@ BlockDefinition BlockDefinition::blockDefinitionDefault{}; -BlockDefinition::BlockDefinition(const std::string& defaultValue, const float minimumValue, const float maximumValue) +BlockDefinition::BlockDefinition(const std::string_view defaultValue, const float minimumValue, const float maximumValue) : m_DefaultValue{ defaultValue } , m_MinimumValue{ minimumValue } , m_MaximumValue{ maximumValue } { diff --git a/dGame/dPropertyBehaviors/BlockDefinition.h b/dGame/dPropertyBehaviors/BlockDefinition.h index 84722ea2..0822a4f0 100644 --- a/dGame/dPropertyBehaviors/BlockDefinition.h +++ b/dGame/dPropertyBehaviors/BlockDefinition.h @@ -7,13 +7,13 @@ class AMFArrayValue; class BlockDefinition { public: - BlockDefinition(const std::string& defaultValue = "", const float minimumValue = 0.0f, const float maximumValue = 0.0f); + BlockDefinition(const std::string_view defaultValue = "", const float minimumValue = 0.0f, const float maximumValue = 0.0f); static BlockDefinition blockDefinitionDefault; - [[nodiscard]] const std::string& GetDefaultValue() const { return m_DefaultValue; } + [[nodiscard]] std::string_view GetDefaultValue() const { return m_DefaultValue; } [[nodiscard]] float GetMinimumValue() const noexcept { return m_MinimumValue; } [[nodiscard]] float GetMaximumValue() const noexcept { return m_MaximumValue; } - void SetDefaultValue(const std::string& value) { m_DefaultValue = value; } + void SetDefaultValue(const std::string_view value) { m_DefaultValue = std::string{ value }; } void SetMinimumValue(const float value) noexcept { m_MinimumValue = value; } void SetMaximumValue(const float value) noexcept { m_MaximumValue = value; } diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/Action.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/Action.cpp index 6a21be9b..8906cac2 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviorMessages/Action.cpp +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/Action.cpp @@ -7,16 +7,16 @@ Action::Action(const AMFArrayValue& arguments) { for (const auto& [paramName, paramValue] : arguments.GetAssociative()) { if (paramName == "Type") { if (paramValue->GetValueType() != eAmf::String) continue; - m_Type = static_cast(paramValue)->GetValue(); + m_Type = static_cast(paramValue.get())->GetValue(); } else { m_ValueParameterName = paramName; // Message is the only known string parameter if (m_ValueParameterName == "Message") { if (paramValue->GetValueType() != eAmf::String) continue; - m_ValueParameterString = static_cast(paramValue)->GetValue(); + m_ValueParameterString = static_cast(paramValue.get())->GetValue(); } else { if (paramValue->GetValueType() != eAmf::Double) continue; - m_ValueParameterDouble = static_cast(paramValue)->GetValue(); + m_ValueParameterDouble = static_cast(paramValue.get())->GetValue(); } } } diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/Action.h b/dGame/dPropertyBehaviors/ControlBehaviorMessages/Action.h index 8146e08d..44b0ce76 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviorMessages/Action.h +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/Action.h @@ -17,9 +17,9 @@ class Action { public: Action() = default; Action(const AMFArrayValue& arguments); - [[nodiscard]] const std::string& GetType() const { return m_Type; }; - [[nodiscard]] const std::string& GetValueParameterName() const { return m_ValueParameterName; }; - [[nodiscard]] const std::string& GetValueParameterString() const { return m_ValueParameterString; }; + [[nodiscard]] std::string_view GetType() const { return m_Type; }; + [[nodiscard]] std::string_view GetValueParameterName() const { return m_ValueParameterName; }; + [[nodiscard]] std::string_view GetValueParameterString() const { return m_ValueParameterString; }; [[nodiscard]] double GetValueParameterDouble() const noexcept { return m_ValueParameterDouble; }; void SendBehaviorBlocksToClient(AMFArrayValue& args) const; diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/ActionContext.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/ActionContext.cpp index 36da8d73..9c88acc3 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviorMessages/ActionContext.cpp +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/ActionContext.cpp @@ -4,21 +4,21 @@ #include "Amf3.h" -ActionContext::ActionContext(const AMFArrayValue& arguments, const std::string& customStateKey, const std::string& customStripKey) +ActionContext::ActionContext(const AMFArrayValue& arguments, const std::string_view customStateKey, const std::string_view customStripKey) : m_StripId{ GetStripIdFromArgument(arguments, customStripKey) } , m_StateId{ GetBehaviorStateFromArgument(arguments, customStateKey) } { } -BehaviorState ActionContext::GetBehaviorStateFromArgument(const AMFArrayValue& arguments, const std::string& key) const { +BehaviorState ActionContext::GetBehaviorStateFromArgument(const AMFArrayValue& arguments, const std::string_view key) const { const auto* const stateIDValue = arguments.Get(key); - if (!stateIDValue) throw std::invalid_argument("Unable to find behavior state from argument \"" + key + "\""); + if (!stateIDValue) throw std::invalid_argument("Unable to find behavior state from argument \"" + std::string{ key } + "\""); return static_cast(stateIDValue->GetValue()); } -StripId ActionContext::GetStripIdFromArgument(const AMFArrayValue& arguments, const std::string& key) const { +StripId ActionContext::GetStripIdFromArgument(const AMFArrayValue& arguments, const std::string_view key) const { const auto* const stripIdValue = arguments.Get(key); - if (!stripIdValue) throw std::invalid_argument("Unable to find strip ID from argument \"" + key + "\""); + if (!stripIdValue) throw std::invalid_argument("Unable to find strip ID from argument \"" + std::string{ key } + "\""); return static_cast(stripIdValue->GetValue()); } diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/ActionContext.h b/dGame/dPropertyBehaviors/ControlBehaviorMessages/ActionContext.h index 8ecea8a2..d6b84aba 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviorMessages/ActionContext.h +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/ActionContext.h @@ -4,6 +4,8 @@ #include "BehaviorStates.h" #include "dCommonVars.h" +#include + class AMFArrayValue; /** @@ -13,13 +15,13 @@ class AMFArrayValue; class ActionContext { public: ActionContext() noexcept = default; - ActionContext(const AMFArrayValue& arguments, const std::string& customStateKey = "stateID", const std::string& customStripKey = "stripID"); + ActionContext(const AMFArrayValue& arguments, const std::string_view customStateKey = "stateID", const std::string_view customStripKey = "stripID"); [[nodiscard]] StripId GetStripId() const noexcept { return m_StripId; }; [[nodiscard]] BehaviorState GetStateId() const noexcept { return m_StateId; }; private: - [[nodiscard]] BehaviorState GetBehaviorStateFromArgument(const AMFArrayValue& arguments, const std::string& key) const; - [[nodiscard]] StripId GetStripIdFromArgument(const AMFArrayValue& arguments, const std::string& key) const; + [[nodiscard]] BehaviorState GetBehaviorStateFromArgument(const AMFArrayValue& arguments, const std::string_view key) const; + [[nodiscard]] StripId GetStripIdFromArgument(const AMFArrayValue& arguments, const std::string_view key) const; StripId m_StripId{ 0 }; BehaviorState m_StateId{ BehaviorState::HOME_STATE }; }; diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddActionMessage.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddActionMessage.cpp index 35b9cf0d..0b0b9eaf 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddActionMessage.cpp +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddActionMessage.cpp @@ -10,5 +10,5 @@ AddActionMessage::AddActionMessage(const AMFArrayValue& arguments) m_Action = Action{ *actionValue }; - LOG_DEBUG("actionIndex %i stripId %i stateId %i type %s valueParameterName %s valueParameterString %s valueParameterDouble %f m_BehaviorId %i", m_ActionIndex, m_ActionContext.GetStripId(), m_ActionContext.GetStateId(), m_Action.GetType().c_str(), m_Action.GetValueParameterName().c_str(), m_Action.GetValueParameterString().c_str(), m_Action.GetValueParameterDouble(), m_BehaviorId); + LOG_DEBUG("actionIndex %i stripId %i stateId %i type %s valueParameterName %s valueParameterString %s valueParameterDouble %f m_BehaviorId %i", m_ActionIndex, m_ActionContext.GetStripId(), m_ActionContext.GetStateId(), m_Action.GetType().data(), m_Action.GetValueParameterName().data(), m_Action.GetValueParameterString().data(), m_Action.GetValueParameterDouble(), m_BehaviorId); } diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddStripMessage.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddStripMessage.cpp index c7207b33..c2933fbf 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddStripMessage.cpp +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddStripMessage.cpp @@ -19,7 +19,7 @@ AddStripMessage::AddStripMessage(const AMFArrayValue& arguments) m_ActionsToAdd.emplace_back(*actionValue); - LOG_DEBUG("xPosition %f yPosition %f stripId %i stateId %i behaviorId %i t %s valueParameterName %s valueParameterString %s valueParameterDouble %f", m_Position.GetX(), m_Position.GetY(), m_ActionContext.GetStripId(), m_ActionContext.GetStateId(), m_BehaviorId, m_ActionsToAdd.back().GetType().c_str(), m_ActionsToAdd.back().GetValueParameterName().c_str(), m_ActionsToAdd.back().GetValueParameterString().c_str(), m_ActionsToAdd.back().GetValueParameterDouble()); + LOG_DEBUG("xPosition %f yPosition %f stripId %i stateId %i behaviorId %i t %s valueParameterName %s valueParameterString %s valueParameterDouble %f", m_Position.GetX(), m_Position.GetY(), m_ActionContext.GetStripId(), m_ActionContext.GetStateId(), m_BehaviorId, m_ActionsToAdd.back().GetType().data(), m_ActionsToAdd.back().GetValueParameterName().data(), m_ActionsToAdd.back().GetValueParameterString().data(), m_ActionsToAdd.back().GetValueParameterDouble()); } LOG_DEBUG("number of actions %i", m_ActionsToAdd.size()); } diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/BehaviorMessageBase.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/BehaviorMessageBase.cpp index a1cbb064..fb26f37f 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviorMessages/BehaviorMessageBase.cpp +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/BehaviorMessageBase.cpp @@ -5,7 +5,7 @@ #include "dCommonVars.h" int32_t BehaviorMessageBase::GetBehaviorIdFromArgument(const AMFArrayValue& arguments) { - static constexpr const char* key = "BehaviorID"; + static constexpr std::string_view key = "BehaviorID"; const auto* const behaviorIDValue = arguments.Get(key); int32_t behaviorId = DefaultBehaviorId; @@ -19,7 +19,7 @@ int32_t BehaviorMessageBase::GetBehaviorIdFromArgument(const AMFArrayValue& argu return behaviorId; } -int32_t BehaviorMessageBase::GetActionIndexFromArgument(const AMFArrayValue& arguments, const std::string& keyName) const { +int32_t BehaviorMessageBase::GetActionIndexFromArgument(const AMFArrayValue& arguments, const std::string_view keyName) const { const auto* const actionIndexAmf = arguments.Get(keyName); if (!actionIndexAmf) throw std::invalid_argument("Unable to find actionIndex"); diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/BehaviorMessageBase.h b/dGame/dPropertyBehaviors/ControlBehaviorMessages/BehaviorMessageBase.h index bb251a74..cc8c293d 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviorMessages/BehaviorMessageBase.h +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/BehaviorMessageBase.h @@ -22,7 +22,7 @@ public: protected: [[nodiscard]] int32_t GetBehaviorIdFromArgument(const AMFArrayValue& arguments); - [[nodiscard]] int32_t GetActionIndexFromArgument(const AMFArrayValue& arguments, const std::string& keyName = "actionIndex") const; + [[nodiscard]] int32_t GetActionIndexFromArgument(const AMFArrayValue& arguments, const std::string_view keyName = "actionIndex") const; int32_t m_BehaviorId{ DefaultBehaviorId }; }; diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/RenameMessage.h b/dGame/dPropertyBehaviors/ControlBehaviorMessages/RenameMessage.h index 1f4e45c0..68cc83d7 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviorMessages/RenameMessage.h +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/RenameMessage.h @@ -11,7 +11,7 @@ class AMFArrayValue; class RenameMessage : public BehaviorMessageBase { public: RenameMessage(const AMFArrayValue& arguments); - [[nodiscard]] const std::string& GetName() const { return m_Name; }; + [[nodiscard]] std::string_view GetName() const { return m_Name; }; private: std::string m_Name; diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/StripUiPosition.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/StripUiPosition.cpp index ae153a5f..5a5592ac 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviorMessages/StripUiPosition.cpp +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/StripUiPosition.cpp @@ -3,7 +3,7 @@ #include "Amf3.h" #include "tinyxml2.h" -StripUiPosition::StripUiPosition(const AMFArrayValue& arguments, const std::string& uiKeyName) { +StripUiPosition::StripUiPosition(const AMFArrayValue& arguments, const std::string_view uiKeyName) { const auto* const uiArray = arguments.GetArray(uiKeyName); if (!uiArray) return; diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/StripUiPosition.h b/dGame/dPropertyBehaviors/ControlBehaviorMessages/StripUiPosition.h index 47501ff7..eeeb67bb 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviorMessages/StripUiPosition.h +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/StripUiPosition.h @@ -14,7 +14,7 @@ namespace tinyxml2 { class StripUiPosition { public: StripUiPosition() noexcept = default; - StripUiPosition(const AMFArrayValue& arguments, const std::string& uiKeyName = "ui"); + StripUiPosition(const AMFArrayValue& arguments, const std::string_view uiKeyName = "ui"); void SendBehaviorBlocksToClient(AMFArrayValue& args) const; [[nodiscard]] double GetX() const noexcept { return m_XPosition; } [[nodiscard]] double GetY() const noexcept { return m_YPosition; } diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/UpdateActionMessage.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/UpdateActionMessage.cpp index fabf2726..04111a7d 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviorMessages/UpdateActionMessage.cpp +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/UpdateActionMessage.cpp @@ -12,5 +12,5 @@ UpdateActionMessage::UpdateActionMessage(const AMFArrayValue& arguments) m_Action = Action{ *actionValue }; - LOG_DEBUG("type %s valueParameterName %s valueParameterString %s valueParameterDouble %f behaviorId %i actionIndex %i stripId %i stateId %i", m_Action.GetType().c_str(), m_Action.GetValueParameterName().c_str(), m_Action.GetValueParameterString().c_str(), m_Action.GetValueParameterDouble(), m_BehaviorId, m_ActionIndex, m_ActionContext.GetStripId(), m_ActionContext.GetStateId()); + LOG_DEBUG("type %s valueParameterName %s valueParameterString %s valueParameterDouble %f behaviorId %i actionIndex %i stripId %i stateId %i", m_Action.GetType().data(), m_Action.GetValueParameterName().data(), m_Action.GetValueParameterString().data(), m_Action.GetValueParameterDouble(), m_BehaviorId, m_ActionIndex, m_ActionContext.GetStripId(), m_ActionContext.GetStateId()); } diff --git a/dGame/dPropertyBehaviors/ControlBehaviors.cpp b/dGame/dPropertyBehaviors/ControlBehaviors.cpp index 2e074409..756a615c 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviors.cpp +++ b/dGame/dPropertyBehaviors/ControlBehaviors.cpp @@ -76,26 +76,26 @@ void ControlBehaviors::UpdateAction(const AMFArrayValue& arguments) { auto blockDefinition = GetBlockInfo(updateActionMessage.GetAction().GetType()); if (!blockDefinition) { - LOG("Received undefined block type %s. Ignoring.", updateActionMessage.GetAction().GetType().c_str()); + LOG("Received undefined block type %s. Ignoring.", updateActionMessage.GetAction().GetType().data()); return; } if (updateActionMessage.GetAction().GetValueParameterString().size() > 0) { if (updateActionMessage.GetAction().GetValueParameterString().size() < blockDefinition->GetMinimumValue() || updateActionMessage.GetAction().GetValueParameterString().size() > blockDefinition->GetMaximumValue()) { - LOG("Updated block %s is out of range. Ignoring update", updateActionMessage.GetAction().GetType().c_str()); + LOG("Updated block %s is out of range. Ignoring update", updateActionMessage.GetAction().GetType().data()); return; } } else { if (updateActionMessage.GetAction().GetValueParameterDouble() < blockDefinition->GetMinimumValue() || updateActionMessage.GetAction().GetValueParameterDouble() > blockDefinition->GetMaximumValue()) { - LOG("Updated block %s is out of range. Ignoring update", updateActionMessage.GetAction().GetType().c_str()); + LOG("Updated block %s is out of range. Ignoring update", updateActionMessage.GetAction().GetType().data()); return; } } } -void ControlBehaviors::ProcessCommand(Entity* const modelEntity, const AMFArrayValue& arguments, const std::string& command, Entity* const modelOwner) { +void ControlBehaviors::ProcessCommand(Entity* const modelEntity, const AMFArrayValue& arguments, const std::string_view command, Entity* const modelOwner) { if (!isInitialized || !modelEntity || !modelOwner) return; auto* const modelComponent = modelEntity->GetComponent(); @@ -157,7 +157,7 @@ void ControlBehaviors::ProcessCommand(Entity* const modelEntity, const AMFArrayV } else if (command == "updateAction") { context.modelComponent->HandleControlBehaviorsMsg(arguments); } else { - LOG("Unknown behavior command (%s)", command.c_str()); + LOG("Unknown behavior command (%s)", command.data()); } } @@ -279,11 +279,11 @@ ControlBehaviors::ControlBehaviors() { isInitialized = true; LOG_DEBUG("Created all base block classes"); for (auto& [name, block] : blockTypes) { - LOG_DEBUG("block name is %s default %s min %f max %f", name.c_str(), block.GetDefaultValue().c_str(), block.GetMinimumValue(), block.GetMaximumValue()); + LOG_DEBUG("block name is %s default %s min %f max %f", name.data(), block.GetDefaultValue().data(), block.GetMinimumValue(), block.GetMaximumValue()); } } -std::optional ControlBehaviors::GetBlockInfo(const std::string& blockName) { +std::optional ControlBehaviors::GetBlockInfo(const std::string_view blockName) { auto blockDefinition = blockTypes.find(blockName); return blockDefinition != blockTypes.end() ? std::optional(blockDefinition->second) : std::nullopt; } diff --git a/dGame/dPropertyBehaviors/ControlBehaviors.h b/dGame/dPropertyBehaviors/ControlBehaviors.h index f176a070..fdb86746 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviors.h +++ b/dGame/dPropertyBehaviors/ControlBehaviors.h @@ -43,7 +43,7 @@ public: * @param command The command to perform * @param modelOwner The owner of the model which sent this command */ - void ProcessCommand(Entity* const modelEntity, const AMFArrayValue& arguments, const std::string& command, Entity* const modelOwner); + void ProcessCommand(Entity* const modelEntity, const AMFArrayValue& arguments, const std::string_view command, Entity* const modelOwner); /** * @brief Gets a blocks parameter values by the name @@ -53,7 +53,7 @@ public: * * @return A pair of the block parameter name to its typing */ - [[nodiscard]] std::optional GetBlockInfo(const std::string& blockName); + [[nodiscard]] std::optional GetBlockInfo(const std::string_view blockName); private: void RequestUpdatedID(ControlBehaviorContext& context); void SendBehaviorListToClient(const ControlBehaviorContext& context); diff --git a/tests/dCommonTests/AMFDeserializeTests.cpp b/tests/dCommonTests/AMFDeserializeTests.cpp index fb9e5a4f..0a8c0ac7 100644 --- a/tests/dCommonTests/AMFDeserializeTests.cpp +++ b/tests/dCommonTests/AMFDeserializeTests.cpp @@ -13,8 +13,7 @@ */ std::unique_ptr ReadFromBitStream(RakNet::BitStream& bitStream) { AMFDeserialize deserializer; - AMFBaseValue* returnValue(deserializer.Read(bitStream)); - return std::unique_ptr{ returnValue }; + return deserializer.Read(bitStream); } /** @@ -254,7 +253,7 @@ TEST(dCommonTests, AMFDeserializeLivePacketTest) { ASSERT_EQ(strips.size(), 1); - auto* stripsPosition0 = dynamic_cast(strips[0]); + auto* stripsPosition0 = dynamic_cast(strips[0].get()); auto* actionIndex = stripsPosition0->Get("actionIndex"); @@ -272,7 +271,7 @@ TEST(dCommonTests, AMFDeserializeLivePacketTest) { ASSERT_EQ(states.size(), 1); - auto* firstState = dynamic_cast(states[0]); + auto* firstState = dynamic_cast(states[0].get()); auto* stateID = firstState->Get("id"); @@ -282,7 +281,7 @@ TEST(dCommonTests, AMFDeserializeLivePacketTest) { ASSERT_EQ(stripsInState.size(), 1); - auto* firstStrip = dynamic_cast(stripsInState[0]); + auto* firstStrip = dynamic_cast(stripsInState[0].get()); auto& actionsInFirstStrip = firstStrip->GetArray("actions")->GetDense(); @@ -304,7 +303,7 @@ TEST(dCommonTests, AMFDeserializeLivePacketTest) { ASSERT_EQ(stripId->GetValue(), 0.0f); - auto* firstAction = dynamic_cast(actionsInFirstStrip[0]); + auto* firstAction = dynamic_cast(actionsInFirstStrip[0].get()); auto* firstType = firstAction->Get("Type"); @@ -314,7 +313,7 @@ TEST(dCommonTests, AMFDeserializeLivePacketTest) { ASSERT_EQ(firstCallback->GetValue(), ""); - auto* secondAction = dynamic_cast(actionsInFirstStrip[1]); + auto* secondAction = dynamic_cast(actionsInFirstStrip[1].get()); auto* secondType = secondAction->Get("Type"); @@ -328,7 +327,7 @@ TEST(dCommonTests, AMFDeserializeLivePacketTest) { ASSERT_EQ(secondDistance->GetValue(), 25.0f); - auto* thirdAction = dynamic_cast(actionsInFirstStrip[2]); + auto* thirdAction = dynamic_cast(actionsInFirstStrip[2].get()); auto* thirdType = thirdAction->Get("Type"); diff --git a/tests/dGameTests/dGameMessagesTests/GameMessageTests.cpp b/tests/dGameTests/dGameMessagesTests/GameMessageTests.cpp index 2d37d102..7c33c6d0 100644 --- a/tests/dGameTests/dGameMessagesTests/GameMessageTests.cpp +++ b/tests/dGameTests/dGameMessagesTests/GameMessageTests.cpp @@ -38,11 +38,11 @@ protected: } return readFile; } - const AMFArrayValue& ReadArrayFromBitStream(RakNet::BitStream& inStream) { + std::unique_ptr ReadArrayFromBitStream(RakNet::BitStream& inStream) { AMFDeserialize des; - AMFBaseValue* readArray = des.Read(inStream); + AMFBaseValue* readArray = des.Read(inStream).release(); EXPECT_EQ(readArray->GetValueType(), eAmf::Array); - return static_cast(*readArray); + return std::unique_ptr{ static_cast(readArray) }; } }; @@ -88,7 +88,10 @@ TEST_F(GameMessageTests, SendBlueprintLoadItemResponse) { TEST_F(GameMessageTests, ControlBehaviorAddStrip) { auto data = ReadFromFile("addStrip"); RakNet::BitStream inStream(reinterpret_cast(&data[0]), data.length(), true); - AddStripMessage addStrip(ReadArrayFromBitStream(inStream)); + + const auto arr = ReadArrayFromBitStream(inStream); + AddStripMessage addStrip(*arr); + ASSERT_FLOAT_EQ(addStrip.GetPosition().GetX(), 50.65); ASSERT_FLOAT_EQ(addStrip.GetPosition().GetY(), 178.05); ASSERT_EQ(addStrip.GetActionContext().GetStripId(), 0); @@ -103,7 +106,10 @@ TEST_F(GameMessageTests, ControlBehaviorAddStrip) { TEST_F(GameMessageTests, ControlBehaviorRemoveStrip) { auto data = ReadFromFile("removeStrip"); RakNet::BitStream inStream(reinterpret_cast(&data[0]), data.length(), true); - RemoveStripMessage removeStrip(ReadArrayFromBitStream(inStream)); + + const auto arr = ReadArrayFromBitStream(inStream); + RemoveStripMessage removeStrip(*arr); + ASSERT_EQ(static_cast(removeStrip.GetActionContext().GetStripId()), 1); ASSERT_EQ(static_cast(removeStrip.GetActionContext().GetStateId()), 0); ASSERT_EQ(removeStrip.GetBehaviorId(), BehaviorMessageBase::DefaultBehaviorId); @@ -112,7 +118,10 @@ TEST_F(GameMessageTests, ControlBehaviorRemoveStrip) { TEST_F(GameMessageTests, ControlBehaviorMergeStrips) { auto data = ReadFromFile("mergeStrips"); RakNet::BitStream inStream(reinterpret_cast(&data[0]), data.length(), true); - MergeStripsMessage mergeStrips(ReadArrayFromBitStream(inStream)); + + const auto arr = ReadArrayFromBitStream(inStream); + MergeStripsMessage mergeStrips(*arr); + ASSERT_EQ(mergeStrips.GetSourceActionContext().GetStripId(), 2); ASSERT_EQ(mergeStrips.GetDestinationActionContext().GetStripId(), 0); ASSERT_EQ(static_cast(mergeStrips.GetSourceActionContext().GetStateId()), 0); @@ -124,9 +133,11 @@ TEST_F(GameMessageTests, ControlBehaviorMergeStrips) { TEST_F(GameMessageTests, ControlBehaviorSplitStrip) { auto data = ReadFromFile("splitStrip"); RakNet::BitStream inStream(reinterpret_cast(&data[0]), data.length(), true); - SplitStripMessage splitStrip(ReadArrayFromBitStream(inStream)); - ASSERT_EQ(splitStrip.GetBehaviorId(), -1); + const auto arr = ReadArrayFromBitStream(inStream); + SplitStripMessage splitStrip(*arr); + + ASSERT_EQ(splitStrip.GetBehaviorId(), -1); ASSERT_FLOAT_EQ(splitStrip.GetPosition().GetX(), 275.65); ASSERT_FLOAT_EQ(splitStrip.GetPosition().GetY(), 28.7); ASSERT_EQ(splitStrip.GetSourceActionContext().GetStripId(), 0); @@ -139,7 +150,10 @@ TEST_F(GameMessageTests, ControlBehaviorSplitStrip) { TEST_F(GameMessageTests, ControlBehaviorUpdateStripUI) { auto data = ReadFromFile("updateStripUI"); RakNet::BitStream inStream(reinterpret_cast(&data[0]), data.length(), true); - UpdateStripUiMessage updateStripUi(ReadArrayFromBitStream(inStream)); + + const auto arr = ReadArrayFromBitStream(inStream); + UpdateStripUiMessage updateStripUi(*arr); + ASSERT_FLOAT_EQ(updateStripUi.GetPosition().GetX(), 116.65); ASSERT_FLOAT_EQ(updateStripUi.GetPosition().GetY(), 35.35); ASSERT_EQ(updateStripUi.GetActionContext().GetStripId(), 0); @@ -150,7 +164,10 @@ TEST_F(GameMessageTests, ControlBehaviorUpdateStripUI) { TEST_F(GameMessageTests, ControlBehaviorAddAction) { auto data = ReadFromFile("addAction"); RakNet::BitStream inStream(reinterpret_cast(&data[0]), data.length(), true); - AddActionMessage addAction(ReadArrayFromBitStream(inStream)); + + const auto arr = ReadArrayFromBitStream(inStream); + AddActionMessage addAction(*arr); + ASSERT_EQ(addAction.GetActionIndex(), 3); ASSERT_EQ(addAction.GetActionContext().GetStripId(), 0); ASSERT_EQ(static_cast(addAction.GetActionContext().GetStateId()), 0); @@ -164,7 +181,10 @@ TEST_F(GameMessageTests, ControlBehaviorAddAction) { TEST_F(GameMessageTests, ControlBehaviorMigrateActions) { auto data = ReadFromFile("migrateActions"); RakNet::BitStream inStream(reinterpret_cast(&data[0]), data.length(), true); - MigrateActionsMessage migrateActions(ReadArrayFromBitStream(inStream)); + + const auto arr = ReadArrayFromBitStream(inStream); + MigrateActionsMessage migrateActions(*arr); + ASSERT_EQ(migrateActions.GetSrcActionIndex(), 1); ASSERT_EQ(migrateActions.GetDstActionIndex(), 2); ASSERT_EQ(migrateActions.GetSourceActionContext().GetStripId(), 1); @@ -177,7 +197,10 @@ TEST_F(GameMessageTests, ControlBehaviorMigrateActions) { TEST_F(GameMessageTests, ControlBehaviorRearrangeStrip) { auto data = ReadFromFile("rearrangeStrip"); RakNet::BitStream inStream(reinterpret_cast(&data[0]), data.length(), true); - RearrangeStripMessage rearrangeStrip(ReadArrayFromBitStream(inStream)); + + const auto arr = ReadArrayFromBitStream(inStream); + RearrangeStripMessage rearrangeStrip(*arr); + ASSERT_EQ(rearrangeStrip.GetSrcActionIndex(), 2); ASSERT_EQ(rearrangeStrip.GetDstActionIndex(), 1); ASSERT_EQ(rearrangeStrip.GetActionContext().GetStripId(), 0); @@ -188,7 +211,10 @@ TEST_F(GameMessageTests, ControlBehaviorRearrangeStrip) { TEST_F(GameMessageTests, ControlBehaviorAdd) { auto data = ReadFromFile("add"); RakNet::BitStream inStream(reinterpret_cast(&data[0]), data.length(), true); - AddMessage add(ReadArrayFromBitStream(inStream)); + + const auto arr = ReadArrayFromBitStream(inStream); + AddMessage add(*arr); + ASSERT_EQ(add.GetBehaviorId(), 10446); ASSERT_EQ(add.GetBehaviorIndex(), 0); } @@ -196,7 +222,10 @@ TEST_F(GameMessageTests, ControlBehaviorAdd) { TEST_F(GameMessageTests, ControlBehaviorRemoveActions) { auto data = ReadFromFile("removeActions"); RakNet::BitStream inStream(reinterpret_cast(&data[0]), data.length(), true); - RemoveActionsMessage removeActions(ReadArrayFromBitStream(inStream)); + + const auto arr = ReadArrayFromBitStream(inStream); + RemoveActionsMessage removeActions(*arr); + ASSERT_EQ(removeActions.GetBehaviorId(), -1); ASSERT_EQ(removeActions.GetActionIndex(), 1); ASSERT_EQ(removeActions.GetActionContext().GetStripId(), 0); @@ -206,7 +235,10 @@ TEST_F(GameMessageTests, ControlBehaviorRemoveActions) { TEST_F(GameMessageTests, ControlBehaviorRename) { auto data = ReadFromFile("rename"); RakNet::BitStream inStream(reinterpret_cast(&data[0]), data.length(), true); - RenameMessage rename(ReadArrayFromBitStream(inStream)); + + const auto arr = ReadArrayFromBitStream(inStream); + RenameMessage rename(*arr); + ASSERT_EQ(rename.GetName(), "test"); ASSERT_EQ(rename.GetBehaviorId(), BehaviorMessageBase::DefaultBehaviorId); } @@ -214,7 +246,10 @@ TEST_F(GameMessageTests, ControlBehaviorRename) { TEST_F(GameMessageTests, ControlBehaviorUpdateAction) { auto data = ReadFromFile("updateAction"); RakNet::BitStream inStream(reinterpret_cast(&data[0]), data.length(), true); - UpdateActionMessage updateAction(ReadArrayFromBitStream(inStream)); + + const auto arr = ReadArrayFromBitStream(inStream); + UpdateActionMessage updateAction(*arr); + ASSERT_EQ(updateAction.GetAction().GetType(), "FlyDown"); ASSERT_EQ(updateAction.GetAction().GetValueParameterName(), "Distance"); ASSERT_EQ(updateAction.GetAction().GetValueParameterString(), "");