Beispiel #1
0
        /// <summary>
        ///     Create and show mod compatibility error message
        /// </summary>
        private static void ShowModCompatibilityErrorMessage()
        {
            var panel = GUIManager.Instance.CreateWoodpanel(GUIManager.PixelFix.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f),
                                                            new Vector2(0f, 0f), 700, 500);

            panel.SetActive(true);
            var remote = new ModuleVersionData(lastServerVersion);
            var local  = new ModuleVersionData(GetEnforcableMods().ToList());


            var scroll = GUIManager.Instance.CreateScrollView(panel.transform, false, true, 8f, 10f, GUIManager.Instance.ValheimScrollbarHandleColorBlock,
                                                              new Color(0.1568628f, 0.1019608f, 0.0627451f, 1f), 650f, 400f);

            scroll.SetActive(true);

            GUIManager.Instance.CreateText("Remote version:", scroll.transform.Find("Scroll View/Viewport/Content"), new Vector2(0.5f, 0.5f),
                                           new Vector2(0.5f, 0.5f), new Vector2(0, 0), GUIManager.Instance.AveriaSerifBold, 19, GUIManager.Instance.ValheimOrange, true,
                                           new Color(0, 0, 0, 1), 600f, 40f, false);
            GUIManager.Instance.CreateText(remote.ToString(false), scroll.transform.Find("Scroll View/Viewport/Content"), new Vector2(0.5f, 0.5f),
                                           new Vector2(0.5f, 0.5f), new Vector2(0, 0), GUIManager.Instance.AveriaSerifBold, 19, Color.white, true, new Color(0, 0, 0, 1), 600f, 40f,
                                           false);
            GUIManager.Instance.CreateText("Local version:", scroll.transform.Find("Scroll View/Viewport/Content"), new Vector2(0.5f, 0.5f),
                                           new Vector2(0.5f, 0.5f), new Vector2(0, 0), GUIManager.Instance.AveriaSerifBold, 19, GUIManager.Instance.ValheimOrange, true,
                                           new Color(0, 0, 0, 1), 600f, 40f, false);
            GUIManager.Instance.CreateText(local.ToString(false), scroll.transform.Find("Scroll View/Viewport/Content"), new Vector2(0.5f, 0.5f),
                                           new Vector2(0.5f, 0.5f), new Vector2(0, 0), GUIManager.Instance.AveriaSerifBold, 19, Color.white, true, new Color(0, 0, 0, 1), 600f, 40f,
                                           false);

            foreach (var part in CreateErrorMessage(remote, local))
            {
                GUIManager.Instance.CreateText(part.Item2, scroll.transform.Find("Scroll View/Viewport/Content"), new Vector2(0.5f, 0.5f),
                                               new Vector2(0.5f, 0.5f), new Vector2(0, 0), GUIManager.Instance.AveriaSerifBold, 19, part.Item1, true, new Color(0, 0, 0, 1), 600f, 40f,
                                               false);
            }


            scroll.transform.Find("Scroll View").GetComponent <ScrollRect>().verticalNormalizedPosition = 1f;

            var button = GUIManager.Instance.CreateButton("OK", panel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, -215f));

            // Special condition, coming from ingame back into main scene
            button.GetComponent <Image>().pixelsPerUnitMultiplier = 2f;
            button.SetActive(true);

            button.GetComponent <Button>().onClick.AddListener(() =>
            {
                panel.SetActive(false);
                Object.Destroy(panel);
            });

            // Reset the last server version
            lastServerVersion = null;
        }
Beispiel #2
0
        // Hook RPC_PeerInfo to check in front of the original method
        private static void ZNet_RPC_PeerInfo(On.ZNet.orig_RPC_PeerInfo orig, ZNet self, ZRpc rpc, ZPackage pkg)
        {
            if (ZNet.instance.IsServerInstance() || ZNet.instance.IsLocalInstance())
            {
                try
                {
                    var clientVersion = new ModuleVersionData(clientVersions[rpc.GetSocket().GetEndPointString()]);
                    var serverVersion = new ModuleVersionData(GetEnforcableMods().ToList());

                    // Remove from list
                    clientVersions.Remove(rpc.GetSocket().GetEndPointString());

                    // Compare and disconnect when not equal
                    if (!clientVersion.Equals(serverVersion))
                    {
                        rpc.Invoke("Error", 3);
                        return;
                    }
                }
                catch (EndOfStreamException)
                {
                    Logger.LogError("Reading beyond end of stream. Probably client without Jotunn tried to connect.");

                    // Client did not send appended package, just disconnect with the incompatible version error
                    rpc.Invoke("Error", 3);
                    return;
                }
                catch (KeyNotFoundException ex)
                {
                    // Vanilla client trying to connect?
                    // Check mods, if there are some installed on the server which need also to be on the client

                    if (GetEnforcableMods().Any(x => x.Item3 == CompatibilityLevel.EveryoneMustHaveMod))
                    {
                        // There is a mod, which needs to be client side too
                        // Lets disconnect the vanilla client with Incompatible Version message

                        rpc.Invoke("Error", 3);
                        return;
                    }
                }
            }
            else
            {
                // If we got this far on client side, clear lastServerVersion again
                lastServerVersion = null;
            }

            // call original method
            orig(self, rpc, pkg);
        }
Beispiel #3
0
        /// <summary>
        ///     Store server's message.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="data"></param>
        private static void RPC_Jotunn_ReceiveVersionData(ZRpc sender, ZPackage data)
        {
            Logger.LogDebug($"Received Version package from {sender.m_socket.GetEndPointString()}");

            if (!ZNet.instance.IsClientInstance())
            {
                clientVersions[sender.m_socket.GetEndPointString()] = data;
                var clientVersion = new ModuleVersionData(clientVersions[sender.GetSocket().GetEndPointString()]);
                var serverVersion = new ModuleVersionData(GetEnforcableMods().ToList());

                if (!clientVersion.Equals(serverVersion))
                {
                    // Disconnect if mods are not network compatible
                    sender.Invoke("Error", 3);
                }
            }
            else
            {
                lastServerVersion = data;
            }
        }
Beispiel #4
0
        /// <summary>
        ///     Store server's message.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="data"></param>
        private static void RPC_Jotunn_ReceiveVersionData(ZRpc sender, ZPackage data)
        {
            Logger.LogDebug($"Received Version package from {sender.m_socket.GetEndPointString()}");

            if (!ZNet.instance.IsClientInstance())
            {
                ClientVersions[sender.m_socket.GetEndPointString()] = data;
                var serverData = new ModuleVersionData(GetEnforcableMods().ToList());
                var clientData = new ModuleVersionData(data);

                if (!CompareVersionData(serverData, clientData))
                {
                    // Disconnect if mods are not network compatible
                    Logger.LogWarning("RPC_Jotunn_ReceiveVersionData: Disconnecting modded client with incompatible version message. " +
                                      "Mods are not compatible");
                    sender.Invoke("Error", (int)ZNet.ConnectionStatus.ErrorVersion);
                }
            }
            else
            {
                LastServerVersion = data;
            }
        }
Beispiel #5
0
        private static bool ZNet_RPC_PeerInfo(ZNet __instance, ZRpc rpc, ZPackage pkg)
        {
            if (!ZNet.instance.IsClientInstance())
            {
                // Vanilla client trying to connect?
                if (!ClientVersions.ContainsKey(rpc.GetSocket().GetEndPointString()))
                {
                    // Check mods, if there are some installed on the server which need also to be on the client
                    if (GetEnforcableMods().Any(x => x.Item3 == CompatibilityLevel.EveryoneMustHaveMod || x.Item3 == CompatibilityLevel.ClientMustHaveMod))
                    {
                        // There is a mod, which needs to be client side too
                        // Lets disconnect the vanilla client with Incompatible Version message

                        Logger.LogWarning("Disconnecting vanilla client with incompatible version message. " +
                                          "There are mods that need to be installed on the client");
                        rpc.Invoke("Error", (int)ZNet.ConnectionStatus.ErrorVersion);
                        return(false);
                    }
                }
                else
                {
                    var serverData = new ModuleVersionData(GetEnforcableMods().ToList());
                    var clientData = new ModuleVersionData(ClientVersions[rpc.m_socket.GetEndPointString()]);

                    if (!CompareVersionData(serverData, clientData))
                    {
                        // Disconnect if mods are not network compatible
                        Logger.LogWarning("RPC_PeerInfo: Disconnecting modded client with incompatible version message. " +
                                          "Mods are not compatible");
                        rpc.Invoke("Error", (int)ZNet.ConnectionStatus.ErrorVersion);
                        return(false);
                    }
                }
            }

            return(true);
        }
Beispiel #6
0
        /// <summary>
        ///     Create the error message(s) from the server and client message data
        /// </summary>
        /// <param name="server">server data</param>
        /// <param name="client">client data</param>
        /// <returns></returns>
        private static IEnumerable <Tuple <Color, string> > CreateErrorMessage(ModuleVersionData server, ModuleVersionData client)
        {
            // Check Valheim version first
            if (server.ValheimVersion != client.ValheimVersion)
            {
                yield return(new Tuple <Color, string>(Color.red, "Valheim version error:"));

                if (server.ValheimVersion > client.ValheimVersion)
                {
                    yield return(new Tuple <Color, string>(Color.white, $"Please update your client to version {server.ValheimVersion}"));
                }

                if (server.ValheimVersion < client.ValheimVersion)
                {
                    yield return(new Tuple <Color, string>(Color.white,
                                                           $"The server you tried to connect runs {server.ValheimVersion}, which is lower than your version ({client.ValheimVersion})"));

                    yield return(new Tuple <Color, string>(Color.white, "Please contact the server admin for a server update." + Environment.NewLine));
                }
            }

            // And then each module
            foreach (var module in server.Modules)
            {
                // Check first for missing modules on the client side
                if (module.Item3 == CompatibilityLevel.EveryoneMustHaveMod)
                {
                    if (client.Modules.All(x => x.Item1 != module.Item1))
                    {
                        // client is missing needed module
                        yield return(new Tuple <Color, string>(Color.red, "Missing mod:"));

                        yield return(new Tuple <Color, string>(Color.white, $"Please install mod {module.Item1} v{module.Item2}" + Environment.NewLine));

                        continue;
                    }
                }

                // Then all version checks
                var clientModule = client.Modules.First(x => x.Item1 == module.Item1);

                // Major
                if (module.Item4 >= VersionStrictness.Major || clientModule.Item4 >= VersionStrictness.Major)
                {
                    if (module.Item2.Major > clientModule.Item2.Major)
                    {
                        foreach (var messageLine in ClientVersionLowerMessage(module))
                        {
                            yield return(messageLine);
                        }

                        continue;
                    }

                    if (module.Item2.Major < clientModule.Item2.Major)
                    {
                        foreach (var messageLine in ServerVersionLowerMessage(module, clientModule))
                        {
                            yield return(messageLine);
                        }

                        continue;
                    }

                    // Minor
                    if (module.Item4 >= VersionStrictness.Minor || clientModule.Item4 >= VersionStrictness.Minor)
                    {
                        if (module.Item2.Minor > clientModule.Item2.Minor)
                        {
                            foreach (var messageLine in ClientVersionLowerMessage(module))
                            {
                                yield return(messageLine);
                            }

                            continue;
                        }

                        if (module.Item2.Minor < clientModule.Item2.Minor)
                        {
                            foreach (var messageLine in ServerVersionLowerMessage(module, clientModule))
                            {
                                yield return(messageLine);
                            }

                            continue;
                        }
                    }

                    // Patch
                    if (module.Item4 >= VersionStrictness.Patch || clientModule.Item4 >= VersionStrictness.Patch)
                    {
                        if (module.Item2.Build > clientModule.Item2.Build)
                        {
                            foreach (var messageLine in ClientVersionLowerMessage(module))
                            {
                                yield return(messageLine);
                            }

                            continue;
                        }

                        if (module.Item2.Build < clientModule.Item2.Build)
                        {
                            foreach (var messageLine in ServerVersionLowerMessage(module, clientModule))
                            {
                                yield return(messageLine);
                            }
                        }
                    }
                }
            }

            // Now lets find additional modules with NetworkCompatibility attribute in the client's list
            foreach (var module in client.Modules.Where(x => x.Item3 == CompatibilityLevel.EveryoneMustHaveMod))
            {
                if (server.Modules.All(x => x.Item1 != module.Item1))
                {
                    yield return(new Tuple <Color, string>(Color.red, "Additional mod detected:"));

                    yield return(new Tuple <Color, string>(GUIManager.Instance.ValheimOrange,
                                                           $"Mod {module.Item1} v{module.Item2} is not installed on the server."));

                    yield return(new Tuple <Color, string>(Color.white, "Please consider uninstalling this mod." + Environment.NewLine));
                }
            }
        }
Beispiel #7
0
        /// <summary>
        ///     Create the error message(s) from the server and client message data
        /// </summary>
        /// <param name="serverData">server data</param>
        /// <param name="clientData">client data</param>
        /// <returns></returns>
        private static IEnumerable <Tuple <Color, string> > CreateErrorMessage(ModuleVersionData serverData, ModuleVersionData clientData)
        {
            // Check Valheim version first
            if (serverData.ValheimVersion != clientData.ValheimVersion)
            {
                yield return(new Tuple <Color, string>(Color.red, "Valheim version error:"));

                if (serverData.ValheimVersion > clientData.ValheimVersion)
                {
                    yield return(new Tuple <Color, string>(Color.white, $"Please update your client to version {serverData.ValheimVersion}"));
                }

                if (serverData.ValheimVersion < clientData.ValheimVersion)
                {
                    yield return(new Tuple <Color, string>(Color.white,
                                                           $"The server you tried to connect runs {serverData.ValheimVersion}, which is lower than your version ({clientData.ValheimVersion})"));

                    yield return(new Tuple <Color, string>(Color.white, "Please contact the server admin for a server update." + Environment.NewLine));
                }
            }

            // And then each module
            foreach (var serverModule in serverData.Modules)
            {
                // Check first for missing modules on the client side
                if (serverModule.Item3 == CompatibilityLevel.EveryoneMustHaveMod || serverModule.Item3 == CompatibilityLevel.ClientMustHaveMod)
                {
                    if (clientData.Modules.All(x => x.Item1 != serverModule.Item1))
                    {
                        // client is missing needed module
                        yield return(new Tuple <Color, string>(Color.red, "Missing mod:"));

                        yield return(new Tuple <Color, string>(Color.white, $"Please install mod {serverModule.Item1} v{serverModule.Item2}" + Environment.NewLine));

                        continue;
                    }

                    if (!clientData.Modules.Any(x => x.Item1 == serverModule.Item1 && x.Item3 == serverModule.Item3))
                    {
                        // module is there but mod compat level is lower
                        yield return(new Tuple <Color, string>(Color.red, "Compatibility level mismatch:"));

                        yield return(new Tuple <Color, string>(Color.white, $"Please update mod {serverModule.Item1} version v{serverModule.Item2}." + Environment.NewLine));

                        continue;
                    }
                }

                // Then all version checks
                var clientModule = clientData.Modules.FirstOrDefault(x => x.Item1 == serverModule.Item1);

#pragma warning disable CS0618 // Type or member is obsolete
                if (clientModule == null && (serverModule.Item3 == CompatibilityLevel.NotEnforced || serverModule.Item3 == CompatibilityLevel.NoNeedForSync))
                {
                    continue;
                }
#pragma warning restore CS0618 // Type or member is obsolete

#pragma warning disable CS0618 // Type or member is obsolete
                if (clientModule == null &&
                    (serverModule.Item3 == CompatibilityLevel.OnlySyncWhenInstalled ||
                     serverModule.Item3 == CompatibilityLevel.VersionCheckOnly ||
                     serverModule.Item3 == CompatibilityLevel.ServerMustHaveMod))
                {
                    continue;
                }
#pragma warning restore CS0618 // Type or member is obsolete

                // Major
                if (serverModule.Item4 >= VersionStrictness.Major || clientModule.Item4 >= VersionStrictness.Major)
                {
                    if (serverModule.Item2.Major > clientModule.Item2.Major)
                    {
                        foreach (var messageLine in ClientVersionLowerMessage(serverModule))
                        {
                            yield return(messageLine);
                        }

                        continue;
                    }

                    if (serverModule.Item2.Major < clientModule.Item2.Major)
                    {
                        foreach (var messageLine in ServerVersionLowerMessage(serverModule, clientModule))
                        {
                            yield return(messageLine);
                        }

                        continue;
                    }

                    // Minor
                    if (serverModule.Item4 >= VersionStrictness.Minor || clientModule.Item4 >= VersionStrictness.Minor)
                    {
                        if (serverModule.Item2.Minor > clientModule.Item2.Minor)
                        {
                            foreach (var messageLine in ClientVersionLowerMessage(serverModule))
                            {
                                yield return(messageLine);
                            }

                            continue;
                        }

                        if (serverModule.Item2.Minor < clientModule.Item2.Minor)
                        {
                            foreach (var messageLine in ServerVersionLowerMessage(serverModule, clientModule))
                            {
                                yield return(messageLine);
                            }

                            continue;
                        }
                    }

                    // Patch
                    if (serverModule.Item4 >= VersionStrictness.Patch || clientModule.Item4 >= VersionStrictness.Patch)
                    {
                        if (serverModule.Item2.Build > clientModule.Item2.Build)
                        {
                            foreach (var messageLine in ClientVersionLowerMessage(serverModule))
                            {
                                yield return(messageLine);
                            }

                            continue;
                        }

                        if (serverModule.Item2.Build < clientModule.Item2.Build)
                        {
                            foreach (var messageLine in ServerVersionLowerMessage(serverModule, clientModule))
                            {
                                yield return(messageLine);
                            }
                        }
                    }
                }
            }

            // Now lets find additional modules with NetworkCompatibility attribute in the client's list
            foreach (var clientModule in clientData.Modules.Where(x => x.Item3 == CompatibilityLevel.EveryoneMustHaveMod || x.Item3 == CompatibilityLevel.ServerMustHaveMod))
            {
                if (serverData.Modules.All(x => x.Item1 != clientModule.Item1))
                {
                    yield return(new Tuple <Color, string>(Color.red, "Additional mod detected:"));

                    yield return(new Tuple <Color, string>(GUIManager.Instance.ValheimOrange,
                                                           $"Mod {clientModule.Item1} v{clientModule.Item2} is not installed on the server."));

                    yield return(new Tuple <Color, string>(Color.white, "Please consider uninstalling this mod." + Environment.NewLine));

                    continue;
                }

                if (!serverData.Modules.Any(x => x.Item1 == clientModule.Item1 && x.Item3 == clientModule.Item3))
                {
                    yield return(new Tuple <Color, string>(Color.red, "Compatibility level mismatch:"));

                    yield return(new Tuple <Color, string>(Color.white, $"Please update mod {clientModule.Item1} version v{clientModule.Item2} on the server." + Environment.NewLine));

                    continue;
                }
            }
        }
Beispiel #8
0
        internal static bool CompareVersionData(ModuleVersionData serverData, ModuleVersionData clientData)
        {
            if (ReferenceEquals(serverData, clientData))
            {
                return(true);
            }

            if (!Equals(serverData.ValheimVersion, clientData.ValheimVersion))
            {
                return(false);
            }

            // Check server enforced mods
            foreach (var serverModule in serverData.Modules.Where(x => x.Item3 == CompatibilityLevel.EveryoneMustHaveMod || x.Item3 == CompatibilityLevel.ClientMustHaveMod))
            {
                if (!clientData.Modules.Any(x => x.Item1 == serverModule.Item1 && x.Item3 == serverModule.Item3))
                {
                    return(false);
                }
            }

            // Check client enforced mods
            foreach (var clientModule in clientData.Modules.Where(x => x.Item3 == CompatibilityLevel.EveryoneMustHaveMod || x.Item3 == CompatibilityLevel.ServerMustHaveMod))
            {
                if (!serverData.Modules.Any(x => x.Item1 == clientModule.Item1 && x.Item3 == clientModule.Item3))
                {
                    return(false);
                }
            }

            // Compare modules
            foreach (var serverModule in serverData.Modules)
            {
#pragma warning disable CS0618 // Type or member is obsolete
                if (serverModule.Item3 == CompatibilityLevel.NoNeedForSync || serverModule.Item3 == CompatibilityLevel.NotEnforced)
                {
                    continue;
                }
#pragma warning restore CS0618 // Type or member is obsolete

                var clientModule = clientData.Modules.FirstOrDefault(x => x.Item1 == serverModule.Item1);

#pragma warning disable CS0618 // Type or member is obsolete
                if (clientModule == null &&
                    (serverModule.Item3 == CompatibilityLevel.OnlySyncWhenInstalled ||
                     serverModule.Item3 == CompatibilityLevel.VersionCheckOnly ||
                     serverModule.Item3 == CompatibilityLevel.ServerMustHaveMod))
                {
                    continue;
                }
#pragma warning restore CS0618 // Type or member is obsolete

                if (clientModule == null)
                {
                    return(false);
                }

                if (serverModule.Item2.Major != clientModule.Item2.Major &&
                    (serverModule.Item4 >= VersionStrictness.Major || clientModule.Item4 >= VersionStrictness.Major))
                {
                    return(false);
                }

                if (serverModule.Item2.Minor != clientModule.Item2.Minor &&
                    (serverModule.Item4 >= VersionStrictness.Minor || clientModule.Item4 >= VersionStrictness.Minor))
                {
                    return(false);
                }

                if (serverModule.Item2.Build != clientModule.Item2.Build &&
                    (serverModule.Item4 >= VersionStrictness.Patch || clientModule.Item4 >= VersionStrictness.Patch))
                {
                    return(false);
                }
            }

            return(true);
        }