diff --git a/README.md b/README.md
index c6ff5d1..928160c 100644
--- a/README.md
+++ b/README.md
@@ -1,28 +1,28 @@
-![GitHub tag (with filter)](https://img.shields.io/github/v/tag/K4ryuu/Project_Template?style=for-the-badge&label=Version)
-![GitHub Repo stars](https://img.shields.io/github/stars/K4ryuu/Project_Template?style=for-the-badge)
-![GitHub issues](https://img.shields.io/github/issues/K4ryuu/Project_Template?style=for-the-badge)
-![GitHub](https://img.shields.io/github/license/K4ryuu/Project_Template?style=for-the-badge)
-![GitHub contributors](https://img.shields.io/github/contributors/K4ryuu/Project_Template?style=for-the-badge)
-![GitHub all releases](https://img.shields.io/github/downloads/K4ryuu/Project_Template/total?style=for-the-badge)
-![GitHub last commit (branch)](https://img.shields.io/github/last-commit/K4ryuu/Project_Template/dev?style=for-the-badge)
+![GitHub tag (with filter)](https://img.shields.io/github/v/tag/K4ryuu/CS2_SteamRestrict?style=for-the-badge&label=Version)
+![GitHub Repo stars](https://img.shields.io/github/stars/K4ryuu/CS2_SteamRestrict?style=for-the-badge)
+![GitHub issues](https://img.shields.io/github/issues/K4ryuu/CS2_SteamRestrict?style=for-the-badge)
+![GitHub](https://img.shields.io/github/license/K4ryuu/CS2_SteamRestrict?style=for-the-badge)
+![GitHub contributors](https://img.shields.io/github/contributors/K4ryuu/CS2_SteamRestrict?style=for-the-badge)
+![GitHub all releases](https://img.shields.io/github/downloads/K4ryuu/CS2_SteamRestrict/total?style=for-the-badge)
+![GitHub last commit (branch)](https://img.shields.io/github/last-commit/K4ryuu/CS2_SteamRestrict/dev?style=for-the-badge)
@@ -62,7 +62,7 @@
## About The Project
-DESCRIPTION HERE
+Enhance your game server's control with this plugin. Fetch and analyze player data from their Steam profiles, enforce minimum CS:GO playtime and Steam level requirements, and customize restrictions for Prime and non-Prime players. Flexible and powerful server management tool.
(back to top)
@@ -71,7 +71,6 @@ DESCRIPTION HERE
To use this server addon, you'll need the following dependencies installed:
- [**CounterStrikeSharp**](https://github.com/roflmuffin/CounterStrikeSharp/actions/workflows/cmake-single-platform.yml): CounterStrikeSharp allows you to write server plugins in C# for Counter-Strike 2/Source2/CS2
-- **MySQL Database (Version 5.2 or higher):** This project requires a MySQL database to store and manage data. You can host your own MySQL server or use a third-party hosting service. Make sure it's at least version 5.2 or higher.
(back to top)
@@ -106,13 +105,12 @@ Before you begin, ensure you have the following prerequisites:
- A working CS2 (Counter-Strike 2) server.
- CounterStrikeSharp is up to date and is running on your server.
-- A compatible MySQL database (Version 5.2 or higher) set up and configured.
(back to top)
### Installation
-1. **Download the Addon:** Start by downloading the addon from the [GitHub Releases Page](https://github.com/K4ryuu/Project_Template/releases). Choose the latest release version.
+1. **Download the Addon:** Start by downloading the addon from the [GitHub Releases Page](https://github.com/K4ryuu/CS2_SteamRestrict/releases). Choose the latest release version.
2. **Extract the Addon:** After downloading, extract the contents of the addon to the counterstrikesharp/plugins directory on your server. Inside the plugins folder, you should have a folder named exactly as the project dll. From the releases, you find it pre zipped with the correct name.
@@ -128,13 +126,13 @@ The addon provides several commands and console variables (convars) to customize
### Commands
-- **Command 1:** Describe the first command and how to use it.
+- None
(back to top)
### Console Variables (Convars)
-- **Convar 1:** Describe the first convar and how to set its value.
+- None
(back to top)
@@ -142,7 +140,7 @@ The addon provides several commands and console variables (convars) to customize
## Roadmap
-- [ ] No plans for now
+- [ ] No plans yet
(back to top)
diff --git a/src/.gitkeep b/src/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/src/CFG.cs b/src/CFG.cs
new file mode 100644
index 0000000..011fe51
--- /dev/null
+++ b/src/CFG.cs
@@ -0,0 +1,57 @@
+using System.Text.Json;
+
+internal class CFG
+{
+ public static Config config = new();
+
+ public void CheckConfig(string moduleDirectory)
+ {
+ string path = Path.Join(moduleDirectory, "config.json");
+
+ if (!File.Exists(path))
+ {
+ CreateAndWriteFile(path);
+ }
+
+ using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
+ using (StreamReader sr = new StreamReader(fs))
+ {
+ // Deserialize the JSON from the file and load the configuration.
+ config = JsonSerializer.Deserialize(sr.ReadToEnd())!;
+ }
+ }
+
+ private static void CreateAndWriteFile(string path)
+ {
+
+ using (FileStream fs = File.Create(path))
+ {
+ // File is created, and fs will automatically be disposed when the using block exits.
+ }
+
+ Console.WriteLine($"File created: {File.Exists(path)}");
+
+ Config config = new Config
+ {
+ SteamWebAPI = "-",
+ };
+
+ // Serialize the config object to JSON and write it to the file.
+ string jsonConfig = JsonSerializer.Serialize(config, new JsonSerializerOptions()
+ {
+ WriteIndented = true
+ });
+ File.WriteAllText(path, jsonConfig);
+ }
+}
+
+internal class Config
+{
+ public string? SteamWebAPI { get; set; }
+ public int MinimumHourNonPrime { get; set; }
+ public int MinimumHourPrime { get; set; }
+ public int MinimumLevelNonPrime { get; set; }
+ public int MinimumLevelPrime { get; set; }
+ public bool BlockPrivateProfile { get; set; }
+ public bool BlockNonPrime { get; set; }
+}
\ No newline at end of file
diff --git a/src/CounterStrikeSharp.API.dll b/src/CounterStrikeSharp.API.dll
new file mode 100644
index 0000000..656b1e9
Binary files /dev/null and b/src/CounterStrikeSharp.API.dll differ
diff --git a/src/K4ryuuSteamRestrict.cs b/src/K4ryuuSteamRestrict.cs
new file mode 100644
index 0000000..15ceb60
--- /dev/null
+++ b/src/K4ryuuSteamRestrict.cs
@@ -0,0 +1,206 @@
+using System.Text;
+using CounterStrikeSharp.API.Core;
+using CounterStrikeSharp.API.Core.Attributes;
+using CounterStrikeSharp.API.Core.Attributes.Registration;
+using CounterStrikeSharp.API.Modules.Utils;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Newtonsoft.Json.Linq;
+using CounterStrikeSharp.API;
+
+namespace K4ryuuSteamRestrict
+{
+ [MinimumApiVersion(16)]
+ public class SteamRestrictPlugin : BasePlugin
+ {
+ public class SteamUserInfo
+ {
+ public int SteamLevel { get; set; }
+ public int CSGOPlaytime { get; set; }
+ public bool IsPrivate { get; set; }
+ public bool HasPrime { get; set; }
+ }
+
+ public override string ModuleName => "Steam Restrict";
+ public override string ModuleVersion => "1.0.0";
+ public override string ModuleAuthor => "K4ryuu";
+
+ public override void Load(bool hotReload)
+ {
+ new CFG().CheckConfig(ModuleDirectory);
+ }
+
+ [GameEventHandler]
+ public HookResult OnClientConnect(EventPlayerConnectFull @event, GameEventInfo info)
+ {
+ CCSPlayerController player = @event.Userid;
+
+ if (player == null || !player.IsValid || player.IsBot || CFG.config.SteamWebAPI == "-")
+ return HookResult.Continue;
+
+ _ = FetchSteamUserInfo(player);
+
+
+ return HookResult.Continue;
+ }
+
+ private async Task FetchSteamUserInfo(CCSPlayerController player)
+ {
+ SteamUserInfo userInfo = new SteamUserInfo();
+
+ using (HttpClient httpClient = new HttpClient())
+ {
+ string steamId = player.SteamID.ToString();
+ string steamWebAPIKey = CFG.config.SteamWebAPI!;
+
+ string gamesUrl = $"https://api.steampowered.com/IPlayerService/GetOwnedGames/v1/?key={steamWebAPIKey}&steamid={steamId}&format=json";
+ HttpResponseMessage gamesResponse = await httpClient.GetAsync(gamesUrl);
+
+ if (gamesResponse.IsSuccessStatusCode)
+ {
+ string gamesJson = await gamesResponse.Content.ReadAsStringAsync();
+ userInfo.CSGOPlaytime = ParseCS2Playtime(gamesJson) / 60;
+
+ JArray games = (JObject.Parse(gamesJson)["response"]!["games"] as JArray)!;
+ bool hasPrime = games.Any(game => (int)game["appid"]! == 54029);
+ userInfo.HasPrime = hasPrime;
+ }
+ else
+ {
+ userInfo.HasPrime = false;
+ userInfo.CSGOPlaytime = 0;
+ }
+
+ // Fetch Steam level
+ string levelUrl = $"http://api.steampowered.com/IPlayerService/GetSteamLevel/v1/?key={steamWebAPIKey}&steamid={steamId}";
+ HttpResponseMessage levelResponse = await httpClient.GetAsync(levelUrl);
+
+ if (levelResponse.IsSuccessStatusCode)
+ {
+ string levelJson = await levelResponse.Content.ReadAsStringAsync();
+ userInfo.SteamLevel = ParseSteamLevel(levelJson);
+ }
+ else
+ {
+ userInfo.SteamLevel = 0;
+ }
+
+ // Fetch other user information
+ string userUrl = $"https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v2/?key={steamWebAPIKey}&steamids={steamId}";
+ HttpResponseMessage userResponse = await httpClient.GetAsync(userUrl);
+
+ if (userResponse.IsSuccessStatusCode)
+ {
+ string userJson = await userResponse.Content.ReadAsStringAsync();
+ ParseSteamUserInfo(userJson, userInfo);
+ }
+ else
+ {
+ userInfo.IsPrivate = false;
+ }
+
+ if (IsRestrictionViolated(userInfo))
+ {
+ Server.ExecuteCommand($"kickid {player.UserId} \"You have been kicked for not meeting the minimum requirements.\"");
+ }
+ }
+
+ return userInfo;
+ }
+
+ private bool IsRestrictionViolated(SteamUserInfo userInfo)
+ {
+ bool isViolated = false;
+
+ if (userInfo.HasPrime)
+ {
+ if (CFG.config.MinimumHourPrime != -1 && userInfo.CSGOPlaytime < CFG.config.MinimumHourPrime
+ || CFG.config.MinimumLevelPrime != -1 && userInfo.SteamLevel < CFG.config.MinimumLevelPrime)
+ {
+ isViolated = true;
+ }
+ }
+ else
+ {
+ if (CFG.config.MinimumHourNonPrime != -1 && userInfo.CSGOPlaytime < CFG.config.MinimumHourNonPrime
+ || CFG.config.MinimumLevelNonPrime != -1 && userInfo.SteamLevel < CFG.config.MinimumLevelNonPrime)
+ {
+ isViolated = true;
+ }
+ }
+
+ if (CFG.config.BlockPrivateProfile && userInfo.IsPrivate)
+ {
+ isViolated = true;
+ }
+
+ return isViolated;
+ }
+
+ private int ParseCS2Playtime(string json)
+ {
+ int csPlaytime = 0;
+
+ try
+ {
+ JObject data = JObject.Parse(json);
+ JArray games = (data["response"]!["games"] as JArray)!;
+
+ if (games != null)
+ {
+ foreach (var game in games)
+ {
+ int appId = (int)game["appid"]!;
+ if (appId == 730)
+ {
+ csPlaytime = (int)game["playtime_forever"]!;
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"Error parsing CS:GO playtime: {ex.Message}");
+ }
+
+ return csPlaytime;
+ }
+
+ private int ParseSteamLevel(string json)
+ {
+ int steamLevel = 0;
+
+ try
+ {
+ JObject data = JObject.Parse(json);
+ steamLevel = (int)data["response"]!["player_level"]!;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"Error parsing Steam level: {ex.Message}");
+ }
+
+ return steamLevel;
+ }
+
+ private void ParseSteamUserInfo(string json, SteamUserInfo userInfo)
+ {
+ try
+ {
+ JObject data = JObject.Parse(json);
+ JArray players = (data["response"]!["players"] as JArray)!;
+
+ if (players != null && players.Count > 0)
+ {
+ var player = players[0];
+
+ userInfo.IsPrivate = (int)player["communityvisibilitystate"]! != 3;
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"Error parsing Steam user info: {ex.Message}");
+ }
+ }
+ }
+}
diff --git a/src/K4ryuuSteamRestrict.csproj b/src/K4ryuuSteamRestrict.csproj
new file mode 100644
index 0000000..c2a336e
--- /dev/null
+++ b/src/K4ryuuSteamRestrict.csproj
@@ -0,0 +1,12 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
\ No newline at end of file