bool CPatchManager::IsSameFile( FILE_INFO& info ) { WIN32_FILE_ATTRIBUTE_DATA attribute; BOOL bOK = ::GetFileAttributesEx( info.szPath, GetFileExInfoStandard, &attribute ); if( bOK ) { if( info.nFileSize == attribute.nFileSizeLow ) // 파일 크기 같고 { // GMT단위로 비교한다. SYSTEMTIME stServer, stClient; FileTimeToSystemTime( &info.ft, &stServer ); FileTimeToSystemTime( &attribute.ftLastWriteTime, &stClient ); // 시각이 일치할 때 CTime timeServer( (int)stServer.wYear, (int)stServer.wMonth, (int)stServer.wDay, (int)stServer.wHour, (int)stServer.wMinute, (int)stServer.wSecond ); CTime timeClient( (int)stClient.wYear, (int)stClient.wMonth, (int)stClient.wDay, (int)stClient.wHour, (int)stClient.wMinute, (int)stClient.wSecond ); time_t nTimeGap = static_cast< time_t >( timeServer.GetTime() - timeClient.GetTime() ); if( abs(nTimeGap) <= 60*3 ) // 3분 이하의 차이는 무시 return true; } } return false; }
void CLevel::ProcessGameEvents () { // Game events { NET_Packet P; u32 svT = timeServer()-NET_Latency; /* if (!game_events->queue.empty()) Msg("- d[%d],ts[%d] -- E[svT=%d],[evT=%d]",Device.dwTimeGlobal,timeServer(),svT,game_events->queue.begin()->timestamp); */ #ifdef SPAWN_ANTIFREEZE while (spawn_events->available(svT)) { u16 ID, dest, type; spawn_events->get(ID, dest, type, P); game_events->insert(P); } u32 avail_time = 5; u32 elps = Device.frame_elapsed(); if (elps < 30) avail_time = 33 - elps; u32 work_limit = elps + avail_time; #endif while (game_events->available(svT)) { u16 ID,dest,type; game_events->get (ID,dest,type,P); #ifdef SPAWN_ANTIFREEZE // не отправлять события не заспавненным объектам if (g_bootComplete && M_EVENT == ID && PostponedSpawn(dest)) { spawn_events->insert(P); continue; } if (g_bootComplete && M_SPAWN == ID && Device.frame_elapsed() > work_limit) // alpet: позволит плавнее выводить объекты в онлайн, без заметных фризов { u16 parent_id; GetSpawnInfo(P, parent_id); //------------------------------------------------- if (parent_id < 0xffff) // откладывать спавн только объектов в контейнеры { //if (!spawn_events->available(svT)) //Msg("* ProcessGameEvents, spawn event postponed. Events rest = %d", game_events->queue.size()); spawn_events->insert(P); continue; } } #endif switch (ID) { case M_SPAWN: { u16 dummy16; P.r_begin(dummy16); cl_Process_Spawn(P); }break; case M_EVENT: { cl_Process_Event(dest, type, P); }break; case M_MOVE_PLAYERS: { u8 Count = P.r_u8(); for (u8 i=0; i<Count; i++) { u16 ID = P.r_u16(); Fvector NewPos, NewDir; P.r_vec3(NewPos); P.r_vec3(NewDir); CActor* OActor = smart_cast<CActor*>(Objects.net_Find (ID)); if (0 == OActor) break; OActor->MoveActor(NewPos, NewDir); }; NET_Packet PRespond; PRespond.w_begin(M_MOVE_PLAYERS_RESPOND); Send(PRespond, net_flags(TRUE, TRUE)); }break; case M_STATISTIC_UPDATE: { if (GameID() != eGameIDSingle) Game().m_WeaponUsageStatistic->OnUpdateRequest(&P); }break; case M_FILE_TRANSFER: { if (m_file_transfer) //in case of net_Stop m_file_transfer->on_message(&P); }break; case M_GAMEMESSAGE: { Game().OnGameMessage(P); }break; default: { VERIFY(0); }break; } } } if (OnServer() && GameID()!= eGameIDSingle) Game().m_WeaponUsageStatistic->Send_Check_Respond(); }
void CLevel::ProcessGameEvents () { // Game events { NET_Packet P; u32 svT = timeServer()-NET_Latency; /* if (!game_events->queue.empty()) Msg("- d[%d],ts[%d] -- E[svT=%d],[evT=%d]",Device.dwTimeGlobal,timeServer(),svT,game_events->queue.begin()->timestamp); */ #ifdef SPAWN_ANTIFREEZE while (spawn_events->available(svT)) { u16 ID,dest,type; spawn_events->get (ID,dest,type,P); game_events->insert (P); } u32 avail_time = 5; u32 elps = Device.frame_elapsed(); if (elps < 30) avail_time = 33 - elps; u32 work_limit = elps + avail_time; #endif while (game_events->available(svT)) { u16 ID,dest,type; game_events->get (ID,dest,type,P); #ifdef SPAWN_ANTIFREEZE // не отправлять события не заспавненным объектам if (g_bootComplete && M_EVENT == ID && PostponedSpawn(dest)) { spawn_events->insert(P); continue; } if (g_bootComplete && M_SPAWN == ID && Device.frame_elapsed() > work_limit) // alpet: позволит плавнее выводить объекты в онлайн, без заметных фризов { u16 parent_id; GetSpawnInfo(P, parent_id); //------------------------------------------------- if (parent_id < 0xffff) // откладывать спавн только объектов в контейнеры { if (!spawn_events->available(svT)) Msg("* ProcessGameEvents, spawn event postponed. Events rest = %d", game_events->queue.size()); spawn_events->insert(P); continue; } } #endif switch (ID) { case M_SPAWN: { u16 dummy16; P.r_begin(dummy16); cl_Process_Spawn(P); }break; case M_EVENT: { cl_Process_Event(dest, type, P); }break; default: { VERIFY(0); }break; } } } if (OnServer() && GameID()!= GAME_SINGLE) Game().m_WeaponUsageStatistic->Send_Check_Respond(); }
void CLevel::ClientReceive() { Demo_StartFrame(); Demo_Update(); m_dwRPC = 0; m_dwRPS = 0; for (NET_Packet* P = net_msg_Retreive(); P; P=net_msg_Retreive()) { //----------------------------------------------------- m_dwRPC++; m_dwRPS += P->B.count; //----------------------------------------------------- u16 m_type; u16 ID; P->r_begin (m_type); switch (m_type) { case M_MAP_SYNC: { shared_str map_name; P->r_stringZ(map_name); shared_str _name = net_Hosts.size() ? net_Hosts.front().dpSessionName:""; if(_name.size() && _name!=map_name && OnClient()) { Msg("!!! map sync failed. current is[%s] server is[%s]",m_name.c_str(), map_name.c_str()); Engine.Event.Defer ("KERNEL:disconnect"); Engine.Event.Defer ("KERNEL:start",m_caServerOptions.size() ? size_t( xr_strdup(*m_caServerOptions)) : 0, m_caClientOptions.size() ? size_t(xr_strdup(*m_caClientOptions)) : 0); } }break; case M_SPAWN: { if (!m_bGameConfigStarted || !bReady) { Msg ("Unconventional M_SPAWN received : cgf[%s] | bReady[%s]", (m_bGameConfigStarted) ? "true" : "false", (bReady) ? "true" : "false"); break; } /*/ cl_Process_Spawn(*P); /*/ game_events->insert (*P); if (g_bDebugEvents) ProcessGameEvents(); //*/ } break; case M_EVENT: game_events->insert (*P); if (g_bDebugEvents) ProcessGameEvents(); break; case M_EVENT_PACK: NET_Packet tmpP; while (!P->r_eof()) { tmpP.B.count = P->r_u8(); P->r(&tmpP.B.data, tmpP.B.count); tmpP.timeReceive = P->timeReceive; game_events->insert (tmpP); if (g_bDebugEvents) ProcessGameEvents(); }; break; case M_UPDATE: { game->net_import_update (*P); //------------------------------------------- if (OnServer()) break; //------------------------------------------- }; // ни в коем случае нельзя здесь ставить break, т.к. в случае если все объекты не влазят в пакет M_UPDATE, // они досылаются через M_UPDATE_OBJECTS case M_UPDATE_OBJECTS: { Objects.net_Import (P); if (OnClient()) UpdateDeltaUpd(timeServer()); IClientStatistic pStat = Level().GetStatistic(); u32 dTime = 0; if ((Level().timeServer() + pStat.getPing()) < P->timeReceive) { dTime = pStat.getPing(); } else dTime = Level().timeServer() - P->timeReceive + pStat.getPing(); u32 NumSteps = ph_world->CalcNumSteps(dTime); SetNumCrSteps(NumSteps); }break; // case M_UPDATE_OBJECTS: // { // Objects.net_Import (P); // }break; //----------- for E3 ----------------------------- case M_CL_UPDATE: { if (OnClient()) break; P->r_u16 (ID); u32 Ping = P->r_u32(); CGameObject* O = smart_cast<CGameObject*>(Objects.net_Find (ID)); if (0 == O) break; O->net_Import(*P); //--------------------------------------------------- UpdateDeltaUpd(timeServer()); if (pObjects4CrPr.empty() && pActors4CrPr.empty()) break; if (O->CLS_ID != CLSID_OBJECT_ACTOR) break; u32 dTime = 0; if ((Level().timeServer() + Ping) < P->timeReceive) { #ifdef DEBUG // Msg("! TimeServer[%d] < TimeReceive[%d]", Level().timeServer(), P->timeReceive); #endif dTime = Ping; } else dTime = Level().timeServer() - P->timeReceive + Ping; u32 NumSteps = ph_world->CalcNumSteps(dTime); SetNumCrSteps(NumSteps); O->CrPr_SetActivationStep(u32(ph_world->m_steps_num) - NumSteps); AddActor_To_Actors4CrPr(O); }break; case M_MOVE_PLAYERS: { u8 Count = P->r_u8(); for (u8 i=0; i<Count; i++) { u16 ID = P->r_u16(); Fvector NewPos, NewDir; P->r_vec3(NewPos); P->r_vec3(NewDir); CActor* OActor = smart_cast<CActor*>(Objects.net_Find (ID)); if (0 == OActor) break; OActor->MoveActor(NewPos, NewDir); }; NET_Packet PRespond; PRespond.w_begin(M_MOVE_PLAYERS_RESPOND); Send(PRespond, net_flags(TRUE, TRUE)); }break; //------------------------------------------------ case M_CL_INPUT: { P->r_u16 (ID); CObject* O = Objects.net_Find (ID); if (0 == O) break; O->net_ImportInput(*P); }break; //--------------------------------------------------- case M_SV_CONFIG_NEW_CLIENT: InitializeClientGame(*P); break; case M_SV_CONFIG_GAME: game->net_import_state (*P); break; case M_SV_CONFIG_FINISHED: game_configured = TRUE; Msg("- Game configuring : Finished "); break; case M_MIGRATE_DEACTIVATE: // TO: Changing server, just deactivate { P->r_u16 (ID); CObject* O = Objects.net_Find (ID); if (0 == O) break; O->net_MigrateInactive (*P); if (bDebug) Log("! MIGRATE_DEACTIVATE",*O->cName()); } break; case M_MIGRATE_ACTIVATE: // TO: Changing server, full state { P->r_u16 (ID); CObject* O = Objects.net_Find (ID); if (0 == O) break; O->net_MigrateActive (*P); if (bDebug) Log("! MIGRATE_ACTIVATE",*O->cName()); } break; case M_CHAT: { char buffer[256]; P->r_stringZ(buffer); Msg ("- %s",buffer); } break; case M_GAMEMESSAGE: { if (!game) break; Game().OnGameMessage(*P); }break; case M_RELOAD_GAME: case M_LOAD_GAME: case M_CHANGE_LEVEL: { if(m_type==M_LOAD_GAME) { string256 saved_name; P->r_stringZ (saved_name); if(xr_strlen(saved_name) && ai().get_alife()) { CSavedGameWrapper wrapper(saved_name); if (wrapper.level_id() == ai().level_graph().level_id()) { Engine.Event.Defer ("Game:QuickLoad", size_t(xr_strdup(saved_name)), 0); break; } } } Engine.Event.Defer ("KERNEL:disconnect"); Engine.Event.Defer ("KERNEL:start",size_t(xr_strdup(*m_caServerOptions)),size_t(xr_strdup(*m_caClientOptions))); }break; case M_SAVE_GAME: { ClientSave (); }break; case M_GAMESPY_CDKEY_VALIDATION_CHALLENGE: { OnGameSpyChallenge(P); }break; case M_AUTH_CHALLENGE: { OnBuildVersionChallenge(); }break; case M_CLIENT_CONNECT_RESULT: { OnConnectResult(P); }break; case M_CHAT_MESSAGE: { if (!game) break; Game().OnChatMessage(P); }break; case M_CLIENT_WARN: { if (!game) break; Game().OnWarnMessage(P); }break; case M_REMOTE_CONTROL_AUTH: case M_REMOTE_CONTROL_CMD: { Game().OnRadminMessage(m_type, P); }break; case M_CHANGE_LEVEL_GAME: { Msg("- M_CHANGE_LEVEL_GAME Received"); if (OnClient()) { Engine.Event.Defer ("KERNEL:disconnect"); Engine.Event.Defer ("KERNEL:start",m_caServerOptions.size() ? size_t( xr_strdup(*m_caServerOptions)) : 0,m_caClientOptions.size() ? size_t(xr_strdup(*m_caClientOptions)) : 0); } else { const char* m_SO = m_caServerOptions.c_str(); // const char* m_CO = m_caClientOptions.c_str(); m_SO = strchr(m_SO, '/'); if (m_SO) m_SO++; m_SO = strchr(m_SO, '/'); string128 LevelName = ""; string128 GameType = ""; P->r_stringZ(LevelName); P->r_stringZ(GameType); string4096 NewServerOptions = ""; sprintf_s(NewServerOptions, "%s/%s", LevelName, GameType); if (m_SO) strcat(NewServerOptions, m_SO); m_caServerOptions = NewServerOptions; Engine.Event.Defer ("KERNEL:disconnect"); Engine.Event.Defer ("KERNEL:start",size_t(xr_strdup(*m_caServerOptions)),size_t(xr_strdup(*m_caClientOptions))); }; }break; case M_CHANGE_SELF_NAME: { net_OnChangeSelfName(P); }break; case M_BULLET_CHECK_RESPOND: { if (!game) break; if (GameID() != GAME_SINGLE) Game().m_WeaponUsageStatistic->On_Check_Respond(P); }break; case M_STATISTIC_UPDATE: { if (!game) break; if (GameID() != GAME_SINGLE) Game().m_WeaponUsageStatistic->OnUpdateRequest(P); }break; case M_STATISTIC_UPDATE_RESPOND: { if (!game) break; if (GameID() != GAME_SINGLE) Game().m_WeaponUsageStatistic->OnUpdateRespond(P); }break; case M_BATTLEYE: { #ifdef BATTLEYE battleye_system.ReadPacketClient( P ); #endif // BATTLEYE }break; } net_msg_Release(); } // if (!g_bDebugEvents) ProcessGameSpawns(); }
int main(int argc, char *argv[]) { int pidFork; int i; int S[3], pid; socklen_t clilen; struct sockaddr_in serv_addr, cli_addr; signal(SIGCHLD,SIG_IGN); for (i=0; i<3; i++) { S[i] = socket(AF_INET, SOCK_STREAM, 0); if (S[i] < 0) error("ERROR opening socket!\n"); fcntl(S[i], F_SETFL, O_NONBLOCK); bzero((char *) &serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(PORT1+i); if (bind(S[i], (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) error("ERROR on binding!\n"); listen(S[i],5); } clilen = sizeof(cli_addr); if ((pidFork = fork()) == 0) { while(1) { int i=0; for (i=0; i<3; i++) { int NS; if((NS = accept(S[i], (struct sockaddr *) &cli_addr, &clilen)) >0 ) { pid = fork(); if (pid < 0) error("ERROR on fork"); if (pid == 0) { close(S[i]); if (i == 0) timeServer(NS); if (i == 1) fileServer(NS); if (i == 2) execServer(NS); exit(0); }else close(NS); } } } } return (0); }