mirror of
https://github.com/RaidMax/IW4M-Admin.git
synced 2025-06-11 15:52:25 -05:00
more work on skill based team balance.
added on player disconnect to custom callbacks
This commit is contained in:
@ -37,7 +37,7 @@ namespace IW4MAdmin.Application.IO
|
||||
Server = server;
|
||||
}
|
||||
|
||||
public void PollForChanges()
|
||||
public async Task PollForChanges()
|
||||
{
|
||||
while (!Server.Manager.ShutdownRequested())
|
||||
{
|
||||
@ -45,7 +45,7 @@ namespace IW4MAdmin.Application.IO
|
||||
{
|
||||
try
|
||||
{
|
||||
UpdateLogEvents();
|
||||
await UpdateLogEvents();
|
||||
}
|
||||
|
||||
catch (Exception e)
|
||||
@ -59,7 +59,7 @@ namespace IW4MAdmin.Application.IO
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateLogEvents()
|
||||
private async Task UpdateLogEvents()
|
||||
{
|
||||
long fileSize = Reader.Length;
|
||||
|
||||
@ -74,7 +74,7 @@ namespace IW4MAdmin.Application.IO
|
||||
|
||||
PreviousFileSize = fileSize;
|
||||
|
||||
var events = Reader.ReadEventsFromLog(Server, fileDiff, 0);
|
||||
var events = await Reader.ReadEventsFromLog(Server, fileDiff, 0);
|
||||
|
||||
foreach (var ev in events)
|
||||
{
|
||||
|
@ -4,6 +4,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IW4MAdmin.Application.IO
|
||||
{
|
||||
@ -22,7 +23,7 @@ namespace IW4MAdmin.Application.IO
|
||||
Parser = parser;
|
||||
}
|
||||
|
||||
public ICollection<GameEvent> ReadEventsFromLog(Server server, long fileSizeDiff, long startPosition)
|
||||
public async Task<ICollection<GameEvent>> ReadEventsFromLog(Server server, long fileSizeDiff, long startPosition)
|
||||
{
|
||||
// allocate the bytes for the new log lines
|
||||
List<string> logLines = new List<string>();
|
||||
@ -30,6 +31,7 @@ namespace IW4MAdmin.Application.IO
|
||||
// open the file as a stream
|
||||
using (var rd = new StreamReader(new FileStream(LogFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), Utilities.EncodingType))
|
||||
{
|
||||
// todo: max async
|
||||
// take the old start position and go back the number of new characters
|
||||
rd.BaseStream.Seek(-fileSizeDiff, SeekOrigin.End);
|
||||
// the difference should be in the range of a int :P
|
||||
|
@ -5,6 +5,7 @@ using SharedLibraryCore.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using static SharedLibraryCore.Utilities;
|
||||
|
||||
namespace IW4MAdmin.Application.IO
|
||||
@ -29,18 +30,19 @@ namespace IW4MAdmin.Application.IO
|
||||
|
||||
public int UpdateInterval => 1000;
|
||||
|
||||
public ICollection<GameEvent> ReadEventsFromLog(Server server, long fileSizeDiff, long startPosition)
|
||||
public async Task<ICollection<GameEvent>> ReadEventsFromLog(Server server, long fileSizeDiff, long startPosition)
|
||||
{
|
||||
#if DEBUG == true
|
||||
server.Logger.WriteDebug($"Begin reading {fileSizeDiff} from http log");
|
||||
#endif
|
||||
var events = new List<GameEvent>();
|
||||
string b64Path = server.LogPath.ToBase64UrlSafeString();
|
||||
var response = Api.Log(b64Path).Result;
|
||||
var response = await Api.Log(b64Path);
|
||||
|
||||
if (!response.Success)
|
||||
{
|
||||
server.Logger.WriteError($"Could not get log server info of {LogFile}/{b64Path} ({server.LogPath})");
|
||||
return events;
|
||||
}
|
||||
|
||||
// parse each line
|
||||
|
@ -151,7 +151,9 @@ namespace IW4MAdmin.Application
|
||||
{
|
||||
Logger.WriteWarning($"Delayed event for {e.Origin} was ignored because the target has left");
|
||||
// hack: don't do anything with the event because the target is invalid
|
||||
e.Origin = null;
|
||||
e.Type = GameEvent.EventType.Unknown;
|
||||
|
||||
}
|
||||
}
|
||||
Logger.WriteDebug($"Adding delayed event of type {e.Type} for {e.Origin} back for processing");
|
||||
@ -265,11 +267,7 @@ namespace IW4MAdmin.Application
|
||||
ThreadPool.GetAvailableThreads(out int availableThreads, out int m);
|
||||
Logger.WriteDebug($"There are {workerThreads - availableThreads} active threading tasks");
|
||||
#endif
|
||||
#if DEBUG
|
||||
await Task.Delay(10000);
|
||||
#else
|
||||
await Task.Delay(ConfigHandler.Configuration().RConPollRate);
|
||||
#endif
|
||||
}
|
||||
|
||||
// trigger the event processing loop to end
|
||||
|
@ -26,6 +26,7 @@ namespace IW4MAdmin
|
||||
{
|
||||
private static readonly Index loc = Utilities.CurrentLocalization.LocalizationIndex;
|
||||
private GameLogEventDetection LogEvent;
|
||||
public int Id { get; private set; }
|
||||
|
||||
public IW4MServer(IManager mgr, ServerConfiguration cfg) : base(mgr, cfg)
|
||||
{
|
||||
@ -33,30 +34,28 @@ namespace IW4MAdmin
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
if (GameName == Game.IW4)
|
||||
if ($"{IP}:{Port.ToString()}" == "66.150.121.184:28965")
|
||||
{
|
||||
// todo: make this better with collisions
|
||||
int id = Math.Abs($"{IP}:{Port.ToString()}".Select(a => (int)a).Sum());
|
||||
|
||||
// hack: this is a nasty fix for get hashcode being changed
|
||||
switch (id)
|
||||
{
|
||||
case 765:
|
||||
return 886229536;
|
||||
case 760:
|
||||
return 1645744423;
|
||||
case 761:
|
||||
return 1645809959;
|
||||
}
|
||||
|
||||
return id;
|
||||
return 886229536;
|
||||
}
|
||||
|
||||
else
|
||||
if ($"{IP}:{Port.ToString()}" == "66.150.121.184:28960")
|
||||
{
|
||||
int id = HashCode.Combine(IP, Port);
|
||||
return id < 0 ? Math.Abs(id) : id;
|
||||
return 1645744423;
|
||||
}
|
||||
|
||||
if ($"{IP}:{Port.ToString()}" == "66.150.121.184:28970")
|
||||
{
|
||||
return 1645809959;
|
||||
}
|
||||
|
||||
if (Id == 0)
|
||||
{
|
||||
Id = HashCode.Combine(IP, Port);
|
||||
Id = Id < 0 ? Math.Abs(Id) : Id;
|
||||
}
|
||||
|
||||
return Id;
|
||||
}
|
||||
|
||||
public async Task OnPlayerJoined(Player logClient)
|
||||
@ -560,11 +559,13 @@ namespace IW4MAdmin
|
||||
|
||||
if (E.Type == GameEvent.EventType.Broadcast)
|
||||
{
|
||||
#if DEBUG == false
|
||||
// this is a little ugly but I don't want to change the abstract class
|
||||
if (E.Data != null)
|
||||
{
|
||||
await E.Owner.ExecuteCommandAsync(E.Data);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
while (ChatHistory.Count > Math.Ceiling((double)ClientNum / 2))
|
||||
@ -661,7 +662,7 @@ namespace IW4MAdmin
|
||||
waiterList.Add(e);
|
||||
}
|
||||
// wait for all the disconnect tasks to finish
|
||||
await Task.WhenAll(waiterList.Select(e => e.WaitAsync()));
|
||||
await Task.WhenAll(waiterList.Select(e => e.WaitAsync(10 * 1000)));
|
||||
|
||||
waiterList.Clear();
|
||||
// this are our new connecting clients
|
||||
@ -686,7 +687,7 @@ namespace IW4MAdmin
|
||||
}
|
||||
|
||||
// wait for all the connect tasks to finish
|
||||
await Task.WhenAll(waiterList.Select(e => e.WaitAsync()));
|
||||
await Task.WhenAll(waiterList.Select(e => e.WaitAsync(10 * 1000)));
|
||||
|
||||
if (ConnectionErrors > 0)
|
||||
{
|
||||
@ -700,7 +701,7 @@ namespace IW4MAdmin
|
||||
catch (NetworkException e)
|
||||
{
|
||||
ConnectionErrors++;
|
||||
if (ConnectionErrors == 1)
|
||||
if (ConnectionErrors == 3)
|
||||
{
|
||||
Logger.WriteError($"{e.Message} {IP}:{Port}, {loc["SERVER_ERROR_POLLING"]}");
|
||||
Logger.WriteDebug($"Internal Exception: {e.Data["internal_exception"]}");
|
||||
|
31
Application/SharedGUIDKick.js
Normal file
31
Application/SharedGUIDKick.js
Normal file
@ -0,0 +1,31 @@
|
||||
var plugin = {
|
||||
author: 'RaidMax',
|
||||
version: 1.1,
|
||||
name: 'Shared GUID Kicker Plugin',
|
||||
|
||||
onEventAsync: function (gameEvent, server) {
|
||||
// make sure we only check for IW4(x)
|
||||
if (server.GameName !== 2) {
|
||||
return false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
// connect or join event
|
||||
if (gameEvent.Type === 3) {
|
||||
// this GUID seems to have been packed in a IW4 torrent and results in an unreasonable amount of people using the same GUID
|
||||
if (gameEvent.Origin.NetworkId === -805366929435212061) {
|
||||
gameEvent.Origin.Kick('Your GUID is generic. Delete players/guids.dat and rejoin', _IW4MAdminClient);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onLoadAsync: function (manager) {
|
||||
},
|
||||
|
||||
onUnloadAsync: function () {
|
||||
},
|
||||
|
||||
onTickAsync: function (server) {
|
||||
}
|
||||
};
|
62
Application/VPNDetection.js
Normal file
62
Application/VPNDetection.js
Normal file
@ -0,0 +1,62 @@
|
||||
var plugin = {
|
||||
author: 'RaidMax',
|
||||
version: 1.0,
|
||||
name: 'VPN Detection Plugin',
|
||||
|
||||
manager: null,
|
||||
logger: null,
|
||||
vpnExceptionIds: [],
|
||||
|
||||
checkForVpn: function (origin) {
|
||||
var exempt = false;
|
||||
// prevent players that are exempt from being kicked
|
||||
this.vpnExceptionIds.forEach(function (id) {
|
||||
if (id === origin.ClientId) {
|
||||
exempt = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if (exempt) {
|
||||
return;
|
||||
}
|
||||
|
||||
var usingVPN = false;
|
||||
|
||||
try {
|
||||
var cl = new System.Net.Http.HttpClient();
|
||||
var re = cl.GetAsync('https://api.xdefcon.com/proxy/check/?ip=' + origin.IPAddressString).Result;
|
||||
var co = re.Content;
|
||||
var parsedJSON = JSON.parse(co.ReadAsStringAsync().Result);
|
||||
co.Dispose();
|
||||
re.Dispose();
|
||||
cl.Dispose();
|
||||
usingVPN = parsedJSON.success && parsedJSON.proxy;
|
||||
} catch (e) {
|
||||
this.logger.WriteError(e.message);
|
||||
}
|
||||
|
||||
if (usingVPN) {
|
||||
this.logger.WriteInfo(origin + ' is using a VPN (' + origin.IPAddressString + ')');
|
||||
origin.Kick(_localization.LocalizationIndex["SERVER_KICK_VPNS_NOTALLOWED"], _IW4MAdminClient);
|
||||
}
|
||||
},
|
||||
|
||||
onEventAsync: function (gameEvent, server) {
|
||||
// connect event
|
||||
if (gameEvent.Type === 3) {
|
||||
this.checkForVpn(gameEvent.Origin);
|
||||
}
|
||||
},
|
||||
|
||||
onLoadAsync: function (manager) {
|
||||
this.manager = manager;
|
||||
this.logger = manager.GetLogger(0);
|
||||
},
|
||||
|
||||
onUnloadAsync: function () {
|
||||
},
|
||||
|
||||
onTickAsync: function (server) {
|
||||
}
|
||||
};
|
Reference in New Issue
Block a user