void CLevel::g_cl_Spawn (LPCSTR name, u8 rp, u16 flags, Fvector pos) { // Create CSE_Abstract* E = F_entity_Create(name); VERIFY (E); // Fill E->s_name = name; E->set_name_replace (""); //. E->s_gameid = u8(GameID()); E->s_RP = rp; E->ID = 0xffff; E->ID_Parent = 0xffff; E->ID_Phantom = 0xffff; E->s_flags.assign (flags); E->RespawnTime = 0; E->o_Position = pos; // Send NET_Packet P; E->Spawn_Write (P,TRUE); Send (P,net_flags(TRUE)); // Destroy F_entity_Destroy (E); }
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); } } }
/////////spawn object representing destroyed item////////////////////////////////////////////////////////////////////////////////// void CPHDestroyable::GenSpawnReplace(u16 ref_id,LPCSTR section,shared_str visual_name) { CSE_Abstract *D = F_entity_Create(section);//*cNameSect() VERIFY (D); CSE_Visual *V =smart_cast<CSE_Visual*>(D); V->set_visual (*visual_name); CSE_PHSkeleton *l_tpPHSkeleton = smart_cast<CSE_PHSkeleton*>(D); VERIFY (l_tpPHSkeleton); l_tpPHSkeleton->source_id = ref_id; //init // Send D->s_name = section;//*cNameSect() D->ID_Parent = u16(-1); InitServerObject (D); if (OnServer()) { NET_Packet P; D->Spawn_Write (P,TRUE); Level().Send (P,net_flags(TRUE)); // Destroy F_entity_Destroy (D); m_depended_objects++; }; };
//call this after CGameObject::net_Spawn BOOL CInventoryOwner::net_Spawn (CSE_Abstract* DC) { if (!m_pTrade) m_pTrade = xr_new<CTrade>(this); if (m_trade_parameters) xr_delete (m_trade_parameters); m_trade_parameters = xr_new<CTradeParameters>(trade_section()); //получить указатель на объект, InventoryOwner //m_inventory->setSlotsBlocked(false); CGameObject *pThis = smart_cast<CGameObject*>(this); if(!pThis) return FALSE; CSE_Abstract* E = (CSE_Abstract*)(DC); if ( IsGameTypeSingle() ) { CSE_ALifeTraderAbstract* pTrader = NULL; if(E) pTrader = smart_cast<CSE_ALifeTraderAbstract*>(E); if(!pTrader) return FALSE; R_ASSERT( pTrader->character_profile().size() ); //синхронизируем параметры персонажа с серверным объектом CharacterInfo().Init(pTrader); //------------------------------------- m_known_info_registry->registry().init(E->ID); //------------------------------------- CAI_PhraseDialogManager* dialog_manager = smart_cast<CAI_PhraseDialogManager*>(this); if( dialog_manager && !dialog_manager->GetStartDialog().size() ) { dialog_manager->SetStartDialog(CharacterInfo().StartDialog()); dialog_manager->SetDefaultStartDialog(CharacterInfo().StartDialog()); } m_game_name = pTrader->m_character_name; } else { CharacterInfo().m_SpecificCharacter.Load ("mp_actor"); CharacterInfo().InitSpecificCharacter ("mp_actor"); CharacterInfo().m_SpecificCharacter.data()->m_sGameName = (E->name_replace()[0]) ? E->name_replace() : *pThis->cName(); m_game_name = (E->name_replace()[0]) ? E->name_replace() : *pThis->cName(); } if(!pThis->Local()) return TRUE; return TRUE; }
void CWeapon::SpawnAmmo(u32 boxCurr, LPCSTR ammoSect, u32 ParentID) { if(!m_ammoTypes.size()) return; if (OnClient()) return; m_bAmmoWasSpawned = true; int l_type = 0; l_type %= m_ammoTypes.size(); if(!ammoSect) ammoSect = m_ammoTypes[l_type].c_str(); ++l_type; l_type %= m_ammoTypes.size(); CSE_Abstract *D = F_entity_Create(ammoSect); { CSE_ALifeItemAmmo *l_pA = smart_cast<CSE_ALifeItemAmmo*>(D); R_ASSERT (l_pA); l_pA->m_boxSize = (u16)pSettings->r_s32(ammoSect, "box_size"); D->s_name = ammoSect; D->set_name_replace (""); //. D->s_gameid = u8(GameID()); D->s_RP = 0xff; D->ID = 0xffff; if (ParentID == 0xffffffff) D->ID_Parent = (u16)H_Parent()->ID(); else D->ID_Parent = (u16)ParentID; D->ID_Phantom = 0xffff; D->s_flags.assign (M_SPAWN_OBJECT_LOCAL); D->RespawnTime = 0; l_pA->m_tNodeID = g_dedicated_server ? u32(-1) : ai_location().level_vertex_id(); if(boxCurr == 0xffffffff) boxCurr = l_pA->m_boxSize; while(boxCurr) { l_pA->a_elapsed = (u16)(boxCurr > l_pA->m_boxSize ? l_pA->m_boxSize : boxCurr); NET_Packet P; D->Spawn_Write (P, TRUE); Level().Send (P,net_flags(TRUE)); if(boxCurr > l_pA->m_boxSize) boxCurr -= l_pA->m_boxSize; else boxCurr = 0; } } F_entity_Destroy (D); }
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 }
u16 GetSpawnInfo(NET_Packet &P, u16 &parent_id) { u16 dummy16, id; P.r_begin(dummy16); shared_str s_name; P.r_stringZ(s_name); CSE_Abstract* E = F_entity_Create(*s_name); E->Spawn_Read(P); if (E->s_flags.is(M_SPAWN_UPDATE)) E->UPDATE_Read(P); id = E->ID; parent_id = E->ID_Parent; F_entity_Destroy(E); P.r_pos = 0; return id; }
void CALifeGraphRegistry::detach (CSE_Abstract &object, CSE_ALifeInventoryItem *item, GameGraph::_GRAPH_ID game_vertex_id, bool alife_query, bool remove_children) { #ifdef DEBUG if (psAI_Flags.test(aiALife)) { Msg ("[LSS] Detaching item [%s][%d] from [%s][%d]",item->base()->name_replace(),item->base()->ID,object.name_replace(),object.ID); } #endif if (alife_query) add (smart_cast<CSE_ALifeDynamicObject*>(item),game_vertex_id); else { CSE_ALifeDynamicObject *object = smart_cast<CSE_ALifeDynamicObject*>(item); VERIFY (object); object->m_tGraphID = game_vertex_id; level().add (object); } CSE_ALifeDynamicObject *dynamic_object = smart_cast<CSE_ALifeDynamicObject*>(&object); R_ASSERT2 (!alife_query || dynamic_object,"Cannot detach an item from non-alife object"); VERIFY (alife_query || !smart_cast<CSE_ALifeDynamicObject*>(&object) || (ai().game_graph().vertex(smart_cast<CSE_ALifeDynamicObject*>(&object)->m_tGraphID)->level_id() == level().level_id())); if (dynamic_object) dynamic_object->detach (item,0,alife_query,remove_children); else { #ifdef DEBUG bool value = std::find(object.children.begin(),object.children.end(),item->base()->ID) != object.children.end(); if (!value) { Msg ("! ERROR: can't detach independant object. entity[%s:%d], parent[%s:%d], section[%s]", item->base()->name_replace(),item->base()->ID,object.name_replace(),object.ID, *item->base()->s_name); } #endif // DEBUG // R_ASSERT2 (value,"Can't detach an item which is not on my own"); } }
CSE_Abstract *CALifeSimulatorBase::spawn_item (LPCSTR section, const Fvector &position, u32 level_vertex_id, GameGraph::_GRAPH_ID game_vertex_id, u16 parent_id, bool registration) { CSE_Abstract *abstract = F_entity_Create(section); R_ASSERT3 (abstract,"Cannot find item with section",section); abstract->s_name = section; //. abstract->s_gameid = u8(GAME_SINGLE); abstract->s_RP = 0xff; abstract->ID = server().PerformIDgen(0xffff); abstract->ID_Parent = parent_id; abstract->ID_Phantom = 0xffff; abstract->o_Position = position; abstract->m_wVersion = SPAWN_VERSION; string256 s_name_replace; strcpy_s (s_name_replace,*abstract->s_name); if (abstract->ID < 1000) strcat (s_name_replace,"0"); if (abstract->ID < 100) strcat (s_name_replace,"0"); if (abstract->ID < 10) strcat (s_name_replace,"0"); string16 S1; strcat (s_name_replace,itoa(abstract->ID,S1,10)); abstract->set_name_replace (s_name_replace); CSE_ALifeDynamicObject *dynamic_object = smart_cast<CSE_ALifeDynamicObject*>(abstract); VERIFY (dynamic_object); //оружие спавним с полным магазинои CSE_ALifeItemWeapon* weapon = smart_cast<CSE_ALifeItemWeapon*>(dynamic_object); if(weapon) weapon->a_elapsed = weapon->get_ammo_magsize(); dynamic_object->m_tNodeID = level_vertex_id; dynamic_object->m_tGraphID = game_vertex_id; dynamic_object->m_tSpawnID = u16(-1); if (registration) register_object (dynamic_object,true); dynamic_object->spawn_supplies (); dynamic_object->on_spawn (); // Msg ("LSS : SPAWN : [%s],[%s], level %s",*dynamic_object->s_name,dynamic_object->name_replace(),*ai().game_graph().header().level(ai().game_graph().vertex(dynamic_object->m_tGraphID)->level_id()).name()); return (dynamic_object); }
//процесс отсоединения вещи заключается в спауне новой вещи //в инвентаре и установке соответствующих флагов в родительском //объекте, поэтому функция должна быть переопределена bool CInventoryItem::Detach(const char* item_section_name, bool b_spawn_item) { if (OnClient()) return true; if(b_spawn_item) { CSE_Abstract* D = F_entity_Create(item_section_name); R_ASSERT (D); CSE_ALifeDynamicObject *l_tpALifeDynamicObject = smart_cast<CSE_ALifeDynamicObject*>(D); R_ASSERT (l_tpALifeDynamicObject); l_tpALifeDynamicObject->m_tNodeID = object().ai_location().level_vertex_id(); // Fill D->s_name = item_section_name; D->set_name_replace (""); D->s_gameid = u8(GameID()); D->s_RP = 0xff; D->ID = 0xffff; if (GameID() == GAME_SINGLE) { D->ID_Parent = u16(object().H_Parent()->ID()); } else // i'm not sure this is right { // but it is simpliest way to avoid exception in MP BuyWnd... [Satan] if (object().H_Parent()) D->ID_Parent = u16(object().H_Parent()->ID()); else D->ID_Parent = NULL; } D->ID_Phantom = 0xffff; D->o_Position = object().Position(); D->s_flags.assign (M_SPAWN_OBJECT_LOCAL); D->RespawnTime = 0; // Send NET_Packet P; D->Spawn_Write (P,TRUE); Level().Send (P,net_flags(TRUE)); // Destroy F_entity_Destroy (D); } return true; }
void CPHSkeleton::SpawnCopy() { if(PPhysicsShellHolder()->Local()) { CSE_Abstract* D = F_entity_Create("ph_skeleton_object");//*cNameSect() R_ASSERT (D); ///////////////////////////////////////////////////////////////////////////////////////////// CSE_ALifePHSkeletonObject *l_tpALifePhysicObject = smart_cast<CSE_ALifePHSkeletonObject*>(D); R_ASSERT (l_tpALifePhysicObject); l_tpALifePhysicObject->_flags.set (CSE_PHSkeleton::flSpawnCopy,1); //SetNotNeedSave() ///////////////////////////////////////////////////////////////////////////////////////////// InitServerObject (D); // Send NET_Packet P; D->Spawn_Write (P,TRUE); Level().Send (P,net_flags(TRUE)); // Destroy F_entity_Destroy (D); } }
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("-------------------- "); }
CSE_Abstract *CLevelSpawnConstructor::create_object (IReader *chunk) { NET_Packet net_packet; net_packet.B.count = chunk->length(); chunk->r (net_packet.B.data,net_packet.B.count); // we do not need to close chunk since we iterate on them // chunk->close (); u16 ID; net_packet.r_begin (ID); R_ASSERT2 (M_SPAWN==ID,"ID doesn't match to the spawn-point ID!"); string64 section_name; net_packet.r_stringZ (section_name); CSE_Abstract *abstract = F_entity_Create(section_name); if (!abstract) { string256 temp; sprintf (temp,"Can't create entity '%s' !\n",section_name); R_ASSERT2 (abstract,temp); } abstract->Spawn_Read (net_packet); return (abstract); }
void CInventoryOwner::spawn_supplies () { CGameObject *game_object = smart_cast<CGameObject*>(this); VERIFY (game_object); if (smart_cast<CBaseMonster*>(this)) return; if (use_bolts()) Level().spawn_item ("bolt",game_object->Position(),game_object->ai_location().level_vertex_id(),game_object->ID()); if (!ai().get_alife() && GameID()==GAME_SINGLE) { CSE_Abstract *abstract = Level().spawn_item("device_pda",game_object->Position(),game_object->ai_location().level_vertex_id(),game_object->ID(),true); CSE_ALifeItemPDA *pda = smart_cast<CSE_ALifeItemPDA*>(abstract); R_ASSERT (pda); pda->m_original_owner = (u16)game_object->ID(); NET_Packet P; abstract->Spawn_Write (P,TRUE); Level().Send (P,net_flags(TRUE)); F_entity_Destroy (abstract); } }
CSE_Abstract *CLevel::spawn_item (LPCSTR section, const Fvector &position, u32 level_vertex_id, u16 parent_id, bool return_item) { CSE_Abstract *abstract = F_entity_Create(section); R_ASSERT3 (abstract,"Cannot find item with section",section); CSE_ALifeDynamicObject *dynamic_object = smart_cast<CSE_ALifeDynamicObject*>(abstract); if (dynamic_object && ai().get_level_graph()) { dynamic_object->m_tNodeID = level_vertex_id; if (ai().level_graph().valid_vertex_id(level_vertex_id) && ai().get_game_graph() && ai().get_cross_table()) dynamic_object->m_tGraphID = ai().cross_table().vertex(level_vertex_id).game_vertex_id(); } //оружие спавним с полным магазинои CSE_ALifeItemWeapon* weapon = smart_cast<CSE_ALifeItemWeapon*>(abstract); if(weapon) weapon->a_elapsed = weapon->get_ammo_magsize(); // Fill abstract->s_name = section; abstract->set_name_replace (section); //. abstract->s_gameid = u8(GameID()); abstract->o_Position = position; abstract->s_RP = 0xff; abstract->ID = 0xffff; abstract->ID_Parent = parent_id; abstract->ID_Phantom = 0xffff; abstract->s_flags.assign(M_SPAWN_OBJECT_LOCAL); abstract->RespawnTime = 0; if (!return_item) { NET_Packet P; abstract->Spawn_Write (P,TRUE); Send (P,net_flags(TRUE)); F_entity_Destroy (abstract); return (0); } else return (abstract); }
void SArtefactActivation::SpawnAnomaly() { VERIFY(!ph_world->Processing()); string128 tmp; LPCSTR str = pSettings->r_string("artefact_spawn_zones",*m_af->cNameSect()); VERIFY3(3==_GetItemCount(str),"Bad record format in artefact_spawn_zones",str); float zone_radius = (float)atof(_GetItem(str,1,tmp)); float zone_power = (float)atof(_GetItem(str,2,tmp)); LPCSTR zone_sect = _GetItem(str,0,tmp); //must be last call of _GetItem... (LPCSTR !!!) Fvector pos; m_af->Center(pos); CSE_Abstract *object = Level().spawn_item( zone_sect, pos, m_af->ai_location().level_vertex_id(), 0xffff, true ); CSE_ALifeAnomalousZone* AlifeZone = smart_cast<CSE_ALifeAnomalousZone*>(object); VERIFY(AlifeZone); CShapeData::shape_def _shape; _shape.data.sphere.P.set (0.0f,0.0f,0.0f); _shape.data.sphere.R = zone_radius; _shape.type = CShapeData::cfSphere; AlifeZone->assign_shapes (&_shape,1); AlifeZone->m_maxPower = zone_power; AlifeZone->m_owner_id = m_owner_id; AlifeZone->m_space_restrictor_type = RestrictionSpace::eRestrictorTypeNone; NET_Packet P; object->Spawn_Write (P,TRUE); Level().Send (P,net_flags(TRUE)); F_entity_Destroy (object); #ifdef DEBUG Msg("artefact [%s] spawned a zone [%s] at [%f]", *m_af->cName(), zone_sect, Device.fTimeGlobal); #endif }
void CLevel::cl_Process_Spawn(NET_Packet& P) { // Begin analysis shared_str s_name; P.r_stringZ (s_name); // Create DC (xrSE) CSE_Abstract* E = F_entity_Create (*s_name); R_ASSERT2(E, *s_name); E->Spawn_Read (P); if (E->s_flags.is(M_SPAWN_UPDATE)) E->UPDATE_Read (P); if (!E->match_configuration()) { F_entity_Destroy(E); return; } //------------------------------------------------- //. Msg ("M_SPAWN - %s[%d][%x] - %d %d", *s_name, E->ID, E,E->ID_Parent, Device.dwFrame); //------------------------------------------------- //force object to be local for server client if (OnServer()) { E->s_flags.set(M_SPAWN_OBJECT_LOCAL, TRUE); }; /* game_spawn_queue.push_back(E); if (g_bDebugEvents) ProcessGameSpawns(); /*/ g_sv_Spawn (E); F_entity_Destroy (E); //*/ };
void CALifeGraphRegistry::attach (CSE_Abstract &object, CSE_ALifeInventoryItem *item, GameGraph::_GRAPH_ID game_vertex_id, bool alife_query, bool add_children) { #ifdef DEBUG if (psAI_Flags.test(aiALife)) { Msg ("[LSS] Attaching item [%s][%d] to [%s][%d]",item->base()->name_replace(),item->base()->ID,object.name_replace(),object.ID); } #endif if (alife_query) remove (smart_cast<CSE_ALifeDynamicObject*>(item),game_vertex_id); else level().remove (smart_cast<CSE_ALifeDynamicObject*>(item)); CSE_ALifeDynamicObject *dynamic_object = smart_cast<CSE_ALifeDynamicObject*>(&object); R_ASSERT2 (!alife_query || dynamic_object,"Cannot attach an item to a non-alife object object"); dynamic_object->attach (item,alife_query,add_children); }
void xrServer::Update () { NET_Packet Packet; u32 position; csPlayers.Enter (); VERIFY (verify_entities()); // game update game->ProcessDelayedEvent(); game->Update (); // spawn queue u32 svT = Device.TimerAsync(); while (!(q_respawn.empty() || (svT<q_respawn.begin()->timestamp))) { // get svs_respawn R = *q_respawn.begin(); q_respawn.erase (q_respawn.begin()); // CSE_Abstract* E = ID_to_entity(R.phantom); E->Spawn_Write (Packet,FALSE); u16 ID; Packet.r_begin (ID); R_ASSERT(M_SPAWN==ID); ClientID clientID; clientID.set(0xffff); Process_spawn (Packet,clientID); } // for (u32 client=0; client<net_Players.size(); ++client) { // Initialize process and check for available bandwidth xrClientData* Client = (xrClientData*) net_Players [client]; if (!Client->net_Ready) continue; if (!HasBandwidth(Client) #ifdef DEBUG && !g_sv_SendUpdate #endif ) continue; // Send relevant entities to client // CSE_Abstract* Base = Client->owner; u16 PacketType = M_UPDATE; Packet.w_begin (PacketType); // GameUpdate ++(Client->game_replicate_id); u32 g_it = (Client->game_replicate_id % client_Count()); // u32 g_id = net_Players[g_it]->ID; ClientID g_id = net_Players[g_it]->ID; game->net_Export_Update (Packet,Client->ID,g_id); // if (!Client->flags.bLocal) game->net_Export_GameTime(Packet); if (!Client->flags.bLocal || client_Count() == 1) { #ifdef DEBUG if (g_Dump_Update_Write) Msg("---- UPDATE_Write to %s --- ", *(Client->Name)); #endif // Entities NET_Packet tmpPacket; xrS_entities::iterator I=entities.begin(),E=entities.end(); for (; I!=E; ++I) { CSE_Abstract& Test = *(I->second); if (0==Test.owner) continue; // Phantom(?) if (!Test.net_Ready) continue; if (Test.owner == Client && Client->flags.bLocal) continue; // Can't be relevant if (Test.s_flags.is(M_SPAWN_OBJECT_PHANTOM)) continue; // Surely: phantom tmpPacket.B.count = 0; // write specific data { tmpPacket.w_u16 (Test.ID ); tmpPacket.w_chunk_open8 (position ); Test.UPDATE_Write (tmpPacket ); #ifdef DEBUG if (g_Dump_Update_Write) Msg("* %s : %d", Test.name(), u32(tmpPacket.w_tell()-position)-sizeof(u8)); #endif tmpPacket.w_chunk_close8 (position ); if (Packet.B.count + tmpPacket.B.count < NET_PacketSizeLimit) { Packet.w(tmpPacket.B.data, tmpPacket.B.count); } else { if (Packet.B.count > 2) { // if (!Client->flags.bLocal) // Msg ("- Server Update[%d] to Client : %d", PacketType, Packet.B.count); SendTo (Client->ID,Packet,net_flags(FALSE,TRUE)); } PacketType = M_UPDATE_OBJECTS; Packet.w_begin(PacketType); } } } #ifdef DEBUG if (g_Dump_Update_Write) Msg("----------------------- "); #endif }; if (Packet.B.count > 2) { // if (!Client->flags.bLocal) // Msg ("- Server Update[%d] to Client : %d", PacketType, Packet.B.count); SendTo (Client->ID,Packet,net_flags(FALSE,TRUE)); } } #ifdef DEBUG g_sv_SendUpdate = 0; #endif if (game->sv_force_sync) Perform_game_export(); VERIFY (verify_entities()); //----------------------------------------------------- //Remove any of long time disconnected players for (u32 DI = 0; DI<net_Players_disconnected.size(); DI++) { IClient* CL = net_Players_disconnected[DI]; if (CL->dwTime_LastUpdate+g_sv_Client_Reconnect_Time*60000<Device.dwTimeGlobal) client_Destroy(CL); } //----------------------------------------------------- csPlayers.Leave (); }
BOOL CGameObject::net_Spawn (CSE_Abstract* DC) { VERIFY (!m_spawned); m_spawned = true; m_spawn_time = Device.dwFrame; m_ai_obstacle = xr_new<ai_obstacle>(this); CSE_Abstract *E = (CSE_Abstract*)DC; VERIFY (E); const CSE_Visual *visual = smart_cast<const CSE_Visual*>(E); if (visual) { cNameVisual_set (visual_name(E)); if (visual->flags.test(CSE_Visual::flObstacle)) { ISpatial *self = smart_cast<ISpatial*>(this); self->spatial.type |= STYPE_OBSTACLE; } } // Naming cName_set (E->s_name); cNameSect_set (E->s_name); if (E->name_replace()[0]) cName_set (E->name_replace()); bool demo_spectator = false; if (Level().IsDemoPlayStarted() && E->ID == u16(-1)) { Msg("* Spawning demo spectator ..."); demo_spectator = true; } else { R_ASSERT(Level().Objects.net_Find(E->ID) == NULL); } setID (E->ID); // if (GameID() != eGameIDSingle) // Msg ("CGameObject::net_Spawn -- object %s[%x] setID [%d]", *(E->s_name), this, E->ID); // XForm XFORM().setXYZ (E->o_Angle); Position().set (E->o_Position); #ifdef DEBUG if(ph_dbg_draw_mask1.test(ph_m1_DbgTrackObject)&&stricmp(PH_DBG_ObjectTrackName(),*cName())==0) { Msg("CGameObject::net_Spawn obj %s Position set from CSE_Abstract %f,%f,%f",PH_DBG_ObjectTrackName(),Position().x,Position().y,Position().z); } #endif VERIFY (_valid(renderable.xform)); VERIFY (!fis_zero(DET(renderable.xform))); CSE_ALifeObject *O = smart_cast<CSE_ALifeObject*>(E); if (O && xr_strlen(O->m_ini_string)) { #pragma warning(push) #pragma warning(disable:4238) m_ini_file = xr_new<CInifile>( &IReader ( (void*)(*(O->m_ini_string)), O->m_ini_string.size() ), FS.get_path("$game_config$")->m_Path ); #pragma warning(pop) } m_story_id = ALife::_STORY_ID(-1); if (O) m_story_id = O->m_story_id; // Net params setLocal (E->s_flags.is(M_SPAWN_OBJECT_LOCAL)); if (Level().IsDemoPlay()) //&& OnClient()) { if (!demo_spectator) { setLocal(FALSE); } }; setReady (TRUE); if (!demo_spectator) g_pGameLevel->Objects.net_Register (this); m_server_flags.one (); if (O) { m_server_flags = O->m_flags; if (O->m_flags.is(CSE_ALifeObject::flVisibleForAI)) spatial.type |= STYPE_VISIBLEFORAI; else spatial.type = (spatial.type | STYPE_VISIBLEFORAI) ^ STYPE_VISIBLEFORAI; } reload (*cNameSect()); if(!g_dedicated_server) CScriptBinder::reload (*cNameSect()); reinit (); if(!g_dedicated_server) CScriptBinder::reinit (); #ifdef DEBUG if(ph_dbg_draw_mask1.test(ph_m1_DbgTrackObject)&&stricmp(PH_DBG_ObjectTrackName(),*cName())==0) { Msg("CGameObject::net_Spawn obj %s After Script Binder reinit %f,%f,%f",PH_DBG_ObjectTrackName(),Position().x,Position().y,Position().z); } #endif //load custom user data from server if(!E->client_data.empty()) { // Msg ("client data is present for object [%d][%s], load is processed",ID(),*cName()); IReader ireader = IReader(&*E->client_data.begin(), E->client_data.size()); net_Load (ireader); } else { // Msg ("no client data for object [%d][%s], load is skipped",ID(),*cName()); } // if we have a parent if ( ai().get_level_graph() ) { if ( E->ID_Parent == 0xffff ) { CSE_ALifeObject* l_tpALifeObject = smart_cast<CSE_ALifeObject*>(E); if (l_tpALifeObject && ai().level_graph().valid_vertex_id(l_tpALifeObject->m_tNodeID)) ai_location().level_vertex (l_tpALifeObject->m_tNodeID); else { CSE_Temporary* l_tpTemporary = smart_cast<CSE_Temporary*> (E); if (l_tpTemporary && ai().level_graph().valid_vertex_id(l_tpTemporary->m_tNodeID)) ai_location().level_vertex (l_tpTemporary->m_tNodeID); } if (l_tpALifeObject && ai().game_graph().valid_vertex_id(l_tpALifeObject->m_tGraphID)) ai_location().game_vertex (l_tpALifeObject->m_tGraphID); validate_ai_locations (false); // validating position if ( UsedAI_Locations() && ai().level_graph().inside( ai_location().level_vertex_id(), Position() ) && can_validate_position_on_spawn() ) Position().y = EPS_L + ai().level_graph().vertex_plane_y(*ai_location().level_vertex(),Position().x,Position().z); } else { CSE_ALifeObject* const alife_object = smart_cast<CSE_ALifeObject*>(E); if ( alife_object && ai().level_graph().valid_vertex_id(alife_object->m_tNodeID) ) { ai_location().level_vertex (alife_object->m_tNodeID); ai_location().game_vertex (alife_object->m_tGraphID); } } } inherited::net_Spawn (DC); m_bObjectRemoved = false; spawn_supplies (); #ifdef DEBUG if(ph_dbg_draw_mask1.test(ph_m1_DbgTrackObject)&&stricmp(PH_DBG_ObjectTrackName(),*cName())==0) { Msg("CGameObject::net_Spawn obj %s Before CScriptBinder::net_Spawn %f,%f,%f",PH_DBG_ObjectTrackName(),Position().x,Position().y,Position().z); } BOOL ret =CScriptBinder::net_Spawn(DC); #else return (CScriptBinder::net_Spawn(DC)); #endif #ifdef DEBUG if(ph_dbg_draw_mask1.test(ph_m1_DbgTrackObject)&&stricmp(PH_DBG_ObjectTrackName(),*cName())==0) { Msg("CGameObject::net_Spawn obj %s Before CScriptBinder::net_Spawn %f,%f,%f",PH_DBG_ObjectTrackName(),Position().x,Position().y,Position().z); } return ret; #endif }
void CGameGraphBuilder::load_graph_point (NET_Packet &net_packet) { string256 section_id; u16 id; net_packet.r_begin (id); R_ASSERT (M_SPAWN == id); net_packet.r_stringZ (section_id); // if (xr_strcmp("graph_point",section_id)) // return; CSE_Abstract *entity = F_entity_Create(section_id); if (!entity) { Msg ("Cannot create entity from section %s, skipping",section_id); return; } CSE_ALifeGraphPoint *graph_point = smart_cast<CSE_ALifeGraphPoint*>(entity); if (!graph_point) { F_entity_Destroy (entity); return; } entity->Spawn_Read (net_packet); vertex_type vertex; vertex.tLocalPoint = graph_point->o_Position; // check for duplicate graph point positions { graph_type::const_vertex_iterator I = graph().vertices().begin(); graph_type::const_vertex_iterator E = graph().vertices().end(); for ( ; I != E; ++I) { if ((*I).second->data().tLocalPoint.distance_to_sqr(vertex.tLocalPoint) < EPS_L) { Msg ("! removing graph point [%s][%f][%f][%f] because it is too close to the another graph point",entity->name_replace(),VPUSH(entity->o_Position)); return; } } } vertex.tGlobalPoint = graph_point->o_Position; vertex.tNodeID = level_graph().valid_vertex_position(vertex.tLocalPoint) ? level_graph().vertex_id(vertex.tLocalPoint) : u32(-1); if (!level_graph().valid_vertex_id(vertex.tNodeID)) { Msg ("! removing graph point [%s][%f][%f][%f] because it is outside of the AI map",entity->name_replace(),VPUSH(entity->o_Position)); return; } { graph_type::const_vertex_iterator I = graph().vertices().begin(); graph_type::const_vertex_iterator E = graph().vertices().end(); for ( ; I != E; ++I) { if ((*I).second->data().tNodeID == vertex.tNodeID) { Msg ("! removing graph point [%s][%f][%f][%f] because it has the same AI node as another graph point",entity->name_replace(),VPUSH(entity->o_Position)); return; } } } vertex.tNeighbourCount = 0; Memory.mem_copy (vertex.tVertexTypes,graph_point->m_tLocations,GameGraph::LOCATION_TYPE_COUNT*sizeof(GameGraph::_LOCATION_ID)); vertex.tLevelID = 0; vertex.tDeathPointCount = 0; vertex.dwPointOffset = 0; graph().add_vertex (vertex,graph().vertices().size()); F_entity_Destroy (entity); }
CLevelGameGraph ( LPCSTR graph_file_name, LPCSTR raw_cross_table_file_name, CGameGraph::SLevel *tLevel, LPCSTR S, u32 dwOffset, u32 dwLevelID, CInifile *Ini ) { m_tLevel = *tLevel; m_dwOffset = dwOffset; m_tpLevelPoints.clear (); FILE_NAME caFileName; // loading graph strcpy_s (caFileName,graph_file_name); m_tpGraph = new CGameGraph(caFileName); strcpy_s (caFileName,raw_cross_table_file_name); CGameLevelCrossTable *l_tpCrossTable = new CGameLevelCrossTable(caFileName); CLevelGraph *l_tpAI_Map = new CLevelGraph(S); VERIFY2 (l_tpCrossTable->header().level_guid() == l_tpAI_Map->header().guid(), "cross table doesn't correspond to the AI-map, rebuild graph!"); VERIFY2 (l_tpCrossTable->header().game_guid() == m_tpGraph->header().guid(), "cross table doesn't correspond to the graph, rebuild graph!"); VERIFY2 (m_tpGraph->header().level(GameGraph::_LEVEL_ID(0)).guid() == l_tpAI_Map->header().guid(), "cross table doesn't correspond to the AI-map, rebuild graph!"); VERIFY (l_tpAI_Map->header().vertex_count() == l_tpCrossTable->header().level_vertex_count()); VERIFY (m_tpGraph->header().vertex_count() == l_tpCrossTable->header().game_vertex_count()); tLevel->m_guid = l_tpAI_Map->header().guid(); { for (GameGraph::_GRAPH_ID i=0, n = m_tpGraph->header().vertex_count(); i<n; ++i) if ((!l_tpAI_Map->valid_vertex_id(m_tpGraph->vertex(i)->level_vertex_id()) || (l_tpCrossTable->vertex(m_tpGraph->vertex(i)->level_vertex_id()).game_vertex_id() != i) || !l_tpAI_Map->inside(m_tpGraph->vertex(i)->level_vertex_id(),m_tpGraph->vertex(i)->level_point()))) { Msg ("! Graph doesn't correspond to the cross table"); R_ASSERT2 (false,"Graph doesn't correspond to the cross table"); } } m_tpVertices.resize (m_tpGraph->header().vertex_count()); GRAPH_VERTEX_IT B = m_tpVertices.begin(); GRAPH_VERTEX_IT I = B; GRAPH_VERTEX_IT E = m_tpVertices.end(); for ( ; I != E; I++) { (*I).tLocalPoint = m_tpGraph->vertex(int(I - B))->level_point(); (*I).tGlobalPoint.add (m_tpGraph->vertex(int(I - B))->game_point(),m_tLevel.offset()); (*I).tLevelID = dwLevelID; (*I).tNodeID = m_tpGraph->vertex(int(I - B))->level_vertex_id(); Memory.mem_copy ((*I).tVertexTypes,m_tpGraph->vertex(int(I - B))->vertex_type(),GameGraph::LOCATION_TYPE_COUNT*sizeof(GameGraph::_LOCATION_ID)); (*I).tNeighbourCount = m_tpGraph->vertex(int(I - B))->edge_count(); CGameGraph::const_iterator b,i,e; m_tpGraph->begin (int(I - B),i,e); (*I).tpaEdges = (CGameGraph::CEdge*)xr_malloc((*I).tNeighbourCount*sizeof(CGameGraph::CEdge)); b = i; for ( ; i != e; ++i) { GameGraph::CEdge &edge = (*I).tpaEdges[i - b]; edge = *i; VERIFY ((edge.vertex_id() + dwOffset) < (u32(1) << (8*sizeof(GameGraph::_GRAPH_ID)))); edge.m_vertex_id = (GameGraph::_GRAPH_ID)(edge.m_vertex_id + dwOffset); } (*I).dwPointOffset = 0; vfGenerateDeathPoints (int(I - B),l_tpCrossTable,l_tpAI_Map,(*I).tDeathPointCount); } xr_delete (l_tpCrossTable); xr_delete (l_tpAI_Map); // updating cross-table { strcpy_s (caFileName,raw_cross_table_file_name); CGameLevelCrossTable *tpCrossTable = new CGameLevelCrossTable(caFileName); xr_vector<CGameLevelCrossTable::CCell> tCrossTableUpdate; tCrossTableUpdate.resize(tpCrossTable->header().level_vertex_count()); for (int i=0; i<(int)tpCrossTable->header().level_vertex_count(); i++) { tCrossTableUpdate[i] = tpCrossTable->vertex(i); VERIFY (u32(tCrossTableUpdate[i].tGraphIndex) < tpCrossTable->header().game_vertex_count()); tCrossTableUpdate[i].tGraphIndex = tCrossTableUpdate[i].tGraphIndex + (GameGraph::_GRAPH_ID)dwOffset; } CGameLevelCrossTable::CHeader tCrossTableHeader; tCrossTableHeader.dwVersion = XRAI_CURRENT_VERSION; tCrossTableHeader.dwNodeCount = tpCrossTable->m_tCrossTableHeader.dwNodeCount; tCrossTableHeader.dwGraphPointCount = tpCrossTable->m_tCrossTableHeader.dwGraphPointCount; tCrossTableHeader.m_level_guid = tpCrossTable->m_tCrossTableHeader.m_level_guid; tCrossTableHeader.m_game_guid = tGraphHeader.m_guid; xr_delete (tpCrossTable); m_cross_table.w(&tCrossTableHeader,sizeof(tCrossTableHeader)); for (int i=0; i<(int)tCrossTableHeader.dwNodeCount; i++) m_cross_table.w(&(tCrossTableUpdate[i]),sizeof(tCrossTableUpdate[i])); } // fill vertex map { string_path fName; strconcat (sizeof(fName),fName,S,"level.spawn"); IReader *F = FS.r_open(fName); u32 id; IReader *O = F->open_chunk_iterator(id); for (int i=0; O; O = F->open_chunk_iterator(id,O)) { NET_Packet P; P.B.count = O->length(); O->r (P.B.data,P.B.count); u16 ID; P.r_begin (ID); R_ASSERT (M_SPAWN==ID); P.r_stringZ (fName); CSE_Abstract *E = F_entity_Create(fName); R_ASSERT3 (E,"Can't create entity.",fName); // E->Spawn_Read (P); CSE_ALifeGraphPoint *tpGraphPoint = smart_cast<CSE_ALifeGraphPoint*>(E); if (tpGraphPoint) { E->Spawn_Read (P); Fvector tVector; tVector = tpGraphPoint->o_Position; GameGraph::_GRAPH_ID tGraphID = GameGraph::_GRAPH_ID(-1); float fMinDistance = 1000000.f; { GRAPH_VERTEX_IT B = m_tpVertices.begin(); GRAPH_VERTEX_IT I = B; GRAPH_VERTEX_IT E = m_tpVertices.end(); for ( ; I != E; I++) { float fDistance = (*I).tLocalPoint.distance_to(tVector); if (fDistance < fMinDistance) { fMinDistance = fDistance; tGraphID = GameGraph::_GRAPH_ID(I - B); if (fMinDistance < EPS_L) break; } } } if (fMinDistance < EPS_L) { SConnectionVertex T; LPSTR S; S = xr_strdup(tpGraphPoint->name_replace()); T.caConnectName = xr_strdup(*tpGraphPoint->m_caConnectionPointName); T.dwLevelID = dwfGetIDByLevelName(Ini,*tpGraphPoint->m_caConnectionLevelName); // T.tGraphID = (GameGraph::_GRAPH_ID)i; // T.tOldGraphID = tGraphID; T.tOldGraphID = (GameGraph::_GRAPH_ID)i; T.tGraphID = tGraphID; bool ok = true; VERTEX_MAP::const_iterator II = m_tVertexMap.begin(); VERTEX_MAP::const_iterator EE = m_tVertexMap.end(); for ( ; II != EE; ++II) if (T.tOldGraphID == (*II).second.tOldGraphID) { ok = false; Msg ("Graph point %s is removed,because it has the same position as some another graph point",E->name_replace()); break; } if (ok) { m_tVertexMap.insert (mk_pair(S,T)); i++; } } } F_entity_Destroy (E); } if (i != m_tpGraph->header().vertex_count()) Msg ("Graph for the level %s doesn't correspond to the graph points from Level Editor! (%d : %d)",*m_tLevel.name(),i,m_tpGraph->header().vertex_count()); VERTEX_MAP::const_iterator I = m_tVertexMap.begin(); VERTEX_MAP::const_iterator E = m_tVertexMap.end(); for ( ; I != E; ++I) { R_ASSERT3 (!xr_strlen((*I).second.caConnectName) || ((*I).second.tGraphID < m_tpVertices.size()),"Rebuild graph for the level",*m_tLevel.name()); } // VERIFY3 (i == m_tpGraph->header().vertex_count(), "Rebuild graph for the level ",m_tLevel.name()); O->close (); FS.r_close (F); } };
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; } }