mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-12-25 06:53:35 +00:00
Further implement Property Behavior parsing (#936)
Further implements the ControlBehavior processing and adds preparations for cheat detection
This commit is contained in:
parent
3cd0d1ec3d
commit
72c93c8913
@ -163,6 +163,7 @@ set(INCLUDED_DIRECTORIES
|
||||
"dGame/dMission"
|
||||
"dGame/dEntity"
|
||||
"dGame/dPropertyBehaviors"
|
||||
"dGame/dPropertyBehaviors/ControlBehaviorMessages"
|
||||
"dGame/dUtilities"
|
||||
"dPhysics"
|
||||
"dNavigation"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
9
dGame/dPropertyBehaviors/BlockDefinition.cpp
Normal file
9
dGame/dPropertyBehaviors/BlockDefinition.cpp
Normal 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;
|
||||
}
|
25
dGame/dPropertyBehaviors/BlockDefinition.h
Normal file
25
dGame/dPropertyBehaviors/BlockDefinition.h
Normal 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__
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
@ -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__
|
@ -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);
|
||||
}
|
@ -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__
|
@ -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);
|
||||
}
|
||||
}
|
@ -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__
|
@ -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__
|
@ -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
|
||||
)
|
@ -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);
|
||||
}
|
||||
|
@ -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__
|
@ -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);
|
||||
}
|
@ -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__
|
@ -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);
|
||||
}
|
@ -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__
|
@ -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);
|
||||
}
|
@ -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__
|
@ -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);
|
||||
}
|
@ -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__
|
@ -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);
|
||||
}
|
@ -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__
|
@ -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());
|
||||
}
|
@ -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__
|
@ -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);
|
||||
}
|
@ -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__
|
@ -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);
|
||||
}
|
@ -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__
|
@ -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);
|
||||
}
|
@ -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__
|
@ -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;
|
||||
}
|
||||
|
@ -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__
|
||||
|
@ -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})
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
BIN
tests/dGameTests/dGameMessagesTests/TestBitStreams/add
Normal file
BIN
tests/dGameTests/dGameMessagesTests/TestBitStreams/add
Normal file
Binary file not shown.
BIN
tests/dGameTests/dGameMessagesTests/TestBitStreams/addAction
Normal file
BIN
tests/dGameTests/dGameMessagesTests/TestBitStreams/addAction
Normal file
Binary file not shown.
BIN
tests/dGameTests/dGameMessagesTests/TestBitStreams/addStrip
Normal file
BIN
tests/dGameTests/dGameMessagesTests/TestBitStreams/addStrip
Normal file
Binary file not shown.
BIN
tests/dGameTests/dGameMessagesTests/TestBitStreams/mergeStrips
Normal file
BIN
tests/dGameTests/dGameMessagesTests/TestBitStreams/mergeStrips
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
tests/dGameTests/dGameMessagesTests/TestBitStreams/removeActions
Normal file
BIN
tests/dGameTests/dGameMessagesTests/TestBitStreams/removeActions
Normal file
Binary file not shown.
BIN
tests/dGameTests/dGameMessagesTests/TestBitStreams/removeStrip
Normal file
BIN
tests/dGameTests/dGameMessagesTests/TestBitStreams/removeStrip
Normal file
Binary file not shown.
BIN
tests/dGameTests/dGameMessagesTests/TestBitStreams/rename
Normal file
BIN
tests/dGameTests/dGameMessagesTests/TestBitStreams/rename
Normal file
Binary file not shown.
Binary file not shown.
BIN
tests/dGameTests/dGameMessagesTests/TestBitStreams/splitStrip
Normal file
BIN
tests/dGameTests/dGameMessagesTests/TestBitStreams/splitStrip
Normal file
Binary file not shown.
Binary file not shown.
BIN
tests/dGameTests/dGameMessagesTests/TestBitStreams/updateAction
Normal file
BIN
tests/dGameTests/dGameMessagesTests/TestBitStreams/updateAction
Normal file
Binary file not shown.
BIN
tests/dGameTests/dGameMessagesTests/TestBitStreams/updateStripUI
Normal file
BIN
tests/dGameTests/dGameMessagesTests/TestBitStreams/updateStripUI
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user