private void QueryCompleted(ServerQueryResponse response)
        {
            //   var response = queryTask.Result;
            SetConnectingState(false);

            if (response.Success)
            {
                var s = response.Status;
                var q = s.Query;
                _pingStatus.SetPlayerCount(q.Players.Online, q.Players.Max);

                ConnectionEndpoint = s.EndPoint;

                if (!s.WaitingOnPing)
                {
                    _pingStatus.SetPing(s.Delay);
                }

                if (q.Version.Protocol < (SavedServerEntry.ServerType == ServerType.Java ? JavaProtocol.ProtocolVersion : McpeProtocolInfo.ProtocolVersion))
                {
                    if (SavedServerEntry.ServerType == ServerType.Java)
                    {
                        _pingStatus.SetOutdated(q.Version.Name);
                    }
                }
                else if (q.Version.Protocol > (SavedServerEntry.ServerType == ServerType.Java ? JavaProtocol.ProtocolVersion : McpeProtocolInfo.ProtocolVersion))
                {
                    _pingStatus.SetOutdated($"multiplayer.status.client_out_of_date", true);
                }

                if (q.Description.Extra != null)
                {
                    StringBuilder builder = new StringBuilder();
                    foreach (var extra in q.Description.Extra)
                    {
                        if (extra.Color != null)
                        {
                            builder.Append(API.Utils.TextColor.GetColor(extra.Color).ToString());
                        }

                        if (extra.Bold.HasValue)
                        {
                            builder.Append(ChatFormatting.Bold);
                        }

                        if (extra.Italic.HasValue)
                        {
                            builder.Append(ChatFormatting.Italic);
                        }

                        if (extra.Underlined.HasValue)
                        {
                            builder.Append(ChatFormatting.Underline);
                        }

                        if (extra.Strikethrough.HasValue)
                        {
                            builder.Append(ChatFormatting.Strikethrough);
                        }

                        if (extra.Obfuscated.HasValue)
                        {
                            builder.Append(ChatFormatting.Obfuscated);
                        }

                        builder.Append(extra.Text);
                    }

                    _serverMotd.Text = builder.ToString();
                }
                else
                {
                    _serverMotd.Text = q.Description.Text;
                }

                if (!string.IsNullOrWhiteSpace(q.Favicon))
                {
                    var match = FaviconRegex.Match(q.Favicon);
                    if (match.Success && _graphicsDevice != null)
                    {
                        AutoResetEvent reset = new AutoResetEvent(false);
                        Alex.Instance.UIThreadQueue.Enqueue(() =>
                        {
                            using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(match.Groups["data"].Value)))
                            {
                                ServerIcon = GpuResourceManager.GetTexture2D(this, _graphicsDevice, ms);
                            }

                            reset.Set();
                        });

                        reset.WaitOne();

                        SavedServerEntry.CachedIcon = ServerIcon;
                        _serverIcon.Texture         = ServerIcon;
                    }
                }
            }
            else
            {
                SetErrorMessage(response.ErrorMessage);
            }
        }
Beispiel #2
0
        private static void RequestPlayers(ServerQueryResponse item, UdpClient udp)
        {
            try
            {
                IPEndPoint endp = null;

                var challengeRequest = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, PlayerRequestByte, 0xFF, 0xFF, 0xFF, 0xFF };
                var sendlen          = udp.Send(challengeRequest, 9);
                if (sendlen != 9)
                {
                    return;
                }

                var challengeRespose = udp.Receive(ref endp); // challenge response

                if (challengeRespose[4] != RequestChallengeByte)
                {
                    System.Diagnostics.Trace.WriteLine("Error in RequestPlayers - Challenge response");
                    return;
                }

                challengeRespose[4] = PlayerRequestByte; // change to player request
                sendlen             = udp.Send(challengeRespose, 9);
                if (sendlen != 9)
                {
                    return;
                }

                var playerRespose = udp.Receive(ref endp);

                if (playerRespose[4] != ReponseHeanderByte)
                {
                    System.Diagnostics.Trace.WriteLine("Error in RequestPlayers - Players response");
                    return;
                }

                byte playerCount = playerRespose[5];
                var  offset      = 6;
                var  result      = new List <ServerQueryResponse.Player>(byte.MaxValue);
                for (byte i = 0; i < playerCount; i++)
                {
                    var p = new ServerQueryResponse.Player();
                    p.Idx   = playerRespose[offset];
                    offset += 1;
                    string s;
                    offset      += ReadStringNullTerminated(playerRespose, offset, out s, Encoding.UTF8);
                    p.Name       = s;
                    p.Score      = BitConverter.ToInt32(playerRespose, offset);
                    offset      += 4;
                    p.OnlineTime = TimeSpan.FromSeconds(Convert.ToDouble(BitConverter.ToSingle(playerRespose, offset)));

                    offset += 4;
                    result.Add(p);
                }
                item.Players = result;
                return;
            }
            catch (Exception)
            {
                // ignored
                return;
            }
        }
Beispiel #3
0
        private static void RequestRules(ServerQueryResponse item, System.Net.Sockets.UdpClient udp)
        {
            IPEndPoint endp = null;
            // Rules auslesen
            var challengeRequest = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, RuleRequestByte, 0xFF, 0xFF, 0xFF, 0xFF };
            var sendlen          = udp.Send(challengeRequest, 9);

            byte[] respose = udp.Receive(ref endp);

            if (respose[4] != RequestChallengeByte)
            {
                System.Diagnostics.Debug.WriteLine("Error in RequestRules - Challenge response");
                return;
            }
            respose[4] = RuleRequestByte;
            sendlen    = udp.Send(respose, 9);
            respose    = udp.Receive(ref endp);

            if (respose[4] != RuleReponseByte)
            {
                // no valid response
                return;
            }

            Version version = new Version(item.Version);

            if (version.Major >= 1 && version.Minor >= 56)
            {
                SteamDefragmentedBytes unFramed = respose.DefragmentSteamBytes_1_56();
#if DEBUG
                bool   writeFile = Directory.Exists(@"E:\temp\Data");
                string filename  = @"E:\temp\Data\V_" + item.Version + "_" + item.IpAdresse.ToString();
                if (writeFile)
                {
                    if (respose.Length > 7)
                    {
                        using (var file = new FileStream(filename + ".dat", FileMode.OpenOrCreate))
                        {
                            file.Write(item.Data, 0, item.Data.Length);
                            file.SetLength(item.Data.Length);
                        }

                        using (var file = new FileStream(filename + ".rdat", FileMode.OpenOrCreate))
                        {
                            file.Write(respose, 0, respose.Length);
                            file.SetLength(respose.Length);
                        }

                        using (var file = new FileStream(filename + ".rdefrag", FileMode.OpenOrCreate))
                        {
                            file.Write(unFramed.Bytes, 0, unFramed.Bytes.Length);
                            file.SetLength(unFramed.Bytes.Length);
                        }
                    }
                }
#endif
                if (respose[4] != 0x45)
                {
                    System.Diagnostics.Debug.WriteLine("Error in RequestRules - Rules response not valid");
                    return;
                }

                using (var decodedMem = unFramed.DecodeSteamRuleFile_1_56())
                {
#if DEBUG
                    if (writeFile)
                    {
                        using (var file = new FileStream(filename + ".rules", FileMode.OpenOrCreate))
                        {
                            decodedMem.Data.CopyTo(file);
                        }
                    }
                    decodedMem.Data.Seek(0, SeekOrigin.Begin);
#endif
                    var mods = ReadRules(decodedMem, version);
                    foreach (var keyValuePair in mods)
                    {
                        item.KeyValues.Add(keyValuePair.Key, keyValuePair.Value);
                    }
                }
            }
            else
            {
                item.KeyValues.Add("sigNames:1:1", "Version " + item.Version + " not supported");
            }
        }
Beispiel #4
0
        public static SteamGameServer GetServerInfo(IPEndPoint gameServerQueryEndpoint)
        {
            byte[] startBytes  = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF };
            byte   Header      = 0x54;
            string qryAsString = "Source Engine Query";

            List <byte> qry = new List <byte>();

            qry.AddRange(startBytes);
            qry.Add(Header);
            qry.AddRange(Encoding.Default.GetBytes(qryAsString));
            qry.Add(0x00);

            ServerQueryResponse item = null;
            var sw     = new System.Diagnostics.Stopwatch();
            var buffer = new byte[2048];

            using (System.Net.Sockets.UdpClient udp = new System.Net.Sockets.UdpClient())
            {
                try
                {
                    udp.Connect(gameServerQueryEndpoint);

                    udp.AllowNatTraversal(true);
                    udp.Client.ReceiveTimeout = 300;

                    sw.Start();
                    udp.Send(qry.ToArray(), qry.Count);

                    System.Net.Sockets.SocketError errorCode;
                    var receivedLenght = udp.Client.Receive(buffer, 0, 2048, System.Net.Sockets.SocketFlags.None,
                                                            out errorCode);
                    sw.Stop();
                    if (errorCode != System.Net.Sockets.SocketError.Success)
                    {
                        return(null);
                    }
                    if (receivedLenght == buffer.Length)
                    {
                        throw new Exception("Buffer zu klein");
                    }


                    var receivedBytes = new byte[receivedLenght];
                    Buffer.BlockCopy(buffer, 0, receivedBytes, 0, receivedLenght);
                    //var receivedBytes = udp.Receive(ref endp);

                    var enconding = System.Text.Encoding.UTF8; // System.Text.Encoding.ASCII;

                    using (var mem = new System.IO.MemoryStream(receivedBytes))
                        using (var br = new System.IO.BinaryReader(mem, CharEncoding))
                        {
                            br.ReadInt32();
                            br.ReadByte();

                            item                 = new ServerQueryResponse();
                            item.IpAdresse       = gameServerQueryEndpoint.Address.ToString();
                            item.ProtocolVersion = br.ReadByte();

                            item.Ping = (int)sw.ElapsedMilliseconds;

                            var count = Array.FindIndex(receivedBytes, (int)mem.Position, IsNULL) - (int)mem.Position;
                            item.GameServerName = enconding.GetString(br.ReadBytes(count));
                            br.ReadByte(); // null-byte

                            count    = Array.FindIndex(receivedBytes, (int)mem.Position, IsNULL) - (int)mem.Position;
                            item.Map = enconding.GetString(br.ReadBytes(count));
                            br.ReadByte(); // null-byte
                            //item.Map = ReadStringNullTerminated(br, enconding);

                            count       = Array.FindIndex(receivedBytes, (int)mem.Position, IsNULL) - (int)mem.Position;
                            item.Folder = enconding.GetString(br.ReadBytes(count));
                            br.ReadByte(); // null-byte

                            count     = Array.FindIndex(receivedBytes, (int)mem.Position, IsNULL) - (int)mem.Position;
                            item.Game = enconding.GetString(br.ReadBytes(count));
                            br.ReadByte(); // null-byte

                            item.ID = br.ReadInt16();

                            item.CurrentPlayerCount = br.ReadByte();

                            item.MaxPlayerCount = br.ReadByte();

                            item.CurrentBotsCount = br.ReadByte();

                            item.ServerType = (ServerQueryRequestType)br.ReadByte();

                            item.Password = br.ReadByte() == 1;

                            item.VAC = br.ReadByte() == 1;

                            item.Mode = br.ReadByte() == 1;

                            count        = Array.FindIndex(receivedBytes, (int)mem.Position, IsNULL) - (int)mem.Position;
                            item.Version = enconding.GetString(br.ReadBytes(count));
                            br.ReadByte(); // null-byte

                            var edfCode = br.ReadByte();

                            item.Data = receivedBytes;

                            if ((edfCode & 0x80) == 0x80)
                            {
                                item.GamePort = br.ReadUInt16();
                            }



                            if ((edfCode & 0x10) == 0x10)
                            {
                                item.ServerSteamId = br.ReadInt64();
                            }

                            //if ((edfCode & 0x40) == 0x40)
                            //    Console.WriteLine("spectator server");

                            if ((edfCode & 0x20) == 0x20)
                            {
                                count         = Array.FindIndex(receivedBytes, (int)mem.Position, IsNULL) - (int)mem.Position;
                                item.Keywords = enconding.GetString(br.ReadBytes(count));
                                br.ReadByte(); // null-byte
                            }

                            if ((edfCode & 0x01) == 0x01)
                            {
                                item.GameID = br.ReadInt64();
                            }

                            // https://community.bistudio.com/wiki/STEAMWORKSquery
                            // https://developer.valvesoftware.com/wiki/Master_Server_Query_Protocol
                        }

                    RequestRules(item, udp);

                    if (item.CurrentPlayerCount > 0)
                    {
                        udp.Client.ReceiveTimeout = Math.Max(300, Convert.ToInt32((6d * item.CurrentPlayerCount)));
                        RequestPlayers(item, udp);
                    }
                }
                catch
                {
                    sw.Stop();
                }
            }
            return(item != null
                ? new SteamGameServer
            {
                Host = gameServerQueryEndpoint.Address,
                QueryPort = gameServerQueryEndpoint.Port,
                Name = item.GameServerName,
                //Gamename = SteamGameNameFilter,
                Map = item.Map,
                Mission = item.Game,
                MaxPlayers = item.MaxPlayerCount,
                CurrentPlayerCount = item.CurrentPlayerCount,
                Passworded = item.Password,
                Port = item.GamePort,
                Version = item.Version,
                Keywords = item.Keywords,
                CurrentPlayers = new string[0],
                Ping = item.Ping,
                Players = item.Players?.Cast <ISteamGameServerPlayer>().ToArray(),
                Mods = GetValue("modNames", item.KeyValues),
                Modhashs = GetValue("modHashes", item.KeyValues),
                Signatures = GetValue("sigNames", item.KeyValues),
                VerifySignatures = item.Keywords.Contains(",vt,")
            }
                : null);
        }