예제 #1
0
파일: ZNet.cs 프로젝트: fclante/VAC
        private static bool Prefix(ref ZNet __instance, ZRpc rpc, ZPackage pkg)
        {
            if (__instance.IsServer())
            {
                string self = "";
                if (pkg.Size() > 32)
                {
                    pkg.SetPos(pkg.Size() - 32 - 1);
                    if (pkg.ReadByte() == (byte)32)
                    {
                        pkg.SetPos(pkg.GetPos() - 1);
                        self = pkg.ReadString();
                    }
                }

                ZLog.Log((object)("[AntiMods]: Got client hash: " + self + "\nmine: " + VACPlugin.PluginsHash));
                ZLog.LogWarning("Plugins Hash is Equals: " + !self.Equals(VACPlugin.PluginsHash) + " ForceMods: " + VACPlugin.forcesamemods.Value);
                ZLog.LogWarning("Is in Admin List: " + !ZNet.instance.m_adminList.Contains(rpc.GetSocket().GetHostName()) + "Admin Bypass: "******"[AntiMods]: Kicking Client: " + rpc.GetSocket().GetEndPointString() + " (incompatible mods)"));
                    rpc.Invoke("Error", (object)num);
                    return(false);
                }

                ZLog.Log((object)("[AntiMods]: Accepting Client: " + rpc.GetSocket().GetEndPointString()));
            }
            return(true);
        }
예제 #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);
        }
 public static void CharacterUpdate(ZRpc rpc, ZPackage data)
 {
     // Are we the server? Update the character.
     if (ZNet.instance.IsServer())
     {
         Debug.Log("Client->Server CharacterUpdate");
         string   hostName      = rpc.GetSocket().GetHostName();
         ZNetPeer peer          = ZNet.instance.GetPeerByHostName(hostName);
         string   PlayerNameRaw = peer.m_playerName;
         string   PlayerName    = "";
         if (WorldofValheimServerSideCharacters.AllowMultipleCharacters.Value)
         {
             PlayerName = Regex.Replace(PlayerNameRaw, @"<[^>]*>", String.Empty);
         }
         else
         {
             PlayerName = "Single_Character_Mode";
         }
         string CharacterLocation = Util.GetCharacterPath(hostName, PlayerName);
         Debug.Log($"Saving character from SteamID {hostName}.");
         Util.WriteCharacter(CharacterLocation, Util.Decompress(data).GetArray());
         return;
     }
     // Are we the client? Send our character.
     Debug.Log("Server->Client CharacterUpdate");
     if (Player.m_localPlayer != null)
     {
         rpc.Invoke("CharacterUpdate", new object[]
         {
             Util.Compress(Game.instance.GetPlayerProfile().Serialize(Player.m_localPlayer, true))
         });
         return;
     }
 }
 public static IEnumerator Client2(ZRpc rpc)
 {
     rpc.Invoke("Client", new object[] {
         Client.Serialize(rpc.GetSocket().GetHostName())
     });
     yield return(new WaitForSeconds(1));
 }
 public static IEnumerator ZoneHandler2(ZRpc rpc)
 {
     rpc.Invoke("ZoneHandler", new object[] {
         ZoneHandler.Serialize(rpc.GetSocket().GetHostName())
     });
     yield return(new WaitForSeconds(1));
 }
예제 #6
0
        /// <summary>
        ///     Hook ZNet.RPC_PeerInfo on the server to send initial data
        /// </summary>
        /// <param name="self"></param>
        /// <param name="rpc"></param>
        /// <param name="__state"></param>
        private void ZNet_RPC_Pre_PeerInfo(ZNet self, ZRpc rpc, ref PeerInfoBlockingSocket __state)
        {
            PeerInfoBlockingSocket bufferingSocket = null;

            // Create buffering socket
            if (self.IsServer())
            {
                bufferingSocket = new PeerInfoBlockingSocket(rpc.GetSocket());
                rpc.m_socket    = bufferingSocket;
            }

            __state = bufferingSocket;
        }
예제 #7
0
        public static void RPC_UpdateInventory(ZRpc rpc, ZPackage pkg)
        {
            String characterName = pkg.ReadString();
            int    itemsCount    = pkg.ReadInt();

            String steamId = rpc.GetSocket().GetEndPointString();

            List <Server_ItemData> playerItems = new List <Server_ItemData>();

            for (int i = 0; i < itemsCount; i++)
            {
                Server_ItemData data = new Server_ItemData
                {
                    Name    = pkg.ReadString(),
                    Stack   = pkg.ReadInt(),
                    Quality = pkg.ReadInt(),
                    Variant = pkg.ReadInt()
                };

                playerItems.Add(data);
            }

            String dbId     = $"{steamId}_{characterName}";
            var    dbPlayer = Instance.DB.GetPlayerById(dbId);

            if (dbPlayer == null)
            {
                dbPlayer = new DBClasses.DBPlayer()
                {
                    DBPlayerId    = dbId,
                    SteamId       = steamId,
                    CharacterName = characterName,
                    Items         = new List <DBClasses.DBItem>()
                };

                foreach (var item in playerItems)
                {
                    dbPlayer.Items.Add(new DBClasses.DBItem()
                    {
                        ItemName = item.Name, PlayerId = dbPlayer.DBPlayerId, StackCount = item.Stack, Quality = item.Quality, Variant = item.Variant
                    });
                }

                Instance.DB.InsertPlayer(dbPlayer);
            }
            else
            {
                Instance.DB.UpdatePlayer(dbPlayer);
            }
        }
예제 #8
0
 private static void ZNet__SendPeerInfo(ZNet __instance, ZRpc rpc)
 {
     // Are we the client? Then get out!
     if (!__instance.IsServer())
     {
         return;
     }
     // Ok now that that's done. Lets gogogo Servers!
     Debug.Log("Server->Client CharacterData");
     rpc.Invoke("CharacterData", new object[] {
         Util.Compress(Util.LoadOrMakeCharacter(rpc.GetSocket().GetHostName()))
     });
     ServerState.Connections.Add(new ServerState.ConnectionData
     {
         rpc = rpc
     });
 }
 public static void ExitServer(ZRpc rpc, ZPackage data)
 {
     if (ZNet.instance.IsServer())
     {
         Debug.Log("Client->Server ExitServer");
         RPC.CharacterUpdate(rpc, data);
         rpc.Invoke("ExitServer", new object[]
         {
             new ZPackage()
         });
         Debug.Log($"Removing Client {rpc.GetSocket().GetHostName()} from our list");
         ServerState.Connections.RemoveAll((ServerState.ConnectionData conn) => conn.rpc.GetSocket() == rpc.GetSocket());
         Debug.Log("Connections " + ServerState.Connections.Count.ToString());
         return;
     }
     Debug.Log("Server->Client ExitServer");
     ServerState.Connections.RemoveAll((ServerState.ConnectionData conn) => conn.rpc.GetSocket() == rpc.GetSocket());
     ServerState.ClientCanDC = true;
 }
예제 #10
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;
            }
        }
예제 #11
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);
        }
예제 #12
0
            private static IEnumerator SendSettings(ZNet instance, ZRpc rpc, ZPackage pkg)
            {
                byte[] ArraySlice(byte[] source, int offset, int length)
                {
                    var target = new byte[length];

                    Buffer.BlockCopy(source, offset, target, 0, length);
                    return(target);
                }

                var peer = instance.GetPeers().First(p => p.m_rpc == rpc);

                if (!Settings.EnabledForThisWorld)
                {
                    Log($"Skipping sending settings to {PeerName(peer)}, as Better Continents is not enabled in this world");
                }
                else
                {
                    Log($"World is using Better Continents, so client version must match server version {ModInfo.Name}");

                    if (!ClientInfo.TryGetValue(peer.m_uid, out var bcClientInfo))
                    {
                        Log($"Client info for {PeerName(peer)} not found, client has an old version of Better Continents, or none!");
                        rpc.Invoke("Error", ZNet.ConnectionStatus.ErrorConnectFailed);
                        ZNet.instance.Disconnect(peer);
                        yield break;
                    }
                    else if (bcClientInfo.version != ModInfo.Version)
                    {
                        Log($"Client {PeerName(peer)} version {bcClientInfo.version} doesn't match server version {ModInfo.Version}");
                        peer.m_rpc.Invoke("Error", 69);
                        ZNet.instance.Disconnect(peer);
                        yield break;
                    }
                    else
                    {
                        Log($"Client {PeerName(peer)} version {bcClientInfo.version} matches server version {ModInfo.Version}");
                    }

                    // This was the initial way that versioning was implemented, before the client->server way, so may
                    // as well leave it in
                    Log($"Sending server version {ModInfo.Version} to client for bi-lateral version agreement");
                    rpc.Invoke("BetterContinentsVersion", ModInfo.Version);

                    var settingsPackage = new ZPackage();
                    var cleanSettings   = Settings.Clean();
                    cleanSettings.Serialize(settingsPackage);

                    if (WorldCache.CacheItemExists(settingsPackage, bcClientInfo.worldCache))
                    {
                        // We send hash and id
                        string cacheId = WorldCache.PackageID(settingsPackage);
                        Log($"Client {PeerName(peer)} already has cached settings for world, instructing it to load those (id {cacheId})");
                        rpc.Invoke("BetterContinentsConfigLoadFromCache", cacheId);
                    }
                    else
                    {
                        Log($"Client {PeerName(peer)} doesn't have cached settings, sending them now");
                        cleanSettings.Dump();

                        var settingsData = settingsPackage.GetArray();
                        Log($"Sending settings package header for {settingsData.Length} byte stream");
                        rpc.Invoke("BetterContinentsConfigStart", settingsData.Length, GetHashCode(settingsData));

                        const int SendChunkSize = 256 * 1024;

                        for (int sentBytes = 0; sentBytes < settingsData.Length;)
                        {
                            int packetSize = Mathf.Min(settingsData.Length - sentBytes, SendChunkSize);
                            var packet     = ArraySlice(settingsData, sentBytes, packetSize);
                            rpc.Invoke("BetterContinentsConfigPacket", sentBytes, GetHashCode(packet),
                                       new ZPackage(packet));
                            // Make sure to flush or we will saturate the queue...
                            rpc.GetSocket().Flush();
                            sentBytes += packetSize;
                            Log($"Sent {sentBytes} of {settingsData.Length} bytes");
                            float timeout = Time.time + 30;
                            yield return(new WaitUntil(() => rpc.GetSocket().GetSendQueueSize() < SendChunkSize || Time.time > timeout));

                            if (Time.time > timeout)
                            {
                                Log($"Timed out sending config to client {PeerName(peer)} after 30 seconds, disconnecting them");
                                peer.m_rpc.Invoke("Error", ZNet.ConnectionStatus.ErrorConnectFailed);
                                ZNet.instance.Disconnect(peer);
                                yield break;
                            }
                        }
                    }
                    yield return(new WaitUntil(() => ClientInfo[peer.m_uid].readyForPeerInfo || !peer.m_socket.IsConnected()));
                }

                RPC_PeerInfo(instance, rpc, pkg);
            }
예제 #13
0
        //CALLED ON SERVER, Should contain ZDOID and Inventory
        public static void RPC_CharacterIDX(ZRpc rpc, ZPackage pkg)
        {
            ZDOID characterID = pkg.ReadZDOID();

            ZNetPeer peer = (ZNetPeer)_GetPeerMethod.Invoke(ZNet.instance, new object[] { rpc });

            if (peer != null)
            {
                peer.m_characterID = characterID;
                if (Configs.ShowDebugMessages.Value)
                {
                    ZLog.Log($"Got character ZDOID with inventory from {peer.m_playerName} : {characterID}!");
                }
            }

            ZPackage inventoryPackage = pkg.ReadPackage();

            String characterName = inventoryPackage.ReadString();
            int    itemsCount    = inventoryPackage.ReadInt();

            String steamId = rpc.GetSocket().GetEndPointString();

            if (Configs.ShowDebugMessages.Value)
            {
                Instance.Logger.LogInfo($"Getting player {characterName}'s ({steamId}) inventory...");
            }

            List <Server_ItemData> playerItems = new List <Server_ItemData>();

            for (int i = 0; i < itemsCount; i++)
            {
                Server_ItemData data = new Server_ItemData
                {
                    Name    = inventoryPackage.ReadString(),
                    Stack   = inventoryPackage.ReadInt(),
                    Quality = inventoryPackage.ReadInt(),
                    Variant = inventoryPackage.ReadInt()
                };

                playerItems.Add(data);
            }

            if (Configs.ShowDebugMessages.Value)
            {
                Instance.Logger.LogInfo($"Found {playerItems.Count} items in {characterName}'s inventory.");
            }


            String dbId = $"{steamId}_{characterName}";

            var dbPlayer = Instance.DB.GetPlayerById(dbId);

            if (dbPlayer == null)
            {
                if (Configs.ShowDebugMessages.Value)
                {
                    Instance.Logger.LogInfo($"{characterName} is a new character!");
                }

                DBClasses.DBPlayer[] characters = Instance.DB.GetPlayersBySteamId(steamId);

                if (characters.Length >= Configs.MaxCharactersPerPlayer.Value)
                {
                    rpc.Invoke("Error", new object[] { (int)ZNet.ConnectionStatus.ErrorVersion });
                    return;
                }

                dbPlayer = new DBClasses.DBPlayer()
                {
                    DBPlayerId    = dbId,
                    SteamId       = steamId,
                    CharacterName = characterName,
                    Items         = new List <DBClasses.DBItem>()
                };

                foreach (var item in playerItems)
                {
                    dbPlayer.Items.Add(new DBClasses.DBItem()
                    {
                        ItemName = item.Name, PlayerId = dbPlayer.DBPlayerId, StackCount = item.Stack, Quality = item.Quality, Variant = item.Variant
                    });
                }

                Instance.DB.InsertPlayer(dbPlayer);
            }
            else
            {
                bool isSame = true;

                if (dbPlayer.Items.Count != playerItems.Count)
                {
                    isSame = false;
                }
                else
                {
                    for (int i = 0; i < dbPlayer.Items.Count; i++)
                    {
                        if (dbPlayer.Items[i].ItemName != playerItems[i].Name || dbPlayer.Items[i].StackCount != playerItems[i].Stack || dbPlayer.Items[i].Quality != playerItems[i].Quality || dbPlayer.Items[i].Variant != playerItems[i].Variant)
                        {
                            isSame = false;
                            break;
                        }
                    }
                }

                if (isSame)
                {
                    if (Configs.ShowDebugMessages.Value)
                    {
                        Instance.Logger.LogInfo($"{characterName} is still the same");
                    }
                    dbPlayer.LastLoggedIn = DateTime.Now;
                    Instance.DB.UpdatePlayer(dbPlayer);
                }
                else
                {
                    if (Configs.ShowDebugMessages.Value)
                    {
                        Instance.Logger.LogWarning($"{characterName} is NOT the same!");
                    }

                    rpc.Invoke("Error", new object[] { (int)ZNet.ConnectionStatus.ErrorVersion });
                }
            }
        }
예제 #14
0
        private static void RPC_ConsoleCommand(ZRpc rpc, string command)
        {
            if (!modEnabled.Value || !ZNet.instance.IsServer())
            {
                return;
            }

            ZNetPeer peer    = Traverse.Create(ZNet.instance).Method("GetPeer", new object[] { rpc }).GetValue <ZNetPeer>();
            var      steamID = (peer.m_socket as ZSteamSocket).GetPeerID();

            Dbgl($"RPC_ConsoleCommand received command {command} from {steamID}");
            if (!Traverse.Create(ZNet.instance).Field("m_adminList").GetValue <SyncedList>().Contains(rpc.GetSocket().GetHostName()))
            {
                Dbgl("User is not admin!");
                return;
            }

            var    parts  = command.Split(' ').Skip(1).ToArray();
            string result = "";

            if (parts[0] == "help")
            {
                result = "Usage:\r\n" +
                         "serverrewards list users\r\n" +
                         "serverrewards list packages\r\n" +
                         "serverrewards give <steamID> <currency>\r\n" +
                         "serverrewards give all <currency>\r\n" +
                         "serverrewards set <steamID> <currency>\r\n" +
                         "serverrewards set all <currency>\r\n" +
                         "serverrewards givepackage <steamID> <packageID>\r\n" +
                         "serverrewards givepackage all <packageID>\r\n" +
                         "serverrewards spawn <spawnName>";
            }
            else if (parts[0] == "list" && parts.Length == 2)
            {
                if (parts[1] == "users")
                {
                    List <string> userList = new List <string>();
                    List <string> users    = GetAllPlayerIDs();

                    var peerList = ZNet.instance.GetConnectedPeers();
                    foreach (string user in users)
                    {
                        string online = "(offline)";
                        var    tp     = peerList.Find(p => (p.m_socket as ZSteamSocket).GetPeerID().ToString() == user);
                        if (tp != null)
                        {
                            online = tp.m_playerName + " (online)";
                        }
                        userList.Add(user + " " + online);
                    }
                    result = string.Join("\r\n", userList);
                }
                else if (parts[1] == "packages")
                {
                    List <string> packageList = new List <string>();
                    var           packages    = GetAllPackages();
                    foreach (PackageInfo p in packages)
                    {
                        packageList.Add(p.id + " " + p.price);
                    }
                    result = string.Join("\r\n", packageList);
                }
                else
                {
                    result = "Syntax error.";
                }
            }
            else if (parts[0] == "give" && parts.Length == 3)
            {
                try
                {
                    string id = GetSteamID(parts[1]);
                    if (id == null)
                    {
                        result = "User not found.";
                    }
                    else if (AdjustCurrency(id, int.Parse(parts[2])))
                    {
                        result = "Balance adjusted.";
                    }
                    else
                    {
                        result = "Error adjusting player balance.";
                    }
                }
                catch
                {
                    result = "Syntax error.";
                }
            }
            else if (parts[0] == "set" && parts.Length == 3)
            {
                try
                {
                    string id = GetSteamID(parts[1]);
                    if (id == null)
                    {
                        result = "User not found.";
                    }
                    else if (SetCurrency(id, int.Parse(parts[2])))
                    {
                        result = "Balance set.";
                    }
                    else
                    {
                        result = "Error setting player balance.";
                    }
                }
                catch
                {
                    result = "Syntax error.";
                }
            }
            else if (parts[0] == "givepackage" && parts.Length == 3)
            {
                if (parts[1] == "all")
                {
                    IEnumerable <string> users = GetAllPlayerIDs();
                    int count = 0;
                    foreach (string user in users)
                    {
                        string r = GivePackage(parts[1], parts[2]);
                        if (r == null)
                        {
                            count++;
                        }
                    }
                    result = $"Package sent to {count} users!";
                }
                else
                {
                    string id = GetSteamID(parts[1]);
                    if (id == null)
                    {
                        result = "User not found.";
                    }
                    else
                    {
                        result = GivePackage(id, parts[2]);
                        if (result == null)
                        {
                            result = "Package sent!";
                        }
                    }
                }
            }
            else if (parts[0] == "spawn" && parts.Length == 2)
            {
                GameObject prefab = ZNetScene.instance.GetPrefab(parts[1]);
                if (!prefab)
                {
                    result = $"Item {parts[1]} not found!";
                }
                else
                {
                    var go = Instantiate(prefab, Player.m_localPlayer.transform.position + Player.m_localPlayer.transform.forward * 2f + Vector3.up, Quaternion.identity);
                    Player.m_localPlayer.Message(MessageHud.MessageType.TopLeft, string.Format(packageInfoString.Value, Localization.instance.Localize(go.GetComponent <ItemDrop>().m_itemData.m_shared.m_name)), 0, null);
                }
            }
            else
            {
                result = "Syntax error.";
            }
            JsonCommand sendCommand = new JsonCommand()
            {
                command = "SendConsoleString",
                data    = result
            };

            rpc.Invoke("SendServerRewardsJSON", new object[] { JsonUtility.ToJson(sendCommand) });
            Dbgl(result);
        }