mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-11-24 22:47:25 +00:00
feat: partially functioning property behavior ui (no saving or loading yet) (#1384)
* Add addstrip handling add SendBehaviorBlocksToClient serialization add id generation and auto updating add behaviorlisttoclient serialization * fix crash happened if you added state 0 and 6 and nothing in between * Section off code Use proper encapsulation to hide code away and only let specific objects do certain jobs. * Organize serialization Section off into operational chunks Write data at the level most appropriate * Remove and simplify BlockDefinitions Remove pointer usage for BlockDefinitions and move to optional. * ControlBehaviors: Add addaction handling * re-organization remove const from return value change to int from uint use generic methods to reduce code clutter * add strip ui position handling * add split strip functionality * fix issues fix an issue where if you were on an empty state, the server would allow you to remain on that state fix an issue where the ui would not open on the previously opened state fix an issue where deleting strips in order caused the wrong strips to be deleted * update how you remove behaviors from models * Add remove actions and rename * migrate actions * update action and rearrange strip * merge strips * add and move to inventory * Remove dead code * simplify code * nits and move finish MoveToInventory constify serialize further include path fixes use const, comments fix amf message Update ModelComponent.cpp replace operator subscript with at * Update ModelComponent.cpp * Update MigrateActionsMessage.h * const * Move to separate translation units * include amf3 its precompiled, but just in case
This commit is contained in:
parent
09fb1dfff9
commit
c7c84c21ef
@ -1,6 +1,12 @@
|
||||
#include "ModelComponent.h"
|
||||
#include "Entity.h"
|
||||
|
||||
#include "Game.h"
|
||||
#include "Logger.h"
|
||||
|
||||
#include "BehaviorStates.h"
|
||||
#include "ControlBehaviorMsgs.h"
|
||||
|
||||
ModelComponent::ModelComponent(Entity* parent) : Component(parent) {
|
||||
m_OriginalPosition = m_Parent->GetDefaultPosition();
|
||||
m_OriginalRotation = m_Parent->GetDefaultRotation();
|
||||
@ -29,3 +35,40 @@ void ModelComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialU
|
||||
outBitStream->Write1(); // Is this model paused
|
||||
if (bIsInitialUpdate) outBitStream->Write0(); // We are not writing model editing info
|
||||
}
|
||||
|
||||
void ModelComponent::UpdatePendingBehaviorId(const int32_t newId) {
|
||||
for (auto& behavior : m_Behaviors) if (behavior.GetBehaviorId() == -1) behavior.SetBehaviorId(newId);
|
||||
}
|
||||
|
||||
void ModelComponent::SendBehaviorListToClient(AMFArrayValue& args) const {
|
||||
args.Insert("objectID", std::to_string(m_Parent->GetObjectID()));
|
||||
|
||||
auto* behaviorArray = args.InsertArray("behaviors");
|
||||
for (auto& behavior : m_Behaviors) {
|
||||
auto* behaviorArgs = behaviorArray->PushArray();
|
||||
behavior.SendBehaviorListToClient(*behaviorArgs);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelComponent::VerifyBehaviors() {
|
||||
for (auto& behavior : m_Behaviors) behavior.VerifyLastEditedState();
|
||||
}
|
||||
|
||||
void ModelComponent::SendBehaviorBlocksToClient(int32_t behaviorToSend, AMFArrayValue& args) const {
|
||||
args.Insert("BehaviorID", std::to_string(behaviorToSend));
|
||||
args.Insert("objectID", std::to_string(m_Parent->GetObjectID()));
|
||||
for (auto& behavior : m_Behaviors) if (behavior.GetBehaviorId() == behaviorToSend) behavior.SendBehaviorBlocksToClient(args);
|
||||
}
|
||||
|
||||
void ModelComponent::AddBehavior(AddMessage& msg) {
|
||||
// Can only have 1 of the loot behaviors
|
||||
for (auto& behavior : m_Behaviors) if (behavior.GetBehaviorId() == msg.GetBehaviorId()) return;
|
||||
m_Behaviors.insert(m_Behaviors.begin() + msg.GetBehaviorIndex(), PropertyBehavior());
|
||||
m_Behaviors.at(msg.GetBehaviorIndex()).HandleMsg(msg);
|
||||
}
|
||||
|
||||
void ModelComponent::MoveToInventory(MoveToInventoryMessage& msg) {
|
||||
if (msg.GetBehaviorIndex() >= m_Behaviors.size() || m_Behaviors.at(msg.GetBehaviorIndex()).GetBehaviorId() != msg.GetBehaviorId()) return;
|
||||
m_Behaviors.erase(m_Behaviors.begin() + msg.GetBehaviorIndex());
|
||||
// TODO move to the inventory
|
||||
}
|
||||
|
@ -1,4 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "dCommonVars.h"
|
||||
#include "RakNetTypes.h"
|
||||
#include "NiPoint3.h"
|
||||
@ -6,7 +9,15 @@
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
#include "Action.h"
|
||||
#include "PropertyBehavior.h"
|
||||
#include "StripUiPosition.h"
|
||||
|
||||
class AddMessage;
|
||||
class AMFArrayValue;
|
||||
class BehaviorMessageBase;
|
||||
class Entity;
|
||||
class MoveToInventoryMessage;
|
||||
|
||||
/**
|
||||
* Component that represents entities that are a model, e.g. collectible models and BBB models.
|
||||
@ -43,7 +54,68 @@ public:
|
||||
*/
|
||||
void SetRotation(const NiQuaternion& rot) { m_OriginalRotation = rot; }
|
||||
|
||||
/**
|
||||
* Main gateway for all behavior messages to be passed to their respective behaviors.
|
||||
*
|
||||
* @tparam Msg The message type to pass
|
||||
* @param args the arguments of the message to be deserialized
|
||||
*/
|
||||
template<typename Msg>
|
||||
void HandleControlBehaviorsMsg(AMFArrayValue* args) {
|
||||
static_assert(std::is_base_of_v<BehaviorMessageBase, Msg>, "Msg must be a BehaviorMessageBase");
|
||||
Msg msg(args);
|
||||
for (auto& behavior : m_Behaviors) {
|
||||
if (behavior.GetBehaviorId() == msg.GetBehaviorId()) {
|
||||
behavior.HandleMsg(msg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If we somehow added more than 5 behaviors, resize to 5.
|
||||
if (m_Behaviors.size() > 5) m_Behaviors.resize(5);
|
||||
|
||||
// Do not allow more than 5 to be added. The client UI will break if you do!
|
||||
if (m_Behaviors.size() == 5) return;
|
||||
|
||||
auto newBehavior = m_Behaviors.insert(m_Behaviors.begin(), PropertyBehavior());
|
||||
// Generally if we are inserting a new behavior, it is because the client is creating a new behavior.
|
||||
// However if we are testing behaviors the behavior will not exist on the initial pass, so we set the ID here to that of the msg.
|
||||
// This will either set the ID to -1 (no change in the current default) or set the ID to the ID of the behavior we are testing.
|
||||
newBehavior->SetBehaviorId(msg.GetBehaviorId());
|
||||
newBehavior->HandleMsg(msg);
|
||||
};
|
||||
|
||||
void AddBehavior(AddMessage& msg);
|
||||
|
||||
void MoveToInventory(MoveToInventoryMessage& msg);
|
||||
|
||||
// Updates the pending behavior ID to the new ID.
|
||||
void UpdatePendingBehaviorId(const int32_t newId);
|
||||
|
||||
// Sends the behavior list to the client.
|
||||
|
||||
/**
|
||||
* The behaviors AMFArray will have up to 5 elements in the dense portion.
|
||||
* Each element in the dense portion will be made up of another AMFArray
|
||||
* with the following information mapped in the associative portion
|
||||
* "id": Behavior ID cast to an AMFString
|
||||
* "isLocked": AMFTrue or AMFFalse of whether or not the behavior is locked
|
||||
* "isLoot": AMFTrue or AMFFalse of whether or not the behavior is a custom behavior (true if custom)
|
||||
* "name": The name of the behavior formatted as an AMFString
|
||||
*/
|
||||
void SendBehaviorListToClient(AMFArrayValue& args) const;
|
||||
|
||||
void SendBehaviorBlocksToClient(int32_t behaviorToSend, AMFArrayValue& args) const;
|
||||
|
||||
void VerifyBehaviors();
|
||||
|
||||
private:
|
||||
/**
|
||||
* The behaviors of the model
|
||||
* Note: This is a vector because the order of the behaviors matters when serializing to the client.
|
||||
* Note: No two PropertyBehaviors should have the same behavior ID.
|
||||
*/
|
||||
std::vector<PropertyBehavior> m_Behaviors;
|
||||
|
||||
/**
|
||||
* The original position of the model
|
||||
|
@ -1,4 +1,7 @@
|
||||
set(DGAME_DPROPERTYBEHAVIORS_SOURCES
|
||||
"PropertyBehavior.cpp"
|
||||
"State.cpp"
|
||||
"Strip.cpp"
|
||||
"BlockDefinition.cpp"
|
||||
"ControlBehaviors.cpp"
|
||||
)
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "Action.h"
|
||||
#include "Amf3.h"
|
||||
|
||||
Action::Action() {
|
||||
type = "";
|
||||
@ -12,20 +13,34 @@ Action::Action(AMFArrayValue* arguments) {
|
||||
valueParameterName = "";
|
||||
valueParameterString = "";
|
||||
valueParameterDouble = 0.0;
|
||||
for (auto& typeValueMap : arguments->GetAssociative()) {
|
||||
if (typeValueMap.first == "Type") {
|
||||
if (typeValueMap.second->GetValueType() != eAmf::String) continue;
|
||||
type = static_cast<AMFStringValue*>(typeValueMap.second)->GetValue();
|
||||
for (auto& [paramName, paramValue] : arguments->GetAssociative()) {
|
||||
if (paramName == "Type") {
|
||||
if (paramValue->GetValueType() != eAmf::String) continue;
|
||||
type = static_cast<AMFStringValue*>(paramValue)->GetValue();
|
||||
} else {
|
||||
valueParameterName = typeValueMap.first;
|
||||
valueParameterName = paramName;
|
||||
// Message is the only known string parameter
|
||||
if (valueParameterName == "Message") {
|
||||
if (typeValueMap.second->GetValueType() != eAmf::String) continue;
|
||||
valueParameterString = static_cast<AMFStringValue*>(typeValueMap.second)->GetValue();
|
||||
if (paramValue->GetValueType() != eAmf::String) continue;
|
||||
valueParameterString = static_cast<AMFStringValue*>(paramValue)->GetValue();
|
||||
} else {
|
||||
if (typeValueMap.second->GetValueType() != eAmf::Double) continue;
|
||||
valueParameterDouble = static_cast<AMFDoubleValue*>(typeValueMap.second)->GetValue();
|
||||
if (paramValue->GetValueType() != eAmf::Double) continue;
|
||||
valueParameterDouble = static_cast<AMFDoubleValue*>(paramValue)->GetValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Action::SendBehaviorBlocksToClient(AMFArrayValue& args) const {
|
||||
auto* actionArgs = args.PushArray();
|
||||
actionArgs->Insert("Type", type);
|
||||
|
||||
auto valueParameterName = GetValueParameterName();
|
||||
if (valueParameterName.empty()) return;
|
||||
|
||||
if (valueParameterName == "Message") {
|
||||
actionArgs->Insert(valueParameterName, valueParameterString);
|
||||
} else {
|
||||
actionArgs->Insert(valueParameterName, valueParameterDouble);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
#ifndef __ACTION__H__
|
||||
#define __ACTION__H__
|
||||
|
||||
#include "BehaviorMessageBase.h"
|
||||
#include <string>
|
||||
|
||||
class AMFArrayValue;
|
||||
|
||||
/**
|
||||
* @brief Sent if a ControlBehavior message has an Action associated with it
|
||||
@ -11,10 +13,12 @@ class Action {
|
||||
public:
|
||||
Action();
|
||||
Action(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 std::string& GetType() const { return type; };
|
||||
const std::string& GetValueParameterName() const { return valueParameterName; };
|
||||
const std::string& GetValueParameterString() const { return valueParameterString; };
|
||||
const double GetValueParameterDouble() const { return valueParameterDouble; };
|
||||
|
||||
void SendBehaviorBlocksToClient(AMFArrayValue& args) const;
|
||||
private:
|
||||
std::string type;
|
||||
std::string valueParameterName;
|
||||
|
@ -14,8 +14,8 @@ class ActionContext {
|
||||
public:
|
||||
ActionContext();
|
||||
ActionContext(AMFArrayValue* arguments, std::string customStateKey = "stateID", std::string customStripKey = "stripID");
|
||||
const StripId GetStripId() { return stripId; };
|
||||
const BehaviorState GetStateId() { return stateId; };
|
||||
const StripId GetStripId() const { return stripId; };
|
||||
const BehaviorState GetStateId() const { return stateId; };
|
||||
private:
|
||||
BehaviorState GetBehaviorStateFromArgument(AMFArrayValue* arguments, const std::string& key);
|
||||
StripId GetStripIdFromArgument(AMFArrayValue* arguments, const std::string& key);
|
||||
|
@ -14,11 +14,11 @@ class AMFArrayValue;
|
||||
class AddActionMessage : public BehaviorMessageBase {
|
||||
public:
|
||||
AddActionMessage(AMFArrayValue* arguments);
|
||||
const uint32_t GetActionIndex() { return actionIndex; };
|
||||
Action GetAction() { return action; };
|
||||
ActionContext GetActionContext() { return actionContext; };
|
||||
int32_t GetActionIndex() const { return actionIndex; };
|
||||
Action GetAction() const { return action; };
|
||||
ActionContext GetActionContext() const { return actionContext; };
|
||||
private:
|
||||
uint32_t actionIndex;
|
||||
int32_t actionIndex = -1;
|
||||
ActionContext actionContext;
|
||||
Action action;
|
||||
};
|
||||
|
@ -10,7 +10,7 @@
|
||||
class AddMessage : public BehaviorMessageBase {
|
||||
public:
|
||||
AddMessage(AMFArrayValue* arguments);
|
||||
const uint32_t GetBehaviorIndex() { return behaviorIndex; };
|
||||
const uint32_t GetBehaviorIndex() const { return behaviorIndex; };
|
||||
private:
|
||||
uint32_t behaviorIndex;
|
||||
};
|
||||
|
@ -19,9 +19,9 @@ class AMFArrayValue;
|
||||
class AddStripMessage : public BehaviorMessageBase {
|
||||
public:
|
||||
AddStripMessage(AMFArrayValue* arguments);
|
||||
StripUiPosition GetPosition() { return position; };
|
||||
ActionContext GetActionContext() { return actionContext; };
|
||||
std::vector<Action> GetActionsToAdd() { return actionsToAdd; };
|
||||
StripUiPosition GetPosition() const { return position; };
|
||||
ActionContext GetActionContext() const { return actionContext; };
|
||||
std::vector<Action> GetActionsToAdd() const { return actionsToAdd; };
|
||||
private:
|
||||
StripUiPosition position;
|
||||
ActionContext actionContext;
|
||||
|
@ -5,29 +5,27 @@
|
||||
#include "dCommonVars.h"
|
||||
|
||||
BehaviorMessageBase::BehaviorMessageBase(AMFArrayValue* arguments) {
|
||||
behaviorId = 0;
|
||||
behaviorId = GetBehaviorIdFromArgument(arguments);
|
||||
}
|
||||
|
||||
int32_t BehaviorMessageBase::GetBehaviorIdFromArgument(AMFArrayValue* arguments) {
|
||||
const auto* key = "BehaviorID";
|
||||
auto* behaviorIDValue = arguments->Get<std::string>(key);
|
||||
int32_t behaviorID = -1;
|
||||
|
||||
if (behaviorIDValue && behaviorIDValue->GetValueType() == eAmf::String) {
|
||||
behaviorID = std::stoul(behaviorIDValue->GetValue());
|
||||
} else if (arguments->Get(key)->GetValueType() != eAmf::Undefined) {
|
||||
GeneralUtils::TryParse(behaviorIDValue->GetValue(), behaviorId);
|
||||
} else if (arguments->Get(key) && arguments->Get(key)->GetValueType() != eAmf::Undefined) {
|
||||
throw std::invalid_argument("Unable to find behavior ID");
|
||||
}
|
||||
|
||||
return behaviorID;
|
||||
return behaviorId;
|
||||
}
|
||||
|
||||
uint32_t BehaviorMessageBase::GetActionIndexFromArgument(AMFArrayValue* arguments, const std::string& keyName) {
|
||||
int32_t BehaviorMessageBase::GetActionIndexFromArgument(AMFArrayValue* arguments, const std::string& keyName) {
|
||||
auto* actionIndexAmf = arguments->Get<double>(keyName);
|
||||
if (!actionIndexAmf) {
|
||||
throw std::invalid_argument("Unable to find actionIndex");
|
||||
}
|
||||
|
||||
return static_cast<uint32_t>(actionIndexAmf->GetValue());
|
||||
return static_cast<int32_t>(actionIndexAmf->GetValue());
|
||||
}
|
||||
|
@ -7,9 +7,6 @@
|
||||
#include "Amf3.h"
|
||||
#include "dCommonVars.h"
|
||||
|
||||
#include "Game.h"
|
||||
#include "Logger.h"
|
||||
|
||||
enum class BehaviorState : uint32_t;
|
||||
|
||||
/**
|
||||
@ -18,12 +15,14 @@ enum class BehaviorState : uint32_t;
|
||||
*/
|
||||
class BehaviorMessageBase {
|
||||
public:
|
||||
const uint32_t GetBehaviorId() { return behaviorId; };
|
||||
protected:
|
||||
static inline int32_t DefaultBehaviorId = -1;
|
||||
const int32_t GetBehaviorId() const { return behaviorId; };
|
||||
bool IsDefaultBehaviorId() { return behaviorId == DefaultBehaviorId; };
|
||||
BehaviorMessageBase(AMFArrayValue* arguments);
|
||||
protected:
|
||||
int32_t GetBehaviorIdFromArgument(AMFArrayValue* arguments);
|
||||
uint32_t GetActionIndexFromArgument(AMFArrayValue* arguments, const std::string& keyName = "actionIndex");
|
||||
int32_t behaviorId = -1;
|
||||
int32_t GetActionIndexFromArgument(AMFArrayValue* arguments, const std::string& keyName = "actionIndex");
|
||||
int32_t behaviorId = DefaultBehaviorId;
|
||||
};
|
||||
|
||||
#endif //!__BEHAVIORMESSAGEBASE__H__
|
||||
|
@ -0,0 +1,23 @@
|
||||
#ifndef __CONTROLBEHAVIORMSGS__H__
|
||||
#define __CONTROLBEHAVIORMSGS__H__
|
||||
|
||||
#include "Action.h"
|
||||
#include "ActionContext.h"
|
||||
#include "AddActionMessage.h"
|
||||
#include "AddMessage.h"
|
||||
#include "AddStripMessage.h"
|
||||
#include "BehaviorMessageBase.h"
|
||||
#include "ControlBehaviorMsgs.h"
|
||||
#include "MergeStripsMessage.h"
|
||||
#include "MigrateActionsMessage.h"
|
||||
#include "MoveToInventoryMessage.h"
|
||||
#include "RearrangeStripMessage.h"
|
||||
#include "RemoveActionsMessage.h"
|
||||
#include "RemoveStripMessage.h"
|
||||
#include "RenameMessage.h"
|
||||
#include "SplitStripMessage.h"
|
||||
#include "StripUiPosition.h"
|
||||
#include "UpdateActionMessage.h"
|
||||
#include "UpdateStripUiMessage.h"
|
||||
|
||||
#endif //!__CONTROLBEHAVIORMSGS__H__
|
@ -1,6 +1,7 @@
|
||||
#ifndef __MERGESTRIPSMESSAGE__H__
|
||||
#define __MERGESTRIPSMESSAGE__H__
|
||||
|
||||
#include "Action.h"
|
||||
#include "ActionContext.h"
|
||||
#include "BehaviorMessageBase.h"
|
||||
|
||||
@ -13,13 +14,16 @@ class AMFArrayValue;
|
||||
class MergeStripsMessage : public BehaviorMessageBase {
|
||||
public:
|
||||
MergeStripsMessage(AMFArrayValue* arguments);
|
||||
const uint32_t GetDstActionIndex() { return dstActionIndex; };
|
||||
ActionContext GetSourceActionContext() { return sourceActionContext; };
|
||||
ActionContext GetDestinationActionContext() { return destinationActionContext; };
|
||||
int32_t GetDstActionIndex() const { return dstActionIndex; };
|
||||
ActionContext GetSourceActionContext() const { return sourceActionContext; };
|
||||
ActionContext GetDestinationActionContext() const { return destinationActionContext; };
|
||||
const std::vector<Action>& GetMigratedActions() const { return migratedActions; };
|
||||
void SetMigratedActions(std::vector<Action>::const_iterator start, std::vector<Action>::const_iterator end) { migratedActions.assign(start, end); };
|
||||
private:
|
||||
std::vector<Action> migratedActions;
|
||||
ActionContext sourceActionContext;
|
||||
ActionContext destinationActionContext;
|
||||
uint32_t dstActionIndex;
|
||||
int32_t dstActionIndex;
|
||||
};
|
||||
|
||||
#endif //!__MERGESTRIPSMESSAGE__H__
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef __MIGRATEACTIONSMESSAGE__H__
|
||||
#define __MIGRATEACTIONSMESSAGE__H__
|
||||
|
||||
#include "Action.h"
|
||||
#include "ActionContext.h"
|
||||
#include "BehaviorMessageBase.h"
|
||||
|
||||
@ -13,15 +14,18 @@ class AMFArrayValue;
|
||||
class MigrateActionsMessage : public BehaviorMessageBase {
|
||||
public:
|
||||
MigrateActionsMessage(AMFArrayValue* arguments);
|
||||
const uint32_t GetSrcActionIndex() { return srcActionIndex; };
|
||||
const uint32_t GetDstActionIndex() { return dstActionIndex; };
|
||||
ActionContext GetSourceActionContext() { return sourceActionContext; };
|
||||
ActionContext GetDestinationActionContext() { return destinationActionContext; };
|
||||
int32_t GetSrcActionIndex() const { return srcActionIndex; };
|
||||
int32_t GetDstActionIndex() const { return dstActionIndex; };
|
||||
ActionContext GetSourceActionContext() const { return sourceActionContext; };
|
||||
ActionContext GetDestinationActionContext() const { return destinationActionContext; };
|
||||
const std::vector<Action>& GetMigratedActions() const { return migratedActions; };
|
||||
void SetMigratedActions(std::vector<Action>::const_iterator start, std::vector<Action>::const_iterator end) { migratedActions.assign(start, end); };
|
||||
private:
|
||||
std::vector<Action> migratedActions;
|
||||
ActionContext sourceActionContext;
|
||||
ActionContext destinationActionContext;
|
||||
uint32_t srcActionIndex;
|
||||
uint32_t dstActionIndex;
|
||||
int32_t srcActionIndex;
|
||||
int32_t dstActionIndex;
|
||||
};
|
||||
|
||||
#endif //!__MIGRATEACTIONSMESSAGE__H__
|
||||
|
@ -13,7 +13,7 @@ class AMFArrayValue;
|
||||
class MoveToInventoryMessage : public BehaviorMessageBase {
|
||||
public:
|
||||
MoveToInventoryMessage(AMFArrayValue* arguments);
|
||||
const uint32_t GetBehaviorIndex() { return behaviorIndex; };
|
||||
const uint32_t GetBehaviorIndex() const { return behaviorIndex; };
|
||||
private:
|
||||
uint32_t behaviorIndex;
|
||||
};
|
||||
|
@ -11,13 +11,13 @@
|
||||
class RearrangeStripMessage : public BehaviorMessageBase {
|
||||
public:
|
||||
RearrangeStripMessage(AMFArrayValue* arguments);
|
||||
const uint32_t GetSrcActionIndex() { return srcActionIndex; };
|
||||
const uint32_t GetDstActionIndex() { return dstActionIndex; };
|
||||
ActionContext GetActionContext() { return actionContext; };
|
||||
int32_t GetSrcActionIndex() const { return srcActionIndex; };
|
||||
int32_t GetDstActionIndex() const { return dstActionIndex; };
|
||||
ActionContext GetActionContext() const { return actionContext; };
|
||||
private:
|
||||
ActionContext actionContext;
|
||||
uint32_t srcActionIndex;
|
||||
uint32_t dstActionIndex;
|
||||
int32_t srcActionIndex;
|
||||
int32_t dstActionIndex;
|
||||
};
|
||||
|
||||
#endif //!__REARRANGESTRIPMESSAGE__H__
|
||||
|
@ -13,11 +13,11 @@ class AMFArrayValue;
|
||||
class RemoveActionsMessage : public BehaviorMessageBase {
|
||||
public:
|
||||
RemoveActionsMessage(AMFArrayValue* arguments);
|
||||
const uint32_t GetActionIndex() { return actionIndex; };
|
||||
ActionContext GetActionContext() { return actionContext; };
|
||||
int32_t GetActionIndex() const { return actionIndex; };
|
||||
ActionContext GetActionContext() const { return actionContext; };
|
||||
private:
|
||||
ActionContext actionContext;
|
||||
uint32_t actionIndex;
|
||||
int32_t actionIndex;
|
||||
};
|
||||
|
||||
#endif //!__REMOVEACTIONSMESSAGE__H__
|
||||
|
@ -11,7 +11,7 @@
|
||||
class RemoveStripMessage : public BehaviorMessageBase {
|
||||
public:
|
||||
RemoveStripMessage(AMFArrayValue* arguments);
|
||||
ActionContext GetActionContext() { return actionContext; };
|
||||
ActionContext GetActionContext() const { return actionContext; };
|
||||
private:
|
||||
ActionContext actionContext;
|
||||
};
|
||||
|
@ -12,7 +12,7 @@ class AMFArrayValue;
|
||||
class RenameMessage : public BehaviorMessageBase {
|
||||
public:
|
||||
RenameMessage(AMFArrayValue* arguments);
|
||||
const std::string& GetName() { return name; };
|
||||
const std::string& GetName() const { return name; };
|
||||
private:
|
||||
std::string name;
|
||||
};
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef __SPLITSTRIPMESSAGE__H__
|
||||
#define __SPLITSTRIPMESSAGE__H__
|
||||
|
||||
#include "Action.h"
|
||||
#include "ActionContext.h"
|
||||
#include "BehaviorMessageBase.h"
|
||||
#include "StripUiPosition.h"
|
||||
@ -14,15 +15,19 @@ class AMFArrayValue;
|
||||
class SplitStripMessage : public BehaviorMessageBase {
|
||||
public:
|
||||
SplitStripMessage(AMFArrayValue* arguments);
|
||||
ActionContext GetSourceActionContext() { return sourceActionContext; };
|
||||
ActionContext GetDestinationActionContext() { return destinationActionContext; };
|
||||
const uint32_t GetSrcActionIndex() { return srcActionIndex; };
|
||||
StripUiPosition GetPosition() { return destinationPosition; };
|
||||
ActionContext GetSourceActionContext() const { return sourceActionContext; };
|
||||
ActionContext GetDestinationActionContext() const { return destinationActionContext; };
|
||||
int32_t GetSrcActionIndex() const { return srcActionIndex; };
|
||||
StripUiPosition GetPosition() const { return destinationPosition; };
|
||||
const std::vector<Action>& GetTransferredActions() const { return transferredActions; };
|
||||
void SetTransferredActions(std::vector<Action>::const_iterator begin, std::vector<Action>::const_iterator end) { transferredActions.assign(begin, end); };
|
||||
private:
|
||||
ActionContext sourceActionContext;
|
||||
ActionContext destinationActionContext;
|
||||
uint32_t srcActionIndex;
|
||||
int32_t srcActionIndex;
|
||||
StripUiPosition destinationPosition;
|
||||
|
||||
std::vector<Action> transferredActions;
|
||||
};
|
||||
|
||||
#endif //!__SPLITSTRIPMESSAGE__H__
|
||||
|
@ -20,3 +20,9 @@ StripUiPosition::StripUiPosition(AMFArrayValue* arguments, std::string uiKeyName
|
||||
yPosition = yPositionValue->GetValue();
|
||||
xPosition = xPositionValue->GetValue();
|
||||
}
|
||||
|
||||
void StripUiPosition::SendBehaviorBlocksToClient(AMFArrayValue& args) const {
|
||||
auto* uiArgs = args.InsertArray("ui");
|
||||
uiArgs->Insert("x", xPosition);
|
||||
uiArgs->Insert("y", yPosition);
|
||||
}
|
||||
|
@ -11,8 +11,9 @@ class StripUiPosition {
|
||||
public:
|
||||
StripUiPosition();
|
||||
StripUiPosition(AMFArrayValue* arguments, std::string uiKeyName = "ui");
|
||||
double GetX() { return xPosition; };
|
||||
double GetY() { return yPosition; };
|
||||
void SendBehaviorBlocksToClient(AMFArrayValue& args) const;
|
||||
double GetX() const { return xPosition; };
|
||||
double GetY() const { return yPosition; };
|
||||
private:
|
||||
double xPosition;
|
||||
double yPosition;
|
||||
|
@ -14,11 +14,11 @@ class AMFArrayValue;
|
||||
class UpdateActionMessage : public BehaviorMessageBase {
|
||||
public:
|
||||
UpdateActionMessage(AMFArrayValue* arguments);
|
||||
const uint32_t GetActionIndex() { return actionIndex; };
|
||||
ActionContext GetActionContext() { return actionContext; };
|
||||
Action GetAction() { return action; };
|
||||
int32_t GetActionIndex() const { return actionIndex; };
|
||||
ActionContext GetActionContext() const { return actionContext; };
|
||||
Action GetAction() const { return action; };
|
||||
private:
|
||||
uint32_t actionIndex;
|
||||
int32_t actionIndex;
|
||||
ActionContext actionContext;
|
||||
Action action;
|
||||
};
|
||||
|
@ -14,8 +14,8 @@ class AMFArrayValue;
|
||||
class UpdateStripUiMessage : public BehaviorMessageBase {
|
||||
public:
|
||||
UpdateStripUiMessage(AMFArrayValue* arguments);
|
||||
StripUiPosition GetPosition() { return position; };
|
||||
ActionContext GetActionContext() { return actionContext; };
|
||||
StripUiPosition GetPosition() const { return position; };
|
||||
ActionContext GetActionContext() const { return actionContext; };
|
||||
private:
|
||||
StripUiPosition position;
|
||||
ActionContext actionContext;
|
||||
|
@ -30,221 +30,49 @@
|
||||
#include "UpdateActionMessage.h"
|
||||
#include "UpdateStripUiMessage.h"
|
||||
|
||||
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(
|
||||
// [behaviorID, behavior, modelComponent, modelOwner, sysAddr](uint32_t persistentId) {
|
||||
// behavior->SetShouldGetNewID(false);
|
||||
// behavior->SetIsTemplated(false);
|
||||
// behavior->SetBehaviorID(persistentId);
|
||||
void ControlBehaviors::RequestUpdatedID(ControlBehaviorContext& context) {
|
||||
ObjectIDManager::Instance()->RequestPersistentID(
|
||||
[context](uint32_t persistentId) {
|
||||
if (!context) {
|
||||
LOG("Model to update behavior ID for is null. Cannot update ID.");
|
||||
return;
|
||||
}
|
||||
// This updates the behavior ID of the behavior should this be a new behavior
|
||||
AMFArrayValue args;
|
||||
|
||||
// // This updates the behavior ID of the behavior should this be a new behavior
|
||||
// AMFArrayValue args;
|
||||
args.Insert("behaviorID", std::to_string(persistentId));
|
||||
args.Insert("objectID", std::to_string(context.modelComponent->GetParent()->GetObjectID()));
|
||||
|
||||
// AMFStringValue* behaviorIDString = new AMFStringValue();
|
||||
// behaviorIDString->SetValue(std::to_string(persistentId));
|
||||
// args.InsertValue("behaviorID", behaviorIDString);
|
||||
GameMessages::SendUIMessageServerToSingleClient(context.modelOwner, context.modelOwner->GetSystemAddress(), "UpdateBehaviorID", args);
|
||||
context.modelComponent->UpdatePendingBehaviorId(persistentId);
|
||||
|
||||
// AMFStringValue* objectIDAsString = new AMFStringValue();
|
||||
// objectIDAsString->SetValue(std::to_string(modelComponent->GetParent()->GetObjectID()));
|
||||
// args.InsertValue("objectID", objectIDAsString);
|
||||
|
||||
// GameMessages::SendUIMessageServerToSingleClient(modelOwner, sysAddr, "UpdateBehaviorID", &args);
|
||||
// ControlBehaviors::SendBehaviorListToClient(modelComponent->GetParent(), sysAddr, modelOwner);
|
||||
// });
|
||||
// }
|
||||
ControlBehaviors::Instance().SendBehaviorListToClient(context);
|
||||
});
|
||||
}
|
||||
|
||||
void ControlBehaviors::SendBehaviorListToClient(Entity* modelEntity, const SystemAddress& sysAddr, Entity* modelOwner) {
|
||||
auto* modelComponent = modelEntity->GetComponent<ModelComponent>();
|
||||
|
||||
if (!modelComponent) return;
|
||||
void ControlBehaviors::SendBehaviorListToClient(const ControlBehaviorContext& context) {
|
||||
if (!context) return;
|
||||
|
||||
AMFArrayValue behaviorsToSerialize;
|
||||
context.modelComponent->SendBehaviorListToClient(behaviorsToSerialize);
|
||||
|
||||
/**
|
||||
* The behaviors AMFArray will have up to 5 elements in the dense portion.
|
||||
* Each element in the dense portion will be made up of another AMFArray
|
||||
* with the following information mapped in the associative portion
|
||||
* "id": Behavior ID cast to an AMFString
|
||||
* "isLocked": AMFTrue or AMFFalse of whether or not the behavior is locked
|
||||
* "isLoot": AMFTrue or AMFFalse of whether or not the behavior is a custom behavior (true if custom)
|
||||
* "name": The name of the behavior formatted as an AMFString
|
||||
*/
|
||||
|
||||
behaviorsToSerialize.Insert("behaviors");
|
||||
behaviorsToSerialize.Insert("objectID", std::to_string(modelComponent->GetParent()->GetObjectID()));
|
||||
|
||||
GameMessages::SendUIMessageServerToSingleClient(modelOwner, sysAddr, "UpdateBehaviorList", behaviorsToSerialize);
|
||||
}
|
||||
|
||||
void ControlBehaviors::ModelTypeChanged(AMFArrayValue* arguments, ModelComponent* ModelComponent) {
|
||||
auto* modelTypeAmf = arguments->Get<double>("ModelType");
|
||||
if (!modelTypeAmf) return;
|
||||
|
||||
uint32_t modelType = static_cast<uint32_t>(modelTypeAmf->GetValue());
|
||||
|
||||
//TODO Update the model type here
|
||||
}
|
||||
|
||||
void ControlBehaviors::ToggleExecutionUpdates() {
|
||||
//TODO do something with this info
|
||||
}
|
||||
|
||||
void ControlBehaviors::AddStrip(AMFArrayValue* arguments) {
|
||||
AddStripMessage addStripMessage(arguments);
|
||||
}
|
||||
|
||||
void ControlBehaviors::RemoveStrip(AMFArrayValue* arguments) {
|
||||
RemoveStripMessage removeStrip(arguments);
|
||||
}
|
||||
|
||||
void ControlBehaviors::MergeStrips(AMFArrayValue* arguments) {
|
||||
MergeStripsMessage mergeStripsMessage(arguments);
|
||||
}
|
||||
|
||||
void ControlBehaviors::SplitStrip(AMFArrayValue* arguments) {
|
||||
SplitStripMessage splitStripMessage(arguments);
|
||||
}
|
||||
|
||||
void ControlBehaviors::UpdateStripUI(AMFArrayValue* arguments) {
|
||||
UpdateStripUiMessage updateStripUiMessage(arguments);
|
||||
}
|
||||
|
||||
void ControlBehaviors::AddAction(AMFArrayValue* arguments) {
|
||||
AddActionMessage addActionMessage(arguments);
|
||||
}
|
||||
|
||||
void ControlBehaviors::MigrateActions(AMFArrayValue* arguments) {
|
||||
MigrateActionsMessage migrateActionsMessage(arguments);
|
||||
}
|
||||
|
||||
void ControlBehaviors::RearrangeStrip(AMFArrayValue* arguments) {
|
||||
RearrangeStripMessage rearrangeStripMessage(arguments);
|
||||
}
|
||||
|
||||
void ControlBehaviors::Add(AMFArrayValue* arguments) {
|
||||
AddMessage addMessage(arguments);
|
||||
}
|
||||
|
||||
void ControlBehaviors::RemoveActions(AMFArrayValue* arguments) {
|
||||
RemoveActionsMessage removeActionsMessage(arguments);
|
||||
}
|
||||
|
||||
void ControlBehaviors::Rename(Entity* modelEntity, const SystemAddress& sysAddr, Entity* modelOwner, AMFArrayValue* arguments) {
|
||||
RenameMessage renameMessage(arguments);
|
||||
GameMessages::SendUIMessageServerToSingleClient(context.modelOwner, context.modelOwner->GetSystemAddress(), "UpdateBehaviorList", behaviorsToSerialize);
|
||||
}
|
||||
|
||||
// TODO This is also supposed to serialize the state of the behaviors in progress but those aren't implemented yet
|
||||
void ControlBehaviors::SendBehaviorBlocksToClient(ModelComponent* modelComponent, const SystemAddress& sysAddr, Entity* modelOwner, AMFArrayValue* arguments) {
|
||||
// uint32_t behaviorID = ControlBehaviors::GetBehaviorIDFromArgument(arguments);
|
||||
void ControlBehaviors::SendBehaviorBlocksToClient(ControlBehaviorContext& context) {
|
||||
if (!context) return;
|
||||
BehaviorMessageBase behaviorMsg(context.arguments);
|
||||
|
||||
// auto modelBehavior = modelComponent->FindBehavior(behaviorID);
|
||||
|
||||
// if (!modelBehavior) return;
|
||||
|
||||
// modelBehavior->VerifyStates();
|
||||
|
||||
// auto states = modelBehavior->GetBehaviorStates();
|
||||
|
||||
// // Begin serialization.
|
||||
|
||||
// /**
|
||||
// * for each state
|
||||
// * strip id
|
||||
// * ui info
|
||||
// * x
|
||||
// * y
|
||||
// * actions
|
||||
// * action1
|
||||
// * action2
|
||||
// * ...
|
||||
// * behaviorID of strip
|
||||
// * objectID of strip
|
||||
// */
|
||||
// LWOOBJID targetObjectID = LWOOBJID_EMPTY;
|
||||
// behaviorID = 0;
|
||||
// AMFArrayValue behaviorInfo;
|
||||
|
||||
// AMFArrayValue* stateSerialize = new AMFArrayValue();
|
||||
|
||||
// for (auto it = states.begin(); it != states.end(); it++) {
|
||||
// LOG("Begin serialization of state %i!\n", it->first);
|
||||
// AMFArrayValue* state = new AMFArrayValue();
|
||||
|
||||
// AMFDoubleValue* stateAsDouble = new AMFDoubleValue();
|
||||
// stateAsDouble->SetValue(it->first);
|
||||
// state->InsertValue("id", stateAsDouble);
|
||||
|
||||
// AMFArrayValue* strips = new AMFArrayValue();
|
||||
// auto stripsInState = it->second->GetStrips();
|
||||
// for (auto strip = stripsInState.begin(); strip != stripsInState.end(); strip++) {
|
||||
// LOG("Begin serialization of strip %i!\n", strip->first);
|
||||
// AMFArrayValue* thisStrip = new AMFArrayValue();
|
||||
|
||||
// AMFDoubleValue* stripID = new AMFDoubleValue();
|
||||
// stripID->SetValue(strip->first);
|
||||
// thisStrip->InsertValue("id", stripID);
|
||||
|
||||
// AMFArrayValue* uiArray = new AMFArrayValue();
|
||||
// AMFDoubleValue* yPosition = new AMFDoubleValue();
|
||||
// yPosition->SetValue(strip->second->GetYPosition());
|
||||
// uiArray->InsertValue("y", yPosition);
|
||||
|
||||
// AMFDoubleValue* xPosition = new AMFDoubleValue();
|
||||
// xPosition->SetValue(strip->second->GetXPosition());
|
||||
// uiArray->InsertValue("x", xPosition);
|
||||
|
||||
// thisStrip->InsertValue("ui", uiArray);
|
||||
// targetObjectID = modelComponent->GetParent()->GetObjectID();
|
||||
// behaviorID = modelBehavior->GetBehaviorID();
|
||||
|
||||
// AMFArrayValue* stripSerialize = new AMFArrayValue();
|
||||
// for (auto behaviorAction : strip->second->GetActions()) {
|
||||
// LOG("Begin serialization of action %s!\n", behaviorAction->actionName.c_str());
|
||||
// AMFArrayValue* thisAction = new AMFArrayValue();
|
||||
|
||||
// AMFStringValue* actionName = new AMFStringValue();
|
||||
// actionName->SetValue(behaviorAction->actionName);
|
||||
// thisAction->InsertValue("Type", actionName);
|
||||
|
||||
// if (behaviorAction->parameterValueString != "")
|
||||
// {
|
||||
// AMFStringValue* valueAsString = new AMFStringValue();
|
||||
// valueAsString->SetValue(behaviorAction->parameterValueString);
|
||||
// thisAction->InsertValue(behaviorAction->parameterName, valueAsString);
|
||||
// }
|
||||
// else if (behaviorAction->parameterValueDouble != 0.0)
|
||||
// {
|
||||
// AMFDoubleValue* valueAsDouble = new AMFDoubleValue();
|
||||
// valueAsDouble->SetValue(behaviorAction->parameterValueDouble);
|
||||
// thisAction->InsertValue(behaviorAction->parameterName, valueAsDouble);
|
||||
// }
|
||||
// stripSerialize->PushBackValue(thisAction);
|
||||
// }
|
||||
// thisStrip->InsertValue("actions", stripSerialize);
|
||||
// strips->PushBackValue(thisStrip);
|
||||
// }
|
||||
// state->InsertValue("strips", strips);
|
||||
// stateSerialize->PushBackValue(state);
|
||||
// }
|
||||
// behaviorInfo.InsertValue("states", stateSerialize);
|
||||
|
||||
// AMFStringValue* objectidAsString = new AMFStringValue();
|
||||
// objectidAsString->SetValue(std::to_string(targetObjectID));
|
||||
// behaviorInfo.InsertValue("objectID", objectidAsString);
|
||||
|
||||
// AMFStringValue* behaviorIDAsString = new AMFStringValue();
|
||||
// behaviorIDAsString->SetValue(std::to_string(behaviorID));
|
||||
// behaviorInfo.InsertValue("BehaviorID", behaviorIDAsString);
|
||||
|
||||
// GameMessages::SendUIMessageServerToSingleClient(modelOwner, sysAddr, "UpdateBehaviorBlocks", &behaviorInfo);
|
||||
context.modelComponent->VerifyBehaviors();
|
||||
AMFArrayValue behavior;
|
||||
context.modelComponent->SendBehaviorBlocksToClient(behaviorMsg.GetBehaviorId(), behavior);
|
||||
GameMessages::SendUIMessageServerToSingleClient(context.modelOwner, context.modelOwner->GetSystemAddress(), "UpdateBehaviorBlocks", behavior);
|
||||
}
|
||||
|
||||
void ControlBehaviors::UpdateAction(AMFArrayValue* arguments) {
|
||||
UpdateActionMessage updateActionMessage(arguments);
|
||||
auto* blockDefinition = GetBlockInfo(updateActionMessage.GetAction().GetType());
|
||||
auto blockDefinition = GetBlockInfo(updateActionMessage.GetAction().GetType());
|
||||
|
||||
if (!blockDefinition) {
|
||||
LOG("Received undefined block type %s. Ignoring.", updateActionMessage.GetAction().GetType().c_str());
|
||||
@ -266,75 +94,83 @@ void ControlBehaviors::UpdateAction(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;
|
||||
|
||||
args.Insert("visible", false);
|
||||
|
||||
GameMessages::SendUIMessageServerToSingleClient(modelOwner, modelOwner->GetParentUser()->GetSystemAddress(), "ToggleBehaviorEditor", args);
|
||||
|
||||
MoveToInventoryMessage moveToInventoryMessage(arguments);
|
||||
|
||||
SendBehaviorListToClient(modelComponent->GetParent(), sysAddr, modelOwner);
|
||||
}
|
||||
|
||||
void ControlBehaviors::ProcessCommand(Entity* modelEntity, const SystemAddress& sysAddr, AMFArrayValue* arguments, std::string command, Entity* modelOwner) {
|
||||
if (!isInitialized || !modelEntity || !modelOwner || !arguments) return;
|
||||
auto* modelComponent = modelEntity->GetComponent<ModelComponent>();
|
||||
|
||||
if (!modelComponent) return;
|
||||
|
||||
if (command == "sendBehaviorListToClient")
|
||||
SendBehaviorListToClient(modelEntity, sysAddr, modelOwner);
|
||||
else if (command == "modelTypeChanged")
|
||||
ModelTypeChanged(arguments, modelComponent);
|
||||
else if (command == "toggleExecutionUpdates")
|
||||
ToggleExecutionUpdates();
|
||||
else if (command == "addStrip")
|
||||
AddStrip(arguments);
|
||||
else if (command == "removeStrip")
|
||||
RemoveStrip(arguments);
|
||||
else if (command == "mergeStrips")
|
||||
MergeStrips(arguments);
|
||||
else if (command == "splitStrip")
|
||||
SplitStrip(arguments);
|
||||
else if (command == "updateStripUI")
|
||||
UpdateStripUI(arguments);
|
||||
else if (command == "addAction")
|
||||
AddAction(arguments);
|
||||
else if (command == "migrateActions")
|
||||
MigrateActions(arguments);
|
||||
else if (command == "rearrangeStrip")
|
||||
RearrangeStrip(arguments);
|
||||
else if (command == "add")
|
||||
Add(arguments);
|
||||
else if (command == "removeActions")
|
||||
RemoveActions(arguments);
|
||||
else if (command == "rename")
|
||||
Rename(modelEntity, sysAddr, modelOwner, arguments);
|
||||
else if (command == "sendBehaviorBlocksToClient")
|
||||
SendBehaviorBlocksToClient(modelComponent, sysAddr, modelOwner, arguments);
|
||||
else if (command == "moveToInventory")
|
||||
MoveToInventory(modelComponent, sysAddr, modelOwner, arguments);
|
||||
else if (command == "updateAction")
|
||||
UpdateAction(arguments);
|
||||
else
|
||||
LOG("Unknown behavior command (%s)\n", command.c_str());
|
||||
ControlBehaviorContext context(arguments, modelComponent, modelOwner);
|
||||
|
||||
if (command == "sendBehaviorListToClient") {
|
||||
SendBehaviorListToClient(context);
|
||||
} else if (command == "modelTypeChanged") {
|
||||
auto* modelType = arguments->Get<double>("ModelType");
|
||||
if (!modelType) return;
|
||||
|
||||
modelEntity->SetVar<int>(u"modelType", modelType->GetValue());
|
||||
} else if (command == "toggleExecutionUpdates") {
|
||||
// TODO
|
||||
} else if (command == "addStrip") {
|
||||
if (BehaviorMessageBase(context.arguments).IsDefaultBehaviorId()) RequestUpdatedID(context);
|
||||
|
||||
context.modelComponent->HandleControlBehaviorsMsg<AddStripMessage>(context.arguments);
|
||||
} else if (command == "removeStrip") {
|
||||
context.modelComponent->HandleControlBehaviorsMsg<RemoveStripMessage>(arguments);
|
||||
} else if (command == "mergeStrips") {
|
||||
context.modelComponent->HandleControlBehaviorsMsg<MergeStripsMessage>(arguments);
|
||||
} else if (command == "splitStrip") {
|
||||
context.modelComponent->HandleControlBehaviorsMsg<SplitStripMessage>(arguments);
|
||||
} else if (command == "updateStripUI") {
|
||||
context.modelComponent->HandleControlBehaviorsMsg<UpdateStripUiMessage>(arguments);
|
||||
} else if (command == "addAction") {
|
||||
context.modelComponent->HandleControlBehaviorsMsg<AddActionMessage>(arguments);
|
||||
} else if (command == "migrateActions") {
|
||||
context.modelComponent->HandleControlBehaviorsMsg<MigrateActionsMessage>(arguments);
|
||||
} else if (command == "rearrangeStrip") {
|
||||
context.modelComponent->HandleControlBehaviorsMsg<RearrangeStripMessage>(arguments);
|
||||
} else if (command == "add") {
|
||||
AddMessage msg(context.arguments);
|
||||
context.modelComponent->AddBehavior(msg);
|
||||
SendBehaviorListToClient(context);
|
||||
} else if (command == "removeActions") {
|
||||
context.modelComponent->HandleControlBehaviorsMsg<RemoveActionsMessage>(arguments);
|
||||
} else if (command == "rename") {
|
||||
context.modelComponent->HandleControlBehaviorsMsg<RenameMessage>(arguments);
|
||||
|
||||
// Send the list back to the client so the name is updated.
|
||||
SendBehaviorListToClient(context);
|
||||
} else if (command == "sendBehaviorBlocksToClient") {
|
||||
SendBehaviorBlocksToClient(context);
|
||||
} else if (command == "moveToInventory") {
|
||||
MoveToInventoryMessage msg(arguments);
|
||||
context.modelComponent->MoveToInventory(msg);
|
||||
|
||||
AMFArrayValue args;
|
||||
args.Insert("BehaviorID", std::to_string(msg.GetBehaviorId()));
|
||||
GameMessages::SendUIMessageServerToSingleClient(modelOwner, modelOwner->GetParentUser()->GetSystemAddress(), "BehaviorRemoved", args);
|
||||
|
||||
SendBehaviorListToClient(context);
|
||||
} else if (command == "updateAction") {
|
||||
context.modelComponent->HandleControlBehaviorsMsg<UpdateActionMessage>(arguments);
|
||||
} else {
|
||||
LOG("Unknown behavior command (%s)", command.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
ControlBehaviors::ControlBehaviors() {
|
||||
auto blocksBuffer = Game::assetManager->GetFile("ui\\ingame\\blocksdef.xml");
|
||||
if (!blocksBuffer) {
|
||||
LOG("Failed to open blocksdef.xml");
|
||||
LOG("Failed to open blocksdef.xml, property behaviors will be disabled for this zone! "
|
||||
"(This is a necessary file for cheat detection and ensuring we do not send unexpected values to the client)");
|
||||
return;
|
||||
}
|
||||
|
||||
tinyxml2::XMLDocument m_Doc;
|
||||
|
||||
std::string read{};
|
||||
std::string read;
|
||||
|
||||
std::string buffer{};
|
||||
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.
|
||||
@ -371,14 +207,14 @@ ControlBehaviors::ControlBehaviors() {
|
||||
while (block) {
|
||||
blockName = block->Name();
|
||||
|
||||
BlockDefinition* blockDefinition = new BlockDefinition();
|
||||
auto& blockDefinition = blockTypes[blockName];
|
||||
std::string name{};
|
||||
std::string typeName{};
|
||||
|
||||
auto* argument = block->FirstChildElement("Argument");
|
||||
if (argument) {
|
||||
auto* defaultDefinition = argument->FirstChildElement("DefaultValue");
|
||||
if (defaultDefinition) blockDefinition->SetDefaultValue(defaultDefinition->GetText());
|
||||
if (defaultDefinition) blockDefinition.SetDefaultValue(defaultDefinition->GetText());
|
||||
|
||||
auto* typeDefinition = argument->FirstChildElement("Type");
|
||||
if (typeDefinition) typeName = typeDefinition->GetText();
|
||||
@ -388,23 +224,23 @@ ControlBehaviors::ControlBehaviors() {
|
||||
|
||||
// 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
|
||||
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()));
|
||||
if (maximumDefinition) blockDefinition.SetMaximumValue(std::stof(maximumDefinition->GetText()));
|
||||
|
||||
auto* minimumDefinition = argument->FirstChildElement("Minimum");
|
||||
if (minimumDefinition) blockDefinition->SetMinimumValue(std::stof(minimumDefinition->GetText()));
|
||||
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);
|
||||
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
|
||||
blockDefinition.SetMaximumValue(blockDefinition.GetMaximumValue() - 1); // Maximum value is 0 indexed
|
||||
} else {
|
||||
values = argument->FirstChildElement("EnumerationSource");
|
||||
if (!values) {
|
||||
@ -421,8 +257,8 @@ ControlBehaviors::ControlBehaviors() {
|
||||
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");
|
||||
blockDefinition.SetMaximumValue(res.getIntField("countSounds"));
|
||||
blockDefinition.SetDefaultValue("0");
|
||||
} else {
|
||||
LOG("Unsupported Enumeration ServiceType (%s)", serviceName.c_str());
|
||||
continue;
|
||||
@ -433,19 +269,18 @@ ControlBehaviors::ControlBehaviors() {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
blockTypes.insert(std::make_pair(blockName, blockDefinition));
|
||||
block = block->NextSiblingElement();
|
||||
}
|
||||
blockSections = blockSections->NextSiblingElement();
|
||||
}
|
||||
isInitialized = true;
|
||||
LOG_DEBUG("Created all base block classes");
|
||||
for (auto b : blockTypes) {
|
||||
LOG_DEBUG("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());
|
||||
for (auto& [name, block] : blockTypes) {
|
||||
LOG_DEBUG("block name is %s default %s min %f max %f", name.c_str(), block.GetDefaultValue().c_str(), block.GetMinimumValue(), block.GetMaximumValue());
|
||||
}
|
||||
}
|
||||
|
||||
BlockDefinition* ControlBehaviors::GetBlockInfo(const BlockName& blockName) {
|
||||
std::optional<BlockDefinition> ControlBehaviors::GetBlockInfo(const BlockName& blockName) {
|
||||
auto blockDefinition = blockTypes.find(blockName);
|
||||
return blockDefinition != blockTypes.end() ? blockDefinition->second : nullptr;
|
||||
return blockDefinition != blockTypes.end() ? std::optional(blockDefinition->second) : std::nullopt;
|
||||
}
|
||||
|
@ -4,12 +4,13 @@
|
||||
#define __CONTROLBEHAVIORS__H__
|
||||
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "BlockDefinition.h"
|
||||
#include "Singleton.h"
|
||||
|
||||
class AMFArrayValue;
|
||||
class BlockDefinition;
|
||||
class Entity;
|
||||
class ModelComponent;
|
||||
class SystemAddress;
|
||||
@ -17,6 +18,18 @@ class SystemAddress;
|
||||
// Type definition to clarify what is used where
|
||||
typedef std::string BlockName; //! A block name
|
||||
|
||||
struct ControlBehaviorContext {
|
||||
ControlBehaviorContext(AMFArrayValue* args, ModelComponent* modelComponent, Entity* modelOwner) : arguments(args), modelComponent(modelComponent), modelOwner(modelOwner) {};
|
||||
|
||||
operator bool() const {
|
||||
return arguments != nullptr && modelComponent != nullptr && modelOwner != nullptr;
|
||||
}
|
||||
|
||||
AMFArrayValue* arguments;
|
||||
Entity* modelOwner;
|
||||
ModelComponent* modelComponent;
|
||||
};
|
||||
|
||||
class ControlBehaviors: public Singleton<ControlBehaviors> {
|
||||
public:
|
||||
ControlBehaviors();
|
||||
@ -39,27 +52,13 @@ public:
|
||||
*
|
||||
* @return A pair of the block parameter name to its typing
|
||||
*/
|
||||
BlockDefinition* GetBlockInfo(const BlockName& blockName);
|
||||
std::optional<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 RequestUpdatedID(ControlBehaviorContext& context);
|
||||
void SendBehaviorListToClient(const ControlBehaviorContext& context);
|
||||
void SendBehaviorBlocksToClient(ControlBehaviorContext& context);
|
||||
void UpdateAction(AMFArrayValue* arguments);
|
||||
void MoveToInventory(ModelComponent* modelComponent, const SystemAddress& sysAddr, Entity* modelOwner, AMFArrayValue* arguments);
|
||||
std::map<BlockName, BlockDefinition*> blockTypes{};
|
||||
std::map<BlockName, BlockDefinition> blockTypes{};
|
||||
|
||||
// If false, property behaviors will not be able to be edited.
|
||||
bool isInitialized = false;
|
||||
|
131
dGame/dPropertyBehaviors/PropertyBehavior.cpp
Normal file
131
dGame/dPropertyBehaviors/PropertyBehavior.cpp
Normal file
@ -0,0 +1,131 @@
|
||||
#include "PropertyBehavior.h"
|
||||
|
||||
#include "Amf3.h"
|
||||
#include "BehaviorStates.h"
|
||||
#include "ControlBehaviorMsgs.h"
|
||||
|
||||
PropertyBehavior::PropertyBehavior() {
|
||||
m_LastEditedState = BehaviorState::HOME_STATE;
|
||||
}
|
||||
|
||||
template<>
|
||||
void PropertyBehavior::HandleMsg(AddStripMessage& msg) {
|
||||
m_States[msg.GetActionContext().GetStateId()].HandleMsg(msg);
|
||||
m_LastEditedState = msg.GetActionContext().GetStateId();
|
||||
};
|
||||
|
||||
template<>
|
||||
void PropertyBehavior::HandleMsg(AddActionMessage& msg) {
|
||||
m_States[msg.GetActionContext().GetStateId()].HandleMsg(msg);
|
||||
m_LastEditedState = msg.GetActionContext().GetStateId();
|
||||
};
|
||||
|
||||
template<>
|
||||
void PropertyBehavior::HandleMsg(RearrangeStripMessage& msg) {
|
||||
m_States[msg.GetActionContext().GetStateId()].HandleMsg(msg);
|
||||
m_LastEditedState = msg.GetActionContext().GetStateId();
|
||||
};
|
||||
|
||||
template<>
|
||||
void PropertyBehavior::HandleMsg(UpdateActionMessage& msg) {
|
||||
m_States[msg.GetActionContext().GetStateId()].HandleMsg(msg);
|
||||
m_LastEditedState = msg.GetActionContext().GetStateId();
|
||||
};
|
||||
|
||||
template<>
|
||||
void PropertyBehavior::HandleMsg(UpdateStripUiMessage& msg) {
|
||||
m_States[msg.GetActionContext().GetStateId()].HandleMsg(msg);
|
||||
m_LastEditedState = msg.GetActionContext().GetStateId();
|
||||
};
|
||||
|
||||
template<>
|
||||
void PropertyBehavior::HandleMsg(RemoveStripMessage& msg) {
|
||||
m_States[msg.GetActionContext().GetStateId()].HandleMsg(msg);
|
||||
m_LastEditedState = msg.GetActionContext().GetStateId();
|
||||
};
|
||||
|
||||
template<>
|
||||
void PropertyBehavior::HandleMsg(RemoveActionsMessage& msg) {
|
||||
m_States[msg.GetActionContext().GetStateId()].HandleMsg(msg);
|
||||
m_LastEditedState = msg.GetActionContext().GetStateId();
|
||||
};
|
||||
|
||||
template<>
|
||||
void PropertyBehavior::HandleMsg(SplitStripMessage& msg) {
|
||||
m_States[msg.GetSourceActionContext().GetStateId()].HandleMsg(msg);
|
||||
m_States[msg.GetDestinationActionContext().GetStateId()].HandleMsg(msg);
|
||||
m_LastEditedState = msg.GetDestinationActionContext().GetStateId();
|
||||
};
|
||||
|
||||
template<>
|
||||
void PropertyBehavior::HandleMsg(MigrateActionsMessage& msg) {
|
||||
m_States[msg.GetSourceActionContext().GetStateId()].HandleMsg(msg);
|
||||
m_States[msg.GetDestinationActionContext().GetStateId()].HandleMsg(msg);
|
||||
m_LastEditedState = msg.GetDestinationActionContext().GetStateId();
|
||||
};
|
||||
|
||||
template<>
|
||||
void PropertyBehavior::HandleMsg(MergeStripsMessage& msg) {
|
||||
m_States[msg.GetSourceActionContext().GetStateId()].HandleMsg(msg);
|
||||
m_States[msg.GetDestinationActionContext().GetStateId()].HandleMsg(msg);
|
||||
m_LastEditedState = msg.GetDestinationActionContext().GetStateId();
|
||||
};
|
||||
|
||||
template<>
|
||||
void PropertyBehavior::HandleMsg(RenameMessage& msg) {
|
||||
m_Name = msg.GetName();
|
||||
};
|
||||
|
||||
template<>
|
||||
void PropertyBehavior::HandleMsg(AddMessage& msg) {
|
||||
// TODO Parse the corresponding behavior xml file.
|
||||
m_BehaviorId = msg.GetBehaviorId();
|
||||
isLoot = m_BehaviorId != 7965;
|
||||
};
|
||||
|
||||
void PropertyBehavior::SetBehaviorId(int32_t behaviorId) {
|
||||
m_BehaviorId = behaviorId;
|
||||
}
|
||||
|
||||
void PropertyBehavior::SendBehaviorListToClient(AMFArrayValue& args) const {
|
||||
args.Insert("id", std::to_string(m_BehaviorId));
|
||||
args.Insert("name", m_Name);
|
||||
args.Insert("isLocked", isLocked);
|
||||
args.Insert("isLoot", isLoot);
|
||||
}
|
||||
|
||||
void PropertyBehavior::VerifyLastEditedState() {
|
||||
if (!m_States[m_LastEditedState].IsEmpty()) return;
|
||||
|
||||
for (const auto& [stateId, state] : m_States) {
|
||||
if (state.IsEmpty()) continue;
|
||||
|
||||
LOG_DEBUG("Updating last edited state to %i because %i is empty.", stateId, m_LastEditedState);
|
||||
m_LastEditedState = stateId;
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_DEBUG("No states found, sending default state");
|
||||
|
||||
m_LastEditedState = BehaviorState::HOME_STATE;
|
||||
}
|
||||
|
||||
void PropertyBehavior::SendBehaviorBlocksToClient(AMFArrayValue& args) const {
|
||||
auto* stateArray = args.InsertArray("states");
|
||||
|
||||
auto lastState = BehaviorState::HOME_STATE;
|
||||
for (auto& [stateId, state] : m_States) {
|
||||
if (state.IsEmpty()) continue;
|
||||
|
||||
LOG_DEBUG("Serializing state %i", stateId);
|
||||
auto* stateArgs = stateArray->PushArray();
|
||||
stateArgs->Insert("id", static_cast<double>(stateId));
|
||||
state.SendBehaviorBlocksToClient(*stateArgs);
|
||||
}
|
||||
|
||||
auto* executionState = args.InsertArray("executionState");
|
||||
executionState->Insert("stateID", static_cast<double>(m_LastEditedState));
|
||||
executionState->InsertArray("strips");
|
||||
|
||||
// TODO Serialize the execution state of the behavior
|
||||
}
|
49
dGame/dPropertyBehaviors/PropertyBehavior.h
Normal file
49
dGame/dPropertyBehaviors/PropertyBehavior.h
Normal file
@ -0,0 +1,49 @@
|
||||
#ifndef __PROPERTYBEHAVIOR__H__
|
||||
#define __PROPERTYBEHAVIOR__H__
|
||||
|
||||
#include "State.h"
|
||||
|
||||
enum class BehaviorState : uint32_t;
|
||||
|
||||
class AMFArrayValue;
|
||||
|
||||
/**
|
||||
* Represents the Entity of a Property Behavior and holds data associated with the behavior
|
||||
*/
|
||||
class PropertyBehavior {
|
||||
public:
|
||||
PropertyBehavior();
|
||||
template<typename Msg>
|
||||
void HandleMsg(Msg& msg);
|
||||
|
||||
// If the last edited state has no strips, this method will set the last edited state to the first state that has strips.
|
||||
void VerifyLastEditedState();
|
||||
void SendBehaviorListToClient(AMFArrayValue& args) const;
|
||||
void SendBehaviorBlocksToClient(AMFArrayValue& args) const;
|
||||
|
||||
int32_t GetBehaviorId() const { return m_BehaviorId; }
|
||||
void SetBehaviorId(int32_t id);
|
||||
private:
|
||||
|
||||
// The states this behavior has.
|
||||
std::map<BehaviorState, State> m_States;
|
||||
|
||||
// The name of this behavior.
|
||||
std::string m_Name = "New Behavior";
|
||||
|
||||
// Whether this behavior is locked and cannot be edited.
|
||||
bool isLocked = false;
|
||||
|
||||
// Whether this behavior is custom or pre-fab.
|
||||
bool isLoot = false;
|
||||
|
||||
// The last state that was edited. This is used so when the client re-opens the behavior editor, it will open to the last edited state.
|
||||
// If the last edited state has no strips, it will open to the first state that has strips.
|
||||
BehaviorState m_LastEditedState;
|
||||
|
||||
// The behavior id for this behavior. This is expected to be fully unique, however an id of -1 means this behavior was just created
|
||||
// and needs to be assigned an id.
|
||||
int32_t m_BehaviorId = -1;
|
||||
};
|
||||
|
||||
#endif //!__PROPERTYBEHAVIOR__H__
|
137
dGame/dPropertyBehaviors/State.cpp
Normal file
137
dGame/dPropertyBehaviors/State.cpp
Normal file
@ -0,0 +1,137 @@
|
||||
#include "State.h"
|
||||
|
||||
#include "Amf3.h"
|
||||
#include "ControlBehaviorMsgs.h"
|
||||
|
||||
template<>
|
||||
void State::HandleMsg(AddStripMessage& msg) {
|
||||
if (m_Strips.size() <= msg.GetActionContext().GetStripId()) {
|
||||
m_Strips.resize(msg.GetActionContext().GetStripId() + 1);
|
||||
}
|
||||
m_Strips.at(msg.GetActionContext().GetStripId()).HandleMsg(msg);
|
||||
};
|
||||
|
||||
template<>
|
||||
void State::HandleMsg(AddActionMessage& msg) {
|
||||
if (m_Strips.size() <= msg.GetActionContext().GetStripId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_Strips.at(msg.GetActionContext().GetStripId()).HandleMsg(msg);
|
||||
};
|
||||
|
||||
template<>
|
||||
void State::HandleMsg(UpdateStripUiMessage& msg) {
|
||||
if (m_Strips.size() <= msg.GetActionContext().GetStripId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_Strips.at(msg.GetActionContext().GetStripId()).HandleMsg(msg);
|
||||
};
|
||||
|
||||
template<>
|
||||
void State::HandleMsg(RemoveActionsMessage& msg) {
|
||||
if (m_Strips.size() <= msg.GetActionContext().GetStripId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_Strips.at(msg.GetActionContext().GetStripId()).HandleMsg(msg);
|
||||
};
|
||||
|
||||
template<>
|
||||
void State::HandleMsg(RearrangeStripMessage& msg) {
|
||||
if (m_Strips.size() <= msg.GetActionContext().GetStripId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_Strips.at(msg.GetActionContext().GetStripId()).HandleMsg(msg);
|
||||
};
|
||||
|
||||
template<>
|
||||
void State::HandleMsg(UpdateActionMessage& msg) {
|
||||
if (m_Strips.size() <= msg.GetActionContext().GetStripId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_Strips.at(msg.GetActionContext().GetStripId()).HandleMsg(msg);
|
||||
};
|
||||
|
||||
template<>
|
||||
void State::HandleMsg(RemoveStripMessage& msg) {
|
||||
if (m_Strips.size() <= msg.GetActionContext().GetStripId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_Strips.at(msg.GetActionContext().GetStripId()).HandleMsg(msg);
|
||||
};
|
||||
|
||||
template<>
|
||||
void State::HandleMsg(SplitStripMessage& msg) {
|
||||
if (msg.GetTransferredActions().empty()) {
|
||||
if (m_Strips.size() <= msg.GetSourceActionContext().GetStripId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_Strips.at(msg.GetSourceActionContext().GetStripId()).HandleMsg(msg);
|
||||
} else {
|
||||
if (m_Strips.size() <= msg.GetDestinationActionContext().GetStripId()) {
|
||||
m_Strips.resize(msg.GetDestinationActionContext().GetStripId() + 1);
|
||||
}
|
||||
|
||||
m_Strips.at(msg.GetDestinationActionContext().GetStripId()).HandleMsg(msg);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
void State::HandleMsg(MergeStripsMessage& msg) {
|
||||
if (msg.GetMigratedActions().empty()) {
|
||||
if (m_Strips.size() <= msg.GetSourceActionContext().GetStripId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_Strips.at(msg.GetSourceActionContext().GetStripId()).HandleMsg(msg);
|
||||
} else {
|
||||
if (m_Strips.size() <= msg.GetDestinationActionContext().GetStripId()) {
|
||||
m_Strips.resize(msg.GetDestinationActionContext().GetStripId() + 1);
|
||||
}
|
||||
|
||||
m_Strips.at(msg.GetDestinationActionContext().GetStripId()).HandleMsg(msg);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
void State::HandleMsg(MigrateActionsMessage& msg) {
|
||||
if (msg.GetMigratedActions().empty()) {
|
||||
if (m_Strips.size() <= msg.GetSourceActionContext().GetStripId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_Strips.at(msg.GetSourceActionContext().GetStripId()).HandleMsg(msg);
|
||||
} else {
|
||||
if (m_Strips.size() <= msg.GetDestinationActionContext().GetStripId()) {
|
||||
m_Strips.resize(msg.GetDestinationActionContext().GetStripId() + 1);
|
||||
}
|
||||
|
||||
m_Strips.at(msg.GetDestinationActionContext().GetStripId()).HandleMsg(msg);
|
||||
}
|
||||
};
|
||||
|
||||
bool State::IsEmpty() const {
|
||||
for (auto& strip : m_Strips) {
|
||||
if (!strip.IsEmpty()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void State::SendBehaviorBlocksToClient(AMFArrayValue& args) const {
|
||||
auto* strips = args.InsertArray("strips");
|
||||
for (int32_t stripId = 0; stripId < m_Strips.size(); stripId++) {
|
||||
auto& strip = m_Strips.at(stripId);
|
||||
if (strip.IsEmpty()) continue;
|
||||
|
||||
auto* stripArgs = strips->PushArray();
|
||||
stripArgs->Insert("id", static_cast<double>(stripId));
|
||||
|
||||
strip.SendBehaviorBlocksToClient(*stripArgs);
|
||||
}
|
||||
};
|
19
dGame/dPropertyBehaviors/State.h
Normal file
19
dGame/dPropertyBehaviors/State.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef __STATE__H__
|
||||
#define __STATE__H__
|
||||
|
||||
#include "Strip.h"
|
||||
|
||||
class AMFArrayValue;
|
||||
|
||||
class State {
|
||||
public:
|
||||
template<typename Msg>
|
||||
void HandleMsg(Msg& msg);
|
||||
|
||||
void SendBehaviorBlocksToClient(AMFArrayValue& args) const;
|
||||
bool IsEmpty() const;
|
||||
private:
|
||||
std::vector<Strip> m_Strips;
|
||||
};
|
||||
|
||||
#endif //!__STATE__H__
|
87
dGame/dPropertyBehaviors/Strip.cpp
Normal file
87
dGame/dPropertyBehaviors/Strip.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
#include "Strip.h"
|
||||
|
||||
#include "Amf3.h"
|
||||
#include "ControlBehaviorMsgs.h"
|
||||
|
||||
template<>
|
||||
void Strip::HandleMsg(AddStripMessage& msg) {
|
||||
m_Actions = msg.GetActionsToAdd();
|
||||
m_Position = msg.GetPosition();
|
||||
};
|
||||
|
||||
template<>
|
||||
void Strip::HandleMsg(AddActionMessage& msg) {
|
||||
if (msg.GetActionIndex() == -1) return;
|
||||
|
||||
m_Actions.insert(m_Actions.begin() + msg.GetActionIndex(), msg.GetAction());
|
||||
};
|
||||
|
||||
template<>
|
||||
void Strip::HandleMsg(UpdateStripUiMessage& msg) {
|
||||
m_Position = msg.GetPosition();
|
||||
};
|
||||
|
||||
template<>
|
||||
void Strip::HandleMsg(RemoveStripMessage& msg) {
|
||||
m_Actions.clear();
|
||||
};
|
||||
|
||||
template<>
|
||||
void Strip::HandleMsg(RemoveActionsMessage& msg) {
|
||||
if (msg.GetActionIndex() >= m_Actions.size()) return;
|
||||
m_Actions.erase(m_Actions.begin() + msg.GetActionIndex(), m_Actions.end());
|
||||
};
|
||||
|
||||
template<>
|
||||
void Strip::HandleMsg(UpdateActionMessage& msg) {
|
||||
if (msg.GetActionIndex() >= m_Actions.size()) return;
|
||||
m_Actions.at(msg.GetActionIndex()) = msg.GetAction();
|
||||
};
|
||||
|
||||
template<>
|
||||
void Strip::HandleMsg(RearrangeStripMessage& msg) {
|
||||
if (msg.GetDstActionIndex() >= m_Actions.size() || msg.GetSrcActionIndex() >= m_Actions.size() || msg.GetSrcActionIndex() <= msg.GetDstActionIndex()) return;
|
||||
std::rotate(m_Actions.begin() + msg.GetDstActionIndex(), m_Actions.begin() + msg.GetSrcActionIndex(), m_Actions.end());
|
||||
};
|
||||
|
||||
template<>
|
||||
void Strip::HandleMsg(SplitStripMessage& msg) {
|
||||
if (msg.GetTransferredActions().empty() && !m_Actions.empty()) {
|
||||
auto startToMove = m_Actions.begin() + msg.GetSrcActionIndex();
|
||||
msg.SetTransferredActions(startToMove, m_Actions.end());
|
||||
m_Actions.erase(startToMove, m_Actions.end());
|
||||
} else {
|
||||
m_Actions = msg.GetTransferredActions();
|
||||
m_Position = msg.GetPosition();
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
void Strip::HandleMsg(MergeStripsMessage& msg) {
|
||||
if (msg.GetMigratedActions().empty() && !m_Actions.empty()) {
|
||||
msg.SetMigratedActions(m_Actions.begin(), m_Actions.end());
|
||||
m_Actions.erase(m_Actions.begin(), m_Actions.end());
|
||||
} else {
|
||||
m_Actions.insert(m_Actions.begin() + msg.GetDstActionIndex(), msg.GetMigratedActions().begin(), msg.GetMigratedActions().end());
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
void Strip::HandleMsg(MigrateActionsMessage& msg) {
|
||||
if (msg.GetMigratedActions().empty() && !m_Actions.empty()) {
|
||||
auto startToMove = m_Actions.begin() + msg.GetSrcActionIndex();
|
||||
msg.SetMigratedActions(startToMove, m_Actions.end());
|
||||
m_Actions.erase(startToMove, m_Actions.end());
|
||||
} else {
|
||||
m_Actions.insert(m_Actions.begin() + msg.GetDstActionIndex(), msg.GetMigratedActions().begin(), msg.GetMigratedActions().end());
|
||||
}
|
||||
};
|
||||
|
||||
void Strip::SendBehaviorBlocksToClient(AMFArrayValue& args) const {
|
||||
m_Position.SendBehaviorBlocksToClient(args);
|
||||
|
||||
auto* actions = args.InsertArray("actions");
|
||||
for (auto& action : m_Actions) {
|
||||
action.SendBehaviorBlocksToClient(*actions);
|
||||
}
|
||||
};
|
23
dGame/dPropertyBehaviors/Strip.h
Normal file
23
dGame/dPropertyBehaviors/Strip.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef __STRIP__H__
|
||||
#define __STRIP__H__
|
||||
|
||||
#include "Action.h"
|
||||
#include "StripUiPosition.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class AMFArrayValue;
|
||||
|
||||
class Strip {
|
||||
public:
|
||||
template<typename Msg>
|
||||
void HandleMsg(Msg& msg);
|
||||
|
||||
void SendBehaviorBlocksToClient(AMFArrayValue& args) const;
|
||||
bool IsEmpty() const { return m_Actions.empty(); }
|
||||
private:
|
||||
std::vector<Action> m_Actions;
|
||||
StripUiPosition m_Position;
|
||||
};
|
||||
|
||||
#endif //!__STRIP__H__
|
Loading…
Reference in New Issue
Block a user