ReplicationState.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. //
  2. // Urho3D Engine
  3. // Copyright (c) 2008-2011 Lasse Öörni
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. #include "Precompiled.h"
  24. #include "ReplicationState.h"
  25. #include "ReplicationUtils.h"
  26. #include <cstring>
  27. #include "DebugNew.h"
  28. void RevisionBuffer::purgeOld(unsigned short frameNumber)
  29. {
  30. // Remove revisions which are older than last ack, but make sure at least 1 revision remains
  31. if (!mRevisions.size())
  32. return;
  33. unsigned eraseCount = 0;
  34. for (std::vector<Revision>::iterator i = mRevisions.begin(); (i != mRevisions.end() - 1) &&
  35. (mRevisions.size() - eraseCount > 1); ++i)
  36. {
  37. // If oldest and second-oldest are both older than framenumber, or if the second-oldest is on the exact same frame,
  38. // can delete the oldest
  39. std::vector<Revision>::iterator j = i + 1;
  40. if ((j->mFrameNumber == frameNumber) || ((!checkFrameNumber(i->mFrameNumber, frameNumber)) &&
  41. (!checkFrameNumber(j->mFrameNumber, frameNumber))))
  42. eraseCount++;
  43. else
  44. break;
  45. }
  46. if (eraseCount)
  47. {
  48. mRevisions.erase(mRevisions.begin(), mRevisions.begin() + eraseCount);
  49. // Move the data and datapointers
  50. unsigned delta = mRevisions[0].mOffset;
  51. void* src = getModifiableData() + delta;
  52. void* dest = getModifiableData();
  53. memmove(dest, src, getSize() - delta);
  54. resize(getSize() - delta);
  55. for (std::vector<Revision>::iterator i = mRevisions.begin(); i != mRevisions.end(); ++i)
  56. i->mOffset -= delta;
  57. }
  58. }
  59. bool RevisionBuffer::hasUnacked(unsigned short frameNumber) const
  60. {
  61. for (std::vector<Revision>::const_iterator i = mRevisions.begin(); i != mRevisions.end(); ++i)
  62. {
  63. if (checkFrameNumber(i->mFrameNumber, frameNumber, false))
  64. return true;
  65. }
  66. return false;
  67. }
  68. ComponentReplicationState::ComponentReplicationState() :
  69. mExists(true),
  70. mCreatedFrame(0),
  71. mRemovedFrame(0)
  72. {
  73. }
  74. void ComponentReplicationState::created(unsigned short frameNumber)
  75. {
  76. mExists = true;
  77. mCreatedFrame = frameNumber;
  78. mRemovedFrame = 0;
  79. }
  80. void ComponentReplicationState::removed(unsigned short frameNumber)
  81. {
  82. mExists = false;
  83. mCreatedFrame = 0;
  84. mRemovedFrame = frameNumber;
  85. // Clear revisions in case this component gets recreated
  86. mRevisions.clear();
  87. }
  88. void ComponentReplicationState::acked(unsigned short lastAck)
  89. {
  90. // If ack is newer or same age than the creation or removal event, reset it
  91. if ((mCreatedFrame) && (checkFrameNumber(lastAck, mCreatedFrame)))
  92. mCreatedFrame = 0;
  93. if ((mRemovedFrame) && (checkFrameNumber(lastAck, mRemovedFrame)))
  94. mRemovedFrame = 0;
  95. // Remove old data revisions
  96. mRevisions.purgeOld(lastAck);
  97. }
  98. bool ComponentReplicationState::canRemove() const
  99. {
  100. // Can be removed from the replication state if no longer exists, and the remove has been acked
  101. return (!mExists) && (!mRemovedFrame);
  102. }
  103. EntityReplicationState::EntityReplicationState() :
  104. mExists(true),
  105. mCreatedFrame(0),
  106. mRemovedFrame(0),
  107. mStayRelevantTime(0)
  108. {
  109. }
  110. void EntityReplicationState::created(unsigned short frameNumber)
  111. {
  112. mExists = true;
  113. mCreatedFrame = frameNumber;
  114. mRemovedFrame = 0;
  115. }
  116. void EntityReplicationState::removed(unsigned short frameNumber)
  117. {
  118. mExists = false;
  119. mCreatedFrame = 0;
  120. mRemovedFrame = frameNumber;
  121. // Clear property revisions & components in case this entity gets recreated
  122. mPropertyRevisions.clear();
  123. mComponents.clear();
  124. }
  125. void EntityReplicationState::acked(unsigned short lastAck)
  126. {
  127. // If ack is newer or same age than the creation or removal event, reset it
  128. if ((mCreatedFrame) && (checkFrameNumber(lastAck, mCreatedFrame)))
  129. mCreatedFrame = 0;
  130. if ((mRemovedFrame) && (checkFrameNumber(lastAck, mRemovedFrame)))
  131. mRemovedFrame = 0;
  132. // Remove old property revisions
  133. mPropertyRevisions.purgeOld(lastAck);
  134. // Ack each component and remove if necessary
  135. for (std::map<ShortStringHash, ComponentReplicationState>::iterator j = mComponents.begin(); j != mComponents.end();)
  136. {
  137. std::map<ShortStringHash, ComponentReplicationState>::iterator component = j;
  138. ++j;
  139. component->second.acked(lastAck);
  140. if (component->second.canRemove())
  141. mComponents.erase(component);
  142. }
  143. }
  144. bool EntityReplicationState::hasUnacked(unsigned short frameNumber) const
  145. {
  146. if (mPropertyRevisions.hasUnacked(frameNumber))
  147. return true;
  148. for (std::map<ShortStringHash, ComponentReplicationState>::const_iterator i = mComponents.begin(); i != mComponents.end(); ++i)
  149. {
  150. if (i->second.mRevisions.hasUnacked(frameNumber))
  151. return true;
  152. }
  153. return false;
  154. }
  155. bool EntityReplicationState::canRemove() const
  156. {
  157. // Can be removed from the replication state if no longer exists, and the remove has been acked
  158. return (!mExists) && (!mRemovedFrame);
  159. }
  160. unsigned EntityReplicationState::getRevisionCount() const
  161. {
  162. // Return the highest of property revisions and component revisions
  163. int maxRevisions = mPropertyRevisions.getCount();
  164. for (std::map<ShortStringHash, ComponentReplicationState>::const_iterator i = mComponents.begin(); i != mComponents.end(); ++i)
  165. maxRevisions = max((int)maxRevisions, (int)i->second.getRevisionCount());
  166. return maxRevisions;
  167. }
  168. void SceneReplicationState::clear()
  169. {
  170. mEntities.clear();
  171. }
  172. void SceneReplicationState::acked(unsigned short lastAck)
  173. {
  174. // Ack each entity and remove if necessary
  175. for (std::map<EntityID, EntityReplicationState>::iterator i = mEntities.begin(); i != mEntities.end();)
  176. {
  177. std::map<EntityID, EntityReplicationState>::iterator entity = i;
  178. ++i;
  179. entity->second.acked(lastAck);
  180. if (entity->second.canRemove())
  181. mEntities.erase(entity);
  182. }
  183. }
  184. unsigned SceneReplicationState::getRevisionCount() const
  185. {
  186. // Get the highest revision count of all entities;
  187. int maxRevisions = 0;
  188. for (std::map<EntityID, EntityReplicationState>::const_iterator i = mEntities.begin(); i != mEntities.end(); ++i)
  189. maxRevisions = max((int)maxRevisions, (int)i->second.getRevisionCount());
  190. return maxRevisions;
  191. }