Further implement Property Behavior parsing (#936)

Further implements the ControlBehavior processing and adds preparations for cheat detection
This commit is contained in:
David Markowitz 2023-02-13 18:55:44 -08:00 committed by GitHub
parent 3cd0d1ec3d
commit 72c93c8913
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 1181 additions and 362 deletions

View File

@ -163,6 +163,7 @@ set(INCLUDED_DIRECTORIES
"dGame/dMission"
"dGame/dEntity"
"dGame/dPropertyBehaviors"
"dGame/dPropertyBehaviors/ControlBehaviorMessages"
"dGame/dUtilities"
"dPhysics"
"dNavigation"

View File

@ -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

View File

@ -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<AMFArrayValue*>(amfArguments.get()), command, owner);
ControlBehaviors::Instance().ProcessCommand(entity, sysAddr, static_cast<AMFArrayValue*>(amfArguments.get()), command, owner);
}
void GameMessages::HandleBBBSaveRequest(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) {

View File

@ -3,12 +3,9 @@
#ifndef __BEHAVIORSTATES__H__
#define __BEHAVIORSTATES__H__
#include <string>
#include <cstdint>
#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

View File

@ -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;
}

View File

@ -0,0 +1,25 @@
#ifndef __BLOCKDEFINITION__H__
#define __BLOCKDEFINITION__H__
#include <string>
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__

View File

@ -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)

View File

@ -0,0 +1,39 @@
#include "AddActionMessage.h"
AddActionMessage::AddActionMessage(AMFArrayValue* arguments) {
auto* actionIndexAmf = arguments->FindValue<AMFDoubleValue>("actionIndex");
if (!actionIndexAmf) return;
actionIndex = static_cast<uint32_t>(actionIndexAmf->GetDoubleValue());
stripId = GetStripIDFromArgument(arguments);
stateId = GetBehaviorStateFromArgument(arguments);
type = "";
valueParameterName = "";
valueParameterString = "";
valueParameterDouble = 0.0;
auto* action = arguments->FindValue<AMFArrayValue>("action");
if (!action) return;
for (auto& typeValueMap : action->GetAssociativeMap()) {
if (typeValueMap.first == "Type") {
if (typeValueMap.second->GetValueType() != AMFValueType::AMFString) continue;
type = static_cast<AMFStringValue*>(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<AMFStringValue*>(typeValueMap.second)->GetStringValue();
} else {
if (typeValueMap.second->GetValueType() != AMFValueType::AMFDouble) continue;
valueParameterDouble = static_cast<AMFDoubleValue*>(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);
}

View File

@ -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__

View File

@ -0,0 +1,13 @@
#include "AddMessage.h"
AddMessage::AddMessage(AMFArrayValue* arguments) {
behaviorId = GetBehaviorIDFromArgument(arguments);
behaviorIndex = 0;
auto* behaviorIndexValue = arguments->FindValue<AMFDoubleValue>("BehaviorIndex");
if (!behaviorIndexValue) return;
behaviorIndex = static_cast<uint32_t>(behaviorIndexValue->GetDoubleValue());
Game::logger->LogDebug("AddMessage", "bhId %i ndx %i", behaviorId, behaviorIndex);
}

View File

@ -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__

View File

@ -0,0 +1,56 @@
#include "AddStripMessage.h"
AddStripMessage::AddStripMessage(AMFArrayValue* arguments) {
auto* strip = arguments->FindValue<AMFArrayValue>("strip");
if (!strip) return;
auto* actions = strip->FindValue<AMFArrayValue>("actions");
if (!actions) return;
auto* uiArray = arguments->FindValue<AMFArrayValue>("ui");
if (!uiArray) return;
auto* xPositionValue = uiArray->FindValue<AMFDoubleValue>("x");
if (!xPositionValue) return;
xPosition = xPositionValue->GetDoubleValue();
auto* yPositionValue = uiArray->FindValue<AMFDoubleValue>("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<AMFArrayValue>(position);
if (!actionAsArray) continue;
for (auto& typeValueMap : actionAsArray->GetAssociativeMap()) {
if (typeValueMap.first == "Type") {
if (typeValueMap.second->GetValueType() != AMFValueType::AMFString) continue;
type = static_cast<AMFStringValue*>(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<AMFStringValue*>(typeValueMap.second)->GetStringValue();
} else {
if (typeValueMap.second->GetValueType() != AMFValueType::AMFDouble) continue;
valueParameterDouble = static_cast<AMFDoubleValue*>(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);
}
}

View File

@ -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__

View File

@ -0,0 +1,48 @@
#ifndef __BEHAVIORMESSAGEBASE__H__
#define __BEHAVIORMESSAGEBASE__H__
#include <stdexcept>
#include <string>
#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<AMFStringValue>(key);
uint32_t behaviorID = -1;
if (behaviorIDValue) {
behaviorID = std::stoul(behaviorIDValue->GetStringValue());
} else if (arguments->FindValue<AMFUndefinedValue>(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<AMFDoubleValue>(key);
if (!stateIDValue) throw std::invalid_argument("Unable to find behavior state from argument \"" + key + "\"");
BehaviorState stateID = static_cast<BehaviorState>(stateIDValue->GetDoubleValue());
return stateID;
}
StripId GetStripIDFromArgument(AMFArrayValue* arguments, const std::string& key = "stripID") {
auto* stripIDValue = arguments->FindValue<AMFDoubleValue>(key);
if (!stripIDValue) throw std::invalid_argument("Unable to find strip ID from argument \"" + key + "\"");
StripId stripID = static_cast<StripId>(stripIDValue->GetDoubleValue());
return stripID;
}
};
#endif //!__BEHAVIORMESSAGEBASE__H__

View File

@ -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
)

View File

@ -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<AMFDoubleValue>("dstActionIndex");
if (!dstActionIndexValue) return;
dstActionIndex = static_cast<uint32_t>(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);
}

View File

@ -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__

View File

@ -0,0 +1,24 @@
#include "MigrateActionsMessage.h"
MigrateActionsMessage::MigrateActionsMessage(AMFArrayValue* arguments) {
auto* srcActionIndexAmf = arguments->FindValue<AMFDoubleValue>("srcActionIndex");
if (!srcActionIndexAmf) return;
srcActionIndex = static_cast<uint32_t>(srcActionIndexAmf->GetDoubleValue());
srcStripID = GetStripIDFromArgument(arguments, "srcStripID");
srcStateID = GetBehaviorStateFromArgument(arguments, "srcStateID");
auto* dstActionIndexAmf = arguments->FindValue<AMFDoubleValue>("dstActionIndex");
if (!dstActionIndexAmf) return;
dstActionIndex = static_cast<uint32_t>(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);
}

View File

@ -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__

View File

@ -0,0 +1,11 @@
#include "MoveToInventoryMessage.h"
MoveToInventoryMessage::MoveToInventoryMessage(AMFArrayValue* arguments) {
behaviorID = GetBehaviorIDFromArgument(arguments);
auto* behaviorIndexValue = arguments->FindValue<AMFDoubleValue>("BehaviorIndex");
if (!behaviorIndexValue) return;
behaviorIndex = static_cast<uint32_t>(behaviorIndexValue->GetDoubleValue());
Game::logger->LogDebug("MoveToInventoryMessage", "bhId %i bhNdx %i", behaviorID, behaviorIndex);
}

View File

@ -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__

View File

@ -0,0 +1,16 @@
#include "RearrangeStripMessage.h"
RearrangeStripMessage::RearrangeStripMessage(AMFArrayValue* arguments) {
auto* srcActionIndexValue = arguments->FindValue<AMFDoubleValue>("srcActionIndex");
srcActionIndex = static_cast<uint32_t>(srcActionIndexValue->GetDoubleValue());
stripID = GetStripIDFromArgument(arguments);
behaviorID = GetBehaviorIDFromArgument(arguments);
auto* dstActionIndexValue = arguments->FindValue<AMFDoubleValue>("dstActionIndex");
dstActionIndex = static_cast<uint32_t>(dstActionIndexValue->GetDoubleValue());
stateID = GetBehaviorStateFromArgument(arguments);
Game::logger->LogDebug("RearrangeStripMessage", "srcAcnNdx %i dstAcnNdx %i stpId %i bhId %i sttId %i", srcActionIndex, dstActionIndex, stripID, behaviorID, stateID);
}

View File

@ -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__

View File

@ -0,0 +1,15 @@
#include "RemoveActionsMessage.h"
RemoveActionsMessage::RemoveActionsMessage(AMFArrayValue* arguments) {
behaviorID = GetBehaviorIDFromArgument(arguments);
auto* actionIndexAmf = arguments->FindValue<AMFDoubleValue>("actionIndex");
if (!actionIndexAmf) return;
actionIndex = static_cast<uint32_t>(actionIndexAmf->GetDoubleValue());
stripID = GetStripIDFromArgument(arguments);
stateID = GetBehaviorStateFromArgument(arguments);
Game::logger->LogDebug("RemoveActionsMessage", "bhId %i acnNdx %i stpId %i sttId %i", behaviorID, actionIndex, stripID, stateID);
}

View File

@ -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__

View File

@ -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);
}

View File

@ -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__

View File

@ -0,0 +1,11 @@
#include "RenameMessage.h"
RenameMessage::RenameMessage(AMFArrayValue* arguments) {
behaviorID = GetBehaviorIDFromArgument(arguments);
auto* nameAmf = arguments->FindValue<AMFStringValue>("Name");
if (!nameAmf) return;
name = nameAmf->GetStringValue();
Game::logger->LogDebug("RenameMessage", "bhId %i n %s", behaviorID, name.c_str());
}

View File

@ -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__

View File

@ -0,0 +1,29 @@
#include "SplitStripMessage.h"
SplitStripMessage::SplitStripMessage(AMFArrayValue* arguments) {
auto* srcActionIndexValue = arguments->FindValue<AMFDoubleValue>("srcActionIndex");
if (!srcActionIndexValue) return;
srcActionIndex = static_cast<uint32_t>(srcActionIndexValue->GetDoubleValue());
srcStripId = GetStripIDFromArgument(arguments, "srcStripID");
srcStateId = GetBehaviorStateFromArgument(arguments, "srcStateID");
dstStripId = GetStripIDFromArgument(arguments, "dstStripID");
dstStateId = GetBehaviorStateFromArgument(arguments, "dstStateID");
auto* dstStripUiArray = arguments->FindValue<AMFArrayValue>("dstStripUI");
if (!dstStripUiArray) return;
auto* xPositionValue = dstStripUiArray->FindValue<AMFDoubleValue>("x");
auto* yPositionValue = dstStripUiArray->FindValue<AMFDoubleValue>("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);
}

View File

@ -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__

View File

@ -0,0 +1,38 @@
#include "UpdateActionMessage.h"
UpdateActionMessage::UpdateActionMessage(AMFArrayValue* arguments) {
type = "";
valueParameterName = "";
valueParameterString = "";
valueParameterDouble = 0.0;
auto* actionAsArray = arguments->FindValue<AMFArrayValue>("action");
if (!actionAsArray) return;
for (auto& typeValueMap : actionAsArray->GetAssociativeMap()) {
if (typeValueMap.first == "Type") {
if (typeValueMap.second->GetValueType() != AMFValueType::AMFString) continue;
type = static_cast<AMFStringValue*>(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<AMFStringValue*>(typeValueMap.second)->GetStringValue();
} else {
if (typeValueMap.second->GetValueType() != AMFValueType::AMFDouble) continue;
valueParameterDouble = static_cast<AMFDoubleValue*>(typeValueMap.second)->GetDoubleValue();
}
}
}
behaviorID = GetBehaviorIDFromArgument(arguments);
auto* actionIndexValue = arguments->FindValue<AMFDoubleValue>("actionIndex");
if (!actionIndexValue) return;
actionIndex = static_cast<uint32_t>(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);
}

View File

@ -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__

View File

@ -0,0 +1,20 @@
#include "UpdateStripUiMessage.h"
UpdateStripUiMessage::UpdateStripUiMessage(AMFArrayValue* arguments) {
auto* uiArray = arguments->FindValue<AMFArrayValue>("ui");
if (!uiArray) return;
auto* xPositionValue = uiArray->FindValue<AMFDoubleValue>("x");
auto* yPositionValue = uiArray->FindValue<AMFDoubleValue>("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);
}

View File

@ -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__

View File

@ -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<AMFStringValue>(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<AMFUndefinedValue>(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<AMFDoubleValue>(key);
if (!stateIDValue) throw std::invalid_argument("Unable to find behavior state from argument \"" + key + "\"");
BEHAVIORSTATE stateID = static_cast<BEHAVIORSTATE>(stateIDValue->GetDoubleValue());
return stateID;
}
STRIPID GetStripIDFromArgument(AMFArrayValue* arguments, const std::string& key = "stripID") {
auto* stripIDValue = arguments->FindValue<AMFDoubleValue>(key);
if (!stripIDValue) throw std::invalid_argument("Unable to find strip ID from argument \"" + key + "\"");
STRIPID stripID = static_cast<STRIPID>(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<ModelComponent>();
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<AMFDoubleValue>("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<AMFArrayValue>("strip");
if (!strip) return;
auto* actions = strip->FindValue<AMFArrayValue>("actions");
if (!actions) return;
auto* uiArray = arguments->FindValue<AMFArrayValue>("ui");
if (!uiArray) return;
auto* xPositionValue = uiArray->FindValue<AMFDoubleValue>("x");
if (!xPositionValue) return;
double xPosition = xPositionValue->GetDoubleValue();
auto* yPositionValue = uiArray->FindValue<AMFDoubleValue>("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<AMFArrayValue>(position);
if (!actionAsArray) continue;
for (auto& typeValueMap : actionAsArray->GetAssociativeMap()) {
if (typeValueMap.first == "Type") {
if (typeValueMap.second->GetValueType() != AMFValueType::AMFString) continue;
type = static_cast<AMFStringValue*>(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<AMFStringValue*>(typeValueMap.second)->GetStringValue();
} else {
if (typeValueMap.second->GetValueType() != AMFValueType::AMFDouble) continue;
valueParameterDouble = static_cast<AMFDoubleValue*>(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<AMFDoubleValue>("dstActionIndex");
if (!dstActionIndexValue) return;
uint32_t dstActionIndex = static_cast<uint32_t>(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<AMFDoubleValue>("srcActionIndex");
if (!srcActionIndexValue) return;
uint32_t srcActionIndex = static_cast<uint32_t>(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<AMFArrayValue>("dstStripUI");
if (!dstStripUIArray) return;
auto* xPositionValue = dstStripUIArray->FindValue<AMFDoubleValue>("x");
auto* yPositionValue = dstStripUIArray->FindValue<AMFDoubleValue>("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<AMFArrayValue>("ui");
if (!uiArray) return;
auto* xPositionValue = uiArray->FindValue<AMFDoubleValue>("x");
auto* yPositionValue = uiArray->FindValue<AMFDoubleValue>("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<AMFDoubleValue>("actionIndex");
if (!actionIndexAmf) return;
uint32_t actionIndex = static_cast<uint32_t>(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<AMFArrayValue>("action");
if (!action) return;
for (auto& typeValueMap : action->GetAssociativeMap()) {
if (typeValueMap.first == "Type") {
if (typeValueMap.second->GetValueType() != AMFValueType::AMFString) continue;
type = static_cast<AMFStringValue*>(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<AMFStringValue*>(typeValueMap.second)->GetStringValue();
} else {
if (typeValueMap.second->GetValueType() != AMFValueType::AMFDouble) continue;
valueParameterDouble = static_cast<AMFDoubleValue*>(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<AMFDoubleValue>("srcActionIndex");
if (!srcActionIndexAmf) return;
uint32_t srcActionIndex = static_cast<uint32_t>(srcActionIndexAmf->GetDoubleValue());
STRIPID srcStripID = GetStripIDFromArgument(arguments, "srcStripID");
BEHAVIORSTATE srcStateID = GetBehaviorStateFromArgument(arguments, "srcStateID");
auto* dstActionIndexAmf = arguments->FindValue<AMFDoubleValue>("dstActionIndex");
if (!dstActionIndexAmf) return;
uint32_t dstActionIndex = static_cast<uint32_t>(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<AMFDoubleValue>("srcActionIndex");
uint32_t srcActionIndex = static_cast<uint32_t>(srcActionIndexValue->GetDoubleValue());
uint32_t stripID = GetStripIDFromArgument(arguments);
uint32_t behaviorID = GetBehaviorIDFromArgument(arguments);
auto* dstActionIndexValue = arguments->FindValue<AMFDoubleValue>("dstActionIndex");
uint32_t dstActionIndex = static_cast<uint32_t>(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<AMFDoubleValue>("BehaviorIndex");
if (!behaviorIndexAmf) return;
behaviorIndex = static_cast<uint32_t>(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<AMFDoubleValue>("actionIndex");
if (!actionIndexAmf) return;
uint32_t actionIndex = static_cast<uint32_t>(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<AMFStringValue>("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<AMFArrayValue>("action");
if (!actionAsArray) return;
for (auto& typeValueMap : actionAsArray->GetAssociativeMap()) {
if (typeValueMap.first == "Type") {
if (typeValueMap.second->GetValueType() != AMFValueType::AMFString) continue;
type = static_cast<AMFStringValue*>(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<AMFStringValue*>(typeValueMap.second)->GetStringValue();
} else {
if (typeValueMap.second->GetValueType() != AMFValueType::AMFDouble) continue;
valueParameterDouble = static_cast<AMFDoubleValue*>(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<AMFDoubleValue>("actionIndex");
if (!actionIndexValue) return;
uint32_t actionIndex = static_cast<uint32_t>(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<AMFDoubleValue>("BehaviorIndex");
if (!behaviorIndexValue) return;
uint32_t behaviorIndex = static_cast<uint32_t>(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<ModelComponent>();
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 = true;
}
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;
}

View File

@ -3,15 +3,23 @@
#ifndef __CONTROLBEHAVIORS__H__
#define __CONTROLBEHAVIORS__H__
#include <map>
#include <string>
#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<ControlBehaviors> {
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<BlockName, BlockDefinition*> blockTypes{};
// If false, property behaviors will not be able to be edited.
bool isInitialized = false;
};
#endif //!__CONTROLBEHAVIORS__H__

View File

@ -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})

View File

@ -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)

View File

@ -1,15 +1,50 @@
#include "GameMessages.h"
#include "GameDependencies.h"
#include <gtest/gtest.h>
#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 <gtest/gtest.h>
#include <fstream>
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<AMFArrayValue*>(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<uint32_t>(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<int32_t>(removeStrip.GetStripId()), 1);
ASSERT_EQ(static_cast<int32_t>(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<uint32_t>(mergeStrips.GetSrcStateID()), 0);
ASSERT_EQ(static_cast<uint32_t>(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<uint32_t>(splitStrip.GetSrcStateId()), 0);
ASSERT_EQ(static_cast<uint32_t>(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<uint32_t>(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<uint32_t>(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<uint32_t>(migrateActions.GetSrcStateID()), 0);
ASSERT_EQ(static_cast<uint32_t>(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<uint32_t>(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<uint32_t>(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<uint32_t>(updateAction.GetStateID()), 0);
}

View File

@ -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)

Binary file not shown.