Browse Source

Optimized away constant dynamic Variant allocation in comparing attributes when sending a server update.

Lasse Öörni 14 years ago
parent
commit
84d70dcbe7

+ 2 - 2
Engine/Core/Attribute.h

@@ -44,9 +44,9 @@ class AttributeAccessor : public RefCounted
 {
 public:
     /// Get the attribute
-    virtual Variant Get(Serializable* ptr) { return Variant(); }
+    virtual void Get(Serializable* ptr, Variant& dest) {}
     /// Set the attribute
-    virtual void Set(Serializable* ptr, const Variant& value) {}
+    virtual void Set(Serializable* ptr, const Variant& src) {}
 };
 
 /// Description of an automatically serializable variable

+ 2 - 2
Engine/Graphics/Octree.cpp

@@ -286,10 +286,10 @@ void Octree::RegisterObject(Context* context)
     ATTRIBUTE(Octree, VAR_INT, "Number of Levels", numLevels_, DEFAULT_OCTREE_LEVELS, AM_DEFAULT);
 }
 
-void Octree::OnSetAttribute(const AttributeInfo& attr, const Variant& value)
+void Octree::OnSetAttribute(const AttributeInfo& attr, const Variant& src)
 {
     // If any of the (size) attributes change, resize the octree
-    Serializable::OnSetAttribute(attr, value);
+    Serializable::OnSetAttribute(attr, src);
     Resize(worldBoundingBox_, numLevels_);
 }
 

+ 1 - 1
Engine/Graphics/Octree.h

@@ -159,7 +159,7 @@ public:
     static void RegisterObject(Context* context);
     
     /// Handle attribute change
-    virtual void OnSetAttribute(const AttributeInfo& attr, const Variant& value);
+    virtual void OnSetAttribute(const AttributeInfo& attr, const Variant& src);
     
     /// Resize octree. If octree is not empty, drawable objects will be temporarily moved to the root
     void Resize(const BoundingBox& box, unsigned numLevels);

+ 2 - 2
Engine/Graphics/Zone.cpp

@@ -62,9 +62,9 @@ void Zone::RegisterObject(Context* context)
     ATTRIBUTE(Zone, VAR_INT, "Zone Priority", priority_, 0, AM_DEFAULT);
 }
 
-void Zone::OnSetAttribute(const AttributeInfo& attr, const Variant& value)
+void Zone::OnSetAttribute(const AttributeInfo& attr, const Variant& src)
 {
-    Serializable::OnSetAttribute(attr, value);
+    Serializable::OnSetAttribute(attr, src);
     
     // If bounding box changes, dirty the drawable as applicable
     switch (attr.offset_)

+ 1 - 1
Engine/Graphics/Zone.h

@@ -40,7 +40,7 @@ public:
     static void RegisterObject(Context* context);
     
     /// Handle attribute write access
-    virtual void OnSetAttribute(const AttributeInfo& attr, const Variant& value);
+    virtual void OnSetAttribute(const AttributeInfo& attr, const Variant& src);
     
     /// Set bounding box. Will be used as an oriented bounding box to test whether the camera is inside
     void SetBoundingBox(const BoundingBox& box);

+ 3 - 2
Engine/Network/Connection.cpp

@@ -748,7 +748,7 @@ void Connection::ProcessExistingNode(Node* node)
     // Check if attributes have changed
     bool deltaUpdate, latestData;
     
-    node->PrepareUpdates(deltaUpdateBits_, nodeState.attributes_, deltaUpdate, latestData);
+    node->PrepareUpdates(deltaUpdateBits_, classCurrentState_[node->GetType()], nodeState.attributes_, deltaUpdate, latestData);
     
     // Check if user variables have changed. Note: variable removal is not supported
     changedVars_.Clear();
@@ -827,7 +827,8 @@ void Connection::ProcessExistingNode(Node* node)
             ComponentReplicationState& componentState = j->second_;
             componentState.frameNumber_ = frameNumber_;
             
-            component->PrepareUpdates(deltaUpdateBits_, componentState.attributes_, deltaUpdate, latestData);
+            component->PrepareUpdates(deltaUpdateBits_, classCurrentState_[component->GetType()], componentState.attributes_,
+                deltaUpdate, latestData);
             
             // Send deltaupdate message if necessary
             if (deltaUpdate)

+ 2 - 0
Engine/Network/Connection.h

@@ -148,6 +148,8 @@ private:
     HashSet<ShortStringHash> changedVars_;
     /// Internal set for already processed nodes during an update
     HashSet<Node*> processedNodes_;
+    /// Internal map of preallocated variants of correct type per networked object class
+    Map<ShortStringHash, Vector<Variant> > classCurrentState_;
     /// Reused message buffer
     VectorBuffer msg_;
     /// Current controls

+ 2 - 2
Engine/Physics/CollisionShape.cpp

@@ -337,9 +337,9 @@ void CollisionShape::RegisterObject(Context* context)
     ACCESSOR_ATTRIBUTE(CollisionShape, VAR_RESOURCEREF, "Model", GetModelAttr, SetModelAttr, ResourceRef, ResourceRef(Model::GetTypeStatic()), AM_DEFAULT);
 }
 
-void CollisionShape::OnSetAttribute(const AttributeInfo& attr, const Variant& value)
+void CollisionShape::OnSetAttribute(const AttributeInfo& attr, const Variant& src)
 {
-    Serializable::OnSetAttribute(attr, value);
+    Serializable::OnSetAttribute(attr, src);
     
     // Change of some attributes requires the geometry to be recreated
     switch (attr.offset_)

+ 1 - 1
Engine/Physics/CollisionShape.h

@@ -100,7 +100,7 @@ public:
     static void RegisterObject(Context* context);
     
     /// Handle attribute write access
-    virtual void OnSetAttribute(const AttributeInfo& attr, const Variant& value);
+    virtual void OnSetAttribute(const AttributeInfo& attr, const Variant& src);
     /// Perform finalization after a scene load or network update
     virtual void FinishUpdate();
     

+ 2 - 2
Engine/Physics/Joint.cpp

@@ -69,9 +69,9 @@ void Joint::RegisterObject(Context* context)
     ACCESSOR_ATTRIBUTE(Joint, VAR_VECTOR3, "Axis", GetAxis, SetAxis, Vector3, Vector3::ZERO, AM_DEFAULT);
 }
 
-void Joint::OnSetAttribute(const AttributeInfo& attr, const Variant& value)
+void Joint::OnSetAttribute(const AttributeInfo& attr, const Variant& src)
 {
-    Serializable::OnSetAttribute(attr, value);
+    Serializable::OnSetAttribute(attr, src);
     
     // Change of the joint type requires the joint to be recreated
     if (attr.offset_ == offsetof(Joint, type_))

+ 1 - 1
Engine/Physics/Joint.h

@@ -52,7 +52,7 @@ public:
     static void RegisterObject(Context* context);
     
     /// Handle attribute write access
-    virtual void OnSetAttribute(const AttributeInfo& attr, const Variant& value);
+    virtual void OnSetAttribute(const AttributeInfo& attr, const Variant& src);
     /// Perform finalization after a scene load or network update
     virtual void FinishUpdate();
     /// Return the depended on nodes to order network updates

+ 97 - 68
Engine/Scene/Serializable.cpp

@@ -31,17 +31,6 @@
 
 #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) :
@@ -54,12 +43,12 @@ Serializable::~Serializable()
 {
 }
 
-void Serializable::OnSetAttribute(const AttributeInfo& attr, const Variant& value)
+void Serializable::OnSetAttribute(const AttributeInfo& attr, const Variant& src)
 {
     // Check for accessor function mode
     if (attr.accessor_)
     {
-        attr.accessor_->Set(this, value);
+        attr.accessor_->Set(this, src);
         return;
     }
     
@@ -71,70 +60,73 @@ void Serializable::OnSetAttribute(const AttributeInfo& attr, const Variant& valu
     case VAR_INT:
         // If enum type, use the low 8 bits only (assume full value to be initialized)
         if (attr.enumNames_)
-            *(reinterpret_cast<unsigned char*>(dest)) = value.GetInt();
+            *(reinterpret_cast<unsigned char*>(dest)) = src.GetInt();
         else
-            *(reinterpret_cast<int*>(dest)) = value.GetInt();
+            *(reinterpret_cast<int*>(dest)) = src.GetInt();
         break;
         
     case VAR_BOOL:
-        *(reinterpret_cast<bool*>(dest)) = value.GetBool();
+        *(reinterpret_cast<bool*>(dest)) = src.GetBool();
         break;
         
     case VAR_FLOAT:
-        *(reinterpret_cast<float*>(dest)) = value.GetFloat();
+        *(reinterpret_cast<float*>(dest)) = src.GetFloat();
         break;
         
     case VAR_VECTOR2:
-        *(reinterpret_cast<Vector2*>(dest)) = value.GetVector2();
+        *(reinterpret_cast<Vector2*>(dest)) = src.GetVector2();
         break;
         
     case VAR_VECTOR3:
-        *(reinterpret_cast<Vector3*>(dest)) = value.GetVector3();
+        *(reinterpret_cast<Vector3*>(dest)) = src.GetVector3();
         break;
         
     case VAR_VECTOR4:
-        *(reinterpret_cast<Vector4*>(dest)) = value.GetVector4();
+        *(reinterpret_cast<Vector4*>(dest)) = src.GetVector4();
         break;
         
     case VAR_QUATERNION:
-        *(reinterpret_cast<Quaternion*>(dest)) = value.GetQuaternion();
+        *(reinterpret_cast<Quaternion*>(dest)) = src.GetQuaternion();
         break;
         
     case VAR_COLOR:
-        *(reinterpret_cast<Color*>(dest)) = value.GetColor();
+        *(reinterpret_cast<Color*>(dest)) = src.GetColor();
         break;
         
     case VAR_STRING:
-        *(reinterpret_cast<String*>(dest)) = value.GetString();
+        *(reinterpret_cast<String*>(dest)) = src.GetString();
         break;
         
     case VAR_BUFFER:
-        *(reinterpret_cast<PODVector<unsigned char>*>(dest)) = value.GetBuffer();
+        *(reinterpret_cast<PODVector<unsigned char>*>(dest)) = src.GetBuffer();
         break;
         
     case VAR_RESOURCEREF:
-        *(reinterpret_cast<ResourceRef*>(dest)) = value.GetResourceRef();
+        *(reinterpret_cast<ResourceRef*>(dest)) = src.GetResourceRef();
         break;
         
     case VAR_RESOURCEREFLIST:
-        *(reinterpret_cast<ResourceRefList*>(dest)) = value.GetResourceRefList();
+        *(reinterpret_cast<ResourceRefList*>(dest)) = src.GetResourceRefList();
         break;
         
     case VAR_VARIANTVECTOR:
-        *(reinterpret_cast<VariantVector*>(dest)) = value.GetVariantVector();
+        *(reinterpret_cast<VariantVector*>(dest)) = src.GetVariantVector();
         break;
         
     case VAR_VARIANTMAP:
-        *(reinterpret_cast<VariantMap*>(dest)) = value.GetVariantMap();
+        *(reinterpret_cast<VariantMap*>(dest)) = src.GetVariantMap();
         break;
     }
 }
 
-Variant Serializable::OnGetAttribute(const AttributeInfo& attr)
+void Serializable::OnGetAttribute(const AttributeInfo& attr, Variant& dest)
 {
     // Check for accessor function mode
     if (attr.accessor_)
-        return attr.accessor_->Get(this);
+    {
+        attr.accessor_->Get(this, dest);
+        return;
+    }
     
     // Calculate the source address
     void* src = reinterpret_cast<unsigned char*>(this) + attr.offset_;
@@ -144,51 +136,63 @@ Variant Serializable::OnGetAttribute(const AttributeInfo& attr)
     case VAR_INT:
         // If enum type, use the low 8 bits only
         if (attr.enumNames_)
-            return Variant(*(reinterpret_cast<const unsigned char*>(src)));
+            dest = *(reinterpret_cast<const unsigned char*>(src));
         else
-            return Variant(*(reinterpret_cast<const int*>(src)));
+            dest = *(reinterpret_cast<const int*>(src));
+        break;
         
     case VAR_BOOL:
-        return Variant(*(reinterpret_cast<const bool*>(src)));
+        dest = *(reinterpret_cast<const bool*>(src));
+        break;
         
     case VAR_FLOAT:
-        return Variant(*(reinterpret_cast<const float*>(src)));
+        dest = *(reinterpret_cast<const float*>(src));
+        break;
         
     case VAR_VECTOR2:
-        return Variant(*(reinterpret_cast<const Vector2*>(src)));
+        dest = *(reinterpret_cast<const Vector2*>(src));
+        break;
         
     case VAR_VECTOR3:
-        return Variant(*(reinterpret_cast<const Vector3*>(src)));
+        dest = *(reinterpret_cast<const Vector3*>(src));
+        break;
         
     case VAR_VECTOR4:
-        return Variant(*(reinterpret_cast<const Vector4*>(src)));
+        dest = *(reinterpret_cast<const Vector4*>(src));
+        break;
         
     case VAR_QUATERNION:
-        return Variant(*(reinterpret_cast<const Quaternion*>(src)));
+        dest = *(reinterpret_cast<const Quaternion*>(src));
+        break;
         
     case VAR_COLOR:
-        return Variant(*(reinterpret_cast<const Color*>(src)));
+        dest = *(reinterpret_cast<const Color*>(src));
+        break;
         
     case VAR_STRING:
-        return Variant(*(reinterpret_cast<const String*>(src)));
+        dest = *(reinterpret_cast<const String*>(src));
+        break;
         
     case VAR_BUFFER:
-        return Variant(*(reinterpret_cast<const PODVector<unsigned char>*>(src)));
+        dest = *(reinterpret_cast<const PODVector<unsigned char>*>(src));
+        break;
         
     case VAR_RESOURCEREF:
-        return Variant(*(reinterpret_cast<const ResourceRef*>(src)));
+        dest = *(reinterpret_cast<const ResourceRef*>(src));
+        break;
         
     case VAR_RESOURCEREFLIST:
-        return Variant(*(reinterpret_cast<const ResourceRefList*>(src)));
+        dest = *(reinterpret_cast<const ResourceRefList*>(src));
+        break;
         
     case VAR_VARIANTVECTOR:
-        return Variant(*(reinterpret_cast<const VariantVector*>(src)));
+        dest = *(reinterpret_cast<const VariantVector*>(src));
+        break;
         
     case VAR_VARIANTMAP:
-        return Variant(*(reinterpret_cast<const VariantMap*>(src)));
+        dest = *(reinterpret_cast<const VariantMap*>(src));
+        break;
     }
-    
-    return Variant();
 }
 
 bool Serializable::Load(Deserializer& source)
@@ -225,6 +229,7 @@ bool Serializable::Save(Serializer& dest)
     if (!attributes)
         return true;
     
+    Variant value;
     inSerialization_ = true;
     
     for (unsigned i = 0; i < attributes->Size(); ++i)
@@ -233,7 +238,8 @@ bool Serializable::Save(Serializer& dest)
         if (!(attr.mode_ & AM_FILE))
             continue;
         
-        if (!dest.WriteVariantData(OnGetAttribute(attr)))
+        OnGetAttribute(attr, value);
+        if (!dest.WriteVariantData(value))
         {
             LOGERROR("Could not save " + GetTypeName() + ", writing to stream failed");
             inSerialization_ = false;
@@ -323,6 +329,7 @@ bool Serializable::SaveXML(XMLElement& dest)
     if (!attributes)
         return true;
     
+    Variant value;
     inSerialization_ = true;
     
     for (unsigned i = 0; i < attributes->Size(); ++i)
@@ -333,15 +340,16 @@ bool Serializable::SaveXML(XMLElement& dest)
         
         XMLElement attrElem = dest.CreateChild("attribute");
         attrElem.SetString("name", String(attr.name_));
+        OnGetAttribute(attr, value);
         // If enums specified, set as an enum string. Otherwise set directly as a Variant
         if (attr.enumNames_)
         {
-            int enumValue = OnGetAttribute(attr).GetInt();
+            int enumValue = value.GetInt();
             attrElem.SetString("type", "Enum");
             attrElem.SetString("value", String(attr.enumNames_[enumValue]));
         }
         else
-            attrElem.SetVariant(OnGetAttribute(attr));
+            attrElem.SetVariant(value);
     }
     
     inSerialization_ = false;
@@ -410,24 +418,26 @@ bool Serializable::SetAttribute(const String& name, const Variant& value)
     return false;
 }
 
-void Serializable::WriteInitialDeltaUpdate(Serializer& dest, PODVector<unsigned char>& deltaUpdateBits, Vector<Variant>& lastSentState)
+void Serializable::WriteInitialDeltaUpdate(Serializer& dest, PODVector<unsigned char>& deltaUpdateBits,
+    Vector<Variant>& replicationState)
 {
     const Vector<AttributeInfo>* attributes = GetNetworkAttributes();
     if (!attributes)
         return;
     unsigned numAttributes = attributes->Size();
     
-    lastSentState.Resize(numAttributes);
+    replicationState.Resize(numAttributes);
     deltaUpdateBits.Resize((numAttributes + 7) >> 3);
     for (unsigned i = 0; i < deltaUpdateBits.Size(); ++i)
         deltaUpdateBits[i] = 0;
     
-    // Set initial values to the last sent state and compare against defaults
+    // Set initial attribute values and compare against defaults
     for (unsigned i = 0; i < numAttributes; ++i)
     {
         const AttributeInfo& attr = attributes->At(i);
-        lastSentState[i] = OnGetAttribute(attr);
-        if (lastSentState[i] != attr.defaultValue_)
+        
+        OnGetAttribute(attr, replicationState[i]);
+        if (replicationState[i] != attr.defaultValue_)
             deltaUpdateBits[i >> 3] |= (1 << (i & 7));
     }
     
@@ -437,13 +447,14 @@ void Serializable::WriteInitialDeltaUpdate(Serializer& dest, PODVector<unsigned
     for (unsigned i = 0; i < numAttributes; ++i)
     {
         const AttributeInfo& attr = attributes->At(i);
+        
         if (deltaUpdateBits[i >> 3] & (1 << (i & 7)))
-            dest.WriteVariantData(lastSentState[i]);
+            dest.WriteVariantData(replicationState[i]);
     }
 }
 
-void Serializable::PrepareUpdates(PODVector<unsigned char>& deltaUpdateBits, Vector<Variant>& lastSentState, bool& deltaUpdate,
-    bool& latestData)
+void Serializable::PrepareUpdates(PODVector<unsigned char>& deltaUpdateBits, Vector<Variant>& classCurrentState,
+    Vector<Variant>& replicationState, bool& deltaUpdate, bool& latestData)
 {
     deltaUpdate = false;
     latestData = false;
@@ -453,6 +464,10 @@ void Serializable::PrepareUpdates(PODVector<unsigned char>& deltaUpdateBits, Vec
         return;
     unsigned numAttributes = attributes->Size();
     
+    // If class-specific current state has not been previously used, resize it now
+    if (classCurrentState.Empty())
+        classCurrentState.Resize(numAttributes);
+    
     deltaUpdateBits.Resize((numAttributes + 7) >> 3);
     for (unsigned i = 0; i < deltaUpdateBits.Size(); ++i)
         deltaUpdateBits[i] = 0;
@@ -462,8 +477,10 @@ void Serializable::PrepareUpdates(PODVector<unsigned char>& deltaUpdateBits, Vec
         const AttributeInfo& attr = attributes->At(i);
         
         // Check for attribute change
-        if (CompareAndCopyVariant(OnGetAttribute(attr), lastSentState[i]))
+        OnGetAttribute(attr, classCurrentState[i]);
+        if (classCurrentState[i] != replicationState[i])
         {
+            replicationState[i] = classCurrentState[i];
             if (attr.mode_ & AM_LATESTDATA)
                 latestData = true;
             else
@@ -475,7 +492,7 @@ void Serializable::PrepareUpdates(PODVector<unsigned char>& deltaUpdateBits, Vec
     }
 }
 
-void Serializable::WriteDeltaUpdate(Serializer& dest, PODVector<unsigned char>& deltaUpdateBits, Vector<Variant>& lastSentState)
+void Serializable::WriteDeltaUpdate(Serializer& dest, PODVector<unsigned char>& deltaUpdateBits, Vector<Variant>& replicationState)
 {
     const Vector<AttributeInfo>* attributes = GetNetworkAttributes();
     if (!attributes)
@@ -488,12 +505,13 @@ void Serializable::WriteDeltaUpdate(Serializer& dest, PODVector<unsigned char>&
     for (unsigned i = 0; i < numAttributes; ++i)
     {
         const AttributeInfo& attr = attributes->At(i);
+        
         if (deltaUpdateBits[i >> 3] & (1 << (i & 7)))
-            dest.WriteVariantData(lastSentState[i]);
+            dest.WriteVariantData(replicationState[i]);
     }
 }
 
-void Serializable::WriteLatestDataUpdate(Serializer& dest, Vector<Variant>& lastSentState)
+void Serializable::WriteLatestDataUpdate(Serializer& dest, Vector<Variant>& replicationState)
 {
     const Vector<AttributeInfo>* attributes = GetNetworkAttributes();
     if (!attributes)
@@ -503,8 +521,9 @@ void Serializable::WriteLatestDataUpdate(Serializer& dest, Vector<Variant>& last
     for (unsigned i = 0; i < numAttributes; ++i)
     {
         const AttributeInfo& attr = attributes->At(i);
+        
         if (attr.mode_ & AM_LATESTDATA)
-            dest.WriteVariantData(lastSentState[i]);
+            dest.WriteVariantData(replicationState[i]);
     }
 }
 
@@ -521,6 +540,7 @@ void Serializable::ReadDeltaUpdate(Deserializer& source, PODVector<unsigned char
     for (unsigned i = 0; i < numAttributes && !source.IsEof(); ++i)
     {
         const AttributeInfo& attr = attributes->At(i);
+        
         if (deltaUpdateBits[i >> 3] & (1 << (i & 7)))
             OnSetAttribute(attr, source.ReadVariant(attr.type_));
     }
@@ -536,6 +556,7 @@ void Serializable::ReadLatestDataUpdate(Deserializer& source)
     for (unsigned i = 0; i < numAttributes && !source.IsEof(); ++i)
     {
         const AttributeInfo& attr = attributes->At(i);
+        
         if (attr.mode_ & AM_LATESTDATA)
             OnSetAttribute(attr, source.ReadVariant(attr.type_));
     }
@@ -543,30 +564,38 @@ void Serializable::ReadLatestDataUpdate(Deserializer& source)
 
 Variant Serializable::GetAttribute(unsigned index)
 {
+    Variant ret;
+    
     const Vector<AttributeInfo>* attributes = context_->GetAttributes(GetType());
     if (!attributes || index >= attributes->Size())
-        return Variant();
+        return ret;
     
-    return OnGetAttribute(attributes->At(index));
+    OnGetAttribute(attributes->At(index), ret);
+    return ret;
 }
 
 Variant Serializable::GetAttribute(const String& name)
 {
+    Variant ret;
+    
     const Vector<AttributeInfo>* attributes = context_->GetAttributes(GetType());
     if (!attributes)
     {
         LOGERROR(GetTypeName() + " has no attributes");
-        return Variant();
+        return ret;
     }
     
     for (Vector<AttributeInfo>::ConstIterator i = attributes->Begin(); i != attributes->End(); ++i)
     {
         if (i->name_ == name)
-            return OnGetAttribute(*i);
+        {
+            OnGetAttribute(*i, ret);
+            return ret;
+        }
     }
     
     LOGERROR("Could not find attribute " + String(name) + " in " + GetTypeName());
-    return Variant();
+    return ret;
 }
 
 unsigned Serializable::GetNumAttributes() const

+ 10 - 10
Engine/Scene/Serializable.h

@@ -42,9 +42,9 @@ public:
     virtual ~Serializable();
     
     /// Handle attribute write access. Default implementation writes to the variable at offset, or invokes the set accessor
-    virtual void OnSetAttribute(const AttributeInfo& attr, const Variant& value);
+    virtual void OnSetAttribute(const AttributeInfo& attr, const Variant& src);
     /// Handle attribute read access. Default implementation reads the variable at offset, or invokes the get accessor
-    virtual Variant OnGetAttribute(const AttributeInfo& attr);
+    virtual void OnGetAttribute(const AttributeInfo& attr, Variant& dest);
     /// Load from binary data. Return true if successful
     virtual bool Load(Deserializer& source);
     /// Save as binary data. Return true if successful
@@ -61,13 +61,13 @@ public:
     /// Set attribute by name. Return true if successfully set
     bool SetAttribute(const String& name, const Variant& value);
     /// Write initial delta network update (compared to default attribute values) and prepare the last sent state
-    void WriteInitialDeltaUpdate(Serializer& dest, PODVector<unsigned char>& deltaUpdateBits, Vector<Variant>& lastSentState);
+    void WriteInitialDeltaUpdate(Serializer& dest, PODVector<unsigned char>& deltaUpdateBits, Vector<Variant>& replicationState);
     /// Prepare delta and latest data network updates. Needs a previously prepared last sent state from WriteInitialDeltaUpdate()
-    void PrepareUpdates(PODVector<unsigned char>& deltaUpdateBits, Vector<Variant>& lastSentState, bool& deltaUpdate, bool& latestData);
+    void PrepareUpdates(PODVector<unsigned char>& deltaUpdateBits, Vector<Variant>& classCurrentState, Vector<Variant>& replicationState, bool& deltaUpdate, bool& latestData);
     /// Write a delta network update prepared with PrepareUpdates()
-    void WriteDeltaUpdate(Serializer& dest, PODVector<unsigned char>& deltaUpdateBits, Vector<Variant>& lastSentState);
+    void WriteDeltaUpdate(Serializer& dest, PODVector<unsigned char>& deltaUpdateBits, Vector<Variant>& replicationState);
     /// Write a latestdata network update prepared with PrepareUpdates()
-    void WriteLatestDataUpdate(Serializer& dest, Vector<Variant>& lastSentState);
+    void WriteLatestDataUpdate(Serializer& dest, Vector<Variant>& replicationState);
     /// Read and apply a network delta update
     void ReadDeltaUpdate(Deserializer& source, PODVector<unsigned char>& deltaUpdateBits);
     /// Read and apply a network latest data update
@@ -106,10 +106,10 @@ public:
     }
     
     /// Invoke getter function
-    virtual Variant Get(Serializable* ptr)
+    virtual void Get(Serializable* ptr, Variant& dest)
     {
         T* classPtr = static_cast<T*>(ptr);
-        return Variant((classPtr->*getFunction_)());
+        dest = (classPtr->*getFunction_)();
     }
     
     /// Invoke setter function
@@ -140,10 +140,10 @@ public:
     }
     
     /// Invoke getter function
-    virtual Variant Get(Serializable* ptr)
+    virtual void Get(Serializable* ptr, Variant& dest)
     {
         T* classPtr = static_cast<T*>(ptr);
-        return Variant((classPtr->*getFunction_)());
+        dest = (classPtr->*getFunction_)();
     }
     
     /// Invoke setter function