mirror of
https://github.com/WWhiteDreamProject/wwdpublic.git
synced 2026-04-17 05:27:38 +03:00
<!-- This is a semi-strict format, you can add/remove sections as needed but the order/format should be kept the same Remove these comments before submitting --> # Description the adding AI is now up to y'all because i'm not touching loadout code for name datasets, but it shouldn't be too bad from here --------- Signed-off-by: sleepyyapril <123355664+sleepyyapril@users.noreply.github.com> Signed-off-by: SolStar <44028047+ewokswagger@users.noreply.github.com> Signed-off-by: deltanedas <39013340+deltanedas@users.noreply.github.com> Co-authored-by: themias <89101928+themias@users.noreply.github.com> Co-authored-by: Verm <32827189+Vermidia@users.noreply.github.com> Co-authored-by: DrSmugleaf <10968691+DrSmugleaf@users.noreply.github.com> Co-authored-by: Sphiral <145869023+SphiraI@users.noreply.github.com> Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com> Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com> Co-authored-by: Alzore <140123969+Blackern5000@users.noreply.github.com> Co-authored-by: ravage <142820619+ravage123321@users.noreply.github.com> Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> Co-authored-by: Intoxicating-Innocence <188202277+Intoxicating-Innocence@users.noreply.github.com> Co-authored-by: Saphire <lattice@saphi.re> Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Co-authored-by: Errant <35878406+Errant-4@users.noreply.github.com> Co-authored-by: Tayrtahn <tayrtahn@gmail.com> Co-authored-by: CaasGit <87243814+CaasGit@users.noreply.github.com> Co-authored-by: BramvanZijp <56019239+BramvanZijp@users.noreply.github.com> Co-authored-by: Boaz1111 <149967078+Boaz1111@users.noreply.github.com> Co-authored-by: NakataRin <45946146+NakataRin@users.noreply.github.com> Co-authored-by: Kara <lunarautomaton6@gmail.com> Co-authored-by: Plykiya <58439124+Plykiya@users.noreply.github.com> Co-authored-by: SlamBamActionman <slambamactionman@gmail.com> Co-authored-by: Doomsdrayk <robotdoughnut@comcast.net> Co-authored-by: Brandon Hu <103440971+Brandon-Huu@users.noreply.github.com> Co-authored-by: SlamBamActionman <83650252+SlamBamActionman@users.noreply.github.com> Co-authored-by: ElectroJr <leonsfriedrich@gmail.com> Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com> Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com> Co-authored-by: Julian Giebel <juliangiebel@live.de> Co-authored-by: nikthechampiongr <32041239+nikthechampiongr@users.noreply.github.com> Co-authored-by: Repo <47093363+Titian3@users.noreply.github.com> Co-authored-by: Chief-Engineer <119664036+Chief-Engineer@users.noreply.github.com> Co-authored-by: icekot8 <93311212+icekot8@users.noreply.github.com> Co-authored-by: AJCM-git <60196617+AJCM-git@users.noreply.github.com> Co-authored-by: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Co-authored-by: no <165581243+pissdemon@users.noreply.github.com> Co-authored-by: Tornado Tech <54727692+Tornado-Technology@users.noreply.github.com> Co-authored-by: osjarw <62134478+osjarw@users.noreply.github.com> Co-authored-by: Simon <63975668+Simyon264@users.noreply.github.com> Co-authored-by: TGRCDev <tgrc@tgrc.dev> Co-authored-by: Milon <milonpl.git@proton.me> Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com> Co-authored-by: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> Co-authored-by: Fildrance <fildrance@gmail.com> Co-authored-by: pa.pecherskij <pa.pecherskij@interfax.ru> Co-authored-by: chavonadelal <156101927+chavonadelal@users.noreply.github.com> Co-authored-by: SolStar <44028047+ewokswagger@users.noreply.github.com> Co-authored-by: K-Dynamic <20566341+K-Dynamic@users.noreply.github.com> Co-authored-by: lzk <124214523+lzk228@users.noreply.github.com> Co-authored-by: ArchRBX <5040911+ArchRBX@users.noreply.github.com> Co-authored-by: archrbx <punk.gear5260@fastmail.com> Co-authored-by: Radezolid <snappednexus@gmail.com> Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> Co-authored-by: EmoGarbage404 <retron404@gmail.com> Co-authored-by: MilenVolf <63782763+MilenVolf@users.noreply.github.com> Co-authored-by: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com> Co-authored-by: Velcroboy <velcroboy333@hotmail.com> Co-authored-by: neuPanda <chriseparton@gmail.com> Co-authored-by: neuPanda <spainman0@yahoo.com> Co-authored-by: Dvir <39403717+dvir001@users.noreply.github.com> Co-authored-by: Whatstone <whatston3@gmail.com> Co-authored-by: VideoKompany <135313844+VlaDOS1408@users.noreply.github.com> (cherry picked from commit 93ed70acfeda357133a701f637d3faeec02749bb)
206 lines
8.0 KiB
C#
206 lines
8.0 KiB
C#
using System.Collections.Immutable;
|
|
using System.Net;
|
|
using System.Net.Http;
|
|
using System.Net.Http.Headers;
|
|
using System.Net.Http.Json;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Content.Server.Connection;
|
|
using Content.Server.Database;
|
|
using Content.Shared.Database;
|
|
using JetBrains.Annotations;
|
|
using Robust.Server.Player;
|
|
using Robust.Shared;
|
|
using Robust.Shared.Configuration;
|
|
using Robust.Shared.Network;
|
|
using Robust.Shared.Player;
|
|
|
|
namespace Content.Server.Administration
|
|
{
|
|
/// <summary>
|
|
/// Contains data resolved via <see cref="IPlayerLocator"/>.
|
|
/// </summary>
|
|
/// <param name="UserId">The ID of the located user.</param>
|
|
/// <param name="LastAddress">The last known IP address that the user connected with.</param>
|
|
/// <param name="LastHWId">
|
|
/// The last known HWID that the user connected with.
|
|
/// This should be used for placing new records involving HWIDs, such as bans.
|
|
/// For looking up data based on HWID, use combined <see cref="LastLegacyHWId"/> and <see cref="LastModernHWIds"/>.
|
|
/// </param>
|
|
/// <param name="Username">The last known username for the user connected with.</param>
|
|
/// <param name="LastLegacyHWId">
|
|
/// The last known legacy HWID value this user connected with. Only use for old lookups!
|
|
/// </param>
|
|
/// <param name="LastModernHWIds">
|
|
/// The set of last known modern HWIDs the user connected with.
|
|
/// </param>
|
|
public sealed record LocatedPlayerData(
|
|
NetUserId UserId,
|
|
IPAddress? LastAddress,
|
|
ImmutableTypedHwid? LastHWId,
|
|
string Username,
|
|
ImmutableArray<byte>? LastLegacyHWId,
|
|
ImmutableArray<ImmutableArray<byte>> LastModernHWIds);
|
|
|
|
/// <summary>
|
|
/// Utilities for finding user IDs that extend to more than the server database.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Methods in this class will check connected clients, server database
|
|
/// AND the authentication server for lookups, in that order.
|
|
/// </remarks>
|
|
public interface IPlayerLocator
|
|
{
|
|
/// <summary>
|
|
/// Look up a user ID by name globally.
|
|
/// </summary>
|
|
/// <returns>Null if the player does not exist.</returns>
|
|
Task<LocatedPlayerData?> LookupIdByNameAsync(string playerName, CancellationToken cancel = default);
|
|
|
|
/// <summary>
|
|
/// If passed a GUID, looks up the ID and tries to find HWId for it.
|
|
/// If passed a player name, returns <see cref="LookupIdByNameAsync"/>.
|
|
/// </summary>
|
|
Task<LocatedPlayerData?> LookupIdByNameOrIdAsync(string playerName, CancellationToken cancel = default);
|
|
|
|
/// <summary>
|
|
/// Look up a user by <see cref="NetUserId"/> globally.
|
|
/// </summary>
|
|
/// <returns>Null if the player does not exist.</returns>
|
|
Task<LocatedPlayerData?> LookupIdAsync(NetUserId userId, CancellationToken cancel = default);
|
|
}
|
|
|
|
internal sealed class PlayerLocator : IPlayerLocator, IDisposable, IPostInjectInit
|
|
{
|
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
|
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
|
|
[Dependency] private readonly IServerDbManager _db = default!;
|
|
[Dependency] private readonly ILogManager _logManager = default!;
|
|
|
|
private readonly HttpClient _httpClient = new();
|
|
private ISawmill _sawmill = default!;
|
|
|
|
public PlayerLocator()
|
|
{
|
|
if (typeof(PlayerLocator).Assembly.GetName().Version is { } version)
|
|
{
|
|
_httpClient.DefaultRequestHeaders.UserAgent.Add(
|
|
new ProductInfoHeaderValue("SpaceStation14", version.ToString()));
|
|
}
|
|
}
|
|
|
|
public async Task<LocatedPlayerData?> LookupIdByNameAsync(string playerName, CancellationToken cancel = default)
|
|
{
|
|
// Check people currently on the server, the easiest case.
|
|
if (_playerManager.TryGetSessionByUsername(playerName, out var session))
|
|
return ReturnForSession(session);
|
|
|
|
// Check database for past players.
|
|
var record = await _db.GetPlayerRecordByUserName(playerName, cancel);
|
|
if (record != null)
|
|
return ReturnForPlayerRecord(record);
|
|
|
|
// If all else fails, ask the auth server.
|
|
var authServer = _configurationManager.GetCVar(CVars.AuthServer);
|
|
var requestUri = $"{authServer}api/query/name?name={WebUtility.UrlEncode(playerName)}";
|
|
using var resp = await _httpClient.GetAsync(requestUri, cancel);
|
|
|
|
return await HandleAuthServerResponse(resp, cancel);
|
|
}
|
|
|
|
public async Task<LocatedPlayerData?> LookupIdAsync(NetUserId userId, CancellationToken cancel = default)
|
|
{
|
|
// Check people currently on the server, the easiest case.
|
|
if (_playerManager.TryGetSessionById(userId, out var session))
|
|
return ReturnForSession(session);
|
|
|
|
// Check database for past players.
|
|
var record = await _db.GetPlayerRecordByUserId(userId, cancel);
|
|
if (record != null)
|
|
return ReturnForPlayerRecord(record);
|
|
|
|
// If all else fails, ask the auth server.
|
|
var authServer = _configurationManager.GetCVar(CVars.AuthServer);
|
|
var requestUri = $"{authServer}api/query/userid?userid={WebUtility.UrlEncode(userId.UserId.ToString())}";
|
|
using var resp = await _httpClient.GetAsync(requestUri, cancel);
|
|
|
|
return await HandleAuthServerResponse(resp, cancel);
|
|
}
|
|
|
|
private async Task<LocatedPlayerData?> HandleAuthServerResponse(HttpResponseMessage resp, CancellationToken cancel)
|
|
{
|
|
if (resp.StatusCode == HttpStatusCode.NotFound)
|
|
return null;
|
|
|
|
if (!resp.IsSuccessStatusCode)
|
|
{
|
|
_sawmill.Error("Auth server returned bad response {StatusCode}!", resp.StatusCode);
|
|
return null;
|
|
}
|
|
|
|
var responseData = await resp.Content.ReadFromJsonAsync<UserDataResponse>(cancellationToken: cancel);
|
|
if (responseData == null)
|
|
{
|
|
_sawmill.Error("Auth server returned null response!");
|
|
return null;
|
|
}
|
|
|
|
return new LocatedPlayerData(new NetUserId(responseData.UserId), null, null, responseData.UserName, null, []);
|
|
}
|
|
|
|
private static LocatedPlayerData ReturnForSession(ICommonSession session)
|
|
{
|
|
var userId = session.UserId;
|
|
var address = session.Channel.RemoteEndPoint.Address;
|
|
var hwId = session.Channel.UserData.GetModernHwid();
|
|
return new LocatedPlayerData(
|
|
userId,
|
|
address,
|
|
hwId,
|
|
session.Name,
|
|
session.Channel.UserData.HWId,
|
|
session.Channel.UserData.ModernHWIds);
|
|
}
|
|
|
|
private static LocatedPlayerData ReturnForPlayerRecord(PlayerRecord record)
|
|
{
|
|
var hwid = record.HWId;
|
|
|
|
return new LocatedPlayerData(
|
|
record.UserId,
|
|
record.LastSeenAddress,
|
|
hwid,
|
|
record.LastSeenUserName,
|
|
hwid is { Type: HwidType.Legacy } ? hwid.Hwid : null,
|
|
hwid is { Type: HwidType.Modern } ? [hwid.Hwid] : []);
|
|
}
|
|
|
|
public async Task<LocatedPlayerData?> LookupIdByNameOrIdAsync(string playerName, CancellationToken cancel = default)
|
|
{
|
|
if (Guid.TryParse(playerName, out var guid))
|
|
{
|
|
var userId = new NetUserId(guid);
|
|
|
|
return await LookupIdAsync(userId, cancel);
|
|
}
|
|
|
|
return await LookupIdByNameAsync(playerName, cancel);
|
|
}
|
|
|
|
[UsedImplicitly]
|
|
private sealed record UserDataResponse(string UserName, Guid UserId)
|
|
{
|
|
}
|
|
|
|
void IDisposable.Dispose()
|
|
{
|
|
_httpClient.Dispose();
|
|
}
|
|
|
|
void IPostInjectInit.PostInject()
|
|
{
|
|
_sawmill = _logManager.GetSawmill("PlayerLocate");
|
|
}
|
|
}
|
|
}
|