home *** CD-ROM | disk | FTP | other *** search
/ Game Programming in C++ - Start to Finish / GameProgrammingS.iso / developer_install / ReplicaNetFreewareV5_4.exe / data1.cab / Program_Executable_Files / Example6 / DataBlock_GenericSTLVirtual.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2005-10-30  |  6.7 KB  |  246 lines

  1. /* START_LICENSE_HEADER
  2.  
  3. Copyright (C) 2000 Martin Piper, original design and program code
  4. Copyright (C) 2001-2005 Replica Software
  5.  
  6. This program file is copyright (C) Replica Software and can only be used under license.
  7. For more information visit: http://www.replicanet.com/
  8. Or email: info@replicanet.com
  9.  
  10. END_LICENSE_HEADER */
  11. #if defined(_WIN32)
  12. #pragma warning(disable : 4786)
  13. #endif
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <assert.h>
  17. #include "DataBlock_GenericSTLVirtual.h"
  18. #include "RNReplicaNet/Inc/ReplicaNet.h"
  19. #include "RNPlatform/Inc/MessageHelper.h"
  20. #include "RNPlatform/Inc/MemoryTracking.h"
  21.  
  22. using namespace RNReplicaNet;
  23.  
  24. DataBlock_GenericSTLVirtual::DataBlock_GenericSTLVirtual() : mData(0)
  25. {
  26.     // Because we are going to be updating an stl list or vector then we want to make sure updates are in order.
  27.     SetReliableFlag(true);
  28. }
  29.  
  30. DataBlock_GenericSTLVirtual::~DataBlock_GenericSTLVirtual()
  31. {
  32.     std::map<int,SessionBlock *>::iterator st,en;
  33.     st = mPerSessionData.begin();
  34.     en = mPerSessionData.end();
  35.  
  36.     // Delete the remaining session blocks attached to this datablock
  37.     while(st != en)
  38.     {
  39.         SessionBlock *sessdataptr = (*st++).second;
  40.         delete sessdataptr;
  41.     }
  42. }
  43.  
  44. void DataBlock_GenericSTLVirtual::Poll(DataBlockReason *reason)
  45. {
  46.     if (!reason)
  47.     {
  48.         return;
  49.     }
  50.  
  51.     switch (reason->mReasonCode)
  52.     {
  53.         case kDataBlockReason_SomeoneJoined:
  54.         {
  55.             if (!reason->mMessageHelper)
  56.             {
  57.                 return;
  58.             }
  59.             SessionBlock *sessdataptr = new SessionBlock(reason->mSessionReference);
  60.             DoInitialSettingsFor(sessdataptr,GetElementSize());
  61.             // Insert SessionBlock into the std::map with the key reason->mSessionReference
  62.             mPerSessionData[reason->mSessionReference] = sessdataptr;
  63.  
  64.             // Someone joined so calculate an immediate update
  65.             DataBlock::Poll(reason);
  66.             // Number of elements
  67.             reason->mMessageHelper->AddVariable(&sessdataptr->mNumElements,sizeof(sessdataptr->mNumElements));
  68.             // Number of elements changed
  69.             reason->mMessageHelper->AddVariable(&sessdataptr->mNumElements,sizeof(sessdataptr->mNumElements));
  70.             int i;
  71.             for (i=0;i<sessdataptr->mNumElements;i++)
  72.             {
  73.                 reason->mMessageHelper->AddVariable(&i,sizeof(i));
  74.                 reason->mMessageHelper->AddVariable(sessdataptr->mOrderedElementData[i],GetElementSize());
  75.             }
  76.  
  77.             return;
  78.         }
  79.  
  80.         case kDataBlockReason_SomeoneLeft:
  81.         {
  82.             std::map<int,SessionBlock *>::iterator found;
  83.             found = mPerSessionData.find(reason->mSessionReference);
  84.             if (found != mPerSessionData.end())
  85.             {
  86.                 SessionBlock *sessdataptr = (*found).second;
  87.                 assert (sessdataptr->mSessionID == reason->mSessionReference);
  88.                 mPerSessionData.erase(found);
  89.                 delete sessdataptr;
  90.                 return;
  91.             }
  92.             break;
  93.         }
  94.  
  95.         case kDataBlockReason_RecordingNormalPoll:
  96.         {
  97.             // Send the best of what we have so far. This happens to be the current replica state.
  98.             DataBlock::Poll(reason);
  99.             int numElements = GetNumberOfElements();
  100.             reason->mMessageHelper->AddVariable(&numElements,sizeof(numElements));
  101.             // Number of elements changed
  102.             reason->mMessageHelper->AddVariable(&numElements,sizeof(numElements));
  103.             int i;
  104.             for (i=0;i<numElements;i++)
  105.             {
  106.                 reason->mMessageHelper->AddVariable(&i,sizeof(i));
  107.                 reason->mMessageHelper->AddVariable(GetElementPointerAt(i),GetElementSize());
  108.             }
  109.             break;
  110.         }
  111.  
  112.         case kDataBlockReason_NormalPoll:
  113.         {
  114.             if (!reason->mMessageHelper)
  115.             {
  116.                 return;
  117.             }
  118.  
  119.             std::map<int,SessionBlock *>::iterator found;
  120.             found = mPerSessionData.find(reason->mSessionReference);
  121.             if (found != mPerSessionData.end())
  122.             {
  123.                 SessionBlock *sessdataptr = (*found).second;
  124.                 assert (sessdataptr->mSessionID == reason->mSessionReference);
  125.  
  126.                 int numElementsChanged = 0;
  127.                 bool theSizeChanged = false;
  128.                 int i;
  129.                 for (i=0;i<GetNumberOfElements();i++)
  130.                 {
  131.                     // If the data is the same then do nothing
  132.                     if (memcmp(sessdataptr->mOrderedElementData[i],GetElementPointerAt(i),GetElementSize()) != 0)
  133.                     {
  134.                         numElementsChanged++;
  135.                     }
  136.                 }
  137.  
  138.                 if (GetNumberOfElements() != sessdataptr->mNumElements)
  139.                 {
  140.                     theSizeChanged = true;
  141.                 }
  142.  
  143.                 // If either the size or the contents have changed then
  144.                 if (theSizeChanged || numElementsChanged > 0)
  145.                 {
  146.                     // Send the update data
  147.                     DataBlock::Poll(reason);
  148.                     // Number of elements
  149.                     reason->mMessageHelper->AddVariable(&sessdataptr->mNumElements,sizeof(sessdataptr->mNumElements));
  150.                     // Number of elements changed
  151.                     reason->mMessageHelper->AddVariable(&numElementsChanged,sizeof(numElementsChanged));
  152.                     int i;
  153.                     for (i=0;i<sessdataptr->mNumElements;i++)
  154.                     {
  155.                         if (memcmp(sessdataptr->mOrderedElementData[i],GetElementPointerAt(i),GetElementSize()) != 0)
  156.                         {
  157.                             reason->mMessageHelper->AddVariable(&i,sizeof(i));
  158.                             reason->mMessageHelper->AddVariable(GetElementPointerAt(i),GetElementSize());
  159.                         }
  160.                     }
  161.  
  162.                     // After sending the update then copy what we sent
  163.                     DoInitialSettingsFor(sessdataptr,GetElementSize());
  164.                 }
  165.  
  166.                 return;
  167.             }
  168.             break;
  169.         }
  170.  
  171.         default:
  172.             break;
  173.     }
  174. }
  175.  
  176. void DataBlock_GenericSTLVirtual::ParseMessage(MessageHelper *message)
  177. {
  178.     // Decode our updates
  179.     int newSize;
  180.     int numChanged;
  181.     message->GetVariable(&newSize,sizeof(newSize));
  182.     message->GetVariable(&numChanged,sizeof(numChanged));
  183.  
  184.     SetNumberOfElements(newSize);
  185.     int i;
  186.     for (i=0;i<numChanged;i++)
  187.     {
  188.         int index;
  189.         message->GetVariable(&index,sizeof(index));
  190.         void *data = GetElementPointerAt(index);
  191.         message->GetVariable(data,GetElementSize());
  192.     }
  193. }
  194.  
  195. DataBlock_GenericSTLVirtual::SessionBlock::SessionBlock(int sessid)
  196. {
  197.     mSessionID = sessid;
  198.     mOrderedElementData = 0;
  199.     mNumElements = 0;
  200. }
  201.  
  202. DataBlock_GenericSTLVirtual::SessionBlock::~SessionBlock()
  203. {
  204.     if (mOrderedElementData)
  205.     {
  206.         int i;
  207.         for (i=0;i<mNumElements;i++)
  208.         {
  209.             free(mOrderedElementData[i]);
  210.         }
  211.         free(mOrderedElementData);
  212.         mOrderedElementData = 0;
  213.     }
  214. }
  215.  
  216. void DataBlock_GenericSTLVirtual::DoInitialSettingsFor(SessionBlock *sessionBlock,const int elementSize)
  217. {
  218.     // First free all of our blocks
  219.     if (sessionBlock->mOrderedElementData)
  220.     {
  221.         int i;
  222.         for (i=0;i<sessionBlock->mNumElements;i++)
  223.         {
  224.             free(sessionBlock->mOrderedElementData[i]);
  225.         }
  226.         free(sessionBlock->mOrderedElementData);
  227.         sessionBlock->mOrderedElementData = 0;
  228.     }
  229.  
  230.     sessionBlock->mNumElements = GetNumberOfElements();
  231.  
  232.     if (sessionBlock->mNumElements > 0)
  233.     {
  234.  
  235.         sessionBlock->mOrderedElementData = (void **) malloc(sizeof(void *) * sessionBlock->mNumElements);
  236.         int i;
  237.         for (i=0;i<sessionBlock->mNumElements;i++)
  238.         {
  239.             sessionBlock->mOrderedElementData[i] = malloc(elementSize);
  240.             void *data = GetElementPointerAt(i);
  241.             memcpy(sessionBlock->mOrderedElementData[i],data,elementSize);
  242.         }
  243.     }
  244. }
  245.  
  246.