BVB Source Codes

CRYENGINE Show BreakReplicator_Simple.cpp Source code

Return Download CRYENGINE: download BreakReplicator_Simple.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #include "StdAfx.h"
  4. #include "BreakReplicator.h"
  5. #include "GameContext.h"
  6. #include "ObjectSelector.h"
  7. #include "DebugBreakage.h"
  8. #include "BreakReplicator_Simple.h"
  9. #include "SerializeDirHelper.h"
  10. #include "BreakReplicatorGameObject.h"
  11. #include "NetworkCVars.h"
  12.  
  13. /*
  14.    ---------------------------------------------------------------------------------
  15.    TODO:
  16.  
  17.     - * Host Migration *
  18.  
  19.     - Send pos in part space for all break types
  20.       - But mainly glass
  21.  
  22.     - Better memory allocation instead of DynArray
  23.  
  24.    ---------------------------------------------------------------------------------
  25.  */
  26.  
  27. #if DEBUG_NET_BREAKAGE
  28.         #define DEBUG_ASSERT(x) { if (!(x)) { int* p = 0; *p = 42; } } // crash on purpose!
  29. #else
  30.         #define DEBUG_ASSERT(x)
  31. #endif
  32.  
  33. // Tree Syncing
  34. #define NET_SYNC_TREES 0
  35.  
  36. #if NET_USE_SIMPLE_BREAKAGE
  37.  
  38.         #define NET_MAX_BREAKS 4096
  39.  
  40. class BreakStream;
  41.  
  42.         #define NET_MAX_NUMBER_OF_PARTS                     63
  43.  
  44.         #define WORLD_POS_SAMPLE_DISTANCE_APPART_INACCURATE 2.0f
  45.         #define WORLD_POS_SAMPLE_DISTANCE_APPART_ACCURATE   0.005f
  46.  
  47. struct EmittedProduct
  48. {
  49.         IPhysicalEntity* pent;      // a physics entity that came off
  50.         int              partidSrc; // The part id. Note that a gib can contain more than one part. At the moment we just store the part that has the smallest index
  51.         Vec3             initialVel;
  52.         Vec3             initialAngVel;
  53. };
  54.  
  55. struct JointBreakInfo
  56. {
  57.         int idJoint;
  58.         int partidEpicenter;
  59. };
  60.  
  61. /*
  62.    =======================================================================
  63.    BreakStream
  64.    =======================================================================
  65.  
  66.    A BreakStream holds all the info regarding a particular break.
  67.    On the server it is in k_recording mode and on a client it is
  68.    in k_playing mode
  69.  
  70.    Only one BreakStream can be applied to an IPhysicalEntity at any one time
  71.    Each stream has an index associated with it, which is ascending in time.
  72.    The server decides the break index.
  73.  
  74.  */
  75.  
  76.         #define NET_MAX_NUM_FRAMES_TO_FIND_ENTITY                 200
  77.         #define NET_MAX_NUM_FRAMES_TO_WAIT_FOR_BREAK_DEPENDENCY   200
  78.         #define NET_LEVEL_LOAD_TIME_BEFORE_USING_INAVLID_COUNTERS 15.f
  79.  
  80. static BreakStream s_dummyStream;
  81.  
  82. static const char* BreakStreamGetModeName(uint32 mode)
  83. {
  84.         enum EMode {k_invalid = 0, k_recording, k_playing, k_finished, k_numModes};
  85.         #if DEBUG_NET_BREAKAGE
  86.         static const char* names[BreakStream::k_numModes + 1] = {
  87.                 "invalid",
  88.                 "k_recording",
  89.                 "k_playing",
  90.                 "k_finished",
  91.                 "MODE ERROR",
  92.         };
  93.         return names[min((uint32)mode, (uint32)BreakStream::k_numModes)];
  94.         #endif
  95.         return "";
  96. }
  97.  
  98. static const char* BreakStreamGetTypeName(uint32 type)
  99. {
  100.         #if DEBUG_NET_BREAKAGE
  101.         static const char* names[BreakStream::k_numTypes + 1] = {
  102.                 "unknown",
  103.                 "PartBreak",
  104.                 "PlaneBreak",
  105.                 "DeformBreak",
  106.                 "TYPE ERROR",
  107.         };
  108.         return names[min((uint32)type, (uint32)BreakStream::k_numTypes)];
  109.         #endif
  110.         return "";
  111. }
  112.  
  113. /*
  114.    =======================================================================
  115.    Part BreakStream
  116.    =======================================================================
  117.  */
  118.  
  119. class PartBreak : public BreakStream
  120. {
  121. public:
  122.         PartBreak();
  123.         virtual ~PartBreak();
  124.  
  125.         virtual void    Init(EMode mode);
  126.  
  127.         virtual void    SerializeWith(CBitArray& array);
  128.  
  129.         virtual bool    OnCreatePhysEntityPart(const EventPhysCreateEntityPart* pEvent);
  130.         virtual bool    OnRemovePhysEntityParts(const EventPhysRemoveEntityParts* pEvent);
  131.         virtual bool    OnJointBroken(const EventPhysJointBroken* pEvent);
  132.         virtual void    OnEndFrame();
  133.         virtual void    Playback();
  134.  
  135.         EmittedProduct* FindEmittedProduct(const EventPhysCreateEntityPart* pEvent, bool add);
  136.         virtual void    OnSend(SNetBreakDescription& desc);
  137.  
  138. public:
  139.         EmittedProduct* m_products;
  140.         JointBreakInfo* m_jointsBroken;
  141.  
  142.         uint8           m_numProducts;
  143.         uint8           m_numJointsBroken;
  144.         uint8           m_numProductsCollected;
  145. };
  146.  
  147. /*
  148.    =======================================================================
  149.    Plane BreakStream
  150.    =======================================================================
  151.  */
  152.  
  153. // class PlaneBreak : public BreakStream
  154. // {
  155. // public:
  156. //  PlaneBreak();
  157. //  virtual ~PlaneBreak();
  158.  
  159. //  virtual void SerializeWith(CBitArray& array);
  160.  
  161. //  virtual void OnSend( SNetBreakDescription& desc);
  162.  
  163. //  virtual void Playback();
  164.  
  165. //  virtual bool IsWaitinOnRenderMesh();
  166.  
  167. //  virtual bool IsRenderMeshReady();
  168.  
  169. // public:
  170. //  SBreakEvent m_be;
  171. //  IStatObj* m_pStatObj;
  172. // };
  173.  
  174. /*
  175.    =======================================================================
  176.    Deforming BreakStream
  177.    =======================================================================
  178.  */
  179.  
  180. class DeformBreak : public BreakStream
  181. {
  182. public:
  183.         DeformBreak();
  184.         ~DeformBreak();
  185.  
  186.         virtual void SerializeWith(CBitArray& array);
  187.  
  188.         virtual void OnSpawnEntity(IEntity* pEntity);
  189.         virtual void OnSend(SNetBreakDescription& desc);
  190.  
  191.         virtual void Playback();
  192.  
  193. public:
  194.         SBreakEvent        m_be;
  195.         DynArray<EntityId> m_spawnedEntities;
  196. };
  197.  
  198. /*
  199.    =====================================================================
  200.    Part Breakage
  201.    =====================================================================
  202.  
  203.    For something that should be fairly simple, this is a nightmare of events that have to be collated and reconstructed
  204.  
  205.  
  206.    If an item can break as such p1 (A,B,C,D, E,F)   -> p1 (A,B,C)   and new p2 (D,E,F)
  207.  
  208.    We would get these events:
  209.  
  210.    One,
  211.  
  212.    EventPhysRemoveEntityParts
  213.           pEntity = p1
  214.           partIds = Bit(D)| Bit(E) | Bit(F);
  215.  
  216.    And three,
  217.  
  218.    EventPhysCreateEntityPart
  219.           pEntity = p1
  220.           pEntNew = p2
  221.           partidSrc = D
  222.           nTotParts = 3
  223.  
  224.    EventPhysCreateEntityPart
  225.           pEntity = p1
  226.           pEntNew = p2
  227.           partidSrc = E
  228.           nTotParts = 3
  229.  
  230.    EventPhysCreateEntityPart
  231.           pEntity = p1
  232.           pEntNew = p2
  233.           partidSrc = F
  234.           nTotParts = 3
  235.  
  236.    In breakable manager, the first breaks creates a new temp IEntity to hold the remainding piece (A,B,C)
  237.    This entity is identified through rep->OnSpawn()
  238.    A second entity/or particle is created for the piece (D,E,F)
  239.    The initial velocity is serialised.
  240.  
  241.  */
  242.  
  243. /*
  244.    =====================================================================
  245.    SClientGlassBreak
  246.    =====================================================================
  247.    used to inform the server that the client
  248.    broke the glass
  249.  */
  250.  
  251. // struct SClientGlassBreak
  252. // {
  253. //  void SerializeWith( TSerialize ser )
  254. //  {
  255. //    CBitArray array(&ser);
  256. //    m_planeBreak.SerializeWith(array);
  257. //    if (!array.IsReading())
  258. //      array.WriteToSerializer();
  259. //  }
  260.  
  261. //  PlaneBreak m_planeBreak;
  262. // };
  263.  
  264. /*
  265.    =====================================================================
  266.    Object Identification
  267.    =====================================================================
  268.  
  269.    This is a pain! Entitys have entIds and can be serialised over the network.
  270.    But static things like render nodes, brushes, and foliage have no way to be identified.
  271.    Also they may not exist on the client until they are "activated" by the physics on demand system.
  272.    Making identification difficult!
  273.    Current method is to serialise a pos+hash
  274.  */
  275.  
  276. void CObjectIdentifier::Reset()
  277. {
  278.         m_objType = k_unknown;
  279.         m_holdingEntity = 0;
  280.         m_objCenter.zero();
  281.         m_objHash = 0;
  282. }
  283.  
  284. void CObjectIdentifier::SerializeWith(CBitArray& array, bool includeObjCenter)
  285. {
  286.         // This is such a horrible way to identify stuff over
  287.         // the network, we seriously need to do better!
  288.         if (array.IsReading())
  289.         {
  290.                 Reset();
  291.         }
  292.         int bStatic = iszero((int)m_objType - (int)k_static_entity);
  293.         array.Serialize(bStatic, 0, 1);
  294.         if (bStatic)
  295.         {
  296.                 if (includeObjCenter)
  297.                 {
  298.                         CBreakReplicator::SerialisePosition(array, m_objCenter, CNetworkCVars::Get().BreakMaxWorldSize, CBreakReplicator::m_inaccurateWorldPosNumBits); // If you change this, then you might need to adjust CObjectSelector_Eps
  299.                 }
  300.                 array.Serialize(m_objHash, 0, 0xffffffff);
  301.                 if (m_objHash)
  302.                 {
  303.                         m_objType = k_static_entity;
  304.                 }
  305.         }
  306.         else
  307.         {
  308.                 m_objType = k_entity;
  309.                 array.SerializeEntity(m_holdingEntity);
  310.         }
  311. }
  312.  
  313. void CObjectIdentifier::CreateFromPhysicalEntity(const EventPhysMono* pMono)
  314. {
  315.         IEntity* pEntity;
  316.         IRenderNode* pRenderNode;
  317.         Reset();
  318.         switch (pMono->iForeignData)
  319.         {
  320.         case PHYS_FOREIGN_ID_ENTITY:
  321.                 m_objType = k_unknown;    // We are not sure whether this entity started life as a static, or an normal entity, yet
  322.                 m_holdingEntity = (pEntity = (IEntity*)pMono->pForeignData)->GetId();
  323.                 break;
  324.         case PHYS_FOREIGN_ID_STATIC:
  325.                 m_holdingEntity = 0;
  326.                 m_objType = k_static_entity;
  327.                 pRenderNode = (IRenderNode*)pMono->pForeignData;
  328.                 m_objCenter = pRenderNode->GetBBox().GetCenter();
  329.                 m_objHash = CObjectSelector::CalculateHash(pRenderNode, true);
  330.                 break;
  331.         }
  332. }
  333.  
  334. IPhysicalEntity* CObjectIdentifier::GetPhysicsFromHoldingEntity()
  335. {
  336.         IEntity* pEntity;
  337.         if (pEntity = gEnv->pEntitySystem->GetEntity(m_holdingEntity))
  338.         {
  339.                 IPhysicalEntity* pent = pEntity->GetPhysics();
  340.                 LOGBREAK("# FindPhysicalEntity: got pent: %p, from entid: %x", pent, m_holdingEntity);
  341.                 return pent;
  342.         }
  343.         GameWarning("brk: # Couldn't identify an object to break");
  344.         return NULL;
  345. }
  346.  
  347. IPhysicalEntity* CObjectIdentifier::FindPhysicalEntity()
  348. {
  349.         LOGBREAK("# FindPhysicalEntity:");
  350.  
  351.         if (m_holdingEntity)
  352.         {
  353.                 return GetPhysicsFromHoldingEntity();
  354.         }
  355.         if (m_objType == k_static_entity)
  356.         {
  357.                 if (m_objHash)
  358.                 {
  359.                         // First look through the already registered identifiers
  360.                         int idx = CBreakReplicator::Get()->GetIdentifier(this, NULL, true);
  361.                         if (idx >= 0)
  362.                         {
  363.                                 CObjectIdentifier* pIdentifier = &CBreakReplicator::Get()->m_identifiers[idx];
  364.                                 if (pIdentifier->m_holdingEntity)
  365.                                 {
  366.                                         return pIdentifier->GetPhysicsFromHoldingEntity();
  367.                                 }
  368.                         }
  369.                         /* Resort to a physics overlap test */
  370.                         IPhysicalEntity* pent;
  371.                         if (pent = CObjectSelector::FindPhysicalEntity(m_objCenter, m_objHash, 30.f))
  372.                         {
  373.                                 return pent;
  374.                         }
  375.                 }
  376.         }
  377.         GameWarning("brk: # Couldn't identify an object to break");
  378.         return NULL;
  379. }
  380.  
  381. /*
  382.    ====================
  383.    BreakStream
  384.    ====================
  385.  */
  386.  
  387.         #define BS_NUM_RECORDING_FRAMES 2
  388.         #define BS_NUM_PLAYBACK_FRAMES  5
  389.         #define BS_MAX_NUM_TO_PLAYBACK  10
  390.  
  391. BreakStream::BreakStream()
  392.         : m_pent(nullptr)
  393.         , m_breakIdx(0xffff)
  394.         , m_subBreakIdx(~0)
  395.         , m_mode(k_invalid)
  396.         , m_type(0)
  397.         , m_numFramesLeft(0)
  398.         , m_invalidFindCount(0)
  399.         , m_waitForDependent(0)
  400.         , m_logHostMigrationInfo(1)
  401. {
  402.         m_identifier.Reset();
  403. }
  404.  
  405. BreakStream::~BreakStream()
  406. {
  407.         if (m_mode == k_playing)
  408.         {
  409.                 if (m_pent)
  410.                 {
  411.                         m_pent->Release();
  412.                 }
  413.         }
  414. }
  415.  
  416. void BreakStream::Init(EMode mode)
  417. {
  418.         m_mode = mode;
  419.         if (mode == k_playing)
  420.                 m_numFramesLeft = BS_NUM_PLAYBACK_FRAMES;
  421.         if (mode == k_recording)
  422.                 m_numFramesLeft = BS_NUM_RECORDING_FRAMES;
  423. }
  424.  
  425. bool BreakStream::CanSendPayload()
  426. {
  427.         DEBUG_ASSERT(m_mode == k_recording);
  428.         return m_numFramesLeft == 0;
  429. }
  430.  
  431. void BreakStream::OnEndFrame()
  432. {
  433.         const int n = m_numFramesLeft ? m_numFramesLeft - 1 : 0;
  434.         if (m_mode == k_playing && n == 0)
  435.         {
  436.                 if (m_pent)
  437.                 {
  438.                         m_pent->Release();
  439.                         m_pent = NULL;
  440.                 }
  441.                 LogHostMigrationInfo();
  442.                 m_mode = k_finished;
  443.                 m_collector->FinishedBreakage();
  444.                 m_collector = NULL; // release smart ptr
  445.         }
  446.         m_numFramesLeft = n;
  447.         LOGBREAK("# stream: %d, setting m_numFramesLeft: %d, mode=%s", m_breakIdx, m_numFramesLeft, BreakStreamGetModeName(m_mode));
  448. }
  449.  
  450. void BreakStream::LogHostMigrationInfo()
  451. {
  452.         if (m_logHostMigrationInfo == 0)
  453.                 return;
  454.  
  455.         DEBUG_ASSERT(m_mode != k_finished);
  456.         LOGBREAK("HOSTMIG for stream: %d", m_breakIdx);
  457.         {
  458.                 // - Host Migration -
  459.                 // The client also needs to log a copy of a break stream
  460.                 // in case it becomes the server and has to deal with client
  461.                 // joins. Log the break here, but dont send it (eNBF_SendOnlyOnClientJoin flag)
  462.                 SNetBreakDescription desc;
  463.                 desc.flags = (ENetBreakDescFlags)(eNBF_UseSimpleSend | eNBF_SendOnlyOnClientJoin);
  464.                 desc.nEntities = 0;
  465.                 desc.pEntities = NULL;
  466.                 desc.pMessagePayload = this;
  467.                 OnSend(desc);
  468.                 INetContext* pNetContext = CCryAction::GetCryAction()->GetNetContext();
  469.                 if (pNetContext)
  470.                 {
  471.                         pNetContext->LogBreak(desc);
  472.                 }
  473.         }
  474. }
  475.  
  476. void BreakStream::GetAffectedRegion(AABB& aabb)
  477. {
  478.         aabb.min.zero();
  479.         aabb.max.zero();
  480. }
  481.  
  482. void BreakStream::SerialiseSimpleBreakage(TSerialize ser)
  483. {
  484.         CBreakReplicator::Get()->SerialiseBreakage(ser, this);
  485. }
  486.  
  487. void BreakStream::SerializeWith_Begin(CBitArray& array, bool includeObjCenter)
  488. {
  489.         m_identifier.SerializeWith(array, includeObjCenter);
  490.         LOGBREAK("#   identifier(entId:%x, hash:%x, objType=%d)", m_identifier.m_holdingEntity, m_identifier.m_objHash, m_identifier.m_objType);
  491. }
  492.  
  493. bool BreakStream::IsIdentifierEqual(const CObjectIdentifier& identifier)
  494. {
  495.         return (m_identifier.m_holdingEntity && m_identifier.m_holdingEntity == identifier.m_holdingEntity) || (m_identifier.m_objHash && m_identifier.m_objHash == identifier.m_objHash);
  496. }
  497.  
  498. /*
  499.    ===========================
  500.    Part BreakStream
  501.    ===========================
  502.  */
  503.  
  504. PartBreak::PartBreak()
  505. {
  506.         m_type = k_partBreak;
  507.  
  508.         m_numProducts = 0;
  509.         m_numJointsBroken = 0;
  510.         m_numProductsCollected = 0;
  511.         m_products = NULL;
  512.         m_jointsBroken = NULL;
  513. }
  514.  
  515. PartBreak::~PartBreak()
  516. {
  517.         if (m_mode == k_recording)
  518.         {
  519.                 for (int i = 0; i < m_numProducts; i++)
  520.                 {
  521.                         if (m_products[i].pent)
  522.                                 m_products[i].pent->Release();
  523.                 }
  524.         }
  525.         if (m_products)
  526.         {
  527.                 free(m_products);
  528.         }
  529.         if (m_jointsBroken)
  530.         {
  531.                 free(m_jointsBroken);
  532.         }
  533. }
  534.  
  535. void PartBreak::Init(EMode mode)
  536. {
  537.         m_mode = mode;
  538.         if (mode == k_playing)
  539.         {
  540.                 m_numFramesLeft = BS_NUM_PLAYBACK_FRAMES;
  541.         }
  542.         if (mode == k_recording)
  543.         {
  544.                 m_numFramesLeft = BS_NUM_RECORDING_FRAMES;
  545.  
  546.                 // Initially allocate these arrays to a large size
  547.                 // They are then freed and reallocated to a smaller amount once recording has finished
  548.                 m_products = (EmittedProduct*)malloc(sizeof(EmittedProduct) * NET_MAX_NUMBER_OF_PARTS);
  549.                 m_jointsBroken = (JointBreakInfo*)malloc(sizeof(JointBreakInfo) * NET_MAX_NUMBER_OF_PARTS);
  550.         }
  551. }
  552.  
  553. EmittedProduct* PartBreak::FindEmittedProduct(const EventPhysCreateEntityPart* pEvent, bool add)
  554. {
  555.         DEBUG_ASSERT(m_mode != k_finished);
  556.  
  557.         for (int i = 0; i < m_numProducts; i++)
  558.         {
  559.                 if (m_products[i].pent == pEvent->pEntNew)
  560.                 {
  561.                         return &m_products[i];
  562.                 }
  563.         }
  564.  
  565.         if (add)
  566.         {
  567.                 if (m_numProducts < NET_MAX_NUMBER_OF_PARTS)
  568.                 {
  569.                         // This is only done server side, whilst recording
  570.                         CRY_ASSERT(m_mode == k_recording);
  571.                         EmittedProduct* pProduct = m_products + m_numProducts;
  572.                         m_numProducts++;
  573.                         pProduct->pent = pEvent->pEntNew;
  574.                         if (m_mode == k_recording)
  575.                         {
  576.                                 // Don't let the physics delete this until observing has finished
  577.                                 pProduct->pent->AddRef();
  578.                         }
  579.                         // memset(&pProduct->parts, 0, sizeof(pProduct->parts));
  580.                         pProduct->partidSrc = 0xffff;
  581.                         LOGBREAK("#   Added emitted product: %p", pEvent->pEntNew);
  582.                         return pProduct;
  583.                 }
  584.                 else
  585.                 {
  586.                         GameWarning("#brk: TOO MANY EMITTED PRODUCTS CAN'T ADD TO STREAM !!!");
  587.                 }
  588.         }
  589.         return NULL;
  590. }
  591.  
  592. bool PartBreak::OnCreatePhysEntityPart(const EventPhysCreateEntityPart* pEvent)
  593. {
  594.         DEBUG_ASSERT(m_mode != k_finished);
  595.  
  596.         if (pEvent->pEntity == m_pent)
  597.         {
  598.                 LOGBREAK("# OnCreatePhysEntityPart(%s), pent: %p, partidSrc: %d", BreakStreamGetModeName(m_mode), m_pent, pEvent->partidSrc);
  599.                 if (m_mode == k_recording)
  600.                 {
  601.                         if (m_numFramesLeft == 0)
  602.                                 m_numFramesLeft = 1;  // Keep active for one more frame!
  603.  
  604.                         if (EmittedProduct* pProduct = FindEmittedProduct(pEvent, true))
  605.                         {
  606.                                 if (pEvent->partidSrc <= 255)
  607.                                 {
  608.                                         // pProduct->parts.Add(pEvent->partidSrc);
  609.                                         pProduct->partidSrc = min(pProduct->partidSrc, pEvent->partidSrc);
  610.                                         pProduct->initialVel = pEvent->v;
  611.                                         pProduct->initialAngVel = pEvent->w;
  612.                                 }
  613.                                 else
  614.                                 {
  615.                                         GameWarning("#brk: CAN'T ADD EMITTED PRODUCT: partidSrc>255 !!!");
  616.                                 }
  617.                         }
  618.                 }
  619.                 if (m_mode == k_playing)
  620.                 {
  621.                         for (int i = 0; i < m_numProducts; i++)
  622.                         {
  623.                                 if ((m_products[i].partidSrc == pEvent->partidSrc) && (m_products[i].pent == NULL))
  624.                                 {
  625.                                         // Fix up the pent pointer
  626.                                         m_products[i].pent = pEvent->pEntNew;
  627.                                         m_products[i].pent->AddRef();  // Don't let the physics delete this until observing has finished
  628.                                         m_numProductsCollected++;
  629.                                 }
  630.                         }
  631.                 }
  632.                 return true;
  633.         }
  634.         return false;
  635. }
  636.  
  637. bool PartBreak::OnRemovePhysEntityParts(const EventPhysRemoveEntityParts* pEvent)
  638. {
  639.  
  640.         DEBUG_ASSERT(m_mode != k_finished);
  641.         if (pEvent->pEntity == m_pent)
  642.         {
  643.                 if (m_mode == k_recording)
  644.                 {
  645.                         if (m_numFramesLeft == 0)
  646.                                 m_numFramesLeft = 1;  // Keep active for one more frame!
  647.                 }
  648.                 if (m_mode == k_playing)
  649.                 {
  650.                 }
  651.                 return true;
  652.         }
  653.         return false;
  654. }
  655.  
  656. bool PartBreak::OnJointBroken(const EventPhysJointBroken* pEvent)
  657. {
  658.         DEBUG_ASSERT(m_mode != k_finished);
  659.  
  660.         if (pEvent->pEntity[0] == m_pent)
  661.         {
  662.                 LOGBREAK("# OnJointBroken(%s), pent: %p, idJoint: %d, partidEpicenter: %d", BreakStreamGetModeName(m_mode), m_pent, pEvent->idJoint, pEvent->partidEpicenter);
  663.                 if (m_mode == k_recording)
  664.                 {
  665.                         if (m_numJointsBroken < NET_MAX_NUMBER_OF_PARTS && pEvent->idJoint <= 255)
  666.                         {
  667.                                 JointBreakInfo* jb = &m_jointsBroken[m_numJointsBroken++];
  668.                                 jb->idJoint = pEvent->idJoint;
  669.                                 jb->partidEpicenter = pEvent->partidEpicenter;
  670.                         }
  671.                         else
  672.                         {
  673.                                 GameWarning("#brk: TOO MANY BROKEN JOINTS CAN'T ADD TO STREAM / OR JOINT_ID > 255 !!!");
  674.                         }
  675.                 }
  676.                 if (m_mode == k_playing)
  677.                 {
  678.                         LOGBREAK("#    Was listening with numFramesLeft: %d", m_numFramesLeft);
  679.                 }
  680.                 return true;
  681.         }
  682.         return false;
  683. }
  684.  
  685. void PartBreak::OnEndFrame()
  686. {
  687.         DEBUG_ASSERT(m_mode != k_finished);
  688.  
  689.         m_numFramesLeft = m_numFramesLeft ? m_numFramesLeft - 1 : 0;
  690.  
  691.         if (m_mode == k_recording)
  692.         {
  693.                 for (int i = 0; i < m_numProducts; i++)
  694.                 {
  695.                         IPhysicalEntity* pent = m_products[i].pent;
  696.                         if (pent)
  697.                         {
  698.                                 pent->Release();
  699.                                 m_products[i].pent = NULL;
  700.                         }
  701.                 }
  702.         }
  703.         if (m_mode == k_playing)
  704.         {
  705.                 if (m_numFramesLeft == 0 || (m_numProductsCollected == m_numProducts))
  706.                 {
  707.                         // Finished Playback!
  708.                         LOGBREAK("# Playback Stream (%d) is finished (pent: %p)", m_breakIdx, m_pent);
  709.                         if (m_pent)
  710.                         {
  711.                                 m_pent->Release();
  712.                                 m_pent = NULL;
  713.                         }
  714.                         for (int i = 0; i < m_numProducts; i++)
  715.                         {
  716.                                 IPhysicalEntity* pent = m_products[i].pent;
  717.                                 if (pent)
  718.                                 {
  719.                                         m_products[i].pent->Release();
  720.                                         m_products[i].pent = NULL;
  721.                                 }
  722.                         }
  723.                         LogHostMigrationInfo();
  724.                         m_mode = k_finished;
  725.                         m_collector = NULL; // release smart ptr
  726.                 }
  727.         }
  728. }
  729.  
  730.         #pragma warning(push)
  731.         #pragma warning(disable : 6262)// 32k of stack space of CBitArray
  732. void PartBreak::SerializeWith(CBitArray& array)
  733. {
  734.         SerializeWith_Begin(array, true);
  735.  
  736.         array.Serialize(m_numProducts, 0, NET_MAX_NUMBER_OF_PARTS);
  737.         array.Serialize(m_numJointsBroken, 0, NET_MAX_NUMBER_OF_PARTS);
  738.  
  739.         if (array.IsReading())
  740.         {
  741.                 // Allocate space
  742.                 if (m_numProducts)
  743.                 {
  744.                         m_products = (EmittedProduct*) malloc(sizeof(EmittedProduct) * m_numProducts);
  745.                         memset(m_products, 0, sizeof(EmittedProduct) * m_numProducts);
  746.                 }
  747.                 if (m_numJointsBroken)
  748.                 {
  749.                         m_jointsBroken = (JointBreakInfo*) malloc(sizeof(JointBreakInfo) * m_numJointsBroken);
  750.                 }
  751.         }
  752.  
  753.         for (int i = 0; i < m_numJointsBroken; i++)
  754.         {
  755.                 array.Serialize(m_jointsBroken[i].idJoint, 0, 255);
  756.                 array.Serialize(m_jointsBroken[i].partidEpicenter, 0, 255);
  757.         }
  758.  
  759.         for (int i = 0; i < m_numProducts; i++)
  760.         {
  761.                 PREFAST_ASSUME(i > 0 && i < m_numProducts);
  762.                 array.Serialize(m_products[i].partidSrc, 0, 255);
  763.                 SerializeDirVector(array, m_products[i].initialVel, 20.f, 12, 6, 6);
  764.                 SerializeDirVector(array, m_products[i].initialAngVel, 20.f, 12, 6, 6);
  765.         }
  766.  
  767.         #if DEBUG_NET_BREAKAGE
  768.         if (array.IsWriting())
  769.         {
  770.                 CTimeValue time = gEnv->pTimer->GetAsyncTime();
  771.                 LOGBREAK("# .-----------------------------------.");
  772.                 LOGBREAK("# |    type: %s", "JointBreak");
  773.                 LOGBREAK("# .-----------------------------------");
  774.         }
  775.  
  776.         LOGBREAK("#   numProducts: %d", m_numProducts);
  777.         for (int i = 0; i < m_numProducts; i++)
  778.         {
  779.                 EmittedProduct* pProduct = m_products + i;
  780.                 LOGBREAK("#    Product(%d), pent=%p, partidSrc=%d, initialVel=(%f,%f,%f)", i, pProduct->pent, pProduct->partidSrc, XYZ(pProduct->initialVel));
  781.         }
  782.         LOGBREAK("#   numJointBreaks: %d", m_numJointsBroken);
  783.         #endif
  784. }
  785.         #pragma warning(pop)
  786.  
  787. void PartBreak::Playback()
  788. {
  789.         DEBUG_ASSERT(m_mode == k_playing);
  790.  
  791.         LOGBREAK("# .-----------------------------------.");
  792.         LOGBREAK("# |  Playback (%3d)                   |", m_breakIdx);
  793.         LOGBREAK("# .-----------------------------------.");
  794.         LOGBREAK("#   identifier(entId:%x, hash:%x)", m_identifier.m_holdingEntity, m_identifier.m_objHash);
  795.         LOGBREAK("#");
  796.         LOGBREAK("#     Need to break off %d pieces", m_numProducts);
  797.         LOGBREAK("#     Apply %d joint breaks", m_numJointsBroken);
  798.         LOGBREAK("#     Apply breakage to pent: %p", m_pent);
  799.         LOGBREAK("");
  800.  
  801.         // Stay with the joint-break system (for now)
  802.         // I don't like this, but at least we haven't got to
  803.         // replicate all of the physics events, and particle generation
  804.         // which would be painful. It would also involve cut-n-pasted lots
  805.         // of breakablemanager code or a massive refactor.
  806.  
  807.         pe_params_structural_initial_velocity initialVel;
  808.         for (int i = 0; i < m_numProducts; i++)
  809.         {
  810.                 // Pre-Load the initial velocities
  811.                 initialVel.partid = m_products[i].partidSrc;
  812.                 initialVel.v = m_products[i].initialVel;
  813.                 initialVel.w = m_products[i].initialAngVel;
  814.                 m_pent->SetParams(&initialVel);
  815.         }
  816.  
  817.         pe_params_structural_joint pj;
  818.         for (int i = 0; i < m_numJointsBroken; i++)
  819.         {
  820.                 LOGBREAK("#     BREAKING JOINT %d", m_jointsBroken[i].idJoint);
  821.                 pj.id = m_jointsBroken[i].idJoint;
  822.                 pj.partidEpicenter = m_jointsBroken[i].partidEpicenter;
  823.                 pj.bBroken = 1;
  824.                 pj.bReplaceExisting = 1;
  825.                 m_pent->SetParams(&pj);
  826.         }
  827. }
  828.  
  829. void PartBreak::OnSend(SNetBreakDescription& desc)
  830. {
  831.         // Reallocate the arrays to avoid memory wastage
  832.         EmittedProduct* products = NULL;
  833.         JointBreakInfo* jointsBroken = NULL;
  834.  
  835.         if (m_numProducts)
  836.         {
  837.                 products = (EmittedProduct*) malloc(sizeof(EmittedProduct) * m_numProducts);
  838.                 memcpy(products, m_products, sizeof(EmittedProduct) * m_numProducts);
  839.         }
  840.         if (m_numJointsBroken)
  841.         {
  842.                 jointsBroken = (JointBreakInfo*) malloc(sizeof(JointBreakInfo) * m_numJointsBroken);
  843.                 memcpy(jointsBroken, m_jointsBroken, sizeof(JointBreakInfo) * m_numJointsBroken);
  844.         }
  845.  
  846.         free(m_products);
  847.         free(m_jointsBroken);
  848.  
  849.         m_products = products;
  850.         m_jointsBroken = jointsBroken;
  851. }
  852.  
  853. /*
  854.    ===========================
  855.    Plane BreakStream
  856.    ===========================
  857.  */
  858.  
  859. PlaneBreak::PlaneBreak()
  860. {
  861.         m_type = k_planeBreak;
  862.         m_pStatObj = NULL;
  863. }
  864.  
  865. PlaneBreak::~PlaneBreak()
  866. {
  867.         if (m_pStatObj)
  868.                 m_pStatObj->Release();
  869.         m_pStatObj = NULL;
  870. }
  871.  
  872. void PlaneBreak::SerializeWith(CBitArray& array)
  873. {
  874.         LOGBREAK("PlaneBreak::SerializeWith: %s", array.IsReading() ? "Reading:" : "Writing");
  875.  
  876.         SerializeWith_Begin(array, false);
  877.  
  878.         SBreakEvent& breakEvent = m_be;
  879.  
  880.         // TODO: entity glass breakage, in entity space
  881.  
  882.         CBreakReplicator::SerialisePosition(array, m_be.pt, CNetworkCVars::Get().BreakMaxWorldSize, CBreakReplicator::m_accurateWorldPosNumBits);
  883.  
  884.         m_be.partid[1] = GetSlotIdx(m_be.partid[1], 0) << 8 | GetSlotIdx(m_be.partid[1], 1);
  885.  
  886.         SerializeDirHelper(array, m_be.n, 8, 8);
  887.         array.Serialize(m_be.idmat[0], -1, 254);
  888.         array.Serialize(m_be.idmat[1], -1, 254);
  889.         array.Serialize(m_be.partid[1], 0, 0xffff);
  890.         array.Serialize(m_be.iPrim[1], -1, 0x7ffe);
  891.         array.Serialize(m_be.mass[0], 1.f, 1000.f, 8);
  892.         SerializeDirVector(array, m_be.vloc[0], 20.f, 8, 8, 8);
  893.  
  894.         m_be.partid[1] = (m_be.partid[1] & 0xff) + (m_be.partid[1] >> 8) * PARTID_MAX_SLOTS;
  895.  
  896.         // Looks like we dont need these
  897.         m_be.partid[0] = 0;
  898.         m_be.scale.Set(1.f, 1.f, 1.f);
  899.         m_be.radius = 0.f;
  900.         m_be.vloc[1].zero();   // Just assume the hitee is at zero velocity
  901.         m_be.energy = 0.f;
  902.         m_be.penetration = 0.f;
  903.         m_be.mass[1] = 0.f;
  904.         m_be.seed = 0;
  905.  
  906.         m_identifier.m_objCenter = m_be.pt;
  907. }
  908.  
  909. void PlaneBreak::OnSend(SNetBreakDescription& desc)
  910. {
  911.         // If this is the first break, then send immediately
  912.         // If this is a secondary break, then send only on a client join
  913.         desc.flags = (ENetBreakDescFlags)(desc.flags | (eNBF_SendOnlyOnClientJoin & (m_be.bFirstBreak - 1)));
  914. }
  915.  
  916. void PlaneBreak::Playback()
  917. {
  918.         LOGBREAK("# .-----------------------------------.");
  919.         LOGBREAK("# |  PlaneBreak::Playback (%3d)      |", m_breakIdx);
  920.         LOGBREAK("# .-----------------------------------.");
  921.  
  922.         EventPhysCollision epc;
  923.  
  924.         epc.pEntity[0] = 0;
  925.         epc.iForeignData[0] = -1;
  926.         epc.pt = m_be.pt;
  927.         epc.n = m_be.n;
  928.         epc.vloc[0] = m_be.vloc[0];
  929.         epc.vloc[1] = m_be.vloc[1];
  930.         epc.mass[0] = m_be.mass[0];
  931.         epc.mass[1] = m_be.mass[1];
  932.         epc.idmat[0] = m_be.idmat[0];
  933.         epc.idmat[1] = m_be.idmat[1];
  934.         epc.partid[0] = m_be.partid[0];
  935.         epc.partid[1] = m_be.partid[1];
  936.         epc.iPrim[1] = m_be.iPrim[1];
  937.         epc.penetration = m_be.penetration;
  938.         epc.radius = m_be.radius;
  939.  
  940.         if (m_pent)
  941.         {
  942.                 epc.pEntity[1] = m_pent;
  943.                 epc.iForeignData[1] = m_pent->GetiForeignData();
  944.                 epc.pForeignData[1] = m_pent->GetForeignData(epc.iForeignData[1]);
  945.         }
  946.         else
  947.         {
  948.                 epc.pEntity[1] = 0;
  949.                 epc.iForeignData[1] = -1;
  950.                 epc.pForeignData[1] = 0;
  951.         }
  952.  
  953.         CActionGame::PerformPlaneBreak(epc, NULL, CActionGame::ePPB_EnableParticleEffects | CActionGame::ePPB_PlaybackEvent, 0);
  954.  
  955.         LogHostMigrationInfo();
  956.         m_mode = k_finished;
  957.         m_collector = NULL; // release smart ptr
  958. }
  959.  
  960. bool PlaneBreak::IsWaitinOnRenderMesh()
  961. {
  962.         return m_pStatObj != NULL;
  963. }
  964.  
  965. bool PlaneBreak::IsRenderMeshReady()
  966. {
  967.         if (m_pStatObj == NULL)
  968.         {
  969.                 int iForeign = m_pent->GetiForeignData();
  970.                 if (iForeign == PHYS_FOREIGN_ID_STATIC)
  971.                 {
  972.                         if (IRenderNode* pRenderNode = (IRenderNode*)m_pent->GetForeignData(PHYS_FOREIGN_ID_STATIC))
  973.                         {
  974.                                 IStatObj::SSubObject* pSubObj;
  975.                                 Matrix34A mtx;
  976.                                 IStatObj* pStatObj = pRenderNode->GetEntityStatObj(0, 0, &mtx);
  977.                                 if (pStatObj && pStatObj->GetFlags() & STATIC_OBJECT_COMPOUND)
  978.                                         if (pSubObj = pStatObj->GetSubObject(m_be.partid[1]))
  979.                                                 pStatObj = pSubObj->pStatObj;
  980.                                 m_pStatObj = pStatObj;
  981.                                 if (m_pStatObj)
  982.                                         m_pStatObj->AddRef();
  983.                         }
  984.                 }
  985.         }
  986.         if (m_pStatObj)
  987.         {
  988.                 if (m_pStatObj->GetRenderMesh() == NULL)
  989.                 {
  990.                         // Waiting on rendermesh
  991.                         if (m_pent)
  992.                         {
  993.                                 m_pent->Release();
  994.                                 m_pent = NULL;
  995.                         }
  996.                         return false;
  997.                 }
  998.                 // No longer waiting on statobj, release it
  999.                 m_pStatObj->Release();
  1000.                 m_pStatObj = NULL;
  1001.         }
  1002.         return true;
  1003. }
  1004.  
  1005. /*
  1006.    ===========================
  1007.    Deforming BreakStream
  1008.    ===========================
  1009.  */
  1010.  
  1011. DeformBreak::DeformBreak()
  1012. {
  1013.         m_type = k_deformBreak;
  1014. }
  1015.  
  1016. DeformBreak::~DeformBreak()
  1017. {
  1018. }
  1019.  
  1020. void DeformBreak::OnSpawnEntity(IEntity* pEntity)
  1021. {
  1022.         #if NET_SYNC_TREES
  1023.         // We need to make sure that this entity is synchnronised correctly
  1024.         // when being deleted by the memory limiter in action game -
  1025.         // attach a "BreakRepGameObject"
  1026.         pEntity->SetFlags(pEntity->GetFlags() & ~(ENTITY_FLAG_CLIENT_ONLY | ENTITY_FLAG_SERVER_ONLY));
  1027.         IGameObject* pGameObject = CCryAction::GetCryAction()->GetIGameObjectSystem()->CreateGameObjectForEntity(pEntity->GetId());
  1028.         pGameObject->ActivateExtension("BreakRepGameObject");
  1029.  
  1030.         // For now assume that all the spawned entities happen in the same order
  1031.         if (m_mode == k_playing)
  1032.         {
  1033.                 // Tell the low level that we have a new entity
  1034.                 // and it needs binding
  1035.                 m_collector->BindSpawnedEntity(pEntity->GetId(), -1);
  1036.         }
  1037.         // Make a note of entities that will need binding
  1038.         m_spawnedEntities.push_back(pEntity->GetId());
  1039.         #endif
  1040. }
  1041.  
  1042. void DeformBreak::OnSend(SNetBreakDescription& desc)
  1043. {
  1044.         // Inform the low level of the entities we expect to be spawned on the client
  1045.         desc.nEntities = m_spawnedEntities.size();
  1046.         desc.pEntities = m_spawnedEntities.begin();
  1047.         #if DEBUG_NET_BREAKAGE
  1048.         if (m_mode == k_playing)
  1049.         {
  1050.                 LOGBREAK(" HOSTMIG: Stream: %d, DeformBreak: numEnts: %d", m_breakIdx, m_spawnedEntities.size());
  1051.                 for (int i = 0; i < m_spawnedEntities.size(); i++)
  1052.                 {
  1053.                         LOGBREAK("   - EntId: %x", m_spawnedEntities[i]);
  1054.                 }
  1055.         }
  1056.         #endif
  1057. }
  1058.  
  1059. static inline void SerialiseHalf(CBitArray& array, f32& f)
  1060. {
  1061.         union FloatUnion
  1062.         {
  1063.                 f32    f;
  1064.                 uint32 u;
  1065.         } tmp;
  1066.  
  1067.         if (array.IsReading())
  1068.         {
  1069.                 array.Serialize(tmp.u, 0, 0xffff);
  1070.                 tmp.u = tmp.u << 16;
  1071.                 f = tmp.f;
  1072.         }
  1073.         else
  1074.         {
  1075.                 tmp.f = f;
  1076.                 tmp.u = tmp.u >> 16;
  1077.                 array.Serialize(tmp.u, 0, 0xffff);
  1078.         }
  1079. }
  1080.  
  1081. void DeformBreak::SerializeWith(CBitArray& array)
  1082. {
  1083.         SerializeWith_Begin(array, false);
  1084.  
  1085.         LOGBREAK("DeformBreak::SerializeWith: %s", array.IsReading() ? "Reading:" : "Writing");
  1086.  
  1087.         CBreakReplicator::SerialisePosition(array, m_be.pt, CNetworkCVars::Get().BreakMaxWorldSize, CBreakReplicator::m_accurateWorldPosNumBits);
  1088.  
  1089.         SerializeDirHelper(array, m_be.n, 8, 8);
  1090.         SerialiseHalf(array, m_be.energy);
  1091.  
  1092.         m_identifier.m_objCenter = m_be.pt;
  1093. }
  1094.  
  1095. void DeformBreak::Playback()
  1096. {
  1097.         LOGBREAK("# .-----------------------------------.");
  1098.         LOGBREAK("# |  DeformBreak::Playback (%3d)      |", m_breakIdx);
  1099.         LOGBREAK("# .-----------------------------------.");
  1100.  
  1101.         if (m_pent)
  1102.         {
  1103.                 // Tell the low level that breakage has started
  1104.                 m_collector->BeginBreakage();
  1105.  
  1106.                 if (!gEnv->pPhysicalWorld->DeformPhysicalEntity(m_pent, m_be.pt, -m_be.n, m_be.energy))
  1107.                 {
  1108.                         GameWarning("brk: # DeformPhysicalEntity failed");
  1109.                 }
  1110.         }
  1111. }
  1112.  
  1113. /*
  1114.    ================================
  1115.    CBreakReplicator
  1116.    ================================
  1117.  */
  1118.  
  1119. CBreakReplicator* CBreakReplicator::m_pThis = NULL;
  1120. int CBreakReplicator::m_accurateWorldPosNumBits = 0;
  1121. int CBreakReplicator::m_inaccurateWorldPosNumBits = 0;
  1122.  
  1123. // Suppress warning for unintialized array CBreakReplicator::m_pendingStreams
  1124. // cppcheck-suppress uninitMemberVar
  1125. CBreakReplicator::CBreakReplicator(CGameContext* pGameCtx)
  1126.         : m_bDefineProtocolMode_server(false)
  1127.         , m_activeStartIdx(0)
  1128.         , m_numPendingStreams(0)
  1129.         , m_timeSinceLevelLoaded(-1.0f)
  1130. {
  1131.         (void)pGameCtx;
  1132.  
  1133.         // This seems to be created when entering a level for the first time
  1134.         // both on server and clients
  1135.  
  1136.         LOGBREAK("# -------------------------------------------------------------");
  1137.         LOGBREAK("# -   CREATE: CBreakReplicator                         -");
  1138.         LOGBREAK("# -------------------------------------------------------------");
  1139.  
  1140.         DEBUG_ASSERT(m_pThis == NULL);
  1141.         m_pThis = this;
  1142.         m_streams.reserve(100);
  1143.  
  1144.         // Initialise a dummy stream. This is used as a place holder for
  1145.         // stream indexes that have not yet been serialised over on a client
  1146.         // saves lots of null pointer tests
  1147.         s_dummyStream.m_mode = BreakStream::k_finished;
  1148.         s_dummyStream.m_pent = (IPhysicalEntity*)(intptr_t)0xCBADBEEF;
  1149.         s_dummyStream.m_breakIdx = 0xffff;
  1150.  
  1151.         m_removePartEvents.reserve(100);
  1152.         m_entitiesToRemove.reserve(16);
  1153.         m_identifiers.reserve(100);
  1154.         m_streams.reserve(100);
  1155.  
  1156.         if (IPhysicalWorld* pWorld = gEnv->pPhysicalWorld)
  1157.         {
  1158.                 pWorld->AddEventClient(EventPhysRevealEntityPart::id, OnRevealEntityPart, true, 100000.f);
  1159.                 pWorld->AddEventClient(EventPhysCreateEntityPart::id, OnCreatePhysEntityPart, true, 100000.f);
  1160.                 pWorld->AddEventClient(EventPhysRemoveEntityParts::id, OnRemovePhysEntityParts, true, 100000.f);
  1161.                 pWorld->AddEventClient(EventPhysJointBroken::id, OnJointBroken, true, 100000.f);
  1162.         }
  1163.  
  1164.         gEnv->pSystem->GetISystemEventDispatcher()->RegisterListener(this);
  1165.  
  1166.         float max = CNetworkCVars::Get().BreakMaxWorldSize;
  1167.         m_inaccurateWorldPosNumBits = IntegerLog2_RoundUp(uint32(max / WORLD_POS_SAMPLE_DISTANCE_APPART_INACCURATE));
  1168.         m_accurateWorldPosNumBits = IntegerLog2_RoundUp(uint32(max / WORLD_POS_SAMPLE_DISTANCE_APPART_ACCURATE));
  1169.  
  1170.         CryLog("[CBreakReplicator] Inaccurate world pos using range 0-%f with %d bits", max, m_inaccurateWorldPosNumBits);
  1171.         CryLog("[CBreakReplicator] Accurate world pos using range 0-%f with %d bits", max, m_accurateWorldPosNumBits);
  1172. }
  1173.  
  1174. CBreakReplicator::~CBreakReplicator()
  1175. {
  1176.         // When the game quits to the front-end this should be called.
  1177.  
  1178.         LOGBREAK("# -------------------------------------------------------------");
  1179.         LOGBREAK("# -   DESTROY: CBreakReplicator                        -");
  1180.         LOGBREAK("# -------------------------------------------------------------");
  1181.  
  1182.         DEBUG_ASSERT(m_pThis = this);
  1183.         m_pThis = NULL;
  1184.         Reset();
  1185.  
  1186.         gEnv->pSystem->GetISystemEventDispatcher()->RemoveListener(this);
  1187.  
  1188.         if (IPhysicalWorld* pWorld = gEnv->pPhysicalWorld)
  1189.         {
  1190.                 pWorld->RemoveEventClient(EventPhysRevealEntityPart::id, OnRevealEntityPart, true);
  1191.                 pWorld->RemoveEventClient(EventPhysCreateEntityPart::id, OnCreatePhysEntityPart, true);
  1192.                 pWorld->RemoveEventClient(EventPhysRemoveEntityParts::id, OnRemovePhysEntityParts, true);
  1193.                 pWorld->RemoveEventClient(EventPhysJointBroken::id, OnJointBroken, true);
  1194.         }
  1195. }
  1196.  
  1197. void CBreakReplicator::Reset()
  1198. {
  1199.         for (int i = 0; i < m_numPendingStreams; i++)
  1200.         {
  1201.                 m_pendingStreams[i]->Release();
  1202.         }
  1203.  
  1204.         for (int i = 0; i < m_streams.size(); i++)
  1205.         {
  1206.                 if (m_streams[i] != &s_dummyStream)
  1207.                 {
  1208.                         m_streams[i]->Release();
  1209.                 }
  1210.         }
  1211.  
  1212.         m_streams.clear();
  1213.         m_identifiers.clear();
  1214.         m_activeStartIdx = 0;
  1215.         m_numPendingStreams = 0;
  1216. }
  1217.  
  1218. void CBreakReplicator::DefineProtocol(IProtocolBuilder* pBuilder)
  1219. {
  1220.         static SNetProtocolDef nullDef = { 0, 0 };
  1221.  
  1222.         // Setup so that client sends to server, and server recieves
  1223.         // (opposite to the original break replicator)
  1224.         // The messages through here are separate to the stangard break messages!
  1225.         if (m_bDefineProtocolMode_server)
  1226.                 pBuilder->AddMessageSink(this, nullDef, GetProtocolDef());
  1227.         else
  1228.                 pBuilder->AddMessageSink(this, GetProtocolDef(), nullDef);
  1229. }
  1230.  
  1231. void CBreakReplicator::OnSystemEvent(ESystemEvent event, UINT_PTR wparam, UINT_PTR lparam)
  1232. {
  1233.         switch (event)
  1234.         {
  1235.         case ESYSTEM_EVENT_LEVEL_PRECACHE_END:
  1236.                 m_timeSinceLevelLoaded = 0.f;
  1237.                 break;
  1238.         }
  1239. }
  1240.  
  1241. int CBreakReplicator::PushBackNewStream(const EventPhysMono* pMono, BreakStream* pStream)
  1242. {
  1243.         // Insert into the active list
  1244.         const int breakIdx = m_streams.size();
  1245.  
  1246.         LOGBREAK("#   adding new stream: %d for pent: %p", breakIdx, pMono->pEntity);
  1247.         DEBUG_ASSERT(pMono->iForeignData == PHYS_FOREIGN_ID_STATIC || pMono->iForeignData == PHYS_FOREIGN_ID_ENTITY);
  1248.  
  1249.         pStream->AddRef();  // Make sure "dumb" pointers never delete the stream
  1250.  
  1251.         pStream->Init(BreakStream::k_recording);
  1252.         pStream->m_pent = pMono->pEntity;
  1253.         pStream->m_breakIdx = breakIdx;
  1254.         pStream->m_identifier.CreateFromPhysicalEntity(pMono);
  1255.  
  1256.         // Have we already identified this object before?
  1257.         int idx = GetIdentifier(&pStream->m_identifier, pMono->pEntity, true);
  1258.         DEBUG_ASSERT(idx >= 0);
  1259.         DEBUG_ASSERT(pStream->m_identifier.m_objType != CObjectIdentifier::k_unknown);
  1260.  
  1261.         // NB: This code is run only on the server
  1262.         // We need to establish the dependency index m_subBreakIdx
  1263.         int subIndex = 0;
  1264.         int numStreams = m_streams.size();
  1265.         for (int i = numStreams - 1; i >= 0; --i)
  1266.         {
  1267.                 // Find streams that previously broke the same object
  1268.                 if (m_streams[i]->IsIdentifierEqual(pStream->m_identifier))
  1269.                 {
  1270.                         subIndex = m_streams[i]->m_subBreakIdx + 1;
  1271.                         break;
  1272.                 }
  1273.         }
  1274.         pStream->m_subBreakIdx = subIndex;
  1275.  
  1276.         // Insert into the stream list
  1277.         m_streams.push_back(pStream);
  1278.  
  1279.         return breakIdx;
  1280. }
  1281.  
  1282. int CBreakReplicator::GetBreakIndex(const EventPhysMono* pMono, bool add)
  1283. {
  1284.         // This is called both on the server and client and will find
  1285.         // a break stream for the physicalEntity being observed.
  1286.         // On the server if a an active recording stream can't be found
  1287.         // it will add a new one.
  1288.  
  1289.         LOGBREAK("# GetBreakIndex(pent: %p)", pMono->pEntity);
  1290.  
  1291.         int breakIdx = -1;
  1292.  
  1293.         const int lastBreak = m_streams.size();
  1294.         int i = m_activeStartIdx;
  1295.         while (i < lastBreak)
  1296.         {
  1297.                 if (m_streams[i]->m_mode == BreakStream::k_finished || m_streams[i]->m_pent != pMono->pEntity)
  1298.                 {
  1299.                         i++;
  1300.                 }
  1301.                 else
  1302.                 {
  1303.                         breakIdx = i;
  1304.                         break;
  1305.                 }
  1306.         }
  1307.         if (add && i == lastBreak)
  1308.         {
  1309.                 if ((pMono->iForeignData == PHYS_FOREIGN_ID_STATIC) || (pMono->iForeignData == PHYS_FOREIGN_ID_ENTITY))
  1310.                 {
  1311.                         // Start new stream (default is Part Break)
  1312.                         BreakStream* pStream = new PartBreak;
  1313.                         breakIdx = PushBackNewStream(pMono, pStream);
  1314.                 }
  1315.                 else
  1316.                 {
  1317.                         LOGBREAK("#   WARNING: PHYSICS SUPPLIED A BAD LOGGED EVENT!");
  1318.                 }
  1319.         }
  1320.  
  1321.         LOGBREAK("#   returning: breakIdx: %d for pent: %p", breakIdx, pMono->pEntity);
  1322.         return breakIdx;
  1323. }
  1324.  
  1325. int CBreakReplicator::GetIdentifier(CObjectIdentifier* identifier, const IPhysicalEntity* pent, bool add)
  1326. {
  1327.         // Have we already identified this object before?
  1328.         // If so, return the cached version by copying it out
  1329.         // This is called by both the server and client
  1330.  
  1331.         LOGBREAK("# GetIdentifier(for: %p)", pent);
  1332.  
  1333.         int ret = -1;
  1334.         if (identifier->m_objType == CObjectIdentifier::k_static_entity)
  1335.         {
  1336.                 for (int i = 0; i < m_identifiers.size(); i++)  // ToDo: make me faster!
  1337.                 {
  1338.                         if (m_identifiers[i].m_objHash == identifier->m_objHash)
  1339.                         {
  1340.                                 // NOTE: We copy out the identifier to the requestor
  1341.                                 *identifier = m_identifiers[i];
  1342.                                 LOGBREAK("#   returning %d, from k_static_entity pool", i);
  1343.                                 return i;
  1344.                         }
  1345.                 }
  1346.         }
  1347.         if (identifier->m_objType == CObjectIdentifier::k_unknown)
  1348.         {
  1349.                 for (int i = 0; i < m_identifiers.size(); i++)  // ToDo: make me faster!
  1350.                 {
  1351.                         if (m_identifiers[i].m_holdingEntity == identifier->m_holdingEntity)
  1352.                         {
  1353.                                 // NOTE: We copy out the identifier to the requestor
  1354.                                 *identifier = m_identifiers[i];
  1355.                                 LOGBREAK("#   returning %d, from k_unknown", i);
  1356.                                 return i;
  1357.                         }
  1358.                 }
  1359.         }
  1360.  
  1361.         if (ret == -1 && add)
  1362.         {
  1363.                 if (identifier->m_holdingEntity != 0 || identifier->m_objHash != 0)
  1364.                 {
  1365.                         if (identifier->m_objType == CObjectIdentifier::k_unknown)
  1366.                         {
  1367.                                 // Looks like this entity started life as an entity
  1368.                                 identifier->m_objType = CObjectIdentifier::k_entity;
  1369.                         }
  1370.                         m_identifiers.push_back(*identifier);
  1371.                         LOGBREAK("#   adding to %d (entid:%x, hash:%x)", m_identifiers.size() - 1, identifier->m_holdingEntity, identifier->m_objHash);
  1372.                         return m_identifiers.size() - 1;
  1373.                 }
  1374.         }
  1375.         return ret;
  1376. }
  1377.  
  1378. bool CBreakReplicator::OnCreatePhysEntityPart(const EventPhysCreateEntityPart* pEvent)
  1379. {
  1380.         LOGBREAK("# OnCreate: from: %p ----------------", pEvent->pEntity);
  1381.         int breakIdx = GetBreakIndex(pEvent, m_bDefineProtocolMode_server);
  1382.         if (breakIdx >= 0)
  1383.         {
  1384.                 BreakStream* pStream = m_streams[breakIdx];
  1385.                 pStream->OnCreatePhysEntityPart(pEvent);
  1386.                 return true;
  1387.         }
  1388.         return false;
  1389. }
  1390.  
  1391. bool CBreakReplicator::OnRemovePhysEntityParts(const EventPhysRemoveEntityParts* pEvent)
  1392. {
  1393.         LOGBREAK("# OnRemove: from: %p ----------------", pEvent->pEntity);
  1394.         int breakIdx = GetBreakIndex(pEvent, m_bDefineProtocolMode_server);
  1395.  
  1396.         const int oldSize = m_removePartEvents.size();
  1397.  
  1398.         BreakLogAlways("PR: Storing RemovePart event index %d,  'foreign data': 0x%p   iForeignType: %d", oldSize, pEvent->pForeignData, pEvent->iForeignData);
  1399.  
  1400.         m_removePartEvents.push_back(*pEvent);
  1401.  
  1402.         CCryAction::GetCryAction()->OnPartRemoveEvent(oldSize);
  1403.  
  1404.         if (breakIdx >= 0)
  1405.         {
  1406.                 BreakStream* pStream = m_streams[breakIdx];
  1407.                 pStream->OnRemovePhysEntityParts(pEvent);
  1408.                 return true;
  1409.         }
  1410.         return false;
  1411. }
  1412.  
  1413. bool CBreakReplicator::OnRevealEntityPart(const EventPhysRevealEntityPart* pEvent)
  1414. {
  1415.         // Just create an empty stream, ready for the subsequent creates, removes, and joint breaks
  1416.         LOGBREAK("# OnReveal: from: %p ----------------", pEvent->pEntity);
  1417.         int breakIdx = GetBreakIndex(pEvent, m_bDefineProtocolMode_server);
  1418.         if (breakIdx >= 0)
  1419.         {
  1420.                 return true;
  1421.         }
  1422.         return false;
  1423. }
  1424.  
  1425. int CBreakReplicator::OnRevealEntityPart(const EventPhys* pEvent)
  1426. {
  1427.         CBreakReplicator::Get()->OnRevealEntityPart(static_cast<const EventPhysRevealEntityPart*>(pEvent));
  1428.         return 1;
  1429. }
  1430.  
  1431. bool CBreakReplicator::OnJointBroken(const EventPhysJointBroken* pEvent)
  1432. {
  1433.         LOGBREAK("# OnJointBreak: from: %p ----------------", pEvent->pEntity[0]);
  1434.  
  1435.         EventPhysMono mono;
  1436.         mono.pEntity = pEvent->pEntity[0];
  1437.         mono.pForeignData = pEvent->pForeignData[0];
  1438.         mono.iForeignData = pEvent->iForeignData[0];
  1439.  
  1440.         int breakIdx = GetBreakIndex(&mono, m_bDefineProtocolMode_server);
  1441.         if (breakIdx >= 0)
  1442.         {
  1443.                 BreakStream* pStream = m_streams[breakIdx];
  1444.                 pStream->OnJointBroken(pEvent);
  1445.                 return true;
  1446.         }
  1447.         return false;
  1448. }
  1449.  
  1450. void CBreakReplicator::BeginRecordingPlaneBreak(const SBreakEvent& be, EventPhysMono* pMono)
  1451. {
  1452.         if (pMono->iForeignData == PHYS_FOREIGN_ID_STATIC || pMono->iForeignData == PHYS_FOREIGN_ID_ENTITY)
  1453.         {
  1454.                 PlaneBreak* pStream = new PlaneBreak;
  1455.                 pStream->m_be = be;
  1456.                 PushBackNewStream(pMono, pStream);
  1457.         }
  1458.         else
  1459.         {
  1460.                 LOGBREAK("#   WARNING: PHYSICS SUPPLIED A BAD LOGGED PLANE-BREAK EVENT!");
  1461.         }
  1462. }
  1463.  
  1464. void CBreakReplicator::BeginRecordingDeforminBreak(const SBreakEvent& be, EventPhysMono* pMono)
  1465. {
  1466.         if (pMono->iForeignData == PHYS_FOREIGN_ID_STATIC || pMono->iForeignData == PHYS_FOREIGN_ID_ENTITY)
  1467.         {
  1468.                 DeformBreak* pStream = new DeformBreak;
  1469.                 pStream->m_be = be;
  1470.                 PushBackNewStream(pMono, pStream);
  1471.         }
  1472.         else
  1473.         {
  1474.                 LOGBREAK("#   WARNING: PHYSICS SUPPLIED A BAD LOGGED DEFORM-BREAK EVENT!");
  1475.         }
  1476. }
  1477.  
  1478. void CBreakReplicator::OnEndFrame()
  1479. {
  1480.         // Update the active list
  1481.         int i = m_activeStartIdx;
  1482.         const int lastBreak = m_streams.size();
  1483.         while (i < lastBreak && m_streams[i]->m_mode == BreakStream::k_finished)
  1484.                 i++;
  1485.         m_activeStartIdx = i;
  1486.  
  1487.         #if DEBUG_NET_BREAKAGE
  1488.         if (i < lastBreak)
  1489.                 LOGBREAK("# Replicator::OnEndFrame, activeStartIdx: %d", i);
  1490.         #endif
  1491.  
  1492.         for (; i < lastBreak; i++)
  1493.         {
  1494.                 if (m_streams[i]->m_mode != BreakStream::k_finished)
  1495.                 {
  1496.                         // Notify Recorders (on the server), and players (on the clients)
  1497.                         m_streams[i]->OnEndFrame();
  1498.                 }
  1499.         }
  1500.  
  1501.         if (m_bDefineProtocolMode_server)
  1502.         {
  1503.                 // Server:
  1504.                 if (m_activeStartIdx < m_streams.size())
  1505.                 {
  1506.                         // Try to flush active streams
  1507.                         SendPayloads();
  1508.                 }
  1509.         }
  1510.         else
  1511.         {
  1512.                 // Client:
  1513.                 if (m_numPendingStreams > 0)
  1514.                 {
  1515.                         PlaybackBreakage();
  1516.                 }
  1517.         }
  1518.  
  1519.         #if NET_SYNC_TREES
  1520.         //================================
  1521.         // Process Entities To be Removed
  1522.         //================================
  1523.         // If the object is bound to the network then it must not be deleted. Instead the game object
  1524.         // serialises the state and frees the statobj slot on all machines. This is used when the
  1525.         // breakage system is consuming too much memory.
  1526.         // Generally this is just for trees
  1527.         for (i = 0; i < (const int)m_entitiesToRemove.size(); i++)
  1528.         {
  1529.                 EntityId entId = m_entitiesToRemove[i];
  1530.                 IEntity* pEntity = gEnv->pEntitySystem->GetEntity(entId);
  1531.                 if (pEntity)
  1532.                 {
  1533.                         if ((pEntity->GetFlags() & (ENTITY_FLAG_CLIENT_ONLY | ENTITY_FLAG_SERVER_ONLY)) == 0)
  1534.                         {
  1535.                                 if (CGameObject* pGameObject = (CGameObject*) pEntity->GetProxy(ENTITY_PROXY_USER))
  1536.                                 {
  1537.                                         if (IGameObjectExtension* pExtension = pGameObject->QueryExtension("BreakRepGameObject"))
  1538.                                         {
  1539.                                                 // Net serialise that this entity should free its breakage statobj slot
  1540.                                                 static_cast<CBreakRepGameObject*>(pExtension)->m_removed = true;
  1541.                                         }
  1542.                                 }
  1543.                         }
  1544.                         else
  1545.                         {
  1546.                                 // Entities that are not bound to the network can be deleted
  1547.                                 gEnv->pEntitySystem->RemoveEntity(entId);
  1548.                         }
  1549.                 }
  1550.         }
  1551.         m_entitiesToRemove.clear();
  1552.         #endif
  1553. }
  1554.  
  1555. void CBreakReplicator::OnSpawn(IEntity* pEntity, SEntitySpawnParams& params)
  1556. {
  1557. }
  1558.  
  1559. void CBreakReplicator::OnSpawn(IEntity* pEntity, IPhysicalEntity* pPhysEntity, IPhysicalEntity* pSrcPhysEntity)
  1560. {
  1561.         // Check to see if this is an physEnt that we are currently breaking.
  1562.  
  1563.         EventPhysMono mono;
  1564.         mono.pEntity = pSrcPhysEntity;
  1565.         mono.iForeignData = 0xFBAD;
  1566.  
  1567.         EntityId entId = pEntity->GetId();
  1568.  
  1569.         // Udpate the identifiers
  1570.         if (pPhysEntity == pSrcPhysEntity)
  1571.         {
  1572.                 if (IRenderNode* pRenderNode = (IRenderNode*)pSrcPhysEntity->GetForeignData(PHYS_FOREIGN_ID_STATIC))
  1573.                 {
  1574.                         uint32 objHash = CObjectSelector::CalculateHash(pRenderNode, true);
  1575.                         if (objHash)
  1576.                         {
  1577.                                 for (int i = 0; i < m_identifiers.size(); i++)  // ToDo: make me faster!
  1578.                                 {
  1579.                                         if (m_identifiers[i].m_objHash == objHash)
  1580.                                         {
  1581.                                                 m_identifiers[i].m_holdingEntity = entId;
  1582.                                                 break;
  1583.                                         }
  1584.                                 }
  1585.                         }
  1586.                 }
  1587.         }
  1588.  
  1589.         int breakIdx = GetBreakIndex(&mono, false);
  1590.         if (breakIdx >= 0)
  1591.         {
  1592.                 BreakStream* pStream = m_streams[breakIdx];
  1593.                 pStream->OnSpawnEntity(pEntity);
  1594.         }
  1595. }
  1596.  
  1597. void CBreakReplicator::OnRemove(IEntity* pEntity)
  1598. {
  1599.         // ToDo: make me faster!
  1600.         const EntityId entId = pEntity->GetId();
  1601.         for (int i = 0; i < m_identifiers.size(); i++)
  1602.         {
  1603.                 if (m_identifiers[i].m_holdingEntity == entId)
  1604.                 {
  1605.                         m_identifiers[i].m_holdingEntity = 0;
  1606.                 }
  1607.         }
  1608. }
  1609.  
  1610. void CBreakReplicator::RemoveEntity(IEntity* pEntity)
  1611. {
  1612.         #if NET_SYNC_TREES
  1613.         // Delay entity removal, which needs to be done through CBreakRepGameObject
  1614.         m_entitiesToRemove.push_back(pEntity->GetId());
  1615.         #else
  1616.         // Can safely delete straight away
  1617.         CRY_ASSERT(pEntity->GetFlags() & (ENTITY_FLAG_CLIENT_ONLY | ENTITY_FLAG_SERVER_ONLY));
  1618.         gEnv->pEntitySystem->RemoveEntity(pEntity->GetId());
  1619.         #endif
  1620. }
  1621.  
  1622. void CBreakReplicator::SerialisePosition(CBitArray& array, Vec3& pos, float range, int numBits)
  1623. {
  1624.         if (array.IsReading())
  1625.         {
  1626.                 array.Serialize(pos, 0.f, range, numBits);
  1627.                 pos.x += CNetworkCVars::Get().BreakWorldOffsetX;
  1628.                 pos.y += CNetworkCVars::Get().BreakWorldOffsetY;
  1629.         }
  1630.         else
  1631.         {
  1632.                 Vec3 p = pos;
  1633.                 p.x -= CNetworkCVars::Get().BreakWorldOffsetX;
  1634.                 p.y -= CNetworkCVars::Get().BreakWorldOffsetY;
  1635.                 array.Serialize(p, 0.f, range, numBits);
  1636.         }
  1637.  
  1638.         #if DEBUG_NET_BREAKAGE
  1639.         if (pos.x < CNetworkCVars::Get().BreakWorldOffsetX || pos.x > (CNetworkCVars::Get().BreakWorldOffsetX + range))
  1640.                 GameWarning("#brk: ERROR!!!! POSITION OUT OF RANGE");
  1641.         if (pos.y < CNetworkCVars::Get().BreakWorldOffsetY || pos.y > (CNetworkCVars::Get().BreakWorldOffsetY + range))
  1642.                 GameWarning("#brk: ERROR!!!! POSITION OUT OF RANGE");
  1643.         #endif
  1644. }
  1645.  
  1646. void CBreakReplicator::SendPayloads()
  1647. {
  1648.         // Create a simple network payload, without
  1649.         // dependencies on spawned entities
  1650.         SNetBreakDescription desc;
  1651.         desc.flags = eNBF_UseSimpleSend;
  1652.         desc.nEntities = 0;
  1653.         desc.pEntities = NULL;
  1654.  
  1655.         const int lastBreak = m_streams.size();
  1656.         int i = m_activeStartIdx;
  1657.         while (i < lastBreak)
  1658.         {
  1659.                 BreakStream* pStream = m_streams[i];
  1660.                 if (pStream->m_mode == BreakStream::k_recording && pStream->CanSendPayload())
  1661.                 {
  1662.                         if (i == m_activeStartIdx) m_activeStartIdx++;
  1663.                         desc.pMessagePayload = pStream;   // NB: this is an assignment to a "dumb" pointer
  1664.  
  1665.                         // Let the stream fill out the desc if there are entities that need net-binding
  1666.                         pStream->OnSend(desc);
  1667.  
  1668.                         pStream->m_mode = BreakStream::k_finished;
  1669.  
  1670.                         CObjectIdentifier& identifier = pStream->m_identifier;
  1671.                         if (identifier.m_objType == CObjectIdentifier::k_entity && identifier.m_holdingEntity != 0)
  1672.                         {
  1673.                                 // This ensures that this entity is enabled
  1674.                                 // before sending any break messages, which
  1675.                                 // is important for client joins
  1676.                                 desc.breakageEntity = identifier.m_holdingEntity;
  1677.                         }
  1678.  
  1679.                         CCryAction* pCryAction = CCryAction::GetCryAction();
  1680.                         if (pCryAction != NULL)
  1681.                         {
  1682.                                 INetContext* pNetContext = pCryAction->GetNetContext();
  1683.                                 if (pNetContext != NULL)
  1684.                                 {
  1685.                                         pNetContext->LogBreak(desc);
  1686.                                 }
  1687.                         }
  1688.                 }
  1689.                 i++;
  1690.         }
  1691. }
  1692.  
  1693. void CBreakReplicator::PushPlayback(BreakStream* pStream)
  1694. {
  1695.         // Client: push the stream on a todo list.
  1696.         LOGBREAK("# PushPlayback, breakIdx = %d", pStream->m_breakIdx);
  1697.         if (m_numPendingStreams < NET_MAX_PENDING_BREAKAGE_STREAMS)
  1698.         {
  1699.                 // We need to keep the list of pending breaks sorted by breakIdx
  1700.                 // Insert at end, and then push downwards
  1701.                 int i = m_numPendingStreams;
  1702.                 const int breakIdx = pStream->m_breakIdx;
  1703.                 while (i > 0 && breakIdx < m_pendingStreams[i - 1]->m_breakIdx)
  1704.                 {
  1705.                         m_pendingStreams[i] = m_pendingStreams[i - 1];
  1706.                         i--;
  1707.                 }
  1708.                 m_pendingStreams[i] = pStream;
  1709.                 m_numPendingStreams++;
  1710.                 return;
  1711.         }
  1712.         else
  1713.         {
  1714.                 DEBUG_ASSERT("m_numPendingStreams < (NET_MAX_PENDING_BREAKAGE_STREAMS-1)");
  1715.                 GameWarning("#brk: TOO MANY PENDING BREAK STREAMS!");
  1716.         }
  1717.         pStream->Release();
  1718. }
  1719.  
  1720. int CBreakReplicator::PlaybackStream(BreakStream* pStream)
  1721. {
  1722.         if (!pStream->IsRenderMeshReady())
  1723.                 return 0;
  1724.  
  1725.         const int lastBreak = m_streams.size();
  1726.  
  1727.         int bStartStream = 1;
  1728.  
  1729.         LOGBREAK("# Trying playback for breakstream: %d", pStream->m_breakIdx);
  1730.  
  1731.         // Check that we are not already breaking this entity!
  1732.         // can only process one break at a time
  1733.         int i = m_activeStartIdx;
  1734.         while (i < lastBreak)
  1735.         {
  1736.                 if (((m_streams[i]->m_mode - BreakStream::k_playing) | ((INT_PTR)m_streams[i]->m_pent - (INT_PTR)pStream->m_pent)) == 0)
  1737.                 {
  1738.                         // Entity is already being broken, skip for now!
  1739.                         bStartStream = 0;
  1740.                         LOGBREAK("#     ==== CAN'T START because waiting for stream: %d, pent: %p, mode: %s", m_streams[i]->m_breakIdx, m_streams[i]->m_pent, BreakStreamGetModeName(m_streams[i]->m_mode));
  1741.                         break;
  1742.                 }
  1743.                 i++;
  1744.         }
  1745.         if (bStartStream)
  1746.         {
  1747.                 // Make room for the stream
  1748.                 const int initialSize = m_streams.size();
  1749.                 if (m_streams.size() <= pStream->m_breakIdx)
  1750.                 {
  1751.                         m_streams.resize(pStream->m_breakIdx + 32);
  1752.                         const int newSize = m_streams.size();
  1753.                         for (int j = initialSize; j < newSize; j++)
  1754.                         {
  1755.                                 m_streams[j] = &s_dummyStream;
  1756.                         }
  1757.                 }
  1758.                 LOGBREAK("# => Starting Playback for BreakStream: %d", pStream->m_breakIdx);
  1759.                 m_streams[pStream->m_breakIdx] = pStream;
  1760.                 m_activeStartIdx = min(m_activeStartIdx, (int)pStream->m_breakIdx);
  1761.                 pStream->Playback();
  1762.         }
  1763.  
  1764.         return bStartStream;
  1765. }
  1766.  
  1767. void CBreakReplicator::PlaybackBreakage()
  1768. {
  1769.         // Only use the invalid find counters once level has fully loaded
  1770.         if (m_timeSinceLevelLoaded < 0.f)
  1771.                 return;
  1772.  
  1773.         float dt = gEnv->pTimer->GetFrameTime();
  1774.         m_timeSinceLevelLoaded += dt;
  1775.         bool bEnableInavlidCounters = (m_timeSinceLevelLoaded > NET_LEVEL_LOAD_TIME_BEFORE_USING_INAVLID_COUNTERS);
  1776.  
  1777.         // Pull streams out of the pending list,
  1778.         // try to find the physics entity,
  1779.         // making sure that only one stream can act upon
  1780.         // an entity at any one time
  1781.  
  1782.         int n = 0;
  1783.         const int numPending = m_numPendingStreams;
  1784.         int numPlayed = 0;
  1785.  
  1786.         int p = 0;
  1787.         for (; p < numPending && numPlayed < BS_MAX_NUM_TO_PLAYBACK; p++)
  1788.         {
  1789.                 BreakStream* pStream = m_pendingStreams[p];
  1790.                 IPhysicalEntity* pent = pStream->m_pent;
  1791.  
  1792.                 if (pStream->IsWaitinOnRenderMesh() && !pStream->IsRenderMeshReady())
  1793.                 {
  1794.                         // Couldn't start, we need to keep the stream pending
  1795.                         m_pendingStreams[n] = m_pendingStreams[p];
  1796.                         n++;
  1797.                         continue;
  1798.                 }
  1799.  
  1800.                 if (pStream->m_invalidFindCount < NET_MAX_NUM_FRAMES_TO_FIND_ENTITY)
  1801.                 {
  1802.                         bool bCanPlay = false;
  1803.                         if (pStream->m_subBreakIdx == 0)
  1804.                         {
  1805.                                 // Can play straight away, this stream has no dependencies
  1806.                                 bCanPlay = true;
  1807.                         }
  1808.                         else
  1809.                         {
  1810.                                 // Play streams in order - need to wait for their dependents
  1811.                                 for (int i = m_streams.size() - 1; i >= 0; --i)
  1812.                                 {
  1813.                                         if (m_streams[i]->IsIdentifierEqual(pStream->m_identifier))
  1814.                                         {
  1815.                                                 if (pStream->m_subBreakIdx == (m_streams[i]->m_subBreakIdx + 1))
  1816.                                                 {
  1817.                                                         bCanPlay = (m_streams[i]->m_mode == BreakStream::k_finished);
  1818.                                                 }
  1819.                                                 break;
  1820.                                         }
  1821.                                 }
  1822.  
  1823.                                 if (bCanPlay == false && pStream->m_waitForDependent >= NET_MAX_NUM_FRAMES_TO_WAIT_FOR_BREAK_DEPENDENCY)
  1824.                                 {
  1825.                                         // Force the playback of this stream
  1826.                                         bCanPlay = true;
  1827.                                 }
  1828.                                 if (bEnableInavlidCounters)
  1829.                                         pStream->m_waitForDependent++;
  1830.                         }
  1831.  
  1832.                         if (bCanPlay)
  1833.                         {
  1834.                                 if (pent == NULL)
  1835.                                 {
  1836.                                         // Can we identify the physics ent that should be broken by the stream?
  1837.                                         pent = pStream->m_identifier.FindPhysicalEntity();
  1838.                                         if (pent)
  1839.                                         {
  1840.                                                 pent->AddRef(); // Don't let the physics delete until observing has finished
  1841.                                                 pStream->m_pent = pent;
  1842.  
  1843.                                         }
  1844.                                         else
  1845.                                         {
  1846.                                                 if (bEnableInavlidCounters)
  1847.                                                 {
  1848.                                                         pStream->m_invalidFindCount++;
  1849.                                                         LOGBREAK("# WARNING: stream (%d), could not be played, can't find pent to break", pStream->m_breakIdx);
  1850.                                                 }
  1851.                                         }
  1852.                                 }
  1853.                         }
  1854.  
  1855.                         int bPlayed = (pent) ? PlaybackStream(pStream) : 0;
  1856.                         numPlayed += bPlayed;
  1857.                         if (bPlayed == 0)
  1858.                         {
  1859.                                 // Couldn't start, we need to keep the stream pending
  1860.                                 m_pendingStreams[n] = m_pendingStreams[p];
  1861.                                 n++;
  1862.                         }
  1863.                 }
  1864.                 else
  1865.                 {
  1866.                         // Failed to playback the stream
  1867.                         pStream->Release();
  1868.                 }
  1869.         }
  1870.         for (; p < numPending; ++p)
  1871.         {
  1872.                 // Couldn't process (numPlayed<BS_MAX_NUM_TO_PLAYBACK condition), we need to keep the streams pending
  1873.                 m_pendingStreams[n] = m_pendingStreams[p];
  1874.                 n++;
  1875.         }
  1876.         m_numPendingStreams = n;
  1877.  
  1878.         #if DEBUG_NET_BREAKAGE
  1879.         LOGBREAK("# breaks still to play:");
  1880.         for (int i = 0; i < m_numPendingStreams; i++)
  1881.         {
  1882.                 LOGBREAK("#    pending: %d", m_pendingStreams[i]->m_breakIdx);
  1883.         }
  1884.         #endif
  1885. }
  1886.  
  1887. void* CBreakReplicator::SerialiseBreakage(TSerialize ser, BreakStream* pStream)
  1888. {
  1889.         CBitArray array(&ser);
  1890.  
  1891.         if (array.IsReading())
  1892.         {
  1893.                 // Create the correct stream
  1894.                 int type;
  1895.                 int breakIdx;
  1896.                 int subBreakIdx;
  1897.                 array.Serialize(breakIdx, 0, NET_MAX_BREAKS - 1);
  1898.                 array.Serialize(subBreakIdx, 0, 255);
  1899.                 array.Serialize(type, 1, BreakStream::k_numTypes - 1);
  1900.                 assert(pStream == NULL);
  1901.                 if (type == BreakStream::k_partBreak)
  1902.                         pStream = new PartBreak;
  1903.                 if (type == BreakStream::k_planeBreak)
  1904.                         pStream = new PlaneBreak;
  1905.                 if (type == BreakStream::k_deformBreak)
  1906.                         pStream = new DeformBreak;
  1907.                 assert(pStream);
  1908.                 assert(pStream->m_type == type);
  1909.                 pStream->m_breakIdx = breakIdx;
  1910.                 pStream->m_subBreakIdx = subBreakIdx;
  1911.         }
  1912.         else
  1913.         {
  1914.                 array.Serialize(pStream->m_breakIdx, 0, NET_MAX_BREAKS - 1);
  1915.                 array.Serialize(pStream->m_subBreakIdx, 0, 255);
  1916.                 array.Serialize(pStream->m_type, 1, BreakStream::k_numTypes - 1);
  1917.         }
  1918.  
  1919.         #if DEBUG_NET_BREAKAGE
  1920.         LOGBREAK("# .-----------------------------------.");
  1921.         LOGBREAK("# |  %s (type: %s) (idx: %3d)", array.IsReading() ? "RECIEVED" : "SENDING", BreakStreamGetTypeName(pStream->m_type), pStream->m_breakIdx);
  1922.         LOGBREAK("# .-----------------------------------.");
  1923.         #endif
  1924.  
  1925.         pStream->SerializeWith(array);
  1926.  
  1927.         // Flush the bit serialiser
  1928.         if (!array.IsReading())
  1929.         {
  1930.                 array.WriteToSerializer();
  1931.         }
  1932.  
  1933.         return pStream;
  1934. }
  1935.  
  1936. // This is the reciever of the low level RMI
  1937. void* CBreakReplicator::ReceiveSimpleBreakage(TSerialize ser)
  1938. {
  1939.         return SerialiseBreakage(ser, NULL);
  1940. }
  1941.  
  1942. void CBreakReplicator::PlaybackSimpleBreakage(void* userData, INetBreakageSimplePlaybackPtr pBreakage)
  1943. {
  1944.         if (userData)
  1945.         {
  1946.                 // Check we haven't already received this break
  1947.                 // This is only an issue after host-migration
  1948.                 BreakStream* pStream = (BreakStream*)userData;
  1949.                 if (pStream->m_breakIdx >= m_streams.size() || m_streams[pStream->m_breakIdx] == &s_dummyStream)
  1950.                 {
  1951.                         // A break stream has been serialised, push it on the pending playlist
  1952.                         // The low level class, pBreakage, is used to collect any spawned entities
  1953.                         // which need to be net bound
  1954.                         CRY_ASSERT(!CCryAction::GetCryAction()->IsGamePaused());
  1955.                         LOGBREAK("# PlaybackSimpleBreakage: breakIdx: %d", pStream->m_breakIdx);
  1956.                         pStream->AddRef(); // Make sure any "dumb" pointers never delete this stream!
  1957.                         pStream->Init(BreakStream::k_playing);
  1958.                         pStream->m_collector = pBreakage;
  1959.                         // Need to a create a new identifier
  1960.                         // or get a more upto date one from the existing list
  1961.                         GetIdentifier(&pStream->m_identifier, NULL, true);
  1962.                         PushPlayback(pStream);
  1963.                 }
  1964.         }
  1965. }
  1966.  
  1967. const EventPhysRemoveEntityParts* CBreakReplicator::GetRemovePartEvents(int& iNumEvents)
  1968. {
  1969.         iNumEvents = m_removePartEvents.size();
  1970.         if (iNumEvents)
  1971.                 return &(m_removePartEvents[0]);
  1972.         else
  1973.                 return NULL;
  1974. }
  1975.  
  1976. void CBreakReplicator::OnBrokeSomething(const SBreakEvent& be, EventPhysMono* pMono, bool isPlane)
  1977. {
  1978.         if (m_bDefineProtocolMode_server)
  1979.         {
  1980.                 if (isPlane)
  1981.                         BeginRecordingPlaneBreak(be, pMono);
  1982.                 else
  1983.                         BeginRecordingDeforminBreak(be, pMono);
  1984.         }
  1985.         else
  1986.         {
  1987.                 // Client needs to send this to the server
  1988.                 SClientGlassBreak glassBreak;
  1989.                 glassBreak.m_planeBreak.m_identifier.CreateFromPhysicalEntity(pMono);
  1990.                 glassBreak.m_planeBreak.m_be = be;
  1991.                 CBreakReplicator::SendSvRecvGlassBreakWith(glassBreak, CCryAction::GetCryAction()->GetClientChannel());
  1992.         }
  1993. }
  1994.  
  1995. // Static callbacks from the physics events
  1996. int CBreakReplicator::OnJointBroken(const EventPhys* pEvent)
  1997. {
  1998.         m_pThis->OnJointBroken(static_cast<const EventPhysJointBroken*>(pEvent));
  1999.         return 1;
  2000. }
  2001.  
  2002. int CBreakReplicator::OnCreatePhysEntityPart(const EventPhys* pEvent)
  2003. {
  2004.         m_pThis->OnCreatePhysEntityPart(static_cast<const EventPhysCreateEntityPart*>(pEvent));
  2005.         return 1;
  2006. }
  2007.  
  2008. int CBreakReplicator::OnRemovePhysEntityParts(const EventPhys* pEvent)
  2009. {
  2010.         m_pThis->OnRemovePhysEntityParts(static_cast<const EventPhysRemoveEntityParts*>(pEvent));
  2011.         return 1;
  2012. }
  2013.  
  2014. NET_IMPLEMENT_SIMPLE_ATSYNC_MESSAGE_SEND(CBreakReplicator, SvRecvGlassBreak, SClientGlassBreak);
  2015.  
  2016. NET_IMPLEMENT_SIMPLE_ATSYNC_MESSAGE(CBreakReplicator, SvRecvGlassBreak, eNRT_ReliableUnordered, eMPF_BlocksStateChange)
  2017. {
  2018.         // The client broke the glass - this is the server recieving the message
  2019.         // Playback the breakage - but do *not* put it into the break stream list
  2020.         PlaneBreak* planeBreak = (PlaneBreak*)&param.m_planeBreak;
  2021.         IPhysicalEntity* pent = planeBreak->m_identifier.FindPhysicalEntity();
  2022.         if (pent)
  2023.         {
  2024.                 pent->AddRef(); // Released when the planeBreak is destroyed
  2025.                 planeBreak->m_pent = pent;
  2026.                 planeBreak->m_mode = BreakStream::k_playing;
  2027.                 planeBreak->m_logHostMigrationInfo = 0;
  2028.                 planeBreak->Playback();
  2029.         }
  2030.         return true;
  2031. }
  2032.  
  2033. /*
  2034.    ====================================================================================================================================================
  2035.    End - NET_USE_SIMPLE_BREAKAGE
  2036.    ====================================================================================================================================================
  2037.  */
  2038. #endif
  2039.  
downloadBreakReplicator_Simple.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top