Shadowrun: Awakened 29 September 2011 - Build 871
VariableDeltaSerializer.h
Go to the documentation of this file.
00001 #ifndef __VARIABLE_DELTA_SERIALIZER_H
00002 #define __VARIABLE_DELTA_SERIALIZER_H
00003 
00004 #include "VariableListDeltaTracker.h"
00005 #include "DS_MemoryPool.h"
00006 #include "NativeTypes.h"
00007 #include "BitStream.h"
00008 #include "PacketPriority.h"
00009 #include "DS_OrderedList.h"
00010 
00011 namespace RakNet
00012 {
00013 
00030 class VariableDeltaSerializer
00031 {
00032 protected:
00033     struct RemoteSystemVariableHistory;
00034     struct ChangedVariablesList;
00035 
00036 public:
00037     VariableDeltaSerializer();
00038     ~VariableDeltaSerializer();
00039 
00040     struct SerializationContext
00041     {
00042         SerializationContext();
00043         ~SerializationContext();
00044 
00045         RakNetGUID guid;
00046         BitStream *bitStream;
00047         uint32_t rakPeerSendReceipt;
00048         RemoteSystemVariableHistory *variableHistory;
00049         RemoteSystemVariableHistory *variableHistoryIdentical;
00050         RemoteSystemVariableHistory *variableHistoryUnique;
00051         ChangedVariablesList *changedVariables;
00052         uint32_t sendReceipt;
00053         PacketReliability serializationMode;
00054         bool anyVariablesWritten;
00055         bool newSystemSend; // Force send all, do not record
00056     };
00057 
00058     struct DeserializationContext
00059     {
00060         BitStream *bitStream;
00061     };
00062 
00074     void BeginUnreliableAckedSerialize(SerializationContext *context, RakNetGUID _guid, BitStream *_bitStream, uint32_t _sendReceipt);
00075 
00085     void BeginUniqueSerialize(SerializationContext *context, RakNetGUID _guid, BitStream *_bitStream);
00086 
00095     void BeginIdenticalSerialize(SerializationContext *context, bool _isFirstSerializeToThisSystem, BitStream *_bitStream);
00096 
00099     void EndSerialize(SerializationContext *context);
00100 
00104     void BeginDeserialize(DeserializationContext *context, BitStream *_bitStream);
00105 
00107     void EndDeserialize(DeserializationContext *context);
00108 
00112     void AddRemoteSystemVariableHistory(RakNetGUID guid);
00113 
00117     void RemoveRemoteSystemVariableHistory(RakNetGUID guid);
00118 
00122     void OnPreSerializeTick(void);
00123 
00140     void OnMessageReceipt(RakNetGUID guid, uint32_t receiptId, bool messageArrived);
00141 
00149     template <class VarType>
00150     void SerializeVariable(SerializationContext *context, const VarType &variable)
00151     {
00152         if (context->newSystemSend)
00153         {
00154             if (context->variableHistory->variableListDeltaTracker.IsPastEndOfList()==false)
00155             {
00156                 // previously sent data to another system
00157                 context->bitStream->Write(true);
00158                 context->bitStream->Write(variable);
00159                 context->anyVariablesWritten=true;
00160             }
00161             else
00162             {
00163                 // never sent data to another system
00164                 context->variableHistory->variableListDeltaTracker.WriteVarToBitstream(variable, context->bitStream);
00165                 context->anyVariablesWritten=true;
00166             }
00167         }
00168         else if (context->serializationMode==UNRELIABLE_WITH_ACK_RECEIPT)
00169         {
00170             context->anyVariablesWritten|=
00171             context->variableHistory->variableListDeltaTracker.WriteVarToBitstream(variable, context->bitStream, context->changedVariables->bitField, context->changedVariables->bitWriteIndex++);
00172         }
00173         else
00174         {
00175             if (context->variableHistoryIdentical)
00176             {
00177                 // Identical serialization to a number of systems
00178                 if (didComparisonThisTick==false)
00179                     context->anyVariablesWritten|=
00180                     context->variableHistory->variableListDeltaTracker.WriteVarToBitstream(variable, context->bitStream);
00181                 // Else bitstream is written to at the end
00182             }
00183             else
00184             {
00185                 // Per-system serialization
00186                 context->anyVariablesWritten|=
00187                     context->variableHistory->variableListDeltaTracker.WriteVarToBitstream(variable, context->bitStream);
00188             }
00189         }
00190     }
00191 
00197     template <class VarType>
00198     bool DeserializeVariable(DeserializationContext *context, VarType &variable)
00199     {
00200         return VariableListDeltaTracker::ReadVarFromBitstream(variable, context->bitStream);
00201     }
00202 
00203 
00204 
00205 protected:
00206 
00207     // For a given send receipt from RakPeer::Send() track which variables we updated
00208     // That way if that send does not arrive (ID_SND_RECEIPT_LOSS) we can mark those variables as dirty to resend them with current values
00209     struct ChangedVariablesList
00210     {
00211         uint32_t sendReceipt;
00212         unsigned short bitWriteIndex;
00213         unsigned char bitField[56];
00214     };
00215 
00216     // static int Replica2ObjectComp( const uint32_t &key, ChangedVariablesList* const &data );
00217 
00218     static int UpdatedVariablesListPtrComp( const uint32_t &key, ChangedVariablesList* const &data );
00219 
00220     // For each remote system, track the last values of variables we sent to them, and the history of what values changed per call to Send()
00221     // Every serialize if a variable changes from its last value, send it out again
00222     // Also if a send does not arrive (ID_SND_RECEIPT_LOSS) we use updatedVariablesHistory to mark those variables as dirty, to resend them unreliably with the current values
00223     struct RemoteSystemVariableHistory
00224     {
00225         RakNetGUID guid;
00226         VariableListDeltaTracker variableListDeltaTracker;
00227         DataStructures::OrderedList<uint32_t,ChangedVariablesList*,VariableDeltaSerializer::UpdatedVariablesListPtrComp> updatedVariablesHistory;
00228     };
00231     DataStructures::List<RemoteSystemVariableHistory*> remoteSystemVariableHistoryList;
00232 
00233     // Because the ChangedVariablesList is created every serialize and destroyed every receipt I use a pool to avoid fragmentation
00234     DataStructures::MemoryPool<ChangedVariablesList> updatedVariablesMemoryPool;
00235 
00236     bool didComparisonThisTick;
00237     RakNet::BitStream identicalSerializationBs;
00238 
00239     void FreeVarsAssociatedWithReceipt(RakNetGUID guid, uint32_t receiptId);
00240     void DirtyAndFreeVarsAssociatedWithReceipt(RakNetGUID guid, uint32_t receiptId);
00241     unsigned int GetVarsWrittenPerRemoteSystemListIndex(RakNetGUID guid);
00242     void RemoveRemoteSystemVariableHistory(void);
00243 
00244     RemoteSystemVariableHistory* GetRemoteSystemVariableHistory(RakNetGUID guid);
00245 
00246     ChangedVariablesList *AllocChangedVariablesList(void);
00247     void FreeChangedVariablesList(ChangedVariablesList *changedVariables);
00248     void StoreChangedVariablesList(RemoteSystemVariableHistory *variableHistory, ChangedVariablesList *changedVariables, uint32_t sendReceipt);
00249 
00250     RemoteSystemVariableHistory *StartVariableHistoryWrite(RakNetGUID guid);
00251     unsigned int GetRemoteSystemHistoryListIndex(RakNetGUID guid);
00252 
00253 };
00254 
00255 }
00256 
00257 #endif

Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.

GNU Lesser General Public License 3 Sourceforge.net