예제 #1
0
        private byte[] ReplaceIPAdresses(byte[] bytes)
        {
            // skip start information

            for (int k = 10; k < bytes.Length - 3; k++)
            {
                if (bytes[k] == 'K' &&
                    bytes[k + 1] == '0' &&
                    bytes[k + 2] == '4')
                {
                    if (bytes[k + 3] != 'W')
                    {
                        k--;
                    }

                    var nickLength = bytes[k + 4];

                    var nickStart = k + 4 + 3;
                    var nickEnd   = nickStart + (nickLength << 1);

                    var nick = GetUnicodeString(bytes, nickStart, nickEnd);

                    var stats = CoreContext.MasterServer.GetStatsInfo(nick);

                    var id = new CSteamID(stats.SteamId);

                    var pointStart = nickEnd + 7;

                    bytes[pointStart++] = 127;
                    bytes[pointStart++] = 0;
                    bytes[pointStart++] = 0;
                    bytes[pointStart++] = 1;



                    var port = PortBindingManager.AddOrUpdatePortBinding(id).Port;

                    CoreContext.OpenLogsService.Log($"Replace player port [{GetNickHash(nick)}] to {port}");

                    var portBytes = BitConverter.IsLittleEndian ? BitConverter.GetBytes(port).Reverse().ToArray() : BitConverter.GetBytes(port);

                    bytes[pointStart++] = portBytes[1];
                    bytes[pointStart++] = portBytes[0];

                    k += nickLength + 4 + 6;
                }
            }

            return(bytes);
        }
예제 #2
0
        private async Task <byte[]> HandleGamelobbyRequest(byte[] bytes)
        {
            var nicks = new List <string>();

            // skip start information
            for (int k = 10; k < bytes.Length - 3; k++)
            {
                if (bytes[k] == 'K' &&
                    bytes[k + 1] == '0' &&
                    bytes[k + 2] == '4')
                {
                    if (bytes[k + 3] != 'W')
                    {
                        k--;
                    }

                    var nickLength = bytes[k + 4];

                    var nickStart = k + 4 + 3;
                    var nickEnd   = nickStart + (nickLength << 1);

                    var nick = GetUnicodeString(bytes, nickStart, nickEnd);

                    if (!IdByNicksCache.ContainsKey(nick))
                    {
                        nicks.Add(GetUnicodeString(bytes, nickStart, nickEnd));
                    }

                    k += nickLength + 4 + 6;
                }
            }

            if (nicks.Count > 0)
            {
                await LoadSteamIds(nicks);
            }

            // skip start information
            for (int k = 50; k < bytes.Length - 3; k++)
            {
                if (bytes[k] == 'K' &&
                    bytes[k + 1] == '0' &&
                    bytes[k + 2] == '4')
                {
                    if (bytes[k + 3] != 'W')
                    {
                        k--;
                    }

                    var nickLength = bytes[k + 4];

                    var nickStart = k + 4 + 3;
                    var nickEnd   = nickStart + (nickLength << 1);

                    var nick = GetUnicodeString(bytes, nickStart, nickEnd);

                    if (IdByNicksCache.TryGetValue(nick, out CSteamID id))
                    {
                        var pointStart = nickEnd + 7;

                        bytes[pointStart++] = 127;
                        bytes[pointStart++] = 0;
                        bytes[pointStart++] = 0;
                        bytes[pointStart++] = 1;

                        var port      = PortBindingManager.AddOrUpdatePortBinding(id).Port;
                        var portBytes = BitConverter.IsLittleEndian ? BitConverter.GetBytes(port).Reverse().ToArray() : BitConverter.GetBytes(port);

                        bytes[pointStart++] = portBytes[1];
                        bytes[pointStart++] = portBytes[0];
                    }
                    else
                    {
                        throw new Exception("Unknown player nick - " + nick);
                    }

                    k += nickLength + 4 + 6;
                }
            }

            return(bytes);
        }
        /*public static ulong[] RegisteredIds => new ulong[]
         *  {
         *      76561198408785287ul, // Favelin
         *      76561198001658409ul, // elamaunt
         *      76561198064050301ul, // SunRay
         *      76561198137977374ul, // Anibus
         *
         *      76561198011215928ul, // Bukan1
         *      76561198005325871ul, // Bukan2
         *
         *      76561198858224000ul, // Igor_kocerev
         *      76561198233237924ul, // Flashbang
         *      76561198855597623ul, // onebillygrimm
         *      76561198856913976ul, // Jabka_X
         *      76561198174310885ul, // Mizopolak
         *      76561198842926724ul, // veloziraptor
         *      76561198098129338ul, // DAG05 Simon
         *      76561198021093802ul, // ki4a
         *      76561198072623723ul, // Master Yoba
         *      76561198137292489ul, // ZADGE
         *      76561198116829514ul, // Maugan Ra
         *      76561198036915935ul, // SorroWfuL LivED
         *      76561198143540732ul, // YbuBaKa
         *      76561198981516933ul, // Cg_JGHAMO
         *      76561198003604494ul, // Gigamok
         *      76561198360256453ul, // Gedeon
         *      76561198225092112ul, // vladirus
         *      76561198090267618ul, // deREXte
         *      76561198027618614ul, // Sm0kEZ
         *      76561198107179356ul, // Made in USSR
         *      76561198132447203ul, // Dolorosa
         *      76561198386642785ul  // Super_cega
         *  };*/

        private void OnRender(object sender, EventArgs e)
        {
            GameServer.RunCallbacks();
            SteamAPI.RunCallbacks();
            PortBindingManager.UpdateFrame();
        }
예제 #4
0
        public Task LaunchGameAndWait()
        {
            return(Task.Factory.StartNew(async() =>
            {
                ProcessManager.KillAllGameProccessesWithoutWindow();


                if (ProcessManager.GameIsRunning())
                {
                    throw new Exception("Game is running");
                }

                if (!PathFinder.IsPathFound())
                {
                    throw new Exception("Path to game not found in Steam");
                }

                IPHostEntry entry = null;


                try
                {
                    entry = Dns.GetHostEntry("gamespygp");
                }
                catch (Exception)
                {
                    FixHosts();
                }


                if (entry != null)
                {
                    var address = IPAddress.Parse(GameConstants.SERVER_ADDRESS);
                    if (!entry.AddressList.Any(x => x.Equals(address)))
                    {
                        FixHosts();
                    }
                }

                var tcs = new TaskCompletionSource <Process>();

                try
                {
                    Task.Factory.StartNew(() =>
                    {
                        while (!tcs.Task.IsCompleted)
                        {
                            GameServer.RunCallbacks();
                            SteamAPI.RunCallbacks();
                            PortBindingManager.UpdateFrame();
                            Thread.Sleep(5);
                        }
                    }, TaskCreationOptions.LongRunning);

                    var exeFileName = Path.Combine(LauncherPath, "GameFiles", "Patch1.2", "Soulstorm.exe");
                    var procParams = "-nomovies -forcehighpoly";
                    if (AppSettings.ThunderHawkModAutoSwitch)
                    {
                        procParams += " -modname ThunderHawk";
                    }

                    var ssProc = Process.Start(new ProcessStartInfo(exeFileName, procParams)
                    {
                        UseShellExecute = true,
                        WorkingDirectory = PathFinder.GamePath
                    });


                    ServerContext.Start(IPAddress.Any);

                    ssProc.EnableRaisingEvents = true;

                    Task.Run(() => RemoveFogLoop(tcs.Task, ssProc));

                    ssProc.Exited += (s, e) =>
                    {
                        tcs.TrySetResult(ssProc);
                    };
                }
                catch (Exception ex)
                {
                    Logger.Error(ex);
                    tcs.TrySetException(ex);
                }

                await tcs.Task;
                ServerContext.Stop();
            }).Unwrap());
        }
        private static byte[] PackServerList(SocketState state, IEnumerable <Data.GameServer> servers, string[] fields, bool isAutomatch)
        {
            IPEndPoint  remoteEndPoint = ((IPEndPoint)state.Socket.RemoteEndPoint);
            List <byte> data           = new List <byte>();

            data.AddRange(remoteEndPoint.Address.GetAddressBytes());

            byte[] value2 = BitConverter.GetBytes((ushort)remoteEndPoint.Port);
            data.AddRange(BitConverter.IsLittleEndian ? value2.Reverse() : value2);

            if (fields.Length == 1 && fields[0] == "\u0004")
            {
                fields = new string[0];
            }

            data.Add((byte)fields.Length);
            data.Add(0);

            foreach (var field in fields)
            {
                data.AddRange(Encoding.UTF8.GetBytes(field));
                data.AddRange(new byte[] { 0, 0 });
            }

            PortBindingManager.ClearPortBindings();

            foreach (var server in servers)
            {
                if (server.Properties.TryGetValue("gamename", out string gamename))
                {
                    if (isAutomatch && gamename != "whamdowfram")
                    {
                        continue;
                    }

                    if (!isAutomatch && gamename != "whamdowfr")
                    {
                        continue;
                    }
                }

                // commented this stuff out since it caused some issues on testing, might come back to it later and see what's happening...
                // NAT traversal stuff...
                // 126 (\x7E)	= public ip / public port / private ip / private port / icmp ip
                // 115 (\x73)	= public ip / public port / private ip / private port
                // 85 (\x55)	= public ip / public port
                // 81 (\x51)	= public ip / public port

                var    localip0  = server.Get <string>("localip0");
                ushort localport = ushort.Parse(server.Get <string>("localport") ?? "0");
                var    queryPort = (ushort)server.Get <int>("QueryPort");
                var    iPAddress = server.Get <string>("IPAddress");

                var retranslator = PortBindingManager.AddOrUpdatePortBinding(server.HostSteamId);

                retranslator.AttachedServer = server;

                ushort retranslationPort = retranslator.Port;



                var channelHash = ChatCrypt.PiStagingRoomHash("127.0.0.1", "127.0.0.1", retranslationPort);

                // start connection establishment
                SteamNetworking.SendP2PPacket(server.HostSteamId, new byte[] { 0 }, 1, EP2PSend.k_EP2PSendReliable, 1);

                IDByChannelCache[channelHash]        = server.HostSteamId;
                ChannelByIDCache[server.HostSteamId] = channelHash;

                var retranslationPortBytes = BitConverter.IsLittleEndian ? BitConverter.GetBytes(retranslationPort).Reverse() : BitConverter.GetBytes(retranslationPort);

                server["hostport"]  = retranslationPort.ToString();
                server["localport"] = retranslationPort.ToString();

                var flags = ServerFlags.UNSOLICITED_UDP_FLAG |
                            ServerFlags.PRIVATE_IP_FLAG |
                            ServerFlags.NONSTANDARD_PORT_FLAG |
                            ServerFlags.NONSTANDARD_PRIVATE_PORT_FLAG |
                            ServerFlags.HAS_KEYS_FLAG;

                var loopbackIpBytes = IPAddress.Loopback.GetAddressBytes();

                data.Add((byte)flags);
                data.AddRange(loopbackIpBytes);
                data.AddRange(retranslationPortBytes);
                data.AddRange(loopbackIpBytes);
                data.AddRange(retranslationPortBytes);

                data.Add(255);

                for (int i = 0; i < fields.Length; i++)
                {
                    var name = fields[i];
                    var f    = GetField(server, name);

                    data.AddRange(Encoding.UTF8.GetBytes(f));

                    if (i < fields.Length - 1)
                    {
                        data.Add(0);
                        data.Add(255);
                    }
                }

                data.Add(0);
            }

            data.Add(0);
            data.Add(255);
            data.Add(255);
            data.Add(255);
            data.Add(255);

            return(data.ToArray());
        }
예제 #6
0
        private unsafe void OnGameDataReceived(IAsyncResult async)
        {
            SocketState state = (SocketState)async.AsyncState;

            if (state == null || state.GameSocket == null || !state.GameSocket.Connected)
            {
                return;
            }

            try
            {
                // receive data from the socket
                int received = state.GameSocket.EndReceive(async);

                if (received == 0)
                {
                    return;
                }

                var buffer = state.GameBuffer;

                using (var ms = new MemoryStream(buffer, 0, received))
                {
                    if (!state.SendingEncoded)
                    {
                        using (var reader = new StreamReader(ms))
                        {
                            var asciValue = reader.ReadToEnd();

                            Log("CHATDATA", asciValue);

                            ms.Position = 0;

                            var line = reader.ReadLine();

                            if (line.StartsWith("CRYPT"))
                            {
                                state.SendingEncoded = true;

                                /*if (line.Contains("whammer40kdc"))
                                 * {
                                 *  Gamename = "whammer40kdc".ToAssciiBytes();
                                 *  Gamekey = "Ue9v3H".ToAssciiBytes();
                                 * }*/

                                if (line.Contains("whamdowfr"))
                                {
                                    Gamename = "whamdowfr".ToAssciiBytes();
                                    Gamekey  = "pXL838".ToAssciiBytes();
                                }

                                if (Gamekey == null)
                                {
                                    state.Dispose();
                                    return;
                                }

                                var chall = "0000000000000000".ToAssciiBytes();

                                var receivingGameKey   = new ChatCrypt.GDCryptKey();
                                var sendingGameKey     = new ChatCrypt.GDCryptKey();
                                var receivingServerKey = new ChatCrypt.GDCryptKey();
                                var sendingServerKey   = new ChatCrypt.GDCryptKey();

                                fixed(byte *challPtr = chall)
                                {
                                    fixed(byte *gamekeyPtr = Gamekey)
                                    {
                                        ChatCrypt.GSCryptKeyInit(receivingGameKey, challPtr, gamekeyPtr, Gamekey.Length);
                                        ChatCrypt.GSCryptKeyInit(sendingGameKey, challPtr, gamekeyPtr, Gamekey.Length);
                                        ChatCrypt.GSCryptKeyInit(receivingServerKey, challPtr, gamekeyPtr, Gamekey.Length);
                                        ChatCrypt.GSCryptKeyInit(sendingServerKey, challPtr, gamekeyPtr, Gamekey.Length);
                                    }
                                }

                                state.ReceivingGameKey   = receivingGameKey;
                                state.SendingGameKey     = sendingGameKey;
                                state.ReceivingServerKey = receivingServerKey;
                                state.SendingServerKey   = sendingServerKey;

                                // Send to server without encoding
                                _serverSocket.Send(buffer, received, SocketFlags.None);
                            }
                            else
                            {
                                // Send to server without encoding
                                _serverSocket.Send(buffer, received, SocketFlags.None);
                            }
                        }
                    }
                    else
                    {
                        using (var reader = new BinaryReader(ms, Encoding.ASCII))
                        {
                            var start = ms.Position;

                            var bytes = reader.ReadBytes((int)(ms.Length - ms.Position));

                            if (state.SendingEncoded)
                            {
                                byte *bytesPtr = stackalloc byte[bytes.Length];

                                for (int i = 0; i < bytes.Length; i++)
                                {
                                    bytesPtr[i] = bytes[i];
                                }

                                ChatCrypt.GSEncodeDecode(state.ReceivingGameKey, bytesPtr, bytes.Length);

                                for (int i = 0; i < bytes.Length; i++)
                                {
                                    bytes[i] = bytesPtr[i];
                                }
                            }

                            var utf8value = Encoding.UTF8.GetString(bytes);

                            Log("CHATDATA", utf8value);

                            if (utf8value.StartsWith("LOGIN", StringComparison.OrdinalIgnoreCase))
                            {
                                var nick = utf8value.Split(' ')[2];

                                ChatNick = nick;

                                SendToServerSocket(ref state, bytes);

                                goto CONTINUE;
                            }

                            if (utf8value.StartsWith("USRIP", StringComparison.OrdinalIgnoreCase))
                            {
                                SendToServerSocket(ref state, bytes);

                                goto CONTINUE;
                            }

                            var hostAddressIndex = utf8value.IndexOf(HOST_ADDRESS_TOKEN, StringComparison.OrdinalIgnoreCase);

                            if (hostAddressIndex != -1)
                            {
                                var port = CutPortValue(utf8value, hostAddressIndex + HOST_ADDRESS_TOKEN.Length, out string portString);

                                port = ByteHelpers.ReverseEndian16(port);

                                var hostSteamId = PortBindingManager.GetSteamIdByPort(port);

                                if (!hostSteamId.HasValue)
                                {
                                    port        = ByteHelpers.ReverseEndian16(port);
                                    hostSteamId = PortBindingManager.GetSteamIdByPort(port);
                                }

                                if (hostSteamId.HasValue)
                                {
                                    utf8value = utf8value.Replace(HOST_ADDRESS_TOKEN + portString, HOST_ADDRESS_TOKEN + hostSteamId.Value.m_SteamID);
                                }
                            }

                            var index = utf8value.IndexOf("#GSP!whamdowfr!", StringComparison.OrdinalIgnoreCase);

                            if (index != -1)
                            {
                                var encodedEndPoint = utf8value.Substring(index + 15, 10);

                                CSteamID steamId;

                                if (ServerListReport.CurrentUserRoomHash == encodedEndPoint)
                                {
                                    steamId = SteamUser.GetSteamID();
                                }
                                else
                                {
                                    if (!ServerListRetrieve.IDByChannelCache.TryGetValue(encodedEndPoint, out steamId))
                                    {
                                        ServerListReport.CurrentUserRoomHash = encodedEndPoint;
                                        steamId = SteamUser.GetSteamID();
                                    }
                                }

                                utf8value = utf8value.Replace(encodedEndPoint, steamId.m_SteamID.ToString());

                                SendToServerSocket(ref state, Encoding.UTF8.GetBytes(utf8value));

                                goto CONTINUE;
                            }

                            //  16777343 ~ 1.0.0.127  inversed port 63349 port
                            // :QWEQWE!X44vf1Wf1X|[email protected] PRIVMSG elamaunt :ACTION 7; 16777343; 63349; 16777343; 63349; 1;

                            SendToServerSocket(ref state, bytes);
                        }
                    }
                }
            }
            catch (ObjectDisposedException)
            {
                if (state != null)
                {
                    state.Dispose();
                }
                state = null;
                return;
            }
            catch (SocketException e)
            {
                switch (e.SocketErrorCode)
                {
                case SocketError.ConnectionReset:
                    if (state != null)
                    {
                        state.Dispose();
                    }
                    state = null;
                    return;

                case SocketError.Disconnecting:
                    if (state != null)
                    {
                        state.Dispose();
                    }
                    state = null;
                    return;

                default:
                    LogError(Category, "Error receiving data");
                    LogError(Category, String.Format("{0} {1}", e.SocketErrorCode, e));
                    if (state != null)
                    {
                        state.Dispose();
                    }
                    state = null;
                    return;
                }
            }
            catch (Exception e)
            {
                LogError(Category, "Error receiving data");
                LogError(Category, e.ToString());
            }

            // and we wait for more data...
            CONTINUE : WaitForGameData(state);
        }
예제 #7
0
        private unsafe void OnServerDataReceived(IAsyncResult async)
        {
            SocketState state = (SocketState)async.AsyncState;

            if (state == null || _serverSocket == null || !_serverSocket.Connected || state.GameSocket == null || !state.GameSocket.Connected)
            {
                return;
            }

            try
            {
                // receive data from the socket
                int received = _serverSocket.EndReceive(async);

                if (received == 0)
                {
                    return;
                }

                var bytes = new byte[received];

                for (int i = 0; i < received; i++)
                {
                    bytes[i] = state.ServerBuffer[i];
                }

                if (state.ReceivingEncoded)
                {
                    fixed(byte *bytesToSendPtr = bytes)
                    ChatCrypt.GSEncodeDecode(state.ReceivingServerKey, bytesToSendPtr, received);
                }

                var utf8value = Encoding.UTF8.GetString(bytes);

                Log(Category, utf8value);

                if (utf8value.StartsWith(":s 705", StringComparison.OrdinalIgnoreCase))
                {
                    SendToGameSocket(ref state, bytes);

                    state.ReceivingEncoded = true;
                    goto CONTINUE;
                }

                if (utf8value.IndexOf($@"UTM #GSP!whamdowfr!", StringComparison.OrdinalIgnoreCase) != -1)
                {
                    ProcessHelper.RestoreGameWindow();
                }

                if (utf8value.StartsWith("ROOMCOUNTERS", StringComparison.OrdinalIgnoreCase))
                {
                    var values = utf8value.Split(new string[] { "ROOMCOUNTERS", " ", "\r\n" }, StringSplitOptions.RemoveEmptyEntries);

                    for (int i = 0; i < ChatRoomPlayersCounts.Length; i++)
                    {
                        ChatRoomPlayersCounts[i] = 0;
                    }

                    for (int i = 0; i < values.Length; i += 2)
                    {
                        var roomIndex = values[i];
                        var count     = values[i + 1];

                        ChatRoomPlayersCounts[int.Parse(roomIndex) - 1] = int.Parse(count);
                    }
                    goto CONTINUE;
                }

                var index = utf8value.IndexOf("#GSP!whamdowfr!", StringComparison.OrdinalIgnoreCase);

                if (index != -1)
                {
                    int endIndex = index + 15;
                    for (; endIndex < utf8value.Length; endIndex++)
                    {
                        if (!char.IsDigit(utf8value[endIndex]))
                        {
                            break;
                        }
                    }

                    var stringSteamId = utf8value.Substring(index + 15, endIndex - index - 15);
                    var steamId       = new CSteamID(ulong.Parse(stringSteamId));

                    if (steamId != SteamUser.GetSteamID())
                    {
                        if (ServerListRetrieve.ChannelByIDCache.TryGetValue(steamId, out string roomHash))
                        {
                            utf8value = utf8value.Replace(stringSteamId, ServerListRetrieve.ChannelByIDCache[steamId]);
                        }
                        else
                        {
                            utf8value = utf8value.Replace(stringSteamId, ServerListReport.CurrentUserRoomHash);
                        }
                    }
                    else
                    {
                        utf8value = utf8value.Replace(stringSteamId, ServerListReport.CurrentUserRoomHash);
                    }

                    SendToGameSocket(ref state, Encoding.UTF8.GetBytes(utf8value));

                    goto CONTINUE;
                }

                var hostAddressIndex = utf8value.IndexOf(HOST_ADDRESS_TOKEN, StringComparison.OrdinalIgnoreCase);

                if (hostAddressIndex != -1)
                {
                    var steamIdValue = CutULongValue(utf8value, hostAddressIndex + HOST_ADDRESS_TOKEN.Length, out string idString);

                    if (steamIdValue <= 65536)
                    {
                        return;
                    }

                    var hostSteamId = new CSteamID(steamIdValue);
                    var port        = PortBindingManager.AddOrUpdatePortBinding(hostSteamId).Port;

                    utf8value = utf8value.Replace(HOST_ADDRESS_TOKEN + idString, HOST_ADDRESS_TOKEN + port.ToString());

                    SendToGameSocket(ref state, Encoding.UTF8.GetBytes(utf8value));

                    goto CONTINUE;
                }

                SendToGameSocket(ref state, bytes);
            }

            catch (Exception e)
            {
                LogError(Category, "Error receiving data");
                LogError(Category, e.ToString());
            }

            // and we wait for more data...
            CONTINUE : WaitForServerData(state);
        }
예제 #8
0
        private bool ParseServerDetails(IPEndPoint remote, byte[] data)
        {
            string receivedData = Encoding.UTF8.GetString(data);

            //Console.WriteLine(receivedData.Replace("\x00", "\\x00").Replace("\x02", "\\x02"));

            // split by 000 (info/player separator) and 002 (players/teams separator)
            // the players/teams separator is really 00, but because 00 may also be used elsewhere (an empty value for example), we hardcode it to 002
            // the 2 is the size of the teams, for BF2 this is always 2.
            string[] sections = receivedData.Split(new string[] { "\x00\x00\x00", "\x00\x00\x02" }, StringSplitOptions.None);

            //Console.WriteLine(sections.Length);

            if (sections.Length != 3 && !receivedData.EndsWith("\x00\x00"))
            {
                return(true); // true means we don't send back a response
            }
            string serverVars = sections[0];

            //string playerVars = sections[1];
            //string teamVars = sections[2];

            string[] serverVarsSplit = serverVars.Split(new string[] { "\x00" }, StringSplitOptions.None);

            var server = new GameServer();

            server["IPAddress"]     = remote.Address.ToString();
            server["QueryPort"]     = remote.Port.ToString();
            server["LastRefreshed"] = DateTime.UtcNow.ToString();
            server["LastPing"]      = DateTime.UtcNow.ToString();
            server["country"]       = "??";

            for (int i = 0; i < serverVarsSplit.Length - 1; i += 2)
            {
                if (serverVarsSplit[i] == "hostname")
                {
                    server.Set(serverVarsSplit[i], Regex.Replace(serverVarsSplit[i + 1], @"\s+", " ").Trim());
                }
                else
                {
                    server.Set(serverVarsSplit[i], serverVarsSplit[i + 1]);
                }
            }

            var gamename = server.Get <string>("gamename");

            if (server.Get <string>("statechanged") == "3" && gamename.Equals("whamdowfram", StringComparison.Ordinal))
            {
                ServerContext.ChatServer.SentServerMessageToClient("Вы создаете хост для игры в авто. Другие игроки увидят ваш хост через некоторое время (до минуты), получат оповещение и смогут подключиться для игры.\n\r");
            }

            server["hostport"]  = remote.Port.ToString();
            server["localport"] = remote.Port.ToString();

            var gamevariant = server.Get <string>("gamevariant");

            /*if (!gamevariant.IsNullOrWhiteSpace())
             * {
             *  if (gamevariant != SteamConstants.GameVariant)
             *  {
             *      ServerContext.ChatServer.SentServerMessageToClient("Вы используете не ту версию модификации. Вам необходимо использовать Soulstorm Bugfix Mod 1.56a.\r\n");
             *  }
             * }*/

            // you've got to have all these properties in order for your server to be valid
            if (!String.IsNullOrWhiteSpace(server.Get <string>("hostname")) &&
                !String.IsNullOrWhiteSpace(gamevariant) &&
                !String.IsNullOrWhiteSpace(server.Get <string>("gamever")) &&
                !String.IsNullOrWhiteSpace(server.Get <string>("gametype")) &&
                server.Get <string>("maxplayers") != "0")
            {
                server.Valid = true;
            }

            // if the server list doesn't contain this server, we need to return false in order to send a challenge
            // if the server replies back with the good challenge, it'll be added in AddValidServer
            if (!SteamLobbyManager.IsInLobbyNow)
            {
                return(false);
            }

            if (server.Properties.TryGetValue("statechanged", out string value))
            {
                var strValue = value?.ToString();

                if (strValue == "2")
                {
                    SteamLobbyManager.LeaveFromCurrentLobby();
                    return(true);
                }
            }

            PortBindingManager.ClearPortBindings();

            var wasJoinable = SteamLobbyManager.IsLobbyJoinable;

            SteamLobbyManager.UpdateCurrentLobby(server, CoreContext.ThunderHawkModManager.ActiveModRevision);

            if (!wasJoinable && SteamLobbyManager.IsLobbyJoinable)
            {
                var hostname = server.Get <string>("hostname");

                if (gamename == "whamdowfram")
                {
                    ServerContext.ChatServer.SendAutomatchGameBroadcast(hostname, int.Parse(server.Get <string>("maxplayers")));
                }
            }

            return(true);
        }