Use game time from log to ignore potential false disconnect lines - Fix for latent linking issues with multiple ips - Anticheat fix for T6 - retry kick on update if they're not allowed to connect
This commit is contained in:
parent
15e2170100
commit
fe380ca331
1
.gitignore
vendored
1
.gitignore
vendored
@ -240,3 +240,4 @@ launchSettings.json
|
|||||||
/Master/master/persistence
|
/Master/master/persistence
|
||||||
/WebfrontCore/wwwroot/fonts
|
/WebfrontCore/wwwroot/fonts
|
||||||
/WebfrontCore/wwwroot/font
|
/WebfrontCore/wwwroot/font
|
||||||
|
/Plugins/Tests/TestSourceFiles
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
using SharedLibraryCore.Database.Models;
|
using SharedLibraryCore.Database.Models;
|
||||||
using SharedLibraryCore.Interfaces;
|
using SharedLibraryCore.Interfaces;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using static SharedLibraryCore.Server;
|
using static SharedLibraryCore.Server;
|
||||||
|
|
||||||
@ -78,7 +80,18 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
|
|
||||||
public virtual GameEvent GenerateGameEvent(string logLine)
|
public virtual GameEvent GenerateGameEvent(string logLine)
|
||||||
{
|
{
|
||||||
logLine = Regex.Replace(logLine, @"([0-9]+:[0-9]+ |^[0-9]+ )", "").Trim();
|
var timeMatch = Regex.Match(logLine, @"^ *(([0-9]+):([0-9]+) |^[0-9]+ )");
|
||||||
|
int gameTime = 0;
|
||||||
|
|
||||||
|
if (timeMatch.Success)
|
||||||
|
{
|
||||||
|
gameTime = (timeMatch.Groups.Values as IEnumerable<object>)
|
||||||
|
.Skip(2)
|
||||||
|
.Select(_value => int.Parse(_value.ToString()))
|
||||||
|
.Sum();
|
||||||
|
logLine = logLine.Substring(timeMatch.Value.Length);
|
||||||
|
}
|
||||||
|
|
||||||
string[] lineSplit = logLine.Split(';');
|
string[] lineSplit = logLine.Split(';');
|
||||||
string eventType = lineSplit[0];
|
string eventType = lineSplit[0];
|
||||||
|
|
||||||
@ -107,7 +120,8 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
Origin = new EFClient() { NetworkId = originId },
|
Origin = new EFClient() { NetworkId = originId },
|
||||||
Message = message,
|
Message = message,
|
||||||
Extra = logLine,
|
Extra = logLine,
|
||||||
RequiredEntity = GameEvent.EventRequiredEntity.Origin
|
RequiredEntity = GameEvent.EventRequiredEntity.Origin,
|
||||||
|
GameTime = gameTime
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +132,8 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
Origin = new EFClient() { NetworkId = originId },
|
Origin = new EFClient() { NetworkId = originId },
|
||||||
Message = message,
|
Message = message,
|
||||||
Extra = logLine,
|
Extra = logLine,
|
||||||
RequiredEntity = GameEvent.EventRequiredEntity.Origin
|
RequiredEntity = GameEvent.EventRequiredEntity.Origin,
|
||||||
|
GameTime = gameTime
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,7 +154,8 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
Data = logLine,
|
Data = logLine,
|
||||||
Origin = new EFClient() { NetworkId = originId },
|
Origin = new EFClient() { NetworkId = originId },
|
||||||
Target = new EFClient() { NetworkId = targetId },
|
Target = new EFClient() { NetworkId = targetId },
|
||||||
RequiredEntity = GameEvent.EventRequiredEntity.Origin | GameEvent.EventRequiredEntity.Target
|
RequiredEntity = GameEvent.EventRequiredEntity.Origin | GameEvent.EventRequiredEntity.Target,
|
||||||
|
GameTime = gameTime
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -159,7 +175,8 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
Data = logLine,
|
Data = logLine,
|
||||||
Origin = new EFClient() { NetworkId = originId },
|
Origin = new EFClient() { NetworkId = originId },
|
||||||
Target = new EFClient() { NetworkId = targetId },
|
Target = new EFClient() { NetworkId = targetId },
|
||||||
RequiredEntity = GameEvent.EventRequiredEntity.Origin | GameEvent.EventRequiredEntity.Target
|
RequiredEntity = GameEvent.EventRequiredEntity.Origin | GameEvent.EventRequiredEntity.Target,
|
||||||
|
GameTime = gameTime
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -185,7 +202,8 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
State = EFClient.ClientState.Connecting,
|
State = EFClient.ClientState.Connecting,
|
||||||
},
|
},
|
||||||
RequiredEntity = GameEvent.EventRequiredEntity.None,
|
RequiredEntity = GameEvent.EventRequiredEntity.None,
|
||||||
IsBlocking = true
|
IsBlocking = true,
|
||||||
|
GameTime = gameTime
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -210,7 +228,8 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
State = EFClient.ClientState.Disconnecting
|
State = EFClient.ClientState.Disconnecting
|
||||||
},
|
},
|
||||||
RequiredEntity = GameEvent.EventRequiredEntity.None,
|
RequiredEntity = GameEvent.EventRequiredEntity.None,
|
||||||
IsBlocking = true
|
IsBlocking = true,
|
||||||
|
GameTime = gameTime
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -223,7 +242,8 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
Data = logLine,
|
Data = logLine,
|
||||||
Origin = Utilities.IW4MAdminClient(),
|
Origin = Utilities.IW4MAdminClient(),
|
||||||
Target = Utilities.IW4MAdminClient(),
|
Target = Utilities.IW4MAdminClient(),
|
||||||
RequiredEntity = GameEvent.EventRequiredEntity.None
|
RequiredEntity = GameEvent.EventRequiredEntity.None,
|
||||||
|
GameTime = gameTime
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,7 +258,8 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
Origin = Utilities.IW4MAdminClient(),
|
Origin = Utilities.IW4MAdminClient(),
|
||||||
Target = Utilities.IW4MAdminClient(),
|
Target = Utilities.IW4MAdminClient(),
|
||||||
Extra = dump.DictionaryFromKeyValue(),
|
Extra = dump.DictionaryFromKeyValue(),
|
||||||
RequiredEntity = GameEvent.EventRequiredEntity.None
|
RequiredEntity = GameEvent.EventRequiredEntity.None,
|
||||||
|
GameTime = gameTime
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,7 +271,8 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
Type = GameEvent.EventType.JoinTeam,
|
Type = GameEvent.EventType.JoinTeam,
|
||||||
Data = logLine,
|
Data = logLine,
|
||||||
Origin = new EFClient() { NetworkId = lineSplit[1].ConvertGuidToLong(Configuration.GuidNumberStyle) },
|
Origin = new EFClient() { NetworkId = lineSplit[1].ConvertGuidToLong(Configuration.GuidNumberStyle) },
|
||||||
RequiredEntity = GameEvent.EventRequiredEntity.Target
|
RequiredEntity = GameEvent.EventRequiredEntity.Target,
|
||||||
|
GameTime = gameTime
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +289,8 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
Data = logLine,
|
Data = logLine,
|
||||||
Origin = new EFClient() { NetworkId = originId },
|
Origin = new EFClient() { NetworkId = originId },
|
||||||
Target = new EFClient() { NetworkId = targetId },
|
Target = new EFClient() { NetworkId = targetId },
|
||||||
RequiredEntity = GameEvent.EventRequiredEntity.Origin | GameEvent.EventRequiredEntity.Target
|
RequiredEntity = GameEvent.EventRequiredEntity.Origin | GameEvent.EventRequiredEntity.Target,
|
||||||
|
GameTime = gameTime
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,7 +306,8 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
Data = logLine,
|
Data = logLine,
|
||||||
Origin = new EFClient() { NetworkId = originId },
|
Origin = new EFClient() { NetworkId = originId },
|
||||||
Target = new EFClient() { NetworkId = targetId },
|
Target = new EFClient() { NetworkId = targetId },
|
||||||
RequiredEntity = GameEvent.EventRequiredEntity.Origin | GameEvent.EventRequiredEntity.Target
|
RequiredEntity = GameEvent.EventRequiredEntity.Origin | GameEvent.EventRequiredEntity.Target,
|
||||||
|
GameTime = gameTime
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,7 +317,8 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
Data = logLine,
|
Data = logLine,
|
||||||
Origin = Utilities.IW4MAdminClient(),
|
Origin = Utilities.IW4MAdminClient(),
|
||||||
Target = Utilities.IW4MAdminClient(),
|
Target = Utilities.IW4MAdminClient(),
|
||||||
RequiredEntity = GameEvent.EventRequiredEntity.None
|
RequiredEntity = GameEvent.EventRequiredEntity.None,
|
||||||
|
GameTime = gameTime
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ namespace IW4MAdmin
|
|||||||
private readonly ITranslationLookup _translationLookup;
|
private readonly ITranslationLookup _translationLookup;
|
||||||
private const int REPORT_FLAG_COUNT = 4;
|
private const int REPORT_FLAG_COUNT = 4;
|
||||||
private readonly IPluginImporter _pluginImporter;
|
private readonly IPluginImporter _pluginImporter;
|
||||||
|
private int lastGameTime = 0;
|
||||||
|
|
||||||
public int Id { get; private set; }
|
public int Id { get; private set; }
|
||||||
|
|
||||||
@ -93,18 +94,18 @@ namespace IW4MAdmin
|
|||||||
if (client.ClientNumber >= 0)
|
if (client.ClientNumber >= 0)
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
Logger.WriteInfo($"Client {client} [{client.State.ToString().ToLower()}] disconnecting...");
|
Logger.WriteInfo($"Client {client} [{client.State.ToString().ToLower()}] disconnecting...");
|
||||||
Clients[client.ClientNumber] = null;
|
Clients[client.ClientNumber] = null;
|
||||||
await client.OnDisconnect();
|
await client.OnDisconnect();
|
||||||
|
|
||||||
var e = new GameEvent()
|
var e = new GameEvent()
|
||||||
{
|
{
|
||||||
Origin = client,
|
Origin = client,
|
||||||
Owner = this,
|
Owner = this,
|
||||||
Type = GameEvent.EventType.Disconnect
|
Type = GameEvent.EventType.Disconnect
|
||||||
};
|
};
|
||||||
|
|
||||||
Manager.GetEventHandler().AddEvent(e);
|
Manager.GetEventHandler().AddEvent(e);
|
||||||
#if DEBUG == true
|
#if DEBUG == true
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -434,6 +435,14 @@ namespace IW4MAdmin
|
|||||||
|
|
||||||
else if (E.Type == GameEvent.EventType.PreDisconnect)
|
else if (E.Type == GameEvent.EventType.PreDisconnect)
|
||||||
{
|
{
|
||||||
|
bool isPotentialFalseQuit = E.GameTime.HasValue && E.GameTime.Value == lastGameTime;
|
||||||
|
|
||||||
|
if (isPotentialFalseQuit)
|
||||||
|
{
|
||||||
|
Logger.WriteInfo($"Receive predisconnect event for {E}, but it occured at game time {E.GameTime.Value}, which is the same last map change, so we're ignoring");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// predisconnect comes from minimal rcon polled players and minimal log players
|
// predisconnect comes from minimal rcon polled players and minimal log players
|
||||||
// so we need to disconnect the "full" version of the client
|
// so we need to disconnect the "full" version of the client
|
||||||
var client = GetClientsAsList().FirstOrDefault(_client => _client.Equals(E.Origin));
|
var client = GetClientsAsList().FirstOrDefault(_client => _client.Equals(E.Origin));
|
||||||
@ -531,11 +540,21 @@ namespace IW4MAdmin
|
|||||||
string mapname = dict["mapname"];
|
string mapname = dict["mapname"];
|
||||||
UpdateMap(mapname);
|
UpdateMap(mapname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (E.GameTime.HasValue)
|
||||||
|
{
|
||||||
|
lastGameTime = E.GameTime.Value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (E.Type == GameEvent.EventType.MapEnd)
|
if (E.Type == GameEvent.EventType.MapEnd)
|
||||||
{
|
{
|
||||||
Logger.WriteInfo("Game ending...");
|
Logger.WriteInfo("Game ending...");
|
||||||
|
|
||||||
|
if (E.GameTime.HasValue)
|
||||||
|
{
|
||||||
|
lastGameTime = E.GameTime.Value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (E.Type == GameEvent.EventType.Tell)
|
if (E.Type == GameEvent.EventType.Tell)
|
||||||
@ -601,6 +620,12 @@ namespace IW4MAdmin
|
|||||||
Logger.WriteDebug(e.GetExceptionInfo());
|
Logger.WriteDebug(e.GetExceptionInfo());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (client.IPAddress != null && client.State == ClientState.Disconnecting)
|
||||||
|
{
|
||||||
|
Logger.WriteWarning($"{client} state is Disconnecting (probably kicked), but they are still connected. trying to kick again...");
|
||||||
|
await client.CanConnect(client.IPAddress);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -70,7 +70,7 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="hit">kill performed by the player</param>
|
/// <param name="hit">kill performed by the player</param>
|
||||||
/// <returns>true if detection reached thresholds, false otherwise</returns>
|
/// <returns>true if detection reached thresholds, false otherwise</returns>
|
||||||
public DetectionPenaltyResult ProcessHit(EFClientKill hit, bool isDamage)
|
public IEnumerable<DetectionPenaltyResult> ProcessHit(EFClientKill hit)
|
||||||
{
|
{
|
||||||
var results = new List<DetectionPenaltyResult>();
|
var results = new List<DetectionPenaltyResult>();
|
||||||
|
|
||||||
@ -81,10 +81,10 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
// hack: prevents false positives
|
// hack: prevents false positives
|
||||||
(LastWeapon != hit.Weapon && (hit.TimeOffset - LastOffset) == 50))
|
(LastWeapon != hit.Weapon && (hit.TimeOffset - LastOffset) == 50))
|
||||||
{
|
{
|
||||||
return new DetectionPenaltyResult()
|
return new[] {new DetectionPenaltyResult()
|
||||||
{
|
{
|
||||||
ClientPenalty = EFPenalty.PenaltyType.Any,
|
ClientPenalty = EFPenalty.PenaltyType.Any,
|
||||||
};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
LastWeapon = hit.Weapon;
|
LastWeapon = hit.Weapon;
|
||||||
@ -92,7 +92,7 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
HitLocationCount[hit.HitLoc].Count++;
|
HitLocationCount[hit.HitLoc].Count++;
|
||||||
HitCount++;
|
HitCount++;
|
||||||
|
|
||||||
if (!isDamage)
|
if (hit.IsKill)
|
||||||
{
|
{
|
||||||
Kills++;
|
Kills++;
|
||||||
}
|
}
|
||||||
@ -464,12 +464,7 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
|
|
||||||
Tracker.OnChange(snapshot);
|
Tracker.OnChange(snapshot);
|
||||||
|
|
||||||
return results.FirstOrDefault(_result => _result.ClientPenalty == EFPenalty.PenaltyType.Ban) ??
|
return results;
|
||||||
results.FirstOrDefault(_result => _result.ClientPenalty == EFPenalty.PenaltyType.Flag) ??
|
|
||||||
new DetectionPenaltyResult()
|
|
||||||
{
|
|
||||||
ClientPenalty = EFPenalty.PenaltyType.Any,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -510,7 +510,6 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
|
|
||||||
if (Plugin.Config.Configuration().EnableAntiCheat && !attacker.IsBot && attacker.ClientId != victim.ClientId)
|
if (Plugin.Config.Configuration().EnableAntiCheat && !attacker.IsBot && attacker.ClientId != victim.ClientId)
|
||||||
{
|
{
|
||||||
DetectionPenaltyResult result = new DetectionPenaltyResult() { ClientPenalty = EFPenalty.PenaltyType.Any };
|
|
||||||
clientDetection.TrackedHits.Add(hit);
|
clientDetection.TrackedHits.Add(hit);
|
||||||
|
|
||||||
if (clientDetection.TrackedHits.Count >= MIN_HITS_TO_RUN_DETECTION)
|
if (clientDetection.TrackedHits.Count >= MIN_HITS_TO_RUN_DETECTION)
|
||||||
@ -525,9 +524,9 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
|
|
||||||
if (oldestHit.IsAlive)
|
if (oldestHit.IsAlive)
|
||||||
{
|
{
|
||||||
result = clientDetection.ProcessHit(oldestHit, isDamage);
|
var result = DeterminePenaltyResult(clientDetection.ProcessHit(oldestHit), attacker.CurrentServer.EndPoint);
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
await ApplyPenalty(result, attacker);
|
await ApplyPenalty(result, attacker);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (clientDetection.Tracker.HasChanges && result.ClientPenalty != EFPenalty.PenaltyType.Any)
|
if (clientDetection.Tracker.HasChanges && result.ClientPenalty != EFPenalty.PenaltyType.Any)
|
||||||
@ -564,6 +563,18 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DetectionPenaltyResult DeterminePenaltyResult(IEnumerable<DetectionPenaltyResult> results, long serverId)
|
||||||
|
{
|
||||||
|
// allow disabling of certain detection types
|
||||||
|
results = results.Where(_result => ShouldUseDetection(serverId, _result.Type));
|
||||||
|
return results.FirstOrDefault(_result => _result.ClientPenalty == EFPenalty.PenaltyType.Ban) ??
|
||||||
|
results.FirstOrDefault(_result => _result.ClientPenalty == EFPenalty.PenaltyType.Flag) ??
|
||||||
|
new DetectionPenaltyResult()
|
||||||
|
{
|
||||||
|
ClientPenalty = EFPenalty.PenaltyType.Any,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public async Task SaveHitCache(long serverId)
|
public async Task SaveHitCache(long serverId)
|
||||||
{
|
{
|
||||||
using (var ctx = new DatabaseContext(true))
|
using (var ctx = new DatabaseContext(true))
|
||||||
@ -594,12 +605,6 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
|
|
||||||
async Task ApplyPenalty(DetectionPenaltyResult penalty, EFClient attacker)
|
async Task ApplyPenalty(DetectionPenaltyResult penalty, EFClient attacker)
|
||||||
{
|
{
|
||||||
// allow disabling of certain detection types
|
|
||||||
if (!ShouldUseDetection(attacker.CurrentServer.EndPoint, penalty.Type))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var penaltyClient = Utilities.IW4MAdminClient(attacker.CurrentServer);
|
var penaltyClient = Utilities.IW4MAdminClient(attacker.CurrentServer);
|
||||||
switch (penalty.ClientPenalty)
|
switch (penalty.ClientPenalty)
|
||||||
{
|
{
|
||||||
|
@ -217,6 +217,10 @@ namespace SharedLibraryCore
|
|||||||
public EventRequiredEntity RequiredEntity { get; set; }
|
public EventRequiredEntity RequiredEntity { get; set; }
|
||||||
public string Data; // Data is usually the message sent by player
|
public string Data; // Data is usually the message sent by player
|
||||||
public string Message;
|
public string Message;
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies the game time offset as printed in the log
|
||||||
|
/// </summary>
|
||||||
|
public int? GameTime { get; set; }
|
||||||
public EFClient Origin;
|
public EFClient Origin;
|
||||||
public EFClient Target;
|
public EFClient Target;
|
||||||
public Server Owner;
|
public Server Owner;
|
||||||
|
@ -328,6 +328,7 @@ namespace SharedLibraryCore.Database.Models
|
|||||||
e.FailReason = GameEvent.EventFailReason.Permission;
|
e.FailReason = GameEvent.EventFailReason.Permission;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
State = ClientState.Disconnecting;
|
||||||
sender.CurrentServer.Manager.GetEventHandler().AddEvent(e);
|
sender.CurrentServer.Manager.GetEventHandler().AddEvent(e);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@ -563,7 +564,7 @@ namespace SharedLibraryCore.Database.Models
|
|||||||
CurrentServer.Logger.WriteDebug($"OnJoin finished for {this}");
|
CurrentServer.Logger.WriteDebug($"OnJoin finished for {this}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> CanConnect(int? ipAddress)
|
public async Task<bool> CanConnect(int? ipAddress)
|
||||||
{
|
{
|
||||||
var loc = Utilities.CurrentLocalization.LocalizationIndex;
|
var loc = Utilities.CurrentLocalization.LocalizationIndex;
|
||||||
var autoKickClient = Utilities.IW4MAdminClient(CurrentServer);
|
var autoKickClient = Utilities.IW4MAdminClient(CurrentServer);
|
||||||
|
@ -110,11 +110,14 @@ namespace SharedLibraryCore.Services
|
|||||||
.Include(a => a.Link)
|
.Include(a => a.Link)
|
||||||
// we only want alias that have the same IP address or share a link
|
// we only want alias that have the same IP address or share a link
|
||||||
.Where(_alias => _alias.IPAddress == ip || (_alias.LinkId == entity.AliasLinkId));
|
.Where(_alias => _alias.IPAddress == ip || (_alias.LinkId == entity.AliasLinkId));
|
||||||
|
|
||||||
var aliases = await iqAliases.ToListAsync();
|
var aliases = await iqAliases.ToListAsync();
|
||||||
|
var currentIPs = aliases.Where(_a2 => _a2.IPAddress != null).Select(_a2 => _a2.IPAddress).Distinct();
|
||||||
|
var floatingIPAliases = await context.Aliases.Where(_alias => currentIPs.Contains(_alias.IPAddress)).ToListAsync();
|
||||||
|
aliases.AddRange(floatingIPAliases);
|
||||||
|
|
||||||
// see if they have a matching IP + Name but new NetworkId
|
// see if they have a matching IP + Name but new NetworkId
|
||||||
var existingExactAlias = aliases.FirstOrDefault(a => a.Name == name && a.IPAddress == ip);
|
var existingExactAlias = aliases.OrderBy(_alias => _alias.LinkId).FirstOrDefault(a => a.Name == name && a.IPAddress == ip);
|
||||||
bool hasExactAliasMatch = existingExactAlias != null;
|
bool hasExactAliasMatch = existingExactAlias != null;
|
||||||
|
|
||||||
// if existing alias matches link them
|
// if existing alias matches link them
|
||||||
@ -128,17 +131,22 @@ namespace SharedLibraryCore.Services
|
|||||||
bool isAliasLinkUpdated = newAliasLink.AliasLinkId != entity.AliasLink.AliasLinkId;
|
bool isAliasLinkUpdated = newAliasLink.AliasLinkId != entity.AliasLink.AliasLinkId;
|
||||||
|
|
||||||
await context.SaveChangesAsync();
|
await context.SaveChangesAsync();
|
||||||
|
int distinctLinkCount = aliases.Select(_alias => _alias.LinkId).Distinct().Count();
|
||||||
// this happens when the link we found is different than the one we create before adding an IP
|
// this happens when the link we found is different than the one we create before adding an IP
|
||||||
if (isAliasLinkUpdated)
|
if (isAliasLinkUpdated || distinctLinkCount > 1)
|
||||||
{
|
{
|
||||||
entity.CurrentServer.Logger.WriteDebug($"[updatealias] found a link for {entity} so we are updating link from {entity.AliasLink.AliasLinkId} to {newAliasLink.AliasLinkId}");
|
entity.CurrentServer.Logger.WriteDebug($"[updatealias] found a link for {entity} so we are updating link from {entity.AliasLink.AliasLinkId} to {newAliasLink.AliasLinkId}");
|
||||||
|
|
||||||
var oldAliasLink = entity.AliasLink;
|
var completeAliasLinkIds = aliases.Select(_item => _item.LinkId)
|
||||||
|
.Append(entity.AliasLinkId)
|
||||||
|
.Distinct()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
entity.CurrentServer.Logger.WriteDebug($"[updatealias] updating aliasLinks {string.Join(',', completeAliasLinkIds)} for IP {ip} to {newAliasLink.AliasLinkId}");
|
||||||
|
|
||||||
// update all the clients that have the old alias link
|
// update all the clients that have the old alias link
|
||||||
await context.Clients
|
await context.Clients
|
||||||
.Where(_client => _client.AliasLinkId == oldAliasLink.AliasLinkId)
|
.Where(_client => completeAliasLinkIds.Contains(_client.AliasLinkId))
|
||||||
.ForEachAsync(_client => _client.AliasLinkId = newAliasLink.AliasLinkId);
|
.ForEachAsync(_client => _client.AliasLinkId = newAliasLink.AliasLinkId);
|
||||||
|
|
||||||
// we also need to update all the penalties or they get deleted
|
// we also need to update all the penalties or they get deleted
|
||||||
@ -151,7 +159,7 @@ namespace SharedLibraryCore.Services
|
|||||||
// link2 is deleted
|
// link2 is deleted
|
||||||
// link2 penalties are orphaned
|
// link2 penalties are orphaned
|
||||||
await context.Penalties
|
await context.Penalties
|
||||||
.Where(_penalty => _penalty.LinkId == oldAliasLink.AliasLinkId)
|
.Where(_penalty => completeAliasLinkIds.Contains(_penalty.LinkId))
|
||||||
.ForEachAsync(_penalty => _penalty.LinkId = newAliasLink.AliasLinkId);
|
.ForEachAsync(_penalty => _penalty.LinkId = newAliasLink.AliasLinkId);
|
||||||
|
|
||||||
entity.AliasLink = newAliasLink;
|
entity.AliasLink = newAliasLink;
|
||||||
@ -159,13 +167,16 @@ namespace SharedLibraryCore.Services
|
|||||||
|
|
||||||
// update all previous aliases
|
// update all previous aliases
|
||||||
await context.Aliases
|
await context.Aliases
|
||||||
.Where(_alias => _alias.LinkId == oldAliasLink.AliasLinkId)
|
.Where(_alias => completeAliasLinkIds.Contains(_alias.LinkId))
|
||||||
.ForEachAsync(_alias => _alias.LinkId = newAliasLink.AliasLinkId);
|
.ForEachAsync(_alias => _alias.LinkId = newAliasLink.AliasLinkId);
|
||||||
|
|
||||||
await context.SaveChangesAsync();
|
await context.SaveChangesAsync();
|
||||||
// we want to delete the now inactive alias
|
// we want to delete the now inactive alias
|
||||||
context.AliasLinks.Remove(oldAliasLink);
|
if (newAliasLink.AliasLinkId != entity.AliasLinkId)
|
||||||
await context.SaveChangesAsync();
|
{
|
||||||
|
context.AliasLinks.Remove(entity.AliasLink);
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// the existing alias matches ip and name, so we can just ignore the temporary one
|
// the existing alias matches ip and name, so we can just ignore the temporary one
|
||||||
|
Loading…
Reference in New Issue
Block a user