#include common_scripts\utility; #include maps\mp\_utility; #include maps\mp\gametypes\_hud_util; #include maps\mp\gametypes\_playerlogic; init() { // setup default vars level.eventBus = spawnstruct(); level.eventBus.inVar = "sv_iw4madmin_in"; level.eventBus.outVar = "sv_iw4madmin_out"; level.clientDataKey = "clientData"; level.eventTypes = spawnstruct(); level.eventTypes.clientDataReceived = "ClientDataReceived"; level.eventTypes.clientDataRequested = "ClientDataRequested"; level.eventTypes.executeCommandRequested = "ExecuteCommandRequested"; SetDvarIfUninitialized( level.eventBus.inVar, "" ); SetDvarIfUninitialized( level.eventBus.outVar, "" ); SetDvarIfUninitialized( "sv_iw4madmin_integration_enabled", 1 ); // map the event type to the handler level.eventCallbacks = []; level.eventCallbacks[level.eventTypes.clientDataReceived] = ::OnClientDataReceived; level.eventCallbacks[level.eventTypes.executeCommandRequested] = ::OnExecuteCommand; // start long running tasks level thread PlayerWaitEvents(); level thread MonitorBus(); level thread OnPlayerConnect(); } ////////////////////////////////// // Client Methods ////////////////////////////////// OnPlayerConnect() { level endon ( "disconnect" ); for ( ;; ) { level waittill( "connected", player ); player.pers[level.clientDataKey] = spawnstruct(); player thread OnPlayerSpawned(); } } OnPlayerSpawned() { self endon( "disconnect" ); for ( ;; ) { self waittill( "spawned_player" ); self PlayerConnectEvents(); } } DisplayWelcomeData() { self endon( "disconnect" ); clientData = self.pers[level.clientDataKey]; self IPrintLnBold( "Welcome, your level is ^5" + clientData.permissionLevel ); wait (2.0); self IPrintLnBold( "You were last seen ^5" + clientData.lastConnection ); } PlayerConnectEvents() { self endon( "disconnect" ); clientData = self.pers[level.clientDataKey]; if ( isDefined( clientData.state ) && clientData.state == "complete" ) { return; } self RequestClientBasicData(); // example of requesting meta from IW4MAdmin // self RequestClientMeta( "LastServerPlayed" ); } PlayerWaitEvents() { level endon( "game_ended" ); self endon( "disconnect" ); for ( ;; ) { level waittill( "client_event", client ); /#self IPrintLn("Processing Event " + client.event.type + "-" + client.event.subtype );#/ eventHandler = level.eventCallbacks[client.event.type]; if ( isDefined( eventHandler ) ) { client [[eventHandler]]( client.event ); } client.eventData = []; } } ////////////////////////////////// // Helper Methods ////////////////////////////////// RequestClientMeta( metaKey ) { getClientMetaEvent = BuildEventRequest( true, level.eventTypes.clientDataRequested, "Meta", self, metaKey ); self thread QueueEvent( getClientMetaEvent, level.eventTypes.clientDataRequested ); } RequestClientBasicData() { getClientDataEvent = BuildEventRequest( true, level.eventTypes.clientDataRequested, "None", self, "" ); self thread QueueEvent( getClientDataEvent, level.eventTypes.clientDataRequested ); } BuildEventRequest( responseExpected, eventType, eventSubtype, client, data ) { if ( !isDefined( data ) ) { data = ""; } if ( !isDefined( eventSubtype ) ) { eventSubtype = "None"; } request = "0"; if ( responseExpected ) { request = "1"; } request = request + ";" + eventType + ";" + eventSubtype + ";" + client getEntityNumber() + ";" + data; return request; } MonitorBus() { level endon( "game_ended" ); for( ;; ) { wait ( 0.25 ); // check to see if IW4MAdmin is ready to receive more data if ( getDvar( level.eventBus.inVar ) == "" ) { level notify( "bus_ready" ); } eventString = getDvar( level.eventBus.outVar ); if ( eventString == "" ) { continue; } /#IPrintLn( "-> " + eventString );#/ NotifyClientEvent( strtok( eventString, ";" ) ); SetDvar( level.eventBus.outVar, "" ); } } QueueEvent( request, eventType ) { self endon( "disconnect" ); start = GetTime(); maxWait = 15 * 1000; // 15 seconds timedOut = ""; while ( GetDvar( level.eventBus.inVar ) != "" && ( GetTime() - start ) < maxWait ) { level waittill_notify_or_timeout( "bus_ready", 5 ); if ( GetDvar( level.eventBus.inVar ) != "" ) { /#self IPrintLn("A request is already in progress...");#/ timedOut = "set"; continue; } timedOut = "unset"; } if ( timedOut == "set") { /# self IPrintLn("Timed out waiting for response...");#/ if ( eventType == level.eventTypes.clientDataRequested ) // todo: this is dirty fix { self.pers["clientData"].state = "failed"; } return; } /#IPrintLn("<- " + request);#/ SetDvar( level.eventBus.inVar, request ); } ParseDataString( data ) { dataParts = strtok( data, "|" ); dict = []; counter = 0; foreach ( part in dataParts ) { splitPart = strtok( part, "=" ); key = splitPart[0]; value = splitPart[1]; dict[key] = value; dict[counter] = key; counter++; } return dict; } NotifyClientEvent( eventInfo ) { client = getPlayerFromClientNum( int( eventInfo[3] ) ); event = spawnstruct(); event.type = eventInfo[1]; event.subtype = eventInfo[2]; event.data = eventInfo[4]; /#IPrintLn(event.data);#/ client.event = event; level notify( "client_event", client ); } ////////////////////////////////// // Event Handlers ///////////////////////////////// OnClientDataReceived( event ) { event.data = ParseDataString( event.data ); clientData = self.pers[level.clientDataKey]; if ( event.subtype == "Meta" ) { if ( !isDefined( clientData["meta"] ) ) { clientData.meta = []; } metaKey = event.data[0]; clientData["meta"][metaKey] = event.data[metaKey]; return; } clientData.permissionLevel = event.data["level"]; clientData.lastConnection = event.data["lastConnection"]; clientData.state = "complete"; self thread DisplayWelcomeData(); } OnExecuteCommand( event ) { data = ParseDataString( event.data ); switch ( event.subtype ) { case "GiveWeapon": self GiveWeaponImpl( data ); break; case "TakeWeapons": self TakeWeaponsImpl(); break; case "SwitchTeams": self TeamSwitchImpl(); break; case "Hide": self HideImpl(); break; case "Unhide": self UnhideImpl(); break; case "Alert": self AlertImpl( data ); break; } } ////////////////////////////////// // Command Implementations ///////////////////////////////// GiveWeaponImpl( data ) { if ( IsAlive( self ) ) { self IPrintLnBold( "You have been given a new weapon" ); self GiveWeapon( data["weaponName"] ); self SwitchToWeapon( data["weaponName"] ); } } TakeWeaponsImpl() { if ( IsAlive( self ) ) { self TakeAllWeapons(); self IPrintLnBold( "All your weapons have been taken" ); } } TeamSwitchImpl() { if ( self.team == "allies" ) { self [[level.axis]](); } else { self [[level.allies]](); } } HideImpl() { if ( IsAlive( self ) ) { self Hide(); self IPrintLnBold( "You are now hidden" ); } } UnhideImpl() { if ( IsAlive( self ) ) { self Show(); self IPrintLnBold( "You are now visible" ); } } AlertImpl( data ) { self thread maps\mp\gametypes\_hud_message::oldNotifyMessage( data["alertType"], data["message"], "compass_waypoint_target", ( 1, 0, 0 ), "ui_mp_nukebomb_timer", 7.5 ); }