mirror of
https://github.com/daffyyyy/CS2-SimpleAdmin.git
synced 2026-02-23 04:00:38 +00:00
Add files via upload
This commit is contained in:
BIN
MODULES/CS2-SimpleAdmin_PlayTimeModule/CS2-SimpleAdminApi.dll
Normal file
BIN
MODULES/CS2-SimpleAdmin_PlayTimeModule/CS2-SimpleAdminApi.dll
Normal file
Binary file not shown.
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<RootNamespace>CS2_SimpleAdmin_PlayTimeModule</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.316" />
|
||||
<PackageReference Include="Dapper" Version="2.1.66" />
|
||||
<PackageReference Include="MySqlConnector" Version="2.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="CS2-SimpleAdminApi">
|
||||
<HintPath>CS2-SimpleAdminApi.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CS2-SimpleAdmin_PlayTimeModule", "CS2-SimpleAdmin_PlayTimeModule.csproj", "{FEF949BC-C8AD-4ECB-ABA1-449AE685B31C}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{FEF949BC-C8AD-4ECB-ABA1-449AE685B31C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FEF949BC-C8AD-4ECB-ABA1-449AE685B31C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FEF949BC-C8AD-4ECB-ABA1-449AE685B31C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FEF949BC-C8AD-4ECB-ABA1-449AE685B31C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,4 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=L_003A_005CGITHUB_005CCS2_002DSimpleAdmin_005CModules_005CCS2_002DSimpleAdmin_005FPlayTimeModule_005CCS2_002DSimpleAdminApi_002Edll/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AGameEvents_002Eg_002Ecs_002Fl_003AC_0021_003FUsers_003Fxdaff_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F7e129fe222b6d23f1a582a7dfdd9f730e7925c8ab8d2d5fb457fdf385e69_003FGameEvents_002Eg_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AICS2_005FSimpleAdminApi_002Ecs_002Fl_003AC_0021_003FUsers_003Fxdaff_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fa64168ca28114bbebf4c9d9298397d462200_003Fd2_003Fb9523498_003FICS2_005FSimpleAdminApi_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>
|
||||
@@ -0,0 +1,181 @@
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Core.Capabilities;
|
||||
using CS2_SimpleAdminApi;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using CounterStrikeSharp.API.Core.Attributes.Registration;
|
||||
using CounterStrikeSharp.API.Modules.Admin;
|
||||
using CounterStrikeSharp.API.Modules.Commands;
|
||||
using CounterStrikeSharp.API.Modules.Entities;
|
||||
|
||||
namespace CS2_SimpleAdmin_PlayTimeModule;
|
||||
|
||||
public sealed class CS2_SimpleAdmin_PlayTimeModule : BasePlugin
|
||||
{
|
||||
public override string ModuleName => "[CS2-SimpleAdmin] PlayTime Module";
|
||||
public override string ModuleVersion => "1.0.0";
|
||||
|
||||
private static ICS2_SimpleAdminApi? _sharedApi;
|
||||
private readonly PluginCapability<ICS2_SimpleAdminApi> _pluginCapability = new("simpleadmin:api");
|
||||
|
||||
private Database? _database;
|
||||
private readonly Dictionary<ulong, PlayTimeModel> _playTimes = [];
|
||||
|
||||
public override void OnAllPluginsLoaded(bool hotReload)
|
||||
{
|
||||
_sharedApi = _pluginCapability.Get();
|
||||
|
||||
if (_sharedApi == null)
|
||||
{
|
||||
Logger.LogError("CS2-SimpleAdmin SharedApi not found");
|
||||
Unload(false);
|
||||
return;
|
||||
}
|
||||
|
||||
AddCommandListener("jointeam", JoinTeamListener);
|
||||
// ## Zrobic to na jointeam
|
||||
|
||||
_database = new Database(_sharedApi.GetConnectionString());
|
||||
}
|
||||
|
||||
private HookResult JoinTeamListener(CCSPlayerController? player, CommandInfo commandinfo)
|
||||
{
|
||||
if (player == null || !player.IsValid || player.IsBot)
|
||||
return HookResult.Continue;
|
||||
|
||||
int team = GetTeamNumber(commandinfo);
|
||||
|
||||
if (player.TeamNum == team)
|
||||
return HookResult.Continue;
|
||||
|
||||
var steamId = player.SteamID;
|
||||
if (!_playTimes.TryGetValue(steamId, out var playTimeModel)) return HookResult.Continue;
|
||||
|
||||
HandlePlayTimeUpdate(playTimeModel.OldTeam, team, playTimeModel, x => x.Teams[playTimeModel.OldTeam].JoinedTime, time => playTimeModel.Teams[playTimeModel.OldTeam].PlayTime += time);
|
||||
playTimeModel.Teams[player.TeamNum].JoinedTime = DateTime.Now;
|
||||
playTimeModel.OldTeam = team;
|
||||
|
||||
return HookResult.Continue;
|
||||
}
|
||||
|
||||
[GameEventHandler]
|
||||
public HookResult EventPlayerFullConnect(EventPlayerConnectFull @event, GameEventInfo _)
|
||||
{
|
||||
if (_sharedApi == null || _database == null)
|
||||
return HookResult.Continue;
|
||||
|
||||
var player = @event.Userid;
|
||||
if (player == null || !player.IsValid || player.IsBot)
|
||||
return HookResult.Continue;
|
||||
|
||||
var steamId = player.SteamID;
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var playTimeModel = await _database.GetPlayTimeAsync(steamId, _sharedApi.GetServerId());
|
||||
if (playTimeModel == null)
|
||||
return;
|
||||
|
||||
_playTimes.Add(steamId, playTimeModel);
|
||||
});
|
||||
|
||||
return HookResult.Continue;
|
||||
}
|
||||
|
||||
[GameEventHandler(HookMode.Pre)]
|
||||
public HookResult EventPlayerDisconnect(EventPlayerDisconnect @event, GameEventInfo _)
|
||||
{
|
||||
if (_sharedApi == null || _database == null)
|
||||
return HookResult.Continue;
|
||||
|
||||
var player = @event.Userid;
|
||||
if (player == null || !player.IsValid || player.IsBot)
|
||||
return HookResult.Continue;
|
||||
|
||||
var steamId = player.SteamID;
|
||||
|
||||
if (!_playTimes.TryGetValue(steamId, out var playTimeModel)) return HookResult.Continue;
|
||||
|
||||
var totalPlayTime = (int)(DateTime.Now - playTimeModel.JoinedTime).TotalSeconds;
|
||||
if (totalPlayTime <= 10) return HookResult.Continue;
|
||||
playTimeModel.TotalPlayTime += totalPlayTime;
|
||||
|
||||
HandlePlayTimeUpdate(playTimeModel.OldTeam, playTimeModel.OldTeam, playTimeModel, x => x.Teams[playTimeModel.OldTeam].JoinedTime, time => playTimeModel.Teams[playTimeModel.OldTeam].PlayTime += time);
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await _database.UpdatePlayTimeAsync(steamId, playTimeModel, _sharedApi.GetServerId());
|
||||
_playTimes.Remove(steamId);
|
||||
});
|
||||
|
||||
return HookResult.Continue;
|
||||
}
|
||||
|
||||
[GameEventHandler(HookMode.Pre)]
|
||||
public HookResult EventPlayerChangeTeam(EventPlayerTeam @event, GameEventInfo _)
|
||||
{
|
||||
if (_sharedApi == null || _database == null)
|
||||
return HookResult.Continue;
|
||||
|
||||
var player = @event.Userid;
|
||||
|
||||
if (player == null || !player.IsValid || player.IsBot)
|
||||
return HookResult.Continue;
|
||||
|
||||
var steamId = player.SteamID;
|
||||
if (!_playTimes.TryGetValue(steamId, out var playTimeModel)) return HookResult.Continue;
|
||||
|
||||
// Set the appropriate join time based on the team
|
||||
playTimeModel.Teams[@event.Team].JoinedTime = DateTime.Now;
|
||||
|
||||
HandlePlayTimeUpdate(playTimeModel.OldTeam, @event.Team, playTimeModel, x => x.Teams[playTimeModel.OldTeam].JoinedTime, time => playTimeModel.Teams[playTimeModel.OldTeam].PlayTime += time);
|
||||
playTimeModel.OldTeam = @event.Team;
|
||||
|
||||
return HookResult.Continue;
|
||||
}
|
||||
|
||||
[GameEventHandler]
|
||||
public HookResult EventPlayerSpawn(EventPlayerSpawn @event, GameEventInfo _)
|
||||
{
|
||||
if (_sharedApi == null || _database == null)
|
||||
return HookResult.Continue;
|
||||
|
||||
var player = @event.Userid;
|
||||
if (player == null || !player.IsValid || player.IsBot || player.Connected != PlayerConnectedState.PlayerConnected)
|
||||
return HookResult.Continue;
|
||||
|
||||
var steamId = player.SteamID;
|
||||
// if (AdminManager.PlayerHasPermissions(new SteamID(steamId)))
|
||||
if (!_playTimes.TryGetValue(steamId, out var playTimeModel)) return HookResult.Continue;
|
||||
|
||||
if (playTimeModel.OldTeam != player.TeamNum)
|
||||
{
|
||||
HandlePlayTimeUpdate(playTimeModel.OldTeam, player.TeamNum, playTimeModel, x => x.Teams[playTimeModel.OldTeam].JoinedTime, time => playTimeModel.Teams[playTimeModel.OldTeam].PlayTime += time);
|
||||
}
|
||||
|
||||
playTimeModel.OldTeam = player.TeamNum;
|
||||
playTimeModel.Teams[player.TeamNum].JoinedTime = DateTime.Now;
|
||||
|
||||
return HookResult.Continue;
|
||||
}
|
||||
|
||||
private static void HandlePlayTimeUpdate(int oldTeam, int newTeam, PlayTimeModel playTimeModel, Func<PlayTimeModel, DateTime?> getJoinTime, Action<int> updatePlayTime)
|
||||
{
|
||||
var joinedTime = getJoinTime(playTimeModel);
|
||||
if (!joinedTime.HasValue) return;
|
||||
|
||||
// Add playtime to the appropriate team
|
||||
var playTime = (int)(DateTime.Now - joinedTime.Value).TotalSeconds;
|
||||
|
||||
updatePlayTime(playTime); // Update playtime for the corresponding team
|
||||
|
||||
// Clear the join time after updating playtime
|
||||
playTimeModel.Teams[oldTeam].JoinedTime = null;
|
||||
}
|
||||
|
||||
private static int GetTeamNumber(CommandInfo info)
|
||||
{
|
||||
var startIndex = info.ArgByIndex(0).Equals("jointeam", StringComparison.CurrentCultureIgnoreCase) ? 1 : 0;
|
||||
return info.ArgCount > startIndex && int.TryParse(info.ArgByIndex(startIndex), out var teamId) ? teamId : -1;
|
||||
}
|
||||
|
||||
}
|
||||
10
MODULES/CS2-SimpleAdmin_PlayTimeModule/Config.cs
Normal file
10
MODULES/CS2-SimpleAdmin_PlayTimeModule/Config.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using CounterStrikeSharp.API.Core;
|
||||
|
||||
namespace CS2_SimpleAdmin_PlayTimeModule;
|
||||
|
||||
public class Config : IBasePluginConfig
|
||||
{
|
||||
public int Version { get; set; } = 1;
|
||||
public string AdminFlag { get; set; } = "@css/ban";
|
||||
public int MinPlayers { get; set; } = 4;
|
||||
}
|
||||
115
MODULES/CS2-SimpleAdmin_PlayTimeModule/Database.cs
Normal file
115
MODULES/CS2-SimpleAdmin_PlayTimeModule/Database.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using Dapper;
|
||||
using MySqlConnector;
|
||||
|
||||
namespace CS2_SimpleAdmin_PlayTimeModule;
|
||||
|
||||
public class Database(string dbConnectionString)
|
||||
{
|
||||
private async Task<MySqlConnection> GetConnectionAsync()
|
||||
{
|
||||
var connection = new MySqlConnection(dbConnectionString);
|
||||
await connection.OpenAsync();
|
||||
return connection;
|
||||
}
|
||||
|
||||
public async Task<PlayTimeModel?> GetPlayTimeAsync(ulong steamId, int? serverId)
|
||||
{
|
||||
if (!serverId.HasValue)
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
await using var connection = await GetConnectionAsync();
|
||||
const string query = """
|
||||
SELECT total_playtime AS TotalPlayTime,
|
||||
spec_playtime AS SpecPlayTime,
|
||||
hidden_playtime AS HiddenPlayTime,
|
||||
ct_playtime AS CtPlayTime,
|
||||
tt_playtime AS TtPlayTime
|
||||
FROM sa_playtime
|
||||
WHERE steamid = @SteamId AND server_id = @ServerId
|
||||
LIMIT 1;
|
||||
""";
|
||||
|
||||
var rawResult = await connection.QueryFirstOrDefaultAsync(query, new { SteamId = steamId, ServerId = serverId });
|
||||
|
||||
var model = new PlayTimeModel();
|
||||
|
||||
if (rawResult != null)
|
||||
{
|
||||
model.TotalPlayTime = rawResult.TotalPlayTime;
|
||||
model.Teams[0].PlayTime = rawResult.HiddenPlayTime;
|
||||
model.Teams[1].PlayTime = rawResult.SpecPlayTime;
|
||||
model.Teams[2].PlayTime = rawResult.TtPlayTime;
|
||||
model.Teams[3].PlayTime = rawResult.CtPlayTime;
|
||||
}
|
||||
|
||||
// var result = await connection.QueryFirstOrDefaultAsync<PlayTimeModel>(query, new { SteamId = steamId, ServerId = serverId })
|
||||
// ?? new PlayTimeModel(totalPlayTime: 0);
|
||||
|
||||
model.JoinedTime = DateTime.Now;
|
||||
return model;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Error retrieving playtime data for SteamId {steamId}: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UpdatePlayTimeAsync(ulong steamId, PlayTimeModel model, int? serverId)
|
||||
{
|
||||
if (!serverId.HasValue)
|
||||
return;
|
||||
try
|
||||
{
|
||||
const string checkQuery =
|
||||
"SELECT EXISTS(SELECT 1 FROM sa_playtime WHERE steamid = @SteamId AND server_id = @ServerId LIMIT 1);";
|
||||
|
||||
const string insertQuery =
|
||||
"INSERT INTO sa_playtime (steamid, server_id, total_playtime, spec_playtime, hidden_playtime, ct_playtime, tt_playtime) " +
|
||||
"VALUES (@SteamId, @ServerId, @TotalPlayTime, @SpecPlayTime, @HiddenPlayTime, @CtPlayTime, @TtPlayTime);";
|
||||
|
||||
const string updateQuery =
|
||||
"UPDATE sa_playtime " +
|
||||
"SET total_playtime = @TotalPlayTime, spec_playtime = @SpecPlayTime, hidden_playtime = @HiddenPlayTime, ct_playtime = @CtPlayTime, tt_playtime = @TtPlayTime " +
|
||||
"WHERE steamid = @SteamId AND server_id = @ServerId;";
|
||||
|
||||
await using var connection = await GetConnectionAsync();
|
||||
|
||||
var exists =
|
||||
await connection.ExecuteScalarAsync<bool>(checkQuery, new { SteamId = steamId, ServerId = serverId });
|
||||
|
||||
if (exists)
|
||||
{
|
||||
await connection.ExecuteAsync(updateQuery, new
|
||||
{
|
||||
SteamId = steamId,
|
||||
ServerId = serverId,
|
||||
model.TotalPlayTime,
|
||||
HiddenPlayTime = model.Teams[0].PlayTime,
|
||||
SpecPlayTime = model.Teams[1].PlayTime,
|
||||
TtPlayTime = model.Teams[2].PlayTime,
|
||||
CtPlayTime = model.Teams[3].PlayTime
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
await connection.ExecuteAsync(insertQuery, new
|
||||
{
|
||||
SteamId = steamId,
|
||||
ServerId = serverId,
|
||||
model.TotalPlayTime,
|
||||
HiddenPlayTime = model.Teams[0].PlayTime,
|
||||
SpecPlayTime = model.Teams[1].PlayTime,
|
||||
TtPlayTime = model.Teams[2].PlayTime,
|
||||
CtPlayTime = model.Teams[3].PlayTime
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
31
MODULES/CS2-SimpleAdmin_PlayTimeModule/PlayTimeModel.cs
Normal file
31
MODULES/CS2-SimpleAdmin_PlayTimeModule/PlayTimeModel.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
namespace CS2_SimpleAdmin_PlayTimeModule;
|
||||
|
||||
public class PlayTimeModel
|
||||
{
|
||||
public PlayTimeModel()
|
||||
{
|
||||
}
|
||||
|
||||
public PlayTimeModel(int totalPlayTime)
|
||||
{
|
||||
TotalPlayTime = totalPlayTime;
|
||||
}
|
||||
|
||||
public int TotalPlayTime { get; set; }
|
||||
public DateTime JoinedTime { get; set; }
|
||||
public int OldTeam { get; set; } = 1;
|
||||
|
||||
public Dictionary<int, PlayerTeamModel> Teams { get; set; } = new()
|
||||
{
|
||||
{ 0, new PlayerTeamModel() }, // Hidden
|
||||
{ 1, new PlayerTeamModel() }, // Spec
|
||||
{ 2, new PlayerTeamModel() }, // TT
|
||||
{ 3, new PlayerTeamModel() }, // CT
|
||||
};
|
||||
}
|
||||
|
||||
public class PlayerTeamModel
|
||||
{
|
||||
public int PlayTime { get; set; }
|
||||
public DateTime? JoinedTime { get; set; }
|
||||
}
|
||||
7
MODULES/CS2-SimpleAdmin_PlayTimeModule/global.json
Normal file
7
MODULES/CS2-SimpleAdmin_PlayTimeModule/global.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"sdk": {
|
||||
"version": "8.0.0",
|
||||
"rollForward": "latestMinor",
|
||||
"allowPrerelease": false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user