Proton (#420)
* Proton-1 finished! Signed-off-by: pacable <igor.mamaev1@gmail.com> * fix Signed-off-by: pacable <igor.mamaev1@gmail.com> --------- Signed-off-by: pacable <igor.mamaev1@gmail.com>
This commit is contained in:
parent
ce81c1a7a2
commit
939249a38b
18 changed files with 473 additions and 2 deletions
|
|
@ -16,6 +16,7 @@
|
|||
<Button Visible="False" Name="Kick" Text="{Loc 'admin-player-actions-kick'}" StyleClasses="OpenBoth" />
|
||||
<Button Visible="False" Name="Ban" Text="{Loc 'admin-player-actions-ban'}" StyleClasses="OpenBoth" />
|
||||
<Button Visible="False" Name="Respawn" Text="{Loc 'admin-player-actions-respawn'}" StyleClasses="OpenBoth" />
|
||||
<Button Visible="False" Name="Screenshot" Text="{Loc 'admin-player-actions-screenshot'}" StyleClasses="OpenBoth"/> <!-- Sunrise edit -->
|
||||
<Button Visible="False" Name="Follow" Text="{Loc 'admin-player-actions-follow'}" StyleClasses="OpenLeft" />
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
|
|
|
|||
|
|
@ -167,6 +167,19 @@ namespace Content.Client.Administration.UI.Bwoink
|
|||
_console.ExecuteCommand($"kick \"{_currentPlayer.Username}\"");
|
||||
};
|
||||
|
||||
// Sunrise-start
|
||||
Screenshot.OnPressed += _ =>
|
||||
{
|
||||
if (!AdminUIHelpers.TryConfirm(Screenshot, _confirmations))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_currentPlayer is not null)
|
||||
_console.ExecuteCommand($"screenshot \"{_currentPlayer.Username}\"");
|
||||
};
|
||||
// Sunrise-end
|
||||
|
||||
Follow.OnPressed += _ =>
|
||||
{
|
||||
if (_currentPlayer is not null)
|
||||
|
|
@ -233,6 +246,11 @@ namespace Content.Client.Administration.UI.Bwoink
|
|||
Respawn.Visible = _adminManager.CanCommand("respawn");
|
||||
Respawn.Disabled = !Respawn.Visible || disabled;
|
||||
|
||||
// Sunrise-start
|
||||
Screenshot.Visible = _adminManager.CanCommand("kick");
|
||||
Screenshot.Disabled = !Screenshot.Visible || disabled;
|
||||
// Sunrise-end
|
||||
|
||||
Follow.Visible = _adminManager.CanCommand("follow");
|
||||
Follow.Disabled = !Follow.Visible || disabled;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<DefaultWindow xmlns="https://spacestation14.io"
|
||||
xmlns:cc="clr-namespace:Content.Client.Administration.UI.Bwoink"
|
||||
SetSize="900 500"
|
||||
SetSize="1000 600"
|
||||
HeaderClass="windowHeaderAlert"
|
||||
TitleClass="windowTitleAlert"
|
||||
Title="{Loc 'bwoink-user-title'}" >
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
<Button Name="SubmitKickButton" Text="{Loc admin-player-actions-kick}" Disabled="True"/>
|
||||
<Button Name="SubmitAHelpButton" Text="{Loc admin-player-actions-ahelp}" Disabled="True"/>
|
||||
<Button Name="SubmitRespawnButton" Text="{Loc admin-player-actions-respawn}" Disabled="True"/>
|
||||
<Button Name="ScreenshotButton" Text="{Loc admin-player-actions-get-screenshot}" Disabled="True"/> <!-- Sunrise edit -->
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</DefaultWindow>
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ namespace Content.Client.Administration.UI.Tabs.AdminTab
|
|||
SubmitKickButton.OnPressed += SubmitKickButtonOnPressed;
|
||||
SubmitAHelpButton.OnPressed += SubmitAhelpButtonOnPressed;
|
||||
SubmitRespawnButton.OnPressed += SubmitRespawnButtonOnPressed;
|
||||
ScreenshotButton.OnPressed += ScreenshotButtonOnPressed; // Sunrise-edit
|
||||
PlayerList.OnSelectionChanged += OnListOnOnSelectionChanged;
|
||||
}
|
||||
|
||||
|
|
@ -36,8 +37,22 @@ namespace Content.Client.Administration.UI.Tabs.AdminTab
|
|||
SubmitKickButton.Disabled = disableButtons;
|
||||
SubmitAHelpButton.Disabled = disableButtons;
|
||||
SubmitRespawnButton.Disabled = disableButtons;
|
||||
ScreenshotButton.Disabled = disableButtons; // Sunrise-edit
|
||||
}
|
||||
|
||||
// Sunrise-start
|
||||
private void ScreenshotButtonOnPressed(BaseButton.ButtonEventArgs obj)
|
||||
{
|
||||
if (_selectedPlayer == null)
|
||||
return;
|
||||
|
||||
if (!AdminUIHelpers.TryConfirm(ScreenshotButton, _confirmations))
|
||||
return;
|
||||
|
||||
IoCManager.Resolve<IClientConsoleHost>().ExecuteCommand($"screenshot \"{_selectedPlayer.Username}\"");
|
||||
}
|
||||
// Sunrise-end
|
||||
|
||||
private void SubmitKickButtonOnPressed(BaseButton.ButtonEventArgs obj)
|
||||
{
|
||||
if (_selectedPlayer == null)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using Content.Client._Sunrise.Proton; // Sunrise-Proton
|
||||
using Content.Client._Sunrise.ServersHub;
|
||||
using Content.Client.Administration.Managers;
|
||||
using Content.Client.Changelog;
|
||||
|
|
@ -73,6 +74,7 @@ namespace Content.Client.Entry
|
|||
[Dependency] private readonly ContentReplayPlaybackManager _replayMan = default!;
|
||||
[Dependency] private readonly DebugMonitorManager _debugMonitorManager = default!;
|
||||
[Dependency] private readonly ServersHubManager _serversHubManager = default!; // Sunrise-Hub
|
||||
[Dependency] private readonly ProtonManager _proton = default!; // Sunrise-Proton
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
|
|
@ -137,6 +139,7 @@ namespace Content.Client.Entry
|
|||
_playbackMan.Initialize();
|
||||
|
||||
_serversHubManager.Initialize(); // Sunrise-Hub
|
||||
_proton.Initialize(); // Sunrise-Proton
|
||||
|
||||
//AUTOSCALING default Setup!
|
||||
_configManager.SetCVar("interface.resolutionAutoScaleUpperCutoffX", 1080);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using Content.Client._Sunrise.ServersHub;
|
||||
using Content.Client._Sunrise.Proton; // Sunrise-Proton
|
||||
using Content.Client._Sunrise.ServersHub;
|
||||
using Content.Client.Administration.Managers;
|
||||
using Content.Client.Changelog;
|
||||
using Content.Client.Chat.Managers;
|
||||
|
|
@ -56,6 +57,7 @@ namespace Content.Client.IoC
|
|||
// Sunrise
|
||||
|
||||
collection.Register<ServersHubManager>(); // Sunrise-Hub
|
||||
collection.Register<ProtonManager>(); // Sunrise-Proton
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
80
Content.Client/_Sunrise/Proton/ClientProtonManager.cs
Normal file
80
Content.Client/_Sunrise/Proton/ClientProtonManager.cs
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
using Content.Shared._Sunrise.Proton;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.ContentPack;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Utility;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
|
||||
namespace Content.Client._Sunrise.Proton;
|
||||
|
||||
public sealed class ProtonManager
|
||||
{
|
||||
[Dependency] private readonly IClyde _clyde = default!;
|
||||
[Dependency] private readonly IResourceManager _resourceManager = default!;
|
||||
[Dependency] private readonly IClientNetManager _netManager = default!;
|
||||
[Dependency] private readonly ILogManager _logManager = default!;
|
||||
|
||||
private ISawmill _sawmill = default!;
|
||||
|
||||
public static readonly ResPath ProtonPath = new ResPath("/Proton");
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
_sawmill = _logManager.GetSawmill("proton");
|
||||
|
||||
_resourceManager.UserData.CreateDir(ProtonPath);
|
||||
|
||||
_sawmill.Debug($"Proton Manager successfully initialized");
|
||||
|
||||
// Registration of messages
|
||||
_netManager.RegisterNetMessage<ProtonRequestScreenshotClient>(HandleRequestScreenshot);
|
||||
_netManager.RegisterNetMessage<ProtonRequestScreenshotServer>();
|
||||
_netManager.RegisterNetMessage<ProtonResponseScreenshotClient>();
|
||||
_netManager.RegisterNetMessage<ProtonResponseScreenshotServer>(HandleResponseScreenshot);
|
||||
}
|
||||
|
||||
private void HandleRequestScreenshot(ProtonRequestScreenshotClient request)
|
||||
{
|
||||
_clyde.Screenshot(ScreenshotType.Final, pixels => {HandleScreenshot(ref request, pixels);});
|
||||
|
||||
_sawmill.Debug($"Successfully handled screenshot request");
|
||||
}
|
||||
|
||||
private void HandleScreenshot(ref ProtonRequestScreenshotClient request, Image<Rgb24> screenshot)
|
||||
{
|
||||
var response = new ProtonResponseScreenshotClient()
|
||||
{
|
||||
Screenshot = screenshot,
|
||||
};
|
||||
_netManager.ClientSendMessage(response);
|
||||
|
||||
_sawmill.Debug($"Successfully sent screenshot request");
|
||||
}
|
||||
|
||||
private void HandleResponseScreenshot(ProtonResponseScreenshotServer response)
|
||||
{
|
||||
if (response.Screenshot == null)
|
||||
{
|
||||
_sawmill.Debug($"Received response with null screenshot");
|
||||
return;
|
||||
}
|
||||
|
||||
var path = ProtonPath / $"test-{response.Screenshot.GetHashCode()}.png";
|
||||
|
||||
using var stream = _resourceManager.UserData.OpenWrite(path);
|
||||
response.Screenshot.SaveAsPng(stream);
|
||||
|
||||
_sawmill.Debug($"Successfully received screenshot and saved it to {path}");
|
||||
stream.Close();
|
||||
|
||||
using var imageStream = _resourceManager.UserData.OpenRead(path);
|
||||
var view = new ProtonScreenshotView(Texture.LoadFromPNGStream(imageStream, "screenshot"));
|
||||
view.OpenCentered();
|
||||
imageStream.Close();
|
||||
|
||||
_sawmill.Debug($"Opened window (centered) successfully");
|
||||
}
|
||||
}
|
||||
10
Content.Client/_Sunrise/Proton/ProtonScreenshotView.xaml
Normal file
10
Content.Client/_Sunrise/Proton/ProtonScreenshotView.xaml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<controls:FancyWindow
|
||||
xmlns="https://spacestation14.io"
|
||||
xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
xmlns:latejoin="clr-namespace:Content.Client._Sunrise.Proton"
|
||||
Title="{Loc 'admin-player-actions-screenshot'}"
|
||||
HorizontalExpand="True"
|
||||
VerticalExpand="True">
|
||||
<TextureRect Name="TextureRect"></TextureRect>
|
||||
</controls:FancyWindow>
|
||||
20
Content.Client/_Sunrise/Proton/ProtonScreenshotView.xaml.cs
Normal file
20
Content.Client/_Sunrise/Proton/ProtonScreenshotView.xaml.cs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
using System.Numerics;
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
namespace Content.Client._Sunrise.Proton;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class ProtonScreenshotView : FancyWindow
|
||||
{
|
||||
public ProtonScreenshotView(Texture image)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
TextureRect.Texture = image;
|
||||
TextureRect.TextureScale = new Vector2(0.7f, 0.7f);
|
||||
}
|
||||
}
|
||||
28
Content.Client/_Sunrise/Proton/ScreenshotCommand.cs
Normal file
28
Content.Client/_Sunrise/Proton/ScreenshotCommand.cs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
using Content.Shared._Sunrise.Proton;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
namespace Content.Client._Sunrise.Proton;
|
||||
|
||||
public sealed class ScreenshotCommand : LocalizedCommands
|
||||
{
|
||||
[Dependency] private readonly IClientNetManager _netManager = default!;
|
||||
|
||||
public override string Command => "screenshot";
|
||||
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length < 1)
|
||||
{
|
||||
shell.WriteLine($"You need to provide a player to screenshot. Try running 'screenshot (playername)' as an example");
|
||||
return;
|
||||
}
|
||||
|
||||
var name = args[0];
|
||||
var message = new ProtonRequestScreenshotServer()
|
||||
{
|
||||
Target = name,
|
||||
};
|
||||
_netManager.ClientSendMessage(message);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
using Content.Server._Sunrise.GuideGenerator;
|
||||
using Content.Server._Sunrise.Proton; // Sunrise-Proton
|
||||
using Content.Server._Sunrise.ServersHub;
|
||||
using Content.Server._Sunrise.TTS;
|
||||
using Content.Server.Acz;
|
||||
|
|
@ -48,6 +49,7 @@ namespace Content.Server.Entry
|
|||
private IVoteManager _voteManager = default!;
|
||||
private ServerUpdateManager _updateManager = default!;
|
||||
private ServersHubManager _serversHubManager = default!; // Sunrise-Edit
|
||||
private ProtonManager _proton = default!; // Proton
|
||||
private PlayTimeTrackingManager? _playTimeTracking;
|
||||
private IEntitySystemManager? _sysMan;
|
||||
private IServerDbManager? _dbManager;
|
||||
|
|
@ -95,6 +97,7 @@ namespace Content.Server.Entry
|
|||
_voteManager = IoCManager.Resolve<IVoteManager>();
|
||||
_updateManager = IoCManager.Resolve<ServerUpdateManager>();
|
||||
_serversHubManager = IoCManager.Resolve<ServersHubManager>(); // Sunrise-Edit
|
||||
_proton = IoCManager.Resolve<ProtonManager>(); // Proton
|
||||
_playTimeTracking = IoCManager.Resolve<PlayTimeTrackingManager>();
|
||||
_sysMan = IoCManager.Resolve<IEntitySystemManager>();
|
||||
_dbManager = IoCManager.Resolve<IServerDbManager>();
|
||||
|
|
@ -114,6 +117,7 @@ namespace Content.Server.Entry
|
|||
IoCManager.Resolve<ServerApi>().Initialize();
|
||||
|
||||
IoCManager.Resolve<ServersHubManager>().Initialize(); // Sunrise-Hub
|
||||
IoCManager.Resolve<ProtonManager>().Initialize(); // Proton
|
||||
|
||||
_voteManager.Initialize();
|
||||
_updateManager.Initialize();
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using Content.Server._Sunrise.Proton; // Sunrise-Proton
|
||||
using Content.Server._Sunrise.ServersHub;
|
||||
using Content.Server._Sunrise.TTS;
|
||||
using Content.Server.Administration;
|
||||
|
|
@ -74,6 +75,7 @@ namespace Content.Server.IoC
|
|||
IoCManager.Register<MappingManager>();
|
||||
|
||||
IoCManager.Register<ServersHubManager>(); // Sunrise-Hub
|
||||
IoCManager.Register<ProtonManager>(); // Sunrise-Proton
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
144
Content.Server/_Sunrise/Proton/ServerProtonManager.cs
Normal file
144
Content.Server/_Sunrise/Proton/ServerProtonManager.cs
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
using Content.Server.Administration;
|
||||
using Content.Server.Administration.Managers;
|
||||
using Content.Shared._Sunrise.Proton;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Administration.Managers;
|
||||
using Robust.Server.Console;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Timing;
|
||||
using Timer = Robust.Shared.Timing.Timer;
|
||||
|
||||
namespace Content.Server._Sunrise.Proton;
|
||||
|
||||
public struct ProtonRequest
|
||||
{
|
||||
public NetUserId Admin { get; set; }
|
||||
public TimeSpan TimeStamp { get; set; }
|
||||
}
|
||||
|
||||
public sealed class ProtonManager
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly IServerNetManager _netManager = default!;
|
||||
[Dependency] private readonly ILogManager _logManager = default!;
|
||||
[Dependency] private readonly ISharedAdminManager _adminManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IBanManager _banManager = default!;
|
||||
[Dependency] private readonly IPlayerLocator _locator = default!;
|
||||
[Dependency] private readonly IServerConsoleHost _console = default!;
|
||||
|
||||
private ISawmill _sawmill = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Стэк реквестов,
|
||||
/// ключ - кому был дан запрос
|
||||
/// значение - от кого был запрос
|
||||
/// </summary>
|
||||
private Dictionary<NetUserId, ProtonRequest> _requests = new ();
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
_sawmill = _logManager.GetSawmill("proton");
|
||||
_sawmill.Debug($"Proton Manager successfully initialized");
|
||||
|
||||
// Registration of messages
|
||||
_netManager.RegisterNetMessage<ProtonRequestScreenshotClient>();
|
||||
_netManager.RegisterNetMessage<ProtonRequestScreenshotServer>(HandleScreenshotRequest);
|
||||
_netManager.RegisterNetMessage<ProtonResponseScreenshotClient>(HandleScreenshotResponse);
|
||||
_netManager.RegisterNetMessage<ProtonResponseScreenshotServer>();
|
||||
}
|
||||
|
||||
private void HandleScreenshotRequest(ProtonRequestScreenshotServer request)
|
||||
{
|
||||
var admin = _playerManager.GetSessionById(request.MsgChannel.UserId);
|
||||
if (!_adminManager.HasAdminFlag(admin, AdminFlags.Moderator))
|
||||
{
|
||||
_sawmill.Debug($"{request.MsgChannel.UserName} requested screenshot without proper admin flags");
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.Target == null)
|
||||
{
|
||||
_sawmill.Debug($"requested screenshot for null player");
|
||||
return;
|
||||
}
|
||||
|
||||
var req = new ProtonRequestScreenshotClient();
|
||||
if (!_playerManager.TryGetSessionByUsername(request.Target, out var targetSession))
|
||||
{
|
||||
_sawmill.Debug($"requested screenshot for unexisting player");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_requests.ContainsKey(targetSession.UserId))
|
||||
{
|
||||
_sawmill.Error($"Multiple requests of one screenshot");
|
||||
return;
|
||||
}
|
||||
|
||||
_netManager.ServerSendMessage(req, targetSession.Channel);
|
||||
|
||||
_requests.Add(targetSession.UserId, new ProtonRequest() { Admin = admin.UserId, TimeStamp = _gameTiming.CurTime });
|
||||
|
||||
_sawmill.Debug($"{request.MsgChannel.UserName} successfully requested screenshot of {targetSession.Channel.UserName}");
|
||||
|
||||
Timer.Spawn(TimeSpan.FromSeconds(30), () => {CheckTimerOnFired(targetSession);});
|
||||
}
|
||||
|
||||
private async void CheckTimerOnFired(ICommonSession session)
|
||||
{
|
||||
if (!_requests.ContainsKey(session.UserId))
|
||||
return;
|
||||
|
||||
BanPlayer(session, "Это автоматический бан. Клиент не ответил на пакет в течении заданного времени");
|
||||
|
||||
_sawmill.Debug($"Successfully banned {session.UserId} for not answering a packet");
|
||||
}
|
||||
|
||||
private void BanPlayer(ICommonSession session, string message)
|
||||
{
|
||||
_console.ExecuteCommand($"ban {session.UserId} \"{message}\" 0 high");
|
||||
}
|
||||
|
||||
private void HandleScreenshotResponse(ProtonResponseScreenshotClient response)
|
||||
{
|
||||
var session = _playerManager.GetSessionById(response.MsgChannel.UserId);
|
||||
|
||||
if (!_requests.ContainsKey(response.MsgChannel.UserId))
|
||||
{
|
||||
_sawmill.Debug($"Received screenshot response without screenshot");
|
||||
BanPlayer(session, "Это автоматический бан. Клиент отправил пустой пакет.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.Screenshot == null)
|
||||
{
|
||||
_sawmill.Debug($"Received screenshot response with null screenshot");
|
||||
BanPlayer(session, "Это автоматический бан. Клиент отправил пустой пакет.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.Screenshot.Height > 5000 || response.Screenshot.Width > 5000)
|
||||
{
|
||||
_sawmill.Debug($"Received screenshot response with too big screenshot");
|
||||
BanPlayer(session, "Это автоматический бан. Клиент отправил слишком большой пакет.");
|
||||
return;
|
||||
}
|
||||
|
||||
var entry = _requests[response.MsgChannel.UserId];
|
||||
|
||||
var resp = new ProtonResponseScreenshotServer()
|
||||
{
|
||||
Screenshot = response.Screenshot,
|
||||
};
|
||||
|
||||
var admin = _playerManager.GetSessionById(entry.Admin);
|
||||
_netManager.ServerSendMessage(resp, admin.Channel);
|
||||
|
||||
_requests.Remove(response.MsgChannel.UserId);
|
||||
}
|
||||
}
|
||||
42
Content.Shared/_Sunrise/Proton/ProtonRequests.cs
Normal file
42
Content.Shared/_Sunrise/Proton/ProtonRequests.cs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
using Lidgren.Network;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._Sunrise.Proton;
|
||||
|
||||
/// <summary>
|
||||
/// Request client to send screenshot
|
||||
/// </summary>
|
||||
public sealed class ProtonRequestScreenshotClient : NetMessage
|
||||
{
|
||||
public override MsgGroups MsgGroup => MsgGroups.Core;
|
||||
|
||||
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer)
|
||||
{
|
||||
}
|
||||
|
||||
public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send request for a screenshot of screen of a specific player
|
||||
/// </summary>
|
||||
public sealed class ProtonRequestScreenshotServer : NetMessage
|
||||
{
|
||||
public override MsgGroups MsgGroup => MsgGroups.Command;
|
||||
|
||||
// Data sent
|
||||
public string? Target;
|
||||
|
||||
public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer)
|
||||
{
|
||||
buffer.Write(Target);
|
||||
}
|
||||
|
||||
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer)
|
||||
{
|
||||
Target = buffer.ReadString();
|
||||
}
|
||||
}
|
||||
99
Content.Shared/_Sunrise/Proton/ProtonResponses.cs
Normal file
99
Content.Shared/_Sunrise/Proton/ProtonResponses.cs
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
using System.IO;
|
||||
using Lidgren.Network;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Serialization;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
|
||||
namespace Content.Shared._Sunrise.Proton;
|
||||
|
||||
// Maybe we could use one type of message to both get screenshot from client to server and send screenshot from server
|
||||
// to admin, who requested this screenshot.
|
||||
|
||||
/// <summary>
|
||||
/// Response, containing screenshot of client's window
|
||||
/// </summary>
|
||||
public sealed class ProtonResponseScreenshotClient : NetMessage
|
||||
{
|
||||
public override MsgGroups MsgGroup => MsgGroups.Command;
|
||||
|
||||
// Data sent
|
||||
public Image<Rgb24>? Screenshot;
|
||||
|
||||
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer)
|
||||
{
|
||||
var imageDataLength = buffer.ReadInt32();
|
||||
|
||||
if (imageDataLength == 0)
|
||||
{
|
||||
Screenshot = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var imageData = buffer.ReadBytes(imageDataLength);
|
||||
|
||||
using var memoryStream = new MemoryStream(imageData);
|
||||
Screenshot = Image.Load<Rgb24>(memoryStream);
|
||||
}
|
||||
|
||||
public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer)
|
||||
{
|
||||
if (Screenshot == null)
|
||||
{
|
||||
buffer.Write(0);
|
||||
return;
|
||||
}
|
||||
|
||||
using var memoryStream = new MemoryStream();
|
||||
Screenshot.SaveAsPng(memoryStream);
|
||||
var imageData = memoryStream.ToArray();
|
||||
|
||||
buffer.Write(imageData.Length);
|
||||
|
||||
buffer.Write(imageData);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Screenshot, sent from server to target admin
|
||||
/// </summary>
|
||||
public sealed class ProtonResponseScreenshotServer : NetMessage
|
||||
{
|
||||
public override MsgGroups MsgGroup => MsgGroups.Command;
|
||||
|
||||
// Data sent
|
||||
public Image<Rgb24>? Screenshot;
|
||||
|
||||
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer)
|
||||
{
|
||||
var imageDataLength = buffer.ReadInt32();
|
||||
|
||||
if (imageDataLength == 0)
|
||||
{
|
||||
Screenshot = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var imageData = buffer.ReadBytes(imageDataLength);
|
||||
|
||||
using var memoryStream = new MemoryStream(imageData);
|
||||
Screenshot = Image.Load<Rgb24>(memoryStream);
|
||||
}
|
||||
|
||||
public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer)
|
||||
{
|
||||
if (Screenshot == null)
|
||||
{
|
||||
buffer.Write(0);
|
||||
return;
|
||||
}
|
||||
|
||||
using var memoryStream = new MemoryStream();
|
||||
Screenshot.SaveAsPng(memoryStream);
|
||||
var imageData = memoryStream.ToArray();
|
||||
|
||||
buffer.Write(imageData.Length);
|
||||
|
||||
buffer.Write(imageData);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
admin-player-actions-screenshot = Screenshot
|
||||
|
|
@ -0,0 +1 @@
|
|||
admin-player-actions-screenshot = Просмотр экрана
|
||||
Loading…
Add table
Reference in a new issue