Compare commits

...

8 Commits

Author SHA1 Message Date
Nereziel
530a7d64c7 Update README.md 2023-11-19 20:45:12 +01:00
Nereziel
3453f4c505 Merge pull request #47 from daffyyyy/feature/global-share
EXPERIMENTAL (GlobalShare) - Website for all servers
2023-11-19 19:03:05 +01:00
Nereziel
25b466422b Update build.yml 2023-11-19 19:02:26 +01:00
daffyyyy
6baa59dd9b Update WeaponPaints.cs
New version
2023-11-19 12:30:47 +01:00
daffyyyy
10afe7ce1e Update WeaponPaints.cs 2023-11-19 12:24:57 +01:00
daffyyyy
5eeb0c5fec Initial 2023-11-19 02:07:29 +01:00
Nereziel
e53ee27b39 Merge pull request #44 from daffyyyy/fix-knives_finally
Finally fixed knife problem?
2023-11-18 19:26:37 +01:00
Dawid Bepierszcz
75112b02fe Update WeaponPaints.cs 2023-11-18 19:21:28 +01:00
5 changed files with 774 additions and 613 deletions

View File

@@ -30,6 +30,7 @@ jobs:
run: dotnet build ${{ env.PROJECT_PATH }} -c WeaponPaints -o ${{ env.OUTPUT_PATH }}
publish:
if: github.event_name == 'push'
permissions: write-all
runs-on: ubuntu-latest
needs: build

View File

@@ -75,6 +75,9 @@ namespace WeaponPaints
[JsonPropertyName("DatabaseName")]
public string DatabaseName { get; set; } = "";
[JsonPropertyName("GlobalShare")]
public bool GlobalShare { get; set; } = false;
[JsonPropertyName("CmdRefreshCooldownSeconds")]
public int CmdRefreshCooldownSeconds { get; set; } = 60;

View File

@@ -11,7 +11,7 @@ There will be a lot of frequent changes which may break functionality or compati
### Features
- changes only paint, seed and wear on weapons and knives
- mysql based
- mysql based or global website at [weaponpaints.fun](https://weaponpaints.fun/), so you dont need mysql/website
- data sync on player connect
- Added command `!wp` to refresh skins (with cooldown in second can be configured)
- Added command `!ws` to show website
@@ -20,10 +20,12 @@ There will be a lot of frequent changes which may break functionality or compati
### CS2 server:
- compile and copy plugin to plugins. Info here [https://docs.cssharp.dev/guides/hello-world-plugin/](https://docs.cssharp.dev/guides/hello-world-plugin/)
- setup `addons/counterstrikesharp/configs/plugins/WeaponPaints/WeaponPaints.json` with database credentials
- setup `addons/counterstrikesharp/configs/plugins/WeaponPaints/WeaponPaints.json`
set `GlobalShare` to true for gloval, or include database credentials
- in `addons/counterstrikesharp/configs/core.json` set **FollowCS2ServerGuidelines** to **false**
### Web install:
- not needed if config `GlobalShare = true`
- requires PHP min v7.3 (tested on php ver `8.2.3` and nginx webserver)
- copy website to web server (img folder not needed)
- import `database.sql` to mysql
@@ -31,6 +33,9 @@ There will be a lot of frequent changes which may break functionality or compati
- fill in database credentials and api key in `class/config.php`
- visit website and login via steam
### Known issues
- Issue on Windows servers, no knives are given.
### Use this plugin at your own risk! Using this may lead to GSLT ban or something else Valve come with. [Valve Server guidelines](https://blog.counter-strike.net/index.php/server_guidelines/)
### Preview

View File

@@ -1,7 +1,6 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Core.Attributes;
using CounterStrikeSharp.API.Core.Attributes.Registration;
using CounterStrikeSharp.API.Modules.Commands;
using CounterStrikeSharp.API.Modules.Entities;
using CounterStrikeSharp.API.Modules.Memory;
@@ -11,20 +10,26 @@ using MySqlConnector;
using Dapper;
using System.Runtime.ExceptionServices;
using System.Reflection;
using CounterStrikeSharp.API.Modules.Cvars;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace WeaponPaints;
[MinimumApiVersion(54)]
[MinimumApiVersion(55)]
public class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig>
{
public override string ModuleName => "WeaponPaints";
public override string ModuleDescription => "Connector for web-based player chosen wepaon paints, and standalone for knife.";
public override string ModuleAuthor => "Nereziel";
public override string ModuleVersion => "0.9";
public override string ModuleVersion => "1.0";
public WeaponPaintsConfig Config { get; set; } = new();
private string DatabaseConnectionString = string.Empty;
private Uri GlobalShareApi = new Uri("https://weaponpaints.fun/api.php");
public bool IsMatchZy = false;
public int GlobalShareServerId = 0;
private DateTime[] commandCooldown = new DateTime[Server.MaxPlayers];
private Dictionary<ulong, Dictionary<nint, int>> gPlayerWeaponPaints = new();
private Dictionary<ulong, Dictionary<nint, int>> gPlayerWeaponSeed = new();
@@ -56,22 +61,24 @@ public class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig>
"weapon_cz75a", "weapon_revolver", "weapon_bayonet", "weapon_knife"
};
public override void Load(bool hotReload)
{
SetGlobalExceptionHandler();
if (!Config.GlobalShare)
{
BuildDatabaseConnectionString();
TestDatabaseConnection();
SetGlobalExceptionHandler();
//MySql = new MySqlDb(Config.DatabaseHost, Config.DatabaseUser, Config.DatabasePassword, Config.DatabaseName!, Config.DatabasePort);
}
RegisterListener<Listeners.OnEntitySpawned>(OnEntitySpawned);
RegisterListener<Listeners.OnClientPutInServer>(OnClientPutInServer);
RegisterListener<Listeners.OnClientDisconnect>(OnClientDisconnect);
RegisterListener<Listeners.OnMapStart>(OnMapStart);
RegisterEventHandler<EventPlayerSpawn>(OnPlayerSpawn);
if (Config.Additional.KnifeEnabled)
SetupMenus();
RegisterEventHandler<EventRoundStart>(OnRoundStart, HookMode.Pre);
RegisterEventHandler<EventItemPickup>(OnItemPickup, HookMode.Pre);
RegisterCommands();
if (hotReload)
{
OnMapStart(string.Empty);
Task.Run(async () =>
{
for (int i = 1; i <= Server.MaxPlayers; i++)
@@ -83,13 +90,21 @@ public class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig>
}
});
}
if (Config.Additional.KnifeEnabled)
SetupMenus();
RegisterCommands();
}
public void OnConfigParsed(WeaponPaintsConfig config)
{
if (!config.GlobalShare)
{
if (config.DatabaseHost.Length < 1 || config.DatabaseName.Length < 1 || config.DatabaseUser.Length < 1)
{
throw new Exception("You need to setup Database credentials in config!");
}
}
Config = config;
}
@@ -124,7 +139,6 @@ public class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig>
{
throw new Exception("Unknown mysql exception! " + ex.Message);
}
CheckDatabaseTables();
}
@@ -158,15 +172,15 @@ public class WeaponPaints : BasePlugin, IPluginConfig<WeaponPaintsConfig>
throw new Exception("Unknown mysql exception! " + ex.Message);
}
}
// TODO: fix for map which change mp_t_default_melee
/*private HookResult OnRoundPreStart(EventRoundPrestart @event, GameEventInfo info)
{
// TODO: fix for map which change mp_t_default_melee
/*private HookResult OnRoundPreStart(EventRoundPrestart @event, GameEventInfo info)
{
NativeAPI.IssueServerCommand("mp_t_default_melee \"\"");
NativeAPI.IssueServerCommand("mp_ct_default_melee \"\"");
return HookResult.Continue;
}
*/
public override void Unload(bool hotReload)
}
*/
public override void Unload(bool hotReload)
{
RemoveGlobalExceptionHandler();
base.Unload(hotReload);
@@ -183,28 +197,78 @@ public override void Unload(bool hotReload)
{
AppDomain.CurrentDomain.FirstChanceException -= this.GlobalExceptionHandler;
}
public void RegisterCommands()
private void RegisterCommands()
{
AddCommand($"css_{Config.Additional.CommandSkin}", "Skins info", (player, info) => { if (player == null) return; OnCommandWS(player, info); });
AddCommand($"css_{Config.Additional.CommandRefresh}", "Skins refresh", (player, info) => { if (player == null) return; OnCommandRefresh(player, info); });
if (Config.Additional.CommandKillEnabled) {
AddCommand($"css_{Config.Additional.CommandKill}", "kill yourself", (player, info) => {
if(player == null || !player.IsValid || !player.PlayerPawn.IsValid)
if (Config.Additional.CommandKillEnabled)
{
AddCommand($"css_{Config.Additional.CommandKill}", "kill yourself", (player, info) =>
{
if (player == null || !player.IsValid || !player.PlayerPawn.IsValid)
return;
player.PlayerPawn.Value.CommitSuicide(true, false);
});
}
}
private void IncompatibilityCheck()
{
// MatchZy
if (Directory.Exists(Path.GetDirectoryName(ModuleDirectory) + "/MatchZy"))
{
Console.WriteLine("[WeaponPaints] Incompatibility found: MatchZy");
IsMatchZy = true;
}
}
private void OnMapStart(string mapName)
{
if (!Config.Additional.KnifeEnabled) return;
// TODO
// needed for now
base.AddTimer(2.0f, () => {
AddTimer(2.0f, () =>
{
NativeAPI.IssueServerCommand("mp_t_default_melee \"\"");
NativeAPI.IssueServerCommand("mp_ct_default_melee \"\"");
IncompatibilityCheck();
});
if (Config.GlobalShare)
GlobalShareConnect();
}
private void GlobalShareConnect()
{
if (!Config.GlobalShare) return;
var values = new Dictionary<string, string>
{
{ "server_address", $"{ConVar.Find("ip")!.StringValue}:{ConVar.Find("hostport")!.GetPrimitiveValue<int>().ToString()}" },
{ "server_hostname", ConVar.Find("hostname")!.StringValue }
};
using (var httpClient = new HttpClient())
{
httpClient.BaseAddress = GlobalShareApi;
var formContent = new FormUrlEncodedContent(values);
Task<HttpResponseMessage> responseTask = httpClient.PostAsync("", formContent);
responseTask.Wait();
HttpResponseMessage response = responseTask.Result;
if (response.IsSuccessStatusCode)
{
Task<string> responseBodyTask = response.Content.ReadAsStringAsync();
responseBodyTask.Wait();
string responseBody = responseBodyTask.Result;
GlobalShareServerId = Int32.Parse(responseBody);
}
else
{
throw new Exception("Unable to retrieve serverid from GlobalShare!");
}
}
Console.WriteLine("[WeaponPaints] GlobalShare ONLINE");
}
private void OnClientPutInServer(int playerSlot)
@@ -222,9 +286,9 @@ public override void Unload(bool hotReload)
{
CCSPlayerController player = Utilities.GetPlayerFromSlot(playerSlot);
if (!player.IsValid || player.IsBot) return;
// TODO: Clean up after player
if (Config.Additional.KnifeEnabled)
g_playersKnife.Remove(playerSlot+1);
g_playersKnife.Remove((int)player.EntityIndex!.Value.Value);
if (Config.Additional.SkinEnabled)
gPlayerWeaponPaints.Remove(new SteamID(player.SteamID).SteamId64);
}
@@ -237,19 +301,42 @@ public override void Unload(bool hotReload)
return HookResult.Continue;
}
if (Config.Additional.KnifeEnabled) {
GiveKnifeToPlayer(player);
AddTimer(0.1f, () => RefreshPlayerKnife(player));
}
if (Config.Additional.SkinVisibilityFix)
if (Config.Additional.KnifeEnabled)
{
// Check the best slot and set it. Weird solution but works xD
GiveKnifeToPlayer(player);
}
return HookResult.Continue;
}
private HookResult OnRoundStart(EventRoundStart @event, GameEventInfo info)
{
if (!IsMatchZy) return HookResult.Continue;
NativeAPI.IssueServerCommand("mp_t_default_melee \"\"");
NativeAPI.IssueServerCommand("mp_ct_default_melee \"\"");
return HookResult.Continue;
}
private HookResult OnItemPickup(EventItemPickup @event, GameEventInfo info)
{
if (@event.Defindex == 42 || @event.Defindex == 59)
{
CCSPlayerController player = @event.Userid;
if (player.IsValid && !player.IsBot && @event.Item == "knife")
{
if (g_playersKnife.ContainsKey((int)player.EntityIndex!.Value.Value)
&&
g_playersKnife[(int)player.EntityIndex!.Value.Value] != "weapon_knife")
{
RefreshPlayerKnife(player, true);
}
}
}
return HookResult.Continue;
}
private void OnEntitySpawned(CEntityInstance entity)
{
if (!Config.Additional.SkinEnabled) return;
@@ -264,7 +351,8 @@ public override void Unload(bool hotReload)
}
Server.NextFrame(() =>
{
try {
try
{
if (!weapon.IsValid) return;
if (weapon.OwnerEntity.Value == null) return;
if (!weapon.OwnerEntity.Value.EntityIndex.HasValue) return;
@@ -295,12 +383,14 @@ public override void Unload(bool hotReload)
var skeleton = GetSkeletonInstance(weapon.CBodyComponent.SceneNode);
skeleton.ModelState.MeshGroupMask = 2;
}
} catch(Exception) {}
}
catch (Exception) { }
});
}
public void GiveKnifeToPlayer(CCSPlayerController player)
public void GiveKnifeToPlayer(CCSPlayerController? player)
{
if (!Config.Additional.KnifeEnabled) return;
if (player == null || !player.IsValid) return;
if (g_playersKnife.TryGetValue((int)player.EntityIndex!.Value.Value, out var knife))
{
@@ -320,8 +410,9 @@ public override void Unload(bool hotReload)
}
}
}
public void RemoveKnifeFromPlayer(CCSPlayerController player)
public void RemoveKnifeFromPlayer(CCSPlayerController? player)
{
if (player == null || !player.IsValid || !player.PawnIsAlive) return;
var weapons = player.PlayerPawn.Value.WeaponServices!.MyWeapons;
foreach (var weapon in weapons)
{
@@ -336,69 +427,31 @@ public override void Unload(bool hotReload)
}
}
}
public void RefreshPlayerKnife(CCSPlayerController player)
public void RefreshPlayerKnife(CCSPlayerController? player, bool remove = false)
{
if (player == null || !player.IsValid || !player.PawnIsAlive) return;
if (remove == true)
RemoveKnifeFromPlayer(player);
AddTimer(0.2f, () =>
{
if (!player.IsValid || !player.PawnIsAlive) return;
if (!PlayerHasKnife(player))
GiveKnifeToPlayer(player);
});
if (Config.Additional.SkinVisibilityFix)
{
AddTimer(0.2f, () => NativeAPI.IssueClientCommand((int)player.EntityIndex!.Value.Value - 1, "slot3"));
AddTimer(0.32f, () => NativeAPI.IssueClientCommand((int)player.EntityIndex!.Value.Value - 1, "slot2"));
AddTimer(0.42f, () => NativeAPI.IssueClientCommand((int)player.EntityIndex!.Value.Value - 1, "slot1"));
AddTimer(0.3f, () => NativeAPI.IssueClientCommand((int)player.EntityIndex!.Value.Value - 1, "slot2"));
AddTimer(0.36f, () => NativeAPI.IssueClientCommand((int)player.EntityIndex!.Value.Value - 1, "slot1"));
}
// Unused method, only for testing
// public void RefreshPlayerKnife(CCSPlayerController player)
// {
// if (!Config.Additional.KnifeEnabled) return;
// // if (!g_playersKnife.ContainsKey((int)player.EntityIndex!.Value.Value)) return;
// // if (!PlayerHasKnife(player))
// // player.GiveNamedItem((CsTeam)player.TeamNum == CsTeam.Terrorist ? "weapon_knife_t" : "weapon_knife");
// var weapons = player.PlayerPawn.Value.WeaponServices!.MyWeapons;
// foreach (var weapon in weapons)
// {
// if (weapon.IsValid && weapon.Value.IsValid)
// {
// //if (weapon.Value.AttributeManager.Item.ItemDefinitionIndex == 42 || weapon.Value.AttributeManager.Item.ItemDefinitionIndex == 59)
// if (weapon.Value.DesignerName.Contains("knife"))
// {
// weapon.Value.Remove();
// break;
// }
// }
// }
// weapons = player.PlayerPawn.Value.WeaponServices!.MyWeapons;
// foreach (var weapon in weapons)
// {
// if (weapon.IsValid && weapon.Value.IsValid)
// {
// //if (weapon.Value.AttributeManager.Item.ItemDefinitionIndex == 42 || weapon.Value.AttributeManager.Item.ItemDefinitionIndex == 59)
// if (weapon.Value.DesignerName.Contains("knife"))
// {
// var temp = weapon.Value;
// var steamId = new SteamID(player.SteamID);
// if (!gPlayerWeaponPaints.ContainsKey(steamId.SteamId64)) return;
// if (!gPlayerWeaponPaints[steamId.SteamId64].ContainsKey(temp.AttributeManager.Item.ItemDefinitionIndex)) return;
// //Log($"Apply on {weapon.DesignerName}({weapon.AttributeManager.Item.ItemDefinitionIndex}) paint {gPlayerWeaponPaints[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]} seed {gPlayerWeaponSeed[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]} wear {gPlayerWeaponWear[steamId.SteamId64][weapon.AttributeManager.Item.ItemDefinitionIndex]}");
// temp.AttributeManager.Item.ItemID = 16384;
// temp.AttributeManager.Item.ItemIDLow = 16384 & 0xFFFFFFFF;
// temp.AttributeManager.Item.ItemIDHigh = temp.AttributeManager.Item.ItemIDLow >> 32;
// temp.FallbackPaintKit = gPlayerWeaponPaints[steamId.SteamId64][temp.AttributeManager.Item.ItemDefinitionIndex];
// temp.FallbackSeed = gPlayerWeaponSeed[steamId.SteamId64][temp.AttributeManager.Item.ItemDefinitionIndex];
// temp.FallbackWear = gPlayerWeaponWear[steamId.SteamId64][temp.AttributeManager.Item.ItemDefinitionIndex];
// break;
// }
// }
// }
// }
public bool PlayerHasKnife(CCSPlayerController player)
}
public bool PlayerHasKnife(CCSPlayerController? player)
{
if (!Config.Additional.KnifeEnabled) return false;
if (!player.IsValid || !player.PawnIsAlive)
if (player == null || !player.IsValid || !player.PawnIsAlive)
{
return false;
}
@@ -427,11 +480,13 @@ public override void Unload(bool hotReload)
if (knifeTypes.TryGetValue(option.Text, out var knife))
{
g_playersKnife[(int)player.EntityIndex!.Value.Value] = knifeTypes[option.Text];
if (!string.IsNullOrEmpty(Config.Messages.ChosenKnifeMenu)) {
if (!string.IsNullOrEmpty(Config.Messages.ChosenKnifeMenu))
{
temp = $"{Config.Prefix} {Config.Messages.ChosenKnifeMenu}".Replace("{KNIFE}", option.Text);
player.PrintToChat(ReplaceTags(temp));
}
if (!string.IsNullOrEmpty(Config.Messages.ChosenKnifeMenuKill) && Config.Additional.CommandKillEnabled) {
if (!string.IsNullOrEmpty(Config.Messages.ChosenKnifeMenuKill) && Config.Additional.CommandKillEnabled)
{
temp = $"{Config.Prefix} {Config.Messages.ChosenKnifeMenuKill}";
player.PrintToChat(ReplaceTags(temp));
}
@@ -453,19 +508,25 @@ public override void Unload(bool hotReload)
if (player == null) return;
string temp = "";
int playerIndex = (int)player.EntityIndex!.Value.Value;
if (DateTime.UtcNow >= commandCooldown[playerIndex].AddSeconds(Config.CmdRefreshCooldownSeconds))
if (commandCooldown != null && DateTime.UtcNow >= commandCooldown[playerIndex].AddSeconds(Config.CmdRefreshCooldownSeconds))
{
commandCooldown[playerIndex] = DateTime.UtcNow;
Task.Run(async () => await GetWeaponPaintsFromDatabase(playerIndex));
if (Config.Additional.KnifeEnabled)
{
Task.Run(async () => await GetKnifeFromDatabase(playerIndex));
if (!string.IsNullOrEmpty(Config.Messages.SuccessRefreshCommand)) {
RemoveKnifeFromPlayer(player);
AddTimer(0.2f, () => GiveKnifeToPlayer(player));
}
if (!string.IsNullOrEmpty(Config.Messages.SuccessRefreshCommand))
{
temp = $"{Config.Prefix} {Config.Messages.SuccessRefreshCommand}";
player.PrintToChat(ReplaceTags(temp));
}
return;
}
if (!string.IsNullOrEmpty(Config.Messages.CooldownRefreshCommand)) {
if (!string.IsNullOrEmpty(Config.Messages.CooldownRefreshCommand))
{
temp = $"{Config.Prefix} {Config.Messages.CooldownRefreshCommand}";
player.PrintToChat(ReplaceTags(temp));
}
@@ -478,16 +539,19 @@ public override void Unload(bool hotReload)
string temp = "";
if (!string.IsNullOrEmpty(Config.Messages.WebsiteMessageCommand)) {
if (!string.IsNullOrEmpty(Config.Messages.WebsiteMessageCommand))
{
temp = $"{Config.Prefix} {Config.Messages.WebsiteMessageCommand}";
player.PrintToChat(ReplaceTags(temp));
}
if (!string.IsNullOrEmpty(Config.Messages.SynchronizeMessageCommand)) {
if (!string.IsNullOrEmpty(Config.Messages.SynchronizeMessageCommand))
{
temp = $"{Config.Prefix} {Config.Messages.SynchronizeMessageCommand}";
player.PrintToChat(ReplaceTags(temp));
}
if (!Config.Additional.KnifeEnabled) return;
if (!string.IsNullOrEmpty(Config.Messages.KnifeMessageCommand)) {
if (!string.IsNullOrEmpty(Config.Messages.KnifeMessageCommand))
{
temp = $"{Config.Prefix} {Config.Messages.KnifeMessageCommand}";
player.PrintToChat(ReplaceTags(temp));
}
@@ -500,12 +564,61 @@ public override void Unload(bool hotReload)
private async Task GetWeaponPaintsFromDatabase(int playerIndex)
{
if (!Config.Additional.SkinEnabled) return;
try
{
CCSPlayerController player = Utilities.GetPlayerFromIndex(playerIndex);
if (player == null || !player.IsValid || player.IsBot) return;
var steamId = new SteamID(player.SteamID);
if (Config.GlobalShare)
{
var values = new Dictionary<string, string>
{
{ "server_id", GlobalShareServerId.ToString() },
{ "steamid", steamId.SteamId64.ToString() },
{ "skins", "1" }
};
UriBuilder builder = new UriBuilder(GlobalShareApi);
builder.Query = string.Join("&", values.Select(p => $"{Uri.EscapeDataString(p.Key)}={Uri.EscapeDataString(p.Value)}"));
using (var httpClient = new HttpClient())
{
httpClient.BaseAddress = GlobalShareApi;
var formContent = new FormUrlEncodedContent(values);
HttpResponseMessage response = await httpClient.GetAsync(builder.Uri);
if (response.IsSuccessStatusCode)
{
string responseBody = await response.Content.ReadAsStringAsync();
JArray jsonArray = JArray.Parse(responseBody);
if (jsonArray.Count > 0)
{
gPlayerWeaponPaints[steamId.SteamId64] = new Dictionary<nint, int>();
gPlayerWeaponWear[steamId.SteamId64] = new Dictionary<nint, float>();
gPlayerWeaponSeed[steamId.SteamId64] = new Dictionary<nint, int>();
foreach (var weapon in jsonArray)
{
int weaponDefIndex = weapon["weapon_defindex"].Value<int>();
int weaponPaintId = weapon["weapon_paint_id"].Value<int>();
float weaponWear = weapon["weapon_wear"].Value<float>();
int weaponSeed = weapon["weapon_seed"].Value<int>();
gPlayerWeaponPaints[steamId.SteamId64][weaponDefIndex] = weaponPaintId;
gPlayerWeaponWear[steamId.SteamId64][weaponDefIndex] = weaponWear;
gPlayerWeaponSeed[steamId.SteamId64][weaponDefIndex] = weaponSeed;
}
}
return;
}
else
{
return;
}
}
}
using (var connection = new MySqlConnection(DatabaseConnectionString))
{
await connection.OpenAsync();
@@ -553,6 +666,44 @@ public override void Unload(bool hotReload)
if (player == null || !player.IsValid || player.IsBot) return;
var steamId = new SteamID(player.SteamID);
if (Config.GlobalShare)
{
var values = new Dictionary<string, string>
{
{ "server_id", GlobalShareServerId.ToString() },
{ "steamid", steamId.SteamId64.ToString() },
{ "knife", "1" }
};
UriBuilder builder = new UriBuilder(GlobalShareApi);
builder.Query = string.Join("&", values.Select(p => $"{Uri.EscapeDataString(p.Key)}={Uri.EscapeDataString(p.Value)}"));
using (var httpClient = new HttpClient())
{
httpClient.BaseAddress = GlobalShareApi;
var formContent = new FormUrlEncodedContent(values);
HttpResponseMessage response = await httpClient.GetAsync(builder.Uri);
if (response.IsSuccessStatusCode)
{
string result = await response.Content.ReadAsStringAsync();
if (!string.IsNullOrEmpty(result))
{
g_playersKnife[playerIndex] = result;
}
else
{
return;
}
}
else
{
return;
}
}
return;
}
using (var connection = new MySqlConnection(DatabaseConnectionString))
{
await connection.OpenAsync();

View File

@@ -11,6 +11,7 @@
<PackageReference Include="CounterStrikeSharp.API" Version="*" />
<PackageReference Include="Dapper" Version="2.1.21" />
<PackageReference Include="MySqlConnector" Version="2.3.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
<ItemGroup>