diff --git a/LobbyCompatibility/Enums/LobbyDiffResult.cs b/LobbyCompatibility/Enums/LobbyDiffResult.cs index 1e6266c..342988e 100644 --- a/LobbyCompatibility/Enums/LobbyDiffResult.cs +++ b/LobbyCompatibility/Enums/LobbyDiffResult.cs @@ -17,7 +17,12 @@ public enum LobbyDiffResult Incompatible, /// - /// Mod list does not exist, and lobby might be compatible. + /// Mod list is compatible, except for unknown mods. + /// + PresumedCompatible, + + /// + /// Mod list information is not available, server does not have LobbyCompatibility installed, or other unknown cause. /// Also applies to vanilla lobbies. /// Unknown diff --git a/LobbyCompatibility/Features/LobbyHelper.cs b/LobbyCompatibility/Features/LobbyHelper.cs index 91721fa..a594a42 100644 --- a/LobbyCompatibility/Features/LobbyHelper.cs +++ b/LobbyCompatibility/Features/LobbyHelper.cs @@ -13,12 +13,11 @@ namespace LobbyCompatibility.Features; /// internal static class LobbyHelper { - public static LobbyDiff LatestLobbyDiff { get; private set; } = new(new List()); public static Dictionary LatestLobbyRequestStringFilters = new(); public static LobbyDistanceFilter? LatestLobbyRequestDistanceFilter; - - private static Dictionary _lobbyDiffCache { get; set; } = new(); private static List? _clientPlugins; + public static LobbyDiff LatestLobbyDiff { get; private set; } = new(new List()); + private static Dictionary LobbyDiffCache { get; } = new(); /// /// Get a from a . @@ -35,7 +34,7 @@ internal static class LobbyHelper /// The . internal static LobbyDiff GetLobbyDiff(Lobby lobby, string? lobbyPluginString) { - if (_lobbyDiffCache.TryGetValue(lobby.Id, out var cachedLobbyDiff)) + if (LobbyDiffCache.TryGetValue(lobby.Id, out var cachedLobbyDiff)) return cachedLobbyDiff; var lobbyPlugins = PluginHelper @@ -106,10 +105,12 @@ internal static LobbyDiff GetLobbyDiff(Lobby lobby, string? lobbyPluginString) clientPlugin.Version, null)); } - LatestLobbyDiff = new LobbyDiff(pluginDiffs); + var lobbyCompatibilityPresent = lobbyPlugins.Any(); + + LatestLobbyDiff = new LobbyDiff(pluginDiffs, lobbyCompatibilityPresent); // Add to cache to avoid making multiple unnecessary GetData() calls - _lobbyDiffCache.Add(lobby.Id, LatestLobbyDiff); + LobbyDiffCache.Add(lobby.Id, LatestLobbyDiff); return LatestLobbyDiff; } @@ -151,17 +152,16 @@ public static string GetCompatibilityHeader(PluginDiffResult pluginDiffResult) /// A custom list of lobbies, with special search filters applied. /// The to filter the lobbies against. /// A array with the applied. - public static Lobby[] FilterLobbies(Lobby[] normalLobbies, Lobby[]? filteredLobbies, ModdedLobbyFilter currentFilter) + public static Lobby[] FilterLobbies(Lobby[] normalLobbies, Lobby[]? filteredLobbies, + ModdedLobbyFilter currentFilter) { List allLobbies = new(); if (filteredLobbies != null) - { // Remove duplicate "normal" lobbies if they were also caught by the hashfilter normalLobbies = normalLobbies .Where(lobby => !filteredLobbies.Any(check => lobby.Equals(check))) .ToArray(); - } if (currentFilter == ModdedLobbyFilter.VanillaAndUnknownOnly) { @@ -173,11 +173,13 @@ public static Lobby[] FilterLobbies(Lobby[] normalLobbies, Lobby[]? filteredLobb // Add only lobbies that are vanilla/unknown allLobbies.AddRange(FilterLobbiesByDiffResult(normalLobbies, LobbyDiffResult.Unknown)); } - else if (filteredLobbies != null && (currentFilter == ModdedLobbyFilter.CompatibleFirst || currentFilter == ModdedLobbyFilter.CompatibleOnly)) + else if (filteredLobbies != null && currentFilter is ModdedLobbyFilter.CompatibleFirst or ModdedLobbyFilter.CompatibleOnly) { // Lobbies returned by the hashfilter are not 100% going to always be compatible, so we'll still need to filter them - var (compatibleFilteredLobbies, otherFilteredLobbies) = SplitLobbiesByDiffResult(filteredLobbies, LobbyDiffResult.Compatible); - var (compatibleNormalLobbies, otherNormalLobbies) = SplitLobbiesByDiffResult(normalLobbies, LobbyDiffResult.Compatible); + var (compatibleFilteredLobbies, otherFilteredLobbies) = + SplitLobbiesByDiffResult(filteredLobbies, LobbyDiffResult.Compatible); + var (compatibleNormalLobbies, otherNormalLobbies) = + SplitLobbiesByDiffResult(normalLobbies, LobbyDiffResult.Compatible); // Add filtered lobbies that are 100% compatible first, then any extra compatible lobbies not caught by the hashfilter allLobbies.AddRange(compatibleFilteredLobbies); @@ -193,7 +195,7 @@ public static Lobby[] FilterLobbies(Lobby[] normalLobbies, Lobby[]? filteredLobb else if (filteredLobbies == null && currentFilter == ModdedLobbyFilter.CompatibleOnly) { // Handle the special case where we're sorting for compatible only and nothing comes up, so we need to force return nothing - allLobbies = new(); + allLobbies = new List(); } else { @@ -205,12 +207,17 @@ public static Lobby[] FilterLobbies(Lobby[] normalLobbies, Lobby[]? filteredLobb } /// - /// Splits a IEnumerable into two arrays based on of it matches or not. + /// Splits a IEnumerable into two arrays based on of it matches or + /// not. /// /// The lobbies. /// The to match against. - /// A tuple containing two IEnumerables. matchedLobbies contains the lobbies that match the LobbyDiffResult, and unmatchedLobbies contains everything else. - private static (IEnumerable matchedLobbies, IEnumerable unmatchedLobbies) SplitLobbiesByDiffResult(IEnumerable lobbies, LobbyDiffResult filteredLobbyDiffResult) + /// + /// A tuple containing two IEnumerables. matchedLobbies contains the lobbies that match the + /// LobbyDiffResult, and unmatchedLobbies contains everything else. + /// + private static (IEnumerable matchedLobbies, IEnumerable unmatchedLobbies) SplitLobbiesByDiffResult( + IEnumerable lobbies, LobbyDiffResult filteredLobbyDiffResult) { List matchedLobbies = new(); List unmatchedLobbies = new(); @@ -233,11 +240,14 @@ private static (IEnumerable matchedLobbies, IEnumerable unmatchedL /// The lobbies. /// The to match against. /// A filtered IEnumerable. - private static IEnumerable FilterLobbiesByDiffResult(IEnumerable lobbies, LobbyDiffResult filteredLobbyDiffResult) - => SplitLobbiesByDiffResult(lobbies, filteredLobbyDiffResult).matchedLobbies; + private static IEnumerable FilterLobbiesByDiffResult(IEnumerable lobbies, + LobbyDiffResult filteredLobbyDiffResult) + { + return SplitLobbiesByDiffResult(lobbies, filteredLobbyDiffResult).matchedLobbies; + } /// - /// Gets the error message for when no lobbies are found using a . + /// Gets the error message for when no lobbies are found using a . /// /// The to get the error message for. public static string GetEmptyLobbyListString(ModdedLobbyFilter moddedLobbyFilter) @@ -249,4 +259,4 @@ public static string GetEmptyLobbyListString(ModdedLobbyFilter moddedLobbyFilter _ => "No available servers to join." }; } -} +} \ No newline at end of file diff --git a/LobbyCompatibility/Features/PluginHelper.cs b/LobbyCompatibility/Features/PluginHelper.cs index 4ba4812..ebbe0cc 100644 --- a/LobbyCompatibility/Features/PluginHelper.cs +++ b/LobbyCompatibility/Features/PluginHelper.cs @@ -198,12 +198,15 @@ internal static bool MatchesTargetRequirements(IEnumerable tar } /// - /// Checks if client is allowed to join vanilla lobbies. + /// Checks if client is allowed to join vanilla or unknown lobbies. /// - /// True if client is allowed to join vanilla lobbies, false otherwise. + /// True if client is allowed to join vanilla or unknown lobbies, false otherwise. + /// This means the client is allowed to have unknown or clientside mods. internal static bool CanJoinVanillaLobbies() { - return GetAllPluginInfo().All(plugin => plugin.CompatibilityLevel is CompatibilityLevel.ClientOnly or null); + return GetAllPluginInfo().All(plugin => + plugin.CompatibilityLevel != CompatibilityLevel.Everyone && + plugin.CompatibilityLevel != CompatibilityLevel.ClientOptional); } /// @@ -284,4 +287,4 @@ private static string GetRequiredPluginsChecksum() return _cachedChecksum = stringBuilder.ToString(); } -} \ No newline at end of file +} diff --git a/LobbyCompatibility/Models/LobbyDiff.cs b/LobbyCompatibility/Models/LobbyDiff.cs index 1639a19..310d14f 100644 --- a/LobbyCompatibility/Models/LobbyDiff.cs +++ b/LobbyCompatibility/Models/LobbyDiff.cs @@ -8,7 +8,8 @@ namespace LobbyCompatibility.Models; /// Container for diffs between lobby and client plugins. /// /// The diffs between the lobby and client plugins. -public record LobbyDiff(List PluginDiffs) +/// Whether or not the lobby has this mod installed. +public record LobbyDiff(List PluginDiffs, bool LobbyCompatibilityPresent = true) { private LobbyDiffResult? _cachedResult; @@ -30,20 +31,18 @@ internal LobbyDiffResult GetModdedLobbyType() if (_cachedResult != null) return (LobbyDiffResult)_cachedResult; - if (PluginDiffs.Count == 0) - { - _cachedResult = LobbyDiffResult.Unknown; - return LobbyDiffResult.Unknown; - } + if (!LobbyCompatibilityPresent) + return (LobbyDiffResult)(_cachedResult = LobbyDiffResult.Unknown); + + var unknownFound = PluginDiffs.Any(pluginDiff => pluginDiff.PluginDiffResult == PluginDiffResult.Unknown); if (PluginDiffs.Any(pluginDiff => pluginDiff.PluginDiffResult != PluginDiffResult.Compatible && pluginDiff.PluginDiffResult != PluginDiffResult.Unknown)) - { - _cachedResult = LobbyDiffResult.Incompatible; - return LobbyDiffResult.Incompatible; - } + return (LobbyDiffResult)(_cachedResult = LobbyDiffResult.Incompatible); + + if (unknownFound) + return (LobbyDiffResult)(_cachedResult = LobbyDiffResult.PresumedCompatible); - _cachedResult = LobbyDiffResult.Compatible; - return LobbyDiffResult.Compatible; + return (LobbyDiffResult)(_cachedResult = LobbyDiffResult.Compatible); } } \ No newline at end of file