浏览代码

Store network replication attributes separately to optimize sending and receiving updates.

Lasse Öörni 14 年之前
父节点
当前提交
50682de1c6
共有 6 个文件被更改,包括 102 次插入117 次删除
  1. 15 1
      Engine/Core/Context.cpp
  2. 11 0
      Engine/Core/Context.h
  3. 7 4
      Engine/Network/Connection.cpp
  4. 0 2
      Engine/Network/Network.cpp
  5. 66 109
      Engine/Scene/Serializable.cpp
  6. 3 1
      Engine/Scene/Serializable.h

+ 15 - 1
Engine/Core/Context.cpp

@@ -74,17 +74,31 @@ void Context::RegisterAttribute(ShortStringHash objectType, const AttributeInfo&
         return;
     
     attributes_[objectType].Push(attr);
+    
+    if (attr.mode_ & AM_NET)
+        networkAttributes_[objectType].Push(attr);
 }
 
 void Context::RemoveAttribute(ShortStringHash objectType, const String& name)
 {
     Vector<AttributeInfo>& attributes = attributes_[objectType];
+    Vector<AttributeInfo>& netAttributes = networkAttributes_[objectType];
+    
     for (Vector<AttributeInfo>::Iterator i = attributes.Begin(); i != attributes.End(); ++i)
     {
         if (i->name_ == name)
         {
             attributes.Erase(i);
-            return;
+            break;
+        }
+    }
+    
+    for (Vector<AttributeInfo>::Iterator i = netAttributes.Begin(); i != netAttributes.End(); ++i)
+    {
+        if (i->name_ == name)
+        {
+            netAttributes.Erase(i);
+            break;
         }
     }
 }

+ 11 - 0
Engine/Core/Context.h

@@ -131,6 +131,8 @@ public:
     const Map<ShortStringHash, SharedPtr<ObjectFactory> >& GetObjectFactories() const { return factories_; }
     /// Return attributes for all object types
     const Map<ShortStringHash, Vector<AttributeInfo> >& GetAllAttributes() const { return attributes_; }
+    /// Return network replication attributes for all object types
+    const Map<ShortStringHash, Vector<AttributeInfo> >& GetAllNetworkAttributes() const { return networkAttributes_; }
     /// Return active event sender. Null outside event handling
     Object* GetSender() const;
     /// Return active event handler. Set by Object. Null outside event handling
@@ -147,6 +149,13 @@ public:
         return i != attributes_.End() ? &i->second_ : 0;
     }
     
+    /// Return network replication attribute descriptions for an object type, or null if none defined
+    const Vector<AttributeInfo>* GetNetworkAttributes(ShortStringHash type) const
+    {
+        Map<ShortStringHash, Vector<AttributeInfo> >::ConstIterator i = networkAttributes_.Find(type);
+        return i != attributes_.End() ? &i->second_ : 0;
+    }
+    
     /// Return event receivers for a sender and event type, or null if they do not exist
     PODVector<Object*>* GetReceivers(Object* sender, StringHash eventType)
     {
@@ -169,6 +178,8 @@ private:
     Map<ShortStringHash, SharedPtr<Object> > subsystems_;
     /// Attribute descriptions per object type
     Map<ShortStringHash, Vector<AttributeInfo> > attributes_;
+    /// Network replication attribute descriptions per object type
+    Map<ShortStringHash, Vector<AttributeInfo> > networkAttributes_;
     /// Event receivers for non-specific events
     Map<StringHash, PODVector<Object*> > receivers_;
     /// Event receivers for specific senders' events

+ 7 - 4
Engine/Network/Connection.cpp

@@ -29,6 +29,7 @@
 #include "Log.h"
 #include "MemoryBuffer.h"
 #include "NetworkEvents.h"
+#include "Profiler.h"
 #include "Protocol.h"
 #include "Scene.h"
 #include "SceneEvents.h"
@@ -183,6 +184,8 @@ void Connection::SendServerUpdate()
     if (!isClient_ || !scene_ || !sceneLoaded_)
         return;
     
+    PROFILE(SendServerUpdate);
+    
     const Map<unsigned, Node*>& nodes = scene_->GetAllNodes();
     
     // Check for new or changed nodes
@@ -216,6 +219,8 @@ void Connection::SendClientUpdate()
     if (isClient_ || !scene_ || !sceneLoaded_)
         return;
     
+    PROFILE(SendClientUpdate);
+    
     msg_.Clear();
     msg_.WriteUInt(controls_.buttons_);
     msg_.WriteFloat(controls_.yaw_);
@@ -362,8 +367,7 @@ void Connection::ProcessSceneUpdate(int msgID, MemoryBuffer& msg)
                 --numVars;
                 
                 ShortStringHash key = msg.ReadShortStringHash();
-                Variant value = msg.ReadVariant();
-                vars[key] = value;
+                vars[key] = msg.ReadVariant();
             }
             
             // Read components
@@ -413,8 +417,7 @@ void Connection::ProcessSceneUpdate(int msgID, MemoryBuffer& msg)
                     --changedVars;
                     
                     ShortStringHash key = msg.ReadShortStringHash();
-                    Variant value = msg.ReadVariant();
-                    vars[key] = value;
+                    vars[key] = msg.ReadVariant();
                 }
             }
             else

+ 0 - 2
Engine/Network/Network.cpp

@@ -66,8 +66,6 @@ Network::~Network()
 
 void Network::HandleMessage(kNet::MessageConnection* source, kNet::message_id_t id, const char* data, size_t numBytes)
 {
-    PROFILE(HandleMessage);
-    
     // Only process messages from known sources
     Connection* connection = GetConnection(source);
     if (connection)

+ 66 - 109
Engine/Scene/Serializable.cpp

@@ -31,6 +31,17 @@
 
 #include "DebugNew.h"
 
+bool CompareAndCopyVariant(const Variant& src, Variant& dest)
+{
+    if (dest != src)
+    {
+        dest = src;
+        return true;
+    }
+    else
+        return false;
+}
+
 OBJECTTYPESTATIC(Serializable);
 
 Serializable::Serializable(Context* context) :
@@ -188,7 +199,6 @@ bool Serializable::Load(Deserializer& source)
     
     inSerialization_ = true;
     
-    // Read attributes as Variants with predefined types from the attribute info
     for (unsigned i = 0; i < attributes->Size(); ++i)
     {
         const AttributeInfo& attr = attributes->At(i);
@@ -201,7 +211,8 @@ bool Serializable::Load(Deserializer& source)
             inSerialization_  = false;
             return false;
         }
-        SetAttribute(i, source.ReadVariant(attr.type_));
+        
+        OnSetAttribute(attr, source.ReadVariant(attr.type_));
     }
     
     inSerialization_ = false;
@@ -216,14 +227,13 @@ bool Serializable::Save(Serializer& dest)
     
     inSerialization_ = true;
     
-    // Then write attributes as Variants without type
     for (unsigned i = 0; i < attributes->Size(); ++i)
     {
         const AttributeInfo& attr = attributes->At(i);
         if (!(attr.mode_ & AM_FILE))
             continue;
         
-        if (!dest.WriteVariantData(GetAttribute(i)))
+        if (!dest.WriteVariantData(OnGetAttribute(attr)))
         {
             LOGERROR("Could not save " + GetTypeName() + ", writing to stream failed");
             inSerialization_ = false;
@@ -255,7 +265,6 @@ bool Serializable::LoadXML(const XMLElement& source)
         if (!(attr.mode_ & AM_FILE))
             continue;
         
-        // We could assume fixed order. However, do name-based lookup instead for more robustness
         XMLElement attrElem = source.GetChild("attribute");
         bool found = false;
         while (attrElem)
@@ -280,12 +289,12 @@ bool Serializable::LoadXML(const XMLElement& source)
                         ++enumValue;
                     }
                     if (enumFound)
-                        SetAttribute(i, Variant(enumValue));
+                        OnSetAttribute(attr, Variant(enumValue));
                     else
                         LOGWARNING("Unknown enum value " + value + " in attribute " + String(attr.name_));
                 }
                 else
-                    SetAttribute(i, attrElem.GetVariant());
+                    OnSetAttribute(attr, attrElem.GetVariant());
                 
                 found = true;
                 break;
@@ -327,12 +336,12 @@ bool Serializable::SaveXML(XMLElement& dest)
         // If enums specified, set as an enum string. Otherwise set directly as a Variant
         if (attr.enumNames_)
         {
-            int enumValue = GetAttribute(i).GetInt();
+            int enumValue = OnGetAttribute(attr).GetInt();
             attrElem.SetString("type", "Enum");
             attrElem.SetString("value", String(attr.enumNames_[enumValue]));
         }
         else
-            attrElem.SetVariant(GetAttribute(i));
+            attrElem.SetVariant(OnGetAttribute(attr));
     }
     
     inSerialization_ = false;
@@ -403,50 +412,33 @@ bool Serializable::SetAttribute(const String& name, const Variant& value)
 
 void Serializable::WriteInitialDeltaUpdate(Serializer& dest, PODVector<unsigned char>& deltaUpdateBits, Vector<Variant>& lastSentState)
 {
-    unsigned numAttributes = GetNumNetworkAttributes();
-    if (!numAttributes)
+    const Vector<AttributeInfo>* attributes = GetNetworkAttributes();
+    if (!attributes)
         return;
-    
-    const Vector<AttributeInfo>* attributes = GetAttributes();
-    unsigned index = 0;
+    unsigned numAttributes = attributes->Size();
     
     lastSentState.Resize(numAttributes);
-    
     deltaUpdateBits.Resize((numAttributes + 7) >> 3);
     for (unsigned i = 0; i < deltaUpdateBits.Size(); ++i)
         deltaUpdateBits[i] = 0;
     
-    for (unsigned i = 0; i < attributes->Size(); ++i)
+    // Set initial values to the last sent state and compare against defaults
+    for (unsigned i = 0; i < numAttributes; ++i)
     {
         const AttributeInfo& attr = attributes->At(i);
-        if (!(attr.mode_ & AM_NET))
-            continue;
-        
-        Variant value = GetAttribute(i);
-        if (value != attr.defaultValue_)
-        {
-            lastSentState[index] = value;
-            deltaUpdateBits[index >> 3] |= (1 << (index & 7));
-        }
-        else
-            lastSentState[index] = attr.defaultValue_;
-        
-        ++index;
+        lastSentState[i] = OnGetAttribute(attr);
+        if (lastSentState[i] != attr.defaultValue_)
+            deltaUpdateBits[i >> 3] |= (1 << (i & 7));
     }
     
+    // First write the change bitfield, then attribute data for non-default attributes
     dest.Write(&deltaUpdateBits[0], deltaUpdateBits.Size());
     
-    index = 0;
-    for (unsigned i = 0; i < attributes->Size(); ++i)
+    for (unsigned i = 0; i < numAttributes; ++i)
     {
         const AttributeInfo& attr = attributes->At(i);
-        if (!(attr.mode_ & AM_NET))
-            continue;
-        
-        if (deltaUpdateBits[index >> 3] & (1 << (index & 7)))
-            dest.WriteVariantData(lastSentState[index]);
-        
-        ++index;
+        if (deltaUpdateBits[i >> 3] & (1 << (i & 7)))
+            dest.WriteVariantData(lastSentState[i]);
     }
 }
 
@@ -456,125 +448,96 @@ void Serializable::PrepareUpdates(PODVector<unsigned char>& deltaUpdateBits, Vec
     deltaUpdate = false;
     latestData = false;
     
-    unsigned numAttributes = GetNumNetworkAttributes();
-    if (!numAttributes)
+    const Vector<AttributeInfo>* attributes = GetNetworkAttributes();
+    if (!attributes)
         return;
-    
-    const Vector<AttributeInfo>* attributes = GetAttributes();
-    unsigned index = 0;
+    unsigned numAttributes = attributes->Size();
     
     deltaUpdateBits.Resize((numAttributes + 7) >> 3);
     for (unsigned i = 0; i < deltaUpdateBits.Size(); ++i)
         deltaUpdateBits[i] = 0;
     
-    for (unsigned i = 0; i < attributes->Size(); ++i)
+    for (unsigned i = 0; i < numAttributes; ++i)
     {
         const AttributeInfo& attr = attributes->At(i);
-        if (!(attr.mode_ & AM_NET))
-            continue;
         
         // Check for attribute change
-        Variant value = GetAttribute(i);
-        if (value != lastSentState[index])
+        if (CompareAndCopyVariant(OnGetAttribute(attr), lastSentState[i]))
         {
-            lastSentState[index] = value;
             if (attr.mode_ & AM_LATESTDATA)
                 latestData = true;
             else
             {
                 deltaUpdate = true;
-                deltaUpdateBits[index >> 3] |= 1 << (index & 7);
+                deltaUpdateBits[i >> 3] |= 1 << (i & 7);
             }
         }
-        
-        ++index;
     }
 }
 
 void Serializable::WriteDeltaUpdate(Serializer& dest, PODVector<unsigned char>& deltaUpdateBits, Vector<Variant>& lastSentState)
 {
-    unsigned numAttributes = GetNumNetworkAttributes();
-    if (!numAttributes)
+    const Vector<AttributeInfo>* attributes = GetNetworkAttributes();
+    if (!attributes)
         return;
+    unsigned numAttributes = attributes->Size();
     
-    const Vector<AttributeInfo>* attributes = GetAttributes();
-    unsigned index = 0;
-    
+    // First write the change bitfield, then attribute data for changed attributes
     dest.Write(&deltaUpdateBits[0], deltaUpdateBits.Size());
     
-    for (unsigned i = 0; i < attributes->Size(); ++i)
+    for (unsigned i = 0; i < numAttributes; ++i)
     {
         const AttributeInfo& attr = attributes->At(i);
-        if (!(attr.mode_ & AM_NET))
-            continue;
-        
-        if (deltaUpdateBits[index >> 3] & (1 << (index & 7)))
-            dest.WriteVariantData(lastSentState[index]);
-        
-        ++index;
+        if (deltaUpdateBits[i >> 3] & (1 << (i & 7)))
+            dest.WriteVariantData(lastSentState[i]);
     }
 }
 
 void Serializable::WriteLatestDataUpdate(Serializer& dest, Vector<Variant>& lastSentState)
 {
-    unsigned numAttributes = GetNumNetworkAttributes();
-    if (!numAttributes)
+    const Vector<AttributeInfo>* attributes = GetNetworkAttributes();
+    if (!attributes)
         return;
+    unsigned numAttributes = attributes->Size();
     
-    const Vector<AttributeInfo>* attributes = GetAttributes();
-    unsigned index = 0;
-    
-    for (unsigned i = 0; i < attributes->Size(); ++i)
+    for (unsigned i = 0; i < numAttributes; ++i)
     {
         const AttributeInfo& attr = attributes->At(i);
-        if (!(attr.mode_ & AM_NET))
-            continue;
-        
         if (attr.mode_ & AM_LATESTDATA)
-            dest.WriteVariantData(lastSentState[index]);
-        
-        ++index;
+            dest.WriteVariantData(lastSentState[i]);
     }
 }
 
 void Serializable::ReadDeltaUpdate(Deserializer& source, PODVector<unsigned char>& deltaUpdateBits)
 {
-    unsigned numAttributes = GetNumNetworkAttributes();
-    if (!numAttributes)
+    const Vector<AttributeInfo>* attributes = GetNetworkAttributes();
+    if (!attributes)
         return;
-    
-    const Vector<AttributeInfo>* attributes = GetAttributes();
-    unsigned index = 0;
+    unsigned numAttributes = attributes->Size();
     
     deltaUpdateBits.Resize((numAttributes + 7) >> 3);
     source.Read(&deltaUpdateBits[0], deltaUpdateBits.Size());
     
-    for (unsigned i = 0; i < attributes->Size() && !source.IsEof(); ++i)
+    for (unsigned i = 0; i < numAttributes && !source.IsEof(); ++i)
     {
         const AttributeInfo& attr = attributes->At(i);
-        if (!(attr.mode_ & AM_NET))
-            continue;
-        
-        if (deltaUpdateBits[index >> 3] & (1 << (index & 7)))
-            SetAttribute(i, source.ReadVariant(attr.type_));
-        
-        ++index;
+        if (deltaUpdateBits[i >> 3] & (1 << (i & 7)))
+            OnSetAttribute(attr, source.ReadVariant(attr.type_));
     }
 }
 
 void Serializable::ReadLatestDataUpdate(Deserializer& source)
 {
-    const Vector<AttributeInfo>* attributes = GetAttributes();
+    const Vector<AttributeInfo>* attributes = GetNetworkAttributes();
     if (!attributes)
         return;
+    unsigned numAttributes = attributes->Size();
     
-    for (unsigned i = 0; i < attributes->Size() && !source.IsEof(); ++i)
+    for (unsigned i = 0; i < numAttributes && !source.IsEof(); ++i)
     {
         const AttributeInfo& attr = attributes->At(i);
-        if ((attr.mode_ & (AM_NET | AM_LATESTDATA)) != (AM_NET | AM_LATESTDATA))
-            continue;
-        
-        SetAttribute(i, source.ReadVariant(attr.type_));
+        if (attr.mode_ & AM_LATESTDATA)
+            OnSetAttribute(attr, source.ReadVariant(attr.type_));
     }
 }
 
@@ -614,22 +577,16 @@ unsigned Serializable::GetNumAttributes() const
 
 unsigned Serializable::GetNumNetworkAttributes() const
 {
-    const Vector<AttributeInfo>* attributes = context_->GetAttributes(GetType());
-    if (!attributes)
-        return 0;
-    
-    unsigned num = 0;
-    for (unsigned i = 0; i < attributes->Size(); ++i)
-    {
-        const AttributeInfo& attr = attributes->At(i);
-        if (attr.mode_ & AM_NET)
-            ++num;
-    }
-    
-    return num;
+    const Vector<AttributeInfo>* attributes = context_->GetNetworkAttributes(GetType());
+    return attributes ? attributes->Size() : 0;
 }
 
 const Vector<AttributeInfo>* Serializable::GetAttributes() const
 {
     return context_->GetAttributes(GetType());
 }
+
+const Vector<AttributeInfo>* Serializable::GetNetworkAttributes() const
+{
+    return context_->GetNetworkAttributes(GetType());
+}

+ 3 - 1
Engine/Scene/Serializable.h

@@ -79,10 +79,12 @@ public:
     Variant GetAttribute(const String& name);
     /// Return number of attributes
     unsigned GetNumAttributes() const;
-    /// Return number of network serialization attributes
+    /// Return number of network replication attributes
     unsigned GetNumNetworkAttributes() const;
     /// Return attribute descriptions, or null if none defined
     const Vector<AttributeInfo>* GetAttributes() const;
+    /// Return network replication attribute descriptions, or null if none defined
+    const Vector<AttributeInfo>* GetNetworkAttributes() const;
     
 protected:
     /// In serialization -flag