NetworkEntityUpdateMessage.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <Multiplayer/NetworkEntity/NetworkEntityUpdateMessage.h>
  9. #include <AzCore/Console/ILogger.h>
  10. namespace Multiplayer
  11. {
  12. NetworkEntityUpdateMessage::NetworkEntityUpdateMessage(NetworkEntityUpdateMessage&& rhs)
  13. : m_networkRole(rhs.m_networkRole)
  14. , m_entityId(rhs.m_entityId)
  15. , m_isDelete(rhs.m_isDelete)
  16. , m_wasMigrated(rhs.m_wasMigrated)
  17. , m_hasValidPrefabId(rhs.m_hasValidPrefabId)
  18. , m_prefabEntityId(rhs.m_prefabEntityId)
  19. , m_data(AZStd::move(rhs.m_data))
  20. {
  21. ;
  22. }
  23. NetworkEntityUpdateMessage::NetworkEntityUpdateMessage(const NetworkEntityUpdateMessage& rhs)
  24. : m_networkRole(rhs.m_networkRole)
  25. , m_entityId(rhs.m_entityId)
  26. , m_isDelete(rhs.m_isDelete)
  27. , m_wasMigrated(rhs.m_wasMigrated)
  28. , m_hasValidPrefabId(rhs.m_hasValidPrefabId)
  29. , m_prefabEntityId(rhs.m_prefabEntityId)
  30. {
  31. if (rhs.m_data != nullptr)
  32. {
  33. m_data = AZStd::make_unique<AzNetworking::PacketEncodingBuffer>();
  34. (*m_data) = (*rhs.m_data); // Deep-copy
  35. }
  36. }
  37. NetworkEntityUpdateMessage::NetworkEntityUpdateMessage(NetEntityRole networkRole, NetEntityId entityId, bool isDeleted, bool wasMigrated)
  38. : m_networkRole(networkRole)
  39. , m_entityId(entityId)
  40. , m_isDelete(isDeleted)
  41. , m_wasMigrated(wasMigrated)
  42. {
  43. ;
  44. }
  45. NetworkEntityUpdateMessage& NetworkEntityUpdateMessage::operator =(NetworkEntityUpdateMessage&& rhs)
  46. {
  47. m_networkRole = rhs.m_networkRole;
  48. m_entityId = rhs.m_entityId;
  49. m_isDelete = rhs.m_isDelete;
  50. m_wasMigrated = rhs.m_wasMigrated;
  51. m_hasValidPrefabId = rhs.m_hasValidPrefabId;
  52. m_prefabEntityId = rhs.m_prefabEntityId;
  53. m_data = AZStd::move(rhs.m_data);
  54. return *this;
  55. }
  56. NetworkEntityUpdateMessage& NetworkEntityUpdateMessage::operator =(const NetworkEntityUpdateMessage& rhs)
  57. {
  58. m_networkRole = rhs.m_networkRole;
  59. m_entityId = rhs.m_entityId;
  60. m_isDelete = rhs.m_isDelete;
  61. m_wasMigrated = rhs.m_wasMigrated;
  62. m_hasValidPrefabId = rhs.m_hasValidPrefabId;
  63. m_prefabEntityId = rhs.m_prefabEntityId;
  64. if (rhs.m_data != nullptr)
  65. {
  66. m_data = AZStd::make_unique<AzNetworking::PacketEncodingBuffer>();
  67. *m_data = (*rhs.m_data);
  68. }
  69. return *this;
  70. }
  71. bool NetworkEntityUpdateMessage::operator ==(const NetworkEntityUpdateMessage& rhs) const
  72. {
  73. // Note that we intentionally don't compare the blob buffers themselves
  74. return ((m_networkRole == rhs.m_networkRole)
  75. && (m_entityId == rhs.m_entityId)
  76. && (m_isDelete == rhs.m_isDelete)
  77. && (m_wasMigrated == rhs.m_wasMigrated)
  78. && (m_hasValidPrefabId == rhs.m_hasValidPrefabId)
  79. && (m_prefabEntityId == rhs.m_prefabEntityId));
  80. }
  81. bool NetworkEntityUpdateMessage::operator !=(const NetworkEntityUpdateMessage& rhs) const
  82. {
  83. return !(*this == rhs);
  84. }
  85. uint32_t NetworkEntityUpdateMessage::GetEstimatedSerializeSize() const
  86. {
  87. // * NOTE * Keep this in sync with the actual serialize method for this class
  88. // If we return an underestimate, the replicator could start generating update packets that fragment, which would be terrible for gameplay latency
  89. static const uint32_t sizeOfFlags = 1;
  90. static const uint32_t sizeOfEntityId = sizeof(NetEntityId);
  91. static const uint32_t sizeOfSliceId = 6;
  92. // 2-byte size header + the actual blob payload itself
  93. const uint32_t sizeOfBlob = static_cast<uint32_t>((m_data != nullptr) ? sizeof(PropertyIndex) + m_data->GetSize() : 0);
  94. if (m_hasValidPrefabId)
  95. {
  96. // sliceId is transmitted
  97. return sizeOfFlags + sizeOfEntityId + sizeOfSliceId + sizeOfBlob;
  98. }
  99. // No sliceId, remote replicator already exists so we don't need to know what type of entity this is
  100. return sizeOfFlags + sizeOfEntityId + sizeOfBlob;
  101. }
  102. NetEntityRole NetworkEntityUpdateMessage::GetNetworkRole() const
  103. {
  104. return m_networkRole;
  105. }
  106. NetEntityId NetworkEntityUpdateMessage::GetEntityId() const
  107. {
  108. return m_entityId;
  109. }
  110. bool NetworkEntityUpdateMessage::GetIsDelete() const
  111. {
  112. return m_isDelete;
  113. }
  114. bool NetworkEntityUpdateMessage::GetWasMigrated() const
  115. {
  116. return m_wasMigrated;
  117. }
  118. bool NetworkEntityUpdateMessage::GetHasValidPrefabId() const
  119. {
  120. return m_hasValidPrefabId;
  121. }
  122. void NetworkEntityUpdateMessage::SetPrefabEntityId(const PrefabEntityId& value)
  123. {
  124. m_hasValidPrefabId = true;
  125. m_prefabEntityId = value;
  126. }
  127. const PrefabEntityId& NetworkEntityUpdateMessage::GetPrefabEntityId() const
  128. {
  129. return m_prefabEntityId;
  130. }
  131. void NetworkEntityUpdateMessage::SetData(const AzNetworking::PacketEncodingBuffer& value)
  132. {
  133. if (m_data == nullptr)
  134. {
  135. m_data = AZStd::make_unique<AzNetworking::PacketEncodingBuffer>();
  136. }
  137. (*m_data) = value;
  138. }
  139. const AzNetworking::PacketEncodingBuffer* NetworkEntityUpdateMessage::GetData() const
  140. {
  141. return m_data.get();
  142. }
  143. AzNetworking::PacketEncodingBuffer& NetworkEntityUpdateMessage::ModifyData()
  144. {
  145. if (m_data == nullptr)
  146. {
  147. m_data = AZStd::make_unique<AzNetworking::PacketEncodingBuffer>();
  148. }
  149. return *m_data;
  150. }
  151. bool NetworkEntityUpdateMessage::Serialize(AzNetworking::ISerializer& serializer)
  152. {
  153. // Always serialize the entityId
  154. serializer.Serialize(m_entityId, "EntityId");
  155. // Use the upper 4 bits for boolean flags, and the lower 4 bits for the network role
  156. uint8_t networkTypeAndFlags = (m_isDelete ? 0x40 : 0x00)
  157. | (m_wasMigrated ? 0x20 : 0x00)
  158. | (m_hasValidPrefabId ? 0x10 : 0x00)
  159. | static_cast<uint8_t>(m_networkRole);
  160. if (serializer.Serialize(networkTypeAndFlags, "TypeAndFlags"))
  161. {
  162. m_isDelete = (networkTypeAndFlags & 0x40) == 0x40;
  163. m_wasMigrated = (networkTypeAndFlags & 0x20) == 0x20;
  164. m_hasValidPrefabId = (networkTypeAndFlags & 0x10) == 0x10;
  165. m_networkRole = static_cast<NetEntityRole>(networkTypeAndFlags & 0x0F);
  166. }
  167. // We always serialize the data, whether it's an update or a delete.
  168. // This ensures that we have consistent entity data at the point of deletion in case any
  169. // network properties are used during deactivation / deletion logic execution.
  170. if (m_hasValidPrefabId)
  171. {
  172. // Only serialize the prefabEntityId if one was provided.
  173. // Otherwise, a remote replicator is expected to be set up and the prefabEntityId would be redundant
  174. serializer.Serialize(m_prefabEntityId, "PrefabEntityId");
  175. }
  176. // m_data should never be nullptr
  177. if (m_data == nullptr)
  178. {
  179. m_data = AZStd::make_unique<AzNetworking::PacketEncodingBuffer>();
  180. }
  181. serializer.Serialize(*m_data, "Data");;
  182. return serializer.IsValid();
  183. }
  184. }