diff --git a/code/components/citizen-server-impl/include/state/SyncTrees_Five.h b/code/components/citizen-server-impl/include/state/SyncTrees_Five.h index 612fc4b47e..eeaacc40ba 100644 --- a/code/components/citizen-server-impl/include/state/SyncTrees_Five.h +++ b/code/components/citizen-server-impl/include/state/SyncTrees_Five.h @@ -508,78 +508,105 @@ struct CVehicleScriptGameStateDataNode } }; -struct CEntityScriptInfoDataNode +struct CEntityScriptInfoDataNode : GenericSerializeDataNode { uint32_t m_scriptHash; uint32_t m_timestamp; + uint32_t m_positionHash; + uint32_t m_instanceId; + uint32_t m_scriptObjectId; + uint32_t m_hostToken; - bool Parse(SyncParseState& state) + template + bool Serialize(Serializer& s) { - auto hasScript = state.buffer.ReadBit(); + bool hasScript = m_scriptHash != 0; + s.Serialize(hasScript); - if (hasScript) // Has script info + if (hasScript) { - // deserialize CGameScriptObjInfo + // -> CGameScriptObjInfo - // -> CGameScriptId + { + // -> CGameScriptId - // ---> rage::scriptId - m_scriptHash = state.buffer.Read(32); - // ---> end + { + // -> rage::scriptId + s.Serialize(32, m_scriptHash); + } - m_timestamp = state.buffer.Read(32); + s.Serialize(32, m_timestamp); - if (state.buffer.ReadBit()) - { - auto positionHash = state.buffer.Read(32); - } + bool hasPositionHash = m_positionHash != 0; + s.Serialize(hasPositionHash); - if (state.buffer.ReadBit()) - { - auto instanceId = state.buffer.Read(7); - } + if (hasPositionHash) + { + s.Serialize(32, m_positionHash); + } + else if constexpr (Serializer::isReader) + { + m_positionHash = 0; + } + + bool hasInstanceId = m_instanceId != 0; + s.Serialize(hasInstanceId); - // -> end + if (hasInstanceId) + { + s.Serialize(8, m_instanceId); + } + else if constexpr (Serializer::isReader) + { + m_instanceId = 0; + } + } - auto scriptObjectId = state.buffer.Read(32); + s.Serialize(32, m_scriptObjectId); - auto hostTokenLength = state.buffer.ReadBit() ? 16 : 3; - auto hostToken = state.buffer.Read(hostTokenLength); + bool longHostToken = m_hostToken >= (1 << 3); + s.Serialize(longHostToken); - // end + auto hostTokenLength = longHostToken ? 16 : 3; + s.Serialize(hostTokenLength, m_hostToken); } - else + else if constexpr (Serializer::isReader) { m_scriptHash = 0; } return true; } +}; - bool Unparse(sync::SyncUnparseState& state) - { - rl::MessageBuffer& buffer = state.buffer; - - if (m_scriptHash) - { - buffer.WriteBit(true); - - buffer.Write(32, m_scriptHash); - buffer.Write(32, m_timestamp); +template<> +struct NodeProcessor +{ + uint32_t lastScriptId = 0; - buffer.WriteBit(false); - buffer.WriteBit(false); + bool PreParse(CEntityScriptInfoDataNode& node, SyncParseState& state) + { + lastScriptId = node.m_scriptHash; - buffer.Write(32, 12); + return false; + } - buffer.WriteBit(false); - buffer.Write(3, 0); - } - else + bool PostParse(CEntityScriptInfoDataNode& node, SyncParseState& state) + { + if (lastScriptId && !node.m_scriptHash) { - buffer.WriteBit(false); + if (state.entity && state.entity->IsOwnedByServerScript()) + { + node.m_scriptHash = lastScriptId; + return true; + } } + return false; + } + + constexpr bool IsHandled() + { return true; } }; diff --git a/code/components/citizen-server-impl/include/state/SyncTrees_Header.h b/code/components/citizen-server-impl/include/state/SyncTrees_Header.h index 5976957ce8..d958e268e1 100644 --- a/code/components/citizen-server-impl/include/state/SyncTrees_Header.h +++ b/code/components/citizen-server-impl/include/state/SyncTrees_Header.h @@ -2,6 +2,28 @@ namespace fx::sync { +template +inline constexpr bool AffectsBlender(); + +template +struct NodeProcessor +{ + bool PreParse(TNode& node, SyncParseState& state) + { + return false; + } + + bool PostParse(TNode& node, SyncParseState& state) + { + return false; + } + + constexpr bool IsHandled() + { + return false; + } +}; + template struct NodeIds { @@ -393,10 +415,39 @@ struct NodeWrapper : public NodeBase // parse manual data if constexpr (ShouldParseNode(0)) { - state.buffer.SetCurrentBit(endBit); - node.Parse(state); + NodeProcessor nodeProc; + + auto doParse = [this, &state, endBit, length]() + { + state.buffer.SetCurrentBit(endBit); + node.Parse(state); + + state.buffer.SetCurrentBit(endBit + length); + }; + + if constexpr (nodeProc.IsHandled()) + { + bool needReparse = nodeProc.PreParse(node, state); + + doParse(); + + needReparse |= nodeProc.PostParse(node, state); + + if (needReparse) + { + rl::MessageBuffer mb(data.size()); + sync::SyncUnparseState unparseState{ mb }; + node.Unparse(unparseState); + + memcpy(data.data(), mb.GetBuffer().data(), mb.GetBuffer().size()); - state.buffer.SetCurrentBit(endBit + length); + this->length = mb.GetCurrentBit(); + } + } + else + { + doParse(); + } } frameIndex = state.frameIndex; diff --git a/code/components/citizen-server-impl/src/state/ServerSetters.cpp b/code/components/citizen-server-impl/src/state/ServerSetters.cpp index 4426260c63..1849f68515 100644 --- a/code/components/citizen-server-impl/src/state/ServerSetters.cpp +++ b/code/components/citizen-server-impl/src/state/ServerSetters.cpp @@ -111,6 +111,8 @@ std::shared_ptr MakeAutomobile(uint32_t model, float posX, f { cdn.m_scriptHash = resourceHash; cdn.m_timestamp = msec().count(); + cdn.m_instanceId = 12; + cdn.m_scriptObjectId = 12; }); return tree; @@ -151,6 +153,8 @@ std::shared_ptr MakeVehicle(uint32_t model, float posX, floa { cdn.m_scriptHash = resourceHash; cdn.m_timestamp = msec().count(); + cdn.m_instanceId = 12; + cdn.m_scriptObjectId = 12; }); return tree; @@ -195,6 +199,8 @@ std::shared_ptr MakePed(uint32_t model, float posX, float po { cdn.m_scriptHash = resourceHash; cdn.m_timestamp = msec().count(); + cdn.m_instanceId = 12; + cdn.m_scriptObjectId = 12; }); return tree; @@ -235,6 +241,8 @@ std::shared_ptr MakeObject(uint32_t model, float posX, float { cdn.m_scriptHash = resourceHash; cdn.m_timestamp = msec().count(); + cdn.m_instanceId = 12; + cdn.m_scriptObjectId = 12; }); return tree;