diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 4f4ac00..10e0fe1 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -31,7 +31,6 @@ jobs:
dotnet publish ${{ env.PLUGIN_NAME }} -c "Release" -o "out/generic" -p:ContinuousIntegrationBuild=true --nologo
mkdir -p ./out/dist/${{ env.PLUGIN_NAME }}
cp ./out/generic/${{ env.PLUGIN_NAME }}.dll ./out/dist/${{ env.PLUGIN_NAME }}
- cp ./out/generic/ValveKeyValue.dll ./out/dist/${{ env.PLUGIN_NAME }}
- name: Create README
uses: docker://pandoc/core:3.1
diff --git a/CS2Interface/CS2Interface.csproj b/CS2Interface/CS2Interface.csproj
index 931f894..c0e809b 100644
--- a/CS2Interface/CS2Interface.csproj
+++ b/CS2Interface/CS2Interface.csproj
@@ -11,7 +11,6 @@
-
diff --git a/CS2Interface/Data/GameDataItems.cs b/CS2Interface/Data/GameDataItems.cs
index 3d7630c..a8f5211 100644
--- a/CS2Interface/Data/GameDataItems.cs
+++ b/CS2Interface/Data/GameDataItems.cs
@@ -1,16 +1,18 @@
using System;
+using System.Collections.Generic;
+using System.Linq;
using System.Threading.Tasks;
using ArchiSteamFarm.Core;
-using ValveKeyValue;
+using SteamKit2;
namespace CS2Interface {
internal class GameDataItems : GameDataResource {
- private KVObject? Data;
+ private KeyValue? Data;
internal GameDataItems(string url) : base(url) {}
internal async Task Update() {
- KVObject? data = await FetchKVResource().ConfigureAwait(false);
+ KeyValue? data = await FetchKVResource().ConfigureAwait(false);
if (data == null) {
ASF.ArchiLogger.LogGenericError(String.Format("Couldn't load game data from: {0}", Url));
@@ -23,22 +25,23 @@ internal async Task Update() {
return true;
}
- internal KVObject? this[string? key] {
+ internal List? this[string? key] {
get {
if (key == null || Data == null) {
return null;
}
- return Data.Search(key);
+ return Data.Children.Where(x => x.Name == key).SelectMany(x => x.Children).ToList();
}
}
- internal KVObject? GetDef(string value, string index, bool suppressErrorLogs = false) {
+ internal KeyValue? GetDef(string value, string index, bool suppressErrorLogs = false) {
if (Data == null) {
return null;
}
- var def = this[value]?[index];
+ KeyValue? def = this[value]?.Where(x => x.Name?.ToUpper().Trim() == index.ToUpper().Trim()).FirstOrDefault();
+
if (def == null) {
if (!suppressErrorLogs) {
ASF.ArchiLogger.LogGenericError(String.Format("Couldn't find definition: {0}[{1}]", value, index));
@@ -47,7 +50,7 @@ internal KVObject? this[string? key] {
return null;
}
- return new KVObject(value, def);
+ return def;
}
}
}
\ No newline at end of file
diff --git a/CS2Interface/Data/GameDataItemsCDN.cs b/CS2Interface/Data/GameDataItemsCDN.cs
index bbedb91..85ad8ab 100644
--- a/CS2Interface/Data/GameDataItemsCDN.cs
+++ b/CS2Interface/Data/GameDataItemsCDN.cs
@@ -25,7 +25,7 @@ internal async Task Update() {
internal string? this[string? key] {
get {
- if (key == null || Data == null) {
+ if (key == null || Data == null || !Data.ContainsKey(key)) {
return null;
}
diff --git a/CS2Interface/Data/GameDataResource.cs b/CS2Interface/Data/GameDataResource.cs
index 8e99a6f..914f351 100644
--- a/CS2Interface/Data/GameDataResource.cs
+++ b/CS2Interface/Data/GameDataResource.cs
@@ -3,7 +3,7 @@
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
-using ValveKeyValue;
+using SteamKit2;
namespace CS2Interface {
internal class GameDataResource {
@@ -14,12 +14,15 @@ internal GameDataResource(string url) {
Url = new Uri(url);
}
- protected async Task FetchKVResource(KVSerializerOptions? options = null) {
+ protected async Task FetchKVResource() {
HttpClient httpClient = new();
using (Stream response = await httpClient.GetStreamAsync(Url).ConfigureAwait(false)) {
- KVSerializer serializer = KVSerializer.Create(KVSerializationFormat.KeyValues1Text);
+ KeyValue kv = new KeyValue();
+ if (!kv.ReadAsText(response)) {
+ return null;
+ }
- return serializer.Deserialize(response, options);
+ return kv;
}
}
diff --git a/CS2Interface/Data/GameDataText.cs b/CS2Interface/Data/GameDataText.cs
index c0a3bba..256d002 100644
--- a/CS2Interface/Data/GameDataText.cs
+++ b/CS2Interface/Data/GameDataText.cs
@@ -1,23 +1,25 @@
using System;
+using System.Collections.Generic;
+using System.Linq;
using System.Threading.Tasks;
using ArchiSteamFarm.Core;
-using ValveKeyValue;
+using SteamKit2;
namespace CS2Interface {
internal class GameDataText : GameDataResource {
- private KVObject? Data;
+ private List? Data;
internal GameDataText(string url) : base(url) {}
internal async Task Update() {
- KVObject? data = (await FetchKVResource(new KVSerializerOptions { HasEscapeSequences = true, EnableValveNullByteBugBehavior = true }).ConfigureAwait(false))?.Search("Tokens");
+ KeyValue? data = await FetchKVResource().ConfigureAwait(false);
if (data == null) {
ASF.ArchiLogger.LogGenericError(String.Format("Couldn't load game data from: {0}", Url));
return false;
}
- Data = data;
+ Data = data.Children.Where(x => x.Name == "Tokens").SelectMany(x => x.Children).ToList();
Updated = true;
return true;
@@ -29,7 +31,7 @@ internal string? this[string? key] {
return null;
}
- return Data.SearchFirst(key)?.Value.ToString();
+ return Data.Where(x => x.Name?.ToUpper().Trim() == key.ToUpper().Trim()).FirstOrDefault()?.Value;
}
}
}
diff --git a/CS2Interface/Data/InventoryItem.cs b/CS2Interface/Data/InventoryItem.cs
index 60e24d1..9cd624e 100644
--- a/CS2Interface/Data/InventoryItem.cs
+++ b/CS2Interface/Data/InventoryItem.cs
@@ -1,10 +1,11 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Text;
using ArchiSteamFarm.Core;
using Newtonsoft.Json;
+using SteamKit2;
using SteamKit2.GC.CSGO.Internal;
-using ValveKeyValue;
namespace CS2Interface {
internal sealed class InventoryItem : Item {
@@ -90,7 +91,7 @@ private bool CanBeMoved() {
}
if (GetAttribute("cannot trade")?.ToUInt32() == 1
- || ItemData!.ItemDef.GetValue("attributes", "cannot trade")?.ToString() == "1"
+ || ItemData!.ItemDef.GetValue("attributes", "cannot trade") == "1"
) {
return false;
}
@@ -103,7 +104,7 @@ private bool CanBeMoved() {
// Apparently certain case keys can't be put in storage units? untested, might not be necessary
// https://github.com/nombersDev/casemove/blob/8289ea35cb6d76c553ee4955adecdf9a02622764/src/main/helpers/classes/steam/items/index.js#L506
// https://dev.doctormckay.com/topic/4086-inventory-and-music-kits/#comment-10610
- if (ItemInfo.flags == 10 && (ItemData!.ItemDef.GetValue("prefab")?.ToString() == "valve weapon_case_key" || ItemData!.ItemDef.GetValue("prefab")?.ToString() == "weapon_case_key")) {
+ if (ItemInfo.flags == 10 && (ItemData!.ItemDef.GetValue("prefab") == "valve weapon_case_key" || ItemData!.ItemDef.GetValue("prefab") == "weapon_case_key")) {
return false;
}
@@ -130,31 +131,27 @@ private bool ParseAttributes(List? attributes) {
}
foreach (CSOEconItemAttribute attribute in attributes) {
- KVObject? attribute_def = GameData.ItemsGame.GetDef("attributes", attribute.def_index.ToString());
+ KeyValue? attribute_def = GameData.ItemsGame.GetDef("attributes", attribute.def_index.ToString());
if (attribute_def == null) {
return false;
}
- string? attribute_name = attribute_def["name"].ToString();
+ string? attribute_name = attribute_def["name"].Value;
if (attribute_name == null) {
ASF.ArchiLogger.LogGenericError(String.Format("Missing name for attribute: {0}", attribute.def_index.ToString()));
return false;
}
- if (attribute_def["attribute_type"]?.ToString() == "vector") {
- ASF.ArchiLogger.LogGenericError(String.Format("zzzz vector for: {0}", attribute_name));
- }
-
- switch (attribute_def["attribute_type"]?.ToString()) {
+ switch (attribute_def["attribute_type"].Value) {
case "uint32":
- case null when attribute_def["stored_as_integer"]?.ToString() == "1":
- Attributes.Add(attribute_name, new Attribute(attribute_name, BitConverter.ToUInt32(attribute.value_bytes)));
+ case null when attribute_def["stored_as_integer"].Value == "1":
+ Attributes.Add(attribute_name, new Attribute(attribute_name, BitConverter.ToUInt32(attribute.value_bytes.ToArray(), 0)));
break;
case "float":
- case null when attribute_def["stored_as_integer"]?.ToString() == "0":
- Attributes.Add(attribute_name, new Attribute(attribute_name, BitConverter.ToSingle(attribute.value_bytes)));
+ case null when attribute_def["stored_as_integer"].Value == "0":
+ Attributes.Add(attribute_name, new Attribute(attribute_name, BitConverter.ToSingle(attribute.value_bytes.ToArray(), 0)));
break;
case "string":
@@ -163,7 +160,7 @@ private bool ParseAttributes(List? attributes) {
case "vector":
default:
- ASF.ArchiLogger.LogGenericError(String.Format("Unknown attribute type: {0}, value: {1}", attribute_def["attribute_type"].ToString(), Convert.ToBase64String(attribute.value_bytes)));
+ ASF.ArchiLogger.LogGenericError(String.Format("Unknown attribute type: {0}, value: {1}", attribute_def["attribute_type"].Value, Convert.ToBase64String(attribute.value_bytes)));
return false;
}
}
diff --git a/CS2Interface/Data/Item.cs b/CS2Interface/Data/Item.cs
index 018756b..bee1645 100644
--- a/CS2Interface/Data/Item.cs
+++ b/CS2Interface/Data/Item.cs
@@ -1,7 +1,7 @@
using System;
using System.Linq;
using Newtonsoft.Json;
-using ValveKeyValue;
+using SteamKit2;
namespace CS2Interface {
internal class Item {
@@ -117,7 +117,7 @@ internal static void SetSerializationProperties(bool should_serialize_additional
protected bool SetAdditionalProperties() {
try {
- ItemData = new(this);
+ ItemData = new ItemData(this);
} catch (Exception) {
GameData.Update(true);
@@ -126,25 +126,25 @@ protected bool SetAdditionalProperties() {
{ // Set rarity name, which differs based on the type of item
string locKey = "loc_key"; // General rarities
- if (ItemData.ItemDef.GetValue("taxonomy", "weapon")?.ToString() == "1") {
+ if (ItemData.ItemDef.GetValue("taxonomy", "weapon") == "1") {
locKey = "loc_key_weapon"; // Weapon skin rarities
- } else if (ItemData.ItemDef.GetValue("item_slot")?.ToString() == "customplayer") {
+ } else if (ItemData.ItemDef.GetValue("item_slot") == "customplayer") {
locKey = "loc_key_character"; // Agent rarities
}
- RarityName = GameData.CsgoEnglish[GameData.ItemsGame["rarities"]?.FirstOrDefault(x => (uint) x["value"] == Rarity)?[locKey].ToString()];
+ RarityName = GameData.CsgoEnglish[GameData.ItemsGame["rarities"]?.FirstOrDefault(x => x["value"].Value == Rarity.ToString())?[locKey].Value];
}
- TypeName = GameData.CsgoEnglish[ItemData.ItemDef.GetValue("item_type_name")?.ToString()?.Substring(1)];
- QualityName = GameData.CsgoEnglish[GameData.ItemsGame["qualities"]?.FirstOrDefault(x => (uint) x["value"] == Quality)?.Name];
+ TypeName = GameData.CsgoEnglish[ItemData.ItemDef.GetValue("item_type_name")?.Substring(1)];
+ QualityName = GameData.CsgoEnglish[GameData.ItemsGame["qualities"]?.FirstOrDefault(x => x["value"].Value == Quality.ToString())?.Name];
OriginName = GameData.GetOriginName(Origin);
// Set the item name, which will be something like: what kind of sticker it is, or the name of the weapon skin, or the type of pin/coin
// If an item has a wear value, but uses the default paint_kit (vanilla knives for example), this will be "-"
- ItemName = GameData.CsgoEnglish[(ItemData.MusicDef?.GetValue("loc_name") ?? ItemData.StickerKitDef?.GetValue("item_name") ?? ItemData.PaintKitDef?.GetValue("description_tag") ?? ItemData.ItemDef.GetValue("item_name"))?.ToString()?.Substring(1)];
+ ItemName = GameData.CsgoEnglish[(ItemData.MusicDef?.GetValue("loc_name") ?? ItemData.StickerKitDef?.GetValue("item_name") ?? ItemData.PaintKitDef?.GetValue("description_tag") ?? ItemData.ItemDef.GetValue("item_name"))?.Substring(1)];
// Set the tool named, used for various things like differentiating between Graffiti and Sealed Graffiti
- if (ItemData.ItemDef.GetValue("prefab")?.ToString() == "csgo_tool") {
- ToolName = GameData.CsgoEnglish[ItemData.ItemDef.GetValue("item_name")?.ToString()?.Substring(1)];
+ if (ItemData.ItemDef.GetValue("prefab") == "csgo_tool") {
+ ToolName = GameData.CsgoEnglish[ItemData.ItemDef.GetValue("item_name")?.Substring(1)];
}
// Set the graffiti color, ignore if tint_id is 0 (Multicolor)
@@ -153,8 +153,8 @@ protected bool SetAdditionalProperties() {
}
// Set various weapon-only attributes
- if (ItemData.ItemDef.GetValue("taxonomy", "weapon")?.ToString() == "1") {
- WeaponName = GameData.CsgoEnglish[ItemData.ItemDef.GetValue("item_name")?.ToString()?.Substring(1)];
+ if (ItemData.ItemDef.GetValue("taxonomy", "weapon") == "1") {
+ WeaponName = GameData.CsgoEnglish[ItemData.ItemDef.GetValue("item_name")?.Substring(1)];
if (Wear != null) {
WearName = GameData.GetWearName(Wear.Value);
@@ -165,9 +165,9 @@ protected bool SetAdditionalProperties() {
// Set the weapon image url
string? cdnNameID;
if (PaintIndex == 0) {
- cdnNameID = ItemData.ItemDef.GetValue("name")?.ToString(); // Vanilla Knives
+ cdnNameID = ItemData.ItemDef.GetValue("name"); // Vanilla Knives
} else {
- cdnNameID = String.Format("{0}_{1}", ItemData.ItemDef.GetValue("name")?.ToString(), ItemData.PaintKitDef!.GetValue("name")?.ToString()); // Everything else
+ cdnNameID = String.Format("{0}_{1}", ItemData.ItemDef.GetValue("name"), ItemData.PaintKitDef!.GetValue("name")); // Everything else
}
WeaponImageURL = GameData.ItemsGameCdn[cdnNameID];
}
@@ -190,29 +190,31 @@ protected bool SetAdditionalProperties() {
// Set the name id, used for determining related set and crate
if (PaintIndex == 0 && ItemData.StickerKitDef == null && ItemData.MusicDef == null) {
- NameID = ItemData.ItemDef.GetValue("name")?.ToString(); // Collectibles, Vanilla Knives
+ NameID = ItemData.ItemDef.GetValue("name"); // Collectibles, Vanilla Knives
} else {
- NameID = String.Format("[{0}]{1}", (ItemData.MusicDef ?? ItemData.StickerKitDef ?? ItemData.PaintKitDef)?.GetValue("name")?.ToString(), ItemData.ItemDef.GetValue("name")?.ToString()); // Everything else
+ NameID = String.Format("[{0}]{1}", (ItemData.MusicDef ?? ItemData.StickerKitDef ?? ItemData.PaintKitDef)?.GetValue("name"), ItemData.ItemDef.GetValue("name")); // Everything else
}
- { // Determine what set, if any, this item belongs to
- KVObject? setItemDef = GameData.ItemsGame["item_sets"]?.FirstOrDefault(x => x["items"][NameID] != null);
- if (setItemDef != null) {
- SetNameID = setItemDef.Name;
- SetName = GameData.CsgoEnglish[setItemDef["name"]?.ToString()?.Substring(1)];
+ if (NameID != null) {
+ { // Determine what set, if any, this item belongs to
+ KeyValue? setItemDef = GameData.ItemsGame["item_sets"]?.FirstOrDefault(x => x["items"][NameID] != KeyValue.Invalid);
+ if (setItemDef != null) {
+ SetNameID = setItemDef.Name;
+ SetName = GameData.CsgoEnglish[setItemDef["name"].Value?.Substring(1)];
+ }
}
- }
- { // Determine what crate, if any, this item belongs to. Doesn't work for souvenir skins, knives, or gloves
- string? lootListName = GameData.ItemsGame["client_loot_lists"]?.FirstOrDefault(x => x[NameID] != null)?.Name;
- lootListName = lootListName == null ? null : GameData.ItemsGame["client_loot_lists"]?.FirstOrDefault(x => x[lootListName] != null)?.Name ?? lootListName; // Some lists in client_loot_lists are nested (1 or 2 layers), we want the top-most layer
- string? lootListID = lootListName == null ? null : GameData.ItemsGame["revolving_loot_lists"]?.FirstOrDefault(x => x.Value.ToString() == lootListName)?.Name;
- KVObject? crateItemDef = lootListID == null ? null : GameData.ItemsGame["items"]?.FirstOrDefault(x => x["attributes"]?["set supply crate series"]?["value"]?.ToString() == lootListID);
- if (crateItemDef != null) {
- CrateNameID = crateItemDef["name"]?.ToString();
- CrateDefIndex = uint.Parse(crateItemDef.Name);
- CrateSupplySeries = uint.Parse(lootListID!);
- CrateName = GameData.CsgoEnglish[crateItemDef["item_name"]?.ToString()?.Substring(1)];
+ { // Determine what crate, if any, this item belongs to. Doesn't work for souvenir skins, knives, or gloves
+ string? lootListName = GameData.ItemsGame["client_loot_lists"]?.FirstOrDefault(x => x[NameID] != KeyValue.Invalid)?.Name;
+ lootListName = lootListName == null ? null : GameData.ItemsGame["client_loot_lists"]?.FirstOrDefault(x => x[lootListName] != KeyValue.Invalid)?.Name ?? lootListName; // Some lists in client_loot_lists are nested (1 or 2 layers), we want the top-most layer
+ string? lootListID = lootListName == null ? null : GameData.ItemsGame["revolving_loot_lists"]?.FirstOrDefault(x => x.Value == lootListName)?.Name;
+ KeyValue? crateItemDef = lootListID == null ? null : GameData.ItemsGame["items"]?.FirstOrDefault(x => x["attributes"]["set supply crate series"]["value"].Value == lootListID);
+ if (crateItemDef != null && crateItemDef.Name != null) {
+ CrateNameID = crateItemDef["name"].Value;
+ CrateDefIndex = uint.Parse(crateItemDef.Name);
+ CrateSupplySeries = uint.Parse(lootListID!);
+ CrateName = GameData.CsgoEnglish[crateItemDef["item_name"].Value?.Substring(1)];
+ }
}
}
diff --git a/CS2Interface/Data/ItemData.cs b/CS2Interface/Data/ItemData.cs
index db33ff7..cc65669 100644
--- a/CS2Interface/Data/ItemData.cs
+++ b/CS2Interface/Data/ItemData.cs
@@ -1,7 +1,7 @@
using System;
using ArchiSteamFarm.Core;
using Newtonsoft.Json;
-using ValveKeyValue;
+using SteamKit2;
namespace CS2Interface {
internal class ItemData {
@@ -33,7 +33,7 @@ private ItemDef CreateItemDef(Item item) {
ItemDef itemDef = new(GameData.ItemsGame.GetDef("items", item.DefIndex.ToString()));
// Add prefab values
- if (!MergePrefab(itemDef, itemDef.GetValue("prefab")?.ToString())) {
+ if (!MergePrefab(itemDef, itemDef.GetValue("prefab"))) {
throw new InvalidOperationException();
}
@@ -48,6 +48,8 @@ private bool MergePrefab(ItemDef itemDef, string? prefab) {
return true;
}
+ // STACK OVERFLOW HERE
+
// Some items have multiple prefabs separated by a space, but only one is valid (it has an entry in ItemsGame)
// Ex: "valve weapon_case_key": "valve" isn't valid, but "weapon_case_key" is
// Ex: "antwerp2022_sticker_capsule_prefab antwerp2022_sellable_item_with_payment_rules": "antwerp2022_sticker_capsule_prefab" is valid, but "antwerp2022_sellable_item_with_payment_rules" isn't
@@ -56,14 +58,14 @@ private bool MergePrefab(ItemDef itemDef, string? prefab) {
bool foundValid = false;
foreach (string prefabName in prefabNames) {
- KVObject? prefabDef = GameData.ItemsGame.GetDef("prefabs", prefabName, suppressErrorLogs: true);
+ KeyValue? prefabDef = GameData.ItemsGame.GetDef("prefabs", prefabName, suppressErrorLogs: true);
if (prefabDef == null) {
continue;
}
foundValid = true;
itemDef.AddDef(prefabDef);
- if (!MergePrefab(itemDef, prefabDef["prefab"]?.ToString())) {
+ if (!MergePrefab(itemDef, prefabDef["prefab"].Value)) {
return false;
};
}
diff --git a/CS2Interface/Data/ItemDef.cs b/CS2Interface/Data/ItemDef.cs
index 0c060f8..49162e9 100644
--- a/CS2Interface/Data/ItemDef.cs
+++ b/CS2Interface/Data/ItemDef.cs
@@ -2,18 +2,18 @@
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
-using ValveKeyValue;
+using SteamKit2;
namespace CS2Interface {
internal class ItemDef {
[JsonProperty(PropertyName = "defs", ItemConverterType = typeof(KVConverter))]
- internal List Defs = new();
+ internal List Defs = new();
- internal ItemDef(KVObject? def) {
+ internal ItemDef(KeyValue? def) {
AddDef(def);
}
- internal void AddDef(KVObject? def) {
+ internal void AddDef(KeyValue? def) {
if (def == null) {
throw new ArgumentNullException();
}
@@ -21,11 +21,11 @@ internal void AddDef(KVObject? def) {
Defs.Add(def);
}
- internal KVValue? GetValue(params string[] keys) {
- return GetValue(Defs, keys);
+ internal string? GetValue(params string[] keys) {
+ return GetValue(Defs, keys)?.Value;
}
- private KVValue? GetValue(IEnumerable defs, IEnumerable keys) {
+ private KeyValue? GetValue(IEnumerable defs, IEnumerable keys) {
if (defs.Count() == 0) {
return null;
}
@@ -33,10 +33,10 @@ internal void AddDef(KVObject? def) {
string key = keys.First();
if (keys.Count() == 1) {
- return defs.FirstOrDefault(def => def[key] != null)?[key];
+ return defs.FirstOrDefault(def => def[key] != KeyValue.Invalid)?[key];
}
- return GetValue(defs.Where(def => def[key] != null).Select(def => new KVObject(key, def[key])), keys.Skip(1).ToArray());
+ return GetValue(defs.Where(def => def[key] != KeyValue.Invalid).Select(def => def[key]), keys.Skip(1).ToArray());
}
}
}
\ No newline at end of file
diff --git a/CS2Interface/Helpers/KVConverter.cs b/CS2Interface/Helpers/KVConverter.cs
index 3c9e6ad..ceebb16 100644
--- a/CS2Interface/Helpers/KVConverter.cs
+++ b/CS2Interface/Helpers/KVConverter.cs
@@ -1,18 +1,19 @@
using System;
+using System.Globalization;
using ArchiSteamFarm.Core;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
-using ValveKeyValue;
+using SteamKit2;
namespace CS2Interface {
public sealed class KVConverter : JsonConverter {
public override bool CanConvert(Type objectType) {
- return objectType == typeof(KVObject);
+ return objectType == typeof(KeyValue);
}
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) {
JToken? json = null;
- if (value is KVObject vdf) {
+ if (value is KeyValue vdf) {
json = ConvertKVObjectToJson(vdf);
}
@@ -25,10 +26,14 @@ public override void WriteJson(JsonWriter writer, object? value, JsonSerializer
json.WriteTo(writer);
}
- private JToken? ConvertKVObjectToJson (KVObject vdf) {
- if (vdf.Value.ValueType == KVValueType.Collection) {
+ private JToken? ConvertKVObjectToJson (KeyValue vdf) {
+ if (vdf.Children.Count > 0) {
JObject json = new();
- foreach (KVObject child in vdf.Children) {
+ foreach (KeyValue child in vdf.Children) {
+ if (child.Name == null) {
+ continue;
+ }
+
try {
json.Add(child.Name, ConvertKVObjectToJson(child));
} catch (Exception e) {
@@ -40,14 +45,19 @@ public override void WriteJson(JsonWriter writer, object? value, JsonSerializer
return json;
}
- return vdf.Value.GetTypeCode() switch {
- TypeCode.Int32 => (int) vdf.Value,
- TypeCode.Int64 => (long) vdf.Value,
- TypeCode.UInt64 => vdf.Value.ToString(),
- TypeCode.Single => (float) vdf.Value,
- TypeCode.String => vdf.Value.ToString(),
- _ => null
- };
+ if (int.TryParse(vdf.Value, out int intValue)) {
+ return intValue;
+ }
+
+ if (long.TryParse(vdf.Value, out long longValue)) {
+ return longValue;
+ }
+
+ if (float.TryParse(vdf.Value, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out float floatValue)) {
+ return floatValue;
+ }
+
+ return vdf.Value;
}
public override bool CanRead {
diff --git a/CS2Interface/Helpers/UtilExtensions.cs b/CS2Interface/Helpers/UtilExtensions.cs
deleted file mode 100644
index 346c095..0000000
--- a/CS2Interface/Helpers/UtilExtensions.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using ValveKeyValue;
-
-namespace CS2Interface {
- public static class UtilExtensions {
- public static KVObject Search(this IEnumerable obj, string value) {
- var objs = obj.Where(x => x.Name.ToUpper().Trim() == value.ToUpper().Trim()).SelectMany(x => x.Children);
- var result = new KVObject(value, objs);
-
- return result;
- }
-
- public static KVObject? SearchFirst(this IEnumerable obj, string value) {
- return obj.Where(x => x.Name.ToUpper().Trim() == value.ToUpper().Trim()).FirstOrDefault();
- }
- }
-}
\ No newline at end of file
diff --git a/build.sh b/build.sh
index 6ec5aa0..151c28a 100755
--- a/build.sh
+++ b/build.sh
@@ -48,7 +48,6 @@ sync
dotnet publish CS2Interface -c "Release" -f net8.0 -o "out/generic" "/p:LinkDuringPublish=false"
mkdir ./out/$plugin_name
cp ./out/generic/$plugin_name.dll ./out/$plugin_name
-cp ./out/generic/ValveKeyValue.dll ./out/$plugin_name
if [[ -f "README.md" ]]; then
if ! command -v pandoc &> /dev/null; then
cp README.md ./out/$plugin_name