using System; using System.Collections.Generic; using System.Net; using JetBrains.Annotations; using Utf8Json; using Webserver.Permissions; namespace Webserver.WebAPI.APIs { [UsedImplicitly] public class Player : AbsRestApi { private static readonly byte[] jsonPlayersKey = JsonWriter.GetEncodedPropertyNameWithBeginObject ("players"); protected override void HandleRestGet (RequestContext _context) { string id = _context.RequestPath; int permissionLevel = _context.PermissionLevel; bool bViewAll = PermissionUtils.CanViewAllPlayers (permissionLevel); PlatformUserIdentifierAbs nativeUserId = _context.Connection?.UserId; // string qs; // if ((qs = _context.Request.QueryString ["count"]) == null || !int.TryParse (qs, out int count)) { // count = 50; // } PrepareEnvelopedResult (out JsonWriter writer); writer.WriteRaw (jsonPlayersKey); writer.WriteBeginArray (); ClientInfo ci; int written = 0; if (string.IsNullOrEmpty (id)) { for (int i = 0; i < ConnectionManager.Instance.Clients.List.Count; i++) { ClientInfo clientInfo = ConnectionManager.Instance.Clients.List [i]; writePlayerJson (ref writer, ref written, clientInfo.PlatformId, bViewAll, nativeUserId); } } else if (int.TryParse (id, out int entityId) && (ci = ConnectionManager.Instance.Clients.ForEntityId (entityId)) != null) { // TODO: Allow finding offline players, also for search other than by EntityId writePlayerJson (ref writer, ref written, ci.PlatformId, bViewAll, nativeUserId); } else { writer.WriteEndArray (); writer.WriteEndObject (); SendEnvelopedResult (_context, ref writer, HttpStatusCode.NotFound); return; } writer.WriteEndArray (); writer.WriteEndObject (); SendEnvelopedResult (_context, ref writer); } #region JSON keys for player result private static readonly byte[] jsonEntityIdKey = JsonWriter.GetEncodedPropertyNameWithBeginObject ("entityId"); private static readonly byte[] jsonNameKey = JsonWriter.GetEncodedPropertyNameWithPrefixValueSeparator ("name"); private static readonly byte[] jsonPlatformIdKey = JsonWriter.GetEncodedPropertyNameWithPrefixValueSeparator ("platformId"); private static readonly byte[] jsonCrossplatformIdKey = JsonWriter.GetEncodedPropertyNameWithPrefixValueSeparator ("crossplatformId"); private static readonly byte[] jsonTotalPlayTimeKey = JsonWriter.GetEncodedPropertyNameWithPrefixValueSeparator ("totalPlayTimeSeconds"); private static readonly byte[] jsonLastOnlineKey = JsonWriter.GetEncodedPropertyNameWithPrefixValueSeparator ("lastOnline"); private static readonly byte[] jsonOnlineKey = JsonWriter.GetEncodedPropertyNameWithPrefixValueSeparator ("online"); private static readonly byte[] jsonIpKey = JsonWriter.GetEncodedPropertyNameWithPrefixValueSeparator ("ip"); private static readonly byte[] jsonPingKey = JsonWriter.GetEncodedPropertyNameWithPrefixValueSeparator ("ping"); private static readonly byte[] jsonPositionKey = JsonWriter.GetEncodedPropertyNameWithPrefixValueSeparator ("position"); private static readonly byte[] jsonLevelKey = JsonWriter.GetEncodedPropertyNameWithPrefixValueSeparator ("level"); private static readonly byte[] jsonHealthKey = JsonWriter.GetEncodedPropertyNameWithPrefixValueSeparator ("health"); private static readonly byte[] jsonStaminaKey = JsonWriter.GetEncodedPropertyNameWithPrefixValueSeparator ("stamina"); private static readonly byte[] jsonScoreKey = JsonWriter.GetEncodedPropertyNameWithPrefixValueSeparator ("score"); private static readonly byte[] jsonDeathsKey = JsonWriter.GetEncodedPropertyNameWithPrefixValueSeparator ("deaths"); private static readonly byte[] jsonKillsKey = JsonWriter.GetEncodedPropertyNameWithPrefixValueSeparator ("kills"); private static readonly byte[] jsonKillsZombiesKey = JsonWriter.GetEncodedPropertyNameWithBeginObject ("zombies"); private static readonly byte[] jsonKillsPlayersKey = JsonWriter.GetEncodedPropertyNameWithPrefixValueSeparator ("players"); private static readonly byte[] jsonBannedKey = JsonWriter.GetEncodedPropertyNameWithPrefixValueSeparator ("banned"); private static readonly byte[] jsonBanActiveKey = JsonWriter.GetEncodedPropertyNameWithBeginObject ("banActive"); private static readonly byte[] jsonBanReasonKey = JsonWriter.GetEncodedPropertyNameWithPrefixValueSeparator ("reason"); private static readonly byte[] jsonBanUntilKey = JsonWriter.GetEncodedPropertyNameWithPrefixValueSeparator ("until"); #endregion private void writePlayerJson (ref JsonWriter _writer, ref int _written, PlatformUserIdentifierAbs _nativeUserId, bool _allowViewAll, PlatformUserIdentifierAbs _requesterNativeUserId) { if (!_allowViewAll && (_requesterNativeUserId == null || !_requesterNativeUserId.Equals (_nativeUserId) )) { return; } ClientInfo ci = ConnectionManager.Instance.Clients.ForUserId (_nativeUserId); if (ci == null) { global::Log.Warning ($"[Web] Player.GET: ClientInfo null"); return; } int entityId = ci.entityId; GameManager.Instance.World.Players.dict.TryGetValue (entityId, out EntityPlayer entity); if (entity == null) { global::Log.Warning ($"[Web] Player.GET: EntityPlayer null"); return; } if (_written > 0) { _writer.WriteValueSeparator (); } _written++; bool online = true; // TODO _writer.WriteRaw (jsonEntityIdKey); _writer.WriteInt32 (entityId); _writer.WriteRaw (jsonNameKey); _writer.WriteString (ci.playerName); _writer.WriteRaw (jsonPlatformIdKey); JsonCommons.WritePlatformUserIdentifier (ref _writer, _nativeUserId); _writer.WriteRaw (jsonCrossplatformIdKey); JsonCommons.WritePlatformUserIdentifier (ref _writer, ci.CrossplatformId); _writer.WriteRaw (jsonTotalPlayTimeKey); //_writer.WriteLong (player.TotalPlayTime); TODO _writer.WriteNull (); _writer.WriteRaw (jsonLastOnlineKey); //JsonCommons.WriteDateTime (ref _writer, player.LastOnline); TODO _writer.WriteNull (); _writer.WriteRaw (jsonOnlineKey); _writer.WriteBoolean (online); _writer.WriteRaw (jsonIpKey); if (online) { _writer.WriteString (ci.ip); // TODO: Possibly show last used IP? } else { _writer.WriteNull (); } _writer.WriteRaw (jsonPingKey); if (online) { _writer.WriteInt32 (ci.ping); } else { _writer.WriteNull (); } _writer.WriteRaw (jsonPositionKey); if (online) { JsonCommons.WritePositionObject (ref _writer, entity.GetPosition ()); // TODO: Possibly show last position? } else { _writer.WriteNull (); } _writer.WriteRaw (jsonLevelKey); _writer.WriteNull (); // TODO _writer.WriteRaw (jsonHealthKey); _writer.WriteInt32 (entity.Health); _writer.WriteRaw (jsonStaminaKey); _writer.WriteSingle (entity.Stamina); _writer.WriteRaw (jsonScoreKey); _writer.WriteInt32 (entity.Score); _writer.WriteRaw (jsonDeathsKey); _writer.WriteInt32 (entity.Died); _writer.WriteRaw (jsonKillsKey); _writer.WriteRaw (jsonKillsZombiesKey); _writer.WriteInt32 (entity.KilledZombies); _writer.WriteRaw (jsonKillsPlayersKey); _writer.WriteInt32 (entity.KilledPlayers); _writer.WriteEndObject (); // End of jsonKillsKey _writer.WriteRaw (jsonBannedKey); bool banned = GameManager.Instance.adminTools.Blacklist.IsBanned (_nativeUserId, out DateTime bannedUntil, out string banReason); if (!banned && ci.CrossplatformId != null) { banned = GameManager.Instance.adminTools.Blacklist.IsBanned (ci.CrossplatformId, out bannedUntil, out banReason); } _writer.WriteRaw (jsonBanActiveKey); _writer.WriteBoolean (banned); _writer.WriteRaw (jsonBanReasonKey); if (banned) { _writer.WriteString (banReason); } else { _writer.WriteNull (); } _writer.WriteRaw (jsonBanUntilKey); if (banned) { JsonCommons.WriteDateTime (ref _writer, bannedUntil); } else { _writer.WriteNull (); } _writer.WriteEndObject (); // End of jsonBannedKeys _writer.WriteEndObject (); // End of jsonEntityIdKey } protected override void HandleRestPost (RequestContext _context, IDictionary _jsonInput, byte[] _jsonInputData) { if (!TryGetJsonField (_jsonInput, "command", out string commandString)) { SendErrorResult (_context, HttpStatusCode.BadRequest, _jsonInputData, "NO_COMMAND"); return; } WebCommandResult.ResultType responseType = WebCommandResult.ResultType.Full; if (TryGetJsonField (_jsonInput, "format", out string formatString)) { if (formatString.EqualsCaseInsensitive ("raw")) { responseType = WebCommandResult.ResultType.Raw; } else if (formatString.EqualsCaseInsensitive ("simple")) { responseType = WebCommandResult.ResultType.ResultOnly; } } int commandSepIndex = commandString.IndexOf (' '); string commandPart = commandSepIndex > 0 ? commandString.Substring (0, commandSepIndex) : commandString; string argumentsPart = commandSepIndex > 0 ? commandString.Substring (commandPart.Length + 1) : ""; IConsoleCommand command = SdtdConsole.Instance.GetCommand (commandPart, true); if (command == null) { SendErrorResult (_context, HttpStatusCode.NotFound, _jsonInputData, "UNKNOWN_COMMAND"); return; } int commandPermissionLevel = GameManager.Instance.adminTools.Commands.GetCommandPermissionLevel (command.GetCommands ()); if (_context.PermissionLevel > commandPermissionLevel) { SendErrorResult (_context, HttpStatusCode.Forbidden, _jsonInputData, "NO_PERMISSION"); return; } _context.Response.SendChunked = true; WebCommandResult wcr = new WebCommandResult (commandPart, argumentsPart, responseType, _context); SdtdConsole.Instance.ExecuteAsync (commandString, wcr); } public override int DefaultPermissionLevel () => 2000; } }