Browse Source

Queue remote events instead of sending immediately to avoid synchronization problems with scene updates.
Changed inSerialization flag to loading flag.

Lasse Öörni 14 years ago
parent
commit
40ad2d09b6

+ 1 - 1
Engine/Graphics/AnimatedModel.cpp

@@ -604,7 +604,7 @@ void AnimatedModel::SetModelAttr(ResourceRef value)
 {
     ResourceCache* cache = GetSubsystem<ResourceCache>();
     // When loading a scene, set model without creating the bone nodes (will be assigned later during post-load)
-    SetModel(cache->GetResource<Model>(value.id_), !inSerialization_);
+    SetModel(cache->GetResource<Model>(value.id_), !IsLoading());
 }
 
 void AnimatedModel::SetBonesEnabledAttr(PODVector<unsigned char> value)

+ 38 - 9
Engine/Network/Connection.cpp

@@ -92,10 +92,12 @@ void Connection::SendMessage(int msgID, unsigned contentID, bool reliable, bool
 
 void Connection::SendRemoteEvent(StringHash eventType, bool inOrder, const VariantMap& eventData)
 {
-    msg_.Clear();
-    msg_.WriteStringHash(eventType);
-    msg_.WriteVariantMap(eventData);
-    SendMessage(MSG_REMOTEEVENT, true, inOrder, msg_);
+    RemoteEvent queuedEvent;
+    queuedEvent.receiverID_ = 0;
+    queuedEvent.eventType_ = eventType;
+    queuedEvent.eventData_ = eventData;
+    queuedEvent.inOrder_ = inOrder;
+    remoteEvents_.Push(queuedEvent);
 }
 
 void Connection::SendRemoteEvent(Node* receiver, StringHash eventType, bool inOrder, const VariantMap& eventData)
@@ -116,11 +118,12 @@ void Connection::SendRemoteEvent(Node* receiver, StringHash eventType, bool inOr
         return;
     }
     
-    msg_.Clear();
-    msg_.WriteVLE(receiver->GetID());
-    msg_.WriteStringHash(eventType);
-    msg_.WriteVariantMap(eventData);
-    SendMessage(MSG_REMOTENODEEVENT, true, inOrder, msg_);
+    RemoteEvent queuedEvent;
+    queuedEvent.receiverID_ = receiver->GetID();
+    queuedEvent.eventType_ = eventType;
+    queuedEvent.eventData_ = eventData;
+    queuedEvent.inOrder_ = inOrder;
+    remoteEvents_.Push(queuedEvent);
 }
 
 void Connection::SetScene(Scene* newScene)
@@ -232,6 +235,32 @@ void Connection::SendClientUpdate()
     SendMessage(MSG_CONTROLS, CONTROLS_CONTENT_ID, false, false, msg_);
 }
 
+void Connection::SendQueuedRemoteEvents()
+{
+    if (remoteEvents_.Empty())
+        return;
+    
+    for (Vector<RemoteEvent>::ConstIterator i = remoteEvents_.Begin(); i != remoteEvents_.End(); ++i)
+    {
+        msg_.Clear();
+        if (!i->receiverID_)
+        {
+            msg_.WriteStringHash(i->eventType_);
+            msg_.WriteVariantMap(i->eventData_);
+            SendMessage(MSG_REMOTEEVENT, true, i->inOrder_, msg_);
+        }
+        else
+        {
+            msg_.WriteVLE(i->receiverID_);
+            msg_.WriteStringHash(i->eventType_);
+            msg_.WriteVariantMap(i->eventData_);
+            SendMessage(MSG_REMOTENODEEVENT, true, i->inOrder_, msg_);
+        }
+    }
+    
+    remoteEvents_.Clear();
+}
+
 void Connection::ProcessPendingLatestData()
 {
     if (!scene_)

+ 17 - 0
Engine/Network/Connection.h

@@ -41,6 +41,19 @@ class Node;
 class Scene;
 class Serializable;
 
+/// Queued remote event
+struct RemoteEvent
+{
+    /// Receiver node ID (0 if not a remote node event)
+    unsigned receiverID_;
+    /// Event type
+    StringHash eventType_;
+    /// Event data
+    VariantMap eventData_;
+    /// In order -flag
+    bool inOrder_;
+};
+
 /// Connection in a networked scene
 class Connection : public Object
 {
@@ -78,6 +91,8 @@ public:
     void SendServerUpdate();
     /// Send latest controls from the client. Called by Network
     void SendClientUpdate();
+    /// Send queued remote events. Called by Network
+    void SendQueuedRemoteEvents();
     /// Process pending latest data for nodes and components
     void ProcessPendingLatestData();
     /// Process a LoadScene message from the server. Called by Network
@@ -142,6 +157,8 @@ private:
     Map<unsigned, PODVector<unsigned char> > nodeLatestData_;
     /// Pending latest data for not yet received components
     Map<unsigned, PODVector<unsigned char> > componentLatestData_;
+    /// Queued remote events
+    Vector<RemoteEvent> remoteEvents_;
     /// Internal vector for delta update
     PODVector<unsigned char> deltaUpdateBits_;
     /// Internal set for node's user variable changes

+ 7 - 1
Engine/Network/Network.cpp

@@ -373,9 +373,12 @@ void Network::Update(float timeStep)
         else if (state == kNet::ConnectionClosed)
             OnServerDisconnected();
         
-        // Send the client update (controls)
+        // Send the client update
         if (updateNow && serverConnection_)
+        {
             serverConnection_->SendClientUpdate();
+            serverConnection_->SendQueuedRemoteEvents();
+        }
     }
     
     // Process client connections if the server has been started
@@ -389,7 +392,10 @@ void Network::Update(float timeStep)
             // Send server updates for each client connection
             for (Map<kNet::MessageConnection*, SharedPtr<Connection> >::ConstIterator i = clientConnections_.Begin();
                 i != clientConnections_.End(); ++i)
+            {
                 i->second_->SendServerUpdate();
+                i->second_->SendQueuedRemoteEvents();
+            }
         }
     }
 }

+ 6 - 11
Engine/Scene/Serializable.cpp

@@ -35,7 +35,7 @@ OBJECTTYPESTATIC(Serializable);
 
 Serializable::Serializable(Context* context) :
     Object(context),
-    inSerialization_(false)
+    loading_(false)
 {
 }
 
@@ -201,7 +201,7 @@ bool Serializable::Load(Deserializer& source)
     if (!attributes)
         return true;
     
-    inSerialization_ = true;
+    loading_ = true;
     
     for (unsigned i = 0; i < attributes->Size(); ++i)
     {
@@ -212,14 +212,14 @@ bool Serializable::Load(Deserializer& source)
         if (source.IsEof())
         {
             LOGERROR("Could not load " + GetTypeName() + ", stream not open or at end");
-            inSerialization_  = false;
+            loading_  = false;
             return false;
         }
         
         OnSetAttribute(attr, source.ReadVariant(attr.type_));
     }
     
-    inSerialization_ = false;
+    loading_ = false;
     return true;
 }
 
@@ -230,7 +230,6 @@ bool Serializable::Save(Serializer& dest)
         return true;
     
     Variant value;
-    inSerialization_ = true;
     
     for (unsigned i = 0; i < attributes->Size(); ++i)
     {
@@ -242,12 +241,10 @@ bool Serializable::Save(Serializer& dest)
         if (!dest.WriteVariantData(value))
         {
             LOGERROR("Could not save " + GetTypeName() + ", writing to stream failed");
-            inSerialization_ = false;
             return false;
         }
     }
     
-    inSerialization_ = false;
     return true;
 }
 
@@ -263,7 +260,7 @@ bool Serializable::LoadXML(const XMLElement& source)
     if (!attributes)
         return true;
     
-    inSerialization_ = true;
+    loading_ = true;
     
     for (unsigned i = 0; i < attributes->Size(); ++i)
     {
@@ -313,7 +310,7 @@ bool Serializable::LoadXML(const XMLElement& source)
             LOGWARNING("Attribute " + String(attr.name_) + " not found in XML data");
     }
     
-    inSerialization_ = false;
+    loading_ = false;
     return true;
 }
 
@@ -330,7 +327,6 @@ bool Serializable::SaveXML(XMLElement& dest)
         return true;
     
     Variant value;
-    inSerialization_ = true;
     
     for (unsigned i = 0; i < attributes->Size(); ++i)
     {
@@ -352,7 +348,6 @@ bool Serializable::SaveXML(XMLElement& dest)
             attrElem.SetVariant(value);
     }
     
-    inSerialization_ = false;
     return true;
 }
 

+ 4 - 2
Engine/Scene/Serializable.h

@@ -85,10 +85,12 @@ public:
     const Vector<AttributeInfo>* GetAttributes() const;
     /// Return network replication attribute descriptions, or null if none defined
     const Vector<AttributeInfo>* GetNetworkAttributes() const;
+    /// Return whether is loading attributes from a file. Is false during network deserialization
+    bool IsLoading() const { return loading_; }
     
 protected:
-    /// In serialization -flag
-    bool inSerialization_;
+    /// Is loading flag
+    bool loading_;
 };
 
 /// Template implementation of the attribute accessor invoke helper class