PlayerBuffer.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /* Copyright (c) 2002-2012 Croteam Ltd.
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of version 2 of the GNU General Public License as published by
  4. the Free Software Foundation
  5. This program is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along
  10. with this program; if not, write to the Free Software Foundation, Inc.,
  11. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
  12. #include "stdh.h"
  13. #include <Engine/Base/Console.h>
  14. #include <Engine/Network/PlayerBuffer.h>
  15. /*
  16. * Constructor.
  17. */
  18. CPlayerBuffer::CPlayerBuffer(void) {
  19. plb_Active = FALSE;
  20. plb_abReceived.Clear();
  21. plb_paLastAction.Clear();
  22. plb_iClient = -1;
  23. }
  24. /*
  25. * Destructor.
  26. */
  27. CPlayerBuffer::~CPlayerBuffer(void) {
  28. }
  29. /*
  30. * Activate player buffer for a new player.
  31. */
  32. void CPlayerBuffer::Activate(INDEX iClient)
  33. {
  34. ASSERT(!plb_Active);
  35. plb_Active = TRUE;
  36. plb_iClient = iClient;
  37. // make packets dummy before receiving something
  38. plb_abReceived.Clear();
  39. plb_paLastAction.Clear();
  40. }
  41. /*
  42. * Deactivate player data for removed player.
  43. */
  44. void CPlayerBuffer::Deactivate(void)
  45. {
  46. ASSERT(plb_Active);
  47. plb_Active = FALSE;
  48. plb_iClient = -1;
  49. }
  50. /*
  51. * Receive action packet from player source.
  52. */
  53. void CPlayerBuffer::ReceiveActionPacket(CNetworkMessage *pnm, INDEX iMaxBuffer)
  54. {
  55. ASSERT(plb_Active);
  56. // receive new action
  57. CPlayerAction pa;
  58. (*pnm)>>pa;
  59. // buffer it
  60. plb_abReceived.AddAction(pa);
  61. // read sendbehind
  62. INDEX iSendBehind = 0;
  63. pnm->ReadBits(&iSendBehind, 2);
  64. // foreach resent action
  65. for(INDEX i=0; i<iSendBehind; i++) {
  66. CPlayerAction paOld;
  67. (*pnm)>>paOld;
  68. // if not already sent out back to the client
  69. if (paOld.pa_llCreated>plb_paLastAction.pa_llCreated) {
  70. // buffer it
  71. plb_abReceived.AddAction(paOld);
  72. }
  73. }
  74. /*
  75. INDEX ctBuffered = plb_abReceived.GetCount();
  76. if (ctBuffered>net_iPlayerBufferActions) {
  77. CPrintF("Receive: BUFFER FULL (%d) ++++++++++++++\n", ctBuffered);
  78. }
  79. CPrintF("Receive: buffered %d\n", ctBuffered);
  80. */
  81. // while there are more too many actions buffered
  82. while(plb_abReceived.GetCount()>iMaxBuffer) {
  83. // purge the oldest one
  84. plb_abReceived.RemoveOldest();
  85. }
  86. }
  87. /* Create action packet for player target from oldest buffered action. */
  88. // (prepares lag info for given client number)
  89. void CPlayerBuffer::CreateActionPacket(CNetworkMessage *pnm, INDEX iClient)
  90. {
  91. ASSERT(plb_Active);
  92. CPlayerAction paCurrent;
  93. //CPrintF("Send: buffered %d\n", plb_abReceived.GetCount());
  94. // if there are any buffered actions
  95. if (plb_abReceived.GetCount()>0) {
  96. // retrieve the oldest one
  97. plb_abReceived.GetActionByIndex(0, paCurrent);
  98. // if there are no buffered actions
  99. } else {
  100. // reuse the last one
  101. paCurrent = plb_paLastAction;
  102. //CPrintF("Send: BUFFER EMPTY ---------\n");
  103. }
  104. // create a new delta action packet between last sent and current action
  105. CPlayerAction paDelta;
  106. for (INDEX i=0; i<sizeof(CPlayerAction); i++) {
  107. ((UBYTE*)&paDelta)[i] = ((UBYTE*)&paCurrent)[i] ^ ((UBYTE*)&plb_paLastAction)[i];
  108. }
  109. // if the client that message is sent to owns the player
  110. if (iClient==plb_iClient) {
  111. // send delta of the timetag
  112. paDelta.pa_llCreated = paCurrent.pa_llCreated-plb_paLastAction.pa_llCreated;
  113. // if the client doesn't own the player
  114. } else {
  115. // no timetag information
  116. paDelta.pa_llCreated = 0;
  117. }
  118. // send the delta packet
  119. (*pnm)<<paDelta;
  120. }
  121. /* Advance action buffer by one tick by removing oldest action. */
  122. void CPlayerBuffer::AdvanceActionBuffer(void)
  123. {
  124. ASSERT(plb_Active);
  125. // if there are any buffered actions
  126. if (plb_abReceived.GetCount()>0) {
  127. // get the oldest one and remove it
  128. CPlayerAction paCurrent;
  129. plb_abReceived.GetActionByIndex(0, paCurrent);
  130. plb_abReceived.RemoveOldest();
  131. // move current action to last action
  132. plb_paLastAction = paCurrent;
  133. }
  134. }