| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911 |
- //
- // Copyright 2020 Electronic Arts Inc.
- //
- // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
- // software: you can redistribute it and/or modify it under the terms of
- // the GNU General Public License as published by the Free Software Foundation,
- // either version 3 of the License, or (at your option) any later version.
- // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
- // in the hope that it will be useful, but with permitted additional restrictions
- // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
- // distributed with this program. You should have received a copy of the
- // GNU General Public License along with permitted additional restrictions
- // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
- /***********************************************************************************************
- *** 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 ***
- ***********************************************************************************************
- * *
- * Project Name : Command & Conquer *
- * *
- * File Name : WINSTUB.CPP *
- * *
- * Programmer : Steve Tall *
- * *
- * Start Date : 05/29/1996 *
- * *
- * Last Update : May 29th 1996 [ST] *
- * *
- *---------------------------------------------------------------------------------------------*
- * Overview: *
- * Internet game statistics to collect and upload to the server *
- * *
- * *
- *---------------------------------------------------------------------------------------------*
- * *
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #ifdef WIN32
- #include "function.h"
- #include "tcpip.h"
- #include "packet.h"
- #include "ccdde.h"
- #define FIELD_PACKET_TYPE "TYPE"
- #define FIELD_GAME_ID "IDNO"
- #define FIELD_START_CREDITS "CRED"
- #define FIELD_BASES "BASE"
- #define FIELD_TIBERIUM "TIBR"
- #define FIELD_CRATES "CRAT"
- #define FIELD_AI_PLAYERS "AIPL"
- #define FIELD_CAPTURE_THE_FLAG "FLAG"
- #define FIELD_START_UNIT_COUNT "UNIT"
- #define FIELD_TECH_LEVEL "TECH"
- #define FIELD_SCENARIO "SCEN"
- #define FIELD_COMPLETION "CMPL"
- #define FIELD_START_TIME "TIME"
- #define FIELD_GAME_DURATION "DURA"
- #define FIELD_FRAME_RATE "AFPS"
- #define FIELD_SPEED_SETTING "SPED"
- #define FIELD_GAME_VERSION "VERS"
- #define FIELD_GAME_BUILD_DATE "DATE"
- #define FIELD_COVERT_PRESENT "COVT"
- #define FIELD_CPU_TYPE "PROC"
- #define FIELD_MEMORY "MEMO"
- #define FIELD_VIDEO_MEMORY "VIDM"
- #define FIELD_SHADOW_REGROWS "SHAD"
- #ifdef WOLAPI_INTEGRATION
- #define FIELD_HOSTORNOT "SDFX"
- #define FIELD_TOURNAMENT "TRNY"
- #define FIELD_NUM_INITIAL_PLAYERS "NUMP"
- #define FIELD_NUM_REMAINING_PLAYERS "REMN"
- #define FIELD_DISCONNECT_PINGS "PING"
- #define FIELD_COMPUTERTOOKOVER "QUIT"
- //#define FIELD_HARDWARE_GUID "GUID"
- #define FIELD_PLAYER1_IP "ADR1"
- #define FIELD_PLAYER2_IP "ADR2"
- #endif
- // ajw The following were never used (thank god).
- #define FIELD_PLAYER1_HANDLE "NAM1"
- #define FIELD_PLAYER2_HANDLE "NAM2"
- #define FIELD_PLAYER1_TEAM "SID1"
- #define FIELD_PLAYER2_TEAM "SID2"
- #define FIELD_PLAYER1_COLOR "COL1"
- #define FIELD_PLAYER2_COLOR "COL2"
- #define FIELD_PLAYER1_CREDITS "CRD1"
- #define FIELD_PLAYER2_CREDITS "CRD2"
- #define FIELD_PLAYER1_UNITS_LEFT "UNL1"
- #define FIELD_PLAYER2_UNITS_LEFT "UNL2"
- #define FIELD_PLAYER1_INFANTRY_LEFT "INL1"
- #define FIELD_PLAYER2_INFANTRY_LEFT "INL2"
- #define FIELD_PLAYER1_PLANES_LEFT "PLL1"
- #define FIELD_PLAYER2_PLANES_LEFT "PLL2"
- #define FIELD_PLAYER1_BUILDINGS_LEFT "BLL1"
- #define FIELD_PLAYER2_BUILDINGS_LEFT "BLL2"
- #define FIELD_PLAYER1_VESSELS_LEFT "VSL1"
- #define FIELD_PLAYER2_VESSELS_LEFT "VSL2"
- #define FIELD_PLAYER1_UNITS_BOUGHT "UNB1"
- #define FIELD_PLAYER2_UNITS_BOUGHT "UNB2"
- #define FIELD_PLAYER1_INFANTRY_BOUGHT "INB1"
- #define FIELD_PLAYER2_INFANTRY_BOUGHT "INB2"
- #define FIELD_PLAYER1_PLANES_BOUGHT "PLB1"
- #define FIELD_PLAYER2_PLANES_BOUGHT "PLB2"
- #define FIELD_PLAYER1_BUILDINGS_BOUGHT "BLB1"
- #define FIELD_PLAYER2_BUILDINGS_BOUGHT "BLB2"
- #define FIELD_PLAYER1_VESSELS_BOUGHT "VSB1"
- #define FIELD_PLAYER2_VESSELS_BOUGHT "VSB2"
- #define FIELD_PLAYER1_UNITS_KILLED "UNK1"
- #define FIELD_PLAYER2_UNITS_KILLED "UNK2"
- #define FIELD_PLAYER1_INFANTRY_KILLED "INK1"
- #define FIELD_PLAYER2_INFANTRY_KILLED "INK2"
- #define FIELD_PLAYER1_PLANES_KILLED "PLK1"
- #define FIELD_PLAYER2_PLANES_KILLED "PLK2"
- #define FIELD_PLAYER1_BUILDINGS_KILLED "BLK1"
- #define FIELD_PLAYER2_BUILDINGS_KILLED "BLK2"
- #define FIELD_PLAYER1_VESSELS_KILLED "VSK1"
- #define FIELD_PLAYER2_VESSELS_KILLED "VSK2"
- #define FIELD_PLAYER1_BUILDINGS_CAPTURED "BLC1"
- #define FIELD_PLAYER2_BUILDINGS_CAPTURED "BLC2"
- #define FIELD_PLAYER1_CRATES_FOUND "CRA1"
- #define FIELD_PLAYER2_CRATES_FOUND "CRA2"
- #define FIELD_PLAYER1_HARVESTED "HRV1"
- #define FIELD_PLAYER2_HARVESTED "HRV2"
- #define PACKET_TYPE_HOST_GAME_INFO (unsigned char) 50
- #define PACKET_TYPE_GUEST_GAME_INFO (unsigned char) 51
- // Note: These enums match those in the game results server code.
- enum {
- COMPLETION_CONNECTION_LOST,
- COMPLETION_PLAYER_1_WON,
- COMPLETION_PLAYER_1_WON_BY_RESIGNATION,
- COMPLETION_PLAYER_1_WON_BY_DISCONNECTION,
- COMPLETION_PLAYER_2_WON,
- COMPLETION_PLAYER_2_WON_BY_RESIGNATION,
- COMPLETION_PLAYER_2_WON_BY_DISCONNECTION,
- #ifdef FIXIT_VERSION_3 // Stalemate games.
- COMPLETION_WASH = 64,
- #endif
- };
- extern unsigned long PlanetWestwoodGameID;
- extern HINSTANCE ProgramInstance;
- extern unsigned long PlanetWestwoodStartTime;
- extern "C" char CPUType;
- bool GameTimerInUse = false;
- TimerClass GameTimer;
- long GameEndTime;
- void *PacketLater = NULL;
- //#include "WolDebug.h"
- #ifdef WOLAPI_INTEGRATION
- #include "WolapiOb.h"
- extern WolapiObject* pWolapi;
- extern bool bReconnectDialogCancelled;
- #endif
- /***********************************************************************************************
- * Send_Statistics_To_Server -- sends internet game statistics to the Westeood server *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 5/29/96 12:38PM ST : Created *
- *=============================================================================================*/
- void Send_Statistics_Packet(void)
- {
- #if (0)//PG
- // debugprint( "Stats: Send_Statistics_Packet() called.\n" );
- #ifndef INTERNET_OFF // Denzil 5/4/98
- #ifdef WOLAPI_INTEGRATION
- if( !pWolapi ) // Should no longer ever happen.
- return;
- #endif
- PacketClass stats;
- HouseClass *player;
- static int packet_size;
- int index;
- bool packet_later = false; // Should the packet be sent later
- void *packet;
- static char field_player_handle[5] = { "NAM?" };
- static char field_player_team[5] = { "SID?" };
- static char field_player_color[5] = { "COL?" };
- static char field_player_credits[5] = { "CRD?" };
- static char field_player_units_left[5] = { "UNL?" };
- static char field_player_infantry_left[5] = { "INL?" };
- static char field_player_planes_left[5] = { "PLL?" };
- static char field_player_buildings_left[5] = { "BLL?" };
- static char field_player_vessels_left[5] = { "VSL?" };
- static char field_player_units_bought[5] = { "UNB?" };
- static char field_player_infantry_bought[5] = { "INB?" };
- static char field_player_planes_bought[5] = { "PLB?" };
- static char field_player_buildings_bought[5] = { "BLB?" };
- static char field_player_vessels_bought[5] = { "VSB?" };
- static char field_player_units_killed[5] = { "UNK?" };
- static char field_player_infantry_killed[5] = { "INK?" };
- static char field_player_planes_killed[5] = { "PLK?" };
- static char field_player_buildings_killed[5] = { "BLK?" };
- static char field_player_vessels_killed[5] = { "VSK?" };
- static char field_player_buildings_captured[5] = { "BLC?" };
- static char field_player_crates_found[5] = { "CRA?" };
- static char field_player_harvested[5] = { "HRV?" };
- static char *houses[] = {
- "SPA",
- "GRE",
- "USS",
- "ENG",
- "ITA",
- "GER",
- "FRA",
- "TKY",
- "GUD",
- "BAD",
- "CIV",
- "JP ",
- "M01",
- "M02",
- "M03",
- "M04",
- "M05",
- "M06",
- "M07",
- "M08"
- };
- if (!PacketLater){
- /*
- ** Field to identify this as C&C 95 internet game statistics packet
- */
- #ifdef WOLAPI_INTEGRATION
- if( pWolapi->bGameServer )
- {
- stats.Add_Field( FIELD_HOSTORNOT, (unsigned char)0 ); // Reversed meaning of this for Neal.
- }else{
- stats.Add_Field( FIELD_HOSTORNOT, (unsigned char)1 );
- }
- #else
- if (Server){
- stats.Add_Field(FIELD_PACKET_TYPE, PACKET_TYPE_HOST_GAME_INFO);
- }else{
- stats.Add_Field(FIELD_PACKET_TYPE, PACKET_TYPE_GUEST_GAME_INFO);
- }
- #endif
- /*
- ** Game ID. A unique game identifier assigned by WChat.
- */
- stats.Add_Field(FIELD_GAME_ID, PlanetWestwoodGameID);
- #ifdef WOLAPI_INTEGRATION
- // Number of players initially in game.
- stats.Add_Field( FIELD_NUM_INITIAL_PLAYERS, (unsigned long)pWolapi->GameInfoCurrent.iPlayerCount );
- //debugprint( "Stats: number of initial players is %i\n", pWolapi->GameInfoCurrent.iPlayerCount );
- // Number of players remaining in game. Not sure of what use this will be statistically...
- stats.Add_Field( FIELD_NUM_REMAINING_PLAYERS, (unsigned long)Session.Players.Count() );
- //debugprint( "Stats: number of remaining players is %i\n", Session.Players.Count() );
- // Whether or not this was a tournament game.
- stats.Add_Field( FIELD_TOURNAMENT, (unsigned char)( pWolapi->GameInfoCurrent.bTournament ? 1 : 0 ) );
- // ajw This is now in WOLAPI...
- // // A unique value that identifies the machine that the game was played on.
- // HW_PROFILE_INFO hwinfo;
- // ::GetCurrentHwProfile( &hwinfo );
- // stats.Add_Field( FIELD_HARDWARE_GUID, hwinfo.szHwProfileGuid );
- #endif
- /*
- ** Start credits.
- */
- stats.Add_Field(FIELD_START_CREDITS, (unsigned long)Session.Options.Credits);
- /*
- ** Bases (On/Off)
- */
- stats.Add_Field(FIELD_BASES, Session.Options.Bases ? "ON" : "OFF");
- /*
- ** Tiberium (On/Off)
- */
- stats.Add_Field(FIELD_TIBERIUM, Session.Options.Tiberium ? "ON" : "OFF");
- /*
- ** Crates (On/Off)
- */
- stats.Add_Field(FIELD_CRATES, Session.Options.Goodies ? "ON" : "OFF");
- /*
- ** AI Players (On/Off)
- */
- stats.Add_Field(FIELD_AI_PLAYERS, (unsigned long) Session.Options.AIPlayers);
- /*
- ** Shadow regrowth enabled
- */
- stats.Add_Field(FIELD_SHADOW_REGROWS, Special.IsShadowGrow ? "ON" : "OFF" );
- /*
- ** Capture the flag mode (On/Off)
- */
- stats.Add_Field(FIELD_CAPTURE_THE_FLAG, Special.IsCaptureTheFlag ? "ON" : "OFF");
- /*
- ** Start unit count
- */
- stats.Add_Field(FIELD_START_UNIT_COUNT, (unsigned long)Session.Options.UnitCount);
- /*
- ** Tech level.
- */
- stats.Add_Field(FIELD_TECH_LEVEL, (unsigned long)BuildLevel);
- /*
- ** Scenario
- */
- #if (1)
- stats.Add_Field(FIELD_SCENARIO, Session.Options.ScenarioDescription);
- #else //(1)
- char fname[128];
- char namebuffer[40];
- char *abuffer = (char *)_ShapeBuffer;
- memset(abuffer, '\0', _ShapeBufferSize);
- sprintf(fname,"%s.INI",Scen.ScenarioName);
- CCFileClass fileo;
- fileo.Set_Name (fname);
- fileo.Read(abuffer, _ShapeBufferSize-1);
- fileo.Close();
- WWGetPrivateProfileString("Basic", "Name", "Nulls-Ville", namebuffer, 40, abuffer);
- stats.Add_Field(FIELD_SCENARIO, namebuffer);
- //stats.Add_Field(FIELD_SCENARIO, MPlayerScenarios[ScenarioIdx]);
- #endif //(1)
- #ifdef WOLAPI_INTEGRATION
- // Completion status is set for Tournament games only - ajw.
- if( pWolapi->GameInfoCurrent.bTournament )
- {
- #endif
- /*
- ** Game completion status.
- **
- ** Connection lost.
- ** Player 1 won
- ** Player 2 won
- ** Player 1 won by resignation
- ** Player 2 won by resignation
- ** Player 1 aborted
- ** Player 2 aborted
- **
- ** Game was a draw
- */
- HouseClass *player1 = NULL;
- HouseClass *player2 = NULL;
- for (int h=0 ; h<Session.Players.Count(); h++){
- HouseClass *ptr = HouseClass::As_Pointer ((HousesType)(h + HOUSE_MULTI1));
- if (ptr->IsHuman){
- if (player1){
- player2 = ptr;
- break;
- }else{
- player1 = ptr;
- }
- }
- }
- int completion = -1;
- if (player1 && player2){ // Can this ever fail? ajw
- #ifdef FIXIT_VERSION_3
- // Send IP addresses of both players.
- NetNumType net;
- NetNodeType node;
- char szIPAddress[ 30 ];
- Session.Players[ 0 ]->Address.Get_Address( net, node );
- sprintf( szIPAddress, "%i.%i.%i.%i", node[0], node[1], node[2], node[3] );
- if( strcmp( szIPAddress, "255.255.255.255" ) == 0 )
- {
- // Ok. It's not set. Let's try to get it ourselves...
- char szHostName[ 512 ];
- int iRes = gethostname( szHostName, 512 );
- if( iRes != SOCKET_ERROR ) // else forget about trying
- {
- // debugprint( "gethostname got me %s\n", szHostName );
- struct hostent* pHostent = gethostbyname( szHostName );
- if( pHostent ) // else forget about trying
- {
- int i = 0;
- int* piAddress = (int*)pHostent->h_addr_list[ i ];
- while( piAddress )
- {
- // There is a non-null value for this h_addr_list entry.
- char szAsciiIP[ 30 ];
- strcpy( szAsciiIP, inet_ntoa( *( (struct in_addr*)piAddress ) ) );
- // We have an address in the right form.
- // Now, is it an address in a private network? If so we should ignore it.
- unsigned char q1 = ( (char*)piAddress )[ 0 ]; // First digit.
- unsigned char q2 = ( (char*)piAddress )[ 1 ]; // Second digit.
- // debugprint( "ip: %s\n", szAsciiIP );
- if( q1 == 10 || ( q1 == 172 && ( q2 >= 16 && q2 <= 31 ) ) || ( q1 == 192 && q2 == 168 ) )
- {
- // This is a private network address - ignore it and go on to next.
- }
- else
- {
- strcpy( szIPAddress, szAsciiIP );
- break;
- }
- piAddress = (int*)pHostent->h_addr_list[ ++i ];
- }
- }
- // else
- // debugprint( "gethostbyname failed. Error %i\n", WSAGetLastError() );
- }
- // else
- // debugprint( "gethostname failed with %i, error %i\n", iRes, WSAGetLastError() );
- }
- stats.Add_Field( FIELD_PLAYER1_IP, (char*)szIPAddress );
- Session.Players[ 1 ]->Address.Get_Address( net, node );
- sprintf( szIPAddress, "%i.%i.%i.%i", node[0], node[1], node[2], node[3] );
- stats.Add_Field( FIELD_PLAYER2_IP, (char*)szIPAddress );
- #endif
- #ifdef FIXIT_VERSION_3 // Stalemate games.
- if( Scen.bLocalProposesDraw && Scen.bOtherProposesDraw )
- {
- completion = COMPLETION_WASH;
- }
- else
- {
- #endif
- if (ConnectionLost){
- #ifdef WOLAPI_INTEGRATION
- if( bReconnectDialogCancelled )
- {
- if( Session.Players[ 0 ]->Player.ID == HOUSE_MULTI1 )
- // I am player1.
- completion = COMPLETION_PLAYER_2_WON_BY_DISCONNECTION;
- else
- completion = COMPLETION_PLAYER_1_WON_BY_DISCONNECTION;
- }
- else
- {
- completion = COMPLETION_CONNECTION_LOST;
- if( pWolapi->bDisconnectPingingCompleted )
- {
- char szPingResult[ 8 ]; // Format is "x/y a/b", e.g., "3/5 4/5"
- pWolapi->DisconnectPingResultsString( szPingResult );
- stats.Add_Field( FIELD_DISCONNECT_PINGS, (char*)szPingResult );
- }
- // else
- // debugprint( "Stats: bDisconnectPingingCompleted is false! Should be finished!!!!!!!!!!!!!!!\n" );
- }
- #else
- completion = COMPLETION_CONNECTION_LOST;
- #endif
- }else{
- if (player1->IsGiverUpper){
- completion = COMPLETION_PLAYER_2_WON_BY_DISCONNECTION;
- }
- if (player2->IsGiverUpper){
- completion = COMPLETION_PLAYER_1_WON_BY_DISCONNECTION;
- }
- if (player2->IsDefeated){
- /*
- ** Player 1 won. Find out how.
- */
- completion = COMPLETION_PLAYER_1_WON;
- if (player2->IsResigner){
- completion = COMPLETION_PLAYER_1_WON_BY_RESIGNATION;
- }else{
- if (player2->IsGiverUpper){
- completion = COMPLETION_PLAYER_1_WON_BY_DISCONNECTION;
- }
- }
- }else{
- if (player1->IsDefeated){
- /*
- ** Player 2 won. Find out how.
- */
- completion = COMPLETION_PLAYER_2_WON;
- if (player1->IsResigner){
- completion = COMPLETION_PLAYER_2_WON_BY_RESIGNATION;
- }else{
- if (player1->IsGiverUpper){
- completion = COMPLETION_PLAYER_2_WON_BY_DISCONNECTION;
- }
- }
- }
- }
- }
- #ifdef FIXIT_VERSION_3 // Stalemate games.
- }
- #endif
- }
- stats.Add_Field (FIELD_COMPLETION, (char) completion);
- //debugprint( "Stats: Tournament game completion value: %i\n", completion );
- #ifdef WOLAPI_INTEGRATION
- }
- #endif
- /*
- ** Game start time (GMT or Pacific?)
- **
- ** Passed from WChat
- */
- stats.Add_Field (FIELD_START_TIME, (long) PlanetWestwoodStartTime);
- /*
- ** Game duration (seconds).
- */
- stats.Add_Field (FIELD_GAME_DURATION, (long) GameEndTime/60);
- /*
- ** Avg. frame rate.
- */
- #ifdef FIXIT_IP_CRASH
- long divisor = GameEndTime / 60;
- if (divisor != 0) {
- stats.Add_Field (FIELD_FRAME_RATE, (long) Frame / (GameEndTime/60) );
- } else {
- stats.Add_Field (FIELD_FRAME_RATE, 0l);
- }
- #else
- stats.Add_Field (FIELD_FRAME_RATE, (long) Frame / (GameEndTime/60) );
- #endif
- /*
- ** CPU type
- */
- stats.Add_Field (FIELD_CPU_TYPE, (char)CPUType);
- /*
- ** Memory
- */
- MEMORYSTATUS mem_info;
- mem_info.dwLength=sizeof(mem_info);
- GlobalMemoryStatus(&mem_info);
- stats.Add_Field (FIELD_MEMORY, (long)mem_info.dwTotalPhys);
- /*
- ** Video memory
- */
- DDCAPS video_capabilities;
- long video_memory;
- if (DirectDrawObject){
- video_capabilities.dwSize = sizeof (video_capabilities);
- if (DD_OK == DirectDrawObject->GetCaps (&video_capabilities , NULL)){
- video_memory = video_capabilities.dwVidMemTotal;
- video_memory += 1024*1024 -1;
- video_memory &= 0xfff00000;
- stats.Add_Field (FIELD_VIDEO_MEMORY, (long) video_memory);
- }
- }
- /*
- ** Game speed setting.
- */
- stats.Add_Field (FIELD_SPEED_SETTING, (char)Options.GameSpeed);
- /*
- ** Red Alert version/build date
- */
- char version[128];
- sprintf (version, "V%s", VerNum.Version_Name() );
- stats.Add_Field (FIELD_GAME_VERSION, (char*)version);
- char path_to_exe[280];
- FILETIME write_time; //File time is 64 bits
- GetModuleFileName (ProgramInstance, path_to_exe, 280);
- RawFileClass file;
- file.Set_Name(path_to_exe);
- file.Open();
- HANDLE handle = file.Get_File_Handle();
- if (handle != INVALID_HANDLE_VALUE){
- if (GetFileTime (handle, NULL, NULL, &write_time)){
- write_time.dwLowDateTime = htonl (write_time.dwLowDateTime);
- write_time.dwHighDateTime = htonl (write_time.dwHighDateTime);
- stats.Add_Field (FIELD_GAME_BUILD_DATE, (void*)&write_time, sizeof (write_time));
- }
- }
- /*
- ** Covert installed? (Yes/No)
- */
- //stats.Add_Field(FIELD_COVERT_PRESENT, (char) Expansion_Present());
- /*
- ** Build the player specific statistics
- **
- */
- #ifdef WOLAPI_INTEGRATION
- for (int house = 0 ; house < 8 ; house++){
- #else
- for (int house = 0 ; house < 2 ; house++){
- #endif
- player = HouseClass::As_Pointer((HousesType) (house + HOUSE_MULTI1));
- #ifdef WOLAPI_INTEGRATION
- if( !player )
- continue;
- #endif
- /*
- ** Player handle.
- */
- field_player_handle[3] = '1' + (char)house;
- #ifdef WOLAPI_INTEGRATION
- stats.Add_Field (field_player_handle, (char*) player->InitialName);
- //debugprint( "Stats: Player %i name %s\n", house, (char*) player->InitialName );
- //debugprint( "Stats: Player %i ending name %s\n", house, (char*) player->IniName );
- #else
- stats.Add_Field (field_player_handle, (char*) player->IniName);
- #endif
- #ifdef WOLAPI_INTEGRATION
- // Whether or not this player was taken over by the computer, due to his quitting the game.
- if( strcmp( player->IniName, player->InitialName ) )
- stats.Add_Field( FIELD_COMPUTERTOOKOVER, (unsigned char)1 );
- else
- stats.Add_Field( FIELD_COMPUTERTOOKOVER, (unsigned char)0 );
- #endif
- /*
- ** Player team. (NOD or GDI)
- */
- field_player_team[3] = '1' + (char)house;
- stats.Add_Field (field_player_team, houses[player->ActLike]);
- /*
- ** Player color
- */
- field_player_color[3] = '1' + (char)house;
- stats.Add_Field (field_player_color, (unsigned char) (player->Class->House - HOUSE_MULTI1));
- /*
- ** Player end credits.
- */
- field_player_credits[3] = '1' + (char)house;
- stats.Add_Field (field_player_credits, player->Credits + player->Tiberium);
- /*
- ** Number of each unit/building type built
- */
- field_player_infantry_bought[3] = '1' + (char)house;
- field_player_units_bought[3] = '1' + (char)house;
- field_player_planes_bought[3] = '1' + (char)house;
- field_player_buildings_bought[3] = '1' + (char)house;
- field_player_vessels_bought[3] = '1' + (char)house;
- player->InfantryTotals->To_Network_Format();
- player->UnitTotals->To_Network_Format();
- player->AircraftTotals->To_Network_Format();
- player->BuildingTotals->To_Network_Format();
- player->VesselTotals->To_Network_Format();
- stats.Add_Field (field_player_infantry_bought, (void*) player->InfantryTotals->Get_All_Totals(), player->InfantryTotals->Get_Unit_Count()*4);
- stats.Add_Field (field_player_units_bought, (void*) player->UnitTotals->Get_All_Totals(), player->UnitTotals->Get_Unit_Count()*4);
- stats.Add_Field (field_player_planes_bought, (void*) player->AircraftTotals->Get_All_Totals(), player->AircraftTotals->Get_Unit_Count()*4);
- stats.Add_Field (field_player_buildings_bought, (void*) player->BuildingTotals->Get_All_Totals(), player->BuildingTotals->Get_Unit_Count()*4);
- stats.Add_Field (field_player_vessels_bought, (void*) player->VesselTotals->Get_All_Totals(), player->VesselTotals->Get_Unit_Count()*4);
- player->InfantryTotals->To_PC_Format();
- player->UnitTotals->To_PC_Format();
- player->AircraftTotals->To_PC_Format();
- player->BuildingTotals->To_PC_Format();
- /*
- ** Clear out the counts and use the space to count up the current number of units/buildings
- */
- player->InfantryTotals->Clear_Unit_Total();
- player->AircraftTotals->Clear_Unit_Total();
- player->UnitTotals->Clear_Unit_Total();
- player->BuildingTotals->Clear_Unit_Total();
- player->VesselTotals->Clear_Unit_Total();
- /*
- ** Number of units remaining to player
- */
- for (index = 0; index < Units.Count(); index++) {
- UnitClass const * unit = Units.Ptr(index);
- if (player == unit->House){
- player->UnitTotals->Increment_Unit_Total (unit->Class->Type);
- }
- }
- for (index = 0; index < Infantry.Count(); index++) {
- InfantryClass const * infantry = Infantry.Ptr(index);
- if (player == infantry->House && !infantry->Class->IsCivilian){
- player->InfantryTotals->Increment_Unit_Total (infantry->Class->Type);
- }
- }
- for (index = 0; index < Aircraft.Count(); index++) {
- AircraftClass const * aircraft = Aircraft.Ptr(index);
- if (player == aircraft->House){ // && aircraft->Class->Type != AIRCRAFT_CARGO){
- player->AircraftTotals->Increment_Unit_Total (aircraft->Class->Type);
- }
- }
- for (index = 0; index < Buildings.Count(); index++) {
- BuildingClass const * building = Buildings.Ptr(index);
- if (player == building->House){
- player->BuildingTotals->Increment_Unit_Total (building->Class->Type);
- }
- }
- for (index = 0; index < Vessels.Count(); index++) {
- VesselClass const * vessel = Vessels.Ptr(index);
- if (player == vessel->House){
- player->VesselTotals->Increment_Unit_Total (vessel->Class->Type);
- }
- }
- player->InfantryTotals->To_Network_Format();
- player->UnitTotals->To_Network_Format();
- player->AircraftTotals->To_Network_Format();
- player->BuildingTotals->To_Network_Format();
- player->VesselTotals->To_Network_Format();
- field_player_infantry_left[3] = '1' + (char)house;
- field_player_units_left[3] = '1' + (char)house;
- field_player_planes_left[3] = '1' + (char)house;
- field_player_buildings_left[3] = '1' + (char)house;
- #ifdef FIXIT_IP_STATS
- field_player_vessels_left[3] = '1' + (char)house;
- #endif
- stats.Add_Field (field_player_infantry_left, (void*) player->InfantryTotals->Get_All_Totals(), player->InfantryTotals->Get_Unit_Count()*4);
- stats.Add_Field (field_player_units_left, (void*) player->UnitTotals->Get_All_Totals(), player->UnitTotals->Get_Unit_Count()*4);
- stats.Add_Field (field_player_planes_left, (void*) player->AircraftTotals->Get_All_Totals(), player->AircraftTotals->Get_Unit_Count()*4);
- stats.Add_Field (field_player_buildings_left, (void*) player->BuildingTotals->Get_All_Totals(), player->BuildingTotals->Get_Unit_Count()*4);
- stats.Add_Field (field_player_vessels_left, (void*) player->VesselTotals->Get_All_Totals(), player->VesselTotals->Get_Unit_Count()*4);
- /*
- ** Number of enemy units/buildings of each type destroyed.
- */
- player->DestroyedInfantry->To_Network_Format();
- player->DestroyedUnits->To_Network_Format();
- player->DestroyedAircraft->To_Network_Format();
- player->DestroyedBuildings->To_Network_Format();
- player->DestroyedVessels->To_Network_Format();
- field_player_infantry_killed[3] = '1' + (char)house;
- field_player_units_killed[3] = '1' + (char)house;
- field_player_planes_killed[3] = '1' + (char)house;
- field_player_buildings_killed[3] = '1' + (char)house;
- field_player_vessels_killed[3] = '1' + (char)house;
- stats.Add_Field (field_player_infantry_killed, (void*) player->DestroyedInfantry->Get_All_Totals(), player->DestroyedInfantry->Get_Unit_Count()*4);
- stats.Add_Field (field_player_units_killed, (void*) player->DestroyedUnits->Get_All_Totals(), player->DestroyedUnits->Get_Unit_Count()*4);
- stats.Add_Field (field_player_planes_killed, (void*) player->DestroyedAircraft->Get_All_Totals(), player->DestroyedAircraft->Get_Unit_Count()*4);
- stats.Add_Field (field_player_buildings_killed, (void*) player->DestroyedBuildings->Get_All_Totals(), player->DestroyedBuildings->Get_Unit_Count()*4);
- #ifdef FIXIT_VERSION_3
- stats.Add_Field (field_player_vessels_killed, (void*) player->DestroyedVessels->Get_All_Totals(), player->DestroyedVessels->Get_Unit_Count()*4);
- #else
- stats.Add_Field (field_player_vessels_killed, (void*) player->DestroyedVessels->Get_All_Totals(), player->DestroyedBuildings->Get_Unit_Count()*4);
- #endif
- /*
- ** Number and type of enemy buildings captured
- */
- field_player_buildings_captured[3] = '1' + (char)house;
- player->CapturedBuildings->To_Network_Format();
- stats.Add_Field (field_player_buildings_captured, (void*) player->CapturedBuildings->Get_All_Totals(), player->CapturedBuildings->Get_Unit_Count()*4);
- /*
- ** Number of crates discovered and their contents
- */
- field_player_crates_found[3] = '1' + (char)house;
- player->TotalCrates->To_Network_Format();
- stats.Add_Field (field_player_crates_found, (void*) player->TotalCrates->Get_All_Totals(), player->TotalCrates->Get_Unit_Count()*4);
- /*
- ** Amount of tiberium turned into credits
- */
- field_player_harvested[3] = '1' + (char)house;
- stats.Add_Field (field_player_harvested, (unsigned long) player->HarvestedCredits);
- }
- /*
- ** Create the comms packet to be sent
- */
- packet = stats.Create_Comms_Packet(packet_size);
- #ifndef WOLAPI_INTEGRATION // ajw - 'PacketLater' is no longer ever used.
- /*
- ** If a player disconnected then dont send the packet at this time - save it for later
- */
- if (completion == COMPLETION_PLAYER_1_WON_BY_DISCONNECTION
- || completion == COMPLETION_PLAYER_2_WON_BY_DISCONNECTION){
- PacketLater = packet;
- return;
- }
- #endif
- }else{ //else for if (!PacketLater)
- /*
- ** Send the packet we calculated earlier when the disconnect occurred
- */
- packet = PacketLater;
- PacketLater = NULL;
- }
- /*
- ** Send it.....
- */
- const char* szGameResServer;
- int iPort;
- if( pWolapi->GameInfoCurrent.GameKind == CREATEGAMEINFO::AMGAME )
- {
- szGameResServer = pWolapi->szGameResServerHost2;
- iPort = pWolapi->iGameResServerPort2;
- }
- else
- {
- szGameResServer = pWolapi->szGameResServerHost1;
- iPort = pWolapi->iGameResServerPort1;
- }
- if( *szGameResServer )
- {
- if( pWolapi->pNetUtil->RequestGameresSend( szGameResServer, iPort, (unsigned char*)packet, packet_size ) != S_OK )
- //debugprint( "RequestGameresSend( %s, %i ) failed!!!\n", szGameResServer, iPort );
- ;
- }
- /*
- ** Save it to disk as well so I can see it
- */
- // RawFileClass anotherfile ("packet.net");
- // anotherfile.Write(packet, packet_size);
- //debugprint( "Wrote out packet.net\n" );
- /*
- ** Tidy up
- */
- delete [] packet;
- GameStatisticsPacketSent = true;
- #endif // INTERNET_OFF
- #endif
- }
- void Register_Game_Start_Time(void)
- {
- GameTimer.Set (0, true);
- GameTimerInUse = true;
- }
- extern void Register_Game_End_Time(void)
- {
- GameEndTime = GameTimer.Time();
- GameTimerInUse = false;
- }
- #endif //WIN32
|