diff --git a/LobbyCompatibility/Features/LobbyHelper.cs b/LobbyCompatibility/Features/LobbyHelper.cs
index f4852e7..24017a9 100644
--- a/LobbyCompatibility/Features/LobbyHelper.cs
+++ b/LobbyCompatibility/Features/LobbyHelper.cs
@@ -20,10 +20,17 @@ internal static class LobbyHelper
///
/// The lobby to get the diff from.
/// The from the .
- public static LobbyDiff GetLobbyDiff(Lobby lobby)
+ public static LobbyDiff GetLobbyDiff(Lobby lobby) => GetLobbyDiff(GetLobbyPluginPages(lobby));
+
+ ///
+ /// Get a from a .
+ ///
+ /// The list of strings to parse.
+ /// The from the .
+ internal static LobbyDiff GetLobbyDiff(IEnumerable lobbyPluginStrings)
{
var lobbyPlugins = PluginHelper
- .ParseLobbyPluginsMetadata(lobby.GetData(LobbyMetadata.Plugins)).ToList();
+ .ParseLobbyPluginsMetadata(lobbyPluginStrings).ToList();
_clientPlugins ??= PluginHelper.GetAllPluginInfo().ToList();
var pluginDiffs = new List();
@@ -106,4 +113,20 @@ public static string GetCompatibilityHeader(PluginDiffResult pluginDiffResult)
_ => "Unknown"
};
}
+
+ ///
+ /// Get the plugin pages in from a .
+ ///
+ /// The to get the list from.
+ /// The from the .
+ internal static IEnumerable GetLobbyPluginPages(Lobby lobby)
+ {
+ string[] lobbyPluginStrings = [];
+ var i = 0;
+
+ do lobbyPluginStrings[i] = lobby.GetData($"{LobbyMetadata.Plugins}{i}");
+ while (lobbyPluginStrings[i++].Contains("@"));
+
+ return lobbyPluginStrings;
+ }
}
\ No newline at end of file
diff --git a/LobbyCompatibility/Features/PluginHelper.cs b/LobbyCompatibility/Features/PluginHelper.cs
index 478dbde..2784047 100644
--- a/LobbyCompatibility/Features/PluginHelper.cs
+++ b/LobbyCompatibility/Features/PluginHelper.cs
@@ -6,6 +6,7 @@
using LobbyCompatibility.Attributes;
using LobbyCompatibility.Enums;
using LobbyCompatibility.Models;
+using LobbyCompatibility.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
@@ -72,9 +73,9 @@ internal static IEnumerable GetAllPluginInfo()
/// Creates a json string containing the metadata of all plugins, to add to the lobby.
///
/// A json string containing the metadata of all plugins.
- public static string GetLobbyPluginsMetadata()
+ public static string[] GetLobbyPluginsMetadata()
{
- return JsonConvert.SerializeObject(GetAllPluginInfo().ToList(), new VersionConverter());
+ return LobbyCompatibilitySerializer.Serialize(GetAllPluginInfo());
}
///
@@ -82,11 +83,11 @@ public static string GetLobbyPluginsMetadata()
///
/// The json string to parse.
/// A list of plugins in the APIPluginInfo format.
- internal static IEnumerable ParseLobbyPluginsMetadata(string json)
+ internal static IEnumerable ParseLobbyPluginsMetadata(IEnumerable json)
{
try
{
- return JsonConvert.DeserializeObject>(json, new VersionConverter()) ??
+ return LobbyCompatibilitySerializer.Deserialize(json) ??
new List();
}
catch (Exception e)
diff --git a/LobbyCompatibility/Patches/LobbyDataIsJoinablePostfix.cs b/LobbyCompatibility/Patches/LobbyDataIsJoinablePostfix.cs
index 4dbe51d..0a245d1 100644
--- a/LobbyCompatibility/Patches/LobbyDataIsJoinablePostfix.cs
+++ b/LobbyCompatibility/Patches/LobbyDataIsJoinablePostfix.cs
@@ -1,3 +1,4 @@
+using System.Linq;
using HarmonyLib;
using LobbyCompatibility.Enums;
using LobbyCompatibility.Features;
@@ -34,20 +35,20 @@ private static bool Postfix(bool isJoinable, ref Lobby lobby)
return PluginHelper.CanJoinVanillaLobbies() && isJoinable;
}
- var lobbyPluginString = lobby.GetData(LobbyMetadata.Plugins);
-
+ var lobbyPluginStrings = LobbyHelper.GetLobbyPluginPages(lobby).ToArray();
+
// Create lobby diff so LatestLobbyDiff is set
- LobbyHelper.GetLobbyDiff(lobby);
+ LobbyHelper.GetLobbyDiff(lobbyPluginStrings);
// If the lobby does not have any plugin information, return original result (since we can't check anything)
- if (string.IsNullOrEmpty(lobbyPluginString))
+ if (lobbyPluginStrings.Length == 0 || string.IsNullOrEmpty(lobbyPluginStrings[0]))
{
LobbyCompatibilityPlugin.Logger?.LogWarning("Lobby is modded but does not have any plugin information.");
return isJoinable;
}
var matchesPluginRequirements =
- PluginHelper.MatchesTargetRequirements(PluginHelper.ParseLobbyPluginsMetadata(lobbyPluginString));
+ PluginHelper.MatchesTargetRequirements(PluginHelper.ParseLobbyPluginsMetadata(lobbyPluginStrings));
if (!matchesPluginRequirements)
{
diff --git a/LobbyCompatibility/Patches/SteamMatchmakingOnLobbyCreatedPostfix.cs b/LobbyCompatibility/Patches/SteamMatchmakingOnLobbyCreatedPostfix.cs
index 075a9d7..e1d6f23 100644
--- a/LobbyCompatibility/Patches/SteamMatchmakingOnLobbyCreatedPostfix.cs
+++ b/LobbyCompatibility/Patches/SteamMatchmakingOnLobbyCreatedPostfix.cs
@@ -29,8 +29,11 @@ private static void Postfix(Result result, ref Lobby lobby)
// Modded is flagged as true, since we're using mods
lobby.SetData(LobbyMetadata.Modded, "true");
- // Add plugin metadata to the lobby so clients can check if they have the required plugins
- lobby.SetData(LobbyMetadata.Plugins, PluginHelper.GetLobbyPluginsMetadata());
+ // Add paginated plugin metadata to the lobby so clients can check if they have the required plugins
+ var plugins = PluginHelper.GetLobbyPluginsMetadata();
+ // Add each page with delimiter if there's another page
+ for (var i = 0; i < plugins.Length; i++)
+ lobby.SetData($"{LobbyMetadata.Plugins}{i}", $"{plugins[i]}{(i < plugins.Length - 1 ? "@" : "")}");
// Set the joinable modded metadata to the same value as the original joinable metadata, in case it wasn't originally joinable
lobby.SetData(LobbyMetadata.JoinableModded, lobby.GetData(LobbyMetadata.Joinable));
diff --git a/LobbyCompatibility/Serialization/LobbyCompatibilitySerializer.cs b/LobbyCompatibility/Serialization/LobbyCompatibilitySerializer.cs
new file mode 100644
index 0000000..0ea0457
--- /dev/null
+++ b/LobbyCompatibility/Serialization/LobbyCompatibilitySerializer.cs
@@ -0,0 +1,125 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HarmonyLib;
+using LobbyCompatibility.Enums;
+using LobbyCompatibility.Models;
+
+namespace LobbyCompatibility.Serialization;
+
+public static class LobbyCompatibilitySerializer
+{
+ private const char PluginSeparator = '&';
+ private const char FieldSeparator = ';';
+
+ public static string[] Serialize(IEnumerable pluginInfoRecordList)
+ {
+ List allSerializedPlugins = [];
+ List separatedConcatStrings = [];
+
+ allSerializedPlugins.AddRange(pluginInfoRecordList.Select(Serialize));
+
+ var tempString = "";
+
+ foreach (var plugin in allSerializedPlugins)
+ {
+ if (tempString.Length + plugin.Length + 1 < 8192)
+ tempString += $"{(tempString.Length == 0 ? PluginSeparator : "")}{plugin}";
+ else
+ {
+ separatedConcatStrings.Add(tempString);
+ tempString = "";
+ }
+ }
+
+ return separatedConcatStrings.ToArray();
+ }
+
+ private static string Serialize(PluginInfoRecord pluginInfoRecord)
+ {
+ List serializedPluginInfo =
+ [
+ Serialize(pluginInfoRecord.GUID),
+ Serialize(pluginInfoRecord.Version),
+ Serialize(pluginInfoRecord.CompatibilityLevel),
+ Serialize(pluginInfoRecord.VersionStrictness)
+ ];
+
+ return serializedPluginInfo.Join(delimiter: FieldSeparator.ToString());
+ }
+
+ private static string Serialize(string pluginGuid) => pluginGuid;
+
+ private static string Serialize(Version version) => version.ToString();
+
+ private static string Serialize(CompatibilityLevel? compatibilityLevel)
+ {
+ return compatibilityLevel switch
+ {
+ CompatibilityLevel.ClientOnly => "c",
+ CompatibilityLevel.ServerOnly => "s",
+ CompatibilityLevel.Everyone => "e",
+ CompatibilityLevel.ClientOptional => "o",
+ _ => ""
+ };
+ }
+
+ private static string Serialize(VersionStrictness? versionStrictness)
+ {
+ return versionStrictness switch
+ {
+ VersionStrictness.None => "o",
+ VersionStrictness.Major => "m",
+ VersionStrictness.Minor => "n",
+ VersionStrictness.Patch => "p",
+ _ => ""
+ };
+ }
+
+ public static IEnumerable Deserialize(IEnumerable paginatedSerializedPlugins)
+ {
+ var serializedPluginList = paginatedSerializedPlugins.Join(delimiter: PluginSeparator.ToString()).Split(PluginSeparator);
+
+ return serializedPluginList.Select(DeserializePluginInfoRecord);
+ }
+
+ private static PluginInfoRecord DeserializePluginInfoRecord(string pluginInfoRecord)
+ {
+ var splitRecord = pluginInfoRecord.Split(FieldSeparator);
+
+ return new PluginInfoRecord(
+ DeserializeGuid(splitRecord[0]),
+ DeserializeVersion(splitRecord[1]),
+ DeserializeCompatibilityLevel(splitRecord[2]),
+ DeserializeVersionStrictness(splitRecord[3])
+ );
+ }
+
+ private static string DeserializeGuid(string pluginGuid) => pluginGuid;
+
+ private static Version DeserializeVersion(string version) => Version.Parse(version);
+
+ private static CompatibilityLevel? DeserializeCompatibilityLevel(string compatibilityLevel)
+ {
+ return compatibilityLevel switch
+ {
+ "c" => CompatibilityLevel.ClientOnly,
+ "s" => CompatibilityLevel.ServerOnly,
+ "e" => CompatibilityLevel.Everyone,
+ "o" => CompatibilityLevel.ClientOptional,
+ _ => null
+ };
+ }
+
+ private static VersionStrictness? DeserializeVersionStrictness(string versionStrictness)
+ {
+ return versionStrictness switch
+ {
+ "o" => VersionStrictness.None,
+ "m" => VersionStrictness.Major,
+ "n" => VersionStrictness.Minor,
+ "p" => VersionStrictness.Patch,
+ _ => null
+ };
+ }
+}
\ No newline at end of file