internal PlayerStateEvent(EventMessages msg, PlayerPayLoad ppl, bool on) : base(msg) { Player = ppl; Online = on; }
/// <summary> /// Will compare the last status with the current one and return event updates. /// </summary> /// <returns></returns> public EventBase[] Update() { // event-queue var events = new List <EventBase>(); var isFirst = last == null; var current = Base.GetLatestServerInfo(); if (current != null) { // if first info, or last success was different from this (either went online or went offline) => invoke if (NotifyServer && (isFirst || last.HadSuccess != current.HadSuccess)) { Debug.WriteLine("Server '" + Base.Address + ":" + Base.Port + "' status change: " + current.HadSuccess); var errMsg = current.LastError != null ? "Connection Failed: " + current.LastError.GetType().Name : ""; events.Add(new OnlineStatusEvent(current.HadSuccess, current.HadSuccess ? current.ServerMotd : errMsg)); } // if first info, or last player count was different (player went online or offline) => invoke if (NotifyCount) { var diff = isFirst ? current.CurrentPlayerCount : current.CurrentPlayerCount - last.CurrentPlayerCount; if (diff != 0) { Debug.WriteLine("Server '" + Base.Address + ":" + Base.Port + "' count change: " + diff); events.Add(new PlayerChangeEvent(diff)); } } // check current list for new players var onlineIds = new List <string>(); if (current.OnlinePlayers != null) { foreach (var p in current.OnlinePlayers) { // save online user id temporarily if (!onlineIds.Contains(p.Id)) { onlineIds.Add(p.Id); } // register name userNames[p.Id] = p.Name; // if notify and user has state and last state was offline and user is watched, notify change if (NotifyNames && (!userStates.ContainsKey(p.Id) || !userStates[p.Id])) { events.Add(new PlayerStateEvent(p, true)); } // register state or set to true userStates[p.Id] = true; } } // this needs to be done to avoid ElementChangedException var keys = userStates.Keys.ToArray(); // check all states for players who went offline foreach (var k in keys) { if (!userStates[k] || onlineIds.Contains(k)) { continue; } // if user state still true, but he is not in online list => went offline userStates[k] = false; // create payload var p = new PlayerPayLoad { Id = k, RawName = userNames[k] }; // notify => invoke if (NotifyNames) { events.Add(new PlayerStateEvent(p, false)); } } } // set new last last = current; ApplyServerInfo(current); return(events.ToArray()); }
protected override async Task <ServerInfoBase> Get(CancellationToken ct, DateTime startPing, Stopwatch pingTime, TcpClient client, NetworkStream stream) { var _offset = 0; var writeBuffer = new List <byte>(); WriteVarInt(writeBuffer, Proto); WriteString(writeBuffer, address); WriteShort(writeBuffer, Convert.ToInt16(port)); WriteVarInt(writeBuffer, 1); Flush(ct, writeBuffer, stream, 0); // yep, twice. Flush(ct, writeBuffer, stream, 0); var readBuffer = new byte[BufferSize]; await stream.ReadAsync(readBuffer, 0, readBuffer.Length, ct); // done stream.Close(); client.Close(); // IF an IOException arises here, thie server is probably not a minecraft-one var length = ReadVarInt(ref _offset, readBuffer); var packet = ReadVarInt(ref _offset, readBuffer); var jsonLength = ReadVarInt(ref _offset, readBuffer); var json = ReadString(ref _offset, readBuffer, jsonLength); dynamic ping = JsonConvert.DeserializeObject(json); var sample = new List <PlayerPayLoad>(); if (json.Contains("\"sample\":[")) { try { foreach (dynamic key in ping.players.sample) { if (key.id == null || key.name == null) { continue; } var plr = new PlayerPayLoad() { Id = key.id, RawName = key.name }; sample.Add(plr); } } catch (Exception e) { Program.WriteLine("Error when sample processing: " + e.ToString()); } } var desc = ""; if (json.Contains("\"description\":{\"")) { try { desc = (string)ping.description.text; } catch (Exception e) { Program.WriteLine("Error description text: " + e.ToString()); } } if (string.IsNullOrEmpty(desc)) { try { desc = (string)ping.description; } catch (Exception ex) { Program.WriteLine("Error description text: " + ex.ToString()); } } if (string.IsNullOrEmpty(desc)) { throw new FormatException("Empty description!"); } return(new ServerInfoBase(startPing, pingTime.ElapsedMilliseconds, desc, (int)ping.players.max, (int)ping.players.online, (string)ping.version.name, sample)); }
protected override async Task <ServerInfoBase> Get(CancellationToken ct, DateTime startPing, Stopwatch pingTime, TcpClient client, NetworkStream stream) { var _offset = 0; var writeBuffer = new List <byte>(); WriteVarInt(writeBuffer, Proto); WriteString(writeBuffer, address); WriteShort(writeBuffer, Convert.ToInt16(port)); WriteVarInt(writeBuffer, 1); Flush(ct, writeBuffer, stream, 0); // yep, twice. Flush(ct, writeBuffer, stream, 0); var readBuffer = new byte[BufferSize]; await stream.ReadAsync(readBuffer, 0, readBuffer.Length, ct); // done stream.Close(); client.Close(); // IF an IOException arises here, thie server is probably not a minecraft-one var length = ReadVarInt(ref _offset, readBuffer); var packet = ReadVarInt(ref _offset, readBuffer); var jsonLength = ReadVarInt(ref _offset, readBuffer); var json = ReadString(ref _offset, readBuffer, jsonLength); dynamic ping = JsonConvert.DeserializeObject(json); // parse player sample var sample = new List <PlayerPayLoad>(); if (json.Contains("\"sample\":[")) { try { foreach (dynamic key in ping.players.sample) { if (key.id == null || key.name == null) { continue; } var plr = new PlayerPayLoad() { Id = key.id, RawName = key.name }; sample.Add(plr); } } catch (Exception e) { Logger.WriteLine("Error when sample processing: " + e.ToString(), Types.LogLevel.Debug); } } // parse favicon Bitmap image = null; if (json.Contains("\"favicon\":\"")) { try { var hdr = "data:image/png;base64,"; var imgStr = (string)ping.favicon; if (!imgStr.StartsWith(hdr)) { throw new Exception("Unkown Format"); } byte[] imgData = Convert.FromBase64String(imgStr.Substring(hdr.Length)); using (var imgStream = new MemoryStream(imgData, 0, imgData.Length)) image = new Bitmap(imgStream); } catch (Exception ie) { Logger.WriteLine("Error parsing favicon: " + ie.ToString(), Types.LogLevel.Debug); } } // parse MOTD/description var desc = ""; if (json.Contains("\"description\":{\"")) { try { desc = (string)ping.description.text; } catch (Exception e) { Logger.WriteLine("Error description.text: " + e.ToString(), Types.LogLevel.Debug); } } if (string.IsNullOrEmpty(desc)) { try { desc = (string)ping.description; } catch (Exception ex) { Logger.WriteLine("Error description: " + ex.ToString(), Types.LogLevel.Debug); } } if (string.IsNullOrEmpty(desc)) { throw new FormatException("Empty description!"); } return(new ServerInfoBase(startPing, pingTime.ElapsedMilliseconds, desc, (int)ping.players.max, (int)ping.players.online, (string)ping.version.name, image, sample)); }
public PlayerStateEvent(PlayerPayLoad ppl, bool on) { Player = ppl; Online = on; }