Skip to content

Commit fd1ab92

Browse files
authored
Update 2.4.0 (#174)
1 parent dde1890 commit fd1ab92

File tree

6 files changed

+166
-22
lines changed

6 files changed

+166
-22
lines changed
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"GiveNamedItem2": {
3+
"signatures": {
4+
"library": "server",
5+
"windows": "48 83 EC ? 48 C7 44 24 ? ? ? ? ? 45 33 C9 45 33 C0 C6 44 24 ? ? E8 ? ? ? ? 48 83 C4 ? C3 CC CC CC CC CC CC CC CC CC CC CC CC CC CC 48 83 EC",
6+
"linux": "55 48 89 E5 41 57 41 56 41 55 41 54 53 48 83 EC ? 48 89 7D ? 44 89 45"
7+
}
8+
}
9+
}

RetakesAllocator/CustomGameData.cs

+46-19
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,16 @@
11
using System.Runtime.InteropServices;
22
using CounterStrikeSharp.API;
33
using CounterStrikeSharp.API.Core;
4+
using RetakesAllocatorCore.Config;
5+
using RetakesAllocatorCore;
46
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
7+
using System.Text.Json;
58

69
namespace RetakesAllocator;
710

811
public class CustomGameData
912
{
10-
private static Dictionary<string, Dictionary<OSPlatform, string>> _customGameData = new()
11-
{
12-
// Thank you to @Whaliin https://github.com/CS2Plugins/WeaponRestrict/blob/main/WeaponRestrict.json
13-
{
14-
"GiveNamedItem2",
15-
new()
16-
{
17-
{
18-
OSPlatform.Windows,
19-
@"\x48\x83\xEC\x38\x48\xC7\x44\x24\x28\x00\x00\x00\x00\x45\x33\xC9\x45\x33\xC0\xC6\x44\x24\x20\x00\xE8\x2A\x2A\x2A\x2A\x48\x85"
20-
},
21-
{
22-
OSPlatform.Linux,
23-
@"\x55\x48\x89\xE5\x41\x57\x41\x56\x4D\x89\xC6\x41\x55\x49\x89\xD5\x41\x54\x49\x89\xF4"
24-
},
25-
}
26-
}
27-
};
28-
13+
public static Dictionary<string, Dictionary<OSPlatform, string>> _customGameData = new();
2914
private readonly MemoryFunctionVoid<IntPtr, string, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr> GiveNamedItem2;
3015

3116
public readonly
@@ -36,8 +21,50 @@ public readonly
3621

3722
public CustomGameData()
3823
{
24+
LoadCustomGameDataFromJson();
25+
3926
GiveNamedItem2 = new(GetCustomGameDataKey("GiveNamedItem2"));
4027
}
28+
public void LoadCustomGameDataFromJson()
29+
{
30+
string jsonFilePath = $"{Configs.Shared.Module}/../../plugins/RetakesAllocator/gamedata/RetakesAllocator_gamedata.json";
31+
if (!File.Exists(jsonFilePath))
32+
{
33+
Log.Debug($"JSON file does not exist at path: {jsonFilePath}. Returning without loading custom game data.");
34+
return;
35+
}
36+
37+
try
38+
{
39+
var jsonData = File.ReadAllText(jsonFilePath);
40+
var jsonDocument = JsonDocument.Parse(jsonData);
41+
42+
foreach (var element in jsonDocument.RootElement.EnumerateObject())
43+
{
44+
string key = element.Name;
45+
46+
var platformData = new Dictionary<OSPlatform, string>();
47+
48+
if (element.Value.TryGetProperty("signatures", out var signatures))
49+
{
50+
if (signatures.TryGetProperty("windows", out var windows))
51+
{
52+
platformData[OSPlatform.Windows] = windows.GetString()!;
53+
}
54+
55+
if (signatures.TryGetProperty("linux", out var linux))
56+
{
57+
platformData[OSPlatform.Linux] = linux.GetString()!;
58+
}
59+
}
60+
_customGameData[key] = platformData;
61+
}
62+
}
63+
catch (Exception ex)
64+
{
65+
Log.Debug($"Error loading custom game data: {ex.Message}");
66+
}
67+
}
4168

4269
private string GetCustomGameDataKey(string key)
4370
{

RetakesAllocator/Helpers.cs

+88
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using CounterStrikeSharp.API.Modules.Commands;
66
using CounterStrikeSharp.API.Modules.Entities.Constants;
77
using CounterStrikeSharp.API.Modules.Utils;
8+
using RetakesAllocatorCore.Config;
89
using RetakesAllocatorCore;
910

1011
namespace RetakesAllocator;
@@ -201,4 +202,91 @@ public static bool IsWindows()
201202
}
202203

203204
public static bool IsVip(CCSPlayerController player) => AdminManager.PlayerHasPermissions(player, "@css/vip");
205+
206+
public static async Task DownloadMissingFiles()
207+
{
208+
string baseFolderPath = Configs.Shared.Module!;
209+
210+
string gamedataFileName = "gamedata/RetakesAllocator_gamedata.json";
211+
string gamedataGithubUrl = "https://raw.githubusercontent.com/yonilerner/cs2-retakes-allocator/main/Resources/RetakesAllocator_gamedata.json";
212+
string gamedataFilePath = Path.Combine(baseFolderPath, gamedataFileName);
213+
string gamedataDirectoryPath = Path.GetDirectoryName(gamedataFilePath)!;
214+
await CheckAndDownloadFile(gamedataFilePath, gamedataGithubUrl, gamedataDirectoryPath);
215+
}
216+
217+
public static async Task<bool> CheckAndDownloadFile(string filePath, string githubUrl, string directoryPath)
218+
{
219+
if (!File.Exists(filePath))
220+
{
221+
if (!Directory.Exists(directoryPath))
222+
{
223+
Directory.CreateDirectory(directoryPath);
224+
}
225+
await DownloadFileFromGithub(githubUrl, filePath);
226+
return true;
227+
}
228+
else
229+
{
230+
if (Configs.GetConfigData().AutoUpdateSignatures)
231+
{
232+
bool isFileDifferent = await IsFileDifferent(filePath, githubUrl);
233+
if (isFileDifferent)
234+
{
235+
File.Delete(filePath);
236+
await DownloadFileFromGithub(githubUrl, filePath);
237+
return true;
238+
}
239+
}
240+
241+
}
242+
243+
return false;
244+
}
245+
246+
247+
public static async Task<bool> IsFileDifferent(string localFilePath, string githubUrl)
248+
{
249+
try
250+
{
251+
byte[] localFileBytes = await File.ReadAllBytesAsync(localFilePath);
252+
string localFileHash = GetFileHash(localFileBytes);
253+
254+
using (HttpClient client = new HttpClient())
255+
{
256+
byte[] githubFileBytes = await client.GetByteArrayAsync(githubUrl);
257+
string githubFileHash = GetFileHash(githubFileBytes);
258+
return localFileHash != githubFileHash;
259+
}
260+
}
261+
catch (Exception ex)
262+
{
263+
Log.Debug($"Error comparing files: {ex.Message}");
264+
return false;
265+
}
266+
}
267+
268+
public static string GetFileHash(byte[] fileBytes)
269+
{
270+
using (var md5 = System.Security.Cryptography.MD5.Create())
271+
{
272+
byte[] hashBytes = md5.ComputeHash(fileBytes);
273+
return BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
274+
}
275+
}
276+
277+
public static async Task DownloadFileFromGithub(string url, string destinationPath)
278+
{
279+
using (HttpClient client = new HttpClient())
280+
{
281+
try
282+
{
283+
byte[] fileBytes = await client.GetByteArrayAsync(url);
284+
await File.WriteAllBytesAsync(destinationPath, fileBytes);
285+
}
286+
catch (Exception ex)
287+
{
288+
Log.Debug($"Error downloading file: {ex.Message}");
289+
}
290+
}
291+
}
204292
}

RetakesAllocator/RetakesAllocator.cs

+16-2
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ public class RetakesAllocator : BasePlugin
4949

5050
public override void Load(bool hotReload)
5151
{
52+
Configs.Shared.Module = ModuleDirectory;
53+
5254
Log.Debug($"Loaded. Hot reload: {hotReload}");
5355
ResetState();
5456
Batteries.Init();
@@ -60,6 +62,11 @@ public override void Load(bool hotReload)
6062
RoundTypeManager.Instance.SetMap(mapName);
6163
});
6264

65+
_ = Task.Run(async () =>
66+
{
67+
await Helpers.DownloadMissingFiles();
68+
});
69+
6370
if (Configs.GetConfigData().UseOnTickFeatures)
6471
{
6572
RegisterListener<Listeners.OnTick>(OnTick);
@@ -949,7 +956,14 @@ private void AllocateItemsForPlayer(CCSPlayerController player, ICollection<CsIt
949956
continue;
950957
}
951958

952-
CustomFunctions?.PlayerGiveNamedItem(player, itemString);
959+
if(Configs.GetConfigData().CapabilityWeaponPaints)
960+
{
961+
CustomFunctions?.PlayerGiveNamedItem(player, itemString);
962+
}else
963+
{
964+
player.GiveNamedItem(itemString);
965+
}
966+
953967
var slotType = WeaponHelpers.GetSlotTypeForItem(item);
954968
if (slotType is not null)
955969
{
@@ -987,4 +1001,4 @@ private void GiveDefuseKit(CCSPlayerController player)
9871001
}
9881002

9891003
#endregion
990-
}
1004+
}

RetakesAllocatorCore/Config/Configs.cs

+6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ namespace RetakesAllocatorCore.Config;
88

99
public static class Configs
1010
{
11+
public static class Shared
12+
{
13+
public static string? Module { get; set; }
14+
}
1115
private static readonly string ConfigDirectoryName = "config";
1216
private static readonly string ConfigFileName = "config.json";
1317

@@ -229,6 +233,7 @@ public Dictionary<
229233
public bool ResetStateOnGameRestart { get; set; } = true;
230234
public bool AllowAllocationAfterFreezeTime { get; set; } = true;
231235
public bool UseOnTickFeatures { get; set; } = true;
236+
public bool CapabilityWeaponPaints { get; set; } = true;
232237
public bool EnableRoundTypeAnnouncement { get; set; } = true;
233238
public bool EnableRoundTypeAnnouncementCenter { get; set; } = false;
234239
public bool EnableBombSiteAnnouncementCenter { get; set; } = false;
@@ -270,6 +275,7 @@ public Dictionary<
270275

271276
public DatabaseProvider DatabaseProvider { get; set; } = DatabaseProvider.Sqlite;
272277
public string DatabaseConnectionString { get; set; } = "Data Source=data.db; Pooling=False";
278+
public bool AutoUpdateSignatures { get; set; } = true;
273279

274280
public IList<string> Validate()
275281
{

RetakesAllocatorCore/PluginInfo.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace RetakesAllocatorCore;
55

66
public static class PluginInfo
77
{
8-
public const string Version = "2.3.19";
8+
public const string Version = "2.4.0";
99

1010
public static readonly string LogPrefix = $"[RetakesAllocator {Version}] ";
1111

0 commit comments

Comments
 (0)