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

Merge branch 'develop' into release/pre

This commit is contained in:
RaidMax 2024-02-04 20:56:12 -06:00
commit 3d54126911
26 changed files with 194 additions and 46 deletions

View File

@ -53,6 +53,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Integrations\Cod\Integrations.Cod.csproj" /> <ProjectReference Include="..\Integrations\Cod\Integrations.Cod.csproj" />
<ProjectReference Include="..\Integrations\Source\Integrations.Source.csproj" /> <ProjectReference Include="..\Integrations\Source\Integrations.Source.csproj" />
<ProjectReference Include="..\Data\Data.csproj" />
<ProjectReference Include="..\SharedLibraryCore\SharedLibraryCore.csproj"> <ProjectReference Include="..\SharedLibraryCore\SharedLibraryCore.csproj">
<Private>true</Private> <Private>true</Private>
</ProjectReference> </ProjectReference>

View File

@ -0,0 +1,31 @@
using System.Threading.Tasks;
using Data.Models.Client;
using SharedLibraryCore;
using SharedLibraryCore.Configuration;
using SharedLibraryCore.Interfaces;
namespace IW4MAdmin.Application.Commands;
public class ClearAllReportsCommand : Command
{
public ClearAllReportsCommand(CommandConfiguration config, ITranslationLookup layout) : base(config, layout)
{
Name = "clearallreports";
Description = _translationLookup["COMMANDS_REPORTS_CLEAR_DESC"];
Alias = "car";
Permission = EFClient.Permission.Administrator;
RequiresTarget = false;
}
public override Task ExecuteAsync(GameEvent gameEvent)
{
foreach (var server in gameEvent.Owner.Manager.GetServers())
{
server.Reports.Clear();
}
gameEvent.Origin.Tell(_translationLookup["COMMANDS_REPORTS_CLEAR_SUCCESS"]);
return Task.CompletedTask;
}
}

View File

@ -94,6 +94,15 @@ namespace IW4MAdmin.Application
Console.WriteLine($" Version {Utilities.GetVersionAsString()}"); Console.WriteLine($" Version {Utilities.GetVersionAsString()}");
Console.WriteLine("====================================================="); Console.WriteLine("=====================================================");
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("!!!! IMPORTANT !!!!");
Console.WriteLine("The next update of IW4MAdmin will require .NET 8.");
Console.WriteLine("This is a breaking change!");
Console.WriteLine(
"Please update the ASP.NET Core Runtime: https://dotnet.microsoft.com/en-us/download/dotnet/8.0");
Console.WriteLine("!!!!!!!!!!!!!!!!!!!");
Console.ForegroundColor = ConsoleColor.Gray;
await LaunchAsync(); await LaunchAsync();
} }

View File

@ -4,11 +4,8 @@
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<Configurations>Debug;Release;Prerelease</Configurations> <Configurations>Debug;Release;Prerelease</Configurations>
<Platforms>AnyCPU</Platforms> <Platforms>AnyCPU</Platforms>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageId>RaidMax.IW4MAdmin.Data</PackageId>
<Title>RaidMax.IW4MAdmin.Data</Title> <Title>RaidMax.IW4MAdmin.Data</Title>
<Authors /> <Version>1.0.0.0</Version>
<PackageVersion>1.2.0</PackageVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -1,4 +1,4 @@
name: '$(Date:yyyy.MM.dd)$(Rev:.r)' name: '$(Date:yyyy.M.d)$(Rev:.r)'
trigger: trigger:
batch: true batch: true
@ -7,6 +7,10 @@ trigger:
- release/pre - release/pre
- master - master
- develop - develop
paths:
exclude:
- '**/*.yml'
- '*.yml'
pr: none pr: none
@ -66,7 +70,7 @@ jobs:
displayName: 'Build projects' displayName: 'Build projects'
inputs: inputs:
solution: '$(solution)' solution: '$(solution)'
msbuildArgs: '/p:DeployOnBuild=false /p:PackageAsSingleFile=false /p:SkipInvalidConfigurations=true /p:PackageLocation="$(build.artifactStagingDirectory)" /p:Version=$(Build.BuildNumber)' msbuildArgs: '/p:DeployOnBuild=false /p:PackageAsSingleFile=false /p:SkipInvalidConfigurations=true /p:PackageLocation="$(build.artifactStagingDirectory)" /p:Version=$(Build.BuildNumber) /p:PackageVersion=$(Build.BuildNumber)'
platform: '$(buildPlatform)' platform: '$(buildPlatform)'
configuration: '$(buildConfiguration)' configuration: '$(buildConfiguration)'
@ -181,6 +185,13 @@ jobs:
artifact: 'IW4MAdmin.$(buildConfiguration)' artifact: 'IW4MAdmin.$(buildConfiguration)'
publishLocation: 'pipeline' publishLocation: 'pipeline'
- task: PublishPipelineArtifact@1
displayName: 'Publish nuget package artifact'
inputs:
targetPath: '$(Build.Repository.LocalPath)/SharedLibraryCore/bin/$(buildConfiguration)/RaidMax.IW4MAdmin.SharedLibraryCore.$(Build.BuildNumber).nupkg'
artifact: 'SharedLibraryCore.$(Build.BuildNumber).nupkg'
publishLocation: 'pipeline'
- task: FtpUpload@2 - task: FtpUpload@2
condition: ne(variables['Build.SourceBranch'], 'refs/heads/develop') condition: ne(variables['Build.SourceBranch'], 'refs/heads/develop')
displayName: 'Upload zip file to website' displayName: 'Upload zip file to website'

View File

@ -0,0 +1,55 @@
name: '$(Date:yyyy.M.d)$(Rev:.r)'
pr: none
pool:
vmImage: 'windows-2022'
variables:
buildPlatform: 'Any CPU'
outputFolder: '$(Build.ArtifactStagingDirectory)\Publish\$(buildConfiguration)'
releaseType: verified
buildConfiguration: Stable
isPreRelease: false
jobs:
- job: Build_Pack
steps:
- task: PowerShell@2
displayName: 'Setup Build configuration'
condition: or(eq(variables['Build.SourceBranch'], 'refs/heads/release/pre'), eq(variables['Build.SourceBranch'], 'refs/heads/develop'), eq(variables['Build.SourceBranch'], 'refs/heads/chore/nuget-pipeline'))
inputs:
targetType: 'inline'
script: |
echo '##vso[task.setvariable variable=releaseType]prerelease'
echo '##vso[task.setvariable variable=buildConfiguration]Prerelease'
echo '##vso[task.setvariable variable=isPreRelease]true'
failOnStderr: true
- task: DotNetCoreCLI@2
displayName: 'Build Data'
inputs:
command: 'build'
projects: '**/Data.csproj'
arguments: '-c $(buildConfiguration)'
- task: DotNetCoreCLI@2
displayName: 'Build SLC'
inputs:
command: 'build'
projects: '**/SharedLibraryCore.csproj'
arguments: '-c $(buildConfiguration) /p:Version=$(Build.BuildNumber)'
- task: DotNetCoreCLI@2
displayName: 'Pack SLC'
inputs:
command: 'pack'
packagesToPack: '**/SharedLibraryCore.csproj'
versioningScheme: 'byBuildNumber'
- task: PublishPipelineArtifact@1
displayName: 'Publish nuget package artifact'
inputs:
targetPath: 'D:\a\1\a\RaidMax.IW4MAdmin.SharedLibraryCore.$(Build.BuildNumber).nupkg'
artifact: 'SharedLibraryCore.$(Build.BuildNumber).nupkg'
publishLocation: 'pipeline'

View File

@ -137,6 +137,8 @@ waitForFrameThread()
waitForAdditionalAngles( logString, beforeFrameCount, afterFrameCount ) waitForAdditionalAngles( logString, beforeFrameCount, afterFrameCount )
{ {
self endon( "disconnect" );
currentIndex = self.currentAnglePosition; currentIndex = self.currentAnglePosition;
wait( 0.05 * afterFrameCount ); wait( 0.05 * afterFrameCount );

View File

@ -143,6 +143,8 @@ waitForFrameThread()
waitForAdditionalAngles( logString, beforeFrameCount, afterFrameCount ) waitForAdditionalAngles( logString, beforeFrameCount, afterFrameCount )
{ {
self endon( "disconnect" );
currentIndex = self.currentAnglePosition; currentIndex = self.currentAnglePosition;
wait( 0.05 * afterFrameCount ); wait( 0.05 * afterFrameCount );

View File

@ -193,7 +193,7 @@ NoClipImpl()
self God(); self God();
self Noclip(); self Noclip();
self Hide(); self Show();
SetDvar( "sv_cheats", 0 ); SetDvar( "sv_cheats", 0 );

View File

@ -12,6 +12,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
version.txt = version.txt version.txt = version.txt
DeploymentFiles\UpdateIW4MAdmin.ps1 = DeploymentFiles\UpdateIW4MAdmin.ps1 DeploymentFiles\UpdateIW4MAdmin.ps1 = DeploymentFiles\UpdateIW4MAdmin.ps1
DeploymentFiles\UpdateIW4MAdmin.sh = DeploymentFiles\UpdateIW4MAdmin.sh DeploymentFiles\UpdateIW4MAdmin.sh = DeploymentFiles\UpdateIW4MAdmin.sh
DeploymentFiles\nuget-pipeline.yml = DeploymentFiles\nuget-pipeline.yml
EndProjectSection EndProjectSection
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharedLibraryCore", "SharedLibraryCore\SharedLibraryCore.csproj", "{AA0541A2-8D51-4AD9-B0AC-3D1F5B162481}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharedLibraryCore", "SharedLibraryCore\SharedLibraryCore.csproj", "{AA0541A2-8D51-4AD9-B0AC-3D1F5B162481}"

View File

@ -10,7 +10,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.SyndicationFeed.ReaderWriter" Version="1.0.2" /> <PackageReference Include="Microsoft.SyndicationFeed.ReaderWriter" Version="1.0.2" />
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2023.4.5.1" PrivateAssets="All" /> <PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2024.2.5.3" PrivateAssets="All" />
</ItemGroup> </ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent"> <Target Name="PostBuild" AfterTargets="PostBuildEvent">

View File

@ -16,7 +16,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2023.4.5.1" PrivateAssets="All" /> <PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2024.2.5.3" PrivateAssets="All" />
</ItemGroup> </ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent"> <Target Name="PostBuild" AfterTargets="PostBuildEvent">

View File

@ -19,7 +19,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2023.4.5.1" PrivateAssets="All" /> <PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2024.2.5.3" PrivateAssets="All" />
</ItemGroup> </ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent"> <Target Name="PostBuild" AfterTargets="PostBuildEvent">

View File

@ -8,10 +8,11 @@
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<Configurations>Debug;Release;Prerelease</Configurations> <Configurations>Debug;Release;Prerelease</Configurations>
<Platforms>AnyCPU</Platforms> <Platforms>AnyCPU</Platforms>
<RootNamespace>IW4MAdmin.Plugins.Mute</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2023.4.5.1" PrivateAssets="All" /> <PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2024.2.5.3" PrivateAssets="All" />
</ItemGroup> </ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent"> <Target Name="PostBuild" AfterTargets="PostBuildEvent">

View File

@ -131,8 +131,11 @@ public class MuteManager
{ {
var newPenalty = new EFPenalty var newPenalty = new EFPenalty
{ {
Type = muteState is MuteState.Unmuted ? EFPenalty.PenaltyType.Unmute : Type = muteState is MuteState.Unmuted
dateTime is null ? EFPenalty.PenaltyType.Mute : EFPenalty.PenaltyType.TempMute, ? EFPenalty.PenaltyType.Unmute
: dateTime is null
? EFPenalty.PenaltyType.Mute
: EFPenalty.PenaltyType.TempMute,
Expires = muteState is MuteState.Unmuted ? DateTime.UtcNow : dateTime, Expires = muteState is MuteState.Unmuted ? DateTime.UtcNow : dateTime,
Offender = target, Offender = target,
Offense = reason, Offense = reason,
@ -148,10 +151,9 @@ public class MuteManager
{ {
await using var context = _databaseContextFactory.CreateContext(); await using var context = _databaseContextFactory.CreateContext();
var mutePenalties = await context.Penalties var mutePenalties = await context.Penalties
.Where(penalty => penalty.OffenderId == client.ClientId && .Where(penalty => penalty.OffenderId == client.ClientId)
(penalty.Type == EFPenalty.PenaltyType.Mute || .Where(penalty => penalty.Type == EFPenalty.PenaltyType.Mute || penalty.Type == EFPenalty.PenaltyType.TempMute)
penalty.Type == EFPenalty.PenaltyType.TempMute) && .Where(penalty => penalty.Expires == null || penalty.Expires > DateTime.UtcNow)
(penalty.Expires == null || penalty.Expires > DateTime.UtcNow))
.ToListAsync(); .ToListAsync();
foreach (var mutePenalty in mutePenalties) foreach (var mutePenalty in mutePenalties)
@ -169,19 +171,20 @@ public class MuteManager
switch (muteStateMeta.MuteState) switch (muteStateMeta.MuteState)
{ {
case MuteState.Muted: case MuteState.Muted:
await server.ExecuteCommandAsync($"muteClient {client.ClientNumber}"); var muteCommand = string.Format(server.RconParser.Configuration.CommandPrefixes.Mute, client.ClientNumber);
await server.ExecuteCommandAsync(muteCommand);
muteStateMeta.CommandExecuted = true; muteStateMeta.CommandExecuted = true;
break; break;
case MuteState.Unmuted: case MuteState.Unmuted:
await server.ExecuteCommandAsync($"unmute {client.ClientNumber}"); var unMuteCommand = string.Format(server.RconParser.Configuration.CommandPrefixes.Unmute, client.ClientNumber);
await server.ExecuteCommandAsync(unMuteCommand);
muteStateMeta.CommandExecuted = true; muteStateMeta.CommandExecuted = true;
break; break;
} }
} }
private async Task<MuteState?> ReadPersistentDataV1(EFClient client) => TryParse<MuteState>( private async Task<MuteState?> ReadPersistentDataV1(EFClient client) => TryParse<MuteState>(
(await _metaService.GetPersistentMeta(Plugin.MuteKey, client.ClientId))?.Value, (await _metaService.GetPersistentMeta(Plugin.MuteKey, client.ClientId))?.Value, out var muteState)
out var muteState)
? muteState ? muteState
: null; : null;

View File

@ -21,7 +21,7 @@ public class Plugin : IPluginV2
public const string MuteKey = "IW4MMute"; public const string MuteKey = "IW4MMute";
public static IManager Manager { get; private set; } = null!; public static IManager Manager { get; private set; } = null!;
public static readonly Server.Game[] SupportedGames = {Server.Game.IW4}; public static Server.Game[] SupportedGames { get; private set; } = Array.Empty<Server.Game>();
private static readonly string[] DisabledCommands = {nameof(PrivateMessageAdminsCommand), "PrivateMessageCommand"}; private static readonly string[] DisabledCommands = {nameof(PrivateMessageAdminsCommand), "PrivateMessageCommand"};
private readonly IInteractionRegistration _interactionRegistration; private readonly IInteractionRegistration _interactionRegistration;
private readonly IRemoteCommandService _remoteCommandService; private readonly IRemoteCommandService _remoteCommandService;
@ -37,9 +37,11 @@ public class Plugin : IPluginV2
IManagementEventSubscriptions.Load += OnLoad; IManagementEventSubscriptions.Load += OnLoad;
IManagementEventSubscriptions.Unload += OnUnload; IManagementEventSubscriptions.Unload += OnUnload;
IManagementEventSubscriptions.ClientStateInitialized += OnClientStateInitialized; IManagementEventSubscriptions.ClientStateInitialized += OnClientStateInitialized;
IGameServerEventSubscriptions.ClientDataUpdated += OnClientDataUpdated; IGameServerEventSubscriptions.ClientDataUpdated += OnClientDataUpdated;
IGameServerEventSubscriptions.MonitoringStarted += OnServerMonitoredStarted;
IGameEventSubscriptions.ClientMessaged += OnClientMessaged; IGameEventSubscriptions.ClientMessaged += OnClientMessaged;
} }
@ -157,16 +159,16 @@ public class Plugin : IPluginV2
switch (muteMetaJoin) switch (muteMetaJoin)
{ {
case { MuteState: MuteState.Muted }: case {MuteState: MuteState.Muted}:
// Let the client know when their mute expires. // Let the client know when their mute expires.
state.Client.Tell(Utilities.CurrentLocalization state.Client.Tell(Utilities.CurrentLocalization
.LocalizationIndex["PLUGINS_MUTE_REMAINING_TIME"].FormatExt( .LocalizationIndex["PLUGINS_MUTE_REMAINING_TIME"].FormatExt(
muteMetaJoin is { Expiration: not null } muteMetaJoin is {Expiration: not null}
? muteMetaJoin.Expiration.Value.HumanizeForCurrentCulture() ? muteMetaJoin.Expiration.Value.HumanizeForCurrentCulture()
: Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_MUTE_NEVER"], : Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_MUTE_NEVER"],
muteMetaJoin.Reason)); muteMetaJoin.Reason));
break; break;
case { MuteState: MuteState.Unmuting }: case {MuteState: MuteState.Unmuting}:
// Handle unmute of unmuted players. // Handle unmute of unmuted players.
await _muteManager.Unmute(state.Client.CurrentServer, Utilities.IW4MAdminClient(), state.Client, await _muteManager.Unmute(state.Client.CurrentServer, Utilities.IW4MAdminClient(), state.Client,
muteMetaJoin.Reason ?? string.Empty); muteMetaJoin.Reason ?? string.Empty);
@ -319,4 +321,29 @@ public class Plugin : IPluginV2
} }
}; };
} }
private Task OnServerMonitoredStarted(MonitorStartEvent serverEvent, CancellationToken token)
{
var game = (Server.Game)serverEvent.Server.GameCode;
lock (SupportedGames)
{
if (SupportedGames.Contains(game))
{
return Task.CompletedTask;
}
var server = Manager.GetServers().FirstOrDefault(x => x == serverEvent.Server);
var commandIsEmpty = string.IsNullOrWhiteSpace(server?.RconParser.Configuration.CommandPrefixes.Mute);
if (commandIsEmpty)
{
return Task.CompletedTask;
}
SupportedGames = SupportedGames.Append(game).ToArray();
}
return Task.CompletedTask;
}
} }

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>Library</OutputType> <OutputType.>Library</OutputType.>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<ApplicationIcon /> <ApplicationIcon />
<StartupObject /> <StartupObject />
@ -16,7 +16,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2023.4.5.1" PrivateAssets="All" /> <PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2024.2.5.3" PrivateAssets="All" />
</ItemGroup> </ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent"> <Target Name="PostBuild" AfterTargets="PostBuildEvent">

View File

@ -19,6 +19,8 @@ var plugin = {
rconParser.Configuration.CommandPrefixes.Kick = 'clientkick {0} "{1}"'; rconParser.Configuration.CommandPrefixes.Kick = 'clientkick {0} "{1}"';
rconParser.Configuration.CommandPrefixes.Ban = 'clientkick {0} "{1}"'; rconParser.Configuration.CommandPrefixes.Ban = 'clientkick {0} "{1}"';
rconParser.Configuration.CommandPrefixes.TempBan = 'tempbanclient {0} "{1}"'; rconParser.Configuration.CommandPrefixes.TempBan = 'tempbanclient {0} "{1}"';
rconParser.Configuration.CommandPrefixes.Mute = 'muteClient {0}';
rconParser.Configuration.CommandPrefixes.Unmute = 'unmute {0}';
rconParser.Configuration.DefaultRConPort = 28960; rconParser.Configuration.DefaultRConPort = 28960;
rconParser.Configuration.DefaultInstallationDirectoryHint = 'HKEY_CURRENT_USER\\Software\\Classes\\iw4x\\shell\\open\\command'; rconParser.Configuration.DefaultInstallationDirectoryHint = 'HKEY_CURRENT_USER\\Software\\Classes\\iw4x\\shell\\open\\command';

View File

@ -20,6 +20,8 @@ var plugin = {
rconParser.Configuration.CommandPrefixes.Ban = 'clientkick {0} "{1}"'; rconParser.Configuration.CommandPrefixes.Ban = 'clientkick {0} "{1}"';
rconParser.Configuration.CommandPrefixes.TempBan = 'clientkick {0} "{1}"'; rconParser.Configuration.CommandPrefixes.TempBan = 'clientkick {0} "{1}"';
rconParser.Configuration.CommandPrefixes.RConResponse = '\xff\xff\xff\xffprint\n'; rconParser.Configuration.CommandPrefixes.RConResponse = '\xff\xff\xff\xffprint\n';
rconParser.Configuration.CommandPrefixes.Mute = 'muteClient {0}';
rconParser.Configuration.CommandPrefixes.Unmute = 'unmuteClient {0}';
rconParser.Configuration.Dvar.Pattern = '^ *\\"(.+)\\" is: \\"(.+)?\\" default: \\"(.+)?\\"\\n?(?:latched: \\"(.+)?\\"\\n?)?(.*)$'; rconParser.Configuration.Dvar.Pattern = '^ *\\"(.+)\\" is: \\"(.+)?\\" default: \\"(.+)?\\"\\n?(?:latched: \\"(.+)?\\"\\n?)?(.*)$';
rconParser.Configuration.Status.Pattern = '^ *([0-9]+) +-?([0-9]+) +(Yes|No) +((?:[A-Z]+|[0-9]+)) +((?:[a-z]|[0-9]){8,32}|(?:[a-z]|[0-9]){8,32}|bot[0-9]+|(?:[0-9]+)) *(.{0,32}) +(\\d+\\.\\d+\\.\\d+.\\d+\\:-*\\d{1,5}|0+.0+:-*\\d{1,5}|loopback|unknown|bot) +(-*[0-9]+) *$'; rconParser.Configuration.Status.Pattern = '^ *([0-9]+) +-?([0-9]+) +(Yes|No) +((?:[A-Z]+|[0-9]+)) +((?:[a-z]|[0-9]){8,32}|(?:[a-z]|[0-9]){8,32}|bot[0-9]+|(?:[0-9]+)) *(.{0,32}) +(\\d+\\.\\d+\\.\\d+.\\d+\\:-*\\d{1,5}|0+.0+:-*\\d{1,5}|loopback|unknown|bot) +(-*[0-9]+) *$';
rconParser.Configuration.StatusHeader.Pattern = 'num +score +bot +ping +guid +name +address +qport *'; rconParser.Configuration.StatusHeader.Pattern = 'num +score +bot +ping +guid +name +address +qport *';

View File

@ -13,6 +13,7 @@ var plugin = {
onLoadAsync: function (manager) { onLoadAsync: function (manager) {
rconParser = manager.GenerateDynamicRConParser(this.name); rconParser = manager.GenerateDynamicRConParser(this.name);
eventParser = manager.GenerateDynamicEventParser(this.name); eventParser = manager.GenerateDynamicEventParser(this.name);
eventParser.Configuration.GameDirectory = '';
rconParser.Configuration.DefaultInstallationDirectoryHint = '{LocalAppData}/Plutonium/storage/t5'; rconParser.Configuration.DefaultInstallationDirectoryHint = '{LocalAppData}/Plutonium/storage/t5';
rconParser.Configuration.CommandPrefixes.RConResponse = '\xff\xff\xff\xffprint\n'; rconParser.Configuration.CommandPrefixes.RConResponse = '\xff\xff\xff\xffprint\n';
@ -21,6 +22,7 @@ var plugin = {
rconParser.Configuration.CommandPrefixes.RConGetInfo = undefined; rconParser.Configuration.CommandPrefixes.RConGetInfo = undefined;
rconParser.Configuration.GuidNumberStyle = 7; // Integer rconParser.Configuration.GuidNumberStyle = 7; // Integer
rconParser.Configuration.DefaultRConPort = 3074; rconParser.Configuration.DefaultRConPort = 3074;
rconParser.Configuration.OverrideDvarNameMapping.Add('fs_homepath', 'fs_basegame');
rconParser.Configuration.CanGenerateLogPath = false; rconParser.Configuration.CanGenerateLogPath = false;
rconParser.Configuration.OverrideCommandTimeouts.Clear(); rconParser.Configuration.OverrideCommandTimeouts.Clear();

View File

@ -1,5 +1,4 @@
using IW4MAdmin.Plugins.Stats.Cheat; using IW4MAdmin.Plugins.Stats.Cheat;
using IW4MAdmin.Plugins.Stats.Config;
using IW4MAdmin.Plugins.Stats.Web.Dtos; using IW4MAdmin.Plugins.Stats.Web.Dtos;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using SharedLibraryCore; using SharedLibraryCore;
@ -8,6 +7,7 @@ using SharedLibraryCore.Interfaces;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data.Common;
using System.Linq; using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Threading; using System.Threading;
@ -21,8 +21,6 @@ using Data.Models.Server;
using Humanizer.Localisation; using Humanizer.Localisation;
using Microsoft.Data.Sqlite; using Microsoft.Data.Sqlite;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using MySqlConnector;
using Npgsql;
using Stats.Client.Abstractions; using Stats.Client.Abstractions;
using Stats.Config; using Stats.Config;
using Stats.Helpers; using Stats.Helpers;
@ -488,9 +486,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
} }
catch (DbUpdateException updateException) when ( catch (DbUpdateException updateException) when (
updateException.InnerException is PostgresException { SqlState: "23503" } updateException.InnerException is DbException { SqlState: "23503" } or SqliteException { SqliteErrorCode: 787 })
|| updateException.InnerException is SqliteException { SqliteErrorCode: 787 }
|| updateException.InnerException is MySqlException { SqlState: "23503" })
{ {
_log.LogWarning("Trying to add {Client} to stats before they have been added to the database", _log.LogWarning("Trying to add {Client} to stats before they have been added to the database",
pl.ToString()); pl.ToString());

View File

@ -17,7 +17,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2023.4.5.1" PrivateAssets="All" /> <PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2024.2.5.3" PrivateAssets="All" />
</ItemGroup> </ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent"> <Target Name="PostBuild" AfterTargets="PostBuildEvent">

View File

@ -20,7 +20,7 @@
</Target> </Target>
<ItemGroup> <ItemGroup>
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2023.4.5.1" PrivateAssets="All" /> <PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2024.2.5.3" PrivateAssets="All" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -16,5 +16,7 @@
public string RConGetInfo { get; set; } public string RConGetInfo { get; set; }
public string RConResponse { get; set; } public string RConResponse { get; set; }
public string RconGetInfoResponseHeader { get; set; } public string RconGetInfoResponseHeader { get; set; }
public string Mute { get; set; }
public string Unmute { get; set; }
} }
} }

View File

@ -54,8 +54,11 @@
<PackageReference Include="SimpleCrypto.NetCore" Version="1.0.0" /> <PackageReference Include="SimpleCrypto.NetCore" Version="1.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Data\Data.csproj" /> <ProjectReference Include="..\Data\Data.csproj">
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<IncludeAssets>Data.dll</IncludeAssets>
</ProjectReference>
</ItemGroup> </ItemGroup>
<Target Name="PreBuild" BeforeTargets="PreBuildEvent"> <Target Name="PreBuild" BeforeTargets="PreBuildEvent">
@ -65,7 +68,7 @@
<PropertyGroup> <PropertyGroup>
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage</TargetsForTfmSpecificBuildOutput> <TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage</TargetsForTfmSpecificBuildOutput>
</PropertyGroup> </PropertyGroup>
<Target DependsOnTargets="BuildOnlySettings;ResolveReferences" Name="CopyProjectReferencesToPackage"> <Target DependsOnTargets="ResolveReferences" Name="CopyProjectReferencesToPackage">
<ItemGroup> <ItemGroup>
<BuildOutputInPackage Include="@(ReferenceCopyLocalPaths-&gt;WithMetadataValue('ReferenceSourceTarget', 'ProjectReference'))" /> <BuildOutputInPackage Include="@(ReferenceCopyLocalPaths-&gt;WithMetadataValue('ReferenceSourceTarget', 'ProjectReference'))" />
</ItemGroup> </ItemGroup>

View File

@ -63,6 +63,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Plugins\Stats\Stats.csproj" /> <ProjectReference Include="..\Plugins\Stats\Stats.csproj" />
<ProjectReference Include="..\SharedLibraryCore\SharedLibraryCore.csproj" /> <ProjectReference Include="..\SharedLibraryCore\SharedLibraryCore.csproj" />
<ProjectReference Include="..\Data\Data.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>