From d6882a5dd1f6266965616ca23962b9eebdf16018 Mon Sep 17 00:00:00 2001 From: zznty <94796179+zznty@users.noreply.github.com> Date: Tue, 8 Jul 2025 23:01:02 +0700 Subject: [PATCH] fix support for crossplay servers --- CringeBootstrap/CringeBootstrap.csproj | 5 + CringeBootstrap/packages.lock.json | 6 ++ .../Patches/BinaryFormatterPatch.cs | 97 +++++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 CringeLauncher/Patches/BinaryFormatterPatch.cs diff --git a/CringeBootstrap/CringeBootstrap.csproj b/CringeBootstrap/CringeBootstrap.csproj index d9be185..e41551e 100644 --- a/CringeBootstrap/CringeBootstrap.csproj +++ b/CringeBootstrap/CringeBootstrap.csproj @@ -12,12 +12,17 @@ true win-x64 + + + true + ..\icon.ico + diff --git a/CringeBootstrap/packages.lock.json b/CringeBootstrap/packages.lock.json index f8749e2..3f78833 100644 --- a/CringeBootstrap/packages.lock.json +++ b/CringeBootstrap/packages.lock.json @@ -8,6 +8,12 @@ "resolved": "5.3.4", "contentHash": "eMlf4Y0gx5KycV3cdptEocd9Y9h10fWhRVUKyuY9nF6a55eWJlpKHqCWQbgHjvbC/7cBfF8DsZG8dZbST2fpew==" }, + "System.Runtime.Serialization.Formatters": { + "type": "Direct", + "requested": "[9.0.6, )", + "resolved": "9.0.6", + "contentHash": "zm5backJELHp2RgdVA2LJd+Ydnsd0kkJd2/lNPTH9T8gIpzRKMKQgPMFH+1q/7IPlZu8wYL1ZeRqsVgHqmaC8g==" + }, "Velopack": { "type": "Direct", "requested": "[0.0.942, )", diff --git a/CringeLauncher/Patches/BinaryFormatterPatch.cs b/CringeLauncher/Patches/BinaryFormatterPatch.cs new file mode 100644 index 0000000..999b9c6 --- /dev/null +++ b/CringeLauncher/Patches/BinaryFormatterPatch.cs @@ -0,0 +1,97 @@ +using System.Formats.Nrbf; +using HarmonyLib; +using VRage.GameServices; + +namespace CringeLauncher.Patches; + +[HarmonyPatch] +public static class BinaryFormatterPatch +{ + [HarmonyPrefix] + [HarmonyPatch(typeof(MyInventoryHelper), nameof(MyInventoryHelper.CheckItemData))] + private static bool ReadInventoryItemsPrefix(byte[] checkData, out bool checkResult, out List __result) + { + __result = []; + if (!NrbfDecoder.StartsWithPayloadHeader(checkData)) + { + checkResult = false; + return false; + } + + var listRecord = NrbfDecoder.DecodeClassRecord(new MemoryStream(checkData)); + + if (!listRecord.TypeNameMatches(typeof(List)) || + listRecord.GetArrayRecord("_items") is not { } itemsRecord || + itemsRecord.GetArray(typeof(MyGameInventoryItem[]), false) is not SerializationRecord[] items) + { + checkResult = false; + return false; + } + + __result.Capacity = listRecord.GetInt32("_size"); + + foreach (var classRecord in items.OfType()) + { + if (!classRecord.TypeNameMatches(typeof(MyGameInventoryItem))) + continue; + + var itemDefinitionRecord = classRecord.GetClassRecord(PropertyName("ItemDefinition")); + if (itemDefinitionRecord is null || !itemDefinitionRecord.TypeNameMatches(typeof(MyGameInventoryItemDefinition))) + continue; + + var definitionTypeRecord = itemDefinitionRecord.GetClassRecord(PropertyName("DefinitionType")); + if (definitionTypeRecord is null || !definitionTypeRecord.TypeNameMatches(typeof(MyGameInventoryItemDefinitionType))) + continue; + + var itemSlotRecord = itemDefinitionRecord.GetClassRecord(PropertyName("ItemSlot")); + if (itemSlotRecord is null || !itemSlotRecord.TypeNameMatches(typeof(MyGameInventoryItemSlot))) + continue; + + var itemQualityRecord = itemDefinitionRecord.GetClassRecord(PropertyName("ItemQuality")); + if (itemQualityRecord is null || !itemQualityRecord.TypeNameMatches(typeof(MyGameInventoryItemQuality))) + continue; + + var itemDefinition = new MyGameInventoryItemDefinition + { + ID = itemDefinitionRecord.GetInt32(PropertyName("ID")), + Name = itemDefinitionRecord.GetString(PropertyName("Name")), + Tradable = itemDefinitionRecord.GetString(PropertyName("Tradable")), + Marketable = itemDefinitionRecord.GetString(PropertyName("Marketable")), + Description = itemDefinitionRecord.GetString(PropertyName("Description")), + IconTexture = itemDefinitionRecord.GetString(PropertyName("IconTexture")), + DisplayType = itemDefinitionRecord.GetString(PropertyName("DisplayType")), + AssetModifierId = itemDefinitionRecord.GetString(PropertyName("AssetModifierId")), + NameColor = itemDefinitionRecord.GetString(PropertyName("NameColor")), + BackgroundColor = itemDefinitionRecord.GetString(PropertyName("BackgroundColor")), + ToolName = itemDefinitionRecord.GetString(PropertyName("ToolName")), + IsStoreHidden = itemDefinitionRecord.GetBoolean(PropertyName("IsStoreHidden")), + Hidden = itemDefinitionRecord.GetBoolean(PropertyName("Hidden")), + CanBePurchased = itemDefinitionRecord.GetBoolean(PropertyName("CanBePurchased")), + Exchange = itemDefinitionRecord.GetString(PropertyName("Exchange")), + DefinitionType = (MyGameInventoryItemDefinitionType)definitionTypeRecord.GetInt32("value__"), + ItemSlot = (MyGameInventoryItemSlot)itemSlotRecord.GetInt32("value__"), + ItemQuality = (MyGameInventoryItemQuality)itemQualityRecord.GetInt32("value__") + }; + + var id = classRecord.GetUInt64(PropertyName("ID")); + var quantity = classRecord.GetUInt16(PropertyName("Quantity")); + var isStoreFakeItem = classRecord.GetBoolean(PropertyName("IsStoreFakeItem")); + var isNew = classRecord.GetBoolean(PropertyName("IsNew")); + + __result.Add(new MyGameInventoryItem + { + ID = id, + Quantity = quantity, + ItemDefinition = itemDefinition, + IsStoreFakeItem = isStoreFakeItem, + IsNew = isNew, + UsingCharacters = [] + }); + } + + checkResult = true; + return false; + } + + private static string PropertyName(string name) => $"<{name}>k__BackingField"; +} \ No newline at end of file