merge
This commit is contained in:
commit
3f71bc96f4
@ -32,11 +32,13 @@
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
|
||||
<PackageReference Include="RestEase" Version="1.5.7" />
|
||||
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
|
||||
<PackageReference Include="System.CommandLine.DragonFruit" Version="0.4.0-alpha.22272.1" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<ServerGarbageCollection>false</ServerGarbageCollection>
|
||||
<ServerGarbageCollection>true</ServerGarbageCollection>
|
||||
<ConcurrentGarbageCollection>true</ConcurrentGarbageCollection>
|
||||
<TieredCompilation>true</TieredCompilation>
|
||||
<LangVersion>Latest</LangVersion>
|
||||
|
@ -581,9 +581,9 @@ namespace IW4MAdmin.Application
|
||||
throw lastException;
|
||||
}
|
||||
|
||||
if (successServers != config.Servers.Length)
|
||||
if (successServers != config.Servers.Length && !AppContext.TryGetSwitch("NoConfirmPrompt", out _))
|
||||
{
|
||||
if (!Utilities.PromptBool(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_START_WITH_ERRORS"]))
|
||||
if (!Utilities.CurrentLocalization.LocalizationIndex["MANAGER_START_WITH_ERRORS"].PromptBool())
|
||||
{
|
||||
throw lastException;
|
||||
}
|
||||
|
@ -311,6 +311,10 @@
|
||||
{
|
||||
"Name": "tdm",
|
||||
"Alias": "Team Deathmatch"
|
||||
},
|
||||
{
|
||||
"Name": "zom",
|
||||
"Alias": "Zombies"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -1230,7 +1234,43 @@
|
||||
{
|
||||
"Alias": "Zoo",
|
||||
"Name": "mp_zoo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Alias": "Kino der Toten",
|
||||
"Name": "zombie_theater"
|
||||
},
|
||||
{
|
||||
"Alias": "Five",
|
||||
"Name": "zombie_pentagon"
|
||||
},
|
||||
{
|
||||
"Alias": "Ascension",
|
||||
"Name": "zombie_cosmodrome"
|
||||
},
|
||||
{
|
||||
"Alias": "Call of the Dead",
|
||||
"Name": "zombie_coast"
|
||||
},
|
||||
{
|
||||
"Alias": "Moon",
|
||||
"Name": "zombie_moon"
|
||||
},
|
||||
{
|
||||
"Alias": "Nacht Der Untoten",
|
||||
"Name": "zombie_cod5_prototype"
|
||||
},
|
||||
{
|
||||
"Alias": "Verrückt",
|
||||
"Name": "zombie_cod5_asylum"
|
||||
},
|
||||
{
|
||||
"Alias": "Shi No Numa",
|
||||
"Name": "zombie_cod5_sumpf"
|
||||
},
|
||||
{
|
||||
"Alias": "Der Riese",
|
||||
"Name": "zombie_cod5_factory"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -58,7 +58,7 @@ namespace IW4MAdmin.Application
|
||||
/// entrypoint of the application
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static async Task Main(string[] args)
|
||||
public static async Task Main(bool noConfirm = false, int? maxConcurrentRequests = 25, int? requestQueueLimit = 25)
|
||||
{
|
||||
AppDomain.CurrentDomain.SetData("DataDirectory", Utilities.OperatingDirectory);
|
||||
AppDomain.CurrentDomain.AssemblyResolve += (sender, eventArgs) =>
|
||||
@ -73,7 +73,15 @@ namespace IW4MAdmin.Application
|
||||
// added to be a bit more permissive with plugin references
|
||||
return AppDomain.CurrentDomain.GetAssemblies()
|
||||
.FirstOrDefault(asm => asm.FullName?.StartsWith(libraryName) ?? false);
|
||||
};
|
||||
};
|
||||
|
||||
if (noConfirm)
|
||||
{
|
||||
AppContext.SetSwitch("NoConfirmPrompt", true);
|
||||
}
|
||||
|
||||
Environment.SetEnvironmentVariable("MaxConcurrentRequests", (maxConcurrentRequests * Environment.ProcessorCount).ToString());
|
||||
Environment.SetEnvironmentVariable("RequestQueueLimit", requestQueueLimit.ToString());
|
||||
|
||||
Console.OutputEncoding = Encoding.UTF8;
|
||||
Console.ForegroundColor = ConsoleColor.Gray;
|
||||
@ -86,7 +94,7 @@ namespace IW4MAdmin.Application
|
||||
Console.WriteLine($" Version {Utilities.GetVersionAsString()}");
|
||||
Console.WriteLine("=====================================================");
|
||||
|
||||
await LaunchAsync(args);
|
||||
await LaunchAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -112,13 +120,13 @@ namespace IW4MAdmin.Application
|
||||
/// task that initializes application and starts the application monitoring and runtime tasks
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static async Task LaunchAsync(string[] args)
|
||||
private static async Task LaunchAsync()
|
||||
{
|
||||
restart:
|
||||
ITranslationLookup translationLookup = null;
|
||||
var logger = BuildDefaultLogger<Program>(new ApplicationConfiguration());
|
||||
Utilities.DefaultLogger = logger;
|
||||
logger.LogInformation("Begin IW4MAdmin startup. Version is {Version} {@Args}", Version, args);
|
||||
logger.LogInformation("Begin IW4MAdmin startup. Version is {Version}", Version);
|
||||
|
||||
try
|
||||
{
|
||||
@ -426,9 +434,9 @@ namespace IW4MAdmin.Application
|
||||
commandConfigHandler.BuildAsync().GetAwaiter().GetResult();
|
||||
|
||||
var appConfig = appConfigHandler.Configuration();
|
||||
var masterUri = /*Utilities.IsDevelopment
|
||||
var masterUri = Utilities.IsDevelopment
|
||||
? new Uri("http://127.0.0.1:8080")
|
||||
: appConfig?.MasterUrl ?? */new ApplicationConfiguration().MasterUrl;
|
||||
: appConfig?.MasterUrl ?? new ApplicationConfiguration().MasterUrl;
|
||||
var httpClient = new HttpClient
|
||||
{
|
||||
BaseAddress = masterUri,
|
||||
|
@ -14,8 +14,8 @@ public class ScriptPluginHelper
|
||||
{
|
||||
private readonly IManager _manager;
|
||||
private readonly ScriptPluginV2 _scriptPlugin;
|
||||
private readonly SemaphoreSlim _onRequestRunning = new(1, 5);
|
||||
private const int RequestTimeout = 500;
|
||||
private readonly SemaphoreSlim _onRequestRunning = new(1, 1);
|
||||
private const int RequestTimeout = 5000;
|
||||
|
||||
public ScriptPluginHelper(IManager manager, ScriptPluginV2 scriptPlugin)
|
||||
{
|
||||
|
Binary file not shown.
@ -1,263 +0,0 @@
|
||||
#include maps\mp\_utility;
|
||||
#include maps\mp\gametypes\_hud_util;
|
||||
#include common_scripts\utility;
|
||||
|
||||
init()
|
||||
{
|
||||
SetDvarIfUninitialized( "sv_customcallbacks", true );
|
||||
SetDvarIfUninitialized( "sv_framewaittime", 0.05 );
|
||||
SetDvarIfUninitialized( "sv_additionalwaittime", 0.1 );
|
||||
SetDvarIfUninitialized( "sv_maxstoredframes", 12 );
|
||||
SetDvarIfUninitialized( "sv_printradarupdates", 0 );
|
||||
SetDvarIfUninitialized( "sv_printradar_updateinterval", 500 );
|
||||
SetDvarIfUninitialized( "sv_iw4madmin_url", "http://127.0.0.1:1624" );
|
||||
|
||||
level thread onPlayerConnect();
|
||||
if (getDvarInt("sv_printradarupdates") == 1)
|
||||
{
|
||||
level thread runRadarUpdates();
|
||||
}
|
||||
|
||||
level waittill( "prematch_over" );
|
||||
level.callbackPlayerKilled = ::Callback_PlayerKilled;
|
||||
level.callbackPlayerDamage = ::Callback_PlayerDamage;
|
||||
level.callbackPlayerDisconnect = ::Callback_PlayerDisconnect;
|
||||
}
|
||||
|
||||
//It's called slightly different in T6
|
||||
//set_dvar_if_unset(dvar, val, reset)
|
||||
SetDvarIfUninitialized(dvar, val)
|
||||
{
|
||||
set_dvar_if_unset(dvar,val);
|
||||
}
|
||||
|
||||
onPlayerConnect( player )
|
||||
{
|
||||
for( ;; )
|
||||
{
|
||||
level waittill( "connected", player );
|
||||
player thread waitForFrameThread();
|
||||
player thread waitForAttack();
|
||||
}
|
||||
}
|
||||
|
||||
//Got added to T6 on April 2020
|
||||
waitForAttack()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
|
||||
self notifyOnPlayerCommand( "player_shot", "+attack" );
|
||||
self.lastAttackTime = 0;
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
self waittill( "player_shot" );
|
||||
|
||||
self.lastAttackTime = getTime();
|
||||
}
|
||||
}
|
||||
|
||||
runRadarUpdates()
|
||||
{
|
||||
interval = getDvarInt( "sv_printradar_updateinterval" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
for ( i = 0; i <= 17; i++ )
|
||||
{
|
||||
player = level.players[i];
|
||||
|
||||
if ( isDefined( player ) )
|
||||
{
|
||||
payload = player.guid + ";" + player.origin + ";" + player getPlayerAngles() + ";" + player.team + ";" + player.kills + ";" + player.deaths + ";" + player.score + ";" + player GetCurrentWeapon() + ";" + player.health + ";" + isAlive(player) + ";" + player.timePlayed["total"];
|
||||
logPrint( "LiveRadar;" + payload + "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
wait( interval / 1000 );
|
||||
}
|
||||
}
|
||||
|
||||
hitLocationToBone( hitloc )
|
||||
{
|
||||
switch( hitloc )
|
||||
{
|
||||
case "helmet":
|
||||
return "j_helmet";
|
||||
case "head":
|
||||
return "j_head";
|
||||
case "neck":
|
||||
return "j_neck";
|
||||
case "torso_upper":
|
||||
return "j_spineupper";
|
||||
case "torso_lower":
|
||||
return "j_spinelower";
|
||||
case "right_arm_upper":
|
||||
return "j_shoulder_ri";
|
||||
case "left_arm_upper":
|
||||
return "j_shoulder_le";
|
||||
case "right_arm_lower":
|
||||
return "j_elbow_ri";
|
||||
case "left_arm_lower":
|
||||
return "j_elbow_le";
|
||||
case "right_hand":
|
||||
return "j_wrist_ri";
|
||||
case "left_hand":
|
||||
return "j_wrist_le";
|
||||
case "right_leg_upper":
|
||||
return "j_hip_ri";
|
||||
case "left_leg_upper":
|
||||
return "j_hip_le";
|
||||
case "right_leg_lower":
|
||||
return "j_knee_ri";
|
||||
case "left_leg_lower":
|
||||
return "j_knee_le";
|
||||
case "right_foot":
|
||||
return "j_ankle_ri";
|
||||
case "left_foot":
|
||||
return "j_ankle_le";
|
||||
default:
|
||||
return "tag_origin";
|
||||
}
|
||||
}
|
||||
|
||||
waitForFrameThread()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
|
||||
self.currentAnglePosition = 0;
|
||||
self.anglePositions = [];
|
||||
|
||||
for (i = 0; i < getDvarInt( "sv_maxstoredframes" ); i++)
|
||||
{
|
||||
self.anglePositions[i] = self getPlayerAngles();
|
||||
}
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
self.anglePositions[self.currentAnglePosition] = self getPlayerAngles();
|
||||
wait( getDvarFloat( "sv_framewaittime" ) );
|
||||
self.currentAnglePosition = (self.currentAnglePosition + 1) % getDvarInt( "sv_maxstoredframes" );
|
||||
}
|
||||
}
|
||||
|
||||
waitForAdditionalAngles( logString, beforeFrameCount, afterFrameCount )
|
||||
{
|
||||
currentIndex = self.currentAnglePosition;
|
||||
wait( 0.05 * afterFrameCount );
|
||||
|
||||
self.angleSnapshot = [];
|
||||
|
||||
for( j = 0; j < self.anglePositions.size; j++ )
|
||||
{
|
||||
self.angleSnapshot[j] = self.anglePositions[j];
|
||||
}
|
||||
|
||||
anglesStr = "";
|
||||
collectedFrames = 0;
|
||||
i = currentIndex - beforeFrameCount;
|
||||
|
||||
while (collectedFrames < beforeFrameCount)
|
||||
{
|
||||
fixedIndex = i;
|
||||
if (i < 0)
|
||||
{
|
||||
fixedIndex = self.angleSnapshot.size - abs(i);
|
||||
}
|
||||
anglesStr += self.angleSnapshot[int(fixedIndex)] + ":";
|
||||
collectedFrames++;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i == currentIndex)
|
||||
{
|
||||
anglesStr += self.angleSnapshot[i] + ":";
|
||||
i++;
|
||||
}
|
||||
|
||||
collectedFrames = 0;
|
||||
|
||||
while (collectedFrames < afterFrameCount)
|
||||
{
|
||||
fixedIndex = i;
|
||||
if (i > self.angleSnapshot.size - 1)
|
||||
{
|
||||
fixedIndex = i % self.angleSnapshot.size;
|
||||
}
|
||||
anglesStr += self.angleSnapshot[int(fixedIndex)] + ":";
|
||||
collectedFrames++;
|
||||
i++;
|
||||
}
|
||||
|
||||
lastAttack = getTime() - self.lastAttackTime;
|
||||
isAlive = isAlive(self);
|
||||
|
||||
logPrint(logString + ";" + anglesStr + ";" + isAlive + ";" + lastAttack + "\n" );
|
||||
}
|
||||
|
||||
vectorScale( vector, scale )
|
||||
{
|
||||
return ( vector[0] * scale, vector[1] * scale, vector[2] * scale );
|
||||
}
|
||||
|
||||
Process_Hit( type, attacker, sHitLoc, sMeansOfDeath, iDamage, sWeapon )
|
||||
{
|
||||
if (sMeansOfDeath == "MOD_FALLING" || !isPlayer(attacker))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
victim = self;
|
||||
_attacker = attacker;
|
||||
|
||||
if ( !isPlayer( attacker ) && isDefined( attacker.owner ) )
|
||||
{
|
||||
_attacker = attacker.owner;
|
||||
}
|
||||
|
||||
else if( !isPlayer( attacker ) && sMeansOfDeath == "MOD_FALLING" )
|
||||
{
|
||||
_attacker = victim;
|
||||
}
|
||||
|
||||
location = victim GetTagOrigin( hitLocationToBone( sHitLoc ) );
|
||||
isKillstreakKill = false;
|
||||
if(!isPlayer(attacker))
|
||||
{
|
||||
isKillstreakKill = true;
|
||||
}
|
||||
if(maps/mp/killstreaks/_killstreaks::iskillstreakweapon(sWeapon))
|
||||
{
|
||||
isKillstreakKill = true;
|
||||
}
|
||||
|
||||
logLine = "Script" + type + ";" + _attacker.guid + ";" + victim.guid + ";" + _attacker GetTagOrigin("tag_eye") + ";" + location + ";" + iDamage + ";" + sWeapon + ";" + sHitLoc + ";" + sMeansOfDeath + ";" + _attacker getPlayerAngles() + ";" + int(gettime()) + ";" + isKillstreakKill + ";" + _attacker playerADS() + ";0;0";
|
||||
attacker thread waitForAdditionalAngles( logLine, 2, 2 );
|
||||
}
|
||||
|
||||
Callback_PlayerDamage( eInflictor, attacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex )
|
||||
{
|
||||
if ( level.teamBased && isDefined( attacker ) && ( self != attacker ) && isDefined( attacker.team ) && ( self.pers[ "team" ] == attacker.team ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( self.health - iDamage > 0 )
|
||||
{
|
||||
self Process_Hit( "Damage", attacker, sHitLoc, sMeansOfDeath, iDamage, sWeapon );
|
||||
}
|
||||
|
||||
self [[maps/mp/gametypes/_globallogic_player::callback_playerdamage]]( eInflictor, attacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex );
|
||||
}
|
||||
|
||||
Callback_PlayerKilled(eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration)
|
||||
{
|
||||
Process_Hit( "Kill", attacker, sHitLoc, sMeansOfDeath, iDamage, sWeapon );
|
||||
self [[maps/mp/gametypes/_globallogic_player::callback_playerkilled]]( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration );
|
||||
}
|
||||
|
||||
Callback_PlayerDisconnect()
|
||||
{
|
||||
level notify( "disconnected", self );
|
||||
self [[maps/mp/gametypes/_globallogic_player::callback_playerdisconnect]]();
|
||||
}
|
@ -1,6 +1,4 @@
|
||||
#include common_scripts\utility;
|
||||
#include maps\mp\_utility;
|
||||
#include maps\mp\gametypes\_hud_util;
|
||||
|
||||
Init()
|
||||
{
|
||||
@ -19,14 +17,17 @@ Setup()
|
||||
level.eventBus.timeoutKey = "timeout";
|
||||
level.eventBus.timeout = 30;
|
||||
|
||||
level.commonFunctions = spawnstruct();
|
||||
level.commonFunctions.setDvar = "SetDvarIfUninitialized";
|
||||
level.commonFunctions.isBot = "IsBot";
|
||||
level.commonFunctions = spawnstruct();
|
||||
level.commonFunctions.setDvar = "SetDvarIfUninitialized";
|
||||
level.commonFunctions.isBot = "IsBot";
|
||||
level.commonFunctions.getXuid = "GetXuid";
|
||||
level.commonFunctions.getPlayerFromClientNum = "GetPlayerFromClientNum";
|
||||
|
||||
level.commonKeys = spawnstruct();
|
||||
|
||||
level.notifyTypes = spawnstruct();
|
||||
level.notifyTypes.gameFunctionsInitialized = "GameFunctionsInitialized";
|
||||
level.notifyTypes.sharedFunctionsInitialized = "SharedFunctionsInitialized";
|
||||
level.notifyTypes.integrationBootstrapInitialized = "IntegrationBootstrapInitialized";
|
||||
|
||||
level.clientDataKey = "clientData";
|
||||
@ -102,9 +103,6 @@ OnPlayerConnect()
|
||||
}
|
||||
|
||||
player thread OnPlayerSpawned();
|
||||
player thread OnPlayerJoinedTeam();
|
||||
player thread OnPlayerJoinedSpectators();
|
||||
player thread PlayerTrackingOnInterval();
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,30 +117,6 @@ OnPlayerSpawned()
|
||||
}
|
||||
}
|
||||
|
||||
OnPlayerJoinedTeam()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
self waittill( "joined_team" );
|
||||
// join spec and join team occur at the same moment - out of order logging would be problematic
|
||||
wait( 0.25 );
|
||||
LogPrint( GenerateJoinTeamString( false ) );
|
||||
}
|
||||
}
|
||||
|
||||
OnPlayerJoinedSpectators()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
self waittill( "joined_spectators" );
|
||||
LogPrint( GenerateJoinTeamString( true ) );
|
||||
}
|
||||
}
|
||||
|
||||
OnGameEnded()
|
||||
{
|
||||
for ( ;; )
|
||||
@ -187,20 +161,6 @@ PlayerSpawnEvents()
|
||||
self RequestClientBasicData();
|
||||
}
|
||||
|
||||
PlayerTrackingOnInterval()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
wait ( 120 );
|
||||
if ( IsAlive( self ) )
|
||||
{
|
||||
self SaveTrackingMetrics();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MonitorClientEvents()
|
||||
{
|
||||
level endon( "game_ended" );
|
||||
@ -344,37 +304,6 @@ DecrementClientMeta( metaKey, decrementValue, clientId )
|
||||
SetClientMeta( metaKey, decrementValue, clientId, "decrement" );
|
||||
}
|
||||
|
||||
GenerateJoinTeamString( isSpectator )
|
||||
{
|
||||
team = self.team;
|
||||
|
||||
if ( IsDefined( self.joining_team ) )
|
||||
{
|
||||
team = self.joining_team;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( isSpectator || !IsDefined( team ) )
|
||||
{
|
||||
team = "spectator";
|
||||
}
|
||||
}
|
||||
|
||||
guid = self GetXuid();
|
||||
|
||||
if ( guid == "0" )
|
||||
{
|
||||
guid = self.guid;
|
||||
}
|
||||
|
||||
if ( !IsDefined( guid ) || guid == "0" )
|
||||
{
|
||||
guid = "undefined";
|
||||
}
|
||||
|
||||
return "JT;" + guid + ";" + self getEntityNumber() + ";" + team + ";" + self.name + "\n";
|
||||
}
|
||||
|
||||
SetClientMeta( metaKey, metaValue, clientId, direction )
|
||||
{
|
||||
data = "key=" + metaKey + "|value=" + metaValue;
|
||||
@ -400,39 +329,6 @@ SetClientMeta( metaKey, metaValue, clientId, direction )
|
||||
level thread QueueEvent( setClientMetaEvent, level.eventTypes.setClientDataRequested, self );
|
||||
}
|
||||
|
||||
SaveTrackingMetrics()
|
||||
{
|
||||
if ( !IsDefined( self.persistentClientId ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LogDebug( "Saving tracking metrics for " + self.persistentClientId );
|
||||
|
||||
if ( !IsDefined( self.lastShotCount ) )
|
||||
{
|
||||
self.lastShotCount = 0;
|
||||
}
|
||||
|
||||
currentShotCount = self [[level.overrideMethods["GetTotalShotsFired"]]]();
|
||||
change = currentShotCount - self.lastShotCount;
|
||||
self.lastShotCount = currentShotCount;
|
||||
|
||||
LogDebug( "Total Shots Fired increased by " + change );
|
||||
|
||||
if ( !IsDefined( change ) )
|
||||
{
|
||||
change = 0;
|
||||
}
|
||||
|
||||
if ( change == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IncrementClientMeta( "TotalShotsFired", change, self.persistentClientId );
|
||||
}
|
||||
|
||||
BuildEventRequest( responseExpected, eventType, eventSubtype, entOrId, data )
|
||||
{
|
||||
if ( !IsDefined( data ) )
|
||||
@ -565,8 +461,8 @@ NotifyClientEventTimeout( eventType )
|
||||
|
||||
NotifyClientEvent( eventInfo )
|
||||
{
|
||||
origin = getPlayerFromClientNum( int( eventInfo[3] ) );
|
||||
target = getPlayerFromClientNum( int( eventInfo[4] ) );
|
||||
origin = [[level.overrideMethods[level.commonFunctions.getPlayerFromClientNum]]]( int( eventInfo[3] ) );
|
||||
target = [[level.overrideMethods[level.commonFunctions.getPlayerFromClientNum]]]( int( eventInfo[4] ) );
|
||||
|
||||
event = spawnstruct();
|
||||
event.type = eventInfo[1];
|
||||
@ -608,24 +504,6 @@ NotifyClientEvent( eventInfo )
|
||||
level notify( level.eventTypes.localClientEvent, client );
|
||||
}
|
||||
|
||||
GetPlayerFromClientNum( clientNum )
|
||||
{
|
||||
if ( clientNum < 0 )
|
||||
{
|
||||
return undefined;
|
||||
}
|
||||
|
||||
for ( i = 0; i < level.players.size; i++ )
|
||||
{
|
||||
if ( level.players[i] getEntityNumber() == clientNum )
|
||||
{
|
||||
return level.players[i];
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
AddClientCommand( commandName, shouldRunAsTarget, callback, shouldOverwrite )
|
||||
{
|
||||
if ( IsDefined( level.clientCommandCallbacks[commandName] ) && IsDefined( shouldOverwrite ) && !shouldOverwrite )
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
Init()
|
||||
{
|
||||
level.eventBus.gamename = "IW4";
|
||||
|
||||
thread Setup();
|
||||
}
|
||||
|
||||
@ -12,13 +10,15 @@ Setup()
|
||||
level endon( "game_ended" );
|
||||
|
||||
// it's possible that the notify type has not been defined yet so we have to hard code it
|
||||
level waittill( "IntegrationBootstrapInitialized" );
|
||||
level waittill( "SharedFunctionsInitialized" );
|
||||
level.eventBus.gamename = "IW4";
|
||||
|
||||
scripts\_integration_base::RegisterLogger( ::Log2Console );
|
||||
|
||||
level.overrideMethods["GetTotalShotsFired"] = ::GetTotalShotsFired;
|
||||
level.overrideMethods[level.commonFunctions.setDvar] = ::_SetDvarIfUninitialized;
|
||||
level.overrideMethods[level.commonFunctions.isBot] = ::IsTestClient;
|
||||
level.overrideMethods[level.commonFunctions.getXuid] = ::_GetXUID;
|
||||
level.overrideMethods["waittill_notify_or_timeout"] = ::_waittill_notify_or_timeout;
|
||||
level.overrideMethods[level.commonFunctions.changeTeam] = ::ChangeTeam;
|
||||
level.overrideMethods[level.commonFunctions.getTeamCounts] = ::CountPlayers;
|
||||
@ -31,6 +31,8 @@ Setup()
|
||||
|
||||
RegisterClientCommands();
|
||||
|
||||
_SetDvarIfUninitialized( "sv_iw4madmin_autobalance", 0 );
|
||||
|
||||
level notify( level.notifyTypes.gameFunctionsInitialized );
|
||||
|
||||
if ( GetDvarInt( "sv_iw4madmin_integration_enabled" ) != 1 )
|
||||
@ -199,6 +201,11 @@ Log2Console( logLevel, message )
|
||||
PrintConsole( "[" + logLevel + "] " + message + "\n" );
|
||||
}
|
||||
|
||||
_GetXUID()
|
||||
{
|
||||
return self GetXUID();
|
||||
}
|
||||
|
||||
//////////////////////////////////
|
||||
// GUID helpers
|
||||
/////////////////////////////////
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
Init()
|
||||
{
|
||||
level.eventBus.gamename = "IW5";
|
||||
|
||||
thread Setup();
|
||||
}
|
||||
|
||||
@ -12,17 +10,21 @@ Setup()
|
||||
level endon( "game_ended" );
|
||||
|
||||
// it's possible that the notify type has not been defined yet so we have to hard code it
|
||||
level waittill( "IntegrationBootstrapInitialized" );
|
||||
level waittill( "SharedFunctionsInitialized" );
|
||||
level.eventBus.gamename = "IW5";
|
||||
|
||||
scripts\mp\_integration_base::RegisterLogger( ::Log2Console );
|
||||
scripts\_integration_base::RegisterLogger( ::Log2Console );
|
||||
|
||||
level.overrideMethods["GetTotalShotsFired"] = ::GetTotalShotsFired;
|
||||
level.overrideMethods["SetDvarIfUninitialized"] = ::_SetDvarIfUninitialized;
|
||||
level.overrideMethods["waittill_notify_or_timeout"] = ::_waittill_notify_or_timeout;
|
||||
level.overrideMethods[level.commonFunctions.isBot] = ::IsTestClient;
|
||||
level.overrideMethods[level.commonFunctions.getXuid] = ::_GetXUID;
|
||||
|
||||
RegisterClientCommands();
|
||||
|
||||
_SetDvarIfUninitialized( "sv_iw4madmin_autobalance", 0 );
|
||||
|
||||
level notify( level.notifyTypes.gameFunctionsInitialized );
|
||||
|
||||
if ( GetDvarInt( "sv_iw4madmin_integration_enabled" ) != 1 )
|
||||
@ -54,17 +56,17 @@ OnPlayerConnect()
|
||||
|
||||
RegisterClientCommands()
|
||||
{
|
||||
scripts\mp\_integration_base::AddClientCommand( "GiveWeapon", true, ::GiveWeaponImpl );
|
||||
scripts\mp\_integration_base::AddClientCommand( "TakeWeapons", true, ::TakeWeaponsImpl );
|
||||
scripts\mp\_integration_base::AddClientCommand( "SwitchTeams", true, ::TeamSwitchImpl );
|
||||
scripts\mp\_integration_base::AddClientCommand( "Hide", false, ::HideImpl );
|
||||
scripts\mp\_integration_base::AddClientCommand( "Alert", true, ::AlertImpl );
|
||||
scripts\mp\_integration_base::AddClientCommand( "Goto", false, ::GotoImpl );
|
||||
scripts\mp\_integration_base::AddClientCommand( "Kill", true, ::KillImpl );
|
||||
scripts\mp\_integration_base::AddClientCommand( "SetSpectator", true, ::SetSpectatorImpl );
|
||||
scripts\mp\_integration_base::AddClientCommand( "LockControls", true, ::LockControlsImpl );
|
||||
scripts\mp\_integration_base::AddClientCommand( "PlayerToMe", true, ::PlayerToMeImpl );
|
||||
scripts\mp\_integration_base::AddClientCommand( "NoClip", false, ::NoClipImpl );
|
||||
scripts\_integration_base::AddClientCommand( "GiveWeapon", true, ::GiveWeaponImpl );
|
||||
scripts\_integration_base::AddClientCommand( "TakeWeapons", true, ::TakeWeaponsImpl );
|
||||
scripts\_integration_base::AddClientCommand( "SwitchTeams", true, ::TeamSwitchImpl );
|
||||
scripts\_integration_base::AddClientCommand( "Hide", false, ::HideImpl );
|
||||
scripts\_integration_base::AddClientCommand( "Alert", true, ::AlertImpl );
|
||||
scripts\_integration_base::AddClientCommand( "Goto", false, ::GotoImpl );
|
||||
scripts\_integration_base::AddClientCommand( "Kill", true, ::KillImpl );
|
||||
scripts\_integration_base::AddClientCommand( "SetSpectator", true, ::SetSpectatorImpl );
|
||||
scripts\_integration_base::AddClientCommand( "LockControls", true, ::LockControlsImpl );
|
||||
scripts\_integration_base::AddClientCommand( "PlayerToMe", true, ::PlayerToMeImpl );
|
||||
scripts\_integration_base::AddClientCommand( "NoClip", false, ::NoClipImpl );
|
||||
}
|
||||
|
||||
WaitForClientEvents()
|
||||
@ -73,13 +75,13 @@ WaitForClientEvents()
|
||||
|
||||
// example of requesting a meta value
|
||||
lastServerMetaKey = "LastServerPlayed";
|
||||
// self scripts\mp\_integration_base::RequestClientMeta( lastServerMetaKey );
|
||||
// self scripts\_integration_base::RequestClientMeta( lastServerMetaKey );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
self waittill( level.eventTypes.localClientEvent, event );
|
||||
|
||||
scripts\mp\_integration_base::LogDebug( "Received client event " + event.type );
|
||||
scripts\_integration_base::LogDebug( "Received client event " + event.type );
|
||||
|
||||
if ( event.type == level.eventTypes.clientDataReceived && event.data[0] == lastServerMetaKey )
|
||||
{
|
||||
@ -109,6 +111,11 @@ Log2Console( logLevel, message )
|
||||
Print( "[" + logLevel + "] " + message + "\n" );
|
||||
}
|
||||
|
||||
_GetXUID()
|
||||
{
|
||||
return self GetXUID();
|
||||
}
|
||||
|
||||
//////////////////////////////////
|
||||
// GUID helpers
|
||||
/////////////////////////////////
|
||||
@ -126,14 +133,14 @@ SetPersistentData()
|
||||
{
|
||||
// give IW4MAdmin time to collect IP
|
||||
wait( 15 );
|
||||
scripts\mp\_integration_base::LogDebug( "Uploading persistent guid " + persistentGuid );
|
||||
scripts\mp\_integration_base::SetClientMeta( "PersistentClientGuid", persistentGuid );
|
||||
scripts\_integration_base::LogDebug( "Uploading persistent guid " + persistentGuid );
|
||||
scripts\_integration_base::SetClientMeta( "PersistentClientGuid", persistentGuid );
|
||||
return;
|
||||
}
|
||||
|
||||
guid = self SplitGuid();
|
||||
|
||||
scripts\mp\_integration_base::LogDebug( "Persisting client guid " + guidHigh + "," + guidLow );
|
||||
scripts\_integration_base::LogDebug( "Persisting client guid " + guidHigh + "," + guidLow );
|
||||
|
||||
self SetPlayerData( "bests", "none", guid["high"] );
|
||||
self SetPlayerData( "awards", "none", guid["low"] );
|
||||
|
@ -8,6 +8,9 @@ Setup()
|
||||
{
|
||||
level endon( "game_ended" );
|
||||
|
||||
// it's possible that the notify type has not been defined yet so we have to hard code it
|
||||
level waittill( "IntegrationBootstrapInitialized" );
|
||||
|
||||
level.commonFunctions.changeTeam = "ChangeTeam";
|
||||
level.commonFunctions.getTeamCounts = "GetTeamCounts";
|
||||
level.commonFunctions.getMaxClients = "GetMaxClients";
|
||||
@ -25,6 +28,7 @@ Setup()
|
||||
level.overrideMethods[level.commonFunctions.getClientKillStreak] = scripts\_integration_base::NotImplementedFunction;
|
||||
level.overrideMethods[level.commonFunctions.backupRestoreClientKillStreakData] = scripts\_integration_base::NotImplementedFunction;
|
||||
level.overrideMethods[level.commonFunctions.waitTillAnyTimeout] = scripts\_integration_base::NotImplementedFunction;
|
||||
level.overrideMethods["GetPlayerFromClientNum"] = ::GetPlayerFromClientNum;
|
||||
|
||||
// these can be overridden per game if needed
|
||||
level.commonKeys.team1 = "allies";
|
||||
@ -39,15 +43,13 @@ Setup()
|
||||
|
||||
level.iw4madminIntegrationDefaultPerformance = 200;
|
||||
|
||||
level notify( level.notifyTypes.sharedFunctionsInitialized );
|
||||
level waittill( level.notifyTypes.gameFunctionsInitialized );
|
||||
|
||||
if ( GetDvarInt( "sv_iw4madmin_integration_enabled" ) != 1 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( GetDvarInt( "sv_iw4madmin_autobalance" ) != 1 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
level thread OnPlayerConnect();
|
||||
}
|
||||
@ -59,7 +61,22 @@ OnPlayerConnect()
|
||||
for ( ;; )
|
||||
{
|
||||
level waittill( level.eventTypes.connect, player );
|
||||
|
||||
if ( scripts\_integration_base::_IsBot( player ) )
|
||||
{
|
||||
// we don't want to track bots
|
||||
continue;
|
||||
}
|
||||
|
||||
player thread OnPlayerJoinedTeam();
|
||||
player thread OnPlayerJoinedSpectators();
|
||||
player thread PlayerTrackingOnInterval();
|
||||
|
||||
if ( GetDvarInt( "sv_iw4madmin_autobalance" ) != 1 || !IsDefined( [[level.overrideMethods[level.commonFunctions.getTeamBased]]]() ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ![[level.overrideMethods[level.commonFunctions.getTeamBased]]]() )
|
||||
{
|
||||
continue;
|
||||
@ -449,3 +466,123 @@ GetClientPerformanceOrDefault()
|
||||
|
||||
return performance;
|
||||
}
|
||||
|
||||
GetPlayerFromClientNum( clientNum )
|
||||
{
|
||||
if ( clientNum < 0 )
|
||||
{
|
||||
return undefined;
|
||||
}
|
||||
|
||||
for ( i = 0; i < level.players.size; i++ )
|
||||
{
|
||||
if ( level.players[i] getEntityNumber() == clientNum )
|
||||
{
|
||||
return level.players[i];
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
OnPlayerJoinedTeam()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
self waittill( "joined_team" );
|
||||
// join spec and join team occur at the same moment - out of order logging would be problematic
|
||||
wait( 0.25 );
|
||||
LogPrint( GenerateJoinTeamString( false ) );
|
||||
}
|
||||
}
|
||||
|
||||
OnPlayerJoinedSpectators()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
self waittill( "joined_spectators" );
|
||||
LogPrint( GenerateJoinTeamString( true ) );
|
||||
}
|
||||
}
|
||||
|
||||
GenerateJoinTeamString( isSpectator )
|
||||
{
|
||||
team = self.team;
|
||||
|
||||
if ( IsDefined( self.joining_team ) )
|
||||
{
|
||||
team = self.joining_team;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( isSpectator || !IsDefined( team ) )
|
||||
{
|
||||
team = "spectator";
|
||||
}
|
||||
}
|
||||
|
||||
guid = self [[level.overrideMethods[level.commonFunctions.getXuid]]]();
|
||||
|
||||
if ( guid == "0" )
|
||||
{
|
||||
guid = self.guid;
|
||||
}
|
||||
|
||||
if ( !IsDefined( guid ) || guid == "0" )
|
||||
{
|
||||
guid = "undefined";
|
||||
}
|
||||
|
||||
return "JT;" + guid + ";" + self getEntityNumber() + ";" + team + ";" + self.name + "\n";
|
||||
}
|
||||
|
||||
PlayerTrackingOnInterval()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
wait ( 120 );
|
||||
if ( IsAlive( self ) )
|
||||
{
|
||||
self SaveTrackingMetrics();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SaveTrackingMetrics()
|
||||
{
|
||||
if ( !IsDefined( self.persistentClientId ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
scripts\_integration_base::LogDebug( "Saving tracking metrics for " + self.persistentClientId );
|
||||
|
||||
if ( !IsDefined( self.lastShotCount ) )
|
||||
{
|
||||
self.lastShotCount = 0;
|
||||
}
|
||||
|
||||
currentShotCount = self [[level.overrideMethods["GetTotalShotsFired"]]]();
|
||||
change = currentShotCount - self.lastShotCount;
|
||||
self.lastShotCount = currentShotCount;
|
||||
|
||||
scripts\_integration_base::LogDebug( "Total Shots Fired increased by " + change );
|
||||
|
||||
if ( !IsDefined( change ) )
|
||||
{
|
||||
change = 0;
|
||||
}
|
||||
|
||||
if ( change == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
scripts\_integration_base::IncrementClientMeta( "TotalShotsFired", change, self.persistentClientId );
|
||||
}
|
@ -2,8 +2,6 @@
|
||||
|
||||
Init()
|
||||
{
|
||||
level.eventBus.gamename = "T5";
|
||||
|
||||
thread Setup();
|
||||
}
|
||||
|
||||
@ -12,16 +10,20 @@ Setup()
|
||||
level endon( "game_ended" );
|
||||
|
||||
// it's possible that the notify type has not been defined yet so we have to hard code it
|
||||
level waittill( "IntegrationBootstrapInitialized" );
|
||||
level waittill( "SharedFunctionsInitialized" );
|
||||
level.eventBus.gamename = "T5";
|
||||
|
||||
scripts\mp\_integration_base::RegisterLogger( ::Log2Console );
|
||||
scripts\_integration_base::RegisterLogger( ::Log2Console );
|
||||
|
||||
level.overrideMethods["GetTotalShotsFired"] = ::GetTotalShotsFired;
|
||||
level.overrideMethods["SetDvarIfUninitialized"] = ::_SetDvarIfUninitialized;
|
||||
level.overrideMethods["waittill_notify_or_timeout"] = ::_waittill_notify_or_timeout;
|
||||
level.overrideMethods[level.commonFunctions.getXuid] = ::_GetXUID;
|
||||
|
||||
RegisterClientCommands();
|
||||
|
||||
_SetDvarIfUninitialized( "sv_iw4madmin_autobalance", 0 );
|
||||
|
||||
level notify( level.notifyTypes.gameFunctionsInitialized );
|
||||
|
||||
if ( GetDvarInt( "sv_iw4madmin_integration_enabled" ) != 1 )
|
||||
@ -40,7 +42,7 @@ OnPlayerConnect()
|
||||
{
|
||||
level waittill( "connected", player );
|
||||
|
||||
if ( scripts\mp\_integration_base::_IsBot( player ) )
|
||||
if ( scripts\_integration_base::_IsBot( player ) )
|
||||
{
|
||||
// we don't want to track bots
|
||||
continue;
|
||||
@ -53,17 +55,17 @@ OnPlayerConnect()
|
||||
|
||||
RegisterClientCommands()
|
||||
{
|
||||
scripts\mp\_integration_base::AddClientCommand( "GiveWeapon", true, ::GiveWeaponImpl );
|
||||
scripts\mp\_integration_base::AddClientCommand( "TakeWeapons", true, ::TakeWeaponsImpl );
|
||||
scripts\mp\_integration_base::AddClientCommand( "SwitchTeams", true, ::TeamSwitchImpl );
|
||||
scripts\mp\_integration_base::AddClientCommand( "Hide", false, ::HideImpl );
|
||||
scripts\mp\_integration_base::AddClientCommand( "Alert", true, ::AlertImpl );
|
||||
scripts\mp\_integration_base::AddClientCommand( "Goto", false, ::GotoImpl );
|
||||
scripts\mp\_integration_base::AddClientCommand( "Kill", true, ::KillImpl );
|
||||
scripts\mp\_integration_base::AddClientCommand( "SetSpectator", true, ::SetSpectatorImpl );
|
||||
scripts\mp\_integration_base::AddClientCommand( "LockControls", true, ::LockControlsImpl );
|
||||
scripts\mp\_integration_base::AddClientCommand( "PlayerToMe", true, ::PlayerToMeImpl );
|
||||
scripts\mp\_integration_base::AddClientCommand( "NoClip", false, ::NoClipImpl );
|
||||
scripts\_integration_base::AddClientCommand( "GiveWeapon", true, ::GiveWeaponImpl );
|
||||
scripts\_integration_base::AddClientCommand( "TakeWeapons", true, ::TakeWeaponsImpl );
|
||||
scripts\_integration_base::AddClientCommand( "SwitchTeams", true, ::TeamSwitchImpl );
|
||||
scripts\_integration_base::AddClientCommand( "Hide", false, ::HideImpl );
|
||||
scripts\_integration_base::AddClientCommand( "Alert", true, ::AlertImpl );
|
||||
scripts\_integration_base::AddClientCommand( "Goto", false, ::GotoImpl );
|
||||
scripts\_integration_base::AddClientCommand( "Kill", true, ::KillImpl );
|
||||
scripts\_integration_base::AddClientCommand( "SetSpectator", true, ::SetSpectatorImpl );
|
||||
scripts\_integration_base::AddClientCommand( "LockControls", true, ::LockControlsImpl );
|
||||
scripts\_integration_base::AddClientCommand( "PlayerToMe", true, ::PlayerToMeImpl );
|
||||
scripts\_integration_base::AddClientCommand( "NoClip", false, ::NoClipImpl );
|
||||
}
|
||||
|
||||
WaitForClientEvents()
|
||||
@ -72,13 +74,13 @@ WaitForClientEvents()
|
||||
|
||||
// example of requesting a meta value
|
||||
lastServerMetaKey = "LastServerPlayed";
|
||||
// self scripts\mp\_integration_base::RequestClientMeta( lastServerMetaKey );
|
||||
// self scripts\_integration_base::RequestClientMeta( lastServerMetaKey );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
self waittill( level.eventTypes.localClientEvent, event );
|
||||
|
||||
scripts\mp\_integration_base::LogDebug( "Received client event " + event.type );
|
||||
scripts\_integration_base::LogDebug( "Received client event " + event.type );
|
||||
|
||||
if ( event.type == level.eventTypes.clientDataReceived && event.data[0] == lastServerMetaKey )
|
||||
{
|
||||
@ -129,6 +131,11 @@ God()
|
||||
}
|
||||
}
|
||||
|
||||
_GetXUID()
|
||||
{
|
||||
return self GetXUID();
|
||||
}
|
||||
|
||||
//////////////////////////////////
|
||||
// GUID helpers
|
||||
/////////////////////////////////
|
||||
@ -146,14 +153,14 @@ God()
|
||||
{
|
||||
// give IW4MAdmin time to collect IP
|
||||
wait( 15 );
|
||||
scripts\mp\_integration_base::LogDebug( "Uploading persistent guid " + persistentGuid );
|
||||
scripts\mp\_integration_base::SetClientMeta( "PersistentClientGuid", persistentGuid );
|
||||
scripts\_integration_base::LogDebug( "Uploading persistent guid " + persistentGuid );
|
||||
scripts\_integration_base::SetClientMeta( "PersistentClientGuid", persistentGuid );
|
||||
return;
|
||||
}
|
||||
|
||||
guid = self SplitGuid();
|
||||
|
||||
scripts\mp\_integration_base::LogDebug( "Persisting client guid " + guidHigh + "," + guidLow );
|
||||
scripts\_integration_base::LogDebug( "Persisting client guid " + guidHigh + "," + guidLow );
|
||||
|
||||
self SetPlayerData( "bests", "none", guid["high"] );
|
||||
self SetPlayerData( "awards", "none", guid["low"] );
|
||||
@ -395,7 +402,7 @@ NoClipImpl( event, data )
|
||||
|
||||
self IPrintLnBold( "NoClip enabled" );*/
|
||||
|
||||
scripts\mp\_integration_base::LogWarning( "NoClip is not supported on T5!" );
|
||||
scripts\_integration_base::LogWarning( "NoClip is not supported on T5!" );
|
||||
|
||||
}
|
||||
|
||||
|
552
GameFiles/GameInterface/_integration_t5zm.gsc
Normal file
552
GameFiles/GameInterface/_integration_t5zm.gsc
Normal file
@ -0,0 +1,552 @@
|
||||
#include common_scripts\utility;
|
||||
|
||||
Init()
|
||||
{
|
||||
thread Setup();
|
||||
}
|
||||
|
||||
Setup()
|
||||
{
|
||||
level endon( "game_ended" );
|
||||
|
||||
// it's possible that the notify type has not been defined yet so we have to hard code it
|
||||
level waittill( "SharedFunctionsInitialized" );
|
||||
level.eventBus.gamename = "T5";
|
||||
|
||||
scripts\_integration_base::RegisterLogger( ::Log2Console );
|
||||
|
||||
level.overrideMethods["GetTotalShotsFired"] = ::GetTotalShotsFired;
|
||||
level.overrideMethods["SetDvarIfUninitialized"] = ::_SetDvarIfUninitialized;
|
||||
level.overrideMethods["waittill_notify_or_timeout"] = ::_waittill_notify_or_timeout;
|
||||
level.overrideMethods["GetPlayerFromClientNum"] = ::_GetPlayerFromClientNum;
|
||||
|
||||
RegisterClientCommands();
|
||||
|
||||
_SetDvarIfUninitialized( "sv_iw4madmin_autobalance", 0 );
|
||||
|
||||
level notify( level.notifyTypes.gameFunctionsInitialized );
|
||||
|
||||
if ( GetDvarInt( "sv_iw4madmin_integration_enabled" ) != 1 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
level thread OnPlayerConnect();
|
||||
}
|
||||
|
||||
OnPlayerConnect()
|
||||
{
|
||||
level endon ( "game_ended" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
level waittill( "connected", player );
|
||||
|
||||
if ( scripts\_integration_base::_IsBot( player ) )
|
||||
{
|
||||
// we don't want to track bots
|
||||
continue;
|
||||
}
|
||||
|
||||
//player thread SetPersistentData();
|
||||
player thread WaitForClientEvents();
|
||||
}
|
||||
}
|
||||
|
||||
RegisterClientCommands()
|
||||
{
|
||||
scripts\_integration_base::AddClientCommand( "GiveWeapon", true, ::GiveWeaponImpl );
|
||||
scripts\_integration_base::AddClientCommand( "TakeWeapons", true, ::TakeWeaponsImpl );
|
||||
scripts\_integration_base::AddClientCommand( "SwitchTeams", true, ::TeamSwitchImpl );
|
||||
scripts\_integration_base::AddClientCommand( "Hide", false, ::HideImpl );
|
||||
scripts\_integration_base::AddClientCommand( "Alert", true, ::AlertImpl );
|
||||
scripts\_integration_base::AddClientCommand( "Goto", false, ::GotoImpl );
|
||||
scripts\_integration_base::AddClientCommand( "Kill", true, ::KillImpl );
|
||||
scripts\_integration_base::AddClientCommand( "SetSpectator", true, ::SetSpectatorImpl );
|
||||
scripts\_integration_base::AddClientCommand( "LockControls", true, ::LockControlsImpl );
|
||||
scripts\_integration_base::AddClientCommand( "PlayerToMe", true, ::PlayerToMeImpl );
|
||||
scripts\_integration_base::AddClientCommand( "NoClip", false, ::NoClipImpl );
|
||||
}
|
||||
|
||||
WaitForClientEvents()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
|
||||
// example of requesting a meta value
|
||||
lastServerMetaKey = "LastServerPlayed";
|
||||
// self scripts\_integration_base::RequestClientMeta( lastServerMetaKey );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
self waittill( level.eventTypes.localClientEvent, event );
|
||||
|
||||
scripts\_integration_base::LogDebug( "Received client event " + event.type );
|
||||
|
||||
if ( event.type == level.eventTypes.clientDataReceived && event.data[0] == lastServerMetaKey )
|
||||
{
|
||||
clientData = self.pers[level.clientDataKey];
|
||||
lastServerPlayed = clientData.meta[lastServerMetaKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GetTotalShotsFired()
|
||||
{
|
||||
return 0; //ZM has no shot tracking. TODO: add tracking function for event weapon_fired
|
||||
}
|
||||
|
||||
_SetDvarIfUninitialized(dvar, value)
|
||||
{
|
||||
if (GetDvar(dvar)=="" )
|
||||
{
|
||||
SetDvar(dvar, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
return GetDvar(dvar);
|
||||
}
|
||||
|
||||
_waittill_notify_or_timeout( msg, timer )
|
||||
{
|
||||
self endon( msg );
|
||||
wait( timer );
|
||||
}
|
||||
|
||||
Log2Console( logLevel, message )
|
||||
{
|
||||
Print( "[" + logLevel + "] " + message + "\n" );
|
||||
}
|
||||
|
||||
God()
|
||||
{
|
||||
|
||||
if ( !IsDefined( self.godmode ) )
|
||||
{
|
||||
self.godmode = false;
|
||||
}
|
||||
|
||||
if (!self.godmode )
|
||||
{
|
||||
self enableInvulnerability();
|
||||
self.godmode = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.godmode = false;
|
||||
self disableInvulnerability();
|
||||
}
|
||||
}
|
||||
|
||||
_GetPlayerFromClientNum( clientNum )
|
||||
{
|
||||
if ( clientNum < 0 )
|
||||
{
|
||||
return undefined;
|
||||
}
|
||||
|
||||
players = GetPlayers("all");
|
||||
|
||||
for ( i = 0; i < players.size; i++ )
|
||||
{
|
||||
scripts\_integration_base::LogDebug(i+"/"+players.size+ "=" + players[i].name);
|
||||
if ( players[i] getEntityNumber() == clientNum )
|
||||
{
|
||||
return players[i];
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
//////////////////////////////////
|
||||
// GUID helpers
|
||||
/////////////////////////////////
|
||||
|
||||
/*SetPersistentData()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
|
||||
guidHigh = self GetPlayerData( "bests", "none" );
|
||||
guidLow = self GetPlayerData( "awards", "none" );
|
||||
persistentGuid = guidHigh + "," + guidLow;
|
||||
guidIsStored = guidHigh != 0 && guidLow != 0;
|
||||
|
||||
if ( guidIsStored )
|
||||
{
|
||||
// give IW4MAdmin time to collect IP
|
||||
wait( 15 );
|
||||
scripts\_integration_base::LogDebug( "Uploading persistent guid " + persistentGuid );
|
||||
scripts\_integration_base::SetClientMeta( "PersistentClientGuid", persistentGuid );
|
||||
return;
|
||||
}
|
||||
|
||||
guid = self SplitGuid();
|
||||
|
||||
scripts\_integration_base::LogDebug( "Persisting client guid " + guidHigh + "," + guidLow );
|
||||
|
||||
self SetPlayerData( "bests", "none", guid["high"] );
|
||||
self SetPlayerData( "awards", "none", guid["low"] );
|
||||
}
|
||||
|
||||
SplitGuid()
|
||||
{
|
||||
guid = self GetGuid();
|
||||
|
||||
if ( isDefined( self.guid ) )
|
||||
{
|
||||
guid = self.guid;
|
||||
}
|
||||
|
||||
firstPart = 0;
|
||||
secondPart = 0;
|
||||
stringLength = 17;
|
||||
firstPartExp = 0;
|
||||
secondPartExp = 0;
|
||||
|
||||
for ( i = stringLength - 1; i > 0; i-- )
|
||||
{
|
||||
char = GetSubStr( guid, i - 1, i );
|
||||
if ( char == "" )
|
||||
{
|
||||
char = "0";
|
||||
}
|
||||
|
||||
if ( i > stringLength / 2 )
|
||||
{
|
||||
value = GetIntForHexChar( char );
|
||||
power = Pow( 16, secondPartExp );
|
||||
secondPart = secondPart + ( value * power );
|
||||
secondPartExp++;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = GetIntForHexChar( char );
|
||||
power = Pow( 16, firstPartExp );
|
||||
firstPart = firstPart + ( value * power );
|
||||
firstPartExp++;
|
||||
}
|
||||
}
|
||||
|
||||
split = [];
|
||||
split["low"] = int( secondPart );
|
||||
split["high"] = int( firstPart );
|
||||
|
||||
return split;
|
||||
}
|
||||
|
||||
Pow( num, exponent )
|
||||
{
|
||||
result = 1;
|
||||
while( exponent != 0 )
|
||||
{
|
||||
result = result * num;
|
||||
exponent--;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
GetIntForHexChar( char )
|
||||
{
|
||||
char = ToLower( char );
|
||||
// generated by co-pilot because I can't be bothered to make it more "elegant"
|
||||
switch( char )
|
||||
{
|
||||
case "0":
|
||||
return 0;
|
||||
case "1":
|
||||
return 1;
|
||||
case "2":
|
||||
return 2;
|
||||
case "3":
|
||||
return 3;
|
||||
case "4":
|
||||
return 4;
|
||||
case "5":
|
||||
return 5;
|
||||
case "6":
|
||||
return 6;
|
||||
case "7":
|
||||
return 7;
|
||||
case "8":
|
||||
return 8;
|
||||
case "9":
|
||||
return 9;
|
||||
case "a":
|
||||
return 10;
|
||||
case "b":
|
||||
return 11;
|
||||
case "c":
|
||||
return 12;
|
||||
case "d":
|
||||
return 13;
|
||||
case "e":
|
||||
return 14;
|
||||
case "f":
|
||||
return 15;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}*/
|
||||
|
||||
//////////////////////////////////
|
||||
// Command Implementations
|
||||
/////////////////////////////////
|
||||
|
||||
GiveWeaponImpl( event, data )
|
||||
{
|
||||
if ( !IsAlive( self ) )
|
||||
{
|
||||
return self.name + "^7 is not alive";
|
||||
}
|
||||
|
||||
self IPrintLnBold( "You have been given a new weapon" );
|
||||
self GiveWeapon( data["weaponName"] );
|
||||
self SwitchToWeapon( data["weaponName"] );
|
||||
|
||||
return self.name + "^7 has been given ^5" + data["weaponName"];
|
||||
}
|
||||
|
||||
TakeWeaponsImpl( event, data )
|
||||
{
|
||||
if ( !IsAlive( self ) )
|
||||
{
|
||||
return self.name + "^7 is not alive";
|
||||
}
|
||||
|
||||
self TakeAllWeapons();
|
||||
self IPrintLnBold( "All your weapons have been taken" );
|
||||
|
||||
return "Took weapons from " + self.name;
|
||||
}
|
||||
|
||||
TeamSwitchImpl( event, data )
|
||||
{
|
||||
if ( !IsAlive( self ) )
|
||||
{
|
||||
return self + "^7 is not alive";
|
||||
}
|
||||
|
||||
team = level.allies;
|
||||
|
||||
if ( self.team == "allies" )
|
||||
{
|
||||
team = level.axis;
|
||||
}
|
||||
|
||||
self IPrintLnBold( "You are being team switched" );
|
||||
wait( 2 );
|
||||
self [[team]]();
|
||||
|
||||
return self.name + "^7 switched to " + self.team;
|
||||
}
|
||||
|
||||
LockControlsImpl( event, data )
|
||||
{
|
||||
if ( !IsAlive( self ) )
|
||||
{
|
||||
return self.name + "^7 is not alive";
|
||||
}
|
||||
|
||||
if ( !IsDefined ( self.isControlLocked ) )
|
||||
{
|
||||
self.isControlLocked = false;
|
||||
}
|
||||
|
||||
if ( !self.isControlLocked )
|
||||
{
|
||||
self freezeControls( true );
|
||||
self God();
|
||||
self Hide();
|
||||
|
||||
info = [];
|
||||
info[ "alertType" ] = "Alert!";
|
||||
info[ "message" ] = "You have been frozen!";
|
||||
|
||||
self AlertImpl( undefined, info );
|
||||
|
||||
self.isControlLocked = true;
|
||||
|
||||
return self.name + "\'s controls are locked";
|
||||
}
|
||||
else
|
||||
{
|
||||
self freezeControls( false );
|
||||
self God();
|
||||
self Show();
|
||||
|
||||
self.isControlLocked = false;
|
||||
|
||||
return self.name + "\'s controls are unlocked";
|
||||
}
|
||||
}
|
||||
|
||||
NoClipImpl( event, data )
|
||||
{
|
||||
/*if ( !IsAlive( self ) )
|
||||
{
|
||||
self IPrintLnBold( "You are not alive" );
|
||||
}
|
||||
|
||||
if ( !IsDefined ( self.isNoClipped ) )
|
||||
{
|
||||
self.isNoClipped = false;
|
||||
}
|
||||
|
||||
if ( !self.isNoClipped )
|
||||
{
|
||||
self SetClientDvar( "sv_cheats", 1 );
|
||||
self SetClientDvar( "cg_thirdperson", 1 );
|
||||
self SetClientDvar( "sv_cheats", 0 );
|
||||
|
||||
self God();
|
||||
self Noclip();
|
||||
self Hide();
|
||||
|
||||
self.isNoClipped = true;
|
||||
|
||||
self IPrintLnBold( "NoClip enabled" );
|
||||
}
|
||||
else
|
||||
{
|
||||
self SetClientDvar( "sv_cheats", 1 );
|
||||
self SetClientDvar( "cg_thirdperson", 1 );
|
||||
self SetClientDvar( "sv_cheats", 0 );
|
||||
|
||||
self God();
|
||||
self Noclip();
|
||||
self Hide();
|
||||
|
||||
self.isNoClipped = false;
|
||||
|
||||
self IPrintLnBold( "NoClip disabled" );
|
||||
}
|
||||
|
||||
self IPrintLnBold( "NoClip enabled" );*/
|
||||
|
||||
scripts\_integration_base::LogWarning( "NoClip is not supported on T5!" );
|
||||
|
||||
}
|
||||
|
||||
HideImpl( event, data )
|
||||
{
|
||||
if ( !IsAlive( self ) )
|
||||
{
|
||||
self IPrintLnBold( "You are not alive" );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !IsDefined ( self.isHidden ) )
|
||||
{
|
||||
self.isHidden = false;
|
||||
}
|
||||
|
||||
if ( !self.isHidden )
|
||||
{
|
||||
self SetClientDvar( "sv_cheats", 1 );
|
||||
self SetClientDvar( "cg_thirdperson", 1 );
|
||||
self SetClientDvar( "sv_cheats", 0 );
|
||||
|
||||
self God();
|
||||
self Hide();
|
||||
|
||||
self.isHidden = true;
|
||||
|
||||
self IPrintLnBold( "Hide enabled" );
|
||||
}
|
||||
else
|
||||
{
|
||||
self SetClientDvar( "sv_cheats", 1 );
|
||||
self SetClientDvar( "cg_thirdperson", 0 );
|
||||
self SetClientDvar( "sv_cheats", 0 );
|
||||
|
||||
self God();
|
||||
self Show();
|
||||
|
||||
self.isHidden = false;
|
||||
|
||||
self IPrintLnBold( "Hide disabled" );
|
||||
}
|
||||
}
|
||||
|
||||
AlertImpl( event, data )
|
||||
{
|
||||
//self thread maps\mp\gametypes\_hud_message::oldNotifyMessage( data["alertType"], data["message"], undefined, ( 1, 0, 0 ), "mpl_sab_ui_suitcasebomb_timer", 7.5 );
|
||||
self IPrintLnBold(data["message"]);
|
||||
|
||||
return "Sent alert to " + self.name;
|
||||
}
|
||||
|
||||
GotoImpl( event, data )
|
||||
{
|
||||
if ( IsDefined( event.target ) )
|
||||
{
|
||||
return self GotoPlayerImpl( event.target );
|
||||
}
|
||||
else
|
||||
{
|
||||
return self GotoCoordImpl( data );
|
||||
}
|
||||
}
|
||||
|
||||
GotoCoordImpl( data )
|
||||
{
|
||||
if ( !IsAlive( self ) )
|
||||
{
|
||||
self IPrintLnBold( "You are not alive" );
|
||||
return;
|
||||
}
|
||||
|
||||
position = ( int( data["x"] ), int( data["y"] ), int( data["z"]) );
|
||||
self SetOrigin( position );
|
||||
self IPrintLnBold( "Moved to " + "("+ position[0] + "," + position[1] + "," + position[2] + ")" );
|
||||
}
|
||||
|
||||
GotoPlayerImpl( target )
|
||||
{
|
||||
if ( !IsAlive( target ) )
|
||||
{
|
||||
self IPrintLnBold( target.name + " is not alive" );
|
||||
return;
|
||||
}
|
||||
|
||||
self SetOrigin( target GetOrigin() );
|
||||
self IPrintLnBold( "Moved to " + target.name );
|
||||
}
|
||||
|
||||
PlayerToMeImpl( event, data )
|
||||
{
|
||||
if ( !IsAlive( self ) )
|
||||
{
|
||||
return self.name + " is not alive";
|
||||
}
|
||||
|
||||
self SetOrigin( event.origin GetOrigin() );
|
||||
return "Moved here " + self.name;
|
||||
}
|
||||
|
||||
KillImpl( event, data )
|
||||
{
|
||||
if ( !IsAlive( self ) )
|
||||
{
|
||||
return self.name + " is not alive";
|
||||
}
|
||||
|
||||
self Suicide();
|
||||
self IPrintLnBold( "You were killed by " + self.name );
|
||||
|
||||
return "You killed " + self.name;
|
||||
}
|
||||
|
||||
SetSpectatorImpl( event, data )
|
||||
{
|
||||
if ( self.pers["team"] == "spectator" )
|
||||
{
|
||||
return self.name + " is already spectating";
|
||||
}
|
||||
|
||||
self [[level.spectator]]();
|
||||
self IPrintLnBold( "You have been moved to spectator" );
|
||||
|
||||
return self.name + " has been moved to spectator";
|
||||
}
|
571
GameFiles/GameInterface/_integration_t6.gsc
Normal file
571
GameFiles/GameInterface/_integration_t6.gsc
Normal file
@ -0,0 +1,571 @@
|
||||
#include common_scripts\utility;
|
||||
#include maps\mp\_utility;
|
||||
|
||||
Init()
|
||||
{
|
||||
thread Setup();
|
||||
}
|
||||
|
||||
Setup()
|
||||
{
|
||||
level endon( "game_ended" );
|
||||
|
||||
// it's possible that the notify type has not been defined yet so we have to hard code it
|
||||
level waittill( "SharedFunctionsInitialized" );
|
||||
level.eventBus.gamename = "T6";
|
||||
|
||||
scripts\_integration_base::RegisterLogger( ::Log2Console );
|
||||
|
||||
level.overrideMethods["GetTotalShotsFired"] = ::GetTotalShotsFired;
|
||||
level.overrideMethods["SetDvarIfUninitialized"] = ::_SetDvarIfUninitialized;
|
||||
level.overrideMethods["waittill_notify_or_timeout"] = ::_waittill_notify_or_timeout;
|
||||
level.overrideMethods[level.commonFunctions.getXuid] = ::_GetXUID;
|
||||
|
||||
RegisterClientCommands();
|
||||
|
||||
_SetDvarIfUninitialized( "sv_iw4madmin_autobalance", 0 );
|
||||
|
||||
level notify( level.notifyTypes.gameFunctionsInitialized );
|
||||
|
||||
if ( GetDvarInt( "sv_iw4madmin_integration_enabled" ) != 1 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
level thread OnPlayerConnect();
|
||||
}
|
||||
|
||||
OnPlayerConnect()
|
||||
{
|
||||
level endon ( "game_ended" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
level waittill( "connected", player );
|
||||
|
||||
if ( scripts\_integration_base::_IsBot( player ) )
|
||||
{
|
||||
// we don't want to track bots
|
||||
continue;
|
||||
}
|
||||
|
||||
//player thread SetPersistentData();
|
||||
player thread WaitForClientEvents();
|
||||
}
|
||||
}
|
||||
|
||||
RegisterClientCommands()
|
||||
{
|
||||
scripts\_integration_base::AddClientCommand( "GiveWeapon", true, ::GiveWeaponImpl );
|
||||
scripts\_integration_base::AddClientCommand( "TakeWeapons", true, ::TakeWeaponsImpl );
|
||||
scripts\_integration_base::AddClientCommand( "SwitchTeams", true, ::TeamSwitchImpl );
|
||||
scripts\_integration_base::AddClientCommand( "Hide", false, ::HideImpl );
|
||||
scripts\_integration_base::AddClientCommand( "Alert", true, ::AlertImpl );
|
||||
scripts\_integration_base::AddClientCommand( "Goto", false, ::GotoImpl );
|
||||
scripts\_integration_base::AddClientCommand( "Kill", true, ::KillImpl );
|
||||
scripts\_integration_base::AddClientCommand( "SetSpectator", true, ::SetSpectatorImpl );
|
||||
scripts\_integration_base::AddClientCommand( "LockControls", true, ::LockControlsImpl );
|
||||
scripts\_integration_base::AddClientCommand( "PlayerToMe", true, ::PlayerToMeImpl );
|
||||
scripts\_integration_base::AddClientCommand( "NoClip", false, ::NoClipImpl );
|
||||
}
|
||||
|
||||
WaitForClientEvents()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
|
||||
// example of requesting a meta value
|
||||
lastServerMetaKey = "LastServerPlayed";
|
||||
// self scripts\_integration_base::RequestClientMeta( lastServerMetaKey );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
self waittill( level.eventTypes.localClientEvent, event );
|
||||
|
||||
scripts\_integration_base::LogDebug( "Received client event " + event.type );
|
||||
|
||||
if ( event.type == level.eventTypes.clientDataReceived && event.data[0] == lastServerMetaKey )
|
||||
{
|
||||
clientData = self.pers[level.clientDataKey];
|
||||
lastServerPlayed = clientData.meta[lastServerMetaKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GetTotalShotsFired()
|
||||
{
|
||||
return self.pers[ "total_shots" ];
|
||||
}
|
||||
|
||||
_SetDvarIfUninitialized(dvar, value)
|
||||
{
|
||||
maps\mp\_utility::set_dvar_if_unset(dvar, value);
|
||||
}
|
||||
|
||||
_waittill_notify_or_timeout( msg, timer )
|
||||
{
|
||||
self endon( msg );
|
||||
wait( timer );
|
||||
}
|
||||
|
||||
Log2Console( logLevel, message )
|
||||
{
|
||||
Print( "[" + logLevel + "] " + message + "\n" );
|
||||
}
|
||||
|
||||
God()
|
||||
{
|
||||
|
||||
if ( !IsDefined( self.godmode ) )
|
||||
{
|
||||
self.godmode = false;
|
||||
}
|
||||
|
||||
if (!self.godmode )
|
||||
{
|
||||
self enableInvulnerability();
|
||||
self.godmode = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.godmode = false;
|
||||
self disableInvulnerability();
|
||||
}
|
||||
}
|
||||
|
||||
_GetXUID()
|
||||
{
|
||||
return self GetXUID();
|
||||
}
|
||||
|
||||
//////////////////////////////////
|
||||
// GUID helpers
|
||||
/////////////////////////////////
|
||||
|
||||
/*SetPersistentData()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
|
||||
guidHigh = self GetPlayerData( "bests", "none" );
|
||||
guidLow = self GetPlayerData( "awards", "none" );
|
||||
persistentGuid = guidHigh + "," + guidLow;
|
||||
guidIsStored = guidHigh != 0 && guidLow != 0;
|
||||
|
||||
if ( guidIsStored )
|
||||
{
|
||||
// give IW4MAdmin time to collect IP
|
||||
wait( 15 );
|
||||
scripts\_integration_base::LogDebug( "Uploading persistent guid " + persistentGuid );
|
||||
scripts\_integration_base::SetClientMeta( "PersistentClientGuid", persistentGuid );
|
||||
return;
|
||||
}
|
||||
|
||||
guid = self SplitGuid();
|
||||
|
||||
scripts\_integration_base::LogDebug( "Persisting client guid " + guidHigh + "," + guidLow );
|
||||
|
||||
self SetPlayerData( "bests", "none", guid["high"] );
|
||||
self SetPlayerData( "awards", "none", guid["low"] );
|
||||
}
|
||||
|
||||
SplitGuid()
|
||||
{
|
||||
guid = self GetGuid();
|
||||
|
||||
if ( isDefined( self.guid ) )
|
||||
{
|
||||
guid = self.guid;
|
||||
}
|
||||
|
||||
firstPart = 0;
|
||||
secondPart = 0;
|
||||
stringLength = 17;
|
||||
firstPartExp = 0;
|
||||
secondPartExp = 0;
|
||||
|
||||
for ( i = stringLength - 1; i > 0; i-- )
|
||||
{
|
||||
char = GetSubStr( guid, i - 1, i );
|
||||
if ( char == "" )
|
||||
{
|
||||
char = "0";
|
||||
}
|
||||
|
||||
if ( i > stringLength / 2 )
|
||||
{
|
||||
value = GetIntForHexChar( char );
|
||||
power = Pow( 16, secondPartExp );
|
||||
secondPart = secondPart + ( value * power );
|
||||
secondPartExp++;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = GetIntForHexChar( char );
|
||||
power = Pow( 16, firstPartExp );
|
||||
firstPart = firstPart + ( value * power );
|
||||
firstPartExp++;
|
||||
}
|
||||
}
|
||||
|
||||
split = [];
|
||||
split["low"] = int( secondPart );
|
||||
split["high"] = int( firstPart );
|
||||
|
||||
return split;
|
||||
}
|
||||
|
||||
Pow( num, exponent )
|
||||
{
|
||||
result = 1;
|
||||
while( exponent != 0 )
|
||||
{
|
||||
result = result * num;
|
||||
exponent--;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
GetIntForHexChar( char )
|
||||
{
|
||||
char = ToLower( char );
|
||||
// generated by co-pilot because I can't be bothered to make it more "elegant"
|
||||
switch( char )
|
||||
{
|
||||
case "0":
|
||||
return 0;
|
||||
case "1":
|
||||
return 1;
|
||||
case "2":
|
||||
return 2;
|
||||
case "3":
|
||||
return 3;
|
||||
case "4":
|
||||
return 4;
|
||||
case "5":
|
||||
return 5;
|
||||
case "6":
|
||||
return 6;
|
||||
case "7":
|
||||
return 7;
|
||||
case "8":
|
||||
return 8;
|
||||
case "9":
|
||||
return 9;
|
||||
case "a":
|
||||
return 10;
|
||||
case "b":
|
||||
return 11;
|
||||
case "c":
|
||||
return 12;
|
||||
case "d":
|
||||
return 13;
|
||||
case "e":
|
||||
return 14;
|
||||
case "f":
|
||||
return 15;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}*/
|
||||
|
||||
//////////////////////////////////
|
||||
// Command Implementations
|
||||
/////////////////////////////////
|
||||
|
||||
GiveWeaponImpl( event, data )
|
||||
{
|
||||
if ( !IsAlive( self ) )
|
||||
{
|
||||
return self.name + "^7 is not alive";
|
||||
}
|
||||
|
||||
if ( isDefined( level.player_too_many_weapons_monitor ) && level.player_too_many_weapons_monitor )
|
||||
{
|
||||
level.player_too_many_weapons_monitor = false;
|
||||
self notify( "stop_player_too_many_weapons_monitor" );
|
||||
}
|
||||
|
||||
self IPrintLnBold( "You have been given a new weapon" );
|
||||
self GiveWeapon( data["weaponName"] );
|
||||
self SwitchToWeapon( data["weaponName"] );
|
||||
|
||||
return self.name + "^7 has been given ^5" + data["weaponName"];
|
||||
}
|
||||
|
||||
TakeWeaponsImpl( event, data )
|
||||
{
|
||||
if ( !IsAlive( self ) )
|
||||
{
|
||||
return self.name + "^7 is not alive";
|
||||
}
|
||||
|
||||
self TakeAllWeapons();
|
||||
self IPrintLnBold( "All your weapons have been taken" );
|
||||
|
||||
return "Took weapons from " + self.name;
|
||||
}
|
||||
|
||||
TeamSwitchImpl( event, data )
|
||||
{
|
||||
if ( !IsAlive( self ) )
|
||||
{
|
||||
return self + "^7 is not alive";
|
||||
}
|
||||
|
||||
team = level.allies;
|
||||
|
||||
if ( self.team == "allies" )
|
||||
{
|
||||
team = level.axis;
|
||||
}
|
||||
|
||||
self IPrintLnBold( "You are being team switched" );
|
||||
wait( 2 );
|
||||
self [[team]]();
|
||||
|
||||
return self.name + "^7 switched to " + self.team;
|
||||
}
|
||||
|
||||
LockControlsImpl( event, data )
|
||||
{
|
||||
if ( !IsAlive( self ) )
|
||||
{
|
||||
return self.name + "^7 is not alive";
|
||||
}
|
||||
|
||||
if ( !IsDefined ( self.isControlLocked ) )
|
||||
{
|
||||
self.isControlLocked = false;
|
||||
}
|
||||
|
||||
if ( !self.isControlLocked )
|
||||
{
|
||||
self freezeControls( true );
|
||||
self God();
|
||||
self Hide();
|
||||
|
||||
info = [];
|
||||
info[ "alertType" ] = "Alert!";
|
||||
info[ "message" ] = "You have been frozen!";
|
||||
|
||||
self AlertImpl( undefined, info );
|
||||
|
||||
self.isControlLocked = true;
|
||||
|
||||
return self.name + "\'s controls are locked";
|
||||
}
|
||||
else
|
||||
{
|
||||
self freezeControls( false );
|
||||
self God();
|
||||
self Show();
|
||||
|
||||
self.isControlLocked = false;
|
||||
|
||||
return self.name + "\'s controls are unlocked";
|
||||
}
|
||||
}
|
||||
|
||||
NoClipImpl( event, data )
|
||||
{
|
||||
/*if ( !IsAlive( self ) )
|
||||
{
|
||||
self IPrintLnBold( "You are not alive" );
|
||||
}
|
||||
|
||||
if ( !IsDefined ( self.isNoClipped ) )
|
||||
{
|
||||
self.isNoClipped = false;
|
||||
}
|
||||
|
||||
if ( !self.isNoClipped )
|
||||
{
|
||||
self SetClientDvar( "sv_cheats", 1 );
|
||||
self SetClientDvar( "cg_thirdperson", 1 );
|
||||
self SetClientDvar( "sv_cheats", 0 );
|
||||
|
||||
self God();
|
||||
self Noclip();
|
||||
self Hide();
|
||||
|
||||
self.isNoClipped = true;
|
||||
|
||||
self IPrintLnBold( "NoClip enabled" );
|
||||
}
|
||||
else
|
||||
{
|
||||
self SetClientDvar( "sv_cheats", 1 );
|
||||
self SetClientDvar( "cg_thirdperson", 1 );
|
||||
self SetClientDvar( "sv_cheats", 0 );
|
||||
|
||||
self God();
|
||||
self Noclip();
|
||||
self Hide();
|
||||
|
||||
self.isNoClipped = false;
|
||||
|
||||
self IPrintLnBold( "NoClip disabled" );
|
||||
}
|
||||
|
||||
self IPrintLnBold( "NoClip enabled" );*/
|
||||
|
||||
scripts\_integration_base::LogWarning( "NoClip is not supported on T6!" );
|
||||
|
||||
}
|
||||
|
||||
HideImpl( event, data )
|
||||
{
|
||||
if ( !IsAlive( self ) )
|
||||
{
|
||||
self IPrintLnBold( "You are not alive" );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !IsDefined ( self.isHidden ) )
|
||||
{
|
||||
self.isHidden = false;
|
||||
}
|
||||
|
||||
if ( !self.isHidden )
|
||||
{
|
||||
self SetClientDvar( "sv_cheats", 1 );
|
||||
self SetClientDvar( "cg_thirdperson", 1 );
|
||||
self SetClientDvar( "sv_cheats", 0 );
|
||||
|
||||
self God();
|
||||
self Hide();
|
||||
|
||||
self.isHidden = true;
|
||||
|
||||
self IPrintLnBold( "Hide enabled" );
|
||||
}
|
||||
else
|
||||
{
|
||||
self SetClientDvar( "sv_cheats", 1 );
|
||||
self SetClientDvar( "cg_thirdperson", 0 );
|
||||
self SetClientDvar( "sv_cheats", 0 );
|
||||
|
||||
self God();
|
||||
self Show();
|
||||
|
||||
self.isHidden = false;
|
||||
|
||||
self IPrintLnBold( "Hide disabled" );
|
||||
}
|
||||
}
|
||||
|
||||
AlertImpl( event, data )
|
||||
{
|
||||
/*if ( !sessionmodeiszombiesgame() )
|
||||
{*/
|
||||
self thread oldNotifyMessage( data["alertType"], data["message"], undefined, ( 1, 0, 0 ), "mpl_sab_ui_suitcasebomb_timer", 7.5 );
|
||||
/*}
|
||||
else
|
||||
{
|
||||
self IPrintLnBold( data["alertType"] );
|
||||
self IPrintLnBold( data["message"] );
|
||||
}*/
|
||||
|
||||
|
||||
return "Sent alert to " + self.name;
|
||||
}
|
||||
|
||||
GotoImpl( event, data )
|
||||
{
|
||||
if ( IsDefined( event.target ) )
|
||||
{
|
||||
return self GotoPlayerImpl( event.target );
|
||||
}
|
||||
else
|
||||
{
|
||||
return self GotoCoordImpl( data );
|
||||
}
|
||||
}
|
||||
|
||||
GotoCoordImpl( event, data )
|
||||
{
|
||||
if ( !IsAlive( self ) )
|
||||
{
|
||||
self IPrintLnBold( "You are not alive" );
|
||||
return;
|
||||
}
|
||||
|
||||
position = ( int( data["x"] ), int( data["y"] ), int( data["z"]) );
|
||||
self SetOrigin( position );
|
||||
self IPrintLnBold( "Moved to " + "("+ position[0] + "," + position[1] + "," + position[2] + ")" );
|
||||
}
|
||||
|
||||
GotoPlayerImpl( target )
|
||||
{
|
||||
if ( !IsAlive( target ) )
|
||||
{
|
||||
self IPrintLnBold( target.name + " is not alive" );
|
||||
return;
|
||||
}
|
||||
|
||||
self SetOrigin( target GetOrigin() );
|
||||
self IPrintLnBold( "Moved to " + target.name );
|
||||
}
|
||||
|
||||
PlayerToMeImpl( event, data )
|
||||
{
|
||||
if ( !IsAlive( self ) )
|
||||
{
|
||||
return self.name + " is not alive";
|
||||
}
|
||||
|
||||
self SetOrigin( event.origin GetOrigin() );
|
||||
return "Moved here " + self.name;
|
||||
}
|
||||
|
||||
KillImpl( event, data )
|
||||
{
|
||||
if ( !IsAlive( self ) )
|
||||
{
|
||||
return self.name + " is not alive";
|
||||
}
|
||||
|
||||
self Suicide();
|
||||
self IPrintLnBold( "You were killed by " + self.name );
|
||||
|
||||
return "You killed " + self.name;
|
||||
}
|
||||
|
||||
SetSpectatorImpl( event, data )
|
||||
{
|
||||
if ( self.pers["team"] == "spectator" )
|
||||
{
|
||||
return self.name + " is already spectating";
|
||||
}
|
||||
|
||||
self [[level.spectator]]();
|
||||
self IPrintLnBold( "You have been moved to spectator" );
|
||||
|
||||
return self.name + " has been moved to spectator";
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////
|
||||
// T6 specific functions
|
||||
/////////////////////////////////
|
||||
|
||||
/*
|
||||
1:1 the same on MP and ZM but in different includes. Since we probably want to be able to send Alerts on non teambased wagermatechs use our own copy.
|
||||
*/
|
||||
oldnotifymessage( titletext, notifytext, iconname, glowcolor, sound, duration )
|
||||
{
|
||||
/*if ( level.wagermatch && !level.teambased )
|
||||
{
|
||||
return;
|
||||
}*/
|
||||
notifydata = spawnstruct();
|
||||
notifydata.titletext = titletext;
|
||||
notifydata.notifytext = notifytext;
|
||||
notifydata.iconname = iconname;
|
||||
notifydata.sound = sound;
|
||||
notifydata.duration = duration;
|
||||
self.startmessagenotifyqueue[ self.startmessagenotifyqueue.size ] = notifydata;
|
||||
self notify( "received award" );
|
||||
}
|
||||
|
||||
|
86
GameFiles/GameInterface/_integration_t6zm_helper.gsc
Normal file
86
GameFiles/GameInterface/_integration_t6zm_helper.gsc
Normal file
@ -0,0 +1,86 @@
|
||||
init()
|
||||
{
|
||||
|
||||
level.startmessagedefaultduration = 2;
|
||||
level.regulargamemessages = spawnstruct();
|
||||
level.regulargamemessages.waittime = 6;
|
||||
|
||||
|
||||
level thread onplayerconnect();
|
||||
}
|
||||
|
||||
onplayerconnect()
|
||||
{
|
||||
for ( ;; )
|
||||
{
|
||||
level waittill( "connecting", player );
|
||||
player thread displaypopupswaiter();
|
||||
}
|
||||
}
|
||||
|
||||
displaypopupswaiter()
|
||||
{
|
||||
self endon( "disconnect" );
|
||||
self.ranknotifyqueue = [];
|
||||
if ( !isDefined( self.pers[ "challengeNotifyQueue" ] ) )
|
||||
{
|
||||
self.pers[ "challengeNotifyQueue" ] = [];
|
||||
}
|
||||
if ( !isDefined( self.pers[ "contractNotifyQueue" ] ) )
|
||||
{
|
||||
self.pers[ "contractNotifyQueue" ] = [];
|
||||
}
|
||||
self.messagenotifyqueue = [];
|
||||
self.startmessagenotifyqueue = [];
|
||||
self.wagernotifyqueue = [];
|
||||
while ( !level.gameended )
|
||||
{
|
||||
if ( self.startmessagenotifyqueue.size == 0 && self.messagenotifyqueue.size == 0 )
|
||||
{
|
||||
self waittill( "received award" );
|
||||
}
|
||||
waittillframeend;
|
||||
if ( level.gameended )
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( self.startmessagenotifyqueue.size > 0 )
|
||||
{
|
||||
nextnotifydata = self.startmessagenotifyqueue[ 0 ];
|
||||
arrayremoveindex( self.startmessagenotifyqueue, 0, 0 );
|
||||
if ( isDefined( nextnotifydata.duration ) )
|
||||
{
|
||||
duration = nextnotifydata.duration;
|
||||
}
|
||||
else
|
||||
{
|
||||
duration = level.startmessagedefaultduration;
|
||||
}
|
||||
self maps\mp\gametypes_zm\_hud_message::shownotifymessage( nextnotifydata, duration );
|
||||
wait duration;
|
||||
continue;
|
||||
}
|
||||
else if ( self.messagenotifyqueue.size > 0 )
|
||||
{
|
||||
nextnotifydata = self.messagenotifyqueue[ 0 ];
|
||||
arrayremoveindex( self.messagenotifyqueue, 0, 0 );
|
||||
if ( isDefined( nextnotifydata.duration ) )
|
||||
{
|
||||
duration = nextnotifydata.duration;
|
||||
}
|
||||
else
|
||||
{
|
||||
duration = level.regulargamemessages.waittime;
|
||||
}
|
||||
self maps\mp\gametypes_zm\_hud_message::shownotifymessage( nextnotifydata, duration );
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
wait 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,14 +1,20 @@
|
||||
@echo off
|
||||
|
||||
ECHO "Pluto IW5"
|
||||
xcopy /y .\GameInterface\_integration_base.gsc "%LOCALAPPDATA%\Plutonium\storage\iw5\scripts\mp"
|
||||
xcopy /y .\GameInterface\_integration_iw5.gsc "%LOCALAPPDATA%\Plutonium\storage\iw5\scripts\mp"
|
||||
xcopy /y .\GameInterface\_integration_base.gsc "%LOCALAPPDATA%\Plutonium\storage\iw5\scripts"
|
||||
xcopy /y .\GameInterface\_integration_shared.gsc "%LOCALAPPDATA%\Plutonium\storage\iw5\scripts"
|
||||
xcopy /y .\GameInterface\_integration_iw5.gsc "%LOCALAPPDATA%\Plutonium\storage\iw5\scripts"
|
||||
xcopy /y .\AntiCheat\IW5\storage\iw5\scripts\_customcallbacks.gsc "%LOCALAPPDATA%\Plutonium\storage\iw5\scripts\mp"
|
||||
|
||||
ECHO "Pluto T5"
|
||||
xcopy /y .\GameInterface\_integration_base.gsc "%LOCALAPPDATA%\Plutonium\storage\t5\scripts\mp"
|
||||
xcopy /y .\GameInterface\_integration_base.gsc "%LOCALAPPDATA%\Plutonium\storage\t5\scripts"
|
||||
xcopy /y .\GameInterface\_integration_shared.gsc "%LOCALAPPDATA%\Plutonium\storage\t5\scripts"
|
||||
xcopy /y .\GameInterface\_integration_t5.gsc "%LOCALAPPDATA%\Plutonium\storage\t5\scripts\mp"
|
||||
xcopy /y .\GameInterface\_integration_t5zm.gsc "%LOCALAPPDATA%\Plutonium\storage\t5\scripts\sp\zom"
|
||||
|
||||
ECHO "Pluto T6"
|
||||
xcopy /y .\AntiCheat\PT6\storage\t6\scripts\mp\_customcallbacks.gsc "%LOCALAPPDATA%\Plutonium\storage\t6\scripts\mp"
|
||||
xcopy /y .\AntiCheat\PT6\storage\t6\scripts\mp\_customcallbacks.gsc.src "%LOCALAPPDATA%\Plutonium\storage\t6\scripts\mp"
|
||||
xcopy /y .\GameInterface\_integration_base.gsc "%LOCALAPPDATA%\Plutonium\storage\t6\scripts"
|
||||
xcopy /y .\GameInterface\_integration_shared.gsc "%LOCALAPPDATA%\Plutonium\storage\t6\scripts"
|
||||
xcopy /y .\GameInterface\_integration_t6.gsc "%LOCALAPPDATA%\Plutonium\storage\t6\scripts"
|
||||
xcopy /y .\GameInterface\_integration_t6zm_helper.gsc "%LOCALAPPDATA%\Plutonium\storage\t6\scripts\zm"
|
||||
|
@ -385,7 +385,7 @@ const commands = [{
|
||||
required: true
|
||||
}
|
||||
],
|
||||
supportedGames: ['IW4', 'IW5', 'T5'],
|
||||
supportedGames: ['IW4', 'IW5', 'T5', 'T6'],
|
||||
execute: (gameEvent) => {
|
||||
if (!validateEnabled(gameEvent.owner, gameEvent.origin)) {
|
||||
return;
|
||||
@ -405,7 +405,7 @@ const commands = [{
|
||||
name: 'player',
|
||||
required: true
|
||||
}],
|
||||
supportedGames: ['IW4', 'IW5', 'T5'],
|
||||
supportedGames: ['IW4', 'IW5', 'T5', 'T6'],
|
||||
execute: (gameEvent) => {
|
||||
if (!validateEnabled(gameEvent.owner, gameEvent.origin)) {
|
||||
return;
|
||||
@ -423,7 +423,7 @@ const commands = [{
|
||||
name: 'player',
|
||||
required: true
|
||||
}],
|
||||
supportedGames: ['IW4', 'IW5', 'T5'],
|
||||
supportedGames: ['IW4', 'IW5', 'T5', 'T6'],
|
||||
execute: (gameEvent) => {
|
||||
if (!validateEnabled(gameEvent.owner, gameEvent.origin)) {
|
||||
return;
|
||||
@ -441,7 +441,7 @@ const commands = [{
|
||||
name: 'player',
|
||||
required: true
|
||||
}],
|
||||
supportedGames: ['IW4', 'IW5', 'T5'],
|
||||
supportedGames: ['IW4', 'IW5', 'T5', 'T6'],
|
||||
execute: (gameEvent) => {
|
||||
if (!validateEnabled(gameEvent.owner, gameEvent.origin)) {
|
||||
return;
|
||||
@ -471,7 +471,7 @@ const commands = [{
|
||||
permission: 'SeniorAdmin',
|
||||
targetRequired: false,
|
||||
arguments: [],
|
||||
supportedGames: ['IW4', 'IW5', 'T5'],
|
||||
supportedGames: ['IW4', 'IW5', 'T5', 'T6'],
|
||||
execute: (gameEvent) => {
|
||||
if (!validateEnabled(gameEvent.owner, gameEvent.origin)) {
|
||||
return;
|
||||
@ -494,7 +494,7 @@ const commands = [{
|
||||
required: true
|
||||
}
|
||||
],
|
||||
supportedGames: ['IW4', 'IW5', 'T5'],
|
||||
supportedGames: ['IW4', 'IW5', 'T5', 'T6'],
|
||||
execute: (gameEvent) => {
|
||||
if (!validateEnabled(gameEvent.owner, gameEvent.origin)) {
|
||||
return;
|
||||
@ -515,7 +515,7 @@ const commands = [{
|
||||
name: 'player',
|
||||
required: true
|
||||
}],
|
||||
supportedGames: ['IW4', 'IW5', 'T5'],
|
||||
supportedGames: ['IW4', 'IW5', 'T5', 'T6'],
|
||||
execute: (gameEvent) => {
|
||||
if (!validateEnabled(gameEvent.owner, gameEvent.origin)) {
|
||||
return;
|
||||
@ -533,7 +533,7 @@ const commands = [{
|
||||
name: 'player',
|
||||
required: true
|
||||
}],
|
||||
supportedGames: ['IW4', 'IW5', 'T5'],
|
||||
supportedGames: ['IW4', 'IW5', 'T5', 'T6'],
|
||||
execute: (gameEvent) => {
|
||||
if (!validateEnabled(gameEvent.owner, gameEvent.origin)) {
|
||||
return;
|
||||
@ -560,7 +560,7 @@ const commands = [{
|
||||
required: true
|
||||
}
|
||||
],
|
||||
supportedGames: ['IW4', 'IW5', 'T5'],
|
||||
supportedGames: ['IW4', 'IW5', 'T5', 'T6'],
|
||||
execute: (gameEvent) => {
|
||||
if (!validateEnabled(gameEvent.owner, gameEvent.origin)) {
|
||||
return;
|
||||
@ -584,7 +584,7 @@ const commands = [{
|
||||
name: 'player',
|
||||
required: true
|
||||
}],
|
||||
supportedGames: ['IW4', 'IW5', 'T5'],
|
||||
supportedGames: ['IW4', 'IW5', 'T5', 'T6'],
|
||||
execute: (gameEvent) => {
|
||||
if (!validateEnabled(gameEvent.owner, gameEvent.origin)) {
|
||||
return;
|
||||
@ -602,7 +602,7 @@ const commands = [{
|
||||
name: 'player',
|
||||
required: true
|
||||
}],
|
||||
supportedGames: ['IW4', 'IW5', 'T5'],
|
||||
supportedGames: ['IW4', 'IW5', 'T5', 'T6'],
|
||||
execute: (gameEvent) => {
|
||||
if (!validateEnabled(gameEvent.owner, gameEvent.origin)) {
|
||||
return;
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SharedLibraryCore.Dtos
|
||||
{
|
||||
@ -11,11 +12,17 @@ namespace SharedLibraryCore.Dtos
|
||||
|
||||
public class ClientCountSnapshot
|
||||
{
|
||||
[JsonIgnore]
|
||||
public DateTime Time { get; set; }
|
||||
[JsonPropertyName("ts")]
|
||||
public string TimeString => Time.ToString("yyyy-MM-ddTHH:mm:ssZ");
|
||||
[JsonPropertyName("cc")]
|
||||
public int ClientCount { get; set; }
|
||||
[JsonPropertyName("ci")]
|
||||
public bool ConnectionInterrupted { get;set; }
|
||||
[JsonIgnore]
|
||||
public string Map { get; set; }
|
||||
[JsonPropertyName("ma")]
|
||||
public string MapAlias { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SharedLibraryCore;
|
||||
using SharedLibraryCore.Configuration;
|
||||
using SharedLibraryCore.Dtos;
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using WebfrontCore.Controllers.API.Models;
|
||||
|
||||
@ -12,9 +16,14 @@ namespace WebfrontCore.Controllers.API
|
||||
[Route("api/[controller]")]
|
||||
public class Server : BaseController
|
||||
{
|
||||
|
||||
public Server(IManager manager) : base(manager)
|
||||
private readonly IServerDataViewer _serverDataViewer;
|
||||
private readonly ApplicationConfiguration _applicationConfiguration;
|
||||
|
||||
public Server(IManager manager, IServerDataViewer serverDataViewer,
|
||||
ApplicationConfiguration applicationConfiguration) : base(manager)
|
||||
{
|
||||
_serverDataViewer = serverDataViewer;
|
||||
_applicationConfiguration = applicationConfiguration;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
@ -110,5 +119,48 @@ namespace WebfrontCore.Controllers.API
|
||||
completedEvent.Output
|
||||
});
|
||||
}
|
||||
|
||||
[HttpGet("{id}/history")]
|
||||
public async Task<IActionResult> GetClientHistory(string id)
|
||||
{
|
||||
var foundServer = Manager.GetServers().FirstOrDefault(server => server.Id == id);
|
||||
|
||||
if (foundServer == null)
|
||||
{
|
||||
return new NotFoundResult();
|
||||
}
|
||||
|
||||
var clientHistory = (await _serverDataViewer.ClientHistoryAsync(_applicationConfiguration.MaxClientHistoryTime,
|
||||
CancellationToken.None))?
|
||||
.FirstOrDefault(history => history.ServerId == foundServer.LegacyDatabaseId) ??
|
||||
new ClientHistoryInfo
|
||||
{
|
||||
ServerId = foundServer.LegacyDatabaseId,
|
||||
ClientCounts = new List<ClientCountSnapshot>()
|
||||
};
|
||||
|
||||
var counts = clientHistory.ClientCounts?.AsEnumerable() ?? Enumerable.Empty<ClientCountSnapshot>();
|
||||
|
||||
if (foundServer.ClientHistory.ClientCounts.Any())
|
||||
{
|
||||
counts = counts.Union(foundServer.ClientHistory.ClientCounts.Where(history =>
|
||||
history.Time > (clientHistory.ClientCounts?.LastOrDefault()?.Time ?? DateTime.MinValue)))
|
||||
.Where(history => history.Time >= DateTime.UtcNow - _applicationConfiguration.MaxClientHistoryTime);
|
||||
}
|
||||
|
||||
if (ViewBag.Maps?.Count == 0)
|
||||
{
|
||||
return Json(counts.ToList());
|
||||
}
|
||||
|
||||
var clientCountSnapshots = counts.ToList();
|
||||
foreach (var count in clientCountSnapshots)
|
||||
{
|
||||
count.MapAlias = foundServer.Maps.FirstOrDefault(map => map.Name == count.Map)?.Alias ??
|
||||
count.Map;
|
||||
}
|
||||
|
||||
return Json(clientCountSnapshots);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,50 +0,0 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SharedLibraryCore;
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace WebfrontCore.Controllers
|
||||
{
|
||||
[Route("dynamic")]
|
||||
public class DynamicFileController : BaseController
|
||||
{
|
||||
private static readonly IDictionary<string, string> _fileCache = new Dictionary<string, string>();
|
||||
|
||||
public DynamicFileController(IManager manager) : base(manager)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[Route("css/{fileName}")]
|
||||
public async Task<IActionResult> Css(string fileName)
|
||||
{
|
||||
if (fileName.EndsWith(".css"))
|
||||
{
|
||||
if (Utilities.IsDevelopment)
|
||||
{
|
||||
var path = Path.Join(Utilities.OperatingDirectory, "..", "..", "..", "..", "WebfrontCore", "wwwroot", "css", fileName);
|
||||
string cssData = await System.IO.File.ReadAllTextAsync(path);
|
||||
cssData = await Manager.MiddlewareActionHandler.Execute(cssData, "custom_css_accent");
|
||||
return Content(cssData, "text/css");
|
||||
}
|
||||
|
||||
if (!_fileCache.ContainsKey(fileName))
|
||||
{
|
||||
|
||||
string path = $"wwwroot{Path.DirectorySeparatorChar}css{Path.DirectorySeparatorChar}{fileName}";
|
||||
string data = await System.IO.File.ReadAllTextAsync(path);
|
||||
data = await Manager.MiddlewareActionHandler.Execute(data, "custom_css_accent");
|
||||
_fileCache.Add(fileName, data);
|
||||
}
|
||||
|
||||
return Content(_fileCache[fileName], "text/css");
|
||||
}
|
||||
|
||||
return StatusCode(400);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace WebfrontCore.Middleware
|
||||
{
|
||||
public class CustomCssAccentMiddlewareAction : IMiddlewareAction<string>
|
||||
{
|
||||
private readonly List<ColorMap> ColorReplacements = new List<ColorMap>();
|
||||
|
||||
private class ColorMap
|
||||
{
|
||||
public Color Original { get; set; }
|
||||
public Color Replacement { get; set; }
|
||||
}
|
||||
|
||||
public CustomCssAccentMiddlewareAction(string originalPrimaryColor, string originalSecondaryColor, string primaryColor, string secondaryColor)
|
||||
{
|
||||
primaryColor = string.IsNullOrWhiteSpace(primaryColor) ? originalPrimaryColor : primaryColor;
|
||||
secondaryColor = string.IsNullOrWhiteSpace(secondaryColor) ? originalSecondaryColor : secondaryColor;
|
||||
try
|
||||
{
|
||||
ColorReplacements.AddRange(new[]
|
||||
{
|
||||
new ColorMap()
|
||||
{
|
||||
Original = Color.FromArgb(Convert.ToInt32(originalPrimaryColor.Substring(1).ToString(), 16)),
|
||||
Replacement = Color.FromArgb(Convert.ToInt32(primaryColor.Substring(1).ToString(), 16))
|
||||
},
|
||||
new ColorMap()
|
||||
{
|
||||
Original = Color.FromArgb(Convert.ToInt32(originalSecondaryColor.Substring(1).ToString(), 16)),
|
||||
Replacement = Color.FromArgb(Convert.ToInt32(secondaryColor.Substring(1).ToString(), 16))
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
catch (FormatException)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public Task<string> Invoke(string original)
|
||||
{
|
||||
foreach (var color in ColorReplacements)
|
||||
{
|
||||
foreach (var shade in new[] { 0, -19, -25 })
|
||||
{
|
||||
original = original
|
||||
.Replace(ColorToHex(LightenDarkenColor(color.Original, shade)), ColorToHex(LightenDarkenColor(color.Replacement, shade)), StringComparison.OrdinalIgnoreCase)
|
||||
.Replace(ColorToDec(LightenDarkenColor(color.Original, shade)), ColorToDec(LightenDarkenColor(color.Replacement, shade)), StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
return Task.FromResult(original);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// converts color to the hex string representation
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
private string ColorToHex(Color color) => $"#{color.R.ToString("X2")}{color.G.ToString("X2")}{color.B.ToString("X2")}";
|
||||
|
||||
/// <summary>
|
||||
/// converts color to the rgb tuples representation
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
private string ColorToDec(Color color) => $"{(int)color.R}, {(int)color.G}, {(int)color.B}";
|
||||
|
||||
/// <summary>
|
||||
/// lightens or darkens a color on the given amount
|
||||
/// Based off SASS darken/lighten function
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <param name="amount"></param>
|
||||
/// <returns></returns>
|
||||
private Color LightenDarkenColor(Color color, float amount)
|
||||
{
|
||||
int r = color.R + (int)((amount / 100.0f) * color.R);
|
||||
|
||||
if (r > 255) r = 255;
|
||||
else if (r < 0) r = 0;
|
||||
|
||||
int g = color.G + (int)((amount / 100.0f) * color.G);
|
||||
|
||||
if (g > 255) g = 255;
|
||||
else if (g < 0) g = 0;
|
||||
|
||||
int b = color.B + (int)((amount / 100.0f) * color.B);
|
||||
|
||||
if (b > 255) b = 255;
|
||||
else if (b < 0) b = 0;
|
||||
|
||||
return Color.FromArgb(r, g, b);
|
||||
}
|
||||
}
|
||||
}
|
BIN
WebfrontCore/NUglify.dll
Normal file
BIN
WebfrontCore/NUglify.dll
Normal file
Binary file not shown.
BIN
WebfrontCore/Newtonsoft.Json.dll
Normal file
BIN
WebfrontCore/Newtonsoft.Json.dll
Normal file
Binary file not shown.
@ -6,7 +6,6 @@ using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using SharedLibraryCore.Configuration;
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using WebfrontCore.Middleware;
|
||||
|
||||
namespace WebfrontCore
|
||||
{
|
||||
@ -24,11 +23,6 @@ namespace WebfrontCore
|
||||
|
||||
public static Task GetWebHostTask(CancellationToken cancellationToken)
|
||||
{
|
||||
var config = _webHost.Services.GetRequiredService<ApplicationConfiguration>();
|
||||
Manager.MiddlewareActionHandler.Register(null,
|
||||
new CustomCssAccentMiddlewareAction("#007ACC", "#fd7e14", config.WebfrontPrimaryColor,
|
||||
config.WebfrontSecondaryColor), "custom_css_accent");
|
||||
|
||||
return _webHost?.RunAsync(cancellationToken);
|
||||
}
|
||||
|
||||
@ -41,7 +35,12 @@ namespace WebfrontCore
|
||||
.UseContentRoot(SharedLibraryCore.Utilities.OperatingDirectory)
|
||||
#endif
|
||||
.UseUrls(bindUrl)
|
||||
.UseKestrel()
|
||||
.UseKestrel(cfg =>
|
||||
{
|
||||
cfg.Limits.MaxConcurrentConnections =
|
||||
int.Parse(Environment.GetEnvironmentVariable("MaxConcurrentRequests") ?? "1");
|
||||
cfg.Limits.KeepAliveTimeout = TimeSpan.FromSeconds(30);
|
||||
})
|
||||
.ConfigureServices(registerDependenciesAction)
|
||||
.UseStartup<Startup>()
|
||||
.Build();
|
||||
|
@ -4,7 +4,6 @@ using FluentValidation.AspNetCore;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc.ApplicationParts;
|
||||
using Microsoft.AspNetCore.Mvc.Razor;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@ -24,9 +23,6 @@ using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Data.Abstractions;
|
||||
using Data.Helpers;
|
||||
using IW4MAdmin.Plugins.Stats.Helpers;
|
||||
using Stats.Client.Abstractions;
|
||||
using Stats.Config;
|
||||
using WebfrontCore.Controllers.API.Validation;
|
||||
using WebfrontCore.Middleware;
|
||||
using WebfrontCore.QueryHelpers;
|
||||
@ -50,6 +46,12 @@ namespace WebfrontCore
|
||||
.AllowAnyHeader();
|
||||
});
|
||||
});
|
||||
|
||||
services.AddStackPolicy(options =>
|
||||
{
|
||||
options.MaxConcurrentRequests = int.Parse(Environment.GetEnvironmentVariable("MaxConcurrentRequests") ?? "1");
|
||||
options.RequestQueueLimit = int.Parse(Environment.GetEnvironmentVariable("RequestQueueLimit") ?? "1");
|
||||
});
|
||||
|
||||
IEnumerable<Assembly> pluginAssemblies()
|
||||
{
|
||||
@ -132,6 +134,7 @@ namespace WebfrontCore
|
||||
app.UseMiddleware<IPWhitelist>(serviceProvider.GetService<ILogger<IPWhitelist>>(), serviceProvider.GetRequiredService<ApplicationConfiguration>().WebfrontConnectionWhitelist);
|
||||
}
|
||||
|
||||
app.UseConcurrencyLimiter();
|
||||
app.UseStaticFiles();
|
||||
app.UseAuthentication();
|
||||
app.UseCors("AllowAll");
|
||||
|
@ -1,29 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SharedLibraryCore;
|
||||
using SharedLibraryCore.Dtos;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Data.Models;
|
||||
using Data.Models.Client.Stats;
|
||||
using IW4MAdmin.Plugins.Stats.Helpers;
|
||||
using SharedLibraryCore.Configuration;
|
||||
using SharedLibraryCore.Interfaces;
|
||||
|
||||
namespace WebfrontCore.ViewComponents
|
||||
{
|
||||
public class ServerListViewComponent : ViewComponent
|
||||
{
|
||||
private readonly IServerDataViewer _serverDataViewer;
|
||||
private readonly ApplicationConfiguration _appConfig;
|
||||
private readonly DefaultSettings _defaultSettings;
|
||||
|
||||
public ServerListViewComponent(IServerDataViewer serverDataViewer,
|
||||
ApplicationConfiguration applicationConfiguration, DefaultSettings defaultSettings)
|
||||
public ServerListViewComponent(DefaultSettings defaultSettings)
|
||||
{
|
||||
_serverDataViewer = serverDataViewer;
|
||||
_appConfig = applicationConfiguration;
|
||||
_defaultSettings = defaultSettings;
|
||||
}
|
||||
|
||||
@ -46,25 +38,6 @@ namespace WebfrontCore.ViewComponents
|
||||
|
||||
foreach (var server in servers)
|
||||
{
|
||||
var serverId = server.GetIdForServer().Result;
|
||||
var clientHistory = _serverDataViewer.ClientHistoryAsync(_appConfig.MaxClientHistoryTime,
|
||||
CancellationToken.None).Result?
|
||||
.FirstOrDefault(history => history.ServerId == serverId) ??
|
||||
new ClientHistoryInfo
|
||||
{
|
||||
ServerId = serverId,
|
||||
ClientCounts = new List<ClientCountSnapshot>()
|
||||
};
|
||||
|
||||
var counts = clientHistory.ClientCounts?.AsEnumerable() ?? Enumerable.Empty<ClientCountSnapshot>();
|
||||
|
||||
if (server.ClientHistory.ClientCounts.Any())
|
||||
{
|
||||
counts = counts.Union(server.ClientHistory.ClientCounts.Where(history =>
|
||||
history.Time > (clientHistory.ClientCounts?.LastOrDefault()?.Time ?? DateTime.MinValue)))
|
||||
.Where(history => history.Time >= DateTime.UtcNow - _appConfig.MaxClientHistoryTime);
|
||||
}
|
||||
|
||||
serverInfo.Add(new ServerInfo
|
||||
{
|
||||
Name = server.Hostname,
|
||||
@ -76,11 +49,7 @@ namespace WebfrontCore.ViewComponents
|
||||
MaxClients = server.MaxClients,
|
||||
PrivateClientSlots = server.PrivateClientSlots,
|
||||
GameType = server.GametypeName,
|
||||
ClientHistory = new ClientHistoryInfo
|
||||
{
|
||||
ServerId = server.EndPoint,
|
||||
ClientCounts = counts.ToList()
|
||||
},
|
||||
ClientHistory = new ClientHistoryInfo(),
|
||||
Players = server.GetClientsAsList()
|
||||
.Select(client => new PlayerInfo
|
||||
{
|
||||
|
@ -82,8 +82,7 @@
|
||||
}
|
||||
|
||||
<div class="server-history">
|
||||
<div class="server-history-row m-auto bg-dark-dm bg-light-lm rounded-bottom" style="position:relative; width: 100%" id="server_history_@Model.ID" data-serverid="@Model.ID"
|
||||
data-clienthistory='@Html.Raw(Json.Serialize(Model.ClientHistory))'
|
||||
<div class="server-history-row m-auto bg-dark-dm bg-light-lm rounded-bottom" style="position:relative; width: 100%" id="server_history_@Model.ID" data-serverid="@Model.ID" data-server-endpoint="@Model.Endpoint"
|
||||
data-clienthistory-ex='@Html.Raw(Json.Serialize(Model.ClientHistory.ClientCounts))'
|
||||
data-online="@Model.Online">
|
||||
<canvas id="server_history_canvas_@Model.ID" class="rounded-bottom" height="100"></canvas>
|
||||
|
@ -25,7 +25,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<ServerGarbageCollection>false</ServerGarbageCollection>
|
||||
<ServerGarbageCollection>true</ServerGarbageCollection>
|
||||
<ConcurrentGarbageCollection>true</ConcurrentGarbageCollection>
|
||||
<TieredCompilation>true</TieredCompilation>
|
||||
<LangVersion>Latest</LangVersion>
|
||||
@ -47,6 +47,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BuildWebCompiler2022" Version="1.14.10" />
|
||||
<PackageReference Include="FluentValidation.AspNetCore" Version="11.2.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.ConcurrencyLimiter" Version="6.0.16" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.8" />
|
||||
<PackageReference Include="Microsoft.Web.LibraryManager.Build" Version="2.1.175" />
|
||||
</ItemGroup>
|
||||
|
669
WebfrontCore/dotnet-bundle.deps.json
Normal file
669
WebfrontCore/dotnet-bundle.deps.json
Normal file
@ -0,0 +1,669 @@
|
||||
{
|
||||
"runtimeTarget": {
|
||||
"name": ".NETCoreApp,Version=v6.0",
|
||||
"signature": ""
|
||||
},
|
||||
"compilationOptions": {},
|
||||
"targets": {
|
||||
".NETCoreApp,Version=v6.0": {
|
||||
"dotnet-bundle/1.0.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.SourceLink.GitHub": "1.0.0",
|
||||
"NUglify": "1.17.10",
|
||||
"Newtonsoft.Json": "9.0.1"
|
||||
},
|
||||
"runtime": {
|
||||
"dotnet-bundle.dll": {}
|
||||
}
|
||||
},
|
||||
"Microsoft.Build.Tasks.Git/1.0.0": {},
|
||||
"Microsoft.CSharp/4.0.1": {
|
||||
"dependencies": {
|
||||
"System.Collections": "4.0.11",
|
||||
"System.Diagnostics.Debug": "4.0.11",
|
||||
"System.Dynamic.Runtime": "4.0.11",
|
||||
"System.Globalization": "4.0.11",
|
||||
"System.Linq": "4.1.0",
|
||||
"System.Linq.Expressions": "4.1.0",
|
||||
"System.ObjectModel": "4.0.12",
|
||||
"System.Reflection": "4.1.0",
|
||||
"System.Reflection.Extensions": "4.0.1",
|
||||
"System.Reflection.Primitives": "4.0.1",
|
||||
"System.Reflection.TypeExtensions": "4.1.0",
|
||||
"System.Resources.ResourceManager": "4.0.1",
|
||||
"System.Runtime": "4.1.0",
|
||||
"System.Runtime.Extensions": "4.1.0",
|
||||
"System.Runtime.InteropServices": "4.1.0",
|
||||
"System.Threading": "4.0.11"
|
||||
}
|
||||
},
|
||||
"Microsoft.NETCore.Platforms/1.0.1": {},
|
||||
"Microsoft.NETCore.Targets/1.0.1": {},
|
||||
"Microsoft.SourceLink.Common/1.0.0": {},
|
||||
"Microsoft.SourceLink.GitHub/1.0.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.Build.Tasks.Git": "1.0.0",
|
||||
"Microsoft.SourceLink.Common": "1.0.0"
|
||||
}
|
||||
},
|
||||
"Newtonsoft.Json/9.0.1": {
|
||||
"dependencies": {
|
||||
"Microsoft.CSharp": "4.0.1",
|
||||
"System.Collections": "4.0.11",
|
||||
"System.Diagnostics.Debug": "4.0.11",
|
||||
"System.Dynamic.Runtime": "4.0.11",
|
||||
"System.Globalization": "4.0.11",
|
||||
"System.IO": "4.1.0",
|
||||
"System.Linq": "4.1.0",
|
||||
"System.Linq.Expressions": "4.1.0",
|
||||
"System.ObjectModel": "4.0.12",
|
||||
"System.Reflection": "4.1.0",
|
||||
"System.Reflection.Extensions": "4.0.1",
|
||||
"System.Resources.ResourceManager": "4.0.1",
|
||||
"System.Runtime": "4.1.0",
|
||||
"System.Runtime.Extensions": "4.1.0",
|
||||
"System.Runtime.Serialization.Primitives": "4.1.1",
|
||||
"System.Text.Encoding": "4.0.11",
|
||||
"System.Text.Encoding.Extensions": "4.0.11",
|
||||
"System.Text.RegularExpressions": "4.1.0",
|
||||
"System.Threading": "4.0.11",
|
||||
"System.Threading.Tasks": "4.0.11",
|
||||
"System.Xml.ReaderWriter": "4.0.11",
|
||||
"System.Xml.XDocument": "4.0.11"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/netstandard1.0/Newtonsoft.Json.dll": {
|
||||
"assemblyVersion": "9.0.0.0",
|
||||
"fileVersion": "9.0.1.19813"
|
||||
}
|
||||
}
|
||||
},
|
||||
"NUglify/1.17.10": {
|
||||
"runtime": {
|
||||
"lib/net5.0/NUglify.dll": {
|
||||
"assemblyVersion": "1.17.10.0",
|
||||
"fileVersion": "1.17.10.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"System.Collections/4.0.11": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Platforms": "1.0.1",
|
||||
"Microsoft.NETCore.Targets": "1.0.1",
|
||||
"System.Runtime": "4.1.0"
|
||||
}
|
||||
},
|
||||
"System.Diagnostics.Debug/4.0.11": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Platforms": "1.0.1",
|
||||
"Microsoft.NETCore.Targets": "1.0.1",
|
||||
"System.Runtime": "4.1.0"
|
||||
}
|
||||
},
|
||||
"System.Diagnostics.Tools/4.0.1": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Platforms": "1.0.1",
|
||||
"Microsoft.NETCore.Targets": "1.0.1",
|
||||
"System.Runtime": "4.1.0"
|
||||
}
|
||||
},
|
||||
"System.Dynamic.Runtime/4.0.11": {
|
||||
"dependencies": {
|
||||
"System.Collections": "4.0.11",
|
||||
"System.Diagnostics.Debug": "4.0.11",
|
||||
"System.Globalization": "4.0.11",
|
||||
"System.Linq": "4.1.0",
|
||||
"System.Linq.Expressions": "4.1.0",
|
||||
"System.ObjectModel": "4.0.12",
|
||||
"System.Reflection": "4.1.0",
|
||||
"System.Reflection.Emit": "4.0.1",
|
||||
"System.Reflection.Emit.ILGeneration": "4.0.1",
|
||||
"System.Reflection.Primitives": "4.0.1",
|
||||
"System.Reflection.TypeExtensions": "4.1.0",
|
||||
"System.Resources.ResourceManager": "4.0.1",
|
||||
"System.Runtime": "4.1.0",
|
||||
"System.Runtime.Extensions": "4.1.0",
|
||||
"System.Threading": "4.0.11"
|
||||
}
|
||||
},
|
||||
"System.Globalization/4.0.11": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Platforms": "1.0.1",
|
||||
"Microsoft.NETCore.Targets": "1.0.1",
|
||||
"System.Runtime": "4.1.0"
|
||||
}
|
||||
},
|
||||
"System.IO/4.1.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Platforms": "1.0.1",
|
||||
"Microsoft.NETCore.Targets": "1.0.1",
|
||||
"System.Runtime": "4.1.0",
|
||||
"System.Text.Encoding": "4.0.11",
|
||||
"System.Threading.Tasks": "4.0.11"
|
||||
}
|
||||
},
|
||||
"System.IO.FileSystem/4.0.1": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Platforms": "1.0.1",
|
||||
"Microsoft.NETCore.Targets": "1.0.1",
|
||||
"System.IO": "4.1.0",
|
||||
"System.IO.FileSystem.Primitives": "4.0.1",
|
||||
"System.Runtime": "4.1.0",
|
||||
"System.Runtime.Handles": "4.0.1",
|
||||
"System.Text.Encoding": "4.0.11",
|
||||
"System.Threading.Tasks": "4.0.11"
|
||||
}
|
||||
},
|
||||
"System.IO.FileSystem.Primitives/4.0.1": {
|
||||
"dependencies": {
|
||||
"System.Runtime": "4.1.0"
|
||||
}
|
||||
},
|
||||
"System.Linq/4.1.0": {
|
||||
"dependencies": {
|
||||
"System.Collections": "4.0.11",
|
||||
"System.Diagnostics.Debug": "4.0.11",
|
||||
"System.Resources.ResourceManager": "4.0.1",
|
||||
"System.Runtime": "4.1.0",
|
||||
"System.Runtime.Extensions": "4.1.0"
|
||||
}
|
||||
},
|
||||
"System.Linq.Expressions/4.1.0": {
|
||||
"dependencies": {
|
||||
"System.Collections": "4.0.11",
|
||||
"System.Diagnostics.Debug": "4.0.11",
|
||||
"System.Globalization": "4.0.11",
|
||||
"System.IO": "4.1.0",
|
||||
"System.Linq": "4.1.0",
|
||||
"System.ObjectModel": "4.0.12",
|
||||
"System.Reflection": "4.1.0",
|
||||
"System.Reflection.Emit": "4.0.1",
|
||||
"System.Reflection.Emit.ILGeneration": "4.0.1",
|
||||
"System.Reflection.Emit.Lightweight": "4.0.1",
|
||||
"System.Reflection.Extensions": "4.0.1",
|
||||
"System.Reflection.Primitives": "4.0.1",
|
||||
"System.Reflection.TypeExtensions": "4.1.0",
|
||||
"System.Resources.ResourceManager": "4.0.1",
|
||||
"System.Runtime": "4.1.0",
|
||||
"System.Runtime.Extensions": "4.1.0",
|
||||
"System.Threading": "4.0.11"
|
||||
}
|
||||
},
|
||||
"System.ObjectModel/4.0.12": {
|
||||
"dependencies": {
|
||||
"System.Collections": "4.0.11",
|
||||
"System.Diagnostics.Debug": "4.0.11",
|
||||
"System.Resources.ResourceManager": "4.0.1",
|
||||
"System.Runtime": "4.1.0",
|
||||
"System.Threading": "4.0.11"
|
||||
}
|
||||
},
|
||||
"System.Reflection/4.1.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Platforms": "1.0.1",
|
||||
"Microsoft.NETCore.Targets": "1.0.1",
|
||||
"System.IO": "4.1.0",
|
||||
"System.Reflection.Primitives": "4.0.1",
|
||||
"System.Runtime": "4.1.0"
|
||||
}
|
||||
},
|
||||
"System.Reflection.Emit/4.0.1": {
|
||||
"dependencies": {
|
||||
"System.IO": "4.1.0",
|
||||
"System.Reflection": "4.1.0",
|
||||
"System.Reflection.Emit.ILGeneration": "4.0.1",
|
||||
"System.Reflection.Primitives": "4.0.1",
|
||||
"System.Runtime": "4.1.0"
|
||||
}
|
||||
},
|
||||
"System.Reflection.Emit.ILGeneration/4.0.1": {
|
||||
"dependencies": {
|
||||
"System.Reflection": "4.1.0",
|
||||
"System.Reflection.Primitives": "4.0.1",
|
||||
"System.Runtime": "4.1.0"
|
||||
}
|
||||
},
|
||||
"System.Reflection.Emit.Lightweight/4.0.1": {
|
||||
"dependencies": {
|
||||
"System.Reflection": "4.1.0",
|
||||
"System.Reflection.Emit.ILGeneration": "4.0.1",
|
||||
"System.Reflection.Primitives": "4.0.1",
|
||||
"System.Runtime": "4.1.0"
|
||||
}
|
||||
},
|
||||
"System.Reflection.Extensions/4.0.1": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Platforms": "1.0.1",
|
||||
"Microsoft.NETCore.Targets": "1.0.1",
|
||||
"System.Reflection": "4.1.0",
|
||||
"System.Runtime": "4.1.0"
|
||||
}
|
||||
},
|
||||
"System.Reflection.Primitives/4.0.1": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Platforms": "1.0.1",
|
||||
"Microsoft.NETCore.Targets": "1.0.1",
|
||||
"System.Runtime": "4.1.0"
|
||||
}
|
||||
},
|
||||
"System.Reflection.TypeExtensions/4.1.0": {
|
||||
"dependencies": {
|
||||
"System.Reflection": "4.1.0",
|
||||
"System.Runtime": "4.1.0"
|
||||
}
|
||||
},
|
||||
"System.Resources.ResourceManager/4.0.1": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Platforms": "1.0.1",
|
||||
"Microsoft.NETCore.Targets": "1.0.1",
|
||||
"System.Globalization": "4.0.11",
|
||||
"System.Reflection": "4.1.0",
|
||||
"System.Runtime": "4.1.0"
|
||||
}
|
||||
},
|
||||
"System.Runtime/4.1.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Platforms": "1.0.1",
|
||||
"Microsoft.NETCore.Targets": "1.0.1"
|
||||
}
|
||||
},
|
||||
"System.Runtime.Extensions/4.1.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Platforms": "1.0.1",
|
||||
"Microsoft.NETCore.Targets": "1.0.1",
|
||||
"System.Runtime": "4.1.0"
|
||||
}
|
||||
},
|
||||
"System.Runtime.Handles/4.0.1": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Platforms": "1.0.1",
|
||||
"Microsoft.NETCore.Targets": "1.0.1",
|
||||
"System.Runtime": "4.1.0"
|
||||
}
|
||||
},
|
||||
"System.Runtime.InteropServices/4.1.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Platforms": "1.0.1",
|
||||
"Microsoft.NETCore.Targets": "1.0.1",
|
||||
"System.Reflection": "4.1.0",
|
||||
"System.Reflection.Primitives": "4.0.1",
|
||||
"System.Runtime": "4.1.0",
|
||||
"System.Runtime.Handles": "4.0.1"
|
||||
}
|
||||
},
|
||||
"System.Runtime.Serialization.Primitives/4.1.1": {
|
||||
"dependencies": {
|
||||
"System.Resources.ResourceManager": "4.0.1",
|
||||
"System.Runtime": "4.1.0"
|
||||
}
|
||||
},
|
||||
"System.Text.Encoding/4.0.11": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Platforms": "1.0.1",
|
||||
"Microsoft.NETCore.Targets": "1.0.1",
|
||||
"System.Runtime": "4.1.0"
|
||||
}
|
||||
},
|
||||
"System.Text.Encoding.Extensions/4.0.11": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Platforms": "1.0.1",
|
||||
"Microsoft.NETCore.Targets": "1.0.1",
|
||||
"System.Runtime": "4.1.0",
|
||||
"System.Text.Encoding": "4.0.11"
|
||||
}
|
||||
},
|
||||
"System.Text.RegularExpressions/4.1.0": {
|
||||
"dependencies": {
|
||||
"System.Collections": "4.0.11",
|
||||
"System.Globalization": "4.0.11",
|
||||
"System.Resources.ResourceManager": "4.0.1",
|
||||
"System.Runtime": "4.1.0",
|
||||
"System.Runtime.Extensions": "4.1.0",
|
||||
"System.Threading": "4.0.11"
|
||||
}
|
||||
},
|
||||
"System.Threading/4.0.11": {
|
||||
"dependencies": {
|
||||
"System.Runtime": "4.1.0",
|
||||
"System.Threading.Tasks": "4.0.11"
|
||||
}
|
||||
},
|
||||
"System.Threading.Tasks/4.0.11": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Platforms": "1.0.1",
|
||||
"Microsoft.NETCore.Targets": "1.0.1",
|
||||
"System.Runtime": "4.1.0"
|
||||
}
|
||||
},
|
||||
"System.Threading.Tasks.Extensions/4.0.0": {
|
||||
"dependencies": {
|
||||
"System.Collections": "4.0.11",
|
||||
"System.Runtime": "4.1.0",
|
||||
"System.Threading.Tasks": "4.0.11"
|
||||
}
|
||||
},
|
||||
"System.Xml.ReaderWriter/4.0.11": {
|
||||
"dependencies": {
|
||||
"System.Collections": "4.0.11",
|
||||
"System.Diagnostics.Debug": "4.0.11",
|
||||
"System.Globalization": "4.0.11",
|
||||
"System.IO": "4.1.0",
|
||||
"System.IO.FileSystem": "4.0.1",
|
||||
"System.IO.FileSystem.Primitives": "4.0.1",
|
||||
"System.Resources.ResourceManager": "4.0.1",
|
||||
"System.Runtime": "4.1.0",
|
||||
"System.Runtime.Extensions": "4.1.0",
|
||||
"System.Runtime.InteropServices": "4.1.0",
|
||||
"System.Text.Encoding": "4.0.11",
|
||||
"System.Text.Encoding.Extensions": "4.0.11",
|
||||
"System.Text.RegularExpressions": "4.1.0",
|
||||
"System.Threading.Tasks": "4.0.11",
|
||||
"System.Threading.Tasks.Extensions": "4.0.0"
|
||||
}
|
||||
},
|
||||
"System.Xml.XDocument/4.0.11": {
|
||||
"dependencies": {
|
||||
"System.Collections": "4.0.11",
|
||||
"System.Diagnostics.Debug": "4.0.11",
|
||||
"System.Diagnostics.Tools": "4.0.1",
|
||||
"System.Globalization": "4.0.11",
|
||||
"System.IO": "4.1.0",
|
||||
"System.Reflection": "4.1.0",
|
||||
"System.Resources.ResourceManager": "4.0.1",
|
||||
"System.Runtime": "4.1.0",
|
||||
"System.Runtime.Extensions": "4.1.0",
|
||||
"System.Text.Encoding": "4.0.11",
|
||||
"System.Threading": "4.0.11",
|
||||
"System.Xml.ReaderWriter": "4.0.11"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"dotnet-bundle/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Microsoft.Build.Tasks.Git/1.0.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-z2fpmmt+1Jfl+ZnBki9nSP08S1/tbEOxFdsK1rSR+LBehIJz1Xv9/6qOOoGNqlwnAGGVGis1Oj6S8Kt9COEYlQ==",
|
||||
"path": "microsoft.build.tasks.git/1.0.0",
|
||||
"hashPath": "microsoft.build.tasks.git.1.0.0.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.CSharp/4.0.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-17h8b5mXa87XYKrrVqdgZ38JefSUqLChUQpXgSnpzsM0nDOhE40FTeNWOJ/YmySGV6tG6T8+hjz6vxbknHJr6A==",
|
||||
"path": "microsoft.csharp/4.0.1",
|
||||
"hashPath": "microsoft.csharp.4.0.1.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.NETCore.Platforms/1.0.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-2G6OjjJzwBfNOO8myRV/nFrbTw5iA+DEm0N+qUqhrOmaVtn4pC77h38I1jsXGw5VH55+dPfQsqHD0We9sCl9FQ==",
|
||||
"path": "microsoft.netcore.platforms/1.0.1",
|
||||
"hashPath": "microsoft.netcore.platforms.1.0.1.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.NETCore.Targets/1.0.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-rkn+fKobF/cbWfnnfBOQHKVKIOpxMZBvlSHkqDWgBpwGDcLRduvs3D9OLGeV6GWGvVwNlVi2CBbTjuPmtHvyNw==",
|
||||
"path": "microsoft.netcore.targets/1.0.1",
|
||||
"hashPath": "microsoft.netcore.targets.1.0.1.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.SourceLink.Common/1.0.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-G8DuQY8/DK5NN+3jm5wcMcd9QYD90UV7MiLmdljSJixi3U/vNaeBKmmXUqI4DJCOeWizIUEh4ALhSt58mR+5eg==",
|
||||
"path": "microsoft.sourcelink.common/1.0.0",
|
||||
"hashPath": "microsoft.sourcelink.common.1.0.0.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.SourceLink.GitHub/1.0.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-aZyGyGg2nFSxix+xMkPmlmZSsnGQ3w+mIG23LTxJZHN+GPwTQ5FpPgDo7RMOq+Kcf5D4hFWfXkGhoGstawX13Q==",
|
||||
"path": "microsoft.sourcelink.github/1.0.0",
|
||||
"hashPath": "microsoft.sourcelink.github.1.0.0.nupkg.sha512"
|
||||
},
|
||||
"Newtonsoft.Json/9.0.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-U82mHQSKaIk+lpSVCbWYKNavmNH1i5xrExDEquU1i6I5pV6UMOqRnJRSlKO3cMPfcpp0RgDY+8jUXHdQ4IfXvw==",
|
||||
"path": "newtonsoft.json/9.0.1",
|
||||
"hashPath": "newtonsoft.json.9.0.1.nupkg.sha512"
|
||||
},
|
||||
"NUglify/1.17.10": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-gWQYFaWZsYwr8Iz5dcrudn8fyWXgu5NKyPVDyGzF2peXqLLnlz65PEfIhiT0hs1VWCgCRU1Y+/mTp9zsMmFKBg==",
|
||||
"path": "nuglify/1.17.10",
|
||||
"hashPath": "nuglify.1.17.10.nupkg.sha512"
|
||||
},
|
||||
"System.Collections/4.0.11": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-YUJGz6eFKqS0V//mLt25vFGrrCvOnsXjlvFQs+KimpwNxug9x0Pzy4PlFMU3Q2IzqAa9G2L4LsK3+9vCBK7oTg==",
|
||||
"path": "system.collections/4.0.11",
|
||||
"hashPath": "system.collections.4.0.11.nupkg.sha512"
|
||||
},
|
||||
"System.Diagnostics.Debug/4.0.11": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-w5U95fVKHY4G8ASs/K5iK3J5LY+/dLFd4vKejsnI/ZhBsWS9hQakfx3Zr7lRWKg4tAw9r4iktyvsTagWkqYCiw==",
|
||||
"path": "system.diagnostics.debug/4.0.11",
|
||||
"hashPath": "system.diagnostics.debug.4.0.11.nupkg.sha512"
|
||||
},
|
||||
"System.Diagnostics.Tools/4.0.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-xBfJ8pnd4C17dWaC9FM6aShzbJcRNMChUMD42I6772KGGrqaFdumwhn9OdM68erj1ueNo3xdQ1EwiFjK5k8p0g==",
|
||||
"path": "system.diagnostics.tools/4.0.1",
|
||||
"hashPath": "system.diagnostics.tools.4.0.1.nupkg.sha512"
|
||||
},
|
||||
"System.Dynamic.Runtime/4.0.11": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-db34f6LHYM0U0JpE+sOmjar27BnqTVkbLJhgfwMpTdgTigG/Hna3m2MYVwnFzGGKnEJk2UXFuoVTr8WUbU91/A==",
|
||||
"path": "system.dynamic.runtime/4.0.11",
|
||||
"hashPath": "system.dynamic.runtime.4.0.11.nupkg.sha512"
|
||||
},
|
||||
"System.Globalization/4.0.11": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-B95h0YLEL2oSnwF/XjqSWKnwKOy/01VWkNlsCeMTFJLLabflpGV26nK164eRs5GiaRSBGpOxQ3pKoSnnyZN5pg==",
|
||||
"path": "system.globalization/4.0.11",
|
||||
"hashPath": "system.globalization.4.0.11.nupkg.sha512"
|
||||
},
|
||||
"System.IO/4.1.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-3KlTJceQc3gnGIaHZ7UBZO26SHL1SHE4ddrmiwumFnId+CEHP+O8r386tZKaE6zlk5/mF8vifMBzHj9SaXN+mQ==",
|
||||
"path": "system.io/4.1.0",
|
||||
"hashPath": "system.io.4.1.0.nupkg.sha512"
|
||||
},
|
||||
"System.IO.FileSystem/4.0.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-IBErlVq5jOggAD69bg1t0pJcHaDbJbWNUZTPI96fkYWzwYbN6D9wRHMULLDd9dHsl7C2YsxXL31LMfPI1SWt8w==",
|
||||
"path": "system.io.filesystem/4.0.1",
|
||||
"hashPath": "system.io.filesystem.4.0.1.nupkg.sha512"
|
||||
},
|
||||
"System.IO.FileSystem.Primitives/4.0.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-kWkKD203JJKxJeE74p8aF8y4Qc9r9WQx4C0cHzHPrY3fv/L/IhWnyCHaFJ3H1QPOH6A93whlQ2vG5nHlBDvzWQ==",
|
||||
"path": "system.io.filesystem.primitives/4.0.1",
|
||||
"hashPath": "system.io.filesystem.primitives.4.0.1.nupkg.sha512"
|
||||
},
|
||||
"System.Linq/4.1.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-bQ0iYFOQI0nuTnt+NQADns6ucV4DUvMdwN6CbkB1yj8i7arTGiTN5eok1kQwdnnNWSDZfIUySQY+J3d5KjWn0g==",
|
||||
"path": "system.linq/4.1.0",
|
||||
"hashPath": "system.linq.4.1.0.nupkg.sha512"
|
||||
},
|
||||
"System.Linq.Expressions/4.1.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-I+y02iqkgmCAyfbqOmSDOgqdZQ5tTj80Akm5BPSS8EeB0VGWdy6X1KCoYe8Pk6pwDoAKZUOdLVxnTJcExiv5zw==",
|
||||
"path": "system.linq.expressions/4.1.0",
|
||||
"hashPath": "system.linq.expressions.4.1.0.nupkg.sha512"
|
||||
},
|
||||
"System.ObjectModel/4.0.12": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-tAgJM1xt3ytyMoW4qn4wIqgJYm7L7TShRZG4+Q4Qsi2PCcj96pXN7nRywS9KkB3p/xDUjc2HSwP9SROyPYDYKQ==",
|
||||
"path": "system.objectmodel/4.0.12",
|
||||
"hashPath": "system.objectmodel.4.0.12.nupkg.sha512"
|
||||
},
|
||||
"System.Reflection/4.1.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-JCKANJ0TI7kzoQzuwB/OoJANy1Lg338B6+JVacPl4TpUwi3cReg3nMLplMq2uqYfHFQpKIlHAUVAJlImZz/4ng==",
|
||||
"path": "system.reflection/4.1.0",
|
||||
"hashPath": "system.reflection.4.1.0.nupkg.sha512"
|
||||
},
|
||||
"System.Reflection.Emit/4.0.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-P2wqAj72fFjpP6wb9nSfDqNBMab+2ovzSDzUZK7MVIm54tBJEPr9jWfSjjoTpPwj1LeKcmX3vr0ttyjSSFM47g==",
|
||||
"path": "system.reflection.emit/4.0.1",
|
||||
"hashPath": "system.reflection.emit.4.0.1.nupkg.sha512"
|
||||
},
|
||||
"System.Reflection.Emit.ILGeneration/4.0.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-Ov6dU8Bu15Bc7zuqttgHF12J5lwSWyTf1S+FJouUXVMSqImLZzYaQ+vRr1rQ0OZ0HqsrwWl4dsKHELckQkVpgA==",
|
||||
"path": "system.reflection.emit.ilgeneration/4.0.1",
|
||||
"hashPath": "system.reflection.emit.ilgeneration.4.0.1.nupkg.sha512"
|
||||
},
|
||||
"System.Reflection.Emit.Lightweight/4.0.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-sSzHHXueZ5Uh0OLpUQprhr+ZYJrLPA2Cmr4gn0wj9+FftNKXx8RIMKvO9qnjk2ebPYUjZ+F2ulGdPOsvj+MEjA==",
|
||||
"path": "system.reflection.emit.lightweight/4.0.1",
|
||||
"hashPath": "system.reflection.emit.lightweight.4.0.1.nupkg.sha512"
|
||||
},
|
||||
"System.Reflection.Extensions/4.0.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-GYrtRsZcMuHF3sbmRHfMYpvxZoIN2bQGrYGerUiWLEkqdEUQZhH3TRSaC/oI4wO0II1RKBPlpIa1TOMxIcOOzQ==",
|
||||
"path": "system.reflection.extensions/4.0.1",
|
||||
"hashPath": "system.reflection.extensions.4.0.1.nupkg.sha512"
|
||||
},
|
||||
"System.Reflection.Primitives/4.0.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-4inTox4wTBaDhB7V3mPvp9XlCbeGYWVEM9/fXALd52vNEAVisc1BoVWQPuUuD0Ga//dNbA/WeMy9u9mzLxGTHQ==",
|
||||
"path": "system.reflection.primitives/4.0.1",
|
||||
"hashPath": "system.reflection.primitives.4.0.1.nupkg.sha512"
|
||||
},
|
||||
"System.Reflection.TypeExtensions/4.1.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-tsQ/ptQ3H5FYfON8lL4MxRk/8kFyE0A+tGPXmVP967cT/gzLHYxIejIYSxp4JmIeFHVP78g/F2FE1mUUTbDtrg==",
|
||||
"path": "system.reflection.typeextensions/4.1.0",
|
||||
"hashPath": "system.reflection.typeextensions.4.1.0.nupkg.sha512"
|
||||
},
|
||||
"System.Resources.ResourceManager/4.0.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-TxwVeUNoTgUOdQ09gfTjvW411MF+w9MBYL7AtNVc+HtBCFlutPLhUCdZjNkjbhj3bNQWMdHboF0KIWEOjJssbA==",
|
||||
"path": "system.resources.resourcemanager/4.0.1",
|
||||
"hashPath": "system.resources.resourcemanager.4.0.1.nupkg.sha512"
|
||||
},
|
||||
"System.Runtime/4.1.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-v6c/4Yaa9uWsq+JMhnOFewrYkgdNHNG2eMKuNqRn8P733rNXeRCGvV5FkkjBXn2dbVkPXOsO0xjsEeM1q2zC0g==",
|
||||
"path": "system.runtime/4.1.0",
|
||||
"hashPath": "system.runtime.4.1.0.nupkg.sha512"
|
||||
},
|
||||
"System.Runtime.Extensions/4.1.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-CUOHjTT/vgP0qGW22U4/hDlOqXmcPq5YicBaXdUR2UiUoLwBT+olO6we4DVbq57jeX5uXH2uerVZhf0qGj+sVQ==",
|
||||
"path": "system.runtime.extensions/4.1.0",
|
||||
"hashPath": "system.runtime.extensions.4.1.0.nupkg.sha512"
|
||||
},
|
||||
"System.Runtime.Handles/4.0.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-nCJvEKguXEvk2ymk1gqj625vVnlK3/xdGzx0vOKicQkoquaTBJTP13AIYkocSUwHCLNBwUbXTqTWGDxBTWpt7g==",
|
||||
"path": "system.runtime.handles/4.0.1",
|
||||
"hashPath": "system.runtime.handles.4.0.1.nupkg.sha512"
|
||||
},
|
||||
"System.Runtime.InteropServices/4.1.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-16eu3kjHS633yYdkjwShDHZLRNMKVi/s0bY8ODiqJ2RfMhDMAwxZaUaWVnZ2P71kr/or+X9o/xFWtNqz8ivieQ==",
|
||||
"path": "system.runtime.interopservices/4.1.0",
|
||||
"hashPath": "system.runtime.interopservices.4.1.0.nupkg.sha512"
|
||||
},
|
||||
"System.Runtime.Serialization.Primitives/4.1.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-HZ6Du5QrTG8MNJbf4e4qMO3JRAkIboGT5Fk804uZtg3Gq516S7hAqTm2UZKUHa7/6HUGdVy3AqMQKbns06G/cg==",
|
||||
"path": "system.runtime.serialization.primitives/4.1.1",
|
||||
"hashPath": "system.runtime.serialization.primitives.4.1.1.nupkg.sha512"
|
||||
},
|
||||
"System.Text.Encoding/4.0.11": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-U3gGeMlDZXxCEiY4DwVLSacg+DFWCvoiX+JThA/rvw37Sqrku7sEFeVBBBMBnfB6FeZHsyDx85HlKL19x0HtZA==",
|
||||
"path": "system.text.encoding/4.0.11",
|
||||
"hashPath": "system.text.encoding.4.0.11.nupkg.sha512"
|
||||
},
|
||||
"System.Text.Encoding.Extensions/4.0.11": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-jtbiTDtvfLYgXn8PTfWI+SiBs51rrmO4AAckx4KR6vFK9Wzf6tI8kcRdsYQNwriUeQ1+CtQbM1W4cMbLXnj/OQ==",
|
||||
"path": "system.text.encoding.extensions/4.0.11",
|
||||
"hashPath": "system.text.encoding.extensions.4.0.11.nupkg.sha512"
|
||||
},
|
||||
"System.Text.RegularExpressions/4.1.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-i88YCXpRTjCnoSQZtdlHkAOx4KNNik4hMy83n0+Ftlb7jvV6ZiZWMpnEZHhjBp6hQVh8gWd/iKNPzlPF7iyA2g==",
|
||||
"path": "system.text.regularexpressions/4.1.0",
|
||||
"hashPath": "system.text.regularexpressions.4.1.0.nupkg.sha512"
|
||||
},
|
||||
"System.Threading/4.0.11": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-N+3xqIcg3VDKyjwwCGaZ9HawG9aC6cSDI+s7ROma310GQo8vilFZa86hqKppwTHleR/G0sfOzhvgnUxWCR/DrQ==",
|
||||
"path": "system.threading/4.0.11",
|
||||
"hashPath": "system.threading.4.0.11.nupkg.sha512"
|
||||
},
|
||||
"System.Threading.Tasks/4.0.11": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-k1S4Gc6IGwtHGT8188RSeGaX86Qw/wnrgNLshJvsdNUOPP9etMmo8S07c+UlOAx4K/xLuN9ivA1bD0LVurtIxQ==",
|
||||
"path": "system.threading.tasks/4.0.11",
|
||||
"hashPath": "system.threading.tasks.4.0.11.nupkg.sha512"
|
||||
},
|
||||
"System.Threading.Tasks.Extensions/4.0.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-pH4FZDsZQ/WmgJtN4LWYmRdJAEeVkyriSwrv2Teoe5FOU0Yxlb6II6GL8dBPOfRmutHGATduj3ooMt7dJ2+i+w==",
|
||||
"path": "system.threading.tasks.extensions/4.0.0",
|
||||
"hashPath": "system.threading.tasks.extensions.4.0.0.nupkg.sha512"
|
||||
},
|
||||
"System.Xml.ReaderWriter/4.0.11": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-ZIiLPsf67YZ9zgr31vzrFaYQqxRPX9cVHjtPSnmx4eN6lbS/yEyYNr2vs1doGDEscF0tjCZFsk9yUg1sC9e8tg==",
|
||||
"path": "system.xml.readerwriter/4.0.11",
|
||||
"hashPath": "system.xml.readerwriter.4.0.11.nupkg.sha512"
|
||||
},
|
||||
"System.Xml.XDocument/4.0.11": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-Mk2mKmPi0nWaoiYeotq1dgeNK1fqWh61+EK+w4Wu8SWuTYLzpUnschb59bJtGywaPq7SmTuPf44wrXRwbIrukg==",
|
||||
"path": "system.xml.xdocument/4.0.11",
|
||||
"hashPath": "system.xml.xdocument.4.0.11.nupkg.sha512"
|
||||
}
|
||||
}
|
||||
}
|
BIN
WebfrontCore/dotnet-bundle.dll
Normal file
BIN
WebfrontCore/dotnet-bundle.dll
Normal file
Binary file not shown.
BIN
WebfrontCore/dotnet-bundle.exe
Normal file
BIN
WebfrontCore/dotnet-bundle.exe
Normal file
Binary file not shown.
9
WebfrontCore/dotnet-bundle.runtimeconfig.json
Normal file
9
WebfrontCore/dotnet-bundle.runtimeconfig.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"runtimeOptions": {
|
||||
"tfm": "net6.0",
|
||||
"framework": {
|
||||
"name": "Microsoft.NETCore.App",
|
||||
"version": "6.0.0"
|
||||
}
|
||||
}
|
||||
}
|
@ -27,25 +27,25 @@ function getPlayerHistoryChart(playerHistory, i, width, maxClients) {
|
||||
let lastMap = '';
|
||||
|
||||
playerHistory.forEach((elem, i) => {
|
||||
if (elem.map !== lastMap) {
|
||||
if (elem.ma !== lastMap) {
|
||||
mapChange.push(i);
|
||||
lastMap = elem.map;
|
||||
lastMap = elem;
|
||||
}
|
||||
|
||||
if (elem.connectionInterrupted) {
|
||||
offlineTime.push({
|
||||
clientCount: maxClients,
|
||||
timeString: elem.timeString
|
||||
timeString: elem.ts
|
||||
});
|
||||
|
||||
onlineTime.push({
|
||||
clientCount: 0,
|
||||
timeString: elem.timeString
|
||||
timeString: elem.ts
|
||||
})
|
||||
} else {
|
||||
offlineTime.push({
|
||||
clientCount: 0,
|
||||
timeString: elem.timeString
|
||||
timeString: elem.ts
|
||||
});
|
||||
|
||||
onlineTime.push(elem)
|
||||
@ -60,9 +60,9 @@ function getPlayerHistoryChart(playerHistory, i, width, maxClients) {
|
||||
return new Chart(document.getElementById(`server_history_canvas_${i}`), {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: playerHistory.map(history => history.timeString),
|
||||
labels: playerHistory.map(history => history.ts),
|
||||
datasets: [{
|
||||
data: onlineTime.map(history => history.clientCount),
|
||||
data: onlineTime.map(history => history.cc),
|
||||
backgroundColor: fillColor,
|
||||
borderColor: primaryColor,
|
||||
borderWidth: 2,
|
||||
@ -70,7 +70,7 @@ function getPlayerHistoryChart(playerHistory, i, width, maxClients) {
|
||||
hoverBorderWidth: 2
|
||||
},
|
||||
{
|
||||
data: offlineTime.map(history => history.clientCount),
|
||||
data: offlineTime.map(history => history.cc),
|
||||
backgroundColor: createDiagonalPattern(offlineFillColor),
|
||||
borderColor: offlineFillColor,
|
||||
borderWidth: 2,
|
||||
@ -88,7 +88,7 @@ function getPlayerHistoryChart(playerHistory, i, width, maxClients) {
|
||||
callbacks: {
|
||||
// todo: localization at some point
|
||||
title: context => moment(context[0].label).local().calendar(),
|
||||
label: context => context.datasetIndex !== 1 ? `${context.value} ${_localization['WEBFRONT_SCRIPT_SERVER_PLAYERS']} | ${playerHistory[context.index].mapAlias}` : context.value === '0' ? '' : _localization['WEBFRONT_SCRIPT_SERVER_UNREACHABLE'],
|
||||
label: context => context.datasetIndex !== 1 ? `${context.value} ${_localization['WEBFRONT_SCRIPT_SERVER_PLAYERS']} | ${playerHistory[context.index].ma}` : context.value === '0' ? '' : _localization['WEBFRONT_SCRIPT_SERVER_UNREACHABLE'],
|
||||
},
|
||||
mode: 'nearest',
|
||||
intersect: false,
|
||||
@ -153,13 +153,14 @@ $(document).ready(function () {
|
||||
$(this).parent().parent().find('.server-header-ip-address').show();
|
||||
});
|
||||
|
||||
$('.server-history-row').each(function (index, element) {
|
||||
let clientHistory = $(this).data('clienthistory-ex');
|
||||
$('.server-history-row').each(async function (index, element) {
|
||||
const serverId = $(this).data('serverid');
|
||||
const serverEp = $(this).data('server-endpoint');
|
||||
setInterval(() => refreshClientActivity(serverId), 2000 + (index * 100));
|
||||
let maxClients = parseInt($('#server_header_' + serverId + ' .server-maxclients').text());
|
||||
let width = $('.server-header').first().width();
|
||||
getPlayerHistoryChart(clientHistory, serverId, width, maxClients);
|
||||
const clientHistory = await fetch(`/api/server/${serverEp}/history`);
|
||||
getPlayerHistoryChart(await clientHistory.json(), serverId, width, maxClients);
|
||||
});
|
||||
|
||||
$('.moment-date').each((index, element) => {
|
||||
|
Loading…
Reference in New Issue
Block a user