void xrServer::Process_save(NET_Packet& P, ClientID sender) { xrClientData* CL = ID_to_client(sender); if (CL) CL->net_Ready = TRUE; R_ASSERT(CL->flags.bLocal); // while has information while (!P.r_eof()) { // find entity u16 ID; u16 size; P.r_u16 (ID); P.r_u16 (size); s32 _pos_start = P.r_tell (); CSE_Abstract *E = ID_to_entity(ID); if (E) { E->net_Ready = TRUE; E->load (P); } else P.r_advance (size); s32 _pos_end = P.r_tell (); s32 _size = size; if (_size != (_pos_end-_pos_start)) { Msg ("! load/save mismatch, object: '%s'",E?E->name_replace():"unknown"); s32 _rollback = _pos_start+_size; P.r_seek (_rollback); } } }
void xrGameSpyServer::OnCDKey_ReValidation (int LocalID, int hint, char* challenge) { ClientID ID; ID.set(u32(LocalID)); xrGameSpyClientData* CL = (xrGameSpyClientData*) ID_to_client(ID); if (!CL) return; strcpy_s(CL->m_pChallengeString, challenge); CL->m_iCDKeyReauthHint = hint; //--------- Send Respond --------------------------------------------- NET_Packet P; P.w_begin (M_GAMESPY_CDKEY_VALIDATION_CHALLENGE); P.w_u8(1); P.w_stringZ(CL->m_pChallengeString); SendTo(CL->ID, P); }
void xrServer::Process_update(NET_Packet& P, ClientID sender) { xrClientData* CL = ID_to_client(sender); if (!CL) { return; } // if (CL) CL->net_Ready = TRUE; #ifdef DEBUG if (g_Dump_Update_Read) Msg("---- UPDATE_Read --- "); #endif // Entities R_ASSERT(CL->flags.bLocal); // while has information while (!P.r_eof()) { // find entity u16 ID; u8 size; P.r_u16 (ID); P.r_u8 (size); u32 _pos = P.r_tell(); CSE_Abstract *E = ID_to_entity(ID); if (E) { //Msg ("sv_import: %d '%s'",E->ID,E->name_replace()); E->net_Ready = TRUE; E->UPDATE_Read (P); #ifdef DEBUG if (g_Dump_Update_Read) Msg("* %s : %d - %d", E->name(), size, P.r_tell() - _pos); #endif if ((P.r_tell()-_pos) != size) { string16 tmp; CLSID2TEXT (E->m_tClassID,tmp); Debug.fatal (DEBUG_INFO,"Beer from the creator of '%s'",tmp); } } else P.r_advance (size); } #ifdef DEBUG if (g_Dump_Update_Read) Msg("-------------------- "); #endif // Entities }
void xrGameSpyServer::OnCDKey_Validation (int LocalID, int res, char* errormsg) { ClientID ID; ID.set(u32(LocalID)); xrGameSpyClientData* CL = (xrGameSpyClientData*) ID_to_client(ID); if (0 != res) { CL->m_bCDKeyAuth = true; #ifndef MASTER_GOLD Msg("xrGS::CDKey: Validation successful - <%s>", errormsg); #endif // #ifndef MASTER_GOLD Check_GameSpy_CDKey_Success(CL); } else { Msg ("CDKey: Validation failed - <%s>", errormsg); SendConnectResult (CL, u8(res), u8(1), errormsg); } };
void xrServer::Process_update(NET_Packet& P, ClientID sender) { xrClientData* CL = ID_to_client(sender); R_ASSERT2 (CL,"Process_update client not found"); if (g_Dump_Update_Read) Msg("---- UPDATE_Read --- "); R_ASSERT(CL->flags.bLocal); // while has information while (!P.r_eof()) { // find entity u16 ID; u8 size; P.r_u16 (ID); P.r_u8 (size); u32 _pos = P.r_tell(); CSE_Abstract *E = ID_to_entity(ID); if (E) { //Msg ("sv_import: %d '%s'",E->ID,E->name_replace()); E->net_Ready = TRUE; E->UPDATE_Read (P); u32 cp = P.r_tell(); if (g_Dump_Update_Read) Msg("* %s : %d - %d", E->name(), size, cp - _pos); if ((cp - _pos) != size) { string16 tmp; CLSID2TEXT (E->m_tClassID,tmp); Msg("* size = %d, start read = %d, end read = %d", size, _pos, cp); Debug.fatal (DEBUG_INFO,"Beer from the creator of '%s', version of object = %d", tmp, E->m_wVersion); } } else P.r_advance (size); } if (g_Dump_Update_Read) Msg("-------------------- "); }
void xrServer::Process_event_destroy (NET_Packet& P, ClientID sender, u32 time, u16 ID, NET_Packet* pEPack) { u32 MODE = net_flags(TRUE,TRUE); // Parse message u16 id_dest = ID; #ifdef DEBUG if( dbg_net_Draw_Flags.test( dbg_destroy ) ) Msg ("sv destroy object %s [%d]", ent_name_safe(id_dest).c_str(), Device.dwFrame); #endif CSE_Abstract* e_dest = game->get_entity_from_eid (id_dest); // кто должен быть уничтожен if (!e_dest) { #ifndef MASTER_GOLD Msg ("! SV:ge_destroy: [%d] not found on server",id_dest); #endif // #ifndef MASTER_GOLD return; }; R_ASSERT (e_dest); xrClientData *c_dest = e_dest->owner; // клиент, чей юнит R_ASSERT (c_dest); xrClientData *c_from = ID_to_client(sender); // клиент, кто прислал R_ASSERT (c_dest == c_from); // assure client ownership of event u16 parent_id = e_dest->ID_Parent; #ifdef MP_LOGGING Msg("- SV: Process destroy: parent [%d] item [%d][%s]", parent_id, id_dest, e_dest->name()); #endif //#ifdef MP_LOGGING //--------------------------------------------- NET_Packet P2, *pEventPack = pEPack; P2.w_begin (M_EVENT_PACK); //--------------------------------------------- // check if we have children if (!e_dest->children.empty()) { if (!pEventPack) pEventPack = &P2; while (!e_dest->children.empty()) Process_event_destroy (P,sender,time,*e_dest->children.begin(), pEventPack); }; if (0xffff == parent_id && NULL == pEventPack) { SendBroadcast (BroadcastCID,P,MODE); } else { NET_Packet tmpP; if (0xffff != parent_id && Process_event_reject(P,sender,time,parent_id,ID,false)) { game->u_EventGen(tmpP, GE_OWNERSHIP_REJECT, parent_id); tmpP.w_u16(id_dest); tmpP.w_u8(1); if (!pEventPack) pEventPack = &P2; pEventPack->w_u8(u8(tmpP.B.count)); pEventPack->w(&tmpP.B.data, tmpP.B.count); }; game->u_EventGen(tmpP, GE_DESTROY, id_dest); pEventPack->w_u8(u8(tmpP.B.count)); pEventPack->w(&tmpP.B.data, tmpP.B.count); }; if (NULL == pEPack && NULL != pEventPack) { SendBroadcast (BroadcastCID, *pEventPack, MODE); } // Everything OK, so perform entity-destroy if (e_dest->m_bALifeControl && ai().get_alife()) { game_sv_Single *_game = smart_cast<game_sv_Single*>(game); VERIFY (_game); if (ai().alife().objects().object(id_dest,true)) _game->alife().release (e_dest,false); } if (game) game->OnDestroyObject (e_dest->ID); entity_Destroy (e_dest); }
void xrServer::Process_event (NET_Packet& P, ClientID sender) { # ifdef SLOW_VERIFY_ENTITIES VERIFY (verify_entities()); # endif u32 timestamp; u16 type; u16 destination; u32 MODE = net_flags(TRUE,TRUE); // correct timestamp with server-unique-time (note: direct message correction) P.r_u32 (timestamp ); // read generic info P.r_u16 (type ); P.r_u16 (destination); CSE_Abstract* receiver = game->get_entity_from_eid (destination); if (receiver) { R_ASSERT(receiver->owner); receiver->OnEvent (P,type,timestamp,sender); }; switch (type) { case GE_GAME_EVENT: { u16 game_event_type; P.r_u16(game_event_type); game->AddDelayedEvent(P,game_event_type,timestamp,sender); }break; case GE_INFO_TRANSFER: case GE_WPN_STATE_CHANGE: case GE_ZONE_STATE_CHANGE: case GE_ACTOR_JUMPING: case GEG_PLAYER_PLAY_HEADSHOT_PARTICLE: case GEG_PLAYER_ATTACH_HOLDER: case GEG_PLAYER_DETACH_HOLDER: case GEG_PLAYER_ITEM2SLOT: case GEG_PLAYER_ITEM2BELT: case GEG_PLAYER_ITEM2RUCK: case GE_GRENADE_EXPLODE: { SendBroadcast (BroadcastCID,P,MODE); }break; case GEG_PLAYER_ACTIVATEARTEFACT: { Process_event_activate (P,sender,timestamp,destination,P.r_u16(), true); break; }; case GE_INV_ACTION: { xrClientData* CL = ID_to_client(sender); if (CL) CL->net_Ready = TRUE; if (SV_Client) SendTo(SV_Client->ID, P, net_flags(TRUE, TRUE)); }break; case GE_RESPAWN: { CSE_Abstract* E = receiver; if (E) { R_ASSERT (E->s_flags.is(M_SPAWN_OBJECT_PHANTOM)); svs_respawn R; R.timestamp = timestamp + E->RespawnTime*1000; R.phantom = destination; q_respawn.insert (R); } } break; case GE_TRADE_BUY: case GE_OWNERSHIP_TAKE: { Process_event_ownership (P,sender,timestamp,destination); VERIFY (verify_entities()); }break; case GE_OWNERSHIP_TAKE_MP_FORCED: { Process_event_ownership (P,sender,timestamp,destination,TRUE); VERIFY (verify_entities()); }break; case GE_TRADE_SELL: case GE_OWNERSHIP_REJECT: case GE_LAUNCH_ROCKET: { Process_event_reject (P,sender,timestamp,destination,P.r_u16()); VERIFY (verify_entities()); }break; case GE_DESTROY: { Process_event_destroy (P,sender,timestamp,destination, NULL); VERIFY (verify_entities()); } break; case GE_TRANSFER_AMMO: { u16 id_entity; P.r_u16 (id_entity); CSE_Abstract* e_parent = receiver; // кто забирает (для своих нужд) CSE_Abstract* e_entity = game->get_entity_from_eid (id_entity); // кто отдает if (!e_entity) break; if (0xffff != e_entity->ID_Parent) break; // this item already taken xrClientData* c_parent = e_parent->owner; xrClientData* c_from = ID_to_client (sender); R_ASSERT (c_from == c_parent); // assure client ownership of event // Signal to everyone (including sender) SendBroadcast (BroadcastCID,P,MODE); // Perfrom real destroy entity_Destroy (e_entity ); VERIFY (verify_entities()); } break; case GE_HIT: case GE_HIT_STATISTIC: { P.r_pos -=2; if (type == GE_HIT_STATISTIC) { P.B.count -= 4; P.w_u32(sender.value()); }; game->AddDelayedEvent(P,GAME_EVENT_ON_HIT, 0, ClientID() ); } break; case GE_ASSIGN_KILLER: { u16 id_src; P.r_u16 (id_src); CSE_Abstract *e_dest = receiver; // кто умер // this is possible when hit event is sent before destroy event if (!e_dest) break; CSE_ALifeCreatureAbstract *creature = smart_cast<CSE_ALifeCreatureAbstract*>(e_dest); if (creature) creature->set_killer_id( id_src ); // Msg ("[%d][%s] killed [%d][%s]",id_src,id_src==u16(-1) ? "UNKNOWN" : game->get_entity_from_eid(id_src)->name_replace(),id_dest,e_dest->name_replace()); break; } case GE_CHANGE_VISUAL: { CSE_Visual* visual = smart_cast<CSE_Visual*>(receiver); VERIFY(visual); string256 tmp; P.r_stringZ (tmp); visual->set_visual (tmp); }break; case GE_DIE: { // Parse message u16 id_dest = destination, id_src; P.r_u16 (id_src); xrClientData *l_pC = ID_to_client(sender); VERIFY (game && l_pC); #ifndef MASTER_GOLD if ((game->Type() != eGameIDSingle) && l_pC && l_pC->owner) { Msg ("* [%2d] killed by [%2d] - sended by [%s:%2d]", id_dest, id_src, game->get_option_s(*l_pC->name,"name","Player"), l_pC->owner->ID); } #endif // #ifndef MASTER_GOLD CSE_Abstract* e_dest = receiver; // кто умер // this is possible when hit event is sent before destroy event if (!e_dest) break; #ifndef MASTER_GOLD if (game->Type() != eGameIDSingle) Msg ("* [%2d] is [%s:%s]", id_dest, *e_dest->s_name, e_dest->name_replace()); #endif // #ifndef MASTER_GOLD CSE_Abstract* e_src = game->get_entity_from_eid (id_src ); // кто убил if (!e_src) { xrClientData* C = (xrClientData*) game->get_client(id_src); if (C) e_src = C->owner; }; VERIFY (e_src); if (!e_src) { Msg("! ERROR: SV: src killer not exist."); return; } // R_ASSERT2 (e_dest && e_src, "Killer or/and being killed are offline or not exist at all :("); #ifndef MASTER_GOLD if (game->Type() != eGameIDSingle) Msg ("* [%2d] is [%s:%s]", id_src, *e_src->s_name, e_src->name_replace()); #endif // #ifndef MASTER_GOLD game->on_death (e_dest,e_src); xrClientData* c_src = e_src->owner; // клиент, чей юнит убил if (c_src->owner->ID == id_src) { // Main unit P.w_begin (M_EVENT); P.w_u32 (timestamp); P.w_u16 (type); P.w_u16 (destination); P.w_u16 (id_src); P.w_clientID (c_src->ID); } SendBroadcast (BroadcastCID,P,MODE); ////////////////////////////////////////////////////////////////////////// // if (game->Type() == eGameIDSingle) { P.w_begin (M_EVENT); P.w_u32 (timestamp); P.w_u16 (GE_KILL_SOMEONE); P.w_u16 (id_src); P.w_u16 (destination); SendTo (c_src->ID, P, net_flags(TRUE, TRUE)); } ////////////////////////////////////////////////////////////////////////// VERIFY (verify_entities()); } break; case GE_ADDON_ATTACH: case GE_ADDON_DETACH: case GE_CHANGE_POS: { SendTo(SV_Client->ID, P, net_flags(TRUE, TRUE)); }break; case GE_INSTALL_UPGRADE: { shared_str upgrade_id; P.r_stringZ ( upgrade_id ); CSE_ALifeInventoryItem* iitem = smart_cast<CSE_ALifeInventoryItem*>( receiver ); if ( !iitem ) { break; } iitem->add_upgrade ( upgrade_id ); }break; case GEG_PLAYER_DISABLE_SPRINT: case GEG_PLAYER_WEAPON_HIDE_STATE: { SendTo (SV_Client->ID, P, net_flags(TRUE, TRUE)); # ifdef SLOW_VERIFY_ENTITIES VERIFY (verify_entities()); # endif }break; case GEG_PLAYER_ACTIVATE_SLOT: case GEG_PLAYER_ITEM_EAT: { SendTo(SV_Client->ID, P, net_flags(TRUE, TRUE)); # ifdef SLOW_VERIFY_ENTITIES VERIFY (verify_entities()); # endif }break; case GEG_PLAYER_ITEM_SELL: { game->OnPlayer_Sell_Item(sender, P); }break; case GE_TELEPORT_OBJECT: { game->teleport_object (P,destination); }break; case GE_ADD_RESTRICTION: { game->add_restriction (P,destination); }break; case GE_REMOVE_RESTRICTION: { game->remove_restriction(P,destination); }break; case GE_REMOVE_ALL_RESTRICTIONS: { game->remove_all_restrictions(P,destination); }break; case GE_MONEY: { CSE_Abstract *e_dest = receiver; CSE_ALifeTraderAbstract* pTa = smart_cast<CSE_ALifeTraderAbstract*>(e_dest); pTa->m_dwMoney = P.r_u32(); }break; case GE_FREEZE_OBJECT: break; default: R_ASSERT2 (0,"Game Event not implemented!!!"); break; } }
u32 xrServer::OnMessage (NET_Packet& P, ClientID sender) // Non-Zero means broadcasting with "flags" as returned { if (g_pGameLevel && Level().IsDemoSave()) Level().Demo_StoreServerData(P.B.data, P.B.count); u16 type; P.r_begin (type); csPlayers.Enter (); VERIFY (verify_entities()); xrClientData* CL = ID_to_client(sender); switch (type) { case M_UPDATE: { Process_update (P,sender); // No broadcast VERIFY (verify_entities()); }break; case M_SPAWN: { // R_ASSERT(CL->flags.bLocal); if (CL->flags.bLocal) Process_spawn (P,sender); VERIFY (verify_entities()); }break; case M_EVENT: { Process_event (P,sender); VERIFY (verify_entities()); }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); OnMessage (tmpP, sender); }; }break; case M_CL_UPDATE: { xrClientData* CL = ID_to_client (sender); if (!CL) break; CL->net_Ready = TRUE; if (!CL->net_PassUpdates) break; //------------------------------------------------------------------- u32 ClientPing = CL->stats.getPing(); P.w_seek(P.r_tell()+2, &ClientPing, 4); //------------------------------------------------------------------- if (SV_Client) SendTo (SV_Client->ID, P, net_flags(TRUE, TRUE)); VERIFY (verify_entities()); }break; case M_MOVE_PLAYERS_RESPOND: { xrClientData* CL = ID_to_client (sender); if (!CL) break; CL->net_Ready = TRUE; CL->net_PassUpdates = TRUE; }break; //------------------------------------------------------------------- case M_CL_PING_CHALLENGE: { P.r_u32(); u32 id = sender.value(); P.w_seek( P.r_tell(), &(id), 4); if (SV_Client) SendTo (SV_Client->ID, P, net_flags(FALSE)); }break; case M_CL_PING_CHALLENGE_RESPOND: { P.r_u32(); u32 id = P.r_u32(); ClientID clientID; clientID.set(id); u32 clLastPing = P.r_u32(); xrClientData* pCL = ID_to_client(clientID); pCL->ps->Rping = u16(clLastPing); SendTo (clientID, P, net_flags(FALSE)); }break; //------------------------------------------------------------------- case M_CL_INPUT: { xrClientData* CL = ID_to_client (sender); if (CL) CL->net_Ready = TRUE; if (SV_Client) SendTo (SV_Client->ID, P, net_flags(TRUE, TRUE)); VERIFY (verify_entities()); }break; case M_GAMEMESSAGE: { ClientID clientID;clientID.setBroadcast(); SendBroadcast (clientID,P,net_flags(TRUE,TRUE)); VERIFY (verify_entities()); }break; case M_CLIENTREADY: { xrClientData* CL = ID_to_client(sender); if (CL) { CL->net_Ready = TRUE; CL->ps->DeathTime = Device.dwTimeGlobal; game->OnPlayerConnectFinished(sender); }; game->signal_Syncronize (); VERIFY (verify_entities()); }break; case M_SWITCH_DISTANCE: { game->switch_distance (P,sender); VERIFY (verify_entities()); }break; case M_CHANGE_LEVEL: { if (game->change_level(P,sender)){ ClientID clientID;clientID.setBroadcast(); SendBroadcast (clientID,P,net_flags(TRUE,TRUE)); } VERIFY (verify_entities()); }break; case M_SAVE_GAME: { game->save_game (P,sender); VERIFY (verify_entities()); }break; case M_LOAD_GAME: { game->load_game (P,sender); ClientID clientID;clientID.setBroadcast(); SendBroadcast (clientID,P,net_flags(TRUE,TRUE)); VERIFY (verify_entities()); }break; case M_RELOAD_GAME: { ClientID clientID;clientID.setBroadcast(); SendBroadcast (clientID,P,net_flags(TRUE,TRUE)); VERIFY (verify_entities()); }break; case M_SAVE_PACKET: { Process_save (P,sender); VERIFY (verify_entities()); }break; case M_CLIENT_REQUEST_CONNECTION_DATA: { xrClientData* CL = ID_to_client (sender); OnCL_Connected (CL); }break; case M_CHAT_MESSAGE: { xrClientData *l_pC = ID_to_client(sender); OnChatMessage (&P, l_pC); }break; case M_CHANGE_LEVEL_GAME: { ClientID CID; CID.set (0xffffffff); SendBroadcast (CID,P,net_flags(TRUE,TRUE)); }break; case M_CL_AUTH: { game->AddDelayedEvent (P,GAME_EVENT_PLAYER_AUTH, 0, sender); }break; case M_PAUSE_GAME: { ClientID clientID;clientID.setBroadcast(); SendBroadcast (clientID,P,net_flags(TRUE,TRUE)); }break; case M_STATISTIC_UPDATE: { ClientID clientID;clientID.setBroadcast(); if (SV_Client) SendBroadcast (SV_Client->ID,P,net_flags(TRUE,TRUE)); else SendBroadcast (clientID,P,net_flags(TRUE,TRUE)); }break; case M_STATISTIC_UPDATE_RESPOND: { if (SV_Client) SendTo (SV_Client->ID, P, net_flags(TRUE, TRUE)); }break; case M_PLAYER_FIRE: { if (game) game->OnPlayerFire(sender, P); }break; } VERIFY (verify_entities()); csPlayers.Leave (); return IPureServer::OnMessage(P, sender); }