1
0
mirror of https://github.com/RaidMax/IW4M-Admin.git synced 2025-06-10 15:20:48 -05:00

implement initial url request functionality for game interface

This commit is contained in:
RaidMax
2023-06-03 16:48:03 -05:00
parent f19ca8a813
commit dfcf6e958c
6 changed files with 305 additions and 66 deletions

View File

@ -37,7 +37,7 @@ Setup()
level.clientDataKey = "clientData";
level.eventTypes = spawnstruct();
level.eventTypes.localClientEvent = "client_event";
level.eventTypes.eventAvailable = "EventAvailable";
level.eventTypes.clientDataReceived = "ClientDataReceived";
level.eventTypes.clientDataRequested = "ClientDataRequested";
level.eventTypes.setClientDataRequested = "SetClientDataRequested";
@ -70,6 +70,9 @@ Setup()
_SetDvarIfUninitialized( level.eventBus.outVar, "" );
_SetDvarIfUninitialized( level.commonKeys.enabled, 1 );
_SetDvarIfUninitialized( "sv_iw4madmin_integration_debug", 0 );
_SetDvarIfUninitialized( "GroupSeparatorChar", "" );
_SetDvarIfUninitialized( "RecordSeparatorChar", "" );
_SetDvarIfUninitialized( "UnitSeparatorChar", "" );
if ( GetDvarInt( level.commonKeys.enabled ) != 1 )
{
@ -77,35 +80,44 @@ Setup()
}
// start long running tasks
thread MonitorClientEvents();
thread MonitorEvents();
thread MonitorBus();
}
//////////////////////////////////
// Client Methods
//////////////////////////////////
MonitorClientEvents()
MonitorEvents()
{
level endon( level.eventTypes.gameEnd );
for ( ;; )
{
level waittill( level.eventTypes.localClientEvent, client );
level waittill( level.eventTypes.eventAvailable, event );
LogDebug( "Processing Event " + client.event.type + "-" + client.event.subtype );
LogDebug( "Processing Event " + event.type + "-" + event.subtype );
eventHandler = level.eventCallbacks[client.event.type];
eventHandler = level.eventCallbacks[event.type];
if ( IsDefined( eventHandler ) )
{
client [[eventHandler]]( client.event );
LogDebug( "notify client for " + client.event.type );
client notify( level.eventTypes.localClientEvent, client.event );
client notify( client.event.type, client.event );
if ( IsDefined( event.entity ) )
{
event.entity [[eventHandler]]( event );
}
else
{
[[eventHandler]]( event );
}
}
if ( IsDefined( event.entity ) )
{
LogDebug( "Notify client for " + event.type );
event.entity notify( event.type, event );
}
else
{
LogDebug( "Notify level for " + event.type );
level notify( event.type, event );
}
client.eventData = [];
}
}
@ -163,7 +175,7 @@ _Log( LogLevel, message )
{
for( i = 0; i < level.logger._logger.size; i++ )
{
[[level.logger._logger[i]]]( LogLevel, message );
[[level.logger._logger[i]]]( LogLevel, GetSubStr( message, 0, 1000 ) );
}
}
@ -246,18 +258,20 @@ DecrementClientMeta( metaKey, decrementValue, clientId )
SetClientMeta( metaKey, metaValue, clientId, direction )
{
data = "key=" + metaKey + "|value=" + metaValue;
data = [];
data["key"] = metaKey;
data["value"] = metaValue;
clientNumber = -1;
if ( IsDefined ( clientId ) )
{
data = data + "|clientId=" + clientId;
data["clientId"] = clientId;
clientNumber = -1;
}
if ( IsDefined( direction ) )
{
data = data + "|direction=" + direction;
data["direction"] = direction;
}
if ( IsPlayer( self ) )
@ -292,9 +306,12 @@ BuildEventRequest( responseExpected, eventType, eventSubtype, entOrId, data )
{
request = "1";
}
request = request + ";" + eventType + ";" + eventSubtype + ";" + entOrId + ";" + data;
return request;
data = BuildDataString( data );
groupSeparator = GetSubStr( GetDvar( "GroupSeparatorChar" ), 0, 1 );
request = request + groupSeparator + eventType + groupSeparator + eventSubtype + groupSeparator + entOrId + groupSeparator + data;
eturn request;
}
MonitorBus()
@ -319,7 +336,8 @@ MonitorBus()
}
LogDebug( "-> " + eventString );
NotifyClientEvent( strtok( eventString, ";" ) );
groupSeparator = GetSubStr( GetDvar( "GroupSeparatorChar" ), 0, 1 );
NotifyEvent( strtok( eventString, groupSeparator ) );
SetDvar( level.eventBus.outVar, "" );
}
@ -361,7 +379,7 @@ QueueEvent( request, eventType, notifyEntity )
return;
}
LogDebug("<- " + request );
LogDebug( "<- " + request );
SetDvar( level.eventBus.inVar, request );
}
@ -374,13 +392,13 @@ ParseDataString( data )
return [];
}
dataParts = strtok( data, "|" );
dataParts = strtok( data, GetSubStr( GetDvar( "RecordSeparatorChar" ), 0, 1 ) );
dict = [];
for ( i = 0; i < dataParts.size; i++ )
{
part = dataParts[i];
splitPart = strtok( part, "=" );
splitPart = strtok( part, GetSubStr( GetDvar( "UnitSeparatorChar" ), 0, 1 ) );
key = splitPart[0];
value = splitPart[1];
dict[key] = value;
@ -390,6 +408,26 @@ ParseDataString( data )
return dict;
}
BuildDataString( data )
{
if ( IsString( data ) )
{
return data;
}
dataString = "";
keys = GetArrayKeys( data );
unitSeparator = GetSubStr( GetDvar( "UnitSeparatorChar" ), 0, 1 );
recordSeparator = GetSubStr( GetDvar( "RecordSeparatorChar" ), 0, 1 );
for ( i = 0; i < keys.size; i++ )
{
dataString = dataString + keys[i] + unitSeparator + data[keys[i]] + recordSeparator;
}
return dataString;
}
NotifyClientEventTimeout( eventType )
{
// todo: make this actual eventing
@ -399,7 +437,7 @@ NotifyClientEventTimeout( eventType )
}
}
NotifyClientEvent( eventInfo )
NotifyEvent( eventInfo )
{
origin = [[level.overrideMethods[level.commonFunctions.getPlayerFromClientNum]]]( int( eventInfo[3] ) );
target = [[level.overrideMethods[level.commonFunctions.getPlayerFromClientNum]]]( int( eventInfo[4] ) );
@ -407,15 +445,10 @@ NotifyClientEvent( eventInfo )
event = spawnstruct();
event.type = eventInfo[1];
event.subtype = eventInfo[2];
event.data = eventInfo[5];
event.data = ParseDataString( eventInfo[5] );
event.origin = origin;
event.target = target;
if ( IsDefined( event.data ) )
{
LogDebug( "NotifyClientEvent->" + event.data );
}
if ( int( eventInfo[3] ) != -1 && !IsDefined( origin ) )
{
LogDebug( "origin is null but the slot id is " + int( eventInfo[3] ) );
@ -425,23 +458,15 @@ NotifyClientEvent( eventInfo )
LogDebug( "target is null but the slot id is " + int( eventInfo[4] ) );
}
if ( IsDefined( target ) )
client = event.origin;
if ( !IsDefined( client ) )
{
client = event.target;
}
else if ( IsDefined( origin ) )
{
client = event.origin;
}
else
{
LogDebug( "Neither origin or target are set but we are a Client Event, aborting" );
return;
}
client.event = event;
level notify( level.eventTypes.localClientEvent, client );
event.entity = client;
level notify( level.eventTypes.eventAvailable, event );
}
AddClientCommand( commandName, shouldRunAsTarget, callback, shouldOverwrite )
@ -461,7 +486,6 @@ AddClientCommand( commandName, shouldRunAsTarget, callback, shouldOverwrite )
OnClientDataReceived( event )
{
event.data = ParseDataString( event.data );
clientData = self.pers[level.clientDataKey];
if ( event.subtype == "Fail" )
@ -497,7 +521,7 @@ OnClientDataReceived( event )
OnExecuteCommand( event )
{
data = ParseDataString( event.data );
data = event.data;
response = "";
command = level.clientCommandCallbacks[event.subtype];
@ -527,8 +551,7 @@ OnExecuteCommand( event )
OnSetClientDataCompleted( event )
{
data = ParseDataString( event.data );
LogDebug( "Set Client Data -> subtype = " + CoerceUndefined( event.subType ) + ", status = " + CoerceUndefined( data["status"] ) );
LogDebug( "Set Client Data -> subtype = " + CoerceUndefined( event.subType ) + ", status = " + CoerceUndefined( event.data["status"] ) );
}
CoerceUndefined( object )

View File

@ -85,7 +85,7 @@ WaitForClientEvents()
for ( ;; )
{
self waittill( level.eventTypes.localClientEvent, event );
self waittill( level.eventTypes.eventAvailable, event );
scripts\_integration_base::LogDebug( "Received client event " + event.type );

View File

@ -45,8 +45,14 @@ Setup()
level.eventTypes.joinSpec = "joined_spectators";
level.eventTypes.spawned = "spawned_player";
level.eventTypes.gameEnd = "game_ended";
level.eventTypes.urlRequested = "UrlRequested";
level.eventTypes.urlRequestCompleted = "UrlRequestCompleted";
level.eventCallbacks[level.eventTypes.urlRequestCompleted] = ::OnUrlRequestCompletedCallback;
level.iw4madminIntegrationDefaultPerformance = 200;
level.notifyEntities = [];
level notify( level.notifyTypes.sharedFunctionsInitialized );
level waittill( level.notifyTypes.gameFunctionsInitialized );
@ -185,6 +191,135 @@ SaveTrackingMetrics()
scripts\_integration_base::IncrementClientMeta( "TotalShotsFired", change, self.persistentClientId );
}
// #region web requests
RequestUrlObject( request )
{
return RequestUrl( request.url, request.method, request.body, request.headers, request );
}
RequestUrl( url, method, body, headers, webNotify )
{
if ( !IsDefined( webNotify ) )
{
webNotify = SpawnStruct();
webNotify.url = url;
webNotify.method = method;
webNotify.body = body;
webNotify.headers = headers;
}
webNotify.index = GetNextNotifyEntity();
scripts\_integration_base::LogDebug( "next notify index is " + webNotify.index );
level.notifyEntities[webNotify.index] = webNotify;
data = [];
data["url"] = webNotify.url;
data["entity"] = webNotify.index;
if ( IsDefined( method ) )
{
data["method"] = method;
}
if ( IsDefined( body ) )
{
data["body"] = body;
}
if ( IsDefined( headers ) )
{
headerString = "";
keys = GetArrayKeys( headers );
for ( i = 0; i < keys.size; i++ )
{
headerString = headerString + keys[i] + ":" + headers[keys[i]] + ",";
}
data["headers"] = headerString;
}
webNotifyEvent = scripts\_integration_base::BuildEventRequest( true, level.eventTypes.urlRequested, "", webNotify.index, data );
thread scripts\_integration_base::QueueEvent( webNotifyEvent, level.eventTypes.urlRequested, webNotify );
webNotify thread WaitForUrlRequestComplete();
return webNotify;
}
WaitForUrlRequestComplete()
{
level endon( level.eventTypes.gameEnd );
timeoutResult = self [[level.overrideMethods[level.commonFunctions.waitTillAnyTimeout]]]( 30, level.eventTypes.urlRequestCompleted );
if ( timeoutResult == level.eventBus.timeoutKey )
{
scripts\_integration_base::LogWarning( "Request to " + self.url + " timed out" );
self notify ( level.eventTypes.urlRequestCompleted, "error" );
}
scripts\_integration_base::LogDebug( "Request to " + self.url + " completed" );
//self delete();
level.notifyEntities[self.index] = undefined;
}
OnUrlRequestCompletedCallback( event )
{
if ( !IsDefined( event ) || !IsDefined( event.data ) )
{
scripts\_integration_base::LogWarning( "Incomplete data for url request callback. [1]" );
return;
}
notifyEnt = event.data["entity"];
response = event.data["response"];
if ( !IsDefined( notifyEnt ) || !IsDefined( response ) )
{
scripts\_integration_base::LogWarning( "Incomplete data for url request callback. [2] " + scripts\_integration_base::CoerceUndefined( notifyEnt ) + " , " + scripts\_integration_base::CoerceUndefined( response ) );
return;
}
webNotify = level.notifyEntities[int( notifyEnt )];
if ( !IsDefined( webNotify.response ) )
{
webNotify.response = response;
}
else
{
webNotify.response = webNotify.response + response;
}
if ( int( event.data["remaining"] ) != 0 )
{
scripts\_integration_base::LogDebug( "Additional data available for url request " + notifyEnt + " (" + event.data["remaining"] + " chunks remaining)" );
return;
}
scripts\_integration_base::LogDebug( "Notifying " + notifyEnt + " that url request completed" );
webNotify notify( level.eventTypes.urlRequestCompleted, webNotify.response );
}
GetNextNotifyEntity()
{
max = level.notifyEntities.size + 1;
for ( i = 0; i < max; i++ )
{
if ( !IsDefined( level.notifyEntities[i] ) )
{
return i;
}
}
}
// #end region
// #region team balance
OnPlayerDisconnect()