using System.Linq;
using Content.Shared.Radio;
using Content.Server.DeviceNetwork.Systems;
using Content.Shared.DeviceNetwork.Events;
using Content.Server.Station.Systems;
using Content.Shared.GameTicking;
using Content.Shared.DeviceNetwork;
using Content.Shared.DeviceNetwork.Components;
using Content.Shared._Sunrise.Messenger;
using Content.Shared.Inventory;
using Robust.Shared.Prototypes;
using Content.Server.CartridgeLoader;
using Content.Server.DeviceNetwork.Components;
using Robust.Shared.Random;
namespace Content.Server._Sunrise.Messenger;
///
/// Система сервера мессенджера, обрабатывающая сообщения между КПК
///
public sealed partial class MessengerServerSystem : EntitySystem
{
[Dependency] private readonly DeviceNetworkSystem _deviceNetwork = default!;
[Dependency] private readonly SingletonDeviceNetServerSystem _singletonServer = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly StationSystem _stationSystem = default!;
[Dependency] private readonly ILogManager _logManager = default!;
[Dependency] private readonly ILocalizationManager _loc = default!;
[Dependency] private readonly InventorySystem _inventory = default!;
[Dependency] private readonly CartridgeLoaderSystem _cartridgeLoader = default!;
[Dependency] private readonly IRobustRandom _random = default!;
private ISawmill Sawmill { get; set; } = default!;
///
/// Находит GroupId для указанного радиоканала
///
public string? GetGroupIdByRadioChannel(string radioChannelId)
{
foreach (var proto in _prototypeManager.EnumeratePrototypes())
{
if (proto.RadioChannel == radioChannelId)
return proto.GroupId;
}
return null;
}
public override void Initialize()
{
base.Initialize();
Sawmill = _logManager.GetSawmill("messenger.server");
SubscribeLocalEvent(OnPacketReceived);
SubscribeLocalEvent(OnServerConnected);
SubscribeLocalEvent(OnServerDisconnected);
SubscribeLocalEvent(OnRoundRestart);
SubscribeLocalEvent(OnPlayerSpawnComplete);
InitializeSpam();
}
public override void Update(float frameTime)
{
base.Update(frameTime);
UpdateSpam(frameTime);
}
private void OnRoundRestart(EntityUid uid, MessengerServerComponent component, RoundRestartCleanupEvent args)
{
component.Users.Clear();
component.Groups.Clear();
component.MessageHistory.Clear();
component.GroupIdCounter = 0;
component.MessageIdCounter = 0;
}
private void OnServerConnected(EntityUid uid, MessengerServerComponent component, ref DeviceNetServerConnectedEvent args)
{
Sawmill.Info($"Messenger server connected: {ToPrettyString(uid)}");
if (!TryComp(uid, out var serverDevice))
{
Sawmill.Error($"Server DeviceNetwork component not found: {ToPrettyString(uid)}");
return;
}
if (!_deviceNetwork.IsDeviceConnected(uid, serverDevice))
{
if (!_deviceNetwork.ConnectDevice(uid, serverDevice))
{
return;
}
}
CreateAutoGroups(component);
foreach (var user in component.Users.Values)
{
AddUserToAutoGroups(uid, component, user.UserId, user.Name, user.DepartmentIds);
}
}
private void OnServerDisconnected(EntityUid uid, MessengerServerComponent component, ref DeviceNetServerDisconnectedEvent args)
{
}
private void OnPacketReceived(EntityUid uid, MessengerServerComponent component, DeviceNetworkPacketEvent args)
{
if (!_singletonServer.IsActiveServer(uid))
{
return;
}
if (!args.Data.TryGetValue(DeviceNetworkConstants.Command, out string? command))
{
return;
}
switch (command)
{
case MessengerCommands.CmdRegisterUser:
HandleRegisterUser(uid, component, args);
break;
case MessengerCommands.CmdSendMessage:
HandleSendMessage(uid, component, args);
break;
case MessengerCommands.CmdCreateGroup:
HandleCreateGroup(uid, component, args);
break;
case MessengerCommands.CmdAddToGroup:
HandleAddToGroup(uid, component, args);
break;
case MessengerCommands.CmdRemoveFromGroup:
HandleRemoveFromGroup(uid, component, args);
break;
case MessengerCommands.CmdGetUsers:
HandleGetUsers(uid, component, args);
break;
case MessengerCommands.CmdGetGroups:
HandleGetGroups(uid, component, args);
break;
case MessengerCommands.CmdGetMessages:
HandleGetMessages(uid, component, args);
break;
case MessengerCommands.CmdAcceptInvite:
HandleAcceptInvite(uid, component, args);
break;
case MessengerCommands.CmdDeclineInvite:
HandleDeclineInvite(uid, component, args);
break;
case MessengerCommands.CmdLeaveGroup:
HandleLeaveGroup(uid, component, args);
break;
case MessengerCommands.CmdDeleteMessage:
HandleDeleteMessage(uid, component, args);
break;
default:
Sawmill.Warning($"Unknown command received: {command} from {args.SenderAddress}");
break;
}
}
///
/// Генерирует ID для личного чата между двумя пользователями
///
private string GetPersonalChatId(string userId1, string userId2)
{
var ids = new[] { userId1, userId2 }.OrderBy(x => x).ToArray();
return $"personal_{ids[0]}_{ids[1]}";
}
///
/// Ограничивает историю сообщений до указанного количества
///
private void TrimMessageHistory(List history, int maxCount)
{
if (history.Count > maxCount)
{
var toRemove = history.Count - maxCount;
history.RemoveRange(0, toRemove);
}
}
///
/// Получает время станции (обычное время, как в КПК)
///
private TimeSpan GetStationTime()
{
return (DateTime.UtcNow + TimeSpan.FromHours(3)).TimeOfDay;
}
///
/// Получает следующий уникальный ID сообщения
///
private long GetNextMessageId(EntityUid uid, MessengerServerComponent component)
{
return ++component.MessageIdCounter;
}
///
/// Находит сущность сервера мессенджера для станции
///
public (EntityUid, MessengerServerComponent)? GetServerEntity(EntityUid? station)
{
if (station == null)
return null;
var query = EntityQueryEnumerator();
while (query.MoveNext(out var uid, out var comp, out var singleton))
{
if (!_singletonServer.IsActiveServer(uid, singleton))
continue;
if (_stationSystem.GetOwningStation(uid) != station)
continue;
return (uid, comp);
}
return null;
}
}