Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit 5315bc1

Browse files
committed
Patch v1.3.0
1 parent ee615a5 commit 5315bc1

File tree

5 files changed

+201
-23
lines changed

5 files changed

+201
-23
lines changed

CHANGELOG

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
-- 2024. 05. 18 - v1.3.0
2+
3+
- feat: Add configuration json file to allow players to bypass specific restrictions
4+
- feat: Add database to store allowed players for a while and dont validate them all the time
5+
16
-- 2024. 04. 26 - v1.2.1
27

38
- update: Updated from NET7 to NET8

src/KitsuneSteamRestrict.cs

Lines changed: 87 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
using CounterStrikeSharp.API.Core;
33
using CounterStrikeSharp.API.Core.Attributes;
44
using CounterStrikeSharp.API.Modules.Timers;
5+
using CounterStrikeSharp.API.Modules.Admin;
56

67
using System.Text.Json.Serialization;
78
using Microsoft.Extensions.Logging;
8-
using CounterStrikeSharp.API.Modules.Admin;
99

1010
namespace KitsuneSteamRestrict;
1111

@@ -49,13 +49,46 @@ public class PluginConfig : BasePluginConfig
4949

5050
[JsonPropertyName("BlockGameBanned")]
5151
public bool BlockGameBanned { get; set; } = false;
52+
53+
[JsonPropertyName("DatabaseSettings")]
54+
public DatabaseSettings DatabaseSettings = new DatabaseSettings();
55+
56+
[JsonPropertyName("ConfigVersion")]
57+
public override int Version { get; set; } = 2;
58+
}
59+
60+
public sealed class DatabaseSettings
61+
{
62+
[JsonPropertyName("host")]
63+
public string Host { get; set; } = "localhost";
64+
65+
[JsonPropertyName("username")]
66+
public string Username { get; set; } = "root";
67+
68+
[JsonPropertyName("database")]
69+
public string Database { get; set; } = "database";
70+
71+
[JsonPropertyName("password")]
72+
public string Password { get; set; } = "password";
73+
74+
[JsonPropertyName("port")]
75+
public int Port { get; set; } = 3306;
76+
77+
[JsonPropertyName("sslmode")]
78+
public string Sslmode { get; set; } = "none";
79+
80+
[JsonPropertyName("table-prefix")]
81+
public string TablePrefix { get; set; } = "";
82+
83+
[JsonPropertyName("table-purge-days")]
84+
public int TablePurgeDays { get; set; } = 30;
5285
}
5386

54-
[MinimumApiVersion(198)]
87+
[MinimumApiVersion(227)]
5588
public class SteamRestrictPlugin : BasePlugin, IPluginConfig<PluginConfig>
5689
{
5790
public override string ModuleName => "Steam Restrict";
58-
public override string ModuleVersion => "1.2.1";
91+
public override string ModuleVersion => "1.3.0";
5992
public override string ModuleAuthor => "K4ryuu, Cruze @ KitsuneLab";
6093
public override string ModuleDescription => "Restrict certain players from connecting to your server.";
6194

@@ -64,20 +97,29 @@ public class SteamRestrictPlugin : BasePlugin, IPluginConfig<PluginConfig>
6497

6598
private CounterStrikeSharp.API.Modules.Timers.Timer?[] g_hAuthorize = new CounterStrikeSharp.API.Modules.Timers.Timer?[65];
6699

100+
private BypassConfig? _bypassConfig;
67101
public PluginConfig Config { get; set; } = new();
68102

69103
public void OnConfigParsed(PluginConfig config)
70104
{
71-
Config = config;
105+
if (config.Version < Config.Version)
106+
base.Logger.LogWarning("Configuration version mismatch (Expected: {0} | Current: {1})", this.Config.Version, config.Version);
72107

73108
if (string.IsNullOrEmpty(config.SteamWebAPI))
74-
{
75-
Logger.LogError("This plugin won't work because Web API is empty.");
76-
}
109+
base.Logger.LogError("This plugin won't work because Web API is empty.");
110+
111+
Config = config;
77112
}
78113

79114
public override void Load(bool hotReload)
80115
{
116+
string bypassConfigFilePath = "bypass_config.json";
117+
var bypassConfigService = new BypassConfigService(bypassConfigFilePath);
118+
_bypassConfig = bypassConfigService.LoadConfig();
119+
120+
var databaseService = new DatabaseService(Config.DatabaseSettings);
121+
_ = databaseService.EnsureTablesExistAsync();
122+
81123
RegisterListener<Listeners.OnGameServerSteamAPIActivated>(() => { g_bSteamAPIActivated = true; });
82124
RegisterListener<Listeners.OnClientConnect>((int slot, string name, string ipAddress) => { g_hAuthorize[slot]?.Kill(); });
83125
RegisterListener<Listeners.OnClientDisconnect>((int slot) => { g_hAuthorize[slot]?.Kill(); });
@@ -96,8 +138,7 @@ public override void Load(bool hotReload)
96138

97139
public HookResult OnPlayerConnectFull(EventPlayerConnectFull @event, GameEventInfo info)
98140
{
99-
CCSPlayerController player = @event.Userid;
100-
141+
CCSPlayerController? player = @event.Userid;
101142
if (player == null)
102143
return HookResult.Continue;
103144

@@ -131,10 +172,21 @@ private void OnPlayerConnectFull(CCSPlayerController player)
131172
if (!g_bSteamAPIActivated)
132173
return;
133174

134-
nint handle = player.Handle;
135175
ulong authorizedSteamID = player.AuthorizedSteamID.SteamId64;
176+
nint handle = player.Handle;
177+
178+
var databaseService = new DatabaseService(Config.DatabaseSettings);
136179

137-
_ = CheckUserViolations(handle, authorizedSteamID);
180+
Task.Run(async () =>
181+
{
182+
if (await databaseService.IsSteamIdAllowedAsync(authorizedSteamID))
183+
{
184+
Server.NextWorldUpdate(() => Logger.LogInformation($"{player.PlayerName} ({authorizedSteamID}) was allowed to join without validations because they were found in the database."));
185+
return;
186+
}
187+
188+
await CheckUserViolations(handle, authorizedSteamID);
189+
});
138190
}
139191

140192
private async Task CheckUserViolations(nint handle, ulong authorizedSteamID)
@@ -168,6 +220,16 @@ private async Task CheckUserViolations(nint handle, ulong authorizedSteamID)
168220
{
169221
Server.ExecuteCommand($"kickid {player.UserId} \"You have been kicked for not meeting the minimum requirements.\"");
170222
}
223+
else
224+
{
225+
ulong steamID = player.AuthorizedSteamID?.SteamId64 ?? 0;
226+
227+
if (steamID != 0)
228+
{
229+
var databaseService = new DatabaseService(Config.DatabaseSettings);
230+
Task.Run(async () => await databaseService.AddAllowedUserAsync(steamID, Config.DatabaseSettings.TablePurgeDays));
231+
}
232+
}
171233
}
172234
});
173235
}
@@ -177,21 +239,23 @@ private bool IsRestrictionViolated(CCSPlayerController player, SteamUserInfo use
177239
if (AdminManager.PlayerHasPermissions(player, "@css/bypasspremiumcheck"))
178240
return false;
179241

242+
BypassConfig bypassConfig = _bypassConfig ?? new BypassConfig();
243+
180244
bool isPrime = userInfo.HasPrime;
181245
var configChecks = new[]
182246
{
183-
(isPrime, Config.MinimumHourPrime, userInfo.CS2Playtime),
184-
(isPrime, Config.MinimumLevelPrime, userInfo.SteamLevel),
185-
(isPrime, Config.MinimumCS2LevelPrime, userInfo.CS2Level),
186-
(!isPrime, Config.MinimumHourNonPrime, userInfo.CS2Playtime),
187-
(!isPrime, Config.MinimumLevelNonPrime, userInfo.SteamLevel),
188-
(!isPrime, Config.MinimumCS2LevelNonPrime, userInfo.CS2Level),
189-
(true, Config.MinimumSteamAccountAgeInDays, (DateTime.Now - userInfo.SteamAccountAge).TotalDays),
190-
(Config.BlockPrivateProfile, 1, userInfo.IsPrivate ? 0 : 1),
191-
(Config.BlockTradeBanned, 1, userInfo.IsTradeBanned ? 0 : 1),
192-
(Config.BlockGameBanned, 1, userInfo.IsGameBanned ? 0 : 1),
193-
(!string.IsNullOrEmpty(Config.SteamGroupID), 1, userInfo.IsInSteamGroup ? 1 : 0),
194-
(Config.BlockVACBanned, 1, userInfo.IsVACBanned ? 0 : 1),
247+
(isPrime && !bypassConfig.BypassMinimumCS2Level, Config.MinimumCS2LevelPrime, userInfo.CS2Level),
248+
(!isPrime && !bypassConfig.BypassMinimumCS2Level, Config.MinimumCS2LevelNonPrime, userInfo.CS2Level),
249+
(isPrime && !bypassConfig.BypassMinimumHours, Config.MinimumHourPrime, userInfo.CS2Playtime),
250+
(!isPrime && !bypassConfig.BypassMinimumHours, Config.MinimumHourNonPrime, userInfo.CS2Playtime),
251+
(isPrime && !bypassConfig.BypassMinimumLevel, Config.MinimumLevelPrime, userInfo.SteamLevel),
252+
(!isPrime && !bypassConfig.BypassMinimumLevel, Config.MinimumLevelNonPrime, userInfo.SteamLevel),
253+
(!bypassConfig.BypassMinimumSteamAccountAge, Config.MinimumSteamAccountAgeInDays, (DateTime.Now - userInfo.SteamAccountAge).TotalDays),
254+
(Config.BlockPrivateProfile && !bypassConfig.BypassPrivateProfile, 1, userInfo.IsPrivate ? 0 : 1),
255+
(Config.BlockTradeBanned && !bypassConfig.BypassTradeBanned, 1, userInfo.IsTradeBanned ? 0 : 1),
256+
(Config.BlockGameBanned && !bypassConfig.BypassGameBanned, 1, userInfo.IsGameBanned ? 0 : 1),
257+
(!string.IsNullOrEmpty(Config.SteamGroupID) && !bypassConfig.BypassSteamGroupCheck, 1, userInfo.IsInSteamGroup ? 1 : 0),
258+
(Config.BlockVACBanned && !bypassConfig.BypassVACBanned, 1, userInfo.IsVACBanned ? 0 : 1),
195259
};
196260

197261
return configChecks.Any(check => check.Item1 && check.Item2 != -1 && check.Item3 < check.Item2);

src/KitsuneSteamRestrict.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
<ExcludeAssets>runtime</ExcludeAssets>
1616
<IncludeAssets>compile; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
1717
</PackageReference>
18+
<PackageReference Include="Dapper" Version="2.1.35" />
19+
<PackageReference Include="MySqlConnector" Version="2.3.7" />
1820
<PackageReference Include="Newtonsoft.Json" Version="*" />
1921
<PackageReference Include="Steamworks.NET" Version="*" />
2022
</ItemGroup>

src/Models/BypassConfigService.cs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using System.Text.Json;
2+
3+
namespace KitsuneSteamRestrict
4+
{
5+
public class BypassConfig
6+
{
7+
public ulong SteamID { get; set; }
8+
public bool BypassMinimumCS2Level { get; set; } = false;
9+
public bool BypassMinimumHours { get; set; } = false;
10+
public bool BypassMinimumLevel { get; set; } = false;
11+
public bool BypassMinimumSteamAccountAge { get; set; } = false;
12+
public bool BypassPrivateProfile { get; set; } = false;
13+
public bool BypassTradeBanned { get; set; } = false;
14+
public bool BypassVACBanned { get; set; } = false;
15+
public bool BypassSteamGroupCheck { get; set; } = false;
16+
public bool BypassGameBanned { get; set; } = false;
17+
}
18+
19+
public class BypassConfigService
20+
{
21+
private readonly string _configFilePath;
22+
23+
public BypassConfigService(string configFilePath)
24+
{
25+
_configFilePath = configFilePath;
26+
}
27+
28+
public BypassConfig LoadConfig()
29+
{
30+
if (File.Exists(_configFilePath))
31+
{
32+
string json = File.ReadAllText(_configFilePath);
33+
return JsonSerializer.Deserialize<BypassConfig>(json)!;
34+
}
35+
else
36+
{
37+
BypassConfig defaultConfig = new BypassConfig
38+
{
39+
SteamID = 76561198345583467,
40+
BypassMinimumCS2Level = true,
41+
BypassMinimumHours = false,
42+
BypassMinimumLevel = true,
43+
BypassMinimumSteamAccountAge = false,
44+
BypassPrivateProfile = true,
45+
BypassTradeBanned = false,
46+
BypassVACBanned = true,
47+
BypassSteamGroupCheck = false,
48+
BypassGameBanned = true
49+
};
50+
51+
string json = JsonSerializer.Serialize(defaultConfig, new JsonSerializerOptions { WriteIndented = true });
52+
File.WriteAllText(_configFilePath, json);
53+
54+
return defaultConfig;
55+
}
56+
}
57+
}
58+
}

src/Models/DatabaseService.cs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using Dapper;
2+
using KitsuneSteamRestrict;
3+
using MySqlConnector;
4+
5+
public class DatabaseService
6+
{
7+
private readonly string _tablePrefix;
8+
private readonly string _connectionString;
9+
10+
public DatabaseService(DatabaseSettings settings)
11+
{
12+
_tablePrefix = settings.TablePrefix;
13+
_connectionString = $"Server={settings.Host};Port={settings.Port};Database={settings.Database};Uid={settings.Username};Pwd={settings.Password};SslMode={Enum.Parse<MySqlSslMode>(settings.Sslmode, true)};";
14+
}
15+
16+
public async Task<bool> IsSteamIdAllowedAsync(ulong steamId)
17+
{
18+
using var connection = new MySqlConnection(_connectionString);
19+
var result = await connection.QueryFirstOrDefaultAsync<DateTime?>(
20+
$"SELECT `expiration_date` FROM `{_tablePrefix}allowed_users` WHERE `steam_id` = @steamId AND `expiration_date` > NOW()",
21+
new { steamId });
22+
23+
return result.HasValue;
24+
}
25+
26+
public async Task AddAllowedUserAsync(ulong steamId, int daysValid)
27+
{
28+
using var connection = new MySqlConnection(_connectionString);
29+
await connection.ExecuteAsync(
30+
$"INSERT INTO `{_tablePrefix}allowed_users` (`steam_id`, `expiration_date`) VALUES (@steamId, DATE_ADD(NOW(), INTERVAL @daysValid DAY))",
31+
new { steamId, daysValid });
32+
}
33+
34+
public async Task EnsureTablesExistAsync()
35+
{
36+
using var connection = new MySqlConnection(_connectionString);
37+
await connection.ExecuteAsync($@"
38+
CREATE TABLE IF NOT EXISTS `{_tablePrefix}allowed_users` (
39+
`steam_id` BIGINT UNSIGNED PRIMARY KEY,
40+
`expiration_date` DATETIME
41+
)");
42+
}
43+
44+
public async Task PurgeExpiredSavesAsync()
45+
{
46+
using var connection = new MySqlConnection(_connectionString);
47+
await connection.ExecuteAsync($"DELETE FROM `{_tablePrefix}allowed_users` WHERE `expiration_date` < NOW()");
48+
}
49+
}

0 commit comments

Comments
 (0)