protected override async Task <bool> PostServerInfoAsync(GameServer discordGameServer)
        {
            if (discordGameServer == null)
            {
                return(false);
            }
            MineQuery query = null;

            try
            {
                query = new MineQuery(discordGameServer.ServerIP.Address, discordGameServer.ServerIP.Port, logger);
                MineQueryResult serverInfo = await query.GetServerInfoAsync().ConfigureAwait(false);

                if (serverInfo == null)
                {
                    return(false);
                }
                SocketGuild       guild   = discordClient?.GetGuild(discordGameServer.GuildID);
                SocketTextChannel channel = guild?.GetTextChannel(discordGameServer.ChannelID);
                if (guild == null || channel == null)
                {
                    return(false);
                }
                EmbedBuilder builder = new EmbedBuilder()
                                       .WithColor(new Color(21, 26, 35))
                                       .WithTitle($"Minecraft Server ({discordGameServer.ServerIP.Address}:{discordGameServer.ServerIP.Port})")
                                       .WithDescription($"Motd: {serverInfo.Description.Motd}");

                _ = serverInfo.Players.Sample != null && serverInfo.Players.Sample.Count > 0
                    ? builder.AddField($"Online Players ({serverInfo.Players.Online}/{serverInfo.Players.Max})", string.Join(", ", serverInfo.Players.Sample.Select(x => x.Name)))
                    : builder.AddField("Online Players", $"{serverInfo.Players.Online}/{serverInfo.Players.Max}");

                if (discordGameServer.GameVersion.IsEmpty())
                {
                    discordGameServer.GameVersion = serverInfo.Version.Name;
                    _ = dbContext.GameServers.Update(discordGameServer);
                    _ = await dbContext.SaveChangesAsync().ConfigureAwait(false);
                }
                else
                {
                    if (serverInfo.Version.Name != discordGameServer.GameVersion)
                    {
                        discordGameServer.GameVersion       = serverInfo.Version.Name;
                        discordGameServer.LastVersionUpdate = DateTime.Now;
                        _ = dbContext.GameServers.Update(discordGameServer);
                        _ = await dbContext.SaveChangesAsync().ConfigureAwait(false);
                    }
                }
                string lastServerUpdate = "";
                if (discordGameServer.LastVersionUpdate.HasValue)
                {
                    lastServerUpdate = $" (Last update: {discordGameServer.LastVersionUpdate.Value})";
                }

                _ = builder.WithFooter($"Server version: {serverInfo.Version.Name}{lastServerUpdate} || Last check: {DateTime.Now}");

                // Generate chart every full 10 minutes
                if (DateTime.Now.Minute % 10 == 0)
                {
                    string chart = await GenerateHistoryChartAsync(discordGameServer, serverInfo.Players.Online, serverInfo.Players.Max).ConfigureAwait(false);

                    if (!chart.IsEmptyOrWhiteSpace())
                    {
                        _ = builder.AddField("Player Count History", chart);
                    }
                }

                if (discordGameServer.MessageID.HasValue)
                {
                    if (await channel.GetMessageAsync(discordGameServer.MessageID.Value).ConfigureAwait(false) is IUserMessage existingMessage && existingMessage != null)
                    {
                        await existingMessage.ModifyAsync(x => x.Embed = builder.Build()).ConfigureAwait(false);
                    }
                    else
                    {
                        logger.LogWarning($"Error getting updates for server {discordGameServer.ServerIP}. Original message was removed.");
                        await RemoveServerAsync(discordGameServer.ServerIP, discordGameServer.GuildID).ConfigureAwait(false);

                        _ = await channel.SendMessageAsync($"Error getting updates for server {discordGameServer.ServerIP}. Original message was removed. Please use the proper remove command to remove the gameserver").ConfigureAwait(false);

                        return(false);
                    }
                }
                else
                {
                    IUserMessage message = await(channel?.SendMessageAsync("", false, builder.Build())).ConfigureAwait(false);
                    discordGameServer.MessageID = message.Id;
                    _ = dbContext.GameServers.Update(discordGameServer);
                    _ = await dbContext.SaveChangesAsync().ConfigureAwait(false);
                }
            }
예제 #2
0
        public async Task <MineQueryResult> GetServerInfoAsync()
        {
            await client.ConnectAsync(Address, Port).ConfigureAwait(false);

            if (!client.Connected)
            {
                return(null);
            }
            writeBuffer = new List <byte>();
            NetworkStream stream = client.GetStream();

            //Send a "Handshake" packet http://wiki.vg/Server_List_Ping#Ping_Process

            WriteVarInt(47);
            WriteString(Address.ToString());
            WriteShort(25565);
            WriteVarInt(1);
            Flush(stream, 0);

            // Send a "Status Request" packet http://wiki.vg/Server_List_Ping#Ping_Process

            Flush(stream, 0);

            byte[] readBuffer     = new byte[1024];
            var    completeBuffer = new List <byte>();
            int    numberOfBytesRead;

            do
            {
                numberOfBytesRead = await stream.ReadAsync(readBuffer).ConfigureAwait(false);

                completeBuffer.AddRange(readBuffer.Take(numberOfBytesRead));
            }while (numberOfBytesRead > 0);

            try
            {
                byte[] b          = completeBuffer.ToArray();
                int    length     = ReadVarInt(b);
                int    packet     = ReadVarInt(b);
                int    jsonLength = ReadVarInt(b);

                if (jsonLength > completeBuffer.Count - offset)
                {
                    //TODO: log receive error
                    return(null);
                }

                string          json   = ReadString(b, jsonLength);
                MineQueryResult result = JsonSerializer.Deserialize <MineQueryResult>(json);
                return(result);
            }
            catch (IOException ex)
            {
                logger.LogError(ex, $"Couldn't get MineCraft server info for {Address}:{Port}");
                return(null);
            }
            finally
            {
                client.Close();
                stream.Dispose();
            }
        }