Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: partially functioning property behavior ui (no saving or loading yet) #1384

Merged
merged 28 commits into from
Jan 3, 2024
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
1a4d9f9
Add addstrip handling
EmosewaMC Dec 27, 2023
cbcc868
fix crash
EmosewaMC Dec 27, 2023
a1f3261
Section off code
EmosewaMC Dec 27, 2023
3731836
Organize serialization
EmosewaMC Dec 27, 2023
b60582a
Remove and simplify BlockDefinitions
EmosewaMC Dec 27, 2023
06d4943
Merge branch 'main' into 803
EmosewaMC Dec 28, 2023
c416fcd
ControlBehaviors: Add addaction handling
EmosewaMC Dec 28, 2023
b2c7a1b
re-organization
EmosewaMC Dec 28, 2023
8061537
add strip ui position handling
EmosewaMC Dec 28, 2023
98ee7af
add split strip functionality
EmosewaMC Dec 28, 2023
ef1be80
fix issues
EmosewaMC Dec 28, 2023
dce88fc
update how you remove behaviors from models
EmosewaMC Dec 28, 2023
d39531f
Merge branch 'main' into 803
EmosewaMC Dec 30, 2023
a81ac97
Merge branch 'main' into 803
EmosewaMC Dec 31, 2023
f5e9f67
Add remove actions and rename
EmosewaMC Dec 31, 2023
65fe9de
migrate actions
EmosewaMC Dec 31, 2023
686bb13
update action and rearrange strip
EmosewaMC Dec 31, 2023
2adbad2
merge strips
EmosewaMC Dec 31, 2023
d32c48d
add and move to inventory
EmosewaMC Dec 31, 2023
e7f6e44
Remove dead code
EmosewaMC Dec 31, 2023
ff620fa
simplify code
EmosewaMC Jan 1, 2024
dc5b4da
Merge branch 'main' into 803
EmosewaMC Jan 3, 2024
e3a08a1
nits and move finish MoveToInventory
EmosewaMC Jan 3, 2024
0fe4a3c
Update ModelComponent.cpp
EmosewaMC Jan 3, 2024
5cc6f69
Update MigrateActionsMessage.h
EmosewaMC Jan 3, 2024
88fa58d
const
EmosewaMC Jan 3, 2024
5304bc2
Move to separate translation units
EmosewaMC Jan 3, 2024
2c23eeb
include amf3
EmosewaMC Jan 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions dGame/dComponents/ModelComponent.cpp
Original file line number Diff line number Diff line change
@@ -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();
Expand Down Expand Up @@ -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
}
72 changes: 72 additions & 0 deletions dGame/dComponents/ModelComponent.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
#pragma once

#include <map>

#include "dCommonVars.h"
#include "RakNetTypes.h"
#include "NiPoint3.h"
#include "NiQuaternion.h"
#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.
Expand Down Expand Up @@ -43,7 +54,68 @@ class ModelComponent : public Component {
*/
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
Expand Down
3 changes: 3 additions & 0 deletions dGame/dPropertyBehaviors/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
set(DGAME_DPROPERTYBEHAVIORS_SOURCES
"PropertyBehavior.cpp"
"State.cpp"
"Strip.cpp"
"BlockDefinition.cpp"
"ControlBehaviors.cpp"
)
Expand Down
33 changes: 24 additions & 9 deletions dGame/dPropertyBehaviors/ControlBehaviorMessages/Action.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "Action.h"
#include "Amf3.h"

Action::Action() {
type = "";
Expand All @@ -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);
}
}
14 changes: 9 additions & 5 deletions dGame/dPropertyBehaviors/ControlBehaviorMessages/Action.h
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@
#include "Amf3.h"
#include "dCommonVars.h"

#include "Game.h"
#include "Logger.h"

enum class BehaviorState : uint32_t;

/**
Expand All @@ -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__
Original file line number Diff line number Diff line change
@@ -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__
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef __MERGESTRIPSMESSAGE__H__
#define __MERGESTRIPSMESSAGE__H__

#include "Action.h"
#include "ActionContext.h"
#include "BehaviorMessageBase.h"

Expand All @@ -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__
Loading
Loading