STATS.CPP (23371B)
1 // 2 // Copyright 2020 Electronic Arts Inc. 3 // 4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 5 // software: you can redistribute it and/or modify it under the terms of 6 // the GNU General Public License as published by the Free Software Foundation, 7 // either version 3 of the License, or (at your option) any later version. 8 9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 10 // in the hope that it will be useful, but with permitted additional restrictions 11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 12 // distributed with this program. You should have received a copy of the 13 // GNU General Public License along with permitted additional restrictions 14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection 15 16 17 /*********************************************************************************************** 18 *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** 19 *********************************************************************************************** 20 * * 21 * Project Name : Command & Conquer * 22 * * 23 * File Name : WINSTUB.CPP * 24 * * 25 * Programmer : Steve Tall * 26 * * 27 * Start Date : 05/29/1996 * 28 * * 29 * Last Update : May 29th 1996 [ST] * 30 * * 31 *---------------------------------------------------------------------------------------------* 32 * Overview: * 33 * Internet game statistics to collect and upload to the server * 34 * * 35 * * 36 *---------------------------------------------------------------------------------------------* 37 * * 38 * Functions: * 39 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 40 41 #include "function.h" 42 #include "tcpip.h" 43 #include "packet.h" 44 #include "ccdde.h" 45 46 #define FIELD_PACKET_TYPE "TYPE" 47 #define FIELD_GAME_ID "IDNO" 48 #define FIELD_START_CREDITS "CRED" 49 #define FIELD_BASES "BASE" 50 #define FIELD_TIBERIUM "TIBR" 51 #define FIELD_CRATES "CRAT" 52 #define FIELD_AI_PLAYERS "AIPL" 53 #define FIELD_CAPTURE_THE_FLAG "FLAG" 54 #define FIELD_START_UNIT_COUNT "UNIT" 55 #define FIELD_TECH_LEVEL "TECH" 56 #define FIELD_SCENARIO "SCEN" 57 #define FIELD_COMPLETION "CMPL" 58 #define FIELD_START_TIME "TIME" 59 #define FIELD_GAME_DURATION "DURA" 60 #define FIELD_FRAME_RATE "AFPS" 61 #define FIELD_SPEED_SETTING "SPED" 62 #define FIELD_GAME_VERSION "VERS" 63 #define FIELD_GAME_BUILD_DATE "DATE" 64 #define FIELD_COVERT_PRESENT "COVT" 65 #define FIELD_CPU_TYPE "PROC" 66 #define FIELD_MEMORY "MEMO" 67 #define FIELD_VIDEO_MEMORY "VIDM" 68 #define FIELD_PLAYER1_HANDLE "NAM1" 69 #define FIELD_PLAYER2_HANDLE "NAM2" 70 #define FIELD_PLAYER1_TEAM "SID1" 71 #define FIELD_PLAYER2_TEAM "SID2" 72 #define FIELD_PLAYER1_COLOR "COL1" 73 #define FIELD_PLAYER2_COLOR "COL2" 74 #define FIELD_PLAYER1_CREDITS "CRD1" 75 #define FIELD_PLAYER2_CREDITS "CRD2" 76 77 #define FIELD_PLAYER1_UNITS_LEFT "UNL1" 78 #define FIELD_PLAYER2_UNITS_LEFT "UNL2" 79 #define FIELD_PLAYER1_INFANTRY_LEFT "INL1" 80 #define FIELD_PLAYER2_INFANTRY_LEFT "INL2" 81 #define FIELD_PLAYER1_PLANES_LEFT "PLL1" 82 #define FIELD_PLAYER2_PLANES_LEFT "PLL2" 83 #define FIELD_PLAYER1_BUILDINGS_LEFT "BLL1" 84 #define FIELD_PLAYER2_BUILDINGS_LEFT "BLL2" 85 86 #define FIELD_PLAYER1_UNITS_BOUGHT "UNB1" 87 #define FIELD_PLAYER2_UNITS_BOUGHT "UNB2" 88 #define FIELD_PLAYER1_INFANTRY_BOUGHT "INB1" 89 #define FIELD_PLAYER2_INFANTRY_BOUGHT "INB2" 90 #define FIELD_PLAYER1_PLANES_BOUGHT "PLB1" 91 #define FIELD_PLAYER2_PLANES_BOUGHT "PLB2" 92 #define FIELD_PLAYER1_BUILDINGS_BOUGHT "BLB1" 93 #define FIELD_PLAYER2_BUILDINGS_BOUGHT "BLB2" 94 95 #define FIELD_PLAYER1_UNITS_KILLED "UNK1" 96 #define FIELD_PLAYER2_UNITS_KILLED "UNK2" 97 #define FIELD_PLAYER1_INFANTRY_KILLED "INK1" 98 #define FIELD_PLAYER2_INFANTRY_KILLED "INK2" 99 #define FIELD_PLAYER1_PLANES_KILLED "PLK1" 100 #define FIELD_PLAYER2_PLANES_KILLED "PLK2" 101 #define FIELD_PLAYER1_BUILDINGS_KILLED "BLK1" 102 #define FIELD_PLAYER2_BUILDINGS_KILLED "BLK2" 103 104 #define FIELD_PLAYER1_BUILDINGS_CAPTURED "BLC1" 105 #define FIELD_PLAYER2_BUILDINGS_CAPTURED "BLC2" 106 107 #define FIELD_PLAYER1_CRATES_FOUND "CRA1" 108 #define FIELD_PLAYER2_CRATES_FOUND "CRA2" 109 #define FIELD_PLAYER1_HARVESTED "HRV1" 110 #define FIELD_PLAYER2_HARVESTED "HRV2" 111 112 113 #define PACKET_TYPE_HOST_GAME_INFO (unsigned char) 50 114 #define PACKET_TYPE_GUEST_GAME_INFO (unsigned char) 51 115 116 enum { 117 COMPLETION_CONNECTION_LOST, 118 COMPLETION_PLAYER_1_WON, 119 COMPLETION_PLAYER_1_WON_BY_RESIGNATION, 120 COMPLETION_PLAYER_1_WON_BY_DISCONNECTION, 121 COMPLETION_PLAYER_2_WON, 122 COMPLETION_PLAYER_2_WON_BY_RESIGNATION, 123 COMPLETION_PLAYER_2_WON_BY_DISCONNECTION 124 }; 125 126 127 extern unsigned long PlanetWestwoodGameID; 128 extern HINSTANCE ProgramInstance; 129 extern unsigned long PlanetWestwoodStartTime; 130 131 extern "C" char CPUType; 132 133 134 bool GameTimerInUse = false; 135 TimerClass GameTimer; 136 long GameEndTime; 137 void *PacketLater = NULL; 138 139 /*********************************************************************************************** 140 * Send_Statistics_To_Server -- sends internet game statistics to the Westeood server * 141 * * 142 * * 143 * * 144 * INPUT: Nothing * 145 * * 146 * OUTPUT: Nothing * 147 * * 148 * WARNINGS: None * 149 * * 150 * HISTORY: * 151 * 5/29/96 12:38PM ST : Created * 152 *=============================================================================================*/ 153 154 void Send_Statistics_Packet(void) 155 { 156 //PG_TO_FIX 157 #if (0) 158 #ifndef DEMO 159 160 PacketClass stats; 161 HouseClass *player; 162 static int packet_size; 163 int index; 164 bool packet_later = false; // Should the packet be sent later 165 void *packet; 166 167 static char field_player_handle[5] = { "NAM?" }; 168 static char field_player_team[5] = { "SID?" }; 169 static char field_player_color[5] = { "COL?" }; 170 static char field_player_credits[5] = { "CRD?" }; 171 static char field_player_units_left[5] = { "UNL?" }; 172 static char field_player_infantry_left[5] = { "INL?" }; 173 static char field_player_planes_left[5] = { "PLL?" }; 174 static char field_player_buildings_left[5] = { "BLL?" }; 175 static char field_player_units_bought[5] = { "UNB?" }; 176 static char field_player_infantry_bought[5] = { "INB?" }; 177 static char field_player_planes_bought[5] = { "PLB?" }; 178 static char field_player_buildings_bought[5] = { "BLB?" }; 179 static char field_player_units_killed[5] = { "UNK?" }; 180 static char field_player_infantry_killed[5] = { "INK?" }; 181 static char field_player_planes_killed[5] = { "PLK?" }; 182 static char field_player_buildings_killed[5] = { "BLK?" }; 183 static char field_player_buildings_captured[5] = { "BLC?" }; 184 static char field_player_crates_found[5] = { "CRA?" }; 185 static char field_player_harvested[5] = { "HRV?" }; 186 187 static char *houses[] = { 188 "GDI", 189 "NOD", 190 "NUT", 191 "JUR", 192 "M01", 193 "M02", 194 "M03", 195 "M04", 196 "M05", 197 "M06" 198 }; 199 200 CCDebugString ("C&C95 - In Send_Statistics_Packet.\n"); 201 202 203 if (!PacketLater){ 204 205 CCDebugString ("C&C95 - PacketLater is false.\n"); 206 207 208 /* 209 ** Field to identify this as C&C 95 internet game statistics packet 210 */ 211 if (Server){ 212 stats.Add_Field(FIELD_PACKET_TYPE, PACKET_TYPE_HOST_GAME_INFO); 213 }else{ 214 stats.Add_Field(FIELD_PACKET_TYPE, PACKET_TYPE_GUEST_GAME_INFO); 215 } 216 217 /* 218 ** Game ID. A unique game identifier assigned by WChat. 219 */ 220 stats.Add_Field(FIELD_GAME_ID, PlanetWestwoodGameID); 221 222 /* 223 ** Start credits. 224 */ 225 stats.Add_Field(FIELD_START_CREDITS, (unsigned long)MPlayerCredits); 226 227 /* 228 ** Bases (On/Off) 229 */ 230 stats.Add_Field(FIELD_BASES, MPlayerBases ? "ON" : "OFF"); 231 232 /* 233 ** Tiberium (On/Off) 234 */ 235 stats.Add_Field(FIELD_TIBERIUM, MPlayerTiberium ? "ON" : "OFF"); 236 237 /* 238 ** Crates (On/Off) 239 */ 240 stats.Add_Field(FIELD_CRATES, MPlayerGoodies ? "ON" : "OFF"); 241 242 /* 243 ** AI Players (On/Off/Capture the flag) 244 */ 245 stats.Add_Field(FIELD_AI_PLAYERS, MPlayerGhosts ? "ON" : "OFF"); 246 stats.Add_Field(FIELD_CAPTURE_THE_FLAG, Special.IsCaptureTheFlag ? "ON" : "OFF"); 247 248 /* 249 ** Start unit count 250 */ 251 stats.Add_Field(FIELD_START_UNIT_COUNT, (unsigned long)MPlayerUnitCount); 252 253 /* 254 ** Tech level. 255 */ 256 stats.Add_Field(FIELD_TECH_LEVEL, (unsigned long)BuildLevel); 257 258 CCDebugString ("C&C95 - Adding stats field for scenario.\n"); 259 /* 260 ** Scenario 261 */ 262 char fname[128]; 263 char namebuffer[40]; 264 char *abuffer = (char *)_ShapeBuffer; 265 memset(abuffer, '\0', _ShapeBufferSize); 266 sprintf(fname,"%s.INI",ScenarioName); 267 CCFileClass fileo; 268 fileo.Set_Name (fname); 269 fileo.Read(abuffer, _ShapeBufferSize-1); 270 fileo.Close(); 271 WWGetPrivateProfileString("Basic", "Name", "Nulls-Ville", namebuffer, 40, abuffer); 272 stats.Add_Field(FIELD_SCENARIO, namebuffer); 273 //stats.Add_Field(FIELD_SCENARIO, MPlayerScenarios[ScenarioIdx]); 274 275 276 /* 277 ** Game completion status. 278 ** 279 ** Connection lost. 280 ** Player 1 won 281 ** Player 2 won 282 ** Player 1 won by resignation 283 ** Player 2 won by resignation 284 ** Player 1 aborted 285 ** Player 2 aborted 286 ** 287 */ 288 CCDebugString ("C&C95 - Adding stats field for completion status.\n"); 289 HouseClass *player1 = HouseClass::As_Pointer(MPlayerHouses[0]); 290 HouseClass *player2 = HouseClass::As_Pointer(MPlayerHouses[1]); 291 292 int completion = -1; 293 294 if (ConnectionLost){ 295 completion = COMPLETION_CONNECTION_LOST; 296 CCDebugString ("C&C95 - Completion status is connection lost.\n"); 297 }else{ 298 299 if (player1 && player2){ 300 if (player1->IGaveUp){ 301 completion = COMPLETION_PLAYER_2_WON_BY_DISCONNECTION; 302 CCDebugString ("C&C95 - Completion status is player 1 disconnected.\n"); 303 } 304 305 if (player2->IGaveUp){ 306 completion = COMPLETION_PLAYER_1_WON_BY_DISCONNECTION; 307 CCDebugString ("C&C95 - Completion status is player 2 disconnected.\n"); 308 } 309 310 311 if (player2->IsDefeated){ 312 /* 313 ** Player 1 won. Find out how. 314 */ 315 completion = COMPLETION_PLAYER_1_WON; 316 if (player2->Resigned){ 317 completion = COMPLETION_PLAYER_1_WON_BY_RESIGNATION; 318 CCDebugString ("C&C95 - Completion status is player 2 resigned.\n"); 319 }else{ 320 if (player2->IGaveUp){ 321 completion = COMPLETION_PLAYER_1_WON_BY_DISCONNECTION; 322 CCDebugString ("C&C95 - Completion status is player 2 disconnected.\n"); 323 } 324 } 325 326 327 }else{ 328 329 if (player1->IsDefeated){ 330 /* 331 ** Player 2 won. Find out how. 332 */ 333 completion = COMPLETION_PLAYER_2_WON; 334 if (player1->Resigned){ 335 completion = COMPLETION_PLAYER_2_WON_BY_RESIGNATION; 336 CCDebugString ("C&C95 - Completion status is player 1 resigned.\n"); 337 }else{ 338 if (player1->IGaveUp){ 339 completion = COMPLETION_PLAYER_2_WON_BY_DISCONNECTION; 340 CCDebugString ("C&C95 - Completion status is player 1 disconnected.\n"); 341 } 342 } 343 } 344 } 345 } 346 } 347 348 stats.Add_Field (FIELD_COMPLETION, (char) completion); 349 350 351 352 353 354 355 /* 356 ** Game start time (GMT or Pacific?) 357 ** 358 ** Passed from WChat 359 */ 360 stats.Add_Field (FIELD_START_TIME, (long) PlanetWestwoodStartTime); 361 362 /* 363 ** Game duration (seconds). 364 */ 365 stats.Add_Field (FIELD_GAME_DURATION, (long) GameEndTime/60); 366 367 /* 368 ** Avg. frame rate. 369 */ 370 if (GameEndTime/60 == 0){ 371 stats.Add_Field (FIELD_FRAME_RATE, 0L ); 372 }else{ 373 stats.Add_Field (FIELD_FRAME_RATE, (long) Frame / (GameEndTime/60) ); 374 } 375 376 377 CCDebugString ("C&C95 - Adding hardware info stats.\n"); 378 /* 379 ** CPU type 380 */ 381 stats.Add_Field (FIELD_CPU_TYPE, (char)CPUType); 382 383 /* 384 ** Memory 385 */ 386 MEMORYSTATUS mem_info; 387 mem_info.dwLength=sizeof(mem_info); 388 GlobalMemoryStatus(&mem_info); 389 stats.Add_Field (FIELD_MEMORY, (long)mem_info.dwTotalPhys); 390 391 /* 392 ** Video memory 393 */ 394 DDCAPS video_capabilities; 395 long video_memory; 396 397 if (DirectDrawObject){ 398 video_capabilities.dwSize = sizeof (video_capabilities); 399 if (DD_OK == DirectDrawObject->GetCaps (&video_capabilities , NULL)){ 400 video_memory = video_capabilities.dwVidMemTotal; 401 video_memory += 1024*1024 -1; 402 video_memory &= 0xfff00000; 403 stats.Add_Field (FIELD_VIDEO_MEMORY, (long) video_memory); 404 } 405 } 406 407 CCDebugString ("C&C95 - Adding game info stats.\n"); 408 /* 409 ** Game speed setting. 410 */ 411 stats.Add_Field (FIELD_SPEED_SETTING, (char)Options.GameSpeed); 412 413 /* 414 ** C&C 95 version/build date 415 */ 416 char version[128]; 417 sprintf (version, "%d%s", Version_Number(), VersionText); 418 stats.Add_Field (FIELD_GAME_VERSION, version); 419 420 char path_to_exe[280]; 421 FILETIME write_time; //File time is 64 bits 422 423 GetModuleFileName (ProgramInstance, path_to_exe, 280); 424 RawFileClass file; 425 file.Set_Name(path_to_exe); 426 file.Open(); 427 HANDLE handle = file.Get_File_Handle(); 428 429 if (handle != INVALID_HANDLE_VALUE){ 430 if (GetFileTime (handle, NULL, NULL, &write_time)){ 431 write_time.dwLowDateTime = htonl (write_time.dwLowDateTime); 432 write_time.dwHighDateTime = htonl (write_time.dwHighDateTime); 433 stats.Add_Field (FIELD_GAME_BUILD_DATE, (void*)&write_time, sizeof (write_time)); 434 } 435 } 436 437 /* 438 ** Covert installed? (Yes/No) 439 */ 440 stats.Add_Field(FIELD_COVERT_PRESENT, (char) Expansion_Present()); 441 442 CCDebugString ("C&C95 - Adding house specific stats.\n"); 443 /* 444 ** Build the player specific statistics 445 ** 446 */ 447 for (int house = 0 ; house < 2 ; house++){ 448 449 player = HouseClass::As_Pointer(MPlayerHouses[house]); 450 451 if (player){ 452 /* 453 ** Player handle. 454 */ 455 field_player_handle[3] = '1' + (char)house; 456 stats.Add_Field (field_player_handle, (char*) MPlayerNames[house]); 457 458 /* 459 ** Player team. (NOD or GDI) 460 */ 461 field_player_team[3] = '1' + (char)house; 462 stats.Add_Field (field_player_team, houses[player->ActLike]); 463 464 /* 465 ** Player color 466 */ 467 field_player_color[3] = '1' + (char)house; 468 stats.Add_Field (field_player_color, (unsigned char) (player->Class->House - HOUSE_MULTI1)); 469 470 /* 471 ** Player end credits. 472 */ 473 field_player_credits[3] = '1' + (char)house; 474 stats.Add_Field (field_player_credits, player->Credits + player->Tiberium); 475 476 /* 477 ** Number of each unit/building type built 478 */ 479 field_player_infantry_bought[3] = '1' + (char)house; 480 field_player_units_bought[3] = '1' + (char)house; 481 field_player_planes_bought[3] = '1' + (char)house; 482 field_player_buildings_bought[3] = '1' + (char)house; 483 484 player->InfantryTotals->To_Network_Format(); 485 player->UnitTotals->To_Network_Format(); 486 player->AircraftTotals->To_Network_Format(); 487 player->BuildingTotals->To_Network_Format(); 488 489 stats.Add_Field (field_player_infantry_bought, (void*) player->InfantryTotals->Get_All_Totals(), player->InfantryTotals->Get_Unit_Count()*4); 490 stats.Add_Field (field_player_units_bought, (void*) player->UnitTotals->Get_All_Totals(), player->UnitTotals->Get_Unit_Count()*4); 491 stats.Add_Field (field_player_planes_bought, (void*) player->AircraftTotals->Get_All_Totals(), player->AircraftTotals->Get_Unit_Count()*4); 492 stats.Add_Field (field_player_buildings_bought, (void*) player->BuildingTotals->Get_All_Totals(), player->BuildingTotals->Get_Unit_Count()*4); 493 494 player->InfantryTotals->To_PC_Format(); 495 player->UnitTotals->To_PC_Format(); 496 player->AircraftTotals->To_PC_Format(); 497 player->BuildingTotals->To_PC_Format(); 498 499 /* 500 ** Clear out the counts and use the space to count up the current number of units/buildings 501 */ 502 player->InfantryTotals->Clear_Unit_Total(); 503 player->AircraftTotals->Clear_Unit_Total(); 504 player->UnitTotals->Clear_Unit_Total(); 505 player->BuildingTotals->Clear_Unit_Total(); 506 507 /* 508 ** Number of units remaining to player 509 */ 510 for (index = 0; index < Units.Count(); index++) { 511 UnitClass const * unit = Units.Ptr(index); 512 if (unit->House == player){ 513 player->UnitTotals->Increment_Unit_Total (unit->Class->Type); 514 } 515 } 516 517 for (index = 0; index < Infantry.Count(); index++) { 518 InfantryClass const * infantry = Infantry.Ptr(index); 519 if (infantry->House == player && !infantry->Class->IsCivilian){ 520 player->InfantryTotals->Increment_Unit_Total (infantry->Class->Type); 521 } 522 } 523 524 for (index = 0; index < Aircraft.Count(); index++) { 525 AircraftClass const * aircraft = Aircraft.Ptr(index); 526 if (aircraft->House == player && aircraft->Class->Type != AIRCRAFT_CARGO){ 527 player->AircraftTotals->Increment_Unit_Total (aircraft->Class->Type); 528 } 529 } 530 531 for (index = 0; index < Buildings.Count(); index++) { 532 BuildingClass const * building = Buildings.Ptr(index); 533 if (building->House == player){ 534 player->BuildingTotals->Increment_Unit_Total (building->Class->Type); 535 } 536 } 537 538 player->InfantryTotals->To_Network_Format(); 539 player->UnitTotals->To_Network_Format(); 540 player->AircraftTotals->To_Network_Format(); 541 player->BuildingTotals->To_Network_Format(); 542 543 field_player_infantry_left[3] = '1' + (char)house; 544 field_player_units_left[3] = '1' + (char)house; 545 field_player_planes_left[3] = '1' + (char)house; 546 field_player_buildings_left[3] = '1' + (char)house; 547 stats.Add_Field (field_player_infantry_left, (void*) player->InfantryTotals->Get_All_Totals(), player->InfantryTotals->Get_Unit_Count()*4); 548 stats.Add_Field (field_player_units_left, (void*) player->UnitTotals->Get_All_Totals(), player->UnitTotals->Get_Unit_Count()*4); 549 stats.Add_Field (field_player_planes_left, (void*) player->AircraftTotals->Get_All_Totals(), player->AircraftTotals->Get_Unit_Count()*4); 550 stats.Add_Field (field_player_buildings_left, (void*) player->BuildingTotals->Get_All_Totals(), player->BuildingTotals->Get_Unit_Count()*4); 551 552 553 /* 554 ** Number of enemy units/buildings of each type destroyed. 555 */ 556 557 player->DestroyedInfantry->To_Network_Format(); 558 player->DestroyedUnits->To_Network_Format(); 559 player->DestroyedAircraft->To_Network_Format(); 560 player->DestroyedBuildings->To_Network_Format(); 561 562 field_player_infantry_killed[3] = '1' + (char)house; 563 field_player_units_killed[3] = '1' + (char)house; 564 field_player_planes_killed[3] = '1' + (char)house; 565 field_player_buildings_killed[3] = '1' + (char)house; 566 stats.Add_Field (field_player_infantry_killed, (void*) player->DestroyedInfantry->Get_All_Totals(), player->DestroyedInfantry->Get_Unit_Count()*4); 567 stats.Add_Field (field_player_units_killed, (void*) player->DestroyedUnits->Get_All_Totals(), player->DestroyedUnits->Get_Unit_Count()*4); 568 stats.Add_Field (field_player_planes_killed, (void*) player->DestroyedAircraft->Get_All_Totals(), player->DestroyedAircraft->Get_Unit_Count()*4); 569 stats.Add_Field (field_player_buildings_killed, (void*) player->DestroyedBuildings->Get_All_Totals(), player->DestroyedBuildings->Get_Unit_Count()*4); 570 571 572 /* 573 ** Number and type of enemy buildings captured 574 */ 575 field_player_buildings_captured[3] = '1' + (char)house; 576 player->CapturedBuildings->To_Network_Format(); 577 stats.Add_Field (field_player_buildings_captured, (void*) player->CapturedBuildings->Get_All_Totals(), player->CapturedBuildings->Get_Unit_Count()*4); 578 579 /* 580 ** Number of crates discovered and their contents 581 */ 582 field_player_crates_found[3] = '1' + (char)house; 583 player->TotalCrates->To_Network_Format(); 584 stats.Add_Field (field_player_crates_found, (void*) player->TotalCrates->Get_All_Totals(), player->TotalCrates->Get_Unit_Count()*4); 585 586 /* 587 ** Amount of tiberium turned into credits 588 */ 589 field_player_harvested[3] = '1' + (char)house; 590 stats.Add_Field (field_player_harvested, (unsigned long) player->HarvestedCredits); 591 } 592 } 593 594 CCDebugString ("C&C95 - Calling Create_Comms_Packet.\n"); 595 /* 596 ** Create the comms packet to be sent 597 */ 598 packet = stats.Create_Comms_Packet(packet_size); 599 CCDebugString ("C&C95 - Returned from Create_Comms_Packet.\n"); 600 601 /* 602 ** If a player disconnected then dont send the packet at this time - save it for later 603 */ 604 if (completion == COMPLETION_PLAYER_1_WON_BY_DISCONNECTION 605 || completion == COMPLETION_PLAYER_2_WON_BY_DISCONNECTION){ 606 PacketLater = packet; 607 CCDebugString ("C&C95 - Flagging to send the packet later.\n"); 608 return; 609 } 610 611 }else{ //else for if (!PacketLater) 612 613 CCDebugString ("C&C95 - PacketLater is true.\n"); 614 615 /* 616 ** Send the packet we calculated earlier when the disconnect occurred 617 */ 618 packet = PacketLater; 619 PacketLater = NULL; 620 } 621 622 /* 623 ** Send it..... 624 */ 625 int times = 100; //100 times max 626 CountDownTimerClass send_timer; 627 628 CCDebugString ("C&C95 - About to send stats packet to DDE server.\n"); 629 while ( ! Send_Data_To_DDE_Server ((char*)packet, packet_size, DDEServerClass::DDE_PACKET_GAME_RESULTS)){ 630 CCDebugString ("C&C95 - Stats packet send failed.\n"); 631 send_timer.Set (60, true); 632 while (send_timer.Time()){}; 633 } 634 635 636 /* 637 ** Save it to disk as well so I can see it 638 */ 639 #if (0) 640 RawFileClass anotherfile ("packet.net"); 641 anotherfile.Write(packet, packet_size); 642 #endif //(0) 643 /* 644 ** Tidy up 645 */ 646 CCDebugString ("C&C95 - About to delete packet memory.\n"); 647 delete [] packet; 648 649 GameStatisticsPacketSent = true; 650 CCDebugString ("C&C95 - Returning from Send_Statistics_Packet.\n"); 651 #endif //DEMO 652 #endif 653 } 654 655 656 657 658 659 660 661 662 663 void Register_Game_Start_Time(void) 664 { 665 666 GameTimer.Set (0, true); 667 GameTimerInUse = true; 668 } 669 670 671 extern void Register_Game_End_Time(void) 672 { 673 GameEndTime = GameTimer.Time(); 674 GameTimerInUse = false; 675 } 676