diff options
author | Kae <80987908+Novaenia@users.noreply.github.com> | 2024-09-05 19:15:47 +1000 |
---|---|---|
committer | Kae <80987908+Novaenia@users.noreply.github.com> | 2024-09-11 15:19:17 +1000 |
commit | 37f3178d33ab77de064bcbf10b4b03ddb47cc979 (patch) | |
tree | 76e3b3ce2d8716577af98e2bbbc4a41021db5107 /source/core | |
parent | 90db1e0fbadaeb625691d3d0d13f5ae6ef057109 (diff) |
Network compatibility changes
Diffstat (limited to 'source/core')
-rw-r--r-- | source/core/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/core/StarDataStream.cpp | 7 | ||||
-rw-r--r-- | source/core/StarDataStream.hpp | 5 | ||||
-rw-r--r-- | source/core/StarDataStreamDevices.hpp | 4 | ||||
-rw-r--r-- | source/core/StarNetCompatibility.hpp | 41 | ||||
-rw-r--r-- | source/core/StarNetElement.cpp | 4 | ||||
-rw-r--r-- | source/core/StarNetElement.hpp | 30 | ||||
-rw-r--r-- | source/core/StarNetElementBasicFields.cpp | 4 | ||||
-rw-r--r-- | source/core/StarNetElementBasicFields.hpp | 23 | ||||
-rw-r--r-- | source/core/StarNetElementContainers.hpp | 45 | ||||
-rw-r--r-- | source/core/StarNetElementDynamicGroup.hpp | 40 | ||||
-rw-r--r-- | source/core/StarNetElementExt.hpp | 85 | ||||
-rw-r--r-- | source/core/StarNetElementFloatFields.hpp | 19 | ||||
-rw-r--r-- | source/core/StarNetElementGroup.cpp | 41 | ||||
-rw-r--r-- | source/core/StarNetElementGroup.hpp | 8 | ||||
-rw-r--r-- | source/core/StarNetElementSignal.hpp | 18 | ||||
-rw-r--r-- | source/core/StarNetElementSyncGroup.cpp | 20 | ||||
-rw-r--r-- | source/core/StarNetElementSyncGroup.hpp | 8 | ||||
-rw-r--r-- | source/core/StarNetElementTop.hpp | 48 |
19 files changed, 330 insertions, 122 deletions
diff --git a/source/core/CMakeLists.txt b/source/core/CMakeLists.txt index fb31fca..bb8bd22 100644 --- a/source/core/CMakeLists.txt +++ b/source/core/CMakeLists.txt @@ -70,10 +70,12 @@ SET (star_core_HEADERS StarMultiArray.hpp StarMultiArrayInterpolator.hpp StarMultiTable.hpp + StarNetCompatibility.hpp StarNetElement.hpp StarNetElementBasicFields.hpp StarNetElementContainers.hpp StarNetElementDynamicGroup.hpp + StarNetElementExt.hpp StarNetElementFloatFields.hpp StarNetElementGroup.hpp StarNetElementSignal.hpp diff --git a/source/core/StarDataStream.cpp b/source/core/StarDataStream.cpp index 18456b6..1224f54 100644 --- a/source/core/StarDataStream.cpp +++ b/source/core/StarDataStream.cpp @@ -35,6 +35,13 @@ void DataStream::setStreamCompatibilityVersion(unsigned streamCompatibilityVersi m_streamCompatibilityVersion = streamCompatibilityVersion; } +void DataStream::setStreamCompatibilityVersion(NetCompatibilityRules const& rules) { + if (rules.isLegacy) + m_streamCompatibilityVersion = 1; + else + m_streamCompatibilityVersion = CurrentStreamVersion; +} + ByteArray DataStream::readBytes(size_t len) { ByteArray ba; ba.resize(len); diff --git a/source/core/StarDataStream.hpp b/source/core/StarDataStream.hpp index 02cb922..abcbff4 100644 --- a/source/core/StarDataStream.hpp +++ b/source/core/StarDataStream.hpp @@ -1,6 +1,7 @@ #pragma once #include "StarString.hpp" +#include "StarNetCompatibility.hpp" namespace Star { @@ -12,7 +13,7 @@ public: DataStream(); virtual ~DataStream() = default; - static unsigned const CurrentStreamVersion = 1; + static unsigned const CurrentStreamVersion = 2; // DataStream defaults to big-endian order for all primitive types ByteOrder byteOrder() const; @@ -27,7 +28,7 @@ public: // changed for compatibility with older versions of DataStream serialization. unsigned streamCompatibilityVersion() const; void setStreamCompatibilityVersion(unsigned streamCompatibilityVersion); - + void setStreamCompatibilityVersion(NetCompatibilityRules const& rules); // Do direct reads and writes virtual void readData(char* data, size_t len) = 0; virtual void writeData(char const* data, size_t len) = 0; diff --git a/source/core/StarDataStreamDevices.hpp b/source/core/StarDataStreamDevices.hpp index 3f34a72..4452592 100644 --- a/source/core/StarDataStreamDevices.hpp +++ b/source/core/StarDataStreamDevices.hpp @@ -126,8 +126,8 @@ private: class DataStreamExternalBuffer : public DataStream { public: DataStreamExternalBuffer(); - explicit DataStreamExternalBuffer(ByteArray const& byteArray); - explicit DataStreamExternalBuffer(DataStreamBuffer const& buffer); + DataStreamExternalBuffer(ByteArray const& byteArray); + DataStreamExternalBuffer(DataStreamBuffer const& buffer); DataStreamExternalBuffer(DataStreamExternalBuffer const& buffer) = default; DataStreamExternalBuffer(char const* externalData, size_t len); diff --git a/source/core/StarNetCompatibility.hpp b/source/core/StarNetCompatibility.hpp new file mode 100644 index 0000000..730546e --- /dev/null +++ b/source/core/StarNetCompatibility.hpp @@ -0,0 +1,41 @@ +#pragma once +#include "StarDataStream.hpp" + +namespace Star { + + +enum class NetCompatibilityFilter { + None = 0, + Old = 1, + New = 2 +}; + +struct NetCompatibilityRules { + NetCompatibilityRules() = default; + NetCompatibilityRules(uint64_t) = delete; + NetCompatibilityRules(bool legacy); + + bool checkFilter(NetCompatibilityFilter const& filter) const; + + bool isLegacy = false; +}; + +inline NetCompatibilityRules::NetCompatibilityRules(bool legacy) : isLegacy(legacy) {} + +inline bool NetCompatibilityRules::checkFilter(NetCompatibilityFilter const& filter) const { + if (filter == NetCompatibilityFilter::None) + return true; + else if (isLegacy) + return filter == NetCompatibilityFilter::Old; + else + return filter == NetCompatibilityFilter::New; +} + +template <> +struct hash<NetCompatibilityRules> { + size_t operator()(NetCompatibilityRules const& s) const { + return s.isLegacy; + } +}; + +}
\ No newline at end of file diff --git a/source/core/StarNetElement.cpp b/source/core/StarNetElement.cpp index 914badd..343d45a 100644 --- a/source/core/StarNetElement.cpp +++ b/source/core/StarNetElement.cpp @@ -7,8 +7,8 @@ uint64_t NetElementVersion::current() const { return m_version; } -void NetElementVersion::increment() { - ++m_version; +uint64_t NetElementVersion::increment() { + return ++m_version; } void NetElement::enableNetInterpolation(float) {} diff --git a/source/core/StarNetElement.hpp b/source/core/StarNetElement.hpp index dd909b8..393dd3d 100644 --- a/source/core/StarNetElement.hpp +++ b/source/core/StarNetElement.hpp @@ -9,7 +9,7 @@ namespace Star { class NetElementVersion { public: uint64_t current() const; - void increment(); + uint64_t increment(); private: uint64_t m_version = 0; @@ -20,15 +20,15 @@ class NetElement { public: virtual ~NetElement() = default; - // A network of NetElements will have a shared monotinically increasing + // A network of NetElements will have a shared monotonically increasing // NetElementVersion. When elements are updated, they will mark the version // number at the time they are updated so that a delta can be constructed // that contains only changes since any past version. virtual void initNetVersion(NetElementVersion const* version = nullptr) = 0; // Full store / load of the entire element. - virtual void netStore(DataStream& ds) const = 0; - virtual void netLoad(DataStream& ds) = 0; + virtual void netStore(DataStream& ds, NetCompatibilityRules rules) const = 0; + virtual void netLoad(DataStream& ds, NetCompatibilityRules rules) = 0; // Enables interpolation mode. If interpolation mode is enabled, then // NetElements will delay presenting incoming delta data for the @@ -46,14 +46,32 @@ public: // the version at the time of the *last* call to writeDelta, + 1. If // fromVersion is 0, this will always write the full state. Should return // true if a delta was needed and was written to DataStream, false otherwise. - virtual bool writeNetDelta(DataStream& ds, uint64_t fromVersion) const = 0; + virtual bool writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules) const = 0; // Read a delta written by writeNetDelta. 'interpolationTime' is the time in // the future that data from this delta should be delayed and smoothed into, // if interpolation is enabled. - virtual void readNetDelta(DataStream& ds, float interpolationTime = 0.0) = 0; + virtual void readNetDelta(DataStream& ds, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) = 0; // When extrapolating, it is important to notify when a delta WOULD have been // received even if no deltas are produced, so no extrapolation takes place. virtual void blankNetDelta(float interpolationTime); + + NetCompatibilityFilter netCompatibilityFilter() const; + void setNetCompatibilityFilter(NetCompatibilityFilter netFilter); + bool checkWithRules(NetCompatibilityRules const& rules) const; +private: + NetCompatibilityFilter m_netCompatibilityFilter = NetCompatibilityFilter::None; }; +inline NetCompatibilityFilter NetElement::netCompatibilityFilter() const { + return m_netCompatibilityFilter; +} + +inline void NetElement::setNetCompatibilityFilter(NetCompatibilityFilter netFilter) { + m_netCompatibilityFilter = netFilter; +} + +inline bool NetElement::checkWithRules(NetCompatibilityRules const& rules) const { + return rules.checkFilter(m_netCompatibilityFilter); +} + } diff --git a/source/core/StarNetElementBasicFields.cpp b/source/core/StarNetElementBasicFields.cpp index bbb5c5b..618c4a6 100644 --- a/source/core/StarNetElementBasicFields.cpp +++ b/source/core/StarNetElementBasicFields.cpp @@ -49,8 +49,8 @@ void NetElementEvent::setIgnoreOccurrencesOnNetLoad(bool ignoreOccurrencesOnNetL m_ignoreOccurrencesOnNetLoad = ignoreOccurrencesOnNetLoad; } -void NetElementEvent::netLoad(DataStream& ds) { - NetElementUInt::netLoad(ds); +void NetElementEvent::netLoad(DataStream& ds, NetCompatibilityRules rules) { + NetElementUInt::netLoad(ds, rules); if (m_ignoreOccurrencesOnNetLoad) ignoreOccurrences(); } diff --git a/source/core/StarNetElementBasicFields.hpp b/source/core/StarNetElementBasicFields.hpp index 693c6c3..3b46cc0 100644 --- a/source/core/StarNetElementBasicFields.hpp +++ b/source/core/StarNetElementBasicFields.hpp @@ -38,11 +38,11 @@ public: void disableNetInterpolation() override; void tickNetInterpolation(float dt) override; - void netStore(DataStream& ds) const override; - void netLoad(DataStream& ds) override; + void netStore(DataStream& ds, NetCompatibilityRules rules = {}) const override; + void netLoad(DataStream& ds, NetCompatibilityRules rules) override; - bool writeNetDelta(DataStream& ds, uint64_t fromVersion) const override; - void readNetDelta(DataStream& ds, float interpolationTime = 0.0f) override; + bool writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules = {}) const override; + void readNetDelta(DataStream& ds, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override; protected: virtual void readData(DataStream& ds, T& t) const = 0; @@ -107,7 +107,7 @@ public: void ignoreOccurrences(); void setIgnoreOccurrencesOnNetLoad(bool ignoreOccurrencesOnNetLoad); - void netLoad(DataStream& ds) override; + void netLoad(DataStream& ds, NetCompatibilityRules rules) override; protected: void updated() override; @@ -211,7 +211,8 @@ void NetElementBasicField<T>::tickNetInterpolation(float dt) { } template <typename T> -void NetElementBasicField<T>::netStore(DataStream& ds) const { +void NetElementBasicField<T>::netStore(DataStream& ds, NetCompatibilityRules rules) const { + if (!checkWithRules(rules)) return; if (m_pendingInterpolatedValues && !m_pendingInterpolatedValues->empty()) writeData(ds, m_pendingInterpolatedValues->last().second); else @@ -219,7 +220,8 @@ void NetElementBasicField<T>::netStore(DataStream& ds) const { } template <typename T> -void NetElementBasicField<T>::netLoad(DataStream& ds) { +void NetElementBasicField<T>::netLoad(DataStream& ds, NetCompatibilityRules rules) { + if (!checkWithRules(rules)) return; readData(ds, m_value); m_latestUpdateVersion = m_netVersion ? m_netVersion->current() : 0; updated(); @@ -228,7 +230,8 @@ void NetElementBasicField<T>::netLoad(DataStream& ds) { } template <typename T> -bool NetElementBasicField<T>::writeNetDelta(DataStream& ds, uint64_t fromVersion) const { +bool NetElementBasicField<T>::writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules) const { + if (!checkWithRules(rules)) return false; if (m_latestUpdateVersion < fromVersion) return false; @@ -236,11 +239,13 @@ bool NetElementBasicField<T>::writeNetDelta(DataStream& ds, uint64_t fromVersion writeData(ds, m_pendingInterpolatedValues->last().second); else writeData(ds, m_value); + return true; } template <typename T> -void NetElementBasicField<T>::readNetDelta(DataStream& ds, float interpolationTime) { +void NetElementBasicField<T>::readNetDelta(DataStream& ds, float interpolationTime, NetCompatibilityRules rules) { + if (!checkWithRules(rules)) return; T t; readData(ds, t); m_latestUpdateVersion = m_netVersion ? m_netVersion->current() : 0; diff --git a/source/core/StarNetElementContainers.hpp b/source/core/StarNetElementContainers.hpp index 62cce86..2e16b30 100644 --- a/source/core/StarNetElementContainers.hpp +++ b/source/core/StarNetElementContainers.hpp @@ -26,11 +26,12 @@ public: void disableNetInterpolation() override; void tickNetInterpolation(float dt) override; - void netStore(DataStream& ds) const override; - void netLoad(DataStream& ds) override; + void netStore(DataStream& ds, NetCompatibilityRules rules = {}) const override; + void netLoad(DataStream& ds, NetCompatibilityRules rules) override; - bool writeNetDelta(DataStream& ds, uint64_t fromVersion) const override; - void readNetDelta(DataStream& ds, float interpolationTime = 0.0f) override; + bool shouldWriteNetDelta(uint64_t fromVersion, NetCompatibilityRules rules = {}) const; + bool writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules = {}) const override; + void readNetDelta(DataStream& ds, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override; mapped_type const& get(key_type const& key) const; mapped_type const* ptr(key_type const& key) const; @@ -77,6 +78,8 @@ public: template <typename MapType> void setContents(MapType const& values); + uint64_t changeDataLastVersion() const; + private: // If a delta is written from further back than this many steps, the delta // will fall back to a full serialization of the entire state. @@ -152,7 +155,8 @@ void NetElementMapWrapper<BaseMap>::tickNetInterpolation(float dt) { } template <typename BaseMap> -void NetElementMapWrapper<BaseMap>::netStore(DataStream& ds) const { +void NetElementMapWrapper<BaseMap>::netStore(DataStream& ds, NetCompatibilityRules rules) const { + if (!checkWithRules(rules)) return; ds.writeVlqU(BaseMap::size() + m_pendingChangeData.size()); for (auto const& pair : *this) writeChange(ds, SetChange{pair.first, pair.second}); @@ -162,7 +166,8 @@ void NetElementMapWrapper<BaseMap>::netStore(DataStream& ds) const { } template <typename BaseMap> -void NetElementMapWrapper<BaseMap>::netLoad(DataStream& ds) { +void NetElementMapWrapper<BaseMap>::netLoad(DataStream& ds, NetCompatibilityRules rules) { + if (!checkWithRules(rules)) return; m_changeData.clear(); m_changeDataLastVersion = m_netVersion ? m_netVersion->current() : 0; m_pendingChangeData.clear(); @@ -181,13 +186,27 @@ void NetElementMapWrapper<BaseMap>::netLoad(DataStream& ds) { } template <typename BaseMap> -bool NetElementMapWrapper<BaseMap>::writeNetDelta(DataStream& ds, uint64_t fromVersion) const { +bool NetElementMapWrapper<BaseMap>::shouldWriteNetDelta(uint64_t fromVersion, NetCompatibilityRules rules) const { + if (!checkWithRules(rules)) return false; + if (fromVersion < m_changeDataLastVersion) + return true; + + for (auto const& p : m_changeData) + if (p.first >= fromVersion) + return true; + + return false; +} + +template <typename BaseMap> +bool NetElementMapWrapper<BaseMap>::writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules) const { + if (!checkWithRules(rules)) return false; bool deltaWritten = false; if (fromVersion < m_changeDataLastVersion) { deltaWritten = true; ds.writeVlqU(1); - netStore(ds); + netStore(ds, rules); } else { for (auto const& p : m_changeData) { @@ -206,13 +225,14 @@ bool NetElementMapWrapper<BaseMap>::writeNetDelta(DataStream& ds, uint64_t fromV } template <typename BaseMap> -void NetElementMapWrapper<BaseMap>::readNetDelta(DataStream& ds, float interpolationTime) { +void NetElementMapWrapper<BaseMap>::readNetDelta(DataStream& ds, float interpolationTime, NetCompatibilityRules rules) { + if (!checkWithRules(rules)) return; while (true) { uint64_t code = ds.readVlqU(); if (code == 0) { break; } else if (code == 1) { - netLoad(ds); + netLoad(ds, rules); } else if (code == 2) { auto change = readChange(ds); addChangeData(change); @@ -382,6 +402,11 @@ void NetElementMapWrapper<BaseMap>::setContents(MapType const& values) { } template <typename BaseMap> +uint64_t NetElementMapWrapper<BaseMap>::changeDataLastVersion() const { + return m_changeDataLastVersion; +} + +template <typename BaseMap> void NetElementMapWrapper<BaseMap>::writeChange(DataStream& ds, ElementChange const& change) { if (auto sc = change.template ptr<SetChange>()) { ds.write<uint8_t>(0); diff --git a/source/core/StarNetElementDynamicGroup.hpp b/source/core/StarNetElementDynamicGroup.hpp index 4f3a2d3..dbd0c12 100644 --- a/source/core/StarNetElementDynamicGroup.hpp +++ b/source/core/StarNetElementDynamicGroup.hpp @@ -45,11 +45,11 @@ public: void disableNetInterpolation() override; void tickNetInterpolation(float dt) override; - void netStore(DataStream& ds) const override; - void netLoad(DataStream& ds) override; + void netStore(DataStream& ds, NetCompatibilityRules rules = {}) const override; + void netLoad(DataStream& ds, NetCompatibilityRules rules) override; - bool writeNetDelta(DataStream& ds, uint64_t fromVersion) const override; - void readNetDelta(DataStream& ds, float interpolationTime = 0.0f) override; + bool writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules = {}) const override; + void readNetDelta(DataStream& ds, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override; void blankNetDelta(float interpolationTime = 0.0f) override; private: @@ -89,7 +89,7 @@ template <typename Element> auto NetElementDynamicGroup<Element>::addNetElement(ElementPtr element) -> ElementId { readyElement(element); DataStreamBuffer storeBuffer; - element->netStore(storeBuffer); + element->netStore(storeBuffer, {}); auto id = m_idMap.add(std::move(element)); addChangeData(ElementAddition(id, storeBuffer.takeData())); @@ -134,7 +134,7 @@ void NetElementDynamicGroup<Element>::initNetVersion(NetElementVersion const* ve for (auto& pair : m_idMap) { pair.second->initNetVersion(m_netVersion); DataStreamBuffer storeBuffer; - pair.second->netStore(storeBuffer); + pair.second->netStore(storeBuffer, {}); addChangeData(ElementAddition(pair.first, storeBuffer.takeData())); } } @@ -162,19 +162,22 @@ void NetElementDynamicGroup<Element>::tickNetInterpolation(float dt) { } template <typename Element> -void NetElementDynamicGroup<Element>::netStore(DataStream& ds) const { +void NetElementDynamicGroup<Element>::netStore(DataStream& ds, NetCompatibilityRules rules) const { + if (!checkWithRules(rules)) return; ds.writeVlqU(m_idMap.size()); + m_buffer.setStreamCompatibilityVersion(rules); for (auto& pair : m_idMap) { ds.writeVlqU(pair.first); - pair.second->netStore(m_buffer); + pair.second->netStore(m_buffer, rules); ds.write(m_buffer.data()); m_buffer.clear(); } } template <typename Element> -void NetElementDynamicGroup<Element>::netLoad(DataStream& ds) { +void NetElementDynamicGroup<Element>::netLoad(DataStream& ds, NetCompatibilityRules rules) { + if (!checkWithRules(rules)) return; m_changeData.clear(); m_changeDataLastVersion = m_netVersion ? m_netVersion->current() : 0; m_idMap.clear(); @@ -188,7 +191,7 @@ void NetElementDynamicGroup<Element>::netLoad(DataStream& ds) { DataStreamBuffer storeBuffer(ds.read<ByteArray>()); ElementPtr element = make_shared<Element>(); - element->netLoad(storeBuffer); + element->netLoad(storeBuffer, rules); readyElement(element); m_idMap.add(id, std::move(element)); @@ -197,10 +200,11 @@ void NetElementDynamicGroup<Element>::netLoad(DataStream& ds) { } template <typename Element> -bool NetElementDynamicGroup<Element>::writeNetDelta(DataStream& ds, uint64_t fromVersion) const { +bool NetElementDynamicGroup<Element>::writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules) const { + if (!checkWithRules(rules)) return false; if (fromVersion < m_changeDataLastVersion) { ds.write<bool>(true); - netStore(ds); + netStore(ds, rules); return true; } else { @@ -220,8 +224,9 @@ bool NetElementDynamicGroup<Element>::writeNetDelta(DataStream& ds, uint64_t fro } } + m_buffer.setStreamCompatibilityVersion(rules); for (auto& p : m_idMap) { - if (p.second->writeNetDelta(m_buffer, fromVersion)) { + if (p.second->writeNetDelta(m_buffer, fromVersion, rules)) { willWrite(); ds.writeVlqU(p.first + 1); ds.writeBytes(m_buffer.data()); @@ -237,10 +242,11 @@ bool NetElementDynamicGroup<Element>::writeNetDelta(DataStream& ds, uint64_t fro } template <typename Element> -void NetElementDynamicGroup<Element>::readNetDelta(DataStream& ds, float interpolationTime) { +void NetElementDynamicGroup<Element>::readNetDelta(DataStream& ds, float interpolationTime, NetCompatibilityRules rules) { + if (!checkWithRules(rules)) return; bool isFull = ds.read<bool>(); if (isFull) { - netLoad(ds); + netLoad(ds, rules); } else { while (true) { uint64_t code = ds.readVlqU(); @@ -256,7 +262,7 @@ void NetElementDynamicGroup<Element>::readNetDelta(DataStream& ds, float interpo } else if (auto addition = changeUpdate.template ptr<ElementAddition>()) { ElementPtr element = make_shared<Element>(); DataStreamBuffer storeBuffer(std::move(get<1>(*addition))); - element->netLoad(storeBuffer); + element->netLoad(storeBuffer, rules); readyElement(element); m_idMap.add(get<0>(*addition), std::move(element)); } else if (auto removal = changeUpdate.template ptr<ElementRemoval>()) { @@ -265,7 +271,7 @@ void NetElementDynamicGroup<Element>::readNetDelta(DataStream& ds, float interpo } else { ElementId elementId = code - 1; auto const& element = m_idMap.get(elementId); - element->readNetDelta(ds, interpolationTime); + element->readNetDelta(ds, interpolationTime, rules); if (m_interpolationEnabled) m_receivedDeltaIds.add(elementId); } diff --git a/source/core/StarNetElementExt.hpp b/source/core/StarNetElementExt.hpp new file mode 100644 index 0000000..50802fe --- /dev/null +++ b/source/core/StarNetElementExt.hpp @@ -0,0 +1,85 @@ +#pragma once + +#include "StarNetElement.hpp" + +namespace Star { + +template <typename BaseNetElement> +class NetElementOverride : public BaseNetElement { +public: + void netStore(DataStream& ds, NetCompatibilityRules rules = {}) const override; + void netLoad(DataStream& ds, NetCompatibilityRules rules) override; + + bool writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules = {}) const override; + void readNetDelta(DataStream& ds, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override; + + typedef std::function<void(DataStream&, NetCompatibilityRules)> NetStorer; + typedef std::function<void(DataStream&, NetCompatibilityRules)> NetLoader; + typedef std::function<bool(DataStream&, uint64_t, NetCompatibilityRules)> NetDeltaWriter; + typedef std::function<void(DataStream&, float, NetCompatibilityRules)> NetDeltaReader; + + void setNetStorer(NetStorer); + void setNetLoader(NetLoader); + void setNetDeltaWriter(NetDeltaWriter); + void setNetDeltaReader(NetDeltaReader); + void setOverrides(NetStorer netStorer, NetLoader netLoader, + NetDeltaWriter netDeltaWriter, NetDeltaReader netDeltaReader); + +private: + NetStorer m_netStorer; + NetLoader m_netLoader; + + NetDeltaWriter m_netDeltaWriter; + NetDeltaReader m_netDeltaReader; +}; + +template <typename BaseNetElement> +void NetElementOverride<BaseNetElement>::netStore(DataStream& ds, NetCompatibilityRules rules) const { + if (m_netStorer) + m_netStorer(ds, rules); + else + BaseNetElement::netStore(ds, rules); +} + +template <typename BaseNetElement> +void NetElementOverride<BaseNetElement>::netLoad(DataStream& ds, NetCompatibilityRules rules) { + if (m_netLoader) + m_netLoader(ds, rules); + else + BaseNetElement::netLoad(ds, rules); +} + +template <typename BaseNetElement> +bool NetElementOverride<BaseNetElement>::writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules) const { + if (m_netDeltaWriter) + return m_netDeltaWriter(ds, fromVersion, rules); + else + return BaseNetElement::writeNetDelta(ds, fromVersion, rules); +} + +template <typename BaseNetElement> +void NetElementOverride<BaseNetElement>::readNetDelta(DataStream& ds, float interpolationTime, NetCompatibilityRules rules) { + if (m_netDeltaReader) + m_netDeltaReader(ds, interpolationTime, rules); + else + BaseNetElement::readNetDelta(ds, interpolationTime, rules); +} + +template <typename BaseNetElement> +inline void NetElementOverride<BaseNetElement>::setNetStorer(NetStorer f) { m_netStorer = std::move(f); } +template <typename BaseNetElement> +inline void NetElementOverride<BaseNetElement>::setNetLoader(NetLoader f) { m_netLoader = std::move(f); } +template <typename BaseNetElement> +inline void NetElementOverride<BaseNetElement>::setNetDeltaWriter(NetDeltaWriter f) { m_netDeltaWriter = std::move(f); } +template <typename BaseNetElement> +inline void NetElementOverride<BaseNetElement>::setNetDeltaReader(NetDeltaReader f) { m_netDeltaReader = std::move(f); } + +template <typename BaseNetElement> +inline void NetElementOverride<BaseNetElement>::setOverrides(NetStorer netStorer, NetLoader netLoader, NetDeltaWriter netDeltaWriter, NetDeltaReader netDeltaReader) { + m_netStorer = std::move(netStorer); + m_netLoader = std::move(netLoader); + m_netDeltaWriter = std::move(netDeltaWriter); + m_netDeltaReader = std::move(netDeltaReader); +} + +}
\ No newline at end of file diff --git a/source/core/StarNetElementFloatFields.hpp b/source/core/StarNetElementFloatFields.hpp index 57f74a9..6c8fbcf 100644 --- a/source/core/StarNetElementFloatFields.hpp +++ b/source/core/StarNetElementFloatFields.hpp @@ -36,11 +36,11 @@ public: void disableNetInterpolation() override; void tickNetInterpolation(float dt) override; - void netStore(DataStream& ds) const override; - void netLoad(DataStream& ds) override; + void netStore(DataStream& ds, NetCompatibilityRules rules = {}) const override; + void netLoad(DataStream& ds, NetCompatibilityRules rules) override; - bool writeNetDelta(DataStream& ds, uint64_t fromVersion) const override; - void readNetDelta(DataStream& ds, float interpolationTime = 0.0f) override; + bool writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules = {}) const override; + void readNetDelta(DataStream& ds, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override; void blankNetDelta(float interpolationTime = 0.0f) override; private: @@ -131,7 +131,8 @@ void NetElementFloating<T>::tickNetInterpolation(float dt) { } template <typename T> -void NetElementFloating<T>::netStore(DataStream& ds) const { +void NetElementFloating<T>::netStore(DataStream& ds, NetCompatibilityRules rules) const { + if (!checkWithRules(rules)) return; if (m_interpolationDataPoints) writeValue(ds, m_interpolationDataPoints->last().second); else @@ -139,7 +140,8 @@ void NetElementFloating<T>::netStore(DataStream& ds) const { } template <typename T> -void NetElementFloating<T>::netLoad(DataStream& ds) { +void NetElementFloating<T>::netLoad(DataStream& ds, NetCompatibilityRules rules) { + if (!checkWithRules(rules)) return; m_value = readValue(ds); m_latestUpdateVersion = m_netVersion ? m_netVersion->current() : 0; if (m_interpolationDataPoints) { @@ -149,7 +151,8 @@ void NetElementFloating<T>::netLoad(DataStream& ds) { } template <typename T> -bool NetElementFloating<T>::writeNetDelta(DataStream& ds, uint64_t fromVersion) const { +bool NetElementFloating<T>::writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules) const { + if (!checkWithRules(rules)) return false; if (m_latestUpdateVersion < fromVersion) return false; @@ -162,7 +165,7 @@ bool NetElementFloating<T>::writeNetDelta(DataStream& ds, uint64_t fromVersion) } template <typename T> -void NetElementFloating<T>::readNetDelta(DataStream& ds, float interpolationTime) { +void NetElementFloating<T>::readNetDelta(DataStream& ds, float interpolationTime, NetCompatibilityRules rules) { T t = readValue(ds); m_latestUpdateVersion = m_netVersion ? m_netVersion->current() : 0; diff --git a/source/core/StarNetElementGroup.cpp b/source/core/StarNetElementGroup.cpp index 249c978..6626e2b 100644 --- a/source/core/StarNetElementGroup.cpp +++ b/source/core/StarNetElementGroup.cpp @@ -21,14 +21,18 @@ void NetElementGroup::initNetVersion(NetElementVersion const* version) { p.first->initNetVersion(m_version); } -void NetElementGroup::netStore(DataStream& ds) const { +void NetElementGroup::netStore(DataStream& ds, NetCompatibilityRules rules) const { + if (!checkWithRules(rules)) return; for (auto& p : m_elements) - p.first->netStore(ds); + if (p.first->checkWithRules(rules)) + p.first->netStore(ds, rules); } -void NetElementGroup::netLoad(DataStream& ds) { +void NetElementGroup::netLoad(DataStream& ds, NetCompatibilityRules rules) { + if (!checkWithRules(rules)) return; for (auto& p : m_elements) - p.first->netLoad(ds); + if (p.first->checkWithRules(rules)) + p.first->netLoad(ds, rules); } void NetElementGroup::enableNetInterpolation(float extrapolationHint) { @@ -56,17 +60,23 @@ void NetElementGroup::tickNetInterpolation(float dt) { } } -bool NetElementGroup::writeNetDelta(DataStream& ds, uint64_t fromStep) const { +bool NetElementGroup::writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules) const { + if (!checkWithRules(rules)) return false; if (m_elements.size() == 0) { return false; } else if (m_elements.size() == 1) { - return m_elements[0].first->writeNetDelta(ds, fromStep); + return m_elements[0].first->writeNetDelta(ds, fromVersion, rules); } else { bool deltaWritten = false; - for (uint64_t i = 0; i < m_elements.size(); ++i) { - if (m_elements[i].first->writeNetDelta(m_buffer, fromStep)) { + uint64_t i = 0; + m_buffer.setStreamCompatibilityVersion(rules); + for (auto& element : m_elements) { + if (!element.first->checkWithRules(rules)) + continue; + ++i; + if (element.first->writeNetDelta(m_buffer, fromVersion, rules)) { deltaWritten = true; - ds.writeVlqU(i + 1); + ds.writeVlqU(i); ds.writeBytes(m_buffer.data()); m_buffer.clear(); } @@ -77,23 +87,28 @@ bool NetElementGroup::writeNetDelta(DataStream& ds, uint64_t fromStep) const { } } -void NetElementGroup::readNetDelta(DataStream& ds, float interpolationTime) { +void NetElementGroup::readNetDelta(DataStream& ds, float interpolationTime, NetCompatibilityRules rules) { + if (!checkWithRules(rules)) return; if (m_elements.size() == 0) { throw IOException("readNetDelta called on empty NetElementGroup"); } else if (m_elements.size() == 1) { - m_elements[0].first->readNetDelta(ds, interpolationTime); + m_elements[0].first->readNetDelta(ds, interpolationTime, rules); } else { uint64_t readIndex = ds.readVlqU(); - for (uint64_t i = 0; i < m_elements.size(); ++i) { + uint64_t i = 0; + for (auto& element : m_elements) { + if (!element.first->checkWithRules(rules)) + continue; if (readIndex == 0 || readIndex - 1 > i) { if (m_interpolationEnabled) m_elements[i].first->blankNetDelta(interpolationTime); } else if (readIndex - 1 == i) { - m_elements[i].first->readNetDelta(ds, interpolationTime); + m_elements[i].first->readNetDelta(ds, interpolationTime, rules); readIndex = ds.readVlqU(); } else { throw IOException("group indexes out of order in NetElementGroup::readNetDelta"); } + ++i; } } } diff --git a/source/core/StarNetElementGroup.hpp b/source/core/StarNetElementGroup.hpp index fd1bf58..1904a33 100644 --- a/source/core/StarNetElementGroup.hpp +++ b/source/core/StarNetElementGroup.hpp @@ -24,15 +24,15 @@ public: void initNetVersion(NetElementVersion const* version = nullptr) override; - void netStore(DataStream& ds) const override; - void netLoad(DataStream& ds) override; + void netStore(DataStream& ds, NetCompatibilityRules rules = {}) const override; + void netLoad(DataStream& ds, NetCompatibilityRules rules) override; void enableNetInterpolation(float extrapolationHint = 0.0f) override; void disableNetInterpolation() override; void tickNetInterpolation(float dt) override; - bool writeNetDelta(DataStream& ds, uint64_t fromVersion) const override; - void readNetDelta(DataStream& ds, float interpolationTime = 0.0f) override; + bool writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules = {}) const override; + void readNetDelta(DataStream& ds, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override; void blankNetDelta(float interpolationTime) override; NetElementVersion const* netVersion() const; diff --git a/source/core/StarNetElementSignal.hpp b/source/core/StarNetElementSignal.hpp index 9faa127..61a108d 100644 --- a/source/core/StarNetElementSignal.hpp +++ b/source/core/StarNetElementSignal.hpp @@ -16,15 +16,15 @@ public: void initNetVersion(NetElementVersion const* version = nullptr) override; - void netStore(DataStream& ds) const override; - void netLoad(DataStream& ds) override; + void netStore(DataStream& ds, NetCompatibilityRules rules = {}) const override; + void netLoad(DataStream& ds, NetCompatibilityRules rules) override; void enableNetInterpolation(float extrapolationHint = 0.0f) override; void disableNetInterpolation() override; void tickNetInterpolation(float dt) override; - bool writeNetDelta(DataStream& ds, uint64_t fromVersion) const override; - void readNetDelta(DataStream& ds, float interpolationTime = 0.0) override; + bool writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules = {}) const override; + void readNetDelta(DataStream& ds, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override; void send(Signal signal); List<Signal> receive(); @@ -55,10 +55,10 @@ void NetElementSignal<Signal>::initNetVersion(NetElementVersion const* version) } template <typename Signal> -void NetElementSignal<Signal>::netStore(DataStream&) const {} +void NetElementSignal<Signal>::netStore(DataStream&, NetCompatibilityRules) const {} template <typename Signal> -void NetElementSignal<Signal>::netLoad(DataStream&) { +void NetElementSignal<Signal>::netLoad(DataStream&, NetCompatibilityRules) { } template <typename Signal> @@ -83,7 +83,8 @@ void NetElementSignal<Signal>::tickNetInterpolation(float dt) { } template <typename Signal> -bool NetElementSignal<Signal>::writeNetDelta(DataStream& ds, uint64_t fromVersion) const { +bool NetElementSignal<Signal>::writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules) const { + if (!checkWithRules(rules)) return false; size_t numToWrite = 0; for (auto const& p : m_signals) { if (p.version >= fromVersion) @@ -103,7 +104,8 @@ bool NetElementSignal<Signal>::writeNetDelta(DataStream& ds, uint64_t fromVersio } template <typename Signal> -void NetElementSignal<Signal>::readNetDelta(DataStream& ds, float interpolationTime) { +void NetElementSignal<Signal>::readNetDelta(DataStream& ds, float interpolationTime, NetCompatibilityRules rules) { + if (!checkWithRules(rules)) return; size_t numToRead = ds.readVlqU(); for (size_t i = 0; i < numToRead; ++i) { Signal s; diff --git a/source/core/StarNetElementSyncGroup.cpp b/source/core/StarNetElementSyncGroup.cpp index ac8da92..cd98638 100644 --- a/source/core/StarNetElementSyncGroup.cpp +++ b/source/core/StarNetElementSyncGroup.cpp @@ -26,23 +26,27 @@ void NetElementSyncGroup::tickNetInterpolation(float dt) { } } -void NetElementSyncGroup::netStore(DataStream& ds) const { +void NetElementSyncGroup::netStore(DataStream& ds, NetCompatibilityRules rules) const { + if (!checkWithRules(rules)) return; const_cast<NetElementSyncGroup*>(this)->netElementsNeedStore(); - return NetElementGroup::netStore(ds); + return NetElementGroup::netStore(ds, rules); } -void NetElementSyncGroup::netLoad(DataStream& ds) { - NetElementGroup::netLoad(ds); +void NetElementSyncGroup::netLoad(DataStream& ds, NetCompatibilityRules rules) { + if (!checkWithRules(rules)) return; + NetElementGroup::netLoad(ds, rules); netElementsNeedLoad(true); } -bool NetElementSyncGroup::writeNetDelta(DataStream& ds, uint64_t fromVersion) const { +bool NetElementSyncGroup::writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules) const { + if (!checkWithRules(rules)) return false; const_cast<NetElementSyncGroup*>(this)->netElementsNeedStore(); - return NetElementGroup::writeNetDelta(ds, fromVersion); + return NetElementGroup::writeNetDelta(ds, fromVersion, rules); } -void NetElementSyncGroup::readNetDelta(DataStream& ds, float interpolationTime) { - NetElementGroup::readNetDelta(ds, interpolationTime); +void NetElementSyncGroup::readNetDelta(DataStream& ds, float interpolationTime, NetCompatibilityRules rules) { + if (!checkWithRules(rules)) return; + NetElementGroup::readNetDelta(ds, interpolationTime, rules); m_hasRecentChanges = true; m_recentDeltaTime = interpolationTime; diff --git a/source/core/StarNetElementSyncGroup.hpp b/source/core/StarNetElementSyncGroup.hpp index b01200b..30dafe8 100644 --- a/source/core/StarNetElementSyncGroup.hpp +++ b/source/core/StarNetElementSyncGroup.hpp @@ -13,11 +13,11 @@ public: void disableNetInterpolation() override; void tickNetInterpolation(float dt) override; - void netStore(DataStream& ds) const override; - void netLoad(DataStream& ds) override; + void netStore(DataStream& ds, NetCompatibilityRules rules = {}) const override; + void netLoad(DataStream& ds, NetCompatibilityRules rules) override; - bool writeNetDelta(DataStream& ds, uint64_t fromStep) const override; - void readNetDelta(DataStream& ds, float interpolationTime = 0.0f) override; + bool writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules = {}) const override; + void readNetDelta(DataStream& ds, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override; void blankNetDelta(float interpolationTime = 0.0f) override; protected: diff --git a/source/core/StarNetElementTop.hpp b/source/core/StarNetElementTop.hpp index 454b34f..cf3cfb4 100644 --- a/source/core/StarNetElementTop.hpp +++ b/source/core/StarNetElementTop.hpp @@ -1,5 +1,4 @@ -#ifndef STAR_NET_ELEMENT_TOP_HPP -#define STAR_NET_ELEMENT_TOP_HPP +#pragma once #include "StarNetElement.hpp" @@ -12,10 +11,11 @@ class NetElementTop : public BaseNetElement { public: NetElementTop(); - // Returns the state update, combined with the version code that should be - // passed to the next call to writeState. If 'fromVersion' is 0, then this - // is a full write for an initial read of a slave NetElementTop. - pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion = 0); + // Writes the state update to the given DataStream then returns the version + // code that should be passed to the next call to writeState. If + // 'fromVersion' is 0, then this is a full write for an initial read of a + // slave NetElementTop. + pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion = 0, NetCompatibilityRules rules = {}); // Reads a state produced by a call to writeState, optionally with the // interpolation delay time for the data contained in this state update. If // the state is a full update rather than a delta, the interoplation delay @@ -23,7 +23,7 @@ public: // readState, *unless* extrapolation is enabled. If extrapolation is // enabled, reading a blank update calls 'blankNetDelta' which is necessary // to not improperly extrapolate past the end of incoming deltas. - void readNetState(ByteArray data, float interpolationTime = 0.0); + void readNetState(ByteArray data, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}); private: using BaseNetElement::initNetVersion; @@ -32,6 +32,7 @@ private: using BaseNetElement::writeNetDelta; using BaseNetElement::readNetDelta; using BaseNetElement::blankNetDelta; + using BaseNetElement::checkWithRules; NetElementVersion m_netVersion; }; @@ -42,41 +43,34 @@ NetElementTop<BaseNetElement>::NetElementTop() { } template <typename BaseNetElement> -pair<ByteArray, uint64_t> NetElementTop<BaseNetElement>::writeNetState(uint64_t fromVersion) { +pair<ByteArray, uint64_t> NetElementTop<BaseNetElement>::writeNetState(uint64_t fromVersion, NetCompatibilityRules rules) { + DataStreamBuffer ds; + ds.setStreamCompatibilityVersion(rules); if (fromVersion == 0) { - DataStreamBuffer ds; ds.write<bool>(true); - BaseNetElement::netStore(ds); - m_netVersion.increment(); - return {ds.takeData(), m_netVersion.current()}; - + BaseNetElement::netStore(ds, rules); + return {ds.takeData(), m_netVersion.increment()}; } else { - DataStreamBuffer ds; ds.write<bool>(false); - if (!BaseNetElement::writeNetDelta(ds, fromVersion)) { + if (!BaseNetElement::writeNetDelta(ds, fromVersion, rules)) return {ByteArray(), m_netVersion.current()}; - } else { - m_netVersion.increment(); - return {ds.takeData(), m_netVersion.current()}; - } + else + return {ds.takeData(), m_netVersion.increment()}; } } template <typename BaseNetElement> -void NetElementTop<BaseNetElement>::readNetState(ByteArray data, float interpolationTime) { +void NetElementTop<BaseNetElement>::readNetState(ByteArray data, float interpolationTime, NetCompatibilityRules rules) { if (data.empty()) { BaseNetElement::blankNetDelta(interpolationTime); - } else { DataStreamBuffer ds(std::move(data)); - + ds.setStreamCompatibilityVersion(rules); if (ds.read<bool>()) - BaseNetElement::netLoad(ds); + BaseNetElement::netLoad(ds, rules); else - BaseNetElement::readNetDelta(ds, interpolationTime); + BaseNetElement::readNetDelta(ds, interpolationTime, rules); } } -} - -#endif +}
\ No newline at end of file |