diff --git a/CMakeLists.txt b/CMakeLists.txt index 54f0d0dd..41d4219f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -163,6 +163,7 @@ set(INCLUDED_DIRECTORIES "dGame/dMission" "dGame/dEntity" "dGame/dPropertyBehaviors" + "dGame/dPropertyBehaviors/ControlBehaviorMessages" "dGame/dUtilities" "dPhysics" "dNavigation" diff --git a/dCommon/dEnums/dCommonVars.h b/dCommon/dEnums/dCommonVars.h index c90fd8e6..1d4a4c55 100644 --- a/dCommon/dEnums/dCommonVars.h +++ b/dCommon/dEnums/dCommonVars.h @@ -43,8 +43,7 @@ typedef uint32_t LWOCLONEID; //!< Used for Clone IDs typedef uint16_t LWOMAPID; //!< Used for Map IDs typedef uint16_t LWOINSTANCEID; //!< Used for Instance IDs typedef uint32_t PROPERTYCLONELIST; //!< Used for Property Clone IDs -typedef uint32_t STRIPID; -typedef uint32_t BEHAVIORSTATE; +typedef uint32_t StripId; typedef int32_t PetTamingPiece; //!< Pet Taming Pieces diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 58d72d3c..1d897727 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -2475,7 +2475,7 @@ void GameMessages::HandleControlBehaviors(RakNet::BitStream* inStream, Entity* e auto owner = PropertyManagementComponent::Instance()->GetOwner(); if (!owner) return; - ControlBehaviors::ProcessCommand(entity, sysAddr, static_cast(amfArguments.get()), command, owner); + ControlBehaviors::Instance().ProcessCommand(entity, sysAddr, static_cast(amfArguments.get()), command, owner); } void GameMessages::HandleBBBSaveRequest(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { diff --git a/dGame/dPropertyBehaviors/BehaviorStates.h b/dGame/dPropertyBehaviors/BehaviorStates.h index e09e45ba..80cb1dbb 100644 --- a/dGame/dPropertyBehaviors/BehaviorStates.h +++ b/dGame/dPropertyBehaviors/BehaviorStates.h @@ -3,12 +3,9 @@ #ifndef __BEHAVIORSTATES__H__ #define __BEHAVIORSTATES__H__ -#include #include -#include "dCommonVars.h" - -enum States : BEHAVIORSTATE { +enum class BehaviorState : uint32_t { HOME_STATE = 0, //!< The HOME behavior state CIRCLE_STATE, //!< The CIRCLE behavior state SQUARE_STATE, //!< The SQUARE behavior state diff --git a/dGame/dPropertyBehaviors/BlockDefinition.cpp b/dGame/dPropertyBehaviors/BlockDefinition.cpp new file mode 100644 index 00000000..2950ac82 --- /dev/null +++ b/dGame/dPropertyBehaviors/BlockDefinition.cpp @@ -0,0 +1,9 @@ +#include "BlockDefinition.h" + +BlockDefinition BlockDefinition::blockDefinitionDefault{}; + +BlockDefinition::BlockDefinition(std::string defaultValue, float minimumValue, float maximumValue) { + this->defaultValue = defaultValue; + this->minimumValue = minimumValue; + this->maximumValue = maximumValue; +} diff --git a/dGame/dPropertyBehaviors/BlockDefinition.h b/dGame/dPropertyBehaviors/BlockDefinition.h new file mode 100644 index 00000000..3a5a6bf1 --- /dev/null +++ b/dGame/dPropertyBehaviors/BlockDefinition.h @@ -0,0 +1,25 @@ +#ifndef __BLOCKDEFINITION__H__ +#define __BLOCKDEFINITION__H__ + +#include + +class AMFArrayValue; + +class BlockDefinition { +public: + BlockDefinition(std::string defaultValue = "", float minimumValue = 0.0f, float maximumValue = 0.0f); + static BlockDefinition blockDefinitionDefault; + + std::string& GetDefaultValue() { return defaultValue; }; + float GetMinimumValue() { return minimumValue; }; + float GetMaximumValue() { return maximumValue; }; + void SetDefaultValue(std::string value) { defaultValue = value; }; + void SetMinimumValue(float value) { minimumValue = value; }; + void SetMaximumValue(float value) { maximumValue = value; }; +private: + std::string defaultValue; + float minimumValue; + float maximumValue; +}; + +#endif //!__BLOCKDEFINITION__H__ diff --git a/dGame/dPropertyBehaviors/CMakeLists.txt b/dGame/dPropertyBehaviors/CMakeLists.txt index 4f5d60aa..5e33a5f5 100644 --- a/dGame/dPropertyBehaviors/CMakeLists.txt +++ b/dGame/dPropertyBehaviors/CMakeLists.txt @@ -1,4 +1,12 @@ set(DGAME_DPROPERTYBEHAVIORS_SOURCES + "BlockDefinition.cpp" "ControlBehaviors.cpp" - PARENT_SCOPE ) + +add_subdirectory(ControlBehaviorMessages) + +foreach(file ${DGAME_DPROPERTYBEHAVIORS_CONTROLBEHAVIORMESSAGES}) + set(DGAME_DPROPERTYBEHAVIORS_SOURCES ${DGAME_DPROPERTYBEHAVIORS_SOURCES} "ControlBehaviorMessages/${file}") +endforeach() + +set(DGAME_DPROPERTYBEHAVIORS_SOURCES ${DGAME_DPROPERTYBEHAVIORS_SOURCES} PARENT_SCOPE) diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddActionMessage.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddActionMessage.cpp new file mode 100644 index 00000000..f91512fe --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddActionMessage.cpp @@ -0,0 +1,39 @@ +#include "AddActionMessage.h" + +AddActionMessage::AddActionMessage(AMFArrayValue* arguments) { + auto* actionIndexAmf = arguments->FindValue("actionIndex"); + if (!actionIndexAmf) return; + + actionIndex = static_cast(actionIndexAmf->GetDoubleValue()); + + stripId = GetStripIDFromArgument(arguments); + + stateId = GetBehaviorStateFromArgument(arguments); + + type = ""; + valueParameterName = ""; + valueParameterString = ""; + valueParameterDouble = 0.0; + auto* action = arguments->FindValue("action"); + if (!action) return; + + for (auto& typeValueMap : action->GetAssociativeMap()) { + if (typeValueMap.first == "Type") { + if (typeValueMap.second->GetValueType() != AMFValueType::AMFString) continue; + type = static_cast(typeValueMap.second)->GetStringValue(); + } 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(); + } else { + if (typeValueMap.second->GetValueType() != AMFValueType::AMFDouble) continue; + valueParameterDouble = static_cast(typeValueMap.second)->GetDoubleValue(); + } + } + } + + behaviorId = GetBehaviorIDFromArgument(arguments); + Game::logger->LogDebug("AddActionMessage", "acnNdx %i stpId %i sttId %i t %s vpn %s vps %s vpd %f bhId %i", actionIndex, stripId, stateId, type.c_str(), valueParameterName.c_str(), valueParameterString.c_str(), valueParameterDouble, behaviorId); +} diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddActionMessage.h b/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddActionMessage.h new file mode 100644 index 00000000..1f1577ec --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddActionMessage.h @@ -0,0 +1,30 @@ +#ifndef __ADDACTIONMESSAGE__H__ +#define __ADDACTIONMESSAGE__H__ + +#include "BehaviorMessageBase.h" + +class AMFArrayValue; + +class AddActionMessage : public BehaviorMessageBase { +public: + AddActionMessage(AMFArrayValue* arguments); + const uint32_t GetActionIndex() { return actionIndex; }; + const StripId GetStripId() { return stripId; }; + const BehaviorState GetStateId() { return stateId; }; + const std::string& GetType() { return type; }; + const std::string& GetValueParameterName() { return valueParameterName; }; + const std::string& GetValueParameterString() { return valueParameterString; }; + const double GetValueParameterDouble() { return valueParameterDouble; }; + const uint32_t GetBehaviorId() { return behaviorId; }; +private: + uint32_t actionIndex; + StripId stripId; + BehaviorState stateId; + std::string type; + std::string valueParameterName; + std::string valueParameterString; + double valueParameterDouble; + uint32_t behaviorId; +}; + +#endif //!__ADDACTIONMESSAGE__H__ diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddMessage.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddMessage.cpp new file mode 100644 index 00000000..ecddb8e3 --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddMessage.cpp @@ -0,0 +1,13 @@ +#include "AddMessage.h" + +AddMessage::AddMessage(AMFArrayValue* arguments) { + behaviorId = GetBehaviorIDFromArgument(arguments); + + behaviorIndex = 0; + auto* behaviorIndexValue = arguments->FindValue("BehaviorIndex"); + + if (!behaviorIndexValue) return; + + behaviorIndex = static_cast(behaviorIndexValue->GetDoubleValue()); + Game::logger->LogDebug("AddMessage", "bhId %i ndx %i", behaviorId, behaviorIndex); +} diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddMessage.h b/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddMessage.h new file mode 100644 index 00000000..ff8e0c8b --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddMessage.h @@ -0,0 +1,16 @@ +#ifndef __ADDMESSAGE__H__ +#define __ADDMESSAGE__H__ + +#include "BehaviorMessageBase.h" + +class AddMessage : public BehaviorMessageBase { +public: + AddMessage(AMFArrayValue* arguments); + const uint32_t GetBehaviorIndex() { return behaviorIndex; }; + const uint32_t GetBehaviorId() { return behaviorId; }; +private: + uint32_t behaviorId; + uint32_t behaviorIndex; +}; + +#endif //!__ADDMESSAGE__H__ diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddStripMessage.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddStripMessage.cpp new file mode 100644 index 00000000..23662174 --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddStripMessage.cpp @@ -0,0 +1,56 @@ +#include "AddStripMessage.h" + +AddStripMessage::AddStripMessage(AMFArrayValue* arguments) { + auto* strip = arguments->FindValue("strip"); + if (!strip) return; + + auto* actions = strip->FindValue("actions"); + if (!actions) return; + + auto* uiArray = arguments->FindValue("ui"); + if (!uiArray) return; + + auto* xPositionValue = uiArray->FindValue("x"); + if (!xPositionValue) return; + + xPosition = xPositionValue->GetDoubleValue(); + + auto* yPositionValue = uiArray->FindValue("y"); + if (!yPositionValue) return; + + yPosition = yPositionValue->GetDoubleValue(); + + stripId = GetStripIDFromArgument(arguments); + + stateId = GetBehaviorStateFromArgument(arguments); + + behaviorId = GetBehaviorIDFromArgument(arguments); + + type = ""; + valueParameterName = ""; + valueParameterString = ""; + valueParameterDouble = 0.0; + for (uint32_t position = 0; position < actions->GetDenseValueSize(); position++) { + auto* actionAsArray = actions->GetValueAt(position); + if (!actionAsArray) continue; + + for (auto& typeValueMap : actionAsArray->GetAssociativeMap()) { + if (typeValueMap.first == "Type") { + if (typeValueMap.second->GetValueType() != AMFValueType::AMFString) continue; + + type = static_cast(typeValueMap.second)->GetStringValue(); + } 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(); + } else { + if (typeValueMap.second->GetValueType() != AMFValueType::AMFDouble) continue; + valueParameterDouble = static_cast(typeValueMap.second)->GetDoubleValue(); + } + } + } + Game::logger->LogDebug("AddStripMessage", "x %f y %f stpId %i sttId %i bhId %i t %s vpn %s vps %s vpd %f", xPosition, yPosition, stripId, stateId, behaviorId, type.c_str(), valueParameterName.c_str(), valueParameterString.c_str(), valueParameterDouble); + } +} diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddStripMessage.h b/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddStripMessage.h new file mode 100644 index 00000000..bb720bae --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddStripMessage.h @@ -0,0 +1,32 @@ +#ifndef __ADDSTRIPMESSAGE__H__ +#define __ADDSTRIPMESSAGE__H__ + +#include "BehaviorMessageBase.h" + +class AMFArrayValue; + +class AddStripMessage : public BehaviorMessageBase { +public: + AddStripMessage(AMFArrayValue* arguments); + const StripId GetStripId() { return stripId; }; + const BehaviorState GetStateId() { return stateId; }; + const std::string& GetType() { return type; }; + const std::string& GetValueParameterName() { return valueParameterName; }; + const std::string& GetValueParameterString() { return valueParameterString; }; + const double GetXPosition() { return xPosition; }; + const double GetYPosition() { return yPosition; }; + const double GetValueParameterDouble() { return valueParameterDouble; }; + const uint32_t GetBehaviorId() { return behaviorId; }; +private: + double xPosition; + double yPosition; + StripId stripId; + BehaviorState stateId; + uint32_t behaviorId; + std::string type; + std::string valueParameterName; + std::string valueParameterString; + double valueParameterDouble; +}; + +#endif //!__ADDSTRIPMESSAGE__H__ diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/BehaviorMessageBase.h b/dGame/dPropertyBehaviors/ControlBehaviorMessages/BehaviorMessageBase.h new file mode 100644 index 00000000..78025672 --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/BehaviorMessageBase.h @@ -0,0 +1,48 @@ +#ifndef __BEHAVIORMESSAGEBASE__H__ +#define __BEHAVIORMESSAGEBASE__H__ + +#include +#include + +#include "AMFFormat.h" +#include "BehaviorStates.h" +#include "dCommonVars.h" + +#include "Game.h" +#include "dLogger.h" + +class BehaviorMessageBase { +public: + uint32_t GetBehaviorIDFromArgument(AMFArrayValue* arguments, const std::string& key = "BehaviorID") { + auto* behaviorIDValue = arguments->FindValue(key); + uint32_t behaviorID = -1; + + if (behaviorIDValue) { + behaviorID = std::stoul(behaviorIDValue->GetStringValue()); + } else if (arguments->FindValue(key) == nullptr) { + throw std::invalid_argument("Unable to find behavior ID from argument \"" + key + "\""); + } + + return behaviorID; + } + + BehaviorState GetBehaviorStateFromArgument(AMFArrayValue* arguments, const std::string& key = "stateID") { + auto* stateIDValue = arguments->FindValue(key); + if (!stateIDValue) throw std::invalid_argument("Unable to find behavior state from argument \"" + key + "\""); + + BehaviorState stateID = static_cast(stateIDValue->GetDoubleValue()); + + return stateID; + } + + StripId GetStripIDFromArgument(AMFArrayValue* arguments, const std::string& key = "stripID") { + auto* stripIDValue = arguments->FindValue(key); + if (!stripIDValue) throw std::invalid_argument("Unable to find strip ID from argument \"" + key + "\""); + + StripId stripID = static_cast(stripIDValue->GetDoubleValue()); + + return stripID; + } +}; + +#endif //!__BEHAVIORMESSAGEBASE__H__ diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/CMakeLists.txt b/dGame/dPropertyBehaviors/ControlBehaviorMessages/CMakeLists.txt new file mode 100644 index 00000000..8390cd22 --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/CMakeLists.txt @@ -0,0 +1,16 @@ +set(DGAME_DPROPERTYBEHAVIORS_CONTROLBEHAVIORMESSAGES + "AddActionMessage.cpp" + "AddMessage.cpp" + "AddStripMessage.cpp" + "MergeStripsMessage.cpp" + "MigrateActionsMessage.cpp" + "MoveToInventoryMessage.cpp" + "RearrangeStripMessage.cpp" + "RemoveActionsMessage.cpp" + "RemoveStripMessage.cpp" + "RenameMessage.cpp" + "SplitStripMessage.cpp" + "UpdateActionMessage.cpp" + "UpdateStripUiMessage.cpp" + PARENT_SCOPE +) diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/MergeStripsMessage.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/MergeStripsMessage.cpp new file mode 100644 index 00000000..d810e861 --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/MergeStripsMessage.cpp @@ -0,0 +1,20 @@ +#include "MergeStripsMessage.h" + +MergeStripsMessage::MergeStripsMessage(AMFArrayValue* arguments) { + srcStripID = GetStripIDFromArgument(arguments, "srcStripID"); + + dstStateID = GetBehaviorStateFromArgument(arguments, "dstStateID"); + + srcStateID = GetBehaviorStateFromArgument(arguments, "srcStateID"); + + auto* dstActionIndexValue = arguments->FindValue("dstActionIndex"); + if (!dstActionIndexValue) return; + + dstActionIndex = static_cast(dstActionIndexValue->GetDoubleValue()); + + dstStripID = GetStripIDFromArgument(arguments, "dstStripID"); + + behaviorID = GetBehaviorIDFromArgument(arguments); + Game::logger->LogDebug("MergeStripsMessage", "srcStpId %i dstStpId %i srcSttId %i dstSttId %i dstAcnNdx %i bhId %i", srcStripID, dstStripID, srcStateID, dstStateID, dstActionIndex, behaviorID); +} + diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/MergeStripsMessage.h b/dGame/dPropertyBehaviors/ControlBehaviorMessages/MergeStripsMessage.h new file mode 100644 index 00000000..af3aa16f --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/MergeStripsMessage.h @@ -0,0 +1,26 @@ +#ifndef __MERGESTRIPSMESSAGE__H__ +#define __MERGESTRIPSMESSAGE__H__ + +#include "BehaviorMessageBase.h" + +class AMFArrayValue; + +class MergeStripsMessage : public BehaviorMessageBase { +public: + MergeStripsMessage(AMFArrayValue* arguments); + const StripId GetSrcStripID() { return srcStripID; }; + const BehaviorState GetDstStateID() { return dstStateID; }; + const BehaviorState GetSrcStateID() { return srcStateID; }; + const uint32_t GetDstActionIndex() { return dstActionIndex; }; + const StripId GetDstStripID() { return dstStripID; }; + const uint32_t GetBehaviorID() { return behaviorID; }; +private: + StripId srcStripID; + BehaviorState dstStateID; + BehaviorState srcStateID; + uint32_t dstActionIndex; + StripId dstStripID; + uint32_t behaviorID; +}; + +#endif //!__MERGESTRIPSMESSAGE__H__ diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/MigrateActionsMessage.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/MigrateActionsMessage.cpp new file mode 100644 index 00000000..8bb4e819 --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/MigrateActionsMessage.cpp @@ -0,0 +1,24 @@ +#include "MigrateActionsMessage.h" + +MigrateActionsMessage::MigrateActionsMessage(AMFArrayValue* arguments) { + auto* srcActionIndexAmf = arguments->FindValue("srcActionIndex"); + if (!srcActionIndexAmf) return; + + srcActionIndex = static_cast(srcActionIndexAmf->GetDoubleValue()); + + srcStripID = GetStripIDFromArgument(arguments, "srcStripID"); + + srcStateID = GetBehaviorStateFromArgument(arguments, "srcStateID"); + + auto* dstActionIndexAmf = arguments->FindValue("dstActionIndex"); + if (!dstActionIndexAmf) return; + + dstActionIndex = static_cast(dstActionIndexAmf->GetDoubleValue()); + + dstStripID = GetStripIDFromArgument(arguments, "dstStripID"); + + dstStateID = GetBehaviorStateFromArgument(arguments, "dstStateID"); + + behaviorID = GetBehaviorIDFromArgument(arguments); + Game::logger->LogDebug("MigrateActionsMessage", "srcAcnNdx %i dstAcnNdx %i srcStpId %i dstStpId %i srcSttId %i dstSttId %i bhid %i", srcActionIndex, dstActionIndex, srcStripID, dstStripID, srcStateID, dstStateID, behaviorID); +} diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/MigrateActionsMessage.h b/dGame/dPropertyBehaviors/ControlBehaviorMessages/MigrateActionsMessage.h new file mode 100644 index 00000000..26018d69 --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/MigrateActionsMessage.h @@ -0,0 +1,28 @@ +#ifndef __MIGRATEACTIONSMESSAGE__H__ +#define __MIGRATEACTIONSMESSAGE__H__ + +#include "BehaviorMessageBase.h" + +class AMFArrayValue; + +class MigrateActionsMessage : public BehaviorMessageBase { +public: + MigrateActionsMessage(AMFArrayValue* arguments); + const uint32_t GetSrcActionIndex() { return srcActionIndex; }; + const StripId GetSrcStripID() { return srcStripID; }; + const BehaviorState GetSrcStateID() { return srcStateID; }; + const uint32_t GetDstActionIndex() { return dstActionIndex; }; + const StripId GetDstStripID() { return dstStripID; }; + const BehaviorState GetDstStateID() { return dstStateID; }; + const uint32_t GetBehaviorID() { return behaviorID; }; +private: + uint32_t srcActionIndex; + StripId srcStripID; + BehaviorState srcStateID; + uint32_t dstActionIndex; + StripId dstStripID; + BehaviorState dstStateID; + uint32_t behaviorID; +}; + +#endif //!__MIGRATEACTIONSMESSAGE__H__ diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/MoveToInventoryMessage.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/MoveToInventoryMessage.cpp new file mode 100644 index 00000000..7ad7a875 --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/MoveToInventoryMessage.cpp @@ -0,0 +1,11 @@ +#include "MoveToInventoryMessage.h" + +MoveToInventoryMessage::MoveToInventoryMessage(AMFArrayValue* arguments) { + behaviorID = GetBehaviorIDFromArgument(arguments); + + auto* behaviorIndexValue = arguments->FindValue("BehaviorIndex"); + if (!behaviorIndexValue) return; + + behaviorIndex = static_cast(behaviorIndexValue->GetDoubleValue()); + Game::logger->LogDebug("MoveToInventoryMessage", "bhId %i bhNdx %i", behaviorID, behaviorIndex); +} diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/MoveToInventoryMessage.h b/dGame/dPropertyBehaviors/ControlBehaviorMessages/MoveToInventoryMessage.h new file mode 100644 index 00000000..2cf71f3c --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/MoveToInventoryMessage.h @@ -0,0 +1,19 @@ +#ifndef __MOVETOINVENTORYMESSAGE__H__ +#define __MOVETOINVENTORYMESSAGE__H__ + +#include "BehaviorMessageBase.h" + +class AMFArrayValue; + +#pragma warning("This Control Behavior Message does not have a test yet. Non-developers can ignore this warning.") +class MoveToInventoryMessage: public BehaviorMessageBase { +public: + MoveToInventoryMessage(AMFArrayValue* arguments); + const uint32_t GetBehaviorID() { return behaviorID; }; + const uint32_t GetBehaviorIndex() { return behaviorIndex; }; +private: + uint32_t behaviorID; + uint32_t behaviorIndex; +}; + +#endif //!__MOVETOINVENTORYMESSAGE__H__ diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/RearrangeStripMessage.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/RearrangeStripMessage.cpp new file mode 100644 index 00000000..0347aca6 --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/RearrangeStripMessage.cpp @@ -0,0 +1,16 @@ +#include "RearrangeStripMessage.h" + +RearrangeStripMessage::RearrangeStripMessage(AMFArrayValue* arguments) { + auto* srcActionIndexValue = arguments->FindValue("srcActionIndex"); + srcActionIndex = static_cast(srcActionIndexValue->GetDoubleValue()); + + stripID = GetStripIDFromArgument(arguments); + + behaviorID = GetBehaviorIDFromArgument(arguments); + + auto* dstActionIndexValue = arguments->FindValue("dstActionIndex"); + dstActionIndex = static_cast(dstActionIndexValue->GetDoubleValue()); + + stateID = GetBehaviorStateFromArgument(arguments); + Game::logger->LogDebug("RearrangeStripMessage", "srcAcnNdx %i dstAcnNdx %i stpId %i bhId %i sttId %i", srcActionIndex, dstActionIndex, stripID, behaviorID, stateID); +} diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/RearrangeStripMessage.h b/dGame/dPropertyBehaviors/ControlBehaviorMessages/RearrangeStripMessage.h new file mode 100644 index 00000000..4cca0827 --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/RearrangeStripMessage.h @@ -0,0 +1,22 @@ +#ifndef __REARRANGESTRIPMESSAGE__H__ +#define __REARRANGESTRIPMESSAGE__H__ + +#include "BehaviorMessageBase.h" + +class RearrangeStripMessage : public BehaviorMessageBase { +public: + RearrangeStripMessage(AMFArrayValue* arguments); + const uint32_t GetSrcActionIndex() { return srcActionIndex; }; + const uint32_t GetStripID() { return stripID; }; + const uint32_t GetBehaviorID() { return behaviorID; }; + const uint32_t GetDstActionIndex() { return dstActionIndex; }; + const BehaviorState GetStateID() { return stateID; }; +private: + uint32_t srcActionIndex; + uint32_t stripID; + uint32_t behaviorID; + uint32_t dstActionIndex; + BehaviorState stateID; +}; + +#endif //!__REARRANGESTRIPMESSAGE__H__ diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/RemoveActionsMessage.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/RemoveActionsMessage.cpp new file mode 100644 index 00000000..cb1226e3 --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/RemoveActionsMessage.cpp @@ -0,0 +1,15 @@ +#include "RemoveActionsMessage.h" + +RemoveActionsMessage::RemoveActionsMessage(AMFArrayValue* arguments) { + behaviorID = GetBehaviorIDFromArgument(arguments); + + auto* actionIndexAmf = arguments->FindValue("actionIndex"); + if (!actionIndexAmf) return; + + actionIndex = static_cast(actionIndexAmf->GetDoubleValue()); + + stripID = GetStripIDFromArgument(arguments); + + stateID = GetBehaviorStateFromArgument(arguments); + Game::logger->LogDebug("RemoveActionsMessage", "bhId %i acnNdx %i stpId %i sttId %i", behaviorID, actionIndex, stripID, stateID); +} diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/RemoveActionsMessage.h b/dGame/dPropertyBehaviors/ControlBehaviorMessages/RemoveActionsMessage.h new file mode 100644 index 00000000..33678f59 --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/RemoveActionsMessage.h @@ -0,0 +1,22 @@ +#ifndef __REMOVEACTIONSMESSAGE__H__ +#define __REMOVEACTIONSMESSAGE__H__ + +#include "BehaviorMessageBase.h" + +class AMFArrayValue; + +class RemoveActionsMessage : public BehaviorMessageBase { +public: + RemoveActionsMessage(AMFArrayValue* arguments); + const uint32_t GetBehaviorID() { return behaviorID; }; + const uint32_t GetActionIndex() { return actionIndex; }; + const StripId GetStripID() { return stripID; }; + const BehaviorState GetStateID() { return stateID; }; +private: + uint32_t behaviorID; + uint32_t actionIndex; + StripId stripID; + BehaviorState stateID; +}; + +#endif //!__REMOVEACTIONSMESSAGE__H__ diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/RemoveStripMessage.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/RemoveStripMessage.cpp new file mode 100644 index 00000000..3c48ed16 --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/RemoveStripMessage.cpp @@ -0,0 +1,8 @@ +#include "RemoveStripMessage.h" + +RemoveStripMessage::RemoveStripMessage(AMFArrayValue* arguments) { + stripId = GetStripIDFromArgument(arguments); + behaviorState = GetBehaviorStateFromArgument(arguments); + behaviorId = GetBehaviorIDFromArgument(arguments); + Game::logger->LogDebug("RemoveStripMessage", "stpId %i bhStt %i bhId %i", stripId, behaviorState, behaviorId); +} diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/RemoveStripMessage.h b/dGame/dPropertyBehaviors/ControlBehaviorMessages/RemoveStripMessage.h new file mode 100644 index 00000000..312bab31 --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/RemoveStripMessage.h @@ -0,0 +1,18 @@ +#ifndef __REMOVESTRIPMESSAGE__H__ +#define __REMOVESTRIPMESSAGE__H__ + +#include "BehaviorMessageBase.h" + +class RemoveStripMessage : public BehaviorMessageBase { +public: + RemoveStripMessage(AMFArrayValue* arguments); + const StripId GetStripId() { return stripId; }; + const BehaviorState GetBehaviorState() { return behaviorState; }; + const uint32_t GetBehaviorId() { return behaviorId; }; +private: + StripId stripId; + BehaviorState behaviorState; + uint32_t behaviorId; +}; + +#endif //!__REMOVESTRIPMESSAGE__H__ diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/RenameMessage.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/RenameMessage.cpp new file mode 100644 index 00000000..38c49462 --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/RenameMessage.cpp @@ -0,0 +1,11 @@ +#include "RenameMessage.h" + +RenameMessage::RenameMessage(AMFArrayValue* arguments) { + behaviorID = GetBehaviorIDFromArgument(arguments); + + auto* nameAmf = arguments->FindValue("Name"); + if (!nameAmf) return; + + name = nameAmf->GetStringValue(); + Game::logger->LogDebug("RenameMessage", "bhId %i n %s", behaviorID, name.c_str()); +} diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/RenameMessage.h b/dGame/dPropertyBehaviors/ControlBehaviorMessages/RenameMessage.h new file mode 100644 index 00000000..be42d66f --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/RenameMessage.h @@ -0,0 +1,18 @@ +#ifndef __RENAMEMESSAGE__H__ +#define __RENAMEMESSAGE__H__ + +#include "BehaviorMessageBase.h" + +class AMFArrayValue; + +class RenameMessage : public BehaviorMessageBase { +public: + RenameMessage(AMFArrayValue* arguments); + const uint32_t GetBehaviorID() { return behaviorID; }; + const std::string& GetName() { return name; }; +private: + uint32_t behaviorID; + std::string name; +}; + +#endif //!__RENAMEMESSAGE__H__ diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/SplitStripMessage.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/SplitStripMessage.cpp new file mode 100644 index 00000000..d3493aeb --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/SplitStripMessage.cpp @@ -0,0 +1,29 @@ +#include "SplitStripMessage.h" + +SplitStripMessage::SplitStripMessage(AMFArrayValue* arguments) { + auto* srcActionIndexValue = arguments->FindValue("srcActionIndex"); + if (!srcActionIndexValue) return; + + srcActionIndex = static_cast(srcActionIndexValue->GetDoubleValue()); + + srcStripId = GetStripIDFromArgument(arguments, "srcStripID"); + + srcStateId = GetBehaviorStateFromArgument(arguments, "srcStateID"); + + dstStripId = GetStripIDFromArgument(arguments, "dstStripID"); + + dstStateId = GetBehaviorStateFromArgument(arguments, "dstStateID"); + + auto* dstStripUiArray = arguments->FindValue("dstStripUI"); + if (!dstStripUiArray) return; + + auto* xPositionValue = dstStripUiArray->FindValue("x"); + auto* yPositionValue = dstStripUiArray->FindValue("y"); + if (!xPositionValue || !yPositionValue) return; + + yPosition = yPositionValue->GetDoubleValue(); + xPosition = xPositionValue->GetDoubleValue(); + + behaviorId = GetBehaviorIDFromArgument(arguments); + Game::logger->LogDebug("SplitStripMessage", "bhid %i x %f y %f srcStp %i dstStp %i srcStt %i dstStt %i srcActNdx %i", behaviorId, xPosition, yPosition, srcStripId, dstStripId, srcStateId, dstStateId, srcActionIndex); +} diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/SplitStripMessage.h b/dGame/dPropertyBehaviors/ControlBehaviorMessages/SplitStripMessage.h new file mode 100644 index 00000000..e06a9dc4 --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/SplitStripMessage.h @@ -0,0 +1,30 @@ +#ifndef __SPLITSTRIPMESSAGE__H__ +#define __SPLITSTRIPMESSAGE__H__ + +#include "BehaviorMessageBase.h" + +class AMFArrayValue; + +class SplitStripMessage : public BehaviorMessageBase { +public: + SplitStripMessage(AMFArrayValue* arguments); + const uint32_t GetSrcActionIndex() { return srcActionIndex; }; + const StripId GetSrcStripId() { return srcStripId; }; + const BehaviorState GetSrcStateId() { return srcStateId; }; + const StripId GetDstStripId() { return dstStripId; }; + const BehaviorState GetDstStateId() { return dstStateId; }; + const double GetYPosition() { return yPosition; }; + const double GetXPosition() { return xPosition; }; + const uint32_t GetBehaviorId() { return behaviorId; }; +private: + uint32_t srcActionIndex; + StripId srcStripId; + BehaviorState srcStateId; + StripId dstStripId; + BehaviorState dstStateId; + double yPosition; + double xPosition; + uint32_t behaviorId; +}; + +#endif //!__SPLITSTRIPMESSAGE__H__ diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/UpdateActionMessage.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/UpdateActionMessage.cpp new file mode 100644 index 00000000..1d4cc868 --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/UpdateActionMessage.cpp @@ -0,0 +1,38 @@ +#include "UpdateActionMessage.h" + +UpdateActionMessage::UpdateActionMessage(AMFArrayValue* arguments) { + type = ""; + valueParameterName = ""; + valueParameterString = ""; + valueParameterDouble = 0.0; + auto* actionAsArray = arguments->FindValue("action"); + if (!actionAsArray) return; + for (auto& typeValueMap : actionAsArray->GetAssociativeMap()) { + if (typeValueMap.first == "Type") { + if (typeValueMap.second->GetValueType() != AMFValueType::AMFString) continue; + type = static_cast(typeValueMap.second)->GetStringValue(); + } 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(); + } else { + if (typeValueMap.second->GetValueType() != AMFValueType::AMFDouble) continue; + valueParameterDouble = static_cast(typeValueMap.second)->GetDoubleValue(); + } + } + } + + behaviorID = GetBehaviorIDFromArgument(arguments); + + auto* actionIndexValue = arguments->FindValue("actionIndex"); + if (!actionIndexValue) return; + + actionIndex = static_cast(actionIndexValue->GetDoubleValue()); + + stripID = GetStripIDFromArgument(arguments); + + stateID = GetBehaviorStateFromArgument(arguments); + Game::logger->LogDebug("UpdateActionMessage", "t %s vpn %s vps %s vpd %f bhId %i acnNdx %i stpId %i sttId %i", type.c_str(), valueParameterName.c_str(), valueParameterString.c_str(), valueParameterDouble, behaviorID, actionIndex, stripID, stateID); +} diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/UpdateActionMessage.h b/dGame/dPropertyBehaviors/ControlBehaviorMessages/UpdateActionMessage.h new file mode 100644 index 00000000..a42be22b --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/UpdateActionMessage.h @@ -0,0 +1,30 @@ +#ifndef __UPDATEACTIONMESSAGE__H__ +#define __UPDATEACTIONMESSAGE__H__ + +#include "BehaviorMessageBase.h" + +class AMFArrayValue; + +class UpdateActionMessage : public BehaviorMessageBase { +public: + UpdateActionMessage(AMFArrayValue* arguments); + const std::string& GetType() { return type; }; + const std::string& GetValueParameterName() { return valueParameterName; }; + const std::string& GetValueParameterString() { return valueParameterString; }; + const double GetValueParameterDouble() { return valueParameterDouble; }; + const uint32_t GetBehaviorID() { return behaviorID; }; + const uint32_t GetActionIndex() { return actionIndex; }; + const StripId GetStripID() { return stripID; }; + const BehaviorState GetStateID() { return stateID; }; +private: + std::string type; + std::string valueParameterName; + std::string valueParameterString; + double valueParameterDouble; + uint32_t behaviorID; + uint32_t actionIndex; + StripId stripID; + BehaviorState stateID; +}; + +#endif //!__UPDATEACTIONMESSAGE__H__ diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/UpdateStripUiMessage.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/UpdateStripUiMessage.cpp new file mode 100644 index 00000000..60e2f0f3 --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/UpdateStripUiMessage.cpp @@ -0,0 +1,20 @@ +#include "UpdateStripUiMessage.h" + +UpdateStripUiMessage::UpdateStripUiMessage(AMFArrayValue* arguments) { + auto* uiArray = arguments->FindValue("ui"); + if (!uiArray) return; + + auto* xPositionValue = uiArray->FindValue("x"); + auto* yPositionValue = uiArray->FindValue("y"); + if (!xPositionValue || !yPositionValue) return; + + yPosition = yPositionValue->GetDoubleValue(); + xPosition = xPositionValue->GetDoubleValue(); + + stripID = GetStripIDFromArgument(arguments); + + stateID = GetBehaviorStateFromArgument(arguments); + + behaviorID = GetBehaviorIDFromArgument(arguments); + Game::logger->LogDebug("UpdateStripUIMessage", "x %f y %f stpId %i sttId %i bhId %i", xPosition, yPosition, stripID, stateID, behaviorID); +} diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/UpdateStripUiMessage.h b/dGame/dPropertyBehaviors/ControlBehaviorMessages/UpdateStripUiMessage.h new file mode 100644 index 00000000..ca626120 --- /dev/null +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/UpdateStripUiMessage.h @@ -0,0 +1,24 @@ +#ifndef __UPDATESTRIPUIMESSAGE__H__ +#define __UPDATESTRIPUIMESSAGE__H__ + +#include "BehaviorMessageBase.h" + +class AMFArrayValue; + +class UpdateStripUiMessage : public BehaviorMessageBase { +public: + UpdateStripUiMessage(AMFArrayValue* arguments); + const double GetYPosition() { return yPosition; }; + const double GetXPosition() { return xPosition; }; + const StripId GetStripID() { return stripID; }; + const BehaviorState GetStateID() { return stateID; }; + const uint32_t GetBehaviorID() { return behaviorID; }; +private: + double yPosition; + double xPosition; + StripId stripID; + BehaviorState stateID; + uint32_t behaviorID; +}; + +#endif //!__UPDATESTRIPUIMESSAGE__H__ diff --git a/dGame/dPropertyBehaviors/ControlBehaviors.cpp b/dGame/dPropertyBehaviors/ControlBehaviors.cpp index 278b6929..3e8bbacc 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviors.cpp +++ b/dGame/dPropertyBehaviors/ControlBehaviors.cpp @@ -7,40 +7,29 @@ #include "ModelComponent.h" #include "../../dWorldServer/ObjectIDManager.h" #include "dLogger.h" +#include "BehaviorStates.h" +#include "AssetManager.h" +#include "BlockDefinition.h" #include "User.h" +#include "tinyxml2.h" +#include "CDClientDatabase.h" -uint32_t GetBehaviorIDFromArgument(AMFArrayValue* arguments, const std::string& key = "BehaviorID") { - auto* behaviorIDValue = arguments->FindValue(key); - uint32_t behaviorID = -1; +// Message includes +#include "AddActionMessage.h" +#include "AddStripMessage.h" +#include "AddMessage.h" +#include "MigrateActionsMessage.h" +#include "MoveToInventoryMessage.h" +#include "MergeStripsMessage.h" +#include "RearrangeStripMessage.h" +#include "RemoveActionsMessage.h" +#include "RemoveStripMessage.h" +#include "RenameMessage.h" +#include "SplitStripMessage.h" +#include "UpdateActionMessage.h" +#include "UpdateStripUiMessage.h" - if (behaviorIDValue) { - behaviorID = std::stoul(behaviorIDValue->GetStringValue()); - } else if (arguments->FindValue(key) == nullptr){ - throw std::invalid_argument("Unable to find behavior ID from argument \"" + key + "\""); - } - - return behaviorID; -} - -BEHAVIORSTATE GetBehaviorStateFromArgument(AMFArrayValue* arguments, const std::string& key = "stateID") { - auto* stateIDValue = arguments->FindValue(key); - if (!stateIDValue) throw std::invalid_argument("Unable to find behavior state from argument \"" + key + "\""); - - BEHAVIORSTATE stateID = static_cast(stateIDValue->GetDoubleValue()); - - return stateID; -} - -STRIPID GetStripIDFromArgument(AMFArrayValue* arguments, const std::string& key = "stripID") { - auto* stripIDValue = arguments->FindValue(key); - if (!stripIDValue) throw std::invalid_argument("Unable to find strip ID from argument \"" + key + "\""); - - STRIPID stripID = static_cast(stripIDValue->GetDoubleValue()); - - return stripID; -} - -void RequestUpdatedID(int32_t behaviorID, ModelComponent* modelComponent, Entity* modelOwner, const SystemAddress& sysAddr) { +void ControlBehaviors::RequestUpdatedID(int32_t behaviorID, ModelComponent* modelComponent, Entity* modelOwner, const SystemAddress& sysAddr) { // auto behavior = modelComponent->FindBehavior(behaviorID); // if (behavior->GetBehaviorID() == -1 || behavior->GetShouldSetNewID()) { // ObjectIDManager::Instance()->RequestPersistentID( @@ -66,11 +55,7 @@ void RequestUpdatedID(int32_t behaviorID, ModelComponent* modelComponent, Entity // } } -void SendBehaviorListToClient( - Entity* modelEntity, - const SystemAddress& sysAddr, - Entity* modelOwner - ) { +void ControlBehaviors::SendBehaviorListToClient(Entity* modelEntity, const SystemAddress& sysAddr, Entity* modelOwner) { auto* modelComponent = modelEntity->GetComponent(); if (!modelComponent) return; @@ -98,7 +83,7 @@ void SendBehaviorListToClient( GameMessages::SendUIMessageServerToSingleClient(modelOwner, sysAddr, "UpdateBehaviorList", &behaviorsToSerialize); } -void ModelTypeChanged(AMFArrayValue* arguments, ModelComponent* ModelComponent) { +void ControlBehaviors::ModelTypeChanged(AMFArrayValue* arguments, ModelComponent* ModelComponent) { auto* modelTypeAmf = arguments->FindValue("ModelType"); if (!modelTypeAmf) return; @@ -107,292 +92,57 @@ void ModelTypeChanged(AMFArrayValue* arguments, ModelComponent* ModelComponent) //TODO Update the model type here } -void ToggleExecutionUpdates() { +void ControlBehaviors::ToggleExecutionUpdates() { //TODO do something with this info } -void AddStrip(AMFArrayValue* arguments) { - auto* strip = arguments->FindValue("strip"); - if (!strip) return; - - auto* actions = strip->FindValue("actions"); - if (!actions) return; - - auto* uiArray = arguments->FindValue("ui"); - if (!uiArray) return; - - auto* xPositionValue = uiArray->FindValue("x"); - if (!xPositionValue) return; - - double xPosition = xPositionValue->GetDoubleValue(); - - auto* yPositionValue = uiArray->FindValue("y"); - if (!yPositionValue) return; - - double yPosition = yPositionValue->GetDoubleValue(); - - STRIPID stripID = GetStripIDFromArgument(arguments); - - BEHAVIORSTATE stateID = GetBehaviorStateFromArgument(arguments); - - uint32_t behaviorID = GetBehaviorIDFromArgument(arguments); - - std::string type = ""; - std::string valueParameterName = ""; - std::string valueParameterString = ""; - double valueParameterDouble = 0.0; - for (uint32_t position = 0; position < actions->GetDenseValueSize(); position++) { - auto* actionAsArray = actions->GetValueAt(position); - if (!actionAsArray) continue; - - for (auto& typeValueMap : actionAsArray->GetAssociativeMap()) { - if (typeValueMap.first == "Type") { - if (typeValueMap.second->GetValueType() != AMFValueType::AMFString) continue; - - type = static_cast(typeValueMap.second)->GetStringValue(); - } 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(); - } else { - if (typeValueMap.second->GetValueType() != AMFValueType::AMFDouble) continue; - valueParameterDouble = static_cast(typeValueMap.second)->GetDoubleValue(); - } - } - } - // modelComponent->AddStrip(stateID, stripID, type, behaviorID, valueParameterName, valueParameterString, valueParameterDouble, "", xPosition, yPosition); - type.clear(); - valueParameterName.clear(); - valueParameterString.clear(); - valueParameterDouble = 0.0; - } - // RequestUpdatedID(behaviorID); +void ControlBehaviors::AddStrip(AMFArrayValue* arguments) { + AddStripMessage addStripMessage(arguments); } -void RemoveStrip(AMFArrayValue* arguments) { - STRIPID stripID = GetStripIDFromArgument(arguments); - - BEHAVIORSTATE stateID = GetBehaviorStateFromArgument(arguments); - - uint32_t behaviorID = GetBehaviorIDFromArgument(arguments); - - // modelComponent->RemoveStrip(stateID, stripID, behaviorID); - - // RequestUpdatedID(behaviorID); +void ControlBehaviors::RemoveStrip(AMFArrayValue* arguments) { + RemoveStripMessage removeStrip(arguments); } -void MergeStrips(AMFArrayValue* arguments) { - STRIPID srcStripID = GetStripIDFromArgument(arguments, "srcStripID"); - - BEHAVIORSTATE dstStateID = GetBehaviorStateFromArgument(arguments, "dstStateID"); - - BEHAVIORSTATE srcStateID = GetBehaviorStateFromArgument(arguments, "srcStateID"); - - auto* dstActionIndexValue = arguments->FindValue("dstActionIndex"); - if (!dstActionIndexValue) return; - - uint32_t dstActionIndex = static_cast(dstActionIndexValue->GetDoubleValue()); - - STRIPID dstStripID = GetStripIDFromArgument(arguments, "dstStripID"); - - uint32_t behaviorID = GetBehaviorIDFromArgument(arguments); - - // modelComponent->MergeStrips(srcStripID, dstStripID, srcStateID, dstStateID, behaviorID, dstActionIndex); - - // RequestUpdatedID(behaviorID); +void ControlBehaviors::MergeStrips(AMFArrayValue* arguments) { + MergeStripsMessage mergeStripsMessage(arguments); } -void SplitStrip(AMFArrayValue* arguments) { - auto* srcActionIndexValue = arguments->FindValue("srcActionIndex"); - if (!srcActionIndexValue) return; - - uint32_t srcActionIndex = static_cast(srcActionIndexValue->GetDoubleValue()); - - STRIPID srcStripID = GetStripIDFromArgument(arguments, "srcStripID"); - - BEHAVIORSTATE srcStateID = GetBehaviorStateFromArgument(arguments, "srcStateID"); - - STRIPID dstStripID = GetStripIDFromArgument(arguments, "dstStripID"); - - BEHAVIORSTATE dstStateID = GetBehaviorStateFromArgument(arguments, "dstStateID"); - - auto* dstStripUIArray = arguments->FindValue("dstStripUI"); - if (!dstStripUIArray) return; - - auto* xPositionValue = dstStripUIArray->FindValue("x"); - auto* yPositionValue = dstStripUIArray->FindValue("y"); - if (!xPositionValue || !yPositionValue) return; - - // x and y position 15 are just where the game puts the strip by default if none is given. - double yPosition = yPositionValue->GetDoubleValue(); - double xPosition = xPositionValue->GetDoubleValue(); - - uint32_t behaviorID = GetBehaviorIDFromArgument(arguments); - - // modelComponent->SplitStrip(srcActionIndex, srcStripID, srcStateID, dstStripID, dstStateID, behaviorID, yPosition, xPosition); - - // RequestUpdatedID(behaviorID); +void ControlBehaviors::SplitStrip(AMFArrayValue* arguments) { + SplitStripMessage splitStripMessage(arguments); } -void UpdateStripUI(AMFArrayValue* arguments) { - auto* uiArray = arguments->FindValue("ui"); - if (!uiArray) return; - - auto* xPositionValue = uiArray->FindValue("x"); - auto* yPositionValue = uiArray->FindValue("y"); - if (!xPositionValue || !yPositionValue) return; - - double yPosition = yPositionValue->GetDoubleValue(); - double xPosition = xPositionValue->GetDoubleValue(); - - STRIPID stripID = GetStripIDFromArgument(arguments); - - BEHAVIORSTATE stateID = GetBehaviorStateFromArgument(arguments); - - uint32_t behaviorID = GetBehaviorIDFromArgument(arguments); - - // modelComponent->UpdateUIOfStrip(stateID, stripID, xPosition, yPosition, behaviorID); - - // RequestUpdatedID(behaviorID); +void ControlBehaviors::UpdateStripUI(AMFArrayValue* arguments) { + UpdateStripUiMessage updateStripUiMessage(arguments); } -void AddAction(AMFArrayValue* arguments) { - auto* actionIndexAmf = arguments->FindValue("actionIndex"); - if (!actionIndexAmf) return; - - uint32_t actionIndex = static_cast(actionIndexAmf->GetDoubleValue()); - - STRIPID stripID = GetStripIDFromArgument(arguments); - - BEHAVIORSTATE stateID = GetBehaviorStateFromArgument(arguments); - - std::string type = ""; - std::string valueParameterName = ""; - std::string valueParameterString = ""; - double valueParameterDouble = 0.0; - auto* action = arguments->FindValue("action"); - if (!action) return; - - for (auto& typeValueMap : action->GetAssociativeMap()) { - if (typeValueMap.first == "Type") { - if (typeValueMap.second->GetValueType() != AMFValueType::AMFString) continue; - type = static_cast(typeValueMap.second)->GetStringValue(); - } 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(); - } else { - if (typeValueMap.second->GetValueType() != AMFValueType::AMFDouble) continue; - valueParameterDouble = static_cast(typeValueMap.second)->GetDoubleValue(); - } - } - } - - uint32_t behaviorID = GetBehaviorIDFromArgument(arguments); - - // modelComponent->AddAction(stateID, stripID, type, valueParameterName, valueParameterString, valueParameterDouble, "", actionIndex, behaviorID); - - // RequestUpdatedID(behaviorID); +void ControlBehaviors::AddAction(AMFArrayValue* arguments) { + AddActionMessage addActionMessage(arguments); } -void MigrateActions(AMFArrayValue* arguments) { - auto* srcActionIndexAmf = arguments->FindValue("srcActionIndex"); - if (!srcActionIndexAmf) return; - - uint32_t srcActionIndex = static_cast(srcActionIndexAmf->GetDoubleValue()); - - STRIPID srcStripID = GetStripIDFromArgument(arguments, "srcStripID"); - - BEHAVIORSTATE srcStateID = GetBehaviorStateFromArgument(arguments, "srcStateID"); - - auto* dstActionIndexAmf = arguments->FindValue("dstActionIndex"); - if (!dstActionIndexAmf) return; - - uint32_t dstActionIndex = static_cast(dstActionIndexAmf->GetDoubleValue()); - - STRIPID dstStripID = GetStripIDFromArgument(arguments, "dstStripID"); - - BEHAVIORSTATE dstStateID = GetBehaviorStateFromArgument(arguments, "dstStateID"); - - uint32_t behaviorID = GetBehaviorIDFromArgument(arguments); - - // modelComponent->MigrateActions(srcActionIndex, srcStripID, srcStateID, dstActionIndex, dstStripID, dstStateID, behaviorID); - - // RequestUpdatedID(behaviorID); +void ControlBehaviors::MigrateActions(AMFArrayValue* arguments) { + MigrateActionsMessage migrateActionsMessage(arguments); } -void RearrangeStrip(AMFArrayValue* arguments) { - auto* srcActionIndexValue = arguments->FindValue("srcActionIndex"); - uint32_t srcActionIndex = static_cast(srcActionIndexValue->GetDoubleValue()); - - uint32_t stripID = GetStripIDFromArgument(arguments); - - uint32_t behaviorID = GetBehaviorIDFromArgument(arguments); - - auto* dstActionIndexValue = arguments->FindValue("dstActionIndex"); - uint32_t dstActionIndex = static_cast(dstActionIndexValue->GetDoubleValue()); - - BEHAVIORSTATE stateID = GetBehaviorStateFromArgument(arguments); - - // modelComponent->RearrangeStrip(stateID, stripID, srcActionIndex, dstActionIndex, behaviorID); - - // RequestUpdatedID(behaviorID); +void ControlBehaviors::RearrangeStrip(AMFArrayValue* arguments) { + RearrangeStripMessage rearrangeStripMessage(arguments); } -void Add(AMFArrayValue* arguments) { - uint32_t behaviorID = GetBehaviorIDFromArgument(arguments); - - uint32_t behaviorIndex = 0; - auto* behaviorIndexAmf = arguments->FindValue("BehaviorIndex"); - - if (!behaviorIndexAmf) return; - - behaviorIndex = static_cast(behaviorIndexAmf->GetDoubleValue()); - - // modelComponent->AddBehavior(behaviorID, behaviorIndex, modelOwner); - - // SendBehaviorListToClient(); +void ControlBehaviors::Add(AMFArrayValue* arguments) { + AddMessage addMessage(arguments); } -void RemoveActions(AMFArrayValue* arguments) { - uint32_t behaviorID = GetBehaviorIDFromArgument(arguments); - - auto* actionIndexAmf = arguments->FindValue("actionIndex"); - if (!actionIndexAmf) return; - - uint32_t actionIndex = static_cast(actionIndexAmf->GetDoubleValue()); - - STRIPID stripID = GetStripIDFromArgument(arguments); - - BEHAVIORSTATE stateID = GetBehaviorStateFromArgument(arguments); - - // modelComponent->RemoveAction(stateID, stripID, actionIndex, behaviorID); - - // RequestUpdatedID(behaviorID); +void ControlBehaviors::RemoveActions(AMFArrayValue* arguments) { + RemoveActionsMessage removeActionsMessage(arguments); } -void Rename(Entity* modelEntity, const SystemAddress& sysAddr, Entity* modelOwner, AMFArrayValue* arguments) { - uint32_t behaviorID = GetBehaviorIDFromArgument(arguments); - - auto* nameAmf = arguments->FindValue("Name"); - if (!nameAmf) return; - - auto name = nameAmf->GetStringValue(); - - // modelComponent->Rename(behaviorID, name); - - SendBehaviorListToClient(modelEntity, sysAddr, modelOwner); - - // RequestUpdatedID(behaviorID); +void ControlBehaviors::Rename(Entity* modelEntity, const SystemAddress& sysAddr, Entity* modelOwner, AMFArrayValue* arguments) { + RenameMessage renameMessage(arguments); } // TODO This is also supposed to serialize the state of the behaviors in progress but those aren't implemented yet -void SendBehaviorBlocksToClient(ModelComponent* modelComponent, const SystemAddress& sysAddr, Entity* modelOwner, AMFArrayValue* arguments) { - uint32_t behaviorID = GetBehaviorIDFromArgument(arguments); +void ControlBehaviors::SendBehaviorBlocksToClient(ModelComponent* modelComponent, const SystemAddress& sysAddr, Entity* modelOwner, AMFArrayValue* arguments) { + // uint32_t behaviorID = ControlBehaviors::GetBehaviorIDFromArgument(arguments); // auto modelBehavior = modelComponent->FindBehavior(behaviorID); @@ -496,47 +246,26 @@ void SendBehaviorBlocksToClient(ModelComponent* modelComponent, const SystemAddr // GameMessages::SendUIMessageServerToSingleClient(modelOwner, sysAddr, "UpdateBehaviorBlocks", &behaviorInfo); } -void UpdateAction(AMFArrayValue* arguments) { - std::string type = ""; - std::string valueParameterName = ""; - std::string valueParameterString = ""; - double valueParameterDouble = 0.0; - auto* actionAsArray = arguments->FindValue("action"); - if (!actionAsArray) return; - for (auto& typeValueMap : actionAsArray->GetAssociativeMap()) { - if (typeValueMap.first == "Type") { - if (typeValueMap.second->GetValueType() != AMFValueType::AMFString) continue; - type = static_cast(typeValueMap.second)->GetStringValue(); - } 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(); - } else { - if (typeValueMap.second->GetValueType() != AMFValueType::AMFDouble) continue; - valueParameterDouble = static_cast(typeValueMap.second)->GetDoubleValue(); - } +void ControlBehaviors::UpdateAction(AMFArrayValue* arguments) { + UpdateActionMessage updateActionMessage(arguments); + auto* blockDefinition = GetBlockInfo(updateActionMessage.GetType()); + + if (updateActionMessage.GetValueParameterString().size() > 0) { + if (updateActionMessage.GetValueParameterString().size() < blockDefinition->GetMinimumValue() || + updateActionMessage.GetValueParameterString().size() > blockDefinition->GetMaximumValue()) { + Game::logger->Log("ControlBehaviors", "Updated block %s is out of range. Ignoring update", updateActionMessage.GetType().c_str()); + return; + } + } else { + if (updateActionMessage.GetValueParameterDouble() < blockDefinition->GetMinimumValue() || + updateActionMessage.GetValueParameterDouble() > blockDefinition->GetMaximumValue()) { + Game::logger->Log("ControlBehaviors", "Updated block %s is out of range. Ignoring update", updateActionMessage.GetType().c_str()); + return; } } - - uint32_t behaviorID = GetBehaviorIDFromArgument(arguments); - - auto* actionIndexValue = arguments->FindValue("actionIndex"); - if (!actionIndexValue) return; - - uint32_t actionIndex = static_cast(actionIndexValue->GetDoubleValue()); - - STRIPID stripID = GetStripIDFromArgument(arguments); - - BEHAVIORSTATE stateID = GetBehaviorStateFromArgument(arguments); - - // modelComponent->UpdateAction(stateID, stripID, type, valueParameterName, valueParameterString, valueParameterDouble, "", actionIndex, behaviorID); - - // RequestUpdatedID(behaviorID); } -void MoveToInventory(ModelComponent* modelComponent, const SystemAddress& sysAddr, Entity* modelOwner, AMFArrayValue* arguments) { +void ControlBehaviors::MoveToInventory(ModelComponent* modelComponent, const SystemAddress& sysAddr, Entity* modelOwner, AMFArrayValue* arguments) { // This closes the UI menu should it be open while the player is removing behaviors AMFArrayValue args; @@ -545,20 +274,13 @@ void MoveToInventory(ModelComponent* modelComponent, const SystemAddress& sysAdd GameMessages::SendUIMessageServerToSingleClient(modelOwner, modelOwner->GetParentUser()->GetSystemAddress(), "ToggleBehaviorEditor", &args); - uint32_t behaviorID = GetBehaviorIDFromArgument(arguments); - - auto* behaviorIndexValue = arguments->FindValue("BehaviorIndex"); - if (!behaviorIndexValue) return; - - uint32_t behaviorIndex = static_cast(behaviorIndexValue->GetDoubleValue()); - - // modelComponent->MoveBehaviorToInventory(behaviorID, behaviorIndex, modelOwner); + MoveToInventoryMessage moveToInventoryMessage(arguments); SendBehaviorListToClient(modelComponent->GetParent(), sysAddr, modelOwner); } void ControlBehaviors::ProcessCommand(Entity* modelEntity, const SystemAddress& sysAddr, AMFArrayValue* arguments, std::string command, Entity* modelOwner) { - if (!modelEntity || !modelOwner || !arguments) return; + if (!isInitialized || !modelEntity || !modelOwner || !arguments) return; auto* modelComponent = modelEntity->GetComponent(); if (!modelComponent) return; @@ -600,3 +322,135 @@ void ControlBehaviors::ProcessCommand(Entity* modelEntity, const SystemAddress& else Game::logger->Log("ControlBehaviors", "Unknown behavior command (%s)\n", command.c_str()); } + +ControlBehaviors::ControlBehaviors() { + auto blocksDefStreamBuffer = Game::assetManager->GetFileAsBuffer("ui\\ingame\\blocksdef.xml"); + if (!blocksDefStreamBuffer.m_Success) { + Game::logger->Log("ControlBehaviors", "failed to open blocksdef"); + return; + } + std::istream blocksBuffer(&blocksDefStreamBuffer); + if (!blocksBuffer.good()) { + Game::logger->Log("ControlBehaviors", "Blocks buffer is not good!"); + return; + } + + tinyxml2::XMLDocument m_Doc; + + std::string read{}; + + std::string buffer{}; + bool commentBlockStart = false; + while (std::getline(blocksBuffer, read)) { + // tinyxml2 should handle comment blocks but the client has one that fails the processing. + // This preprocessing just removes all comments from the read file out of an abundance of caution. + if (read.find("") != std::string::npos) { + commentBlockStart = false; + continue; + } + if (!commentBlockStart) buffer += read; + } + + auto ret = m_Doc.Parse(buffer.c_str()); + if (ret == tinyxml2::XML_SUCCESS) { + Game::logger->LogDebug("ControlBehaviors", "Successfully parsed the blocksdef file!"); + } else { + Game::logger->Log("Character", "Failed to parse BlocksDef xmlData due to error %i!", ret); + return; + } + auto* blockLibrary = m_Doc.FirstChildElement(); + if (!blockLibrary) { + Game::logger->Log("ControlBehaviors", "No Block Library child element found."); + return; + } + + // Now parse the blocksdef for the cheat detection server side. + // The client does these checks, but a bad actor can bypass the client checks + auto* blockSections = blockLibrary->FirstChildElement(); + while (blockSections) { + auto* block = blockSections->FirstChildElement(); + std::string blockName{}; + while (block) { + blockName = block->Name(); + + BlockDefinition* blockDefinition = new BlockDefinition(); + std::string name{}; + std::string typeName{}; + + auto* argument = block->FirstChildElement("Argument"); + if (argument) { + auto* defaultDefinition = argument->FirstChildElement("DefaultValue"); + if (defaultDefinition) blockDefinition->SetDefaultValue(defaultDefinition->GetText()); + + auto* typeDefinition = argument->FirstChildElement("Type"); + if (typeDefinition) typeName = typeDefinition->GetText(); + + auto* nameDefinition = argument->FirstChildElement("Name"); + if (nameDefinition) name = nameDefinition->GetText(); + + // Now we parse the blocksdef file for the relevant information + if (typeName == "String") { + blockDefinition->SetMaximumValue(50); // The client has a hardcoded limit of 50 characters in a string field + } else if (typeName == "Float" || typeName == "Integer") { + auto* maximumDefinition = argument->FirstChildElement("Maximum"); + if (maximumDefinition) blockDefinition->SetMaximumValue(std::stof(maximumDefinition->GetText())); + + auto* minimumDefinition = argument->FirstChildElement("Minimum"); + if (minimumDefinition) blockDefinition->SetMinimumValue(std::stof(minimumDefinition->GetText())); + } else if (typeName == "Enumeration") { + auto* values = argument->FirstChildElement("Values"); + if (values) { + auto* value = values->FirstChildElement("Value"); + while (value) { + if (value->GetText() == blockDefinition->GetDefaultValue()) blockDefinition->GetDefaultValue() = std::to_string(blockDefinition->GetMaximumValue()); + blockDefinition->SetMaximumValue(blockDefinition->GetMaximumValue() + 1); + value = value->NextSiblingElement("Value"); + } + blockDefinition->SetMaximumValue(blockDefinition->GetMaximumValue() - 1); // Maximum value is 0 indexed + } else { + values = argument->FirstChildElement("EnumerationSource"); + if (!values) { + Game::logger->Log("ControlBehaviors", "Failed to parse EnumerationSource from block (%s)", blockName.c_str()); + continue; + } + + auto* serviceNameNode = values->FirstChildElement("ServiceName"); + if (!serviceNameNode) { + Game::logger->Log("ControlBehaviors", "Failed to parse ServiceName from block (%s)", blockName.c_str()); + continue; + } + + std::string serviceName = serviceNameNode->GetText(); + if (serviceName == "GetBehaviorSoundList") { + auto res = CDClientDatabase::ExecuteQuery("SELECT MAX(id) as countSounds FROM UGBehaviorSounds;"); + blockDefinition->SetMaximumValue(res.getIntField("countSounds")); + blockDefinition->SetDefaultValue("0"); + } else { + Game::logger->Log("ControlBehaviors", "Unsupported Enumeration ServiceType (%s)", serviceName.c_str()); + continue; + } + } + } else { + Game::logger->Log("ControlBehaviors", "Unsupported block value type (%s)!", typeName.c_str()); + continue; + } + } + blockTypes.insert(std::make_pair(blockName, blockDefinition)); + block = block->NextSiblingElement(); + } + blockSections = blockSections->NextSiblingElement(); + } + isInitialized = true; + Game::logger->LogDebug("ControlBehaviors", "Created all base block classes"); + for (auto b : blockTypes) { + Game::logger->LogDebug("ControlBehaviors", "block name is %s default %s min %f max %f", b.first.c_str(), b.second->GetDefaultValue().c_str(), b.second->GetMinimumValue(), b.second->GetMaximumValue()); + } +} + +BlockDefinition* ControlBehaviors::GetBlockInfo(const BlockName& blockName) { + auto blockDefinition = blockTypes.find(blockName); + return blockDefinition != blockTypes.end() ? blockDefinition->second : &BlockDefinition::blockDefinitionDefault; +} diff --git a/dGame/dPropertyBehaviors/ControlBehaviors.h b/dGame/dPropertyBehaviors/ControlBehaviors.h index d487f929..a562aafe 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviors.h +++ b/dGame/dPropertyBehaviors/ControlBehaviors.h @@ -3,15 +3,23 @@ #ifndef __CONTROLBEHAVIORS__H__ #define __CONTROLBEHAVIORS__H__ +#include #include -#include "RakNetTypes.h" +#include "Singleton.h" -class Entity; class AMFArrayValue; +class BlockDefinition; +class Entity; class ModelComponent; +class SystemAddress; -namespace ControlBehaviors { +// Type definition to clarify what is used where +typedef std::string BlockName; //! A block name + +class ControlBehaviors: public Singleton { +public: + ControlBehaviors(); /** * @brief Main driver for processing Property Behavior commands * @@ -22,6 +30,39 @@ namespace ControlBehaviors { * @param modelOwner The owner of the model which sent this command */ void ProcessCommand(Entity* modelEntity, const SystemAddress& sysAddr, AMFArrayValue* arguments, std::string command, Entity* modelOwner); + + /** + * @brief Gets a blocks parameter values by the name + * No exception will be thrown in this function. + * + * @param blockName The block name to get the parameters of + * + * @return A pair of the block parameter name to its typing + */ + BlockDefinition* GetBlockInfo(const BlockName& blockName); +private: + void RequestUpdatedID(int32_t behaviorID, ModelComponent* modelComponent, Entity* modelOwner, const SystemAddress& sysAddr); + void SendBehaviorListToClient(Entity* modelEntity, const SystemAddress& sysAddr, Entity* modelOwner); + void ModelTypeChanged(AMFArrayValue* arguments, ModelComponent* ModelComponent); + void ToggleExecutionUpdates(); + void AddStrip(AMFArrayValue* arguments); + void RemoveStrip(AMFArrayValue* arguments); + void MergeStrips(AMFArrayValue* arguments); + void SplitStrip(AMFArrayValue* arguments); + void UpdateStripUI(AMFArrayValue* arguments); + void AddAction(AMFArrayValue* arguments); + void MigrateActions(AMFArrayValue* arguments); + void RearrangeStrip(AMFArrayValue* arguments); + void Add(AMFArrayValue* arguments); + void RemoveActions(AMFArrayValue* arguments); + void Rename(Entity* modelEntity, const SystemAddress& sysAddr, Entity* modelOwner, AMFArrayValue* arguments); + void SendBehaviorBlocksToClient(ModelComponent* modelComponent, const SystemAddress& sysAddr, Entity* modelOwner, AMFArrayValue* arguments); + void UpdateAction(AMFArrayValue* arguments); + void MoveToInventory(ModelComponent* modelComponent, const SystemAddress& sysAddr, Entity* modelOwner, AMFArrayValue* arguments); + std::map blockTypes{}; + + // If false, property behaviors will not be able to be edited. + bool isInitialized = false; }; #endif //!__CONTROLBEHAVIORS__H__ diff --git a/tests/dGameTests/CMakeLists.txt b/tests/dGameTests/CMakeLists.txt index ba7d4d1c..b1fdaa07 100644 --- a/tests/dGameTests/CMakeLists.txt +++ b/tests/dGameTests/CMakeLists.txt @@ -8,6 +8,8 @@ list(APPEND DGAMETEST_SOURCES ${DCOMPONENTS_TESTS}) add_subdirectory(dGameMessagesTests) list(APPEND DGAMETEST_SOURCES ${DGAMEMESSAGES_TESTS}) +file(COPY ${GAMEMESSAGE_TESTBITSTREAMS} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + # Add the executable. Remember to add all tests above this! add_executable(dGameTests ${DGAMETEST_SOURCES}) diff --git a/tests/dGameTests/dGameMessagesTests/CMakeLists.txt b/tests/dGameTests/dGameMessagesTests/CMakeLists.txt index 2417d29c..54c43777 100644 --- a/tests/dGameTests/dGameMessagesTests/CMakeLists.txt +++ b/tests/dGameTests/dGameMessagesTests/CMakeLists.txt @@ -5,5 +5,10 @@ SET(DGAMEMESSAGES_TESTS get_filename_component(thisFolderName ${CMAKE_CURRENT_SOURCE_DIR} NAME) list(TRANSFORM DGAMEMESSAGES_TESTS PREPEND "${thisFolderName}/") +# Copy test files to testing directory +add_subdirectory(TestBitStreams) +list(TRANSFORM GAMEMESSAGE_TESTBITSTREAMS PREPEND "${thisFolderName}/") +set(GAMEMESSAGE_TESTBITSTREAMS ${GAMEMESSAGE_TESTBITSTREAMS} PARENT_SCOPE) + # Export to parent scope set(DGAMEMESSAGES_TESTS ${DGAMEMESSAGES_TESTS} PARENT_SCOPE) diff --git a/tests/dGameTests/dGameMessagesTests/GameMessageTests.cpp b/tests/dGameTests/dGameMessagesTests/GameMessageTests.cpp index 3d8b2d04..7905c19a 100644 --- a/tests/dGameTests/dGameMessagesTests/GameMessageTests.cpp +++ b/tests/dGameTests/dGameMessagesTests/GameMessageTests.cpp @@ -1,15 +1,50 @@ #include "GameMessages.h" #include "GameDependencies.h" -#include +#include "AMFDeserialize.h" -class GameMessageTests : public GameDependenciesTest { - protected: - void SetUp() override { - SetUpDependencies(); - } - void TearDown() override { - TearDownDependencies(); +#include "AddActionMessage.h" +#include "AddStripMessage.h" +#include "AddMessage.h" +#include "MigrateActionsMessage.h" +#include "MoveToInventoryMessage.h" +#include "MergeStripsMessage.h" +#include "RearrangeStripMessage.h" +#include "RemoveActionsMessage.h" +#include "RemoveStripMessage.h" +#include "RenameMessage.h" +#include "SplitStripMessage.h" +#include "UpdateActionMessage.h" +#include "UpdateStripUiMessage.h" + +#include +#include + +class GameMessageTests: public GameDependenciesTest { +protected: + void SetUp() override { + SetUpDependencies(); + } + void TearDown() override { + TearDownDependencies(); + } + + std::string ReadFromFile(std::string filename) { + std::ifstream file(filename, std::ios::binary); + std::string readFile; + while (file.good()) { + char readCharacter = file.get(); + readFile.push_back(readCharacter); } + + return readFile; + } + + AMFArrayValue* ReadArrayFromBitStream(RakNet::BitStream* inStream) { + AMFDeserialize des; + AMFValue* readArray = des.Read(inStream); + EXPECT_EQ(readArray->GetValueType(), AMFValueType::AMFArray); + return static_cast(readArray); + } }; /** @@ -50,3 +85,143 @@ TEST_F(GameMessageTests, SendBlueprintLoadItemResponse) { ASSERT_EQ(bitStream->GetNumberOfUnreadBits(), 0); } + +TEST_F(GameMessageTests, ControlBehaviorAddStrip) { + auto data = ReadFromFile("addStrip"); + RakNet::BitStream inStream((unsigned char*)data.c_str(), data.length(), true); + AddStripMessage addStrip(ReadArrayFromBitStream(&inStream)); + ASSERT_FLOAT_EQ(addStrip.GetXPosition(), 50.65); + ASSERT_FLOAT_EQ(addStrip.GetYPosition(), 178.05); + ASSERT_EQ(addStrip.GetStripId(), 0); + ASSERT_EQ(static_cast(addStrip.GetStateId()), 0); + ASSERT_EQ(addStrip.GetBehaviorId(), -1); + ASSERT_EQ(addStrip.GetType(), "DropImagination"); + ASSERT_EQ(addStrip.GetValueParameterName(), "Amount"); + ASSERT_EQ(addStrip.GetValueParameterString(), ""); + ASSERT_FLOAT_EQ(addStrip.GetValueParameterDouble(), 1.0); +} + +TEST_F(GameMessageTests, ControlBehaviorRemoveStrip) { + auto data = ReadFromFile("removeStrip"); + RakNet::BitStream inStream((unsigned char*)data.c_str(), data.length(), true); + RemoveStripMessage removeStrip(ReadArrayFromBitStream(&inStream)); + ASSERT_EQ(static_cast(removeStrip.GetStripId()), 1); + ASSERT_EQ(static_cast(removeStrip.GetBehaviorState()), 0); + ASSERT_EQ(removeStrip.GetBehaviorId(), -1); +} + +TEST_F(GameMessageTests, ControlBehaviorMergeStrips) { + auto data = ReadFromFile("mergeStrips"); + RakNet::BitStream inStream((unsigned char*)data.c_str(), data.length(), true); + MergeStripsMessage mergeStrips(ReadArrayFromBitStream(&inStream)); + ASSERT_EQ(mergeStrips.GetSrcStripID(), 2); + ASSERT_EQ(mergeStrips.GetDstStripID(), 0); + ASSERT_EQ(static_cast(mergeStrips.GetSrcStateID()), 0); + ASSERT_EQ(static_cast(mergeStrips.GetDstStateID()), 0); + ASSERT_EQ(mergeStrips.GetDstActionIndex(), 0); + ASSERT_EQ(mergeStrips.GetBehaviorID(), -1); +} + +TEST_F(GameMessageTests, ControlBehaviorSplitStrip) { + auto data = ReadFromFile("splitStrip"); + RakNet::BitStream inStream((unsigned char*)data.c_str(), data.length(), true); + SplitStripMessage splitStrip(ReadArrayFromBitStream(&inStream)); + ASSERT_EQ(splitStrip.GetBehaviorId(), -1); + + ASSERT_FLOAT_EQ(splitStrip.GetXPosition(), 275.65); + ASSERT_FLOAT_EQ(splitStrip.GetYPosition(), 28.7); + ASSERT_EQ(splitStrip.GetSrcStripId(), 0); + ASSERT_EQ(splitStrip.GetDstStripId(), 2); + ASSERT_EQ(static_cast(splitStrip.GetSrcStateId()), 0); + ASSERT_EQ(static_cast(splitStrip.GetDstStateId()), 0); + ASSERT_EQ(splitStrip.GetSrcActionIndex(), 1); +} + +TEST_F(GameMessageTests, ControlBehaviorUpdateStripUI) { + auto data = ReadFromFile("updateStripUI"); + RakNet::BitStream inStream((unsigned char*)data.c_str(), data.length(), true); + UpdateStripUiMessage updateStripUi(ReadArrayFromBitStream(&inStream)); + ASSERT_FLOAT_EQ(updateStripUi.GetXPosition(), 116.65); + ASSERT_FLOAT_EQ(updateStripUi.GetYPosition(), 35.35); + ASSERT_EQ(updateStripUi.GetStripID(), 0); + ASSERT_EQ(static_cast(updateStripUi.GetStateID()), 0); + ASSERT_EQ(updateStripUi.GetBehaviorID(), -1); +} + +TEST_F(GameMessageTests, ControlBehaviorAddAction) { + auto data = ReadFromFile("addAction"); + RakNet::BitStream inStream((unsigned char*)data.c_str(), data.length(), true); + AddActionMessage addAction(ReadArrayFromBitStream(&inStream)); + ASSERT_EQ(addAction.GetActionIndex(), 3); + ASSERT_EQ(addAction.GetStripId(), 0); + ASSERT_EQ(static_cast(addAction.GetStateId()), 0); + ASSERT_EQ(addAction.GetType(), "DoDamage"); + ASSERT_EQ(addAction.GetValueParameterName(), ""); + ASSERT_EQ(addAction.GetValueParameterString(), ""); + ASSERT_EQ(addAction.GetValueParameterDouble(), 0.0); + ASSERT_EQ(addAction.GetBehaviorId(), -1); +} + +TEST_F(GameMessageTests, ControlBehaviorMigrateActions) { + auto data = ReadFromFile("migrateActions"); + RakNet::BitStream inStream((unsigned char*)data.c_str(), data.length(), true); + MigrateActionsMessage migrateActions(ReadArrayFromBitStream(&inStream)); + ASSERT_EQ(migrateActions.GetSrcActionIndex(), 1); + ASSERT_EQ(migrateActions.GetDstActionIndex(), 2); + ASSERT_EQ(migrateActions.GetSrcStripID(), 1); + ASSERT_EQ(migrateActions.GetDstStripID(), 0); + ASSERT_EQ(static_cast(migrateActions.GetSrcStateID()), 0); + ASSERT_EQ(static_cast(migrateActions.GetDstStateID()), 0); + ASSERT_EQ(migrateActions.GetBehaviorID(), -1); +} + +TEST_F(GameMessageTests, ControlBehaviorRearrangeStrip) { + auto data = ReadFromFile("rearrangeStrip"); + RakNet::BitStream inStream((unsigned char*)data.c_str(), data.length(), true); + RearrangeStripMessage rearrangeStrip(ReadArrayFromBitStream(&inStream)); + ASSERT_EQ(rearrangeStrip.GetSrcActionIndex(), 2); + ASSERT_EQ(rearrangeStrip.GetDstActionIndex(), 1); + ASSERT_EQ(rearrangeStrip.GetStripID(), 0); + ASSERT_EQ(rearrangeStrip.GetBehaviorID(), -1); + ASSERT_EQ(static_cast(rearrangeStrip.GetStateID()), 0); +} + +TEST_F(GameMessageTests, ControlBehaviorAdd) { + auto data = ReadFromFile("add"); + RakNet::BitStream inStream((unsigned char*)data.c_str(), data.length(), true); + AddMessage add(ReadArrayFromBitStream(&inStream)); + ASSERT_EQ(add.GetBehaviorId(), 10446); + ASSERT_EQ(add.GetBehaviorIndex(), 0); +} + +TEST_F(GameMessageTests, ControlBehaviorRemoveActions) { + auto data = ReadFromFile("removeActions"); + RakNet::BitStream inStream((unsigned char*)data.c_str(), data.length(), true); + RemoveActionsMessage removeActions(ReadArrayFromBitStream(&inStream)); + ASSERT_EQ(removeActions.GetBehaviorID(), -1); + ASSERT_EQ(removeActions.GetActionIndex(), 1); + ASSERT_EQ(removeActions.GetStripID(), 0); + ASSERT_EQ(static_cast(removeActions.GetStateID()), 0); +} + +TEST_F(GameMessageTests, ControlBehaviorRename) { + auto data = ReadFromFile("rename"); + RakNet::BitStream inStream((unsigned char*)data.c_str(), data.length(), true); + RenameMessage rename(ReadArrayFromBitStream(&inStream)); + ASSERT_EQ(rename.GetName(), "test"); + ASSERT_EQ(rename.GetBehaviorID(), -1); +} + +TEST_F(GameMessageTests, ControlBehaviorUpdateAction) { + auto data = ReadFromFile("updateAction"); + RakNet::BitStream inStream((unsigned char*)data.c_str(), data.length(), true); + UpdateActionMessage updateAction(ReadArrayFromBitStream(&inStream)); + ASSERT_EQ(updateAction.GetType(), "FlyDown"); + ASSERT_EQ(updateAction.GetValueParameterName(), "Distance"); + ASSERT_EQ(updateAction.GetValueParameterString(), ""); + ASSERT_EQ(updateAction.GetValueParameterDouble(), 50.0); + ASSERT_EQ(updateAction.GetBehaviorID(), -1); + ASSERT_EQ(updateAction.GetActionIndex(), 1); + ASSERT_EQ(updateAction.GetStripID(), 0); + ASSERT_EQ(static_cast(updateAction.GetStateID()), 0); +} diff --git a/tests/dGameTests/dGameMessagesTests/TestBitStreams/CMakeLists.txt b/tests/dGameTests/dGameMessagesTests/TestBitStreams/CMakeLists.txt new file mode 100644 index 00000000..e32ed3ef --- /dev/null +++ b/tests/dGameTests/dGameMessagesTests/TestBitStreams/CMakeLists.txt @@ -0,0 +1,24 @@ +set(GAMEMESSAGE_TESTBITSTREAMS +"sendBehaviorListToClient" +"modelTypeChanged" +"toggleExecutionUpdates" +"addStrip" +"removeStrip" +"mergeStrips" +"splitStrip" +"updateStripUI" +"addAction" +"migrateActions" +"rearrangeStrip" +"add" +"removeActions" +"rename" +"updateAction" +) + +# Get the folder name and prepend it to the files above +get_filename_component(thisFolderName ${CMAKE_CURRENT_SOURCE_DIR} NAME) +list(TRANSFORM GAMEMESSAGE_TESTBITSTREAMS PREPEND "${thisFolderName}/") + +# Export our list of files +set(GAMEMESSAGE_TESTBITSTREAMS ${GAMEMESSAGE_TESTBITSTREAMS} PARENT_SCOPE) diff --git a/tests/dGameTests/dGameMessagesTests/TestBitStreams/add b/tests/dGameTests/dGameMessagesTests/TestBitStreams/add new file mode 100644 index 00000000..13c0dd92 Binary files /dev/null and b/tests/dGameTests/dGameMessagesTests/TestBitStreams/add differ diff --git a/tests/dGameTests/dGameMessagesTests/TestBitStreams/addAction b/tests/dGameTests/dGameMessagesTests/TestBitStreams/addAction new file mode 100644 index 00000000..d91d0ee4 Binary files /dev/null and b/tests/dGameTests/dGameMessagesTests/TestBitStreams/addAction differ diff --git a/tests/dGameTests/dGameMessagesTests/TestBitStreams/addStrip b/tests/dGameTests/dGameMessagesTests/TestBitStreams/addStrip new file mode 100644 index 00000000..60ba6521 Binary files /dev/null and b/tests/dGameTests/dGameMessagesTests/TestBitStreams/addStrip differ diff --git a/tests/dGameTests/dGameMessagesTests/TestBitStreams/mergeStrips b/tests/dGameTests/dGameMessagesTests/TestBitStreams/mergeStrips new file mode 100644 index 00000000..062fd10b Binary files /dev/null and b/tests/dGameTests/dGameMessagesTests/TestBitStreams/mergeStrips differ diff --git a/tests/dGameTests/dGameMessagesTests/TestBitStreams/migrateActions b/tests/dGameTests/dGameMessagesTests/TestBitStreams/migrateActions new file mode 100644 index 00000000..217f44d9 Binary files /dev/null and b/tests/dGameTests/dGameMessagesTests/TestBitStreams/migrateActions differ diff --git a/tests/dGameTests/dGameMessagesTests/TestBitStreams/modelTypeChanged b/tests/dGameTests/dGameMessagesTests/TestBitStreams/modelTypeChanged new file mode 100644 index 00000000..ef282ce2 Binary files /dev/null and b/tests/dGameTests/dGameMessagesTests/TestBitStreams/modelTypeChanged differ diff --git a/tests/dGameTests/dGameMessagesTests/TestBitStreams/rearrangeStrip b/tests/dGameTests/dGameMessagesTests/TestBitStreams/rearrangeStrip new file mode 100644 index 00000000..06dda90b Binary files /dev/null and b/tests/dGameTests/dGameMessagesTests/TestBitStreams/rearrangeStrip differ diff --git a/tests/dGameTests/dGameMessagesTests/TestBitStreams/removeActions b/tests/dGameTests/dGameMessagesTests/TestBitStreams/removeActions new file mode 100644 index 00000000..56e158e5 Binary files /dev/null and b/tests/dGameTests/dGameMessagesTests/TestBitStreams/removeActions differ diff --git a/tests/dGameTests/dGameMessagesTests/TestBitStreams/removeStrip b/tests/dGameTests/dGameMessagesTests/TestBitStreams/removeStrip new file mode 100644 index 00000000..46ca0640 Binary files /dev/null and b/tests/dGameTests/dGameMessagesTests/TestBitStreams/removeStrip differ diff --git a/tests/dGameTests/dGameMessagesTests/TestBitStreams/rename b/tests/dGameTests/dGameMessagesTests/TestBitStreams/rename new file mode 100644 index 00000000..bc8827dc Binary files /dev/null and b/tests/dGameTests/dGameMessagesTests/TestBitStreams/rename differ diff --git a/tests/dGameTests/dGameMessagesTests/TestBitStreams/sendBehaviorListToClient b/tests/dGameTests/dGameMessagesTests/TestBitStreams/sendBehaviorListToClient new file mode 100644 index 00000000..fcca696d Binary files /dev/null and b/tests/dGameTests/dGameMessagesTests/TestBitStreams/sendBehaviorListToClient differ diff --git a/tests/dGameTests/dGameMessagesTests/TestBitStreams/splitStrip b/tests/dGameTests/dGameMessagesTests/TestBitStreams/splitStrip new file mode 100644 index 00000000..a23c1682 Binary files /dev/null and b/tests/dGameTests/dGameMessagesTests/TestBitStreams/splitStrip differ diff --git a/tests/dGameTests/dGameMessagesTests/TestBitStreams/toggleExecutionUpdates b/tests/dGameTests/dGameMessagesTests/TestBitStreams/toggleExecutionUpdates new file mode 100644 index 00000000..02a72181 Binary files /dev/null and b/tests/dGameTests/dGameMessagesTests/TestBitStreams/toggleExecutionUpdates differ diff --git a/tests/dGameTests/dGameMessagesTests/TestBitStreams/updateAction b/tests/dGameTests/dGameMessagesTests/TestBitStreams/updateAction new file mode 100644 index 00000000..e007d5e6 Binary files /dev/null and b/tests/dGameTests/dGameMessagesTests/TestBitStreams/updateAction differ diff --git a/tests/dGameTests/dGameMessagesTests/TestBitStreams/updateStripUI b/tests/dGameTests/dGameMessagesTests/TestBitStreams/updateStripUI new file mode 100644 index 00000000..7d0eed92 Binary files /dev/null and b/tests/dGameTests/dGameMessagesTests/TestBitStreams/updateStripUI differ