networkobject.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** Confidential - Westwood Studios ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : Commando *
  23. * *
  24. * $Archive:: /Commando/Code/wwnet/networkobject.cpp $*
  25. * *
  26. * $Author:: Tom_s $*
  27. * *
  28. * $Modtime:: 1/07/02 5:16p $*
  29. * *
  30. * $Revision:: 28 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "networkobject.h"
  36. #include "networkobjectmgr.h"
  37. #include "wwmath.h"
  38. #include "vector3.h"
  39. #include "wwprofile.h"
  40. #include "systimer.h"
  41. #define CLIENT_SIDE_UPDATE_FREQUENCY_SAMPLE_PERIOD (1000 * 10)
  42. ////////////////////////////////////////////////////////////////
  43. // Static member initializtaion
  44. ////////////////////////////////////////////////////////////////
  45. bool NetworkObjectClass::IsServer = false;
  46. ////////////////////////////////////////////////////////////////
  47. //
  48. // NetworkObjectClass
  49. //
  50. ////////////////////////////////////////////////////////////////
  51. NetworkObjectClass::NetworkObjectClass (void) :
  52. ImportStateCount (0),
  53. LastClientsideUpdateTime (0),
  54. NetworkID (0),
  55. IsDeletePending (false),
  56. CachedPriority (0),
  57. UnreliableOverride (false),
  58. AppPacketType (0),
  59. FrequentExportPacketSize(0),
  60. ClientsideUpdateFrequencySampleStartTime(TIMEGETTIME()),
  61. ClientsideUpdateFrequencySampleCount(0),
  62. ClientsideUpdateRate(0),
  63. #ifdef WWDEBUG
  64. CreatedByPacketID(0),
  65. #endif //WWDEBUG
  66. LastObjectIdIDamaged(-1),
  67. LastObjectIdIGotDamagedBy(-1)
  68. {
  69. if (IsServer)
  70. {
  71. //
  72. // Assign the object a unique ID. This will happen on the client too during object
  73. // imports, but will be corrected immediately with an explicit Set_Network_ID call.
  74. //
  75. int new_id = NetworkObjectMgrClass::Get_New_Dynamic_ID();
  76. //WWDEBUG_SAY(("New network id = %d\n", new_id));//TSS2001
  77. Set_Network_ID(new_id);
  78. }
  79. //
  80. // By default, objects have the modifiction dirty bit set.
  81. // Static objects therefore don't need to remember to set this in their constructor.
  82. // Game objects will set BIT_CREATION.
  83. //
  84. Clear_Object_Dirty_Bits ();
  85. memset(CachedPriority_2, 0, sizeof(CachedPriority_2));
  86. return ;
  87. }
  88. ////////////////////////////////////////////////////////////////
  89. //
  90. // ~NetworkObjectClass
  91. //
  92. ////////////////////////////////////////////////////////////////
  93. NetworkObjectClass::~NetworkObjectClass (void)
  94. {
  95. //
  96. // Unregister this object from network updates
  97. //
  98. NetworkObjectMgrClass::Unregister_Object (this);
  99. return ;
  100. }
  101. extern bool SensibleUpdates;
  102. ////////////////////////////////////////////////////////////////
  103. //
  104. // Set_Network_ID
  105. //
  106. ////////////////////////////////////////////////////////////////
  107. void
  108. NetworkObjectClass::Set_Network_ID (int id)
  109. {
  110. WWASSERT(id > 0);
  111. //
  112. // Remove the object from the manager, change it's ID,
  113. // and re-insert it.
  114. //
  115. NetworkObjectMgrClass::Unregister_Object (this);
  116. NetworkID = id;
  117. NetworkObjectMgrClass::Register_Object (this);
  118. return ;
  119. }
  120. ////////////////////////////////////////////////////////////////
  121. //
  122. // Get_Object_Dirty_Bits
  123. //
  124. ////////////////////////////////////////////////////////////////
  125. BYTE
  126. NetworkObjectClass::Get_Object_Dirty_Bits (int client_id)
  127. {
  128. return ClientStatus[client_id];
  129. }
  130. ////////////////////////////////////////////////////////////////
  131. //
  132. // Set_Object_Dirty_Bits
  133. //
  134. ////////////////////////////////////////////////////////////////
  135. void
  136. NetworkObjectClass::Set_Object_Dirty_Bits (int client_id, BYTE bits)
  137. {
  138. ClientStatus[client_id] = bits;
  139. }
  140. ////////////////////////////////////////////////////////////////
  141. //
  142. // Get_Object_Dirty_Bit
  143. //
  144. ////////////////////////////////////////////////////////////////
  145. bool
  146. NetworkObjectClass::Get_Object_Dirty_Bit (int client_id, DIRTY_BIT dirty_bit)
  147. {
  148. return ((ClientStatus[client_id] & dirty_bit) == dirty_bit);
  149. }
  150. ////////////////////////////////////////////////////////////////
  151. //
  152. // Clear_Object_Dirty_Bits
  153. //
  154. ////////////////////////////////////////////////////////////////
  155. void
  156. NetworkObjectClass::Clear_Object_Dirty_Bits (void)
  157. {
  158. //
  159. // Reset the status for each client
  160. //
  161. for (int index = 0; index < MAX_CLIENT_COUNT; index ++) {
  162. ClientStatus[index] = 0;
  163. UpdateInfo[index].LastUpdateTime = 0;
  164. UpdateInfo[index].UpdateRate = 50;
  165. UpdateInfo[index].ClientHintCount = 0;
  166. }
  167. return ;
  168. }
  169. ////////////////////////////////////////////////////////////////
  170. //
  171. // Set_Object_Dirty_Bit
  172. //
  173. ////////////////////////////////////////////////////////////////
  174. void
  175. NetworkObjectClass::Set_Object_Dirty_Bit (int client_id, DIRTY_BIT dirty_bit, bool onoff)
  176. {
  177. if (onoff) {
  178. ClientStatus[client_id] |= dirty_bit;
  179. } else {
  180. ClientStatus[client_id] &= (~dirty_bit);
  181. }
  182. return ;
  183. }
  184. ////////////////////////////////////////////////////////////////
  185. //
  186. // Set_Object_Dirty_Bit
  187. //
  188. ////////////////////////////////////////////////////////////////
  189. void
  190. NetworkObjectClass::Set_Object_Dirty_Bit (DIRTY_BIT dirty_bit, bool onoff)
  191. {
  192. if (!IsServer)
  193. {
  194. return;
  195. }
  196. //
  197. // Change the status for each client
  198. // N.B. Client 0 is actually the server.
  199. //
  200. for (int index = 1; index < MAX_CLIENT_COUNT; index ++) {//TSS2001
  201. if (onoff) {
  202. ClientStatus[index] |= dirty_bit;
  203. } else {
  204. ClientStatus[index] &= (~dirty_bit);
  205. }
  206. }
  207. return ;
  208. }
  209. ////////////////////////////////////////////////////////////////
  210. //
  211. // Is_Client_Dirty
  212. //
  213. ////////////////////////////////////////////////////////////////
  214. bool
  215. NetworkObjectClass::Is_Client_Dirty (int client_id)
  216. {
  217. return ClientStatus[client_id] != 0;
  218. }
  219. ////////////////////////////////////////////////////////////////
  220. //
  221. // Set_Delete_Pending
  222. //
  223. ////////////////////////////////////////////////////////////////
  224. void
  225. NetworkObjectClass::Set_Delete_Pending (void)
  226. {
  227. IsDeletePending = true;
  228. NetworkObjectMgrClass::Register_Object_For_Deletion (this);
  229. return;
  230. }
  231. ////////////////////////////////////////////////////////////////
  232. //
  233. // Reset_Client_Hint_Count
  234. //
  235. ////////////////////////////////////////////////////////////////
  236. void
  237. NetworkObjectClass::Reset_Client_Hint_Count(int client_id)
  238. {
  239. WWASSERT(client_id >= 0 && client_id < MAX_CLIENT_COUNT);
  240. UpdateInfo[client_id].ClientHintCount = 0;
  241. }
  242. ////////////////////////////////////////////////////////////////
  243. //
  244. // Increment_Client_Hint_Count
  245. //
  246. ////////////////////////////////////////////////////////////////
  247. void
  248. NetworkObjectClass::Increment_Client_Hint_Count(int client_id)
  249. {
  250. WWASSERT(client_id >= 0 && client_id < MAX_CLIENT_COUNT);
  251. if (UpdateInfo[client_id].ClientHintCount < 255) {
  252. UpdateInfo[client_id].ClientHintCount++;
  253. }
  254. }
  255. ////////////////////////////////////////////////////////////////
  256. //
  257. // Hint_To_All_Clients
  258. //
  259. ////////////////////////////////////////////////////////////////
  260. void
  261. NetworkObjectClass::Hint_To_All_Clients(void)
  262. {
  263. //
  264. // Hint that an update should be sent to all clients
  265. //
  266. for (int index = 0; index < MAX_CLIENT_COUNT; index ++) {
  267. Increment_Client_Hint_Count(index);
  268. }
  269. }
  270. ////////////////////////////////////////////////////////////////
  271. //
  272. // Get_Client_Hint_Count
  273. //
  274. ////////////////////////////////////////////////////////////////
  275. BYTE
  276. NetworkObjectClass::Get_Client_Hint_Count(int client_id)
  277. {
  278. WWASSERT(client_id >= 0 && client_id < MAX_CLIENT_COUNT);
  279. return UpdateInfo[client_id].ClientHintCount;
  280. }
  281. ////////////////////////////////////////////////////////////////
  282. //
  283. // Belongs_To_Client
  284. //
  285. ////////////////////////////////////////////////////////////////
  286. bool
  287. NetworkObjectClass::Belongs_To_Client (int client_id)
  288. {
  289. WWASSERT(client_id > 0);
  290. int id_min = NETID_CLIENT_OBJECT_MIN + (client_id - 1) * 100000;
  291. int id_max = id_min + 100000 - 1;
  292. return (NetworkID >= id_min) && (NetworkID <= id_max);
  293. }
  294. ////////////////////////////////////////////////////////////////
  295. //
  296. // Get_Last_Update_Time - Returns time that the client last received an update for this object.
  297. //
  298. // In: ID of client
  299. // Out: Last update time.
  300. //
  301. // 10/16/2001 2:45PM ST
  302. ////////////////////////////////////////////////////////////////
  303. unsigned long
  304. NetworkObjectClass::Get_Last_Update_Time(int client_id)
  305. {
  306. // Is this assert right? ST - 10/16/2001 2:44PM
  307. WWASSERT(client_id > 0 && client_id <= MAX_CLIENT_COUNT);
  308. return(UpdateInfo[client_id].LastUpdateTime);
  309. }
  310. ////////////////////////////////////////////////////////////////
  311. //
  312. // Get_Update_Rate - Returns delay in ms between updates for this object to the given client
  313. //
  314. // In: ID of client
  315. // Out: Update delay in ms
  316. //
  317. // 10/16/2001 2:45PM ST
  318. ////////////////////////////////////////////////////////////////
  319. unsigned short
  320. NetworkObjectClass::Get_Update_Rate(int client_id)
  321. {
  322. // Is this assert right? ST - 10/16/2001 2:44PM
  323. WWASSERT(client_id > 0 && client_id <= MAX_CLIENT_COUNT);
  324. return(UpdateInfo[client_id].UpdateRate);
  325. }
  326. ////////////////////////////////////////////////////////////////
  327. //
  328. // Set_Last_Update_Time - Sets time that the client last received an update for this object.
  329. //
  330. // In: ID of client, time this object was sent to the client.
  331. // Out: Nothing
  332. //
  333. // 10/16/2001 2:45PM ST
  334. ////////////////////////////////////////////////////////////////
  335. void
  336. NetworkObjectClass::Set_Last_Update_Time(int client_id, unsigned long time)
  337. {
  338. // Is this assert right? ST - 10/16/2001 2:44PM
  339. WWASSERT(client_id > 0 && client_id <= MAX_CLIENT_COUNT);
  340. UpdateInfo[client_id].LastUpdateTime = time;
  341. }
  342. ////////////////////////////////////////////////////////////////
  343. //
  344. // Set_Update_Rate - Sets the ms delay between updates for this client
  345. //
  346. // In: ID of client, delay in ms between updates
  347. // Out: Nothing
  348. //
  349. // 10/16/2001 2:45PM ST
  350. ////////////////////////////////////////////////////////////////
  351. void
  352. NetworkObjectClass::Set_Update_Rate(int client_id, unsigned short rate)
  353. {
  354. // Is this assert right? ST - 10/16/2001 2:44PM
  355. WWASSERT(client_id > 0 && client_id <= MAX_CLIENT_COUNT);
  356. UpdateInfo[client_id].UpdateRate = rate;
  357. }
  358. /*
  359. ////////////////////////////////////////////////////////////////
  360. //
  361. // Clear_Object_Dirty_Bits
  362. //
  363. ////////////////////////////////////////////////////////////////
  364. void
  365. NetworkObjectClass::Clear_Object_Dirty_Bits (int client_id)
  366. {
  367. ClientStatus[client_id] = 0;
  368. return ;
  369. }
  370. */
  371. //float NetworkObjectClass::RandomFloat = 0.0F;
  372. //TSS2001d float perturbation = RandomFloat * 2 * distance - distance;
  373. /*
  374. ////////////////////////////////////////////////////////////////
  375. //
  376. // Set_Random_Float
  377. //
  378. ////////////////////////////////////////////////////////////////
  379. void
  380. NetworkObjectClass::Set_Random_Float (float random_float)
  381. {
  382. WWASSERT(random_float >= 0 && random_float <= 1);
  383. RandomFloat = random_float;
  384. }
  385. */
  386. //Set_Object_Dirty_Bit (BIT_RARE, true);
  387. //float NetworkObjectClass::MaxDistance = 300.0F;
  388. ////////////////////////////////////////////////////////////////
  389. //
  390. // Compute_Object_Priority
  391. //
  392. ////////////////////////////////////////////////////////////////
  393. /*
  394. float
  395. NetworkObjectClass::Compute_Object_Priority (int client_id, const Vector3 &client_pos)
  396. {
  397. //
  398. // Priority depends on physical distance. Objects with no physical location will
  399. // have a priority of 1.
  400. //
  401. CachedPriority = 0;
  402. if (Is_Client_Dirty(client_id)) {
  403. float distance = Get_Object_Distance (client_pos);
  404. if (distance < MaxDistance)
  405. {
  406. //
  407. // This object is visible to this client.
  408. // Add a random perturbation in the range [-distance, distance].
  409. //
  410. float rand_float = ::rand() / (float) RAND_MAX;
  411. float perturbation = rand_float * 2 * distance - distance;
  412. distance += perturbation;
  413. }
  414. //
  415. // Priority simply decreases linearly with distance and is zero at MaxDistance.
  416. //
  417. CachedPriority = 1 - distance / MaxDistance;
  418. CachedPriority = WWMath::Clamp (CachedPriority, 0.0F, 1.0F);
  419. }
  420. return CachedPriority;
  421. }
  422. */
  423. /*
  424. float
  425. NetworkObjectClass::Compute_Object_Priority (int client_id, const Vector3 &client_pos)
  426. {
  427. //
  428. // Compute the priority of this object to the given client at his given position.
  429. // Priority depends on physical distance. Objects with no physical location will
  430. // have a priority of 1.
  431. //
  432. CachedPriority = 0;
  433. if (Is_Client_Dirty(client_id)) {
  434. float distance = Get_Object_Distance (client_pos);
  435. //
  436. // Priority simply decreases linearly with distance and is zero at MaxDistance.
  437. //
  438. CachedPriority = 1 - distance / MaxDistance;
  439. CachedPriority = WWMath::Clamp (CachedPriority, 0.0F, 1.0F);
  440. }
  441. return CachedPriority;
  442. }
  443. */
  444. ////////////////////////////////////////////////////////////////
  445. //
  446. // Set_Cached_Priority
  447. //
  448. ////////////////////////////////////////////////////////////////
  449. void
  450. NetworkObjectClass::Set_Cached_Priority (float priority)
  451. {
  452. WWASSERT(priority >= 0 && priority <= 1);
  453. CachedPriority = priority;
  454. }
  455. /*
  456. ////////////////////////////////////////////////////////////////
  457. //
  458. // Get_Object_Distance
  459. //
  460. ////////////////////////////////////////////////////////////////
  461. float
  462. NetworkObjectClass::Get_Object_Distance (const Vector3 &client_pos)
  463. {
  464. //
  465. // Objects without a physical location will return a distance of zero.
  466. //
  467. float distance = 0;
  468. //
  469. // Get the object's world position (if it has one)
  470. //
  471. Vector3 position;
  472. if (Get_World_Position (position)) {
  473. //
  474. // Simple distance calculation based on the distance
  475. // between points.
  476. //
  477. distance = (position - client_pos).Length ();
  478. }
  479. return distance;
  480. }
  481. */
  482. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  483. //
  484. // Reset_Last_Clientside_Update_Time -- Reset the time this client object last got an update for the server
  485. //
  486. // In: Nothing.
  487. // Out: Nothing
  488. //
  489. // 10/19/2001 12:19PM ST
  490. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  491. void NetworkObjectClass::Reset_Last_Clientside_Update_Time(void)
  492. {
  493. LastClientsideUpdateTime = 0;
  494. ClientsideUpdateFrequencySampleStartTime = TIMEGETTIME();
  495. ClientsideUpdateFrequencySampleCount = 0;
  496. }
  497. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  498. //
  499. // Set_Last_Clientside_Update_Time -- Set the time this client object last got an update for the server
  500. //
  501. // In: Nothing.
  502. // Out: Nothing
  503. //
  504. // 10/19/2001 12:19PM ST
  505. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  506. void NetworkObjectClass::Set_Last_Clientside_Update_Time (ULONG time)
  507. {
  508. LastClientsideUpdateTime = time;
  509. ClientsideUpdateFrequencySampleCount++;
  510. }
  511. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  512. //
  513. // Get_Clientside_Update_Frequency -- Get the updates rate from the server in ms
  514. //
  515. // In: Nothing.
  516. // Out: Average time between updates from the server in ms
  517. //
  518. // 10/19/2001 12:19PM ST
  519. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  520. int NetworkObjectClass::Get_Clientside_Update_Frequency(void)
  521. {
  522. unsigned long time = TIMEGETTIME();
  523. if (time - ClientsideUpdateFrequencySampleStartTime > CLIENT_SIDE_UPDATE_FREQUENCY_SAMPLE_PERIOD) {
  524. // Say 10 seconds if we don't know.
  525. int rate = 10000;
  526. if (ClientsideUpdateFrequencySampleCount) {
  527. rate = (time - ClientsideUpdateFrequencySampleStartTime) / ClientsideUpdateFrequencySampleCount;
  528. ClientsideUpdateFrequencySampleStartTime = time;
  529. ClientsideUpdateFrequencySampleCount = 0;
  530. }
  531. ClientsideUpdateRate = rate;
  532. }
  533. return(ClientsideUpdateRate);
  534. }
  535. #ifdef WWDEBUG
  536. void NetworkObjectClass::Set_Created_By_Packet_ID (int id)
  537. {
  538. CreatedByPacketID = id;
  539. }
  540. #endif //WWDEBUG