// netScriptMgrBase.cpp // // Copyright (C) 1999-2009 Rockstar Games. All Rights Reserved. // #include "script/handlers/GameScriptMgr.h" // rage includes #include "bank/bank.h" #include "grcore/debugdraw.h" #include "fwsys/timer.h" #include "fwscript/scriptguid.h" // game includes #include "modelinfo/PedModelInfo.h" #include "modelinfo/VehicleModelInfo.h" #include "network/Arrays/NetworkArrayMgr.h" #include "network/Bandwidth/NetworkBandwidthManager.h" #include "network/Events/NetworkEventTypes.h" #include "network/NetworkInterface.h" #include "network/Network.h" #include "network/Objects/NetworkObjectMgr.h" #include "network/Players/NetGamePlayer.h" #include "network/Sessions/NetworkSession.h" #include "peds/ped.h" #include "peds/PlayerInfo.h" #include "scene/streamer/StreamVolume.h" #include "scene/world/GameWorld.h" #include "script/handlers/GameScriptEntity.h" #include "script/handlers/GameScriptHandler.h" #include "script/handlers/GameScriptHandlerNetwork.h" #include "script/handlers/GameScriptResources.h" #include "script/gta_thread.h" #include "script/script.h" #include "script/script_channel.h" #include "script/streamedscripts.h" #include "streaming/populationstreaming.h" #include "streaming/streamingdebug.h" #include "streaming/streamingengine.h" #include "streaming/streaminginfo.h" #include "vfx/misc/MovieManager.h" #include "Event/EventGroup.h" #if __DEV #include "network/NetworkInterface.h" #include "network/objects/NetworkObjectMgr.h" #include "network/Players/NetworkPlayerMgr.h" #include "rline/rlgamerinfo.h" #endif SCRIPT_OPTIMISATIONS() NETWORK_OPTIMISATIONS() XPARAM(override_script); XPARAM(dontCrashOnScriptValidation); PARAM(scriptLogMemoryPeaks, "[MEMORY] Log the memory peaks for the scripts physical and virtual usage."); #if __BANK bkCombo* CGameScriptHandlerMgr::ms_pHandlerCombo = NULL; const char* CGameScriptHandlerMgr::ms_Handlers[CGameScriptHandler::MAX_NUM_SCRIPT_HANDLERS]; unsigned int CGameScriptHandlerMgr::ms_NumHandlers = 0; int CGameScriptHandlerMgr::ms_HandlerComboIndex = 0; bool CGameScriptHandlerMgr::ms_DisplayHandlerInfo = false; bool CGameScriptHandlerMgr::ms_DisplayAllMPHandlers = false; #endif // __BANK u32 CGameScriptHandlerMgr::ms_validNetworkScriptHashes[] = { ATSTRINGHASH("act_cinema", 0x8961d933), ATSTRINGHASH("activity_creator_prototype_launcher", 0x4fb9c566), ATSTRINGHASH("am_agency_suv", 0x12117cf0), ATSTRINGHASH("am_airstrike", 0x060cd733), ATSTRINGHASH("am_ammo_drop", 0xa7c6571d), ATSTRINGHASH("am_armwrestling", 0x3c77f4aa), ATSTRINGHASH("am_armwrestling_apartment", 0x69bdb2d8), ATSTRINGHASH("am_armybase", 0x4efb7452), ATSTRINGHASH("am_backup_heli", 0xddb3aada), ATSTRINGHASH("am_beach_washup_cinematic", 0xE720B4A4), ATSTRINGHASH("am_boat_taxi", 0xd8133249), ATSTRINGHASH("am_bru_box", 0x48600c01), ATSTRINGHASH("am_car_mod_tut", 0x83a66932), ATSTRINGHASH("am_casino_limo", 0x3A5BBA05), ATSTRINGHASH("am_casino_luxury_car", 0xb93135a6), ATSTRINGHASH("am_casino_peds", 0x1C0F96E7), ATSTRINGHASH("am_challenges", 0x59de0357), ATSTRINGHASH("am_cp_collection", 0x0544b90b), ATSTRINGHASH("am_crate_drop", 0x240f2e7b), ATSTRINGHASH("am_criminal_damage", 0xc62526f5), ATSTRINGHASH("am_darts", 0x2a10cf0c), ATSTRINGHASH("am_darts_apartment", 0xab14f1f2), ATSTRINGHASH("am_dead_drop", 0x9497de5d), ATSTRINGHASH("am_destroy_veh", 0xeab28126), ATSTRINGHASH("am_distract_cops", 0x81dc676e), ATSTRINGHASH("am_doors", 0xc80b3112), ATSTRINGHASH("am_ferriswheel", 0xe4e0cbce), ATSTRINGHASH("am_ga_pickups", 0xa77e5305), ATSTRINGHASH("am_gang_call", 0x0266ce78), ATSTRINGHASH("am_heist_int", 0xc74cc971), ATSTRINGHASH("am_heist_island_plane_land_cinematic", 0x560E198), ATSTRINGHASH("am_heist_island_plane_take_off_cinematic", 0x1984610C), ATSTRINGHASH("am_heli_taxi", 0x4840fef0), ATSTRINGHASH("am_hi_plane_take_off_cinematic", 0x418795CC), ATSTRINGHASH("am_hi_plane_land_cinematic", 0x9782808A), ATSTRINGHASH("am_hold_up", 0x0c6dac46), ATSTRINGHASH("am_hot_property", 0x95335193), ATSTRINGHASH("am_hot_target", 0x3c04751e), ATSTRINGHASH("am_hs4_isd_take_vel", 0x9B9330A1), ATSTRINGHASH("am_hs4_lsa_land_nimb_arrive",0x2941F161), ATSTRINGHASH("am_hs4_lsa_land_vel", 0xC288DE3E), ATSTRINGHASH("am_hs4_lsa_take_vel", 0x7BD40072), ATSTRINGHASH("am_hs4_nimb_isd_lsa_leave", 0x85398B65), ATSTRINGHASH("am_hs4_nimb_lsa_isd_leave", 0xC2F73739), ATSTRINGHASH("am_hs4_nimb_lsa_isd_arrive", 0x39DB7A9C), ATSTRINGHASH("am_hs4_vel_lsa_isd", 0x1FF4E6A9), ATSTRINGHASH("am_hunt_the_beast", 0x7e76f859), ATSTRINGHASH("am_lsia_land_cinematic", 0xAEA5F533), ATSTRINGHASH("am_imp_exp", 0x1961b859), ATSTRINGHASH("am_island_backup_heli", 0x68867AF7), ATSTRINGHASH("am_joyrider", 0xe1bc7b99), ATSTRINGHASH("am_kill_list", 0xa8d5e84c), ATSTRINGHASH("am_king_of_the_castle", 0x7a9a3349), ATSTRINGHASH("am_launcher", 0x57c919e1), ATSTRINGHASH("am_lester_cut", 0x1edd4ad1), ATSTRINGHASH("am_lowrider_int", 0x4250943e), ATSTRINGHASH("am_lsia_take_off_cinematic", 0x849DBDF1), ATSTRINGHASH("am_luxury_showroom", 0xf4ab6fb5), ATSTRINGHASH("am_mission_launch", 0x8fa27332), ATSTRINGHASH("am_mp_acid_lab", 0x480e7a1a), ATSTRINGHASH("am_mp_arc_cab_manager", 0x4ee41f75), ATSTRINGHASH("am_mp_arcade", 0x500b732f), ATSTRINGHASH("am_mp_arcade_love_meter", 0x39245013), ATSTRINGHASH("am_mp_arcade_strength_test", 0x7488fe33), ATSTRINGHASH("am_mp_arcade_fortune_teller", 0xf4c6d398), ATSTRINGHASH("am_mp_arcade_claw_crane", 0xa54f9693), ATSTRINGHASH("am_mp_arena_box", 0x8C9C5FB8), ATSTRINGHASH("am_mp_arena_garage", 0x26EBCE20), ATSTRINGHASH("am_mp_armory_aircraft", 0x9c6f5716), ATSTRINGHASH("am_mp_armory_truck", 0x5b9b0272), ATSTRINGHASH("am_mp_auto_shop", 0xba18b4c), ATSTRINGHASH("am_mp_biker_warehouse", 0x504ebb57), ATSTRINGHASH("am_mp_boardroom_seating", 0x70fc43a2), ATSTRINGHASH("am_mp_bunker", 0x89d486f8), ATSTRINGHASH("am_mp_business_hub", 0xC85B5BEF), ATSTRINGHASH("am_mp_car_meet_property", 0x2385bdc4), ATSTRINGHASH("am_mp_car_meet_sandbox", 0x5158A9E4), ATSTRINGHASH("am_mp_casino", 0x7166BD4A), ATSTRINGHASH("am_mp_casino_apartment", 0xD76D873D), ATSTRINGHASH("am_mp_casino_dj_room", 0x12daa5f1), ATSTRINGHASH("am_mp_casino_nightclub", 0x700869D), ATSTRINGHASH("am_mp_casino_valet_garage", 0x6cc29c20), ATSTRINGHASH("am_mp_creator_aircraft", 0xd4dddde0), ATSTRINGHASH("am_mp_creator_trailer", 0xcbd05bfb), ATSTRINGHASH("am_mp_defunct_base", 0xcab8a943), ATSTRINGHASH("am_mp_dj", 0xb369e47f), ATSTRINGHASH("am_mp_drone", 0x230D1E0D), ATSTRINGHASH("am_mp_fixer_hq", 0x995f4ea5), ATSTRINGHASH("am_mp_garage_control", 0xfd4b7439), ATSTRINGHASH("am_mp_hacker_truck", 0x349B7463), ATSTRINGHASH("am_mp_hangar", 0xefc0d4ec), ATSTRINGHASH("am_mp_ie_warehouse", 0xb7a8f8db), ATSTRINGHASH("am_mp_island", 0x1C2A2AF8), ATSTRINGHASH("am_mp_juggalo_hideout", 0xedfd243e), ATSTRINGHASH("am_mp_multistorey_garage", 0x679a06a1), ATSTRINGHASH("am_mp_music_studio", 0xfd3397ae), ATSTRINGHASH("am_mp_mission", 0x626b9c51), ATSTRINGHASH("am_mp_nightclub", 0x8C56B7FE), ATSTRINGHASH("am_mp_orbital_cannon", 0x6c25dccb), ATSTRINGHASH("am_mp_peds", 0xBC350B6D), ATSTRINGHASH("am_mp_property_ext", 0x72ee09f2), ATSTRINGHASH("am_mp_property_int", 0x95b61b3c), ATSTRINGHASH("am_mp_rc_vehicle", 0xd1894172), ATSTRINGHASH("am_mp_shooting_range", 0xaa3368fc), ATSTRINGHASH("am_mp_simeon_showroom", 0x1ed5a03d), ATSTRINGHASH("am_mp_smoking_activity", 0x121a26b9), ATSTRINGHASH("am_mp_smpl_interior_ext", 0xe0a7b7ad), ATSTRINGHASH("am_mp_smpl_interior_int", 0x05973129), ATSTRINGHASH("am_mp_solomon_office", 0x220A2BF3), ATSTRINGHASH("am_mp_submarine", 0xE16957F2), ATSTRINGHASH("am_mp_vehicle_reward", 0x692F8E30), ATSTRINGHASH("am_mp_vehicle_weapon", 0x322bad51), ATSTRINGHASH("am_mp_warehouse", 0x2262ddf0), ATSTRINGHASH("am_mp_yacht", 0xc930c939), ATSTRINGHASH("am_npc_invites", 0x529d545f), ATSTRINGHASH("am_pass_the_parcel", 0x8dd957aa), ATSTRINGHASH("am_patrick", 0xb70b6f22), ATSTRINGHASH("am_penned_in", 0x9fd87720), ATSTRINGHASH("am_penthouse_peds", 0x5c0238a9), ATSTRINGHASH("am_plane_takedown", 0x990a9196), ATSTRINGHASH("am_prison", 0x70da15b8), ATSTRINGHASH("am_prostitute", 0x62773681), ATSTRINGHASH("am_rollercoaster", 0xa8f75ae1), ATSTRINGHASH("am_rontrevor_cut", 0xe895e13e), ATSTRINGHASH("am_taxi", 0x455fe4de), ATSTRINGHASH("am_vehicle_spawn", 0xb726fc82), ATSTRINGHASH("apartment_minigame_launcher", 0xc4382362), ATSTRINGHASH("arcade_seating", 0xA0B1239B), ATSTRINGHASH("arena_box_bench_seats", 0x63905267), ATSTRINGHASH("arena_carmod", 0xdafc0911), ATSTRINGHASH("arena_workshop_seats", 0x7030f53f), ATSTRINGHASH("armory_aircraft_carmod", 0x78ddb08f), ATSTRINGHASH("atm_trigger", 0x1ab4168d), ATSTRINGHASH("auto_shop_seating", 0x7A4A46AE), ATSTRINGHASH("base_carmod", 0x00e813dd), ATSTRINGHASH("base_corridor_seats", 0x16833adb), ATSTRINGHASH("base_entrance_seats", 0x8d055fe8), ATSTRINGHASH("base_heist_seats", 0xc5c0aa16), ATSTRINGHASH("base_lounge_seats", 0xddf302ec), ATSTRINGHASH("base_quaters_seats", 0x01aa9982), ATSTRINGHASH("base_reception_seats", 0x6b938b1b), ATSTRINGHASH("beach_exterior_seating", 0x3DE90B7C), ATSTRINGHASH("blackjack", 0xD378365E), ATSTRINGHASH("business_battles", 0xA6526FA9), ATSTRINGHASH("business_battles_defend", 0x6FA239A5), ATSTRINGHASH("business_battles_sell", 0xF3F871DA), ATSTRINGHASH("business_hub_carmod", 0x6E6F052), ATSTRINGHASH("business_hub_garage_seats", 0x7d5dee96), ATSTRINGHASH("camhedz_arcade", 0xE81212C6), ATSTRINGHASH("car_meet_carmod", 0xBB3D7E9D), ATSTRINGHASH("car_meet_exterior_seating", 0x581858D7), ATSTRINGHASH("car_meet_interior_seating", 0xAEC3C263), ATSTRINGHASH("carmod_shop", 0x1dc6b680), ATSTRINGHASH("cashisking", 0xaa69fdd3), ATSTRINGHASH("casino_bar_seating", 0x6e6fc95f), ATSTRINGHASH("casino_exterior_seating", 0x38C0DADF), ATSTRINGHASH("casino_interior_seating", 0xc2c12122), ATSTRINGHASH("casino_lucky_wheel", 0xbdf0ccff), ATSTRINGHASH("casino_main_lounge_seating", 0x3339c03a), ATSTRINGHASH("casino_nightclub_seating", 0xF8881E62), ATSTRINGHASH("casino_penthouse_seating", 0x5a1b8571), ATSTRINGHASH("casino_slots", 0x5f1459d7), ATSTRINGHASH("casinoroulette", 0x05e86d0d), ATSTRINGHASH("clothes_shop_mp", 0xc0f0bbc3), ATSTRINGHASH("copscrooks_holdup_instance", 0x70871f89), ATSTRINGHASH("copscrooks_job_instance", 0xF28DD9D9), ATSTRINGHASH("dont_cross_the_line", 0x85db1b5a), ATSTRINGHASH("endlesswinter", 0xe237f748), ATSTRINGHASH("fixer_hq_carmod", 0x41f74a04), ATSTRINGHASH("fixer_hq_seating", 0x1a207399), ATSTRINGHASH("fixer_hq_seating_op_floor", 0xc6bd80fc), ATSTRINGHASH("fixer_hq_seating_pq", 0x15dac453), ATSTRINGHASH("fm_bj_race_controler", 0xbe3e7d03), ATSTRINGHASH("fm_content_acid_lab_sell", 0x92772b1f), ATSTRINGHASH("fm_content_acid_lab_setup", 0x61ff0c31), ATSTRINGHASH("fm_content_acid_lab_source", 0x701beffb), ATSTRINGHASH("fm_content_auto_shop_delivery", 0xfc4970dc), ATSTRINGHASH("fm_content_ammunation", 0x4537E4CA), ATSTRINGHASH("fm_content_bank_shootout", 0x3f21df40), ATSTRINGHASH("fm_content_bar_resupply", 0x2363D09D), ATSTRINGHASH("fm_content_business_battles", 0x62EA78D0), ATSTRINGHASH("fm_content_bike_shop_delivery", 0x3ff69732), ATSTRINGHASH("fm_content_cargo", 0x035d0edc), ATSTRINGHASH("fm_content_cerberus", 0xe05f49f1), ATSTRINGHASH("fm_content_club_management", 0xa14222b3), ATSTRINGHASH("fm_content_club_odd_jobs", 0xdf2e4655), ATSTRINGHASH("fm_content_club_source", 0x2b88e6a1), ATSTRINGHASH("fm_content_clubhouse_contracts", 0x5a98b2be), ATSTRINGHASH("fm_content_convoy", 0x4b293c1f), ATSTRINGHASH("fm_content_crime_scene", 0x5CA3449B), ATSTRINGHASH("fm_content_dispatch", 0xBC0EB82E), ATSTRINGHASH("fm_content_drug_lab_work", 0x0bf710af), ATSTRINGHASH("fm_content_drug_vehicle", 0x5B3F117), ATSTRINGHASH("fm_content_export_cargo", 0xee7c5974), ATSTRINGHASH("fm_content_golden_gun", 0xA7CBD213), ATSTRINGHASH("fm_content_gunrunning", 0x1a160b48), ATSTRINGHASH("fm_content_island_dj", 0xBE590E09), ATSTRINGHASH("fm_content_island_heist", 0xF2A65E92), ATSTRINGHASH("fm_content_metal_detector", 0xEEDDF72E), ATSTRINGHASH("fm_content_movie_props", 0x9BF88E0E), ATSTRINGHASH("fm_content_payphone_hit", 0xF7F8D71A), ATSTRINGHASH("fm_content_payphone_intro", 0x2F916684), ATSTRINGHASH("fm_content_phantom_car", 0xF699F9CD), ATSTRINGHASH("fm_content_security_contract", 0x26EA9F66), ATSTRINGHASH("fm_content_serve_and_protect", 0xFF78189D), ATSTRINGHASH("fm_content_sightseeing", 0x975e5d41), ATSTRINGHASH("fm_content_skydive", 0x3d946731), ATSTRINGHASH("fm_content_slasher", 0xD45729DB), ATSTRINGHASH("fm_content_smuggler_plane", 0xb8140067), ATSTRINGHASH("fm_content_smuggler_trail", 0x277b17b6), ATSTRINGHASH("fm_content_source_research", 0xe3e84b48), ATSTRINGHASH("fm_content_sprint", 0x51C051E7), ATSTRINGHASH("fm_content_stash_house", 0x29513dec), ATSTRINGHASH("fm_content_taxi_driver", 0xb7782ad4), ATSTRINGHASH("fm_content_tuner_robbery", 0xB5278C95), ATSTRINGHASH("fm_content_vehicle_list", 0x9E4931D3), ATSTRINGHASH("fm_content_vip_contract_1", 0x75C7E0D3), ATSTRINGHASH("fm_content_xmas_mugger", 0x6cfc0084), ATSTRINGHASH("fm_deathmatch_controler", 0xe62128cb), ATSTRINGHASH("fm_hideout_controler", 0x055ede8c), ATSTRINGHASH("fm_hold_up_tut", 0x75804856), ATSTRINGHASH("fm_horde_controler", 0x514a6d17), ATSTRINGHASH("fm_impromptu_dm_controler", 0xad453307), ATSTRINGHASH("fm_intro", 0xefe7c380), ATSTRINGHASH("fm_mission_controller", 0x6c2ce225), ATSTRINGHASH("fm_mission_controller_2020", 0xBF461AD0), ATSTRINGHASH("fm_race_controler", 0xeb004e0e), ATSTRINGHASH("fm_street_dealer", 0xbc8a3c3e), ATSTRINGHASH("fm_survival_controller", 0x1D477306), ATSTRINGHASH("fmmc_launcher", 0xa3fb8a5e), ATSTRINGHASH("fmmc_playlist_controller", 0x56e10d97), ATSTRINGHASH("freemode", 0xc875557d), ATSTRINGHASH("freemodearcade", 0xff3cad99), ATSTRINGHASH("freemodeLite", 0x1CA0CF36), ATSTRINGHASH("gb_airfreight", 0x59e32892), ATSTRINGHASH("gb_amphibious_assault", 0x31dc55bb), ATSTRINGHASH("gb_assault", 0xc3961a05), ATSTRINGHASH("gb_bank_job", 0x929CEFED), ATSTRINGHASH("gb_bellybeast", 0xd4d41110), ATSTRINGHASH("gb_biker_bad_deal", 0x2334f600), ATSTRINGHASH("gb_biker_burn_assets", 0xd9ee6178), ATSTRINGHASH("gb_biker_contraband_defend", 0x56a1412c), ATSTRINGHASH("gb_biker_contraband_sell", 0xdffc4863), ATSTRINGHASH("gb_biker_contract_killing", 0x1c8463b3), ATSTRINGHASH("gb_biker_criminal_mischief", 0x3e927a10), ATSTRINGHASH("gb_biker_destroy_vans", 0x6a5fc4cc), ATSTRINGHASH("gb_biker_driveby_assassin", 0x2898b9e6), ATSTRINGHASH("gb_biker_free_prisoner", 0x966afe8f), ATSTRINGHASH("gb_biker_joust", 0xa9165795), ATSTRINGHASH("gb_biker_last_respects", 0x63389db5), ATSTRINGHASH("gb_biker_race_p2p", 0xd4caa546), ATSTRINGHASH("gb_biker_rescue_contact", 0x8403149b), ATSTRINGHASH("gb_biker_rippin_it_up", 0x64ad4306), ATSTRINGHASH("gb_biker_safecracker", 0xfc5f9481), ATSTRINGHASH("gb_biker_search_and_destroy", 0x6d5e1016), ATSTRINGHASH("gb_biker_shuttle", 0xd41e6264), ATSTRINGHASH("gb_biker_stand_your_ground", 0x9e4e7734), ATSTRINGHASH("gb_biker_steal_bikes", 0xdd56dc62), ATSTRINGHASH("gb_biker_unload_weapons", 0xb31a0796), ATSTRINGHASH("gb_biker_wheelie_rider", 0xb3e837ff), ATSTRINGHASH("gb_carjacking", 0xa29e8148), ATSTRINGHASH("gb_cashing_out", 0xaa79b0eb), ATSTRINGHASH("gb_casino", 0x13645DC3), ATSTRINGHASH("gb_casino_heist", 0x8ef7e740), ATSTRINGHASH("gb_collect_money", 0x206c6c4b), ATSTRINGHASH("gb_contraband_buy", 0xeb04de05), ATSTRINGHASH("gb_contraband_defend", 0x2055a1a4), ATSTRINGHASH("gb_contraband_sell", 0x7b3e31d2), ATSTRINGHASH("gb_data_hack", 0x45154B11), ATSTRINGHASH("gb_deathmatch", 0x9f42b34b), ATSTRINGHASH("gb_delivery", 0x6e9955cb), ATSTRINGHASH("gb_finderskeepers", 0xa6320c4d), ATSTRINGHASH("gb_fivestar", 0x8dc43a99), ATSTRINGHASH("gb_fortified", 0x51925081), ATSTRINGHASH("gb_fragile_goods", 0x2382af03), ATSTRINGHASH("gb_fully_loaded", 0xda508d57), ATSTRINGHASH("gb_gangops", 0xfb30320a), ATSTRINGHASH("gb_gang_ops_planning", 0x6d20caab), ATSTRINGHASH("gb_gunrunning", 0x8cd0bff0), ATSTRINGHASH("gb_gunrunning_defend", 0x14b421aa), ATSTRINGHASH("gb_gunrunning_delivery", 0x29a28ed8), ATSTRINGHASH("gb_headhunter", 0x71c13b55), ATSTRINGHASH("gb_hunt_the_boss", 0x52d21ba4), ATSTRINGHASH("gb_ie_delivery_cutscene", 0x9114379b), ATSTRINGHASH("gb_illicit_goods_resupply", 0x9d9d13ec), ATSTRINGHASH("gb_infiltration", 0x610BE6A0), ATSTRINGHASH("gb_jewel_store_grab", 0xB0BCBA60), ATSTRINGHASH("gb_ploughed", 0x14611265), ATSTRINGHASH("gb_point_to_point", 0x45bd5447), ATSTRINGHASH("gb_ramped_up", 0x506cc782), ATSTRINGHASH("gb_rob_shop", 0xb4901ab2), ATSTRINGHASH("gb_salvage", 0x4eff43a1), ATSTRINGHASH("gb_security_van", 0xE8DA8C5F), ATSTRINGHASH("gb_sightseer", 0x724eba87), ATSTRINGHASH("gb_smuggler", 0xabd3de17), ATSTRINGHASH("gb_stockpiling", 0xf60a885b), ATSTRINGHASH("gb_target_pursuit", 0x5D94ED7B), ATSTRINGHASH("gb_terminate", 0xf2095bfd), ATSTRINGHASH("gb_transporter", 0x0b87dc63), ATSTRINGHASH("gb_vehicle_export", 0xd9751e61), ATSTRINGHASH("gb_velocity", 0x5f6c2123), ATSTRINGHASH("gb_yacht_rob", 0x7fa4662e), ATSTRINGHASH("ggsm_arcade", 0x2AEDCDFB), ATSTRINGHASH("grid_arcade_cabinet", 0xD5597100), ATSTRINGHASH("golf_mp", 0xcf654b49), ATSTRINGHASH("gunclub_shop", 0x1beb0bf6), ATSTRINGHASH("gunslinger_arcade", 0xDB23F3DC), ATSTRINGHASH("hacker_truck_carmod", 0xCE27944E), ATSTRINGHASH("hairdo_shop_mp", 0xb57685c9), ATSTRINGHASH("hangar_carmod", 0x34141a78), ATSTRINGHASH("heist_island_planning", 0x55EC87F4), ATSTRINGHASH("heistislandtempcinematicfadeout", 0x32ABF33D), ATSTRINGHASH("heistislandtempcinematicfadein", 0xC1508DAB), ATSTRINGHASH("heli_gun", 0xba023427), ATSTRINGHASH("juggalo_hideout_carmod", 0x05760f53), ATSTRINGHASH("lobby", 0x5a8cb6b1), ATSTRINGHASH("luxe_veh_activity", 0x304094ed), ATSTRINGHASH("mg_race_to_point", 0x804da739), ATSTRINGHASH("missioniaaturret", 0x0c5e8432), ATSTRINGHASH("mp_bed_high", 0x272557eb), ATSTRINGHASH("mptestbed", 0x62c09cc6), ATSTRINGHASH("mptutorial", 0xa1cb0fb5), ATSTRINGHASH("mptutorial old", 0xe79e6d99), ATSTRINGHASH("music_studio_seating", 0x95f729db), ATSTRINGHASH("music_studio_seating_external", 0xdbabae79), ATSTRINGHASH("music_studio_smoking", 0xa5c68a5b), ATSTRINGHASH("net_activity_creator_ui", 0x184b4e09), ATSTRINGHASH("net_apartment_activity", 0xdd40b31d), ATSTRINGHASH("net_apartment_activity_light", 0xf3e2dd79), ATSTRINGHASH("net_combat_soaktest", 0xf159fe54), ATSTRINGHASH("net_jacking_soaktest", 0x74fa8e62), ATSTRINGHASH("net_test_drive", 0x4eb46ff0), ATSTRINGHASH("net_session_soaktest", 0xe696faf1), ATSTRINGHASH("nightclub_ground_floor_seats", 0x8e55be9d), ATSTRINGHASH("nightclub_office_seats", 0xfd519148), ATSTRINGHASH("nightclub_vip_seats", 0xdf1e929f), ATSTRINGHASH("nightclubpeds", 0x9a821400), ATSTRINGHASH("ob_bong", 0x57439d64), ATSTRINGHASH("ob_cashregister", 0x0e1819bf), ATSTRINGHASH("ob_drinking_shots", 0x000269eb), ATSTRINGHASH("ob_franklin_beer", 0xb1b4d0ed), ATSTRINGHASH("ob_franklin_wine", 0x00eb926e), ATSTRINGHASH("ob_jukebox", 0xD044BED0), ATSTRINGHASH("ob_mp_bed_high", 0xe003b72c), ATSTRINGHASH("ob_mp_bed_low", 0x0d798ec5), ATSTRINGHASH("ob_mp_bed_med", 0x51c89b45), ATSTRINGHASH("ob_mp_shower_med", 0x96c72262), ATSTRINGHASH("ob_mp_stripper", 0x5a6f3a5f), ATSTRINGHASH("ob_telescope", 0x5202cf8c), ATSTRINGHASH("ob_vend1", 0xa39c1f72), ATSTRINGHASH("ob_vend2", 0x11c77bc7), ATSTRINGHASH("pb_prostitute", 0x6a96798a), ATSTRINGHASH("personal_carmod_shop", 0xdef103d2), ATSTRINGHASH("pilot_school_mp", 0xc5a00edd), ATSTRINGHASH("range_modern_mp", 0x1f538c61), ATSTRINGHASH("road_arcade", 0x7ae86e42), ATSTRINGHASH("sclub_front_bouncer", 0xe79ae0ef), ATSTRINGHASH("simeon_showroom_seating", 0x23802fd8), ATSTRINGHASH("specialgarage", 0xbc24c116), ATSTRINGHASH("specialgaragevehicles", 0x583f311f), ATSTRINGHASH("streaming", 0xd3ac6be7), ATSTRINGHASH("stripclub_drinking", 0xede89eb0), ATSTRINGHASH("stripclub_mp", 0x97cd8e78), ATSTRINGHASH("stripperhome", 0xb8b48b62), ATSTRINGHASH("tattoo_shop", 0xc0d26565), ATSTRINGHASH("tempofficegarage", 0x738b3a59), ATSTRINGHASH("tennis_network_mp", 0xe3940b1c), ATSTRINGHASH("testtutorialforproperties", 0x311fd06a), ATSTRINGHASH("testtutorialproperties", 0x011e64ab), ATSTRINGHASH("testvehiclespawning", 0x2f07d2ae), ATSTRINGHASH("testvehiclespawning2", 0x0c093898), ATSTRINGHASH("Three_Card_Poker", 0xc8608f32), ATSTRINGHASH("tuner_planning", 0x1BE25EB4), ATSTRINGHASH("tuner_property_carmod", 0x70b10f84), ATSTRINGHASH("tuner_sandbox_activity", 0x8758ef91), ATSTRINGHASH("turret_cam_script", 0xe6511181), ATSTRINGHASH("vehiclespawning", 0x70f5ddd6), ATSTRINGHASH("xml_menus", 0x164e8dee), }; unsigned CGameScriptHandlerMgr::NUM_VALID_NETWORK_SCRIPTS = (sizeof(CGameScriptHandlerMgr::ms_validNetworkScriptHashes) / sizeof(u32)); CGameScriptHandlerMgr::CGameScriptHandlerMgr(CNetworkBandwidthManager* bandwidthMgr) : scriptHandlerMgr(static_cast(bandwidthMgr)) { } bool CGameScriptHandlerMgr::CRemoteScriptInfo::IsTerminated() const { unsigned timeout = CNetwork::GetTimeoutTime(); if (m_ActiveParticipants == 0 && timeout > 0) { return (gnetVerify(m_TimeInactive != 0) && GetCurrentTime() - m_TimeInactive > (timeout+1000)); } return false; } void CGameScriptHandlerMgr::CRemoteScriptInfo::AddActiveParticipant( PhysicalPlayerIndex player ) { gnetAssert(player < MAX_NUM_PHYSICAL_PLAYERS); m_ActiveParticipants |= (1<(scriptThread)); } void CGameScriptHandlerMgr::Init() { if (scriptVerify(!m_IsInitialised)) { CGameScriptHandler::InitPool( MEMBUCKET_SYSTEM ); CGameScriptHandlerNetwork::InitPool( MEMBUCKET_SYSTEM ); CGameScriptHandlerNetComponent::InitPool( MEMBUCKET_SYSTEM ); fwScriptGuid::InitPool( MEMBUCKET_SYSTEM ); CScriptEntityExtension::InitPool( MEMBUCKET_SYSTEM ); #if __DEV CScriptEntityExtension::GetPool()->RegisterPoolCallback(CScriptEntityExtension::PoolFullCallback); #endif // __DEV CGameScriptResource::InitPool( MEMBUCKET_SYSTEM ); scriptHandlerMgr::Init(); } #if __SCRIPT_MEM_CALC m_ArrayOfModelsUsedByMovieMeshes.Reset(); m_MapOfMoviesUsedByMovieMeshes.Reset(); m_MapOfRenderTargetsUsedByMovieMeshes.Reset(); m_bTrackMemoryForMovieMeshes = false; m_TotalScriptVirtualMemory = 0; m_TotalScriptPhysicalMemory = 0; m_TotalScriptVirtualMemoryPeak = 0; m_TotalScriptPhysicalMemoryPeak = 0; #endif // __SCRIPT_MEM_CALC scriptHandlerNetComponent::ms_useNoHostFix = Tunables::GetInstance().TryAccess(CD_GLOBAL_HASH, ATSTRINGHASH("USE_NO_HOST_FIX", 0x318526f9), scriptHandlerNetComponent::ms_useNoHostFix); } void CGameScriptHandlerMgr::NetworkInit() { if (gnetVerify(!m_IsNetworkInitialised)) { m_remoteActiveScripts.Reset(); m_remoteTerminatedScripts.Reset(); scriptHandlerMgr::NetworkInit(); } #if __SCRIPT_MEM_CALC m_TotalScriptVirtualMemoryPeak = 0; m_TotalScriptPhysicalMemoryPeak = 0; #endif // __SCRIPT_MEM_CALC } void CGameScriptHandlerMgr::NetworkShutdown() { scriptHandlerMgr::NetworkShutdown(); #if __SCRIPT_MEM_CALC m_TotalScriptVirtualMemoryPeak = 0; m_TotalScriptPhysicalMemoryPeak = 0; #endif // __SCRIPT_MEM_CALC } void CGameScriptHandlerMgr::Shutdown() { if (m_IsInitialised) { scriptHandlerMgr::Shutdown(); CGameScriptResource::ShutdownPool(); fwScriptGuid::ShutdownPool(); CScriptEntityExtension::ShutdownPool(); CGameScriptHandlerNetComponent::ShutdownPool(); CGameScriptHandlerNetwork::ShutdownPool(); CGameScriptHandler::ShutdownPool(); } } void CGameScriptHandlerMgr::Update() { scriptHandlerMgr::Update(); } void CGameScriptHandlerMgr::NetworkUpdate() { scriptHandlerMgr::NetworkUpdate(); u32 i=0; while (i < m_remoteActiveScripts.GetCount()) { if (m_remoteActiveScripts[i].IsTerminated()) { MoveActiveScriptToTerminatedQueue(i); } else { i++; } } } void CGameScriptHandlerMgr::PlayerHasLeft(const netPlayer& player) { scriptHandlerMgr::PlayerHasLeft(player); // remove the player from the participant flags in all active scripts for (u32 i=0; iIsPlayerAParticipant(player.GetPhysicalPlayerIndex())) { pInfo->RemoveParticipant(player.GetPhysicalPlayerIndex()); } if (pInfo->GetHost() == &player) { pInfo->SetHost(NULL); } } } #if __BANK void Bank_ForceResend() { CGameScriptHandlerMgr* pMgr = &CTheScripts::GetScriptHandlerMgr(); const CGameScriptHandler* handler = pMgr->GetScriptHandlerFromComboName(pMgr->ms_Handlers[pMgr->ms_HandlerComboIndex]); if (handler && handler->GetNetworkComponent()) { handler->GetNetworkComponent()->ForceResendOfAllBroadcastData(); } } void Bank_HostRequest() { CGameScriptHandlerMgr* pMgr = &CTheScripts::GetScriptHandlerMgr(); const CGameScriptHandler* handler = pMgr->GetScriptHandlerFromComboName(pMgr->ms_Handlers[pMgr->ms_HandlerComboIndex]); if (handler && handler->GetNetworkComponent()) { handler->GetNetworkComponent()->RequestToBeHost(); } } void CGameScriptHandlerMgr::InitWidgets(bkBank* pBank) { if (scriptVerify(pBank)) { ms_Handlers[0] = "-- none --"; ms_NumHandlers = 1; pBank->PushGroup("Script Handlers",false); ms_pHandlerCombo = pBank->AddCombo("Active Handlers", &ms_HandlerComboIndex, ms_NumHandlers, (const char **)ms_Handlers); pBank->AddToggle("Display handler info", &ms_DisplayHandlerInfo); pBank->AddButton("Resend all broadcast data", Bank_ForceResend); pBank->AddButton("Request to be host", Bank_HostRequest); pBank->AddToggle("Display all MP handlers", &ms_DisplayAllMPHandlers); pBank->PopGroup(); } } // CGameScriptHandlerMgr::ShutdownWidgets // Since ms_pHandlerCombo is created within the script bank, make sure that we remove the combo and set ms_pHandlerCombo to NULL // before the script bank is deleted so that ms_pHandlerCombo doesn't have an invalid address void CGameScriptHandlerMgr::ShutdownWidgets(bkBank* pBank) { if (scriptVerify(pBank)) { pBank->Remove(*ms_pHandlerCombo); ms_pHandlerCombo = NULL; ms_HandlerComboIndex = 0; ms_DisplayHandlerInfo = false; ms_DisplayAllMPHandlers = false; } } #endif // __BANK void CGameScriptHandlerMgr::RegisterScript(scrThread& scriptThread) { scriptHandlerMgr::RegisterScript(scriptThread); #if __BANK UpdateScriptHandlerCombo(); #endif } void CGameScriptHandlerMgr::UnregisterScript(scrThread& scriptThread) { GtaThread& gtaThread = static_cast(scriptThread); CGameScriptHandler* handler = gtaThread.m_Handler; if (AssertVerify(handler) && handler->Terminate()) { DeleteHandlerWithHash(handler->GetScriptId().GetScriptIdHash()); } gtaThread.m_Handler = NULL; #if __BANK UpdateScriptHandlerCombo(); #endif } bool CGameScriptHandlerMgr::IsScriptValidForNetworking(atHashValue scriptName) { #if !__FINAL if (PARAM_dontCrashOnScriptValidation.Get()) { return true; } #endif // !__FINAL for (u32 scriptHash = 0; scriptHash < NUM_VALID_NETWORK_SCRIPTS; scriptHash++) { if (ms_validNetworkScriptHashes[scriptHash] == scriptName) { return true; } } return false; } void CGameScriptHandlerMgr::SetScriptAsANetworkScript(GtaThread& scriptThread, int instanceId) { CGameScriptId& scriptId = static_cast(GetScriptId(scriptThread)); atHashValue hash = scriptId.GetScriptIdHash(); netLoggingInterface *log = CTheScripts::GetScriptHandlerMgr().GetLog(); if (log) { CGameScriptId logId = scriptId; logId.SetInstanceId(instanceId); NetworkLogUtils::WriteLogEvent(*log, "SET_SCRIPT_AS_NETWORK_SCRIPT", "%s", logId.GetScriptName()); } // find network handler for this thread, destroy it and replace with a network handler scriptHandler** ppHandler = m_scriptHandlers.Access(hash); if (ppHandler) { CGameScriptHandler* handler = static_cast(*ppHandler); scriptAssertf(handler->GetNumRegisteredNetworkedObjects() == 0, "CGameScriptHandlerMgr::SetScriptAsANetworkScript : Script %s has registered networked objects", handler->GetScriptName()); if (scriptVerifyf(!handler->RequiresANetworkComponent(), "CGameScriptHandlerMgr::SetScriptAsANetworkScript : Script %s has already been set as a network script", handler->GetScriptName())) { if (!IsScriptValidForNetworking(scriptId.GetScriptNameHash())) { #if !__FINAL NETWORK_QUITF(0, "CGameScriptHandlerMgr::SetScriptAsANetworkScript : Cannot network script %s - it has no entry in the valid network scripts allowlist", handler->GetScriptName()); #endif return; } if (CGameScriptHandlerNetwork::GetPool()->GetNoOfFreeSpaces() == 0) { Displayf("** TOO MANY NETWORKED SCRIPTS RUNNING!! **\n"); Displayf("Active networked scripts:\n"); scriptHandlerMap::Iterator entry = m_scriptHandlers.CreateIterator(); for (entry.Start(); !entry.AtEnd(); entry.Next()) { scriptHandler* handler = entry.GetData(); if (handler && handler->GetNetworkComponent()) { Displayf("%s\n", handler->GetLogName()); } } CNetwork::FlushAllLogFiles(true); NETWORK_QUITF(0, "CGameScriptHandlerMgr::SetScriptAsANetworkScript : Cannot network this script - too many networked scripts running (max %d)", MAX_NUM_ACTIVE_NETWORK_SCRIPTS); return; } scriptHandlerObject* aUnnetworkedObjects[CGameScriptHandler::MAX_UNNETWORKED_OBJECTS]; u32 numUnnetworkedObjects = 0; handler->DetachAllUnnetworkedObjects(aUnnetworkedObjects, numUnnetworkedObjects); DeleteHandlerWithHash(hash); scriptThread.bSafeForNetworkGame = true; scriptThread.InstanceId = instanceId; if (instanceId != -1) { #if __ASSERT scriptHandler* pHandler = GetScriptHandler(GetScriptId(scriptThread)); // we can't have 2 network script handlers with the same id NETWORK_QUITF(!pHandler, "SetScriptAsANetworkScript - a network script already exists with this instance id (%s)", pHandler->GetLogName()); #endif } CGameScriptHandlerNetwork* netHandler = rage_new CGameScriptHandlerNetwork(scriptThread); #if !__NO_OUTPUT scriptHandler** ppHandler = m_scriptHandlers.Access(netHandler->GetScriptId().GetScriptIdHash()); if (ppHandler) { char logNameOfNewHandler[200]; safecpy(logNameOfNewHandler, netHandler->GetLogName(), NELEM(logNameOfNewHandler)); // CGameScriptId::GetLogName() fills in a static string internally so I need to make a copy of one of the LogName's to display in the assert below #if __ASSERT CGameScriptHandler *pGameScriptHandler = static_cast(*ppHandler); Assertf(false, "CGameScriptHandlerMgr::SetScriptAsANetworkScript - about to add %s(%p) script with hash %u. %s(%p) already exists in the map with this hash", logNameOfNewHandler, netHandler, netHandler->GetScriptId().GetScriptIdHash().GetHash(), pGameScriptHandler->GetLogName(), pGameScriptHandler); #endif } #endif // !__NO_OUTPUT m_scriptHandlers.Insert(netHandler->GetScriptId().GetScriptIdHash(), netHandler); if (m_IsNetworkInitialised) { netHandler->CreateNetworkComponent(); } #if __BANK UpdateScriptHandlerCombo(); #endif for (u32 i=0; i(aUnnetworkedObjects[i]->GetScriptInfo()->GetScriptId()).SetInstanceId(instanceId); } netHandler->RegisterExistingScriptObject(*aUnnetworkedObjects[i]); } } } else { scriptAssertf(0, "CGameScriptHandlerMgr::SetScriptAsANetworkScript : The script handler for %s was not found", scriptId.GetLogName()); } } bool CGameScriptHandlerMgr::TryToSetScriptAsANetworkScript(GtaThread& scriptThread, int instanceId) { CGameScriptId& singlePlayerScriptId = static_cast(GetScriptId(scriptThread)); atHashValue singlePlayerHash = singlePlayerScriptId.GetScriptIdHash(); // find existing handler for this thread and attempt to replace it with a network handler scriptHandler** ppHandler = m_scriptHandlers.Access(singlePlayerHash); if (ppHandler) { CGameScriptHandler* pSinglePlayerHandler = static_cast(*ppHandler); scriptAssertf(pSinglePlayerHandler->GetNumRegisteredObjects() == 0, "CGameScriptHandlerMgr::TryToSetScriptAsANetworkScript : Script %s has registered objects", pSinglePlayerHandler->GetScriptName()); if (scriptVerifyf(!pSinglePlayerHandler->RequiresANetworkComponent(), "CGameScriptHandlerMgr::TryToSetScriptAsANetworkScript : Script %s has already been set as a network script", pSinglePlayerHandler->GetScriptName())) { if (CGameScriptHandlerNetwork::GetPool()->GetNoOfFreeSpaces() == 0) { Displayf("** TOO MANY NETWORKED SCRIPTS RUNNING!! **\n"); Displayf("Active networked scripts:\n"); scriptHandlerMap::Iterator entry = m_scriptHandlers.CreateIterator(); for (entry.Start(); !entry.AtEnd(); entry.Next()) { scriptHandler* handler = entry.GetData(); if (handler && handler->GetNetworkComponent()) { Displayf("%s\n", handler->GetLogName()); } } CNetwork::FlushAllLogFiles(true); FatalAssertf(0, "CGameScriptHandlerMgr::TryToSetScriptAsANetworkScript : Cannot network this script - too many networked scripts running (max %d)", MAX_NUM_ACTIVE_NETWORK_SCRIPTS); return false; } if (!m_scriptHandlers.Delete(singlePlayerHash)) { FatalAssertf(0, "CGameScriptHandlerMgr::TryToSetScriptAsANetworkScript : failed to delete handler %s at key %u (%p)\n", pSinglePlayerHandler->GetLogName(), singlePlayerHash.GetHash(), pSinglePlayerHandler); return false; } bool bFailedToCreateNetworkHandler = false; CGameScriptHandlerNetwork* pNetHandler = NULL; bool singlePlayerSafeForNetworkGame = scriptThread.bSafeForNetworkGame; int singlePlayerInstanceId = scriptThread.InstanceId; scriptThread.bSafeForNetworkGame = true; if (instanceId != -1) { scriptThread.InstanceId = instanceId; scriptHandler* pHandler = GetScriptHandler(GetScriptId(scriptThread)); // we can't have 2 network script handlers with the same id if (pHandler) { Displayf("CGameScriptHandlerMgr::TryToSetScriptAsANetworkScript - a network script already exists with this instance id (%s)", pHandler->GetLogName()); bFailedToCreateNetworkHandler = true; } } if (!bFailedToCreateNetworkHandler) { pNetHandler = rage_new CGameScriptHandlerNetwork(scriptThread); scriptHandler** ppHandler = m_scriptHandlers.Access(pNetHandler->GetScriptId().GetScriptIdHash()); if (ppHandler) { #if !__NO_OUTPUT char logNameOfNewHandler[200]; safecpy(logNameOfNewHandler, pNetHandler->GetLogName(), NELEM(logNameOfNewHandler)); // CGameScriptId::GetLogName() fills in a static string internally so I need to make a copy of one of the LogName's to display in the assert below CGameScriptHandler *pGameScriptHandler = static_cast(*ppHandler); Displayf("CGameScriptHandlerMgr::TryToSetScriptAsANetworkScript - about to add %s(%p) script with hash %u. %s(%p) already exists in the map with this hash", logNameOfNewHandler, pNetHandler, pNetHandler->GetScriptId().GetScriptIdHash().GetHash(), pGameScriptHandler->GetLogName(), pGameScriptHandler); #endif // !__NO_OUTPUT bFailedToCreateNetworkHandler = true; } } if (bFailedToCreateNetworkHandler) { if (pNetHandler) { // I don't need to Delete pNetHandler from m_scriptHandlers because it hasn't been Inserted at this stage m_DeletingHandlers = true; pNetHandler->Shutdown(); delete pNetHandler; pNetHandler = NULL; m_DeletingHandlers = false; } // deleting pNetHandler will have cleared scriptThread.m_Handler (in ~CGameScriptHandler()) so make sure it points to pSinglePlayerHandler scriptThread.m_Handler = pSinglePlayerHandler; // Put the original single player handler back to the way it was scriptThread.bSafeForNetworkGame = singlePlayerSafeForNetworkGame; scriptThread.InstanceId = singlePlayerInstanceId; m_scriptHandlers.Insert(singlePlayerHash, pSinglePlayerHandler); } else { if (pSinglePlayerHandler) { // We've already Deleted pSinglePlayerHandler from m_scriptHandlers so now we just need to delete pSinglePlayerHandler itself m_DeletingHandlers = true; pSinglePlayerHandler->Shutdown(); delete pSinglePlayerHandler; pSinglePlayerHandler = NULL; m_DeletingHandlers = false; } // deleting pSinglePlayerHandler will have cleared scriptThread.m_Handler (in ~CGameScriptHandler()) so make sure it points to pNetHandler scriptThread.m_Handler = pNetHandler; m_scriptHandlers.Insert(pNetHandler->GetScriptId().GetScriptIdHash(), pNetHandler); if (m_IsNetworkInitialised) { pNetHandler->CreateNetworkComponent(); } } #if __BANK UpdateScriptHandlerCombo(); #endif return !bFailedToCreateNetworkHandler; } } else { scriptAssertf(0, "CGameScriptHandlerMgr::TryToSetScriptAsANetworkScript : The script handler for %s was not found", singlePlayerScriptId.GetLogName()); } return false; } void CGameScriptHandlerMgr::SetScriptAsSafeToRunInMP(GtaThread& scriptThread) { CGameScriptId& scriptId = static_cast(GetScriptId(scriptThread)); atHashValue hash = scriptId.GetScriptIdHash(); // find network handler for this thread and change its script id scriptHandler** ppHandler = m_scriptHandlers.Access(hash); if (ppHandler) { CGameScriptHandler* handler = static_cast(*ppHandler); if (!m_scriptHandlers.Delete(hash)) { FatalAssertf(0, "CGameScriptHandlerMgr::SetScriptAsSafeToRunInMP - failed to remove handler %s from map", handler->GetLogName()); } scriptThread.bSafeForNetworkGame = true; // recalculate the script id as the hash will now be altered static_cast(handler->GetScriptId()).InitGameScriptId(scriptThread); #if !__NO_OUTPUT scriptHandler** ppHandler = m_scriptHandlers.Access(handler->GetScriptId().GetScriptIdHash()); if (ppHandler) { char logNameOfNewHandler[200]; safecpy(logNameOfNewHandler, handler->GetLogName(), NELEM(logNameOfNewHandler)); // CGameScriptId::GetLogName() fills in a static string internally so I need to make a copy of one of the LogName's to display in the assert below CGameScriptHandler *pGameScriptHandler = static_cast(*ppHandler); Quitf("CGameScriptHandlerMgr::SetScriptAsSafeToRunInMP - about to add %s(%p) script with hash %u. %s(%p) already exists in the map with this hash", logNameOfNewHandler, handler, handler->GetScriptId().GetScriptIdHash().GetHash(), pGameScriptHandler->GetLogName(), pGameScriptHandler); } #endif // !__NO_OUTPUT m_scriptHandlers.Insert(handler->GetScriptId().GetScriptIdHash(), handler); } else { scriptAssertf(0, "CGameScriptHandlerMgr::SetScriptAsSafeToRunInMP : The script handler for %s was not found", scriptId.GetLogName()); } } u32 CGameScriptHandlerMgr::GetAllScriptHandlerEntities(CEntity* entityArray[], u32 arrayLen) { u32 numEntities = 0; scriptHandlerMap::Iterator entry = m_scriptHandlers.CreateIterator(); for (entry.Start(); !entry.AtEnd(); entry.Next()) { CGameScriptHandler* handler = static_cast(entry.GetData()); if (handler) { numEntities += handler->GetAllEntities(&entityArray[numEntities], arrayLen-numEntities); } } return numEntities; } void CGameScriptHandlerMgr::GetNumReservedScriptEntities(u32 &numPeds, u32 &numVehicles, u32 &numObjects) const { numPeds = numVehicles = numObjects = 0; scriptHandlerMap::ConstIterator entry = m_scriptHandlers.CreateIterator(); for (entry.Start(); !entry.AtEnd(); entry.Next()) { CGameScriptHandler* handler = static_cast(entry.GetData()); if (handler && handler->RequiresANetworkComponent()) { const CGameScriptHandlerNetwork* netHandler = static_cast(handler); numPeds += netHandler->GetTotalNumReservedPeds(); numVehicles += netHandler->GetTotalNumReservedVehicles(); numObjects += netHandler->GetTotalNumReservedObjects(); } } } void CGameScriptHandlerMgr::GetNumCreatedScriptEntities(u32 &numPeds, u32 &numVehicles, u32 &numObjects) const { numPeds = numVehicles = numObjects = 0; scriptHandlerMap::ConstIterator entry = m_scriptHandlers.CreateIterator(); for (entry.Start(); !entry.AtEnd(); entry.Next()) { CGameScriptHandler* handler = static_cast(entry.GetData()); if (handler && handler->RequiresANetworkComponent()) { const CGameScriptHandlerNetwork* netHandler = static_cast(handler); numPeds += netHandler->GetNumCreatedPeds(); numVehicles += netHandler->GetNumCreatedVehicles(); numObjects += netHandler->GetNumCreatedObjects(); } } } void CGameScriptHandlerMgr::GetNumRequiredScriptEntities(u32 &numPeds, u32 &numVehicles, u32 &numObjects, CGameScriptHandler* pHandlerToIgnore) const { numPeds = numVehicles = numObjects = 0; scriptHandlerMap::ConstIterator entry = m_scriptHandlers.CreateIterator(); for (entry.Start(); !entry.AtEnd(); entry.Next()) { CGameScriptHandler* handler = static_cast(entry.GetData()); if (handler && handler != pHandlerToIgnore && handler->GetNetworkComponent() && handler->GetNetworkComponent()->IsPlaying()) { const CGameScriptHandlerNetwork* netHandler = static_cast(handler); u32 peds = 0; u32 vehs = 0; u32 objs = 0; netHandler->GetNumRequiredEntities(peds, vehs, objs); numPeds += peds; numVehicles += vehs; numObjects += objs; } } u32 remoteReservedPeds = 0; u32 remoteReservedVehs = 0; u32 remoteReservedObjs = 0; u32 remoteCreatedPeds = 0; u32 remoteCreatedVehs = 0; u32 remoteCreatedObjs = 0; GetRemoteScriptEntityReservations(remoteReservedPeds, remoteReservedVehs, remoteReservedObjs, remoteCreatedPeds, remoteCreatedVehs, remoteCreatedObjs); if (remoteReservedPeds > remoteCreatedPeds) { numPeds += remoteReservedPeds-remoteCreatedPeds; } if (remoteReservedVehs > remoteCreatedVehs) { numVehicles += remoteReservedVehs-remoteCreatedVehs; } if (remoteReservedObjs > remoteCreatedObjs) { numObjects += remoteReservedObjs-remoteCreatedObjs; } } //PURPOSE // Adds info on a new script running remotely but not locally void CGameScriptHandlerMgr::AddRemoteScriptInfo(CRemoteScriptInfo& scriptInfo, const netPlayer* sendingPlayer) { CGameScriptHandler* pHandler = SafeCast(CGameScriptHandler, GetScriptHandler(scriptInfo.GetScriptId())); if (gnetVerifyf(scriptInfo.GetScriptId().GetTimeStamp() != 0, "CGameScriptHandlerMgr::AddRemoteScriptInfo: can't add a remote script info with a timestamp of 0")) { if (sendingPlayer) { WriteRemoteScriptHeader(scriptInfo.GetScriptId(), "Got a remote script info update from %s. Participants: %u, Host token: %u. Reservations: peds(%d), vehicles(%d), objects(%d)", sendingPlayer->GetLogName(), scriptInfo.GetActiveParticipants(), scriptInfo.GetHostToken(), scriptInfo.GetReservedPeds(), scriptInfo.GetReservedVehicles(), scriptInfo.GetReservedObjects()); // the sending player is the current host scriptInfo.SetHost(sendingPlayer); if (pHandler && !pHandler->IsTerminated()) { WriteRemoteScriptHeader(scriptInfo.GetScriptId(), "Ignore: script is running locally"); return; } } else { WriteRemoteScriptHeader(scriptInfo.GetScriptId(), "Locally update remote script info. Participants: %u, Host token: %u. Reservations: peds(%d), vehicles(%d), objects(%d)", scriptInfo.GetActiveParticipants(), scriptInfo.GetHostToken(), scriptInfo.GetReservedPeds(), scriptInfo.GetReservedVehicles(), scriptInfo.GetReservedObjects()); } if (scriptInfo.GetActiveParticipants() == 0) { // this script has terminated, so remove from active queue and add to terminated queue for (u32 i=0; i 0, "Ran out of active remote script infos"); WriteRemoteScriptHeader(scriptInfo.GetScriptId(), "Add new active remote script info"); // add a new info to the active queue if (!m_remoteActiveScripts.Push(scriptInfo)) { Assertf(0, "The remote active script queue is full"); } } } } } void CGameScriptHandlerMgr::AddPlayerToRemoteScript(const CGameScriptId& scriptId, const netPlayer& player) { if (gnetVerifyf(scriptId.GetTimeStamp() != 0, "CGameScriptHandlerMgr::AddPlayerToRemoteScript: scriptId has a timestamp of 0")) { WriteRemoteScriptHeader(scriptId, "Add remote player %s (%d) to remote script", player.GetLogName(), player.GetPhysicalPlayerIndex()); for (u32 i=0; iIsTerminated()) { WriteRemoteScriptHeader(scriptId, "Ignore: script is running locally"); return; } } for (u32 i=0; iGetTransform().GetPosition()); PlayerFlags participantFlags = remoteScriptInfo.GetActiveParticipants(); for (u32 i=0; i(NetworkInterface::GetPlayerMgr().GetPhysicalPlayerFromIndex((PhysicalPlayerIndex)i)); if (pPlayer->GetPlayerPed() && !pPlayer->IsMyPlayer()) { Vector3 playerPos = VEC3V_TO_VECTOR3(pPlayer->GetPlayerPed()->GetTransform().GetPosition()); Vector3 diff = playerPos - localPlayerPos; float playerDist = diff.XYMag2(); if (!pClosestPlayer || playerDist < closestDist) { pClosestPlayer = pPlayer; closestDist = playerDist; } } } } return pClosestPlayer; } //PURPOSE // Gets info on a new script running remotely but not locally CGameScriptHandlerMgr::CRemoteScriptInfo* CGameScriptHandlerMgr::GetRemoteScriptInfo(const CGameScriptId& scriptId, bool bActiveOnly) { for (u32 i=0; i 0) return &m_remoteActiveScripts[i]; else return NULL; } } if (!bActiveOnly) { for (u32 i=0; i(this)->GetRemoteScriptInfo(scriptId, bActiveOnly); } // returns true if the given script is running, either locally or remotely bool CGameScriptHandlerMgr::IsScriptActive(const CGameScriptId& scriptId, bool bMatchOnNameOnly) { bool bScriptActive = false; if (GetScriptHandler(scriptId)) { bScriptActive = true; } else { for (u32 i=0; i 0) { if (bMatchOnNameOnly) { // only match using the script name if (m_remoteActiveScripts[i].m_ScriptId.EqualivalentScriptName(scriptId)) { bScriptActive = true; break; } } else if (m_remoteActiveScripts[i].m_ScriptId == scriptId) { bScriptActive = true; break; } } } } return bScriptActive; } // returns true if the given script has been terminated bool CGameScriptHandlerMgr::IsScriptTerminated(const CGameScriptId& scriptId) { if (GetScriptHandler(scriptId) && !GetScriptHandler(scriptId)->IsTerminated()) { return false; } for (u32 i=0; iGetNetworkComponent() && pHandler->GetNetworkComponent()->IsPlayerAParticipant(player)) { return true; } for (u32 i=0; iGetNetworkComponent() : NULL; if (netComponent && netComponent->GetState() == scriptHandlerNetComponent::NETSCRIPT_PLAYING) { const netPlayer* pHost = netComponent->GetHost(); if (pHost && pHost->IsMyPlayer()) { isHost = true; } } return isHost; } u32 CGameScriptHandlerMgr::GetNumParticipantsOfScript(const CGameScriptId& scriptId) { u32 numParticipants = 0; scriptHandler* pHandler = GetScriptHandler(scriptId); if (pHandler && pHandler->GetNetworkComponent()) { numParticipants = pHandler->GetNetworkComponent()->GetNumParticipants(); } else { u32 i = 0; for (i=0; i(handler.GetScriptId()).InitGameScriptId(*handler.GetThread()); #if !__NO_OUTPUT scriptHandler** ppHandler = m_scriptHandlers.Access(handler.GetScriptId().GetScriptIdHash()); if (ppHandler) { char logNameOfNewHandler[200]; safecpy(logNameOfNewHandler, handler.GetLogName(), NELEM(logNameOfNewHandler)); // CGameScriptId::GetLogName() fills in a static string internally so I need to make a copy of one of the LogName's to display in the assert below CGameScriptHandler *pGameScriptHandler = static_cast(*ppHandler); Quitf("CGameScriptHandlerMgr::RecalculateScriptId - about to add %s(%p) script with hash %u. %s(%p) already exists in the map with this hash", logNameOfNewHandler, &handler, handler.GetScriptId().GetScriptIdHash().GetHash(), pGameScriptHandler->GetLogName(), pGameScriptHandler); } #endif // !__NO_OUTPUT m_scriptHandlers.Insert(handler.GetScriptId().GetScriptIdHash(), &handler); } void CGameScriptHandlerMgr::SetNotInMPCutscene() { scriptHandlerMap::Iterator entry = m_scriptHandlers.CreateIterator(); for (entry.Start(); !entry.AtEnd(); entry.Next()) { CGameScriptHandler* handler = static_cast(entry.GetData()); if (handler && handler->RequiresANetworkComponent()) { CGameScriptHandlerNetwork* netHandler = static_cast(handler); netHandler->SetInMPCutscene(false); } } } void CGameScriptHandlerMgr::AddToReservationCount(CNetObjGame& scriptEntityObj) { if (!scriptEntityObj.IsLocalFlagSet(CNetObjGame::LOCALFLAG_COUNTED_BY_RESERVATIONS)) { CEntity* pEntity = scriptEntityObj.GetEntity(); if (pEntity) { bool bPed = pEntity->GetIsTypePed(); bool bVeh = pEntity->GetIsTypeVehicle(); bool bObj = pEntity->GetIsTypeObject() && scriptEntityObj.GetObjectType() == NET_OBJ_TYPE_OBJECT; // ignore doors and pickups if (bPed || bVeh || bObj) { CScriptEntityExtension* pExtension = pEntity->GetExtension(); const CGameScriptId* pScriptId = NULL; if (pExtension) { pScriptId = static_cast(&pExtension->GetScriptInfo()->GetScriptId()); } if (pScriptId) { for (u32 i=0; iGetLogName(), scriptEntityObj.GetLogName()); LogCurrentReservations(*log); } break; } } } } } } } void CGameScriptHandlerMgr::RemoveFromReservationCount(CNetObjGame& scriptEntityObj) { if (scriptEntityObj.IsLocalFlagSet(CNetObjGame::LOCALFLAG_COUNTED_BY_RESERVATIONS)) { CEntity* pEntity = scriptEntityObj.GetEntity(); if (gnetVerifyf(pEntity, "Failed to remove reservation count for %s. Gameobject is missing", scriptEntityObj.GetLogName())) { bool bPed = pEntity->GetIsTypePed(); bool bVeh = pEntity->GetIsTypeVehicle(); bool bObj = pEntity->GetIsTypeObject() && scriptEntityObj.GetObjectType() == NET_OBJ_TYPE_OBJECT; // ignore doors and pickups CScriptEntityExtension* pExtension = pEntity->GetExtension(); const CGameScriptId* pScriptId = NULL; if (pExtension && pExtension->GetScriptInfo()) { pScriptId = static_cast(&pExtension->GetScriptInfo()->GetScriptId()); } if (pScriptId) { for (u32 i=0; iGetLogName(), scriptEntityObj.GetLogName()); LogCurrentReservations(*log); } break; } } } } } } void CGameScriptHandlerMgr::GetRemoteScriptEntityReservations(u32& reservedPeds, u32& reservedVehicles, u32& reservedObjects, u32& createdPeds, u32& createdVehicles, u32& createdObjects, Vector3* pScopePosition) const { reservedPeds = 0; reservedVehicles = 0; reservedObjects = 0; createdPeds = 0; createdVehicles = 0; createdObjects = 0; PlayerFlags playersNearby = 0; PlayerFlags playersNearbyInPedScope = 0; PlayerFlags playersNearbyInVehScope = 0; PlayerFlags playersNearbyInObjScope = 0; bool playersNearbyCalculated = false; for (u32 i=0; iGetRunningLocally()) { u32 peds = 0; u32 vehs = 0; u32 objs = 0; pInfo->GetReservations(peds, vehs, objs); if (peds != 0 || vehs != 0 || objs != 0) { if (!playersNearbyCalculated) { NetworkInterface::GetObjectManager().GetPlayersNearbyInScope(playersNearbyInPedScope, playersNearbyInVehScope, playersNearbyInObjScope, pScopePosition); playersNearby = playersNearbyInPedScope | playersNearbyInVehScope | playersNearbyInObjScope; playersNearbyCalculated = true; } if (playersNearby != 0) { bool bParticipantNearbyInPedScope = false; bool bParticipantNearbyInVehScope = false; bool bParticipantNearbyInObjScope = false; for (u32 p=0; pGetActiveParticipants() & playerIndex)) { Assert(playersNearbyCalculated); if (playersNearbyInPedScope & playerIndex) { bParticipantNearbyInPedScope = true; } if (playersNearbyInVehScope & playerIndex) { bParticipantNearbyInVehScope = true; } if (playersNearbyInObjScope & playerIndex) { bParticipantNearbyInObjScope = true; } } if (bParticipantNearbyInPedScope == (peds != 0) && bParticipantNearbyInVehScope == (vehs != 0) && bParticipantNearbyInObjScope == (objs != 0)) { break; } } if (bParticipantNearbyInPedScope) { reservedPeds += peds; createdPeds += pInfo->GetCreatedPeds(); } if (bParticipantNearbyInVehScope) { reservedVehicles += vehs; createdVehicles += pInfo->GetCreatedVehicles(); } if (bParticipantNearbyInObjScope) { reservedObjects += objs; createdObjects += pInfo->GetCreatedObjects(); } } } } } } #if ENABLE_NETWORK_LOGGING void CGameScriptHandlerMgr::LogCurrentReservations(netLoggingInterface& log) const { u32 reservedPeds = 0; u32 reservedVehs = 0; u32 reservedObjs = 0; bool bLogLocal = false; bool bLogRemote = false; scriptHandlerMap::ConstIterator entry = m_scriptHandlers.CreateIterator(); for (entry.Start(); !entry.AtEnd(); entry.Next()) { CGameScriptHandler* handler = static_cast(entry.GetData()); if (handler && handler->RequiresANetworkComponent() && !handler->IsTerminated()) { const CGameScriptHandlerNetwork* netHandler = static_cast(handler); reservedPeds = netHandler->GetTotalNumReservedPeds(); reservedVehs = netHandler->GetTotalNumReservedVehicles(); reservedObjs = netHandler->GetTotalNumReservedObjects(); if (reservedPeds > 0 || reservedVehs > 0 || reservedObjs > 0) { if (!bLogLocal) { NetworkLogUtils::WriteLogEvent(log, "LOCAL_SCRIPT_RESERVATIONS", ""); bLogLocal = true; } log.WriteDataValue(netHandler->GetScriptId().GetLogName(), "%d/%d peds, %d/%d vehicles, %d/%d objects", netHandler->GetNumCreatedPeds(), reservedPeds, netHandler->GetNumCreatedVehicles(), reservedVehs, netHandler->GetNumCreatedObjects(), reservedObjs); } } } PlayerFlags playersNearby = 0; PlayerFlags playersNearbyInPedScope = 0; PlayerFlags playersNearbyInVehScope = 0; PlayerFlags playersNearbyInObjScope = 0; bool playersNearbyCalculated = false; for (u32 i=0; iGetRunningLocally()) { reservedPeds = 0; reservedVehs = 0; reservedObjs = 0; pInfo->GetReservations(reservedPeds, reservedVehs, reservedObjs); if (reservedPeds != 0 || reservedVehs != 0 || reservedObjs != 0) { if (!playersNearbyCalculated) { NetworkInterface::GetObjectManager().GetPlayersNearbyInScope(playersNearbyInPedScope, playersNearbyInVehScope, playersNearbyInObjScope); playersNearby = playersNearbyInPedScope | playersNearbyInVehScope | playersNearbyInObjScope; playersNearbyCalculated = true; } if (playersNearby != 0) { bool bParticipantNearbyInPedScope = false; bool bParticipantNearbyInVehScope = false; bool bParticipantNearbyInObjScope = false; for (u32 p=0; pGetActiveParticipants() & playerIndex)) { Assert(playersNearbyCalculated); if (playersNearbyInPedScope & playerIndex) { bParticipantNearbyInPedScope = true; } if (playersNearbyInVehScope & playerIndex) { bParticipantNearbyInVehScope = true; } if (playersNearbyInObjScope & playerIndex) { bParticipantNearbyInObjScope = true; } } } if (!bParticipantNearbyInPedScope) { reservedPeds = 0; } if (!bParticipantNearbyInVehScope) { reservedVehs = 0; } if (!bParticipantNearbyInObjScope) { reservedObjs = 0; } } } if (reservedPeds>0 || reservedVehs>0 || reservedObjs>0) { if (!bLogRemote) { NetworkLogUtils::WriteLogEvent(log, "REMOTE_SCRIPT_RESERVATIONS", ""); bLogRemote = true; } log.WriteDataValue(m_remoteActiveScripts[i].GetScriptId().GetLogName(), "%d/%d peds, %d/%d vehicles, %d/%d objects", pInfo->GetCreatedPeds(), reservedPeds, pInfo->GetCreatedVehicles(), reservedVehs, pInfo->GetCreatedObjects(), reservedObjs); } } } } #else void CGameScriptHandlerMgr::LogCurrentReservations(netLoggingInterface&) const { } #endif // ENABLE_NETWORK_LOGGING #if __BANK void CGameScriptHandlerMgr::DisplayScriptHandlerInfo() const { if (ms_DisplayHandlerInfo) { const CGameScriptHandler* handler = GetScriptHandlerFromComboName(ms_Handlers[ms_HandlerComboIndex]); if (handler) { handler->DisplayScriptHandlerInfo(); grcDebugDraw::AddDebugOutput(""); grcDebugDraw::AddDebugOutput(""); } } if (ms_DisplayAllMPHandlers && NetworkInterface::GetLocalPlayer()) { grcDebugDraw::AddDebugOutput(""); grcDebugDraw::AddDebugOutput("Local net array data: %u (Cached value: %u)", NetworkInterface::GetArrayManager().GetSizeOfLocallyArbitratedArrayData(), NetworkInterface::GetLocalPlayer()->GetSizeOfNetArrayData()); grcDebugDraw::AddDebugOutput(""); scriptHandlerMap::ConstIterator entry = m_scriptHandlers.CreateIterator(); for (entry.Start(); !entry.AtEnd(); entry.Next()) { scriptHandler* handler = entry.GetData(); if (handler && handler->GetNetworkComponent()) { char name[80]; sprintf(name, "%-80s", handler->GetLogName()); u32 size = handler->GetNetworkComponent()->GetSizeOfHostBroadcastData(); if (handler->GetNetworkComponent()->IsHostMigrating()) { grcDebugDraw::AddDebugOutput("%s (Size: %u. Host: ** migrating to %s **)", name, size, handler->GetNetworkComponent()->GetPendingHost()->IsLocal() ? "us" : handler->GetNetworkComponent()->GetPendingHost()->GetLogName()); } else if (!handler->GetNetworkComponent()->GetHost()) { grcDebugDraw::AddDebugOutput("%s (Size: %u. Host: --none--)", name, size); } else { if (handler->GetNetworkComponent()->GetHost()->IsLocal()) { grcDebugDraw::AddDebugOutput("%s (Size: %u. Host: us)", name, size); } else { grcDebugDraw::AddDebugOutput("%s (Size: %u. Host: %s)", name, size, handler->GetNetworkComponent()->GetHost()->GetLogName()); } } } } grcDebugDraw::AddDebugOutput(""); } } void CGameScriptHandlerMgr::DisplayObjectAndResourceInfo() const { scriptHandlerMap::ConstIterator entry = m_scriptHandlers.CreateIterator(); for (entry.Start(); !entry.AtEnd(); entry.Next()) { CGameScriptHandler* handler = static_cast(entry.GetData()); if (handler) { handler->DisplayObjectAndResourceInfo(); } } } void CGameScriptHandlerMgr::DisplayReservationInfo() const { u32 reservedPeds = 0; u32 reservedVehs = 0; u32 reservedObjs = 0; grcDebugDraw::AddDebugOutput("-- LOCAL SCRIPTS --"); scriptHandlerMap::ConstIterator entry = m_scriptHandlers.CreateIterator(); for (entry.Start(); !entry.AtEnd(); entry.Next()) { CGameScriptHandler* handler = static_cast(entry.GetData()); if (handler && handler->RequiresANetworkComponent() && !handler->IsTerminated()) { const CGameScriptHandlerNetwork* netHandler = static_cast(handler); reservedPeds = netHandler->GetTotalNumReservedPeds(); reservedVehs = netHandler->GetTotalNumReservedVehicles(); reservedObjs = netHandler->GetTotalNumReservedObjects(); if (reservedPeds > 0 || reservedVehs > 0 || reservedObjs > 0) { grcDebugDraw::AddDebugOutput("%s: %d/%d peds, %d/%d vehicles, %d/%d objects", netHandler->GetScriptName(), netHandler->GetNumCreatedPeds(), reservedPeds, netHandler->GetNumCreatedVehicles(), reservedVehs, netHandler->GetNumCreatedObjects(), reservedObjs); } } } grcDebugDraw::AddDebugOutput("-- REMOTE SCRIPTS --"); PlayerFlags playersNearby = 0; PlayerFlags playersNearbyInPedScope = 0; PlayerFlags playersNearbyInVehScope = 0; PlayerFlags playersNearbyInObjScope = 0; bool playersNearbyCalculated = false; for (u32 i=0; iGetRunningLocally()) { reservedPeds = 0; reservedVehs = 0; reservedObjs = 0; pInfo->GetReservations(reservedPeds, reservedVehs, reservedObjs); if (reservedPeds != 0 || reservedVehs != 0 || reservedObjs != 0) { if (!playersNearbyCalculated) { NetworkInterface::GetObjectManager().GetPlayersNearbyInScope(playersNearbyInPedScope, playersNearbyInVehScope, playersNearbyInObjScope); playersNearby = playersNearbyInPedScope | playersNearbyInVehScope | playersNearbyInObjScope; playersNearbyCalculated = true; } if (playersNearby != 0) { bool bParticipantNearbyInPedScope = false; bool bParticipantNearbyInVehScope = false; bool bParticipantNearbyInObjScope = false; for (u32 p=0; pGetActiveParticipants() & playerIndex)) { Assert(playersNearbyCalculated); if (playersNearbyInPedScope & playerIndex) { bParticipantNearbyInPedScope = true; } if (playersNearbyInVehScope & playerIndex) { bParticipantNearbyInVehScope = true; } if (playersNearbyInObjScope & playerIndex) { bParticipantNearbyInObjScope = true; } } } if (!bParticipantNearbyInPedScope) { reservedPeds = 0; } if (!bParticipantNearbyInVehScope) { reservedVehs = 0; } if (!bParticipantNearbyInObjScope) { reservedObjs = 0; } } } if (reservedPeds>0 || reservedVehs>0 || reservedObjs>0) { grcDebugDraw::AddDebugOutput("%s: %d/%d peds, %d/%d vehicles, %d/%d objects", pInfo->GetScriptId().GetScriptName(), pInfo->GetCreatedPeds(), reservedPeds, pInfo->GetCreatedVehicles(), reservedVehs, pInfo->GetCreatedObjects(), reservedObjs); } } } } #endif // __BANK #if __SCRIPT_MEM_CALC void CGameScriptHandlerMgr::CalculateMemoryUsage() { const strIndex* ignoreList = NULL; s32 numIgnores = 0; GetResourceIgnoreList(&ignoreList, numIgnores); m_TotalScriptVirtualMemory = 0; m_TotalScriptPhysicalMemory = 0; u32 TotalVirtualForResourcesWithoutStreamingIndex = 0; u32 TotalPhysicalForResourcesWithoutStreamingIndex = 0; const int maxLoadedInt = strStreamingEngine::GetInfo().GetLoadedInfoMap()->GetNumSlots() + strStreamingEngine::GetInfo().GetLoadedPersistentInfoMap()->GetNumSlots() + strStreamingEngine::GetInfo().GetRequestInfoMap()->GetNumSlots() + strStreamingEngine::GetInfo().GetLoadingInfoMap().GetNumSlots(); // Fixes B* 2175673 const int maxLoadedCount = CStreamVolumeMgr::GetStreamingIndicesCount(); const u16 maxLoaded = (u16) Min(maxLoadedInt + maxLoadedCount, 0xffff); strIndex *streamingIndicesForAllScriptsBackingStore = Alloca(strIndex, maxLoaded); atUserArray streamingIndicesForAllScripts(streamingIndicesForAllScriptsBackingStore, maxLoaded); strIndex *streamingIndicesForThisScriptBackingStore = Alloca(strIndex, maxLoaded); atUserArray streamingIndicesForThisScript(streamingIndicesForThisScriptBackingStore, maxLoaded); u32 ScriptThreadId = 0; bool bDisplayScriptDetails = true; bool bFilterScriptObjectDisplay = false; bool bExcludeScripts = false; #if __SCRIPT_MEM_DISPLAY bDisplayScriptDetails = CScriptDebug::GetDisplayDetailedScriptMemoryUsage(); bFilterScriptObjectDisplay = CScriptDebug::GetDisplayDetailedScriptMemoryUsageFiltered(); bExcludeScripts = CScriptDebug::GetExcludeScriptFromScriptMemoryUsage(); #endif // __SCRIPT_MEM_DISPLAY scriptHandlerMap::Iterator entry = m_scriptHandlers.CreateIterator(); for (entry.Start(); !entry.AtEnd(); entry.Next()) { CGameScriptHandler* handler = static_cast(entry.GetData()); if (!handler) continue; streamingIndicesForThisScript.Resize(0); u32 VirtualForResourcesWithoutStreamingIndexInThisScript = 0; u32 PhysicalForResourcesWithoutStreamingIndexInThisScript = 0; ClearMemoryDebugInfoForMovieMeshes(true); handler->CalculateMemoryUsage(streamingIndicesForThisScript, ignoreList, numIgnores, VirtualForResourcesWithoutStreamingIndexInThisScript, PhysicalForResourcesWithoutStreamingIndexInThisScript, bDisplayScriptDetails, bFilterScriptObjectDisplay, 0); //STRFLAG_DONTDELETE); CalculateMemoryUsageForMovieMeshes(handler, VirtualForResourcesWithoutStreamingIndexInThisScript, PhysicalForResourcesWithoutStreamingIndexInThisScript, bDisplayScriptDetails); ScriptThreadId = 0; if (handler->GetThread()) { ScriptThreadId = (u32) handler->GetThread()->GetThreadId(); } if (ScriptThreadId != 0) { if (CStreamVolumeMgr::IsThereAVolumeOwnedBy((scrThreadId) ScriptThreadId)) { CStreamVolumeMgr::GetStreamingIndices(streamingIndicesForThisScript); #if __SCRIPT_MEM_DISPLAY if (bDisplayScriptDetails) { atArray streamingIndicesForStreamingVolume; CStreamVolumeMgr::GetStreamingIndices(streamingIndicesForStreamingVolume); u32 VirtualMemForVolume = 0; u32 PhysicalMemForVolume = 0; strStreamingEngine::GetInfo().GetObjectAndDependenciesSizes(streamingIndicesForStreamingVolume, VirtualMemForVolume, PhysicalMemForVolume, NULL, 0, true); grcDebugDraw::AddDebugOutput("%s(%u) Stream Volume %dK %dK", handler->GetScriptName(), ScriptThreadId, VirtualMemForVolume>>10, PhysicalMemForVolume>>10); } #endif // __SCRIPT_MEM_DISPLAY } } // Display the memory used by render targets for normal Bink movies (not mesh sets) CalculateMemoryUsageForNamedRenderTargets(handler, VirtualForResourcesWithoutStreamingIndexInThisScript, PhysicalForResourcesWithoutStreamingIndexInThisScript, bDisplayScriptDetails); #if __SCRIPT_MEM_DISPLAY if (CScriptDebug::GetDisplayScriptMemoryUsage()) { u32 VirtualMemForThisScript = 0; u32 PhysicalMemForThisScript = 0; strStreamingEngine::GetInfo().GetObjectAndDependenciesSizes(streamingIndicesForThisScript, VirtualMemForThisScript, PhysicalMemForThisScript, ignoreList, numIgnores, true); VirtualMemForThisScript += VirtualForResourcesWithoutStreamingIndexInThisScript; PhysicalMemForThisScript += PhysicalForResourcesWithoutStreamingIndexInThisScript; if (VirtualMemForThisScript > 0 || PhysicalMemForThisScript > 0) { grcDebugDraw::AddDebugOutput("%s(%u) Virtual %dK Physical %dK (for all resources, including deps)", handler->GetScriptName(), ScriptThreadId, VirtualMemForThisScript>>10, PhysicalMemForThisScript>>10); } } #endif // __SCRIPT_MEM_DISPLAY // Add all entries from streamingIndicesForThisScript to streamingIndicesForAllScripts // Should I remove duplicates at this stage? s32 indexCount = streamingIndicesForThisScript.GetCount(); for (s32 i=0; i m_TotalScriptVirtualMemoryPeak) { m_TotalScriptVirtualMemoryPeak = m_TotalScriptVirtualMemory; if (PARAM_scriptLogMemoryPeaks.Get()) Displayf("CGameScriptHandlerMgr : [SCRIPT][MEM_PEAK] : Virtual : %s : %10dK", NetworkInterface::IsInFreeMode() ? "MP" : "SP", m_TotalScriptVirtualMemoryPeak>>10); } if (m_TotalScriptPhysicalMemory > m_TotalScriptPhysicalMemoryPeak) { m_TotalScriptPhysicalMemoryPeak = m_TotalScriptPhysicalMemory; if (PARAM_scriptLogMemoryPeaks.Get()) Displayf("CGameScriptHandlerMgr : [SCRIPT][MEM_PEAK] : Physical : %s : %10dK", NetworkInterface::IsInFreeMode() ? "MP" : "SP", m_TotalScriptPhysicalMemoryPeak>>10); } #if __SCRIPT_MEM_DISPLAY if (CScriptDebug::GetDisplayScriptMemoryUsage()) { if (nTotalPathNodeVirtualMemory > 0 || nTotalPathNodePhysicalMemory > 0) { grcDebugDraw::AddDebugOutput("%s(%d) Virtual %dK Physical %dK", "Script Path Nodes", -1, nTotalPathNodeVirtualMemory>>10, nTotalPathNodePhysicalMemory>>10); } } #endif // __SCRIPT_MEM_DISPLAY // periodically do a test to see if the script streaming memory has exceeded its limit if (m_streamingMemTestTimer.GetMsTime() > static_cast(STREAMING_MEM_CHECK_TIME)) { #if __FINAL size_t virtualLimit = VIRTUAL_STREAMING_MEMORY_LIMIT; size_t physicalLimit = PHYSICAL_STREAMING_MEMORY_LIMIT; #else size_t virtualLimit = VIRTUAL_STREAMING_MEMORY_LIMIT_DBG; size_t physicalLimit = PHYSICAL_STREAMING_MEMORY_LIMIT_DBG; const char *overrideScriptRpfName = NULL; PARAM_override_script.Get(overrideScriptRpfName); if(overrideScriptRpfName && !stricmp(overrideScriptRpfName, "script_rel")) { virtualLimit = VIRTUAL_STREAMING_MEMORY_LIMIT; physicalLimit = PHYSICAL_STREAMING_MEMORY_LIMIT; } #endif if (NetworkInterface::IsInFreeMode() && !CPauseMenu::GetCurrenMissionActive() && !NetworkInterface::IsInSpectatorMode()) { virtualLimit = VIRTUAL_STREAMING_FREEMODE_MEMORY_LIMIT; physicalLimit = PHYSICAL_STREAMING_FREEMODE_MEMORY_LIMIT; } #if !ONE_STREAMING_HEAP if (((m_TotalScriptVirtualMemory>>10) > virtualLimit) || ((m_TotalScriptPhysicalMemory>>10) > physicalLimit)) #else if (((m_TotalScriptVirtualMemory>>10) + (m_TotalScriptPhysicalMemory>>10)) > virtualLimit +physicalLimit) #endif { m_lastStreamingEmergencyTimer.Reset(); } // check if streaming is trying to request too much data at once CPlayerInfo *pPlayerInfo = CGameWorld::GetMainPlayerInfo(); if (pPlayerInfo && !pPlayerInfo->AreControlsDisabled()) { bool emergencyHit = false; s32 indexCount = streamingIndicesForAllScripts.GetCount(); for (s32 i = 0; i < indexCount; ++i) { const strStreamingInfo& info = strStreamingEngine::GetInfo().GetStreamingInfoRef(streamingIndicesForAllScripts[i]); if (info.GetStatus() != STRINFO_LOADING && info.GetStatus() != STRINFO_LOADREQUESTED) { streamingIndicesForAllScripts[i] = strIndex(strIndex::INVALID_INDEX); } } u32 virt = 0; u32 phys = 0; strStreamingEngine::GetInfo().GetObjectAndDependenciesSizes(streamingIndicesForAllScripts, virt, phys, ignoreList, numIgnores, true); if ((virt + phys) >> 10 > TOTAL_STREAMING_REQUEST_TOTAL_LIMIT) { m_lastStreamingReqEmergencyTimer.Reset(); emergencyHit = true; } // check priority requests only if (!emergencyHit) { for (s32 i = 0; i < indexCount; ++i) { if (streamingIndicesForAllScripts[i] == strIndex(strIndex::INVALID_INDEX)) continue; const strStreamingInfo& info = strStreamingEngine::GetInfo().GetStreamingInfoRef(streamingIndicesForAllScripts[i]); if ((info.GetFlags() & STRFLAG_PRIORITY_LOAD) == 0) { streamingIndicesForAllScripts[i] = strIndex(strIndex::INVALID_INDEX); } } u32 virt = 0; u32 phys = 0; strStreamingEngine::GetInfo().GetObjectAndDependenciesSizes(streamingIndicesForAllScripts, virt, phys, ignoreList, numIgnores, true); if ((virt + phys) >> 10 > TOTAL_STREAMING_REQUEST_PRIO_LIMIT) { m_lastStreamingReqEmergencyTimer.Reset(); } } m_streamingMemTestTimer.Reset(); } } } void CGameScriptHandlerMgr::ClearMemoryDebugInfoForMovieMeshes(bool bTrackMemoryForMovieMeshes) const { m_bTrackMemoryForMovieMeshes = bTrackMemoryForMovieMeshes; m_ArrayOfModelsUsedByMovieMeshes.Reset(); m_MapOfMoviesUsedByMovieMeshes.Reset(); m_MapOfRenderTargetsUsedByMovieMeshes.Reset(); } void CGameScriptHandlerMgr::CalculateMemoryUsageForMovieMeshes(const CGameScriptHandler* SCRIPT_MEM_DISPLAY_ONLY(pScriptHandler), u32 &VirtualTotal, u32 &PhysicalTotal, bool SCRIPT_MEM_DISPLAY_ONLY(bDisplayScriptDetails)) const { // Models u32 NumberOfModels = m_ArrayOfModelsUsedByMovieMeshes.GetCount(); if (NumberOfModels > 0) { s32 totalPhysicalMemory = 0; s32 totalVirtualMemory = 0; s32 drawablePhysicalMemory = 0; s32 drawableVirtualMemory = 0; s32 texturePhysicalMemory = 0; s32 textureVirtualMemory = 0; s32 boundsPhysicalMemory = 0; s32 boundsVirtualMemory = 0; CStreamingDebug::GetMemoryStatsByAllocation(m_ArrayOfModelsUsedByMovieMeshes, totalPhysicalMemory, totalVirtualMemory, drawablePhysicalMemory, drawableVirtualMemory, texturePhysicalMemory, textureVirtualMemory, boundsPhysicalMemory, boundsVirtualMemory); VirtualTotal += totalVirtualMemory; PhysicalTotal += totalPhysicalMemory; #if __SCRIPT_MEM_DISPLAY if (bDisplayScriptDetails) { grcDebugDraw::AddDebugOutput("%s(%d) Total For %u Models in Mesh Sets : Virtual %dK Physical %dK", pScriptHandler->GetScriptName(), pScriptHandler->GetThread()->GetThreadId(), NumberOfModels, totalVirtualMemory>>10, totalPhysicalMemory>>10); } #endif // __SCRIPT_MEM_DISPLAY } // Movies u32 virtualSize = 0; u32 physicalSize = 0; u32 NumberOfMovies = m_MapOfMoviesUsedByMovieMeshes.GetNumUsed(); if (NumberOfMovies > 0) { #if __SCRIPT_MEM_DISPLAY if (bDisplayScriptDetails) { grcDebugDraw::AddDebugOutput("%s(%d) Movies used in Mesh Sets", pScriptHandler->GetScriptName(), pScriptHandler->GetThread()->GetThreadId()); } #endif // __SCRIPT_MEM_DISPLAY atMap::Iterator MovieMapIterator = m_MapOfMoviesUsedByMovieMeshes.CreateIterator(); while (!MovieMapIterator.AtEnd()) { u32 movieHandle = MovieMapIterator.GetKey(); // Is there a way to get the name of the movie from its handle? u32 virtSizeForThisMovie = g_movieMgr.GetMemoryUsage(movieHandle); virtualSize += virtSizeForThisMovie; #if __SCRIPT_MEM_DISPLAY if (bDisplayScriptDetails) { grcDebugDraw::AddDebugOutput("Movie Handle=%u: used %d times : Virtual %dK", movieHandle, MovieMapIterator.GetData(), virtSizeForThisMovie>>10); } #endif // __SCRIPT_MEM_DISPLAY MovieMapIterator.Next(); } VirtualTotal += virtualSize; PhysicalTotal += physicalSize; #if __SCRIPT_MEM_DISPLAY if (bDisplayScriptDetails) { grcDebugDraw::AddDebugOutput("%s(%d) Total For Movies in Mesh Sets : Virtual %dK", pScriptHandler->GetScriptName(), pScriptHandler->GetThread()->GetThreadId(), virtualSize>>10); } #endif // __SCRIPT_MEM_DISPLAY } // Render Targets virtualSize = 0; physicalSize = 0; u32 NumberOfRenderTargets = m_MapOfRenderTargetsUsedByMovieMeshes.GetNumUsed(); if (NumberOfRenderTargets > 0) { #if __SCRIPT_MEM_DISPLAY if (bDisplayScriptDetails) { grcDebugDraw::AddDebugOutput("%s(%d) Render Targets used in Mesh Sets", pScriptHandler->GetScriptName(), pScriptHandler->GetThread()->GetThreadId()); } #endif // __SCRIPT_MEM_DISPLAY atMap::Iterator RenderTargetIterator = m_MapOfRenderTargetsUsedByMovieMeshes.CreateIterator(); while (!RenderTargetIterator.AtEnd()) { CRenderTargetMgr::namedRendertarget *pRenderTarget = RenderTargetIterator.GetKey(); if (pRenderTarget) { u32 SizeForThisMovie = pRenderTarget->GetMemoryUsage(); physicalSize += SizeForThisMovie; #if __SCRIPT_MEM_DISPLAY if (bDisplayScriptDetails) { grcDebugDraw::AddDebugOutput("Render Target=%x: used %d times : Physical %dK", pRenderTarget, RenderTargetIterator.GetData(), SizeForThisMovie>>10); } #endif // __SCRIPT_MEM_DISPLAY } RenderTargetIterator.Next(); } VirtualTotal += virtualSize; PhysicalTotal += physicalSize; #if __SCRIPT_MEM_DISPLAY if (bDisplayScriptDetails) { grcDebugDraw::AddDebugOutput("%s(%d) Total For RenderTargets in Mesh Sets : Physical %dK", pScriptHandler->GetScriptName(), pScriptHandler->GetThread()->GetThreadId(), physicalSize>>10); } #endif // __SCRIPT_MEM_DISPLAY } ClearMemoryDebugInfoForMovieMeshes(false); } // Display the memory used by render targets for normal Bink movies (not mesh sets) void CGameScriptHandlerMgr::CalculateMemoryUsageForNamedRenderTargets(const CGameScriptHandler* pScriptHandler, u32& UNUSED_PARAM(virtualMemory), u32 &physicalMemory, bool SCRIPT_MEM_DISPLAY_ONLY(bDisplayScriptDetails)) const { if (pScriptHandler->GetThread()) { u32 physicalMemoryForThisThread = gRenderTargetMgr.GetMemoryUsageForNamedRenderTargets(pScriptHandler->GetThread()->GetThreadId()); physicalMemory += physicalMemoryForThisThread; #if __SCRIPT_MEM_DISPLAY if (bDisplayScriptDetails && (physicalMemoryForThisThread > 0)) { grcDebugDraw::AddDebugOutput("%s(%d) Total For RenderTargets in Movies (excluding movies used by mesh sets) : Physical %dK", pScriptHandler->GetScriptName(), pScriptHandler->GetThread()->GetThreadId(), physicalMemoryForThisThread>>10); } #endif // __SCRIPT_MEM_DISPLAY } } void CGameScriptHandlerMgr::AddToModelsUsedByMovieMeshes(u32 ModelIndex) { if (m_bTrackMemoryForMovieMeshes) { m_ArrayOfModelsUsedByMovieMeshes.PushAndGrow(ModelIndex); } } void CGameScriptHandlerMgr::AddToMoviesUsedByMovieMeshes(u32 MovieHandle) { if (m_bTrackMemoryForMovieMeshes) { u32 *pNumberOfTimesUsed = m_MapOfMoviesUsedByMovieMeshes.Access(MovieHandle); if (pNumberOfTimesUsed) { m_MapOfMoviesUsedByMovieMeshes[MovieHandle] = 1 + *pNumberOfTimesUsed; } else { m_MapOfMoviesUsedByMovieMeshes.Insert(MovieHandle, 1); } } } void CGameScriptHandlerMgr::AddToRenderTargetsUsedByMovieMeshes(CRenderTargetMgr::namedRendertarget *pNamedRenderTarget) { if (m_bTrackMemoryForMovieMeshes) { u32 *pNumberOfTimesUsed = m_MapOfRenderTargetsUsedByMovieMeshes.Access(pNamedRenderTarget); if (pNumberOfTimesUsed) { m_MapOfRenderTargetsUsedByMovieMeshes[pNamedRenderTarget] = 1 + *pNumberOfTimesUsed; } else { m_MapOfRenderTargetsUsedByMovieMeshes.Insert(pNamedRenderTarget, 1); } } } #endif // __SCRIPT_MEM_CALC #if __BANK void CGameScriptHandlerMgr::GetScriptDependencyList(atArray &theArray) { atArray localIndices; const strIndex* ignoreList = NULL; s32 numIgnores = 0; GetResourceIgnoreList(&ignoreList, numIgnores); // ignore vehicle resident texture dictionaries. Not sure why (copied from old mission cleanup code) scriptHandlerMap::Iterator entry = m_scriptHandlers.CreateIterator(); for (entry.Start(); !entry.AtEnd(); entry.Next()) { CGameScriptHandler* handler = static_cast(entry.GetData()); if (handler) { handler->GetStreamingIndices(localIndices, STRFLAG_DONTDELETE); } } for(int i=0;i(entry.GetData()); if (handler && handler->GetScriptName() && AssertVerify(ms_NumHandlersGetScriptName(); } } if (ms_NumHandlers == 0) { ms_Handlers[0] = "-- none --"; ms_NumHandlers = 1; } ms_pHandlerCombo->UpdateCombo("Script Handlers", &ms_HandlerComboIndex, ms_NumHandlers, (const char **)ms_Handlers); } #endif // __DEV } const CGameScriptHandler* CGameScriptHandlerMgr::GetScriptHandlerFromComboName(const char* scriptName) const { scriptHandlerMap::ConstIterator entry = m_scriptHandlers.CreateIterator(); for (entry.Start(); !entry.AtEnd(); entry.Next()) { CGameScriptHandler* handler = static_cast(entry.GetData()); if (handler && handler->GetScriptName() && !strcmp(handler->GetScriptName(), scriptName)) { return handler; } } return NULL; } CGameScriptHandler* CGameScriptHandlerMgr::GetScriptHandlerFromComboName(const char* scriptName) { scriptHandlerMap::Iterator entry = m_scriptHandlers.CreateIterator(); for (entry.Start(); !entry.AtEnd(); entry.Next()) { CGameScriptHandler* handler = static_cast(entry.GetData()); if (handler && handler->GetScriptName() && !strcmp(handler->GetScriptName(), scriptName)) { return handler; } } return NULL; } #endif // __BANK // gets the streaming objects to ignore when calculating or displaying resource memory usage void CGameScriptHandlerMgr::GetResourceIgnoreList(const strIndex** ignoreList, s32& numIgnores) const { const atArray& residentIgnoreList = gPopStreaming.GetResidentObjectList(); *ignoreList = residentIgnoreList.GetElements(); numIgnores = residentIgnoreList.GetCount(); } void CGameScriptHandlerMgr::WriteRemoteScriptHeader(const CGameScriptId& LOGGING_ONLY(scriptId), const char *LOGGING_ONLY(headerText), ...) { #if ENABLE_NETWORK_LOGGING char buffer[netLog::MAX_LOG_STRING]; va_list args; va_start(args, headerText); vsprintf(buffer, headerText, args); va_end(args); if(GetLog()) { GetLog()->Log("\t %s: %s\r\n", scriptId.GetLogName(), buffer); } #endif // #if ENABLE_NETWORK_LOGGING } bool CGameScriptHandlerMgr::HandleTimestampConflict(const CRemoteScriptInfo& scriptInfo) { bool bAddInfo = true; bool bDeleteExistingInfo = false; // watches out for 2 identical scripts running at once with the same timestamp. // this can happen for 2 reasons: // 1) a joining machine starts up and hosts a script immediately before being aware of other machines in the session (and the real host). // This really shouldn't happen: the joining machine should wait for the timeout time before starting up any scripts but we still need to handle // this problem in case it does arise. // 2) a new player is accepted by a host running the script on his own, who drops out immediately. The new player loses the host during the joining // process and starts a new session. The host has not broadcast a remote script info with 0 participants as he thinks there is a remaining // participant (the new player). CGameScriptId remoteScriptId = scriptInfo.GetScriptId(); unsigned remoteTimeStamp = remoteScriptId.GetTimeStamp(); const CGameScriptId* pExistingScriptId = NULL; u32 existingInfoSlot = 0; // set timestamp to 0 so that it matches ids of existing script handlers with differing timestamps remoteScriptId.ResetTimestamp(); // find an existing remote script info for this script for (u32 i=0; iGetTimeStamp(); if (gnetVerify(existingTimestamp != remoteTimeStamp)) { WriteRemoteScriptHeader(*pExistingScriptId, "** TIMESTAMP CONFLICT (Remote timestamp: %d) **", remoteTimeStamp); if (remoteTimeStamp > existingTimestamp) { #if __ASSERT // we should not have an active handler when we get a timestamp conflict scriptHandler* pHandler = GetScriptHandler(*pExistingScriptId); if (pHandler && pHandler->GetNetworkComponent() && pHandler->GetNetworkComponent()->GetState() == scriptHandlerNetComponent::NETSCRIPT_PLAYING) { gnetAssertf(0, "Two versions of script %s active with different timestamps! (Remote timestamp: %d)", pExistingScriptId->GetLogName(), remoteTimeStamp); return true; } #endif WriteRemoteScriptHeader(*pExistingScriptId, "Info removed"); bDeleteExistingInfo = true; existingInfoSlot = i; } else { WriteRemoteScriptHeader(scriptInfo.GetScriptId(), "Info not added"); // don't add this script info bAddInfo = false; } } break; } } if (bDeleteExistingInfo) { MoveActiveScriptToTerminatedQueue(existingInfoSlot); } return bAddInfo; } void CGameScriptHandlerMgr::MoveActiveScriptToTerminatedQueue(u32 activeScriptSlot) { CRemoteScriptInfo scriptInfo = m_remoteActiveScripts[activeScriptSlot]; scriptInfo.SetParticipants(0); scriptInfo.SetHost(NULL); WriteRemoteScriptHeader(scriptInfo.GetScriptId(), "Remote script has terminated, move to terminated queue"); m_remoteActiveScripts.Delete(activeScriptSlot); scriptHandler* pScriptHandler = GetScriptHandler(scriptInfo.GetScriptId()); // ignore the handler if it is running with a 0 timestamp. We only care about the previous instance of the script. bool bIgnoreZeroTimestamp = Tunables::GetInstance().TryAccess(CD_GLOBAL_HASH, ATSTRINGHASH("CLEANUP_SCRIPT_OBJECTS_FIX", 0x03bfbf68), true); if (!pScriptHandler || (bIgnoreZeroTimestamp && static_cast(pScriptHandler->GetScriptId()).GetTimeStamp() == 0)) { WriteRemoteScriptHeader(scriptInfo.GetScriptId(), "Cleanup objects, script not running locally"); // inform the object mgr that this script has terminated, so it can clean up any script objects that belonged to the script NetworkInterface::GetObjectManager().CleanupScriptObjects(scriptInfo.GetScriptId()); } #if __ASSERT for (u32 i=0; i