From 0964ee123ade4c2279d4af0e570ff8faa982eb3d Mon Sep 17 00:00:00 2001 From: Cinkafox <70429757+Cinkafox@users.noreply.github.com> Date: Thu, 17 Aug 2023 23:41:13 +0300 Subject: [PATCH] Ert fix (#317) * Hotfix * Fuck custom server event! Hello gamerule! * add some shit * oopsie * Add CCVAR of loading a ERT map and disable it on dev build --- .../White/AuthPanel/AuthPanelSystem.cs | 33 +-- .../White/ERTRecruitment/Commands/BlockERT.cs | 10 +- .../White/ERTRecruitment/ERTMapComponent.cs | 16 ++ .../ERTRecruitment/ERTRecruitedReasonEvent.cs | 13 ++ .../ERTRecruitment/ERTRecruitmentRule.cs | 193 ++++++++++++++++ .../ERTRecruitmentRuleComponent.cs | 28 +++ .../ERTRecruitment/ERTRecruitmentSystem.cs | 213 ------------------ .../GhostRecruitmentEvents.cs | 7 +- .../GhostRecruitmentSystem.cs | 67 ++++-- .../ServerEvent/Commands/StartServerEvent.cs | 35 --- .../White/ServerEvent/ServerEventSystem.cs | 122 ---------- .../White/AuthPanel/AuthPanelComponent.cs | 2 +- .../GhostRecruitedComponent.cs | 2 +- .../GhostRecruitmentEvents.cs | 21 -- .../GhostRecruitmentSpawnPointComponent.cs | 2 +- .../GhostRecruitment/RecruitedComponent.cs | 2 +- .../White/ServerEvent/Data/IEventAction.cs | 7 - Content.Shared/White/ServerEvent/Events.cs | 26 --- .../White/ServerEvent/ServerEventPrototype.cs | 31 --- Content.Shared/White/WhiteCVars.cs | 8 + .../ConfigPresets/Build/development.toml | 3 + .../Prototypes/White/event_prototypes.yml | 15 +- 22 files changed, 347 insertions(+), 509 deletions(-) create mode 100644 Content.Server/White/ERTRecruitment/ERTMapComponent.cs create mode 100644 Content.Server/White/ERTRecruitment/ERTRecruitedReasonEvent.cs create mode 100644 Content.Server/White/ERTRecruitment/ERTRecruitmentRule.cs create mode 100644 Content.Server/White/ERTRecruitment/ERTRecruitmentRuleComponent.cs delete mode 100644 Content.Server/White/ERTRecruitment/ERTRecruitmentSystem.cs delete mode 100644 Content.Server/White/ServerEvent/Commands/StartServerEvent.cs delete mode 100644 Content.Server/White/ServerEvent/ServerEventSystem.cs delete mode 100644 Content.Shared/White/ServerEvent/Data/IEventAction.cs delete mode 100644 Content.Shared/White/ServerEvent/Events.cs delete mode 100644 Content.Shared/White/ServerEvent/ServerEventPrototype.cs diff --git a/Content.Server/White/AuthPanel/AuthPanelSystem.cs b/Content.Server/White/AuthPanel/AuthPanelSystem.cs index b02de6b4db..7aeafd9543 100644 --- a/Content.Server/White/AuthPanel/AuthPanelSystem.cs +++ b/Content.Server/White/AuthPanel/AuthPanelSystem.cs @@ -1,13 +1,13 @@ -using Content.Server.Access.Systems; +using Content.Server.GameTicking; using Content.Server.Popups; +using Content.Server.Station.Systems; using Content.Server.White.ERTRecruitment; -using Content.Server.White.ServerEvent; using Content.Shared.Access.Systems; using Content.Shared.Administration.Logs; using Content.Shared.Database; using Content.Shared.GameTicking; using Content.Shared.White.AuthPanel; -using Content.Shared.White.Cyborg.Components; +using Content.Shared.White.GhostRecruitment; using Robust.Server.GameObjects; using Robust.Shared.Random; using Robust.Shared.Timing; @@ -20,11 +20,12 @@ public sealed class AuthPanelSystem : EntitySystem [Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly AccessReaderSystem _access = default!; [Dependency] private readonly AppearanceSystem _appearance = default!; - [Dependency] private readonly ServerEventSystem _event = default!; [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly IRobustRandom _random = default!; - [Dependency] private readonly ERTRecruitmentSystem _ert = default!; [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; + [Dependency] private readonly ERTRecruitmentRule _ert = default!; + [Dependency] private readonly GameTicker _gameTicker = default!; + [Dependency] private readonly StationSystem _station = default!; public Dictionary> Counter = new(); public Dictionary> CardIndexes = new(); @@ -38,10 +39,16 @@ public sealed class AuthPanelSystem : EntitySystem { SubscribeLocalEvent(OnButtonPressed); SubscribeLocalEvent(OnPerformAction); + SubscribeLocalEvent(OnReason); SubscribeLocalEvent(OnRestart); } + private void OnReason(EntityUid uid, RecruitedComponent component, ERTRecruitedReasonEvent args) + { + args.Reason = Reason; + } + private void OnRestart(RoundRestartCleanupEvent ev) { Counter.Clear(); @@ -54,15 +61,16 @@ public sealed class AuthPanelSystem : EntitySystem { if (args.Action is AuthPanelAction.ERTRecruit) { - if (_random.Next(0, 10) < 2 - && _event.TryStartEvent(ERTRecruitmentSystem.EventName) - && _event.TryGetEvent(ERTRecruitmentSystem.EventName,out var eventPrototype)) + if (_random.Next(10) < 2) { - eventPrototype.Description = Reason; + _gameTicker.AddGameRule(ERTRecruitmentRuleComponent.EventName); } else { - _ert.DeclineERT(); + var station = _station.GetStationInMap(Transform(uid).MapID); + + if (station != null) + _ert.DeclineERT(station.Value); } foreach (var entities in Counter.Values) @@ -81,9 +89,6 @@ public sealed class AuthPanelSystem : EntitySystem if(args.Session.AttachedEntity == null) return; - if(HasComp(args.Session.AttachedEntity)) - return; - var access = _access.FindAccessTags(args.Session.AttachedEntity.Value); if (!access.Contains("Command")) @@ -168,7 +173,7 @@ public sealed class AuthPanelSystem : EntitySystem var state = new AuthPanelConfirmationActionState(action); var ui = _ui.GetUi(uid, AuthPanelUiKey.Key); - UserInterfaceSystem.SetUiState(ui, state); + _ui.SetUiState(ui, state); _appearance.SetData(uid,AuthPanelVisualLayers.Confirm,true); } } diff --git a/Content.Server/White/ERTRecruitment/Commands/BlockERT.cs b/Content.Server/White/ERTRecruitment/Commands/BlockERT.cs index 158f389388..3b717a49d3 100644 --- a/Content.Server/White/ERTRecruitment/Commands/BlockERT.cs +++ b/Content.Server/White/ERTRecruitment/Commands/BlockERT.cs @@ -16,16 +16,16 @@ public sealed class BlockERT : IConsoleCommand public string Help => "blockert "; public void Execute(IConsoleShell shell, string argStr, string[] args) { - var ertsys = _entities.System(); - var isBlocked = !ertsys.IsBlocked; + var ertsys = _entities.System(); + var isDisabled = !ertsys.IsDisabled; if (args.Length > 0) { - isBlocked = args[0] == "true"; + isDisabled = args[0] == "true"; } - ertsys.IsBlocked = isBlocked; - var message = isBlocked ? "ERT is blocked!" : "ERT is no longer blocked!"; + ertsys.IsDisabled = isDisabled; + var message = isDisabled ? "ERT is blocked!" : "ERT is no longer blocked!"; shell.WriteLine(message); _chatManager.SendAdminAnnouncement(message); } diff --git a/Content.Server/White/ERTRecruitment/ERTMapComponent.cs b/Content.Server/White/ERTRecruitment/ERTMapComponent.cs new file mode 100644 index 0000000000..43fcd31558 --- /dev/null +++ b/Content.Server/White/ERTRecruitment/ERTMapComponent.cs @@ -0,0 +1,16 @@ +using Robust.Shared.Map; +using Robust.Shared.Utility; + +namespace Content.Server.White.ERTRecruitment; + +[RegisterComponent] +public sealed partial class ERTMapComponent : Component +{ + [ViewVariables] + public MapId? MapId; + [ViewVariables] + public EntityUid? Shuttle; + + public static ResPath OutpostMap = new("/Maps/ERT/ERTStation.yml"); + public static ResPath ShuttleMap = new("/Maps/ERT/ERTShuttle.yml"); +} diff --git a/Content.Server/White/ERTRecruitment/ERTRecruitedReasonEvent.cs b/Content.Server/White/ERTRecruitment/ERTRecruitedReasonEvent.cs new file mode 100644 index 0000000000..fbdcf2d01f --- /dev/null +++ b/Content.Server/White/ERTRecruitment/ERTRecruitedReasonEvent.cs @@ -0,0 +1,13 @@ +namespace Content.Server.White.ERTRecruitment; + +[Serializable] +public sealed class ERTRecruitedReasonEvent : EntityEventArgs +{ + public string Reason = ""; + + public void SetReason(string reason) + { + Reason = reason; + } + +} diff --git a/Content.Server/White/ERTRecruitment/ERTRecruitmentRule.cs b/Content.Server/White/ERTRecruitment/ERTRecruitmentRule.cs new file mode 100644 index 0000000000..6a79218e06 --- /dev/null +++ b/Content.Server/White/ERTRecruitment/ERTRecruitmentRule.cs @@ -0,0 +1,193 @@ +using System.Linq; +using System.Numerics; +using Content.Server.Chat.Managers; +using Content.Server.Chat.Systems; +using Content.Server.GameTicking; +using Content.Server.GameTicking.Rules.Components; +using Content.Server.Shuttles.Components; +using Content.Server.Shuttles.Systems; +using Content.Server.StationEvents.Events; +using Content.Server.White.GhostRecruitment; +using Content.Shared.CCVar; +using Content.Shared.White; +using Content.Shared.White.GhostRecruitment; +using JetBrains.Annotations; +using Robust.Server.GameObjects; +using Robust.Server.Maps; +using Robust.Shared.Configuration; +using Robust.Shared.Map; + +namespace Content.Server.White.ERTRecruitment; + +[UsedImplicitly] +public sealed class ERTRecruitmentRule : StationEventSystem +{ + [Dependency] private readonly IChatManager _chat = default!; + [Dependency] private readonly GhostRecruitmentSystem _recruitment = default!; + [Dependency] private readonly IMapManager _mapManager = default!; + [Dependency] private readonly MapLoaderSystem _map = default!; + [Dependency] private readonly ShuttleSystem _shuttle = default!; + [Dependency] private readonly ChatSystem _chatSystem = default!; + [Dependency] private readonly IConfigurationManager _cfgManager = default!; + + private ISawmill _logger = default!; + + public bool IsDisabled = false; + + public override void Initialize() + { + base.Initialize(); + + _logger = Logger.GetSawmill("ERTRecruit"); + SubscribeLocalEvent(OnStartAttempt); + SubscribeLocalEvent(OnRecruitmentSuccess); + } + + protected override void Added(EntityUid uid, ERTRecruitmentRuleComponent component, GameRuleComponent gameRule, GameRuleAddedEvent args) + { + base.Added(uid, component, gameRule, args); + + if (TryGetRandomStation(out var stationUid)) + { + component.TargetStation = stationUid; + } + + if (IsDisabled) + { + if (component.TargetStation != null) + DeclineERT(component.TargetStation.Value); + + component.IsBlocked = true; + return; + } + + var query = EntityQueryEnumerator(); + if (query.MoveNext(out uid, out var ertMapComponent)) + { + component.Outpost = uid; + component.Shuttle = ertMapComponent.Shuttle; + component.MapId = ertMapComponent.MapId; + } + } + + protected override void Started(EntityUid uid, ERTRecruitmentRuleComponent component, GameRuleComponent gameRule, + GameRuleStartedEvent args) + { + base.Started(uid, component, gameRule, args); + _logger.Debug("Event is started"); + + if (component.TargetStation == null || component.IsBlocked) + { + ForceEndSelf(uid,gameRule); + _logger.Debug("oopsie doopsie we make a poopie poopie on starting event!"); + return; + } + + if (_recruitment.GetEventSpawners(ERTRecruitmentRuleComponent.EventName).Count() < component.MinPlayer) + { + _logger.Error("Not enough spawners!"); + + DeclineERT(component.TargetStation.Value); + return; + } + + _chatSystem.DispatchStationAnnouncement(component.TargetStation.Value,Loc.GetString("ert-wait-message"),colorOverride: Color.Gold); + + if (TryComp(component.Shuttle, out var shuttle) && component.Outpost != null) + { + _shuttle.TryFTLDock(component.Shuttle.Value, shuttle, component.Outpost.Value); + } + + _recruitment.StartRecruitment(ERTRecruitmentRuleComponent.EventName); + } + + protected override void Ended(EntityUid uid, ERTRecruitmentRuleComponent component, GameRuleComponent gameRule, GameRuleEndedEvent args) + { + base.Ended(uid, component, gameRule, args); + + if (component.IsBlocked || _recruitment.GetAllRecruited(ERTRecruitmentRuleComponent.EventName).Count() < component.MinPlayer || + !_recruitment.EndRecruitment(ERTRecruitmentRuleComponent.EventName)) + { + if (component.TargetStation != null) + DeclineERT(component.TargetStation.Value); + _recruitment.Cleanup(ERTRecruitmentRuleComponent.EventName); + return; + } + + if (component.TargetStation != null) + AcceptERT(component.TargetStation.Value); + } + + private void OnRecruitmentSuccess(EntityUid uid, RecruitedComponent component, GhostRecruitmentSuccessEvent args) + { + var ev = new ERTRecruitedReasonEvent(); + RaiseLocalEvent(uid,ev); + + _chat.DispatchServerMessage(args.PlayerSession,Loc.GetString("ert-description")); + _chat.DispatchServerMessage(args.PlayerSession, Loc.GetString("ert-reason", ("reason", ev.Reason))); + } + + private void OnStartAttempt(RoundStartAttemptEvent ev) + { + if(_cfgManager.GetCVar(WhiteCVars.LoadERTMap)) + SpawnMap(); + } + + + public void AcceptERT(EntityUid targetStation) + { + _chatSystem.DispatchStationAnnouncement(targetStation,Loc.GetString("ert-accept-message"), + colorOverride: Color.Gold,announcementSound:ERTRecruitmentRuleComponent.ERTYes); + } + + public void DeclineERT(EntityUid targetStation) + { + _chatSystem.DispatchStationAnnouncement(targetStation,Loc.GetString("ert-deny-message"), + colorOverride: Color.Gold,announcementSound:ERTRecruitmentRuleComponent.ERTNo); + } + + private bool SpawnMap() + { + _logger.Debug($"Loading maps!"); + + var mapId = _mapManager.CreateMap(); + var options = new MapLoadOptions + { + LoadMap = true, + }; + + if (!_map.TryLoad(mapId, ERTMapComponent.OutpostMap.ToString(), out var outpostGrids, options) || outpostGrids.Count == 0) + { + _logger.Error( $"Error loading map {ERTMapComponent.OutpostMap}!"); + return false; + } + _logger.Debug($"Loaded map {ERTMapComponent.OutpostMap} on {mapId}!"); + + // Assume the first grid is the outpost grid. + var outpost = outpostGrids[0]; + + // Listen I just don't want it to overlap. + if (!_map.TryLoad(mapId, ERTMapComponent.ShuttleMap.ToString(), out var grids, new MapLoadOptions {Offset = Vector2.One * 1000f}) || !grids.Any()) + { + _logger.Error( $"Error loading grid {ERTMapComponent.ShuttleMap}!"); + return false; + } + _logger.Debug($"Loaded shuttle {ERTMapComponent.ShuttleMap} on {mapId}!"); + + var shuttleId = grids.First(); + + // Naughty, someone saved the shuttle as a map. + if (Deleted(shuttleId)) + { + _logger.Error( $"Tried to load shuttle as a map, aborting."); + _mapManager.DeleteMap(mapId); + return false; + } + + var ERTMap = EnsureComp(outpost); + ERTMap.MapId = mapId; + ERTMap.Shuttle = shuttleId; + + return true; + } +} diff --git a/Content.Server/White/ERTRecruitment/ERTRecruitmentRuleComponent.cs b/Content.Server/White/ERTRecruitment/ERTRecruitmentRuleComponent.cs new file mode 100644 index 0000000000..89999c9dc5 --- /dev/null +++ b/Content.Server/White/ERTRecruitment/ERTRecruitmentRuleComponent.cs @@ -0,0 +1,28 @@ +using Robust.Shared.Audio; +using Robust.Shared.Map; +using Robust.Shared.Utility; + +namespace Content.Server.White.ERTRecruitment; + +[RegisterComponent, Access(typeof(ERTRecruitmentRule))] +public sealed partial class ERTRecruitmentRuleComponent : Component +{ + public static string EventName = "ERTRecruitment"; + [ViewVariables] + public MapId? MapId = null; + + [DataField("minPlayer")] public int MinPlayer = 4; + + public static SoundSpecifier ERTYes = new SoundPathSpecifier("/Audio/Announcements/ert_yes.ogg"); + public static SoundSpecifier ERTNo = new SoundPathSpecifier("/Audio/Announcements/ert_no.ogg"); + + [ViewVariables] + public bool IsBlocked = false; + + [ViewVariables] + public EntityUid? Outpost; + [ViewVariables] + public EntityUid? Shuttle; + [ViewVariables] + public EntityUid? TargetStation; +} diff --git a/Content.Server/White/ERTRecruitment/ERTRecruitmentSystem.cs b/Content.Server/White/ERTRecruitment/ERTRecruitmentSystem.cs deleted file mode 100644 index 380944c9e0..0000000000 --- a/Content.Server/White/ERTRecruitment/ERTRecruitmentSystem.cs +++ /dev/null @@ -1,213 +0,0 @@ -using System.Linq; -using System.Numerics; -using Content.Server.Chat.Managers; -using Content.Server.Chat.Systems; -using Content.Server.GameTicking; -using Content.Server.Shuttles.Components; -using Content.Server.Shuttles.Systems; -using Content.Server.Station.Systems; -using Content.Server.White.GhostRecruitment; -using Content.Server.White.ServerEvent; -using Content.Shared.GameTicking; -using Content.Shared.White.GhostRecruitment; -using Content.Shared.White.ServerEvent; -using Robust.Server.GameObjects; -using Robust.Server.Maps; -using Robust.Shared.Audio; -using Robust.Shared.Map; -using Robust.Shared.Utility; - -namespace Content.Server.White.ERTRecruitment; - -public sealed class ERTRecruitmentSystem : EntitySystem -{ - public static string EventName = "ERTRecruitment"; - private ISawmill _logger = default!; - private MapId? _mapId = null; - - public ResPath OutpostMap = new("/Maps/ERT/ERTStation.yml"); - public ResPath ShuttleMap = new("/Maps/ERT/ERTShuttle.yml"); - - public SoundSpecifier ERTYes = new SoundPathSpecifier("/Audio/Announcements/ert_yes.ogg"); - public SoundSpecifier ERTNo = new SoundPathSpecifier("/Audio/Announcements/ert_no.ogg"); - - public bool IsBlocked = false; - - public EntityUid? Outpost; - public EntityUid? Shuttle; - public EntityUid? TargetStation; - - [Dependency] private readonly ServerEventSystem _event = default!; - [Dependency] private readonly IChatManager _chat = default!; - [Dependency] private readonly GhostRecruitmentSystem _recruitment = default!; - [Dependency] private readonly IMapManager _mapManager = default!; - [Dependency] private readonly MapLoaderSystem _map = default!; - [Dependency] private readonly ShuttleSystem _shuttle = default!; - [Dependency] private readonly StationSystem _station = default!; - [Dependency] private readonly ChatSystem _chatSystem = default!; - - public override void Initialize() - { - _logger = Logger.GetSawmill(EventName); - SubscribeLocalEvent(OnRoundStart); - SubscribeLocalEvent(OnRoundEnd); - SubscribeLocalEvent(OnRecruitmentSuccess); - - SubscribeLocalEvent(OnEventStart); - SubscribeLocalEvent(OnEventEnd); - } - - private void OnEventEnd(EventEnded ev) - { - if(ev.EventName != EventName) - return; - EventEnd(); - } - - private void OnEventStart(EventStarted ev) - { - if(ev.EventName != EventName) - return; - EventStart(); - } - - private void OnRoundEnd(RoundRestartCleanupEvent ev) - { - Outpost = null; - Shuttle = null; - TargetStation = null; - - _mapId = null; - _logger.Debug("Deleted map"); - } - - private void OnRecruitmentSuccess(EntityUid uid, RecruitedComponent component, GhostRecruitmentSuccessEvent args) - { - if(args.RecruitmentName != EventName || !_event.TryGetEvent(EventName, out var prototype)) - return; - - _chat.DispatchServerMessage(args.PlayerSession,Loc.GetString("ert-description")); - _chat.DispatchServerMessage(args.PlayerSession, Loc.GetString("ert-reason",("reason",prototype.Description))); - } - - - private void OnRoundStart(RoundStartAttemptEvent ev) - { - var stations = _station.GetStations(); - if (stations.Count > 0) - { - TargetStation = stations[0]; - } - - SpawnMap(); - } - - public void EventStart() - { - if(TargetStation == null || IsBlocked) - return; - - if (!_event.TryGetEvent(EventName, out var prototype) || - _recruitment.GetEventSpawners(EventName).Count() < prototype.MinPlayer) - { - _logger.Error("Not enough spawners!"); - _event.BreakEvent(EventName); - DeclineERT(); - return; - } - - _chatSystem.DispatchStationAnnouncement(TargetStation.Value,Loc.GetString("ert-wait-message"),colorOverride: Color.Gold); - - if (TryComp(Shuttle, out var shuttle) && Outpost != null) - { - _shuttle.TryFTLDock(Shuttle.Value, shuttle, Outpost.Value); - } - - _recruitment.StartRecruitment(EventName); - } - - public void EventEnd() - { - if (!_event.TryGetEvent(EventName, out var prototype) ) - return; - - if (_recruitment.GetAllRecruited(EventName).Count() < prototype.MinPlayer || - !_recruitment.EndRecruitment(EventName)) - { - DeclineERT(); - return; - } - - AcceptERT(); - } - - public void AcceptERT() - { - if(TargetStation == null) - return; - - _chatSystem.DispatchStationAnnouncement(TargetStation.Value,Loc.GetString("ert-accept-message"), - colorOverride: Color.Gold,announcementSound:ERTYes); - } - - public void DeclineERT() - { - if(TargetStation == null) - return; - - _chatSystem.DispatchStationAnnouncement(TargetStation.Value,Loc.GetString("ert-deny-message"), - colorOverride: Color.Gold,announcementSound:ERTNo); - } - - private bool SpawnMap() - { - _logger.Debug($"Loading maps!"); - if (_mapId != null) - { - // The map is already loaded, so there is no point in loading further - _logger.Debug("Map is already loaded " + _mapId); - return true; - } - - var mapId = _mapManager.CreateMap(); - var options = new MapLoadOptions - { - LoadMap = true, - }; - - if (!_map.TryLoad(mapId, OutpostMap.ToString(), out var outpostGrids, options) || outpostGrids.Count == 0) - { - _logger.Error( $"Error loading map {OutpostMap}!"); - return false; - } - _logger.Debug($"Loaded map {OutpostMap} on {mapId}!"); - - // Assume the first grid is the outpost grid. - Outpost = outpostGrids[0]; - - // Listen I just don't want it to overlap. - if (!_map.TryLoad(mapId, ShuttleMap.ToString(), out var grids, new MapLoadOptions {Offset = Vector2.One * 1000f}) || !grids.Any()) - { - _logger.Error( $"Error loading grid {ShuttleMap}!"); - return false; - } - _logger.Debug($"Loaded shuttle {ShuttleMap} on {mapId}!"); - - var shuttleId = grids.First(); - - // Naughty, someone saved the shuttle as a map. - if (Deleted(shuttleId)) - { - _logger.Error( $"Tried to load shuttle as a map, aborting."); - _mapManager.DeleteMap(mapId); - return false; - } - - _mapId = mapId; - Shuttle = shuttleId; - return true; - } - - - -} diff --git a/Content.Server/White/GhostRecruitment/GhostRecruitmentEvents.cs b/Content.Server/White/GhostRecruitment/GhostRecruitmentEvents.cs index 61a478152e..0e1c643c33 100644 --- a/Content.Server/White/GhostRecruitment/GhostRecruitmentEvents.cs +++ b/Content.Server/White/GhostRecruitment/GhostRecruitmentEvents.cs @@ -1,5 +1,4 @@ -using Robust.Server.Player; -using Robust.Shared.Serialization; +using Robust.Shared.Player; namespace Content.Server.White.GhostRecruitment; @@ -7,9 +6,9 @@ namespace Content.Server.White.GhostRecruitment; public sealed class GhostRecruitmentSuccessEvent : EntityEventArgs { public string RecruitmentName; - public IPlayerSession PlayerSession; + public ICommonSession PlayerSession; - public GhostRecruitmentSuccessEvent(string recruitmentName, IPlayerSession playerSession) + public GhostRecruitmentSuccessEvent(string recruitmentName, ICommonSession playerSession) { RecruitmentName = recruitmentName; PlayerSession = playerSession; diff --git a/Content.Server/White/GhostRecruitment/GhostRecruitmentSystem.cs b/Content.Server/White/GhostRecruitment/GhostRecruitmentSystem.cs index e827c63589..6470493367 100644 --- a/Content.Server/White/GhostRecruitment/GhostRecruitmentSystem.cs +++ b/Content.Server/White/GhostRecruitment/GhostRecruitmentSystem.cs @@ -4,9 +4,12 @@ using Content.Server.Ghost.Components; using Content.Server.Humanoid.Components; using Content.Server.Mind; using Content.Server.Players; +using Content.Shared.Ghost; +using Content.Shared.Players; using Content.Shared.White.GhostRecruitment; using Robust.Server.GameObjects; using Robust.Server.Player; +using Robust.Shared.Player; using Robust.Shared.Random; namespace Content.Server.White.GhostRecruitment; @@ -19,7 +22,7 @@ public sealed class GhostRecruitmentSystem : EntitySystem [Dependency] private readonly EuiManager _eui = default!; [Dependency] private readonly MindSystem _mind = default!; - private readonly Dictionary _openUis = new(); + private readonly Dictionary _openUis = new(); /// /// starts recruiting ghosts, showing them a menu with a choice to recruit. @@ -51,8 +54,6 @@ public sealed class GhostRecruitmentSystem : EntitySystem /// is success? public bool EndRecruitment(string recruitmentName) { - var query = EntityQueryEnumerator(); - var spawners = GetEventSpawners(recruitmentName).ToList(); // We prioritize the queue, for example, the commander first, and then the engineer @@ -60,29 +61,16 @@ public sealed class GhostRecruitmentSystem : EntitySystem var count = 0; - var attemptRecruitment = new GhostRecruitmentAttemptEvent(recruitmentName); - RaiseLocalEvent(attemptRecruitment); - - if (attemptRecruitment.Cancelled) - { - var failEvent = new GhostsRecruitmentFailEvent(recruitmentName); - RaiseLocalEvent(failEvent); - - return false; - } + var query = EntityQueryEnumerator(); while (query.MoveNext(out var uid,out var ghostRecruitedComponent)) { if(ghostRecruitedComponent.RecruitmentName != recruitmentName) continue; - RemComp(uid); - if (!TryComp(uid, out var actorComponent)) continue; - CloseEui(uid,recruitmentName,actorComponent); - // if there are too many recruited, then just skip if(count >= spawners.Count) continue; @@ -100,9 +88,26 @@ public sealed class GhostRecruitmentSystem : EntitySystem var ghostsEvent = new GhostsRecruitmentSuccessEvent(recruitmentName); RaiseLocalEvent(ghostsEvent); + + Cleanup(recruitmentName); return true; } + public void Cleanup(string recruitmentName) + { + ClearEui(recruitmentName); + + var query = EntityQueryEnumerator(); + + while (query.MoveNext(out var uid, out var ghostRecruitedComponent)) + { + if (ghostRecruitedComponent.RecruitmentName != recruitmentName) + continue; + + RemComp(uid); + } + } + private void TransferMind(EntityUid from,EntityUid spawnerUid,GhostRecruitmentSpawnPointComponent? component = null) { if (!Resolve(spawnerUid, ref component) || !TryComp(from,out var actorComponent)) @@ -112,10 +117,14 @@ public sealed class GhostRecruitmentSystem : EntitySystem if(!entityUid.HasValue) return; - var mind = actorComponent.PlayerSession.GetMind()!; - _mind.TransferTo(mind,entityUid.Value); - _mind.UnVisit(mind); + var mind = actorComponent.PlayerSession.GetMind(); + + if (!mind.HasValue) + return; + + _mind.TransferTo(mind.Value, entityUid.Value); + _mind.UnVisit(mind.Value); } private EntityUid? Spawn(EntityUid spawnerUid,GhostRecruitmentSpawnPointComponent? component = null) @@ -159,20 +168,32 @@ public sealed class GhostRecruitmentSystem : EntitySystem return; var eui = new GhostRecruitmentEuiAccept(uid, recruitmentName, this); - _openUis.Add(actorComponent.PlayerSession,eui); - _eui.OpenEui(eui,actorComponent.PlayerSession); + Logger.Debug("Added EUI to "+ uid); + if(_openUis.TryAdd(actorComponent.PlayerSession,eui)) + _eui.OpenEui(eui,actorComponent.PlayerSession); + } + + public void ClearEui(string recruitmentName) + { + foreach (var (session,eui) in _openUis) + { + if (session.AttachedEntity != null) + CloseEui(session.AttachedEntity.Value, recruitmentName); + } } public void CloseEui(EntityUid uid,string recruitmentName,ActorComponent? actorComponent = null) { - if(!Resolve(uid,ref actorComponent)) + if (!Resolve(uid, ref actorComponent)) return; + var session = actorComponent.PlayerSession; if (!_openUis.ContainsKey(session)) return; + Logger.Debug("Removed EUI from "+ uid); _openUis.Remove(session, out var eui); eui?.Close(); diff --git a/Content.Server/White/ServerEvent/Commands/StartServerEvent.cs b/Content.Server/White/ServerEvent/Commands/StartServerEvent.cs deleted file mode 100644 index 5fc55cea34..0000000000 --- a/Content.Server/White/ServerEvent/Commands/StartServerEvent.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Content.Server.Administration; -using Content.Shared.Administration; -using Content.Shared.White.ServerEvent; -using Robust.Shared.Console; - -namespace Content.Server.White.ServerEvent.Commands; - -[AdminCommand(AdminFlags.Admin)] -public sealed class StartServerEvent : IConsoleCommand -{ - [Dependency] private readonly IEntityManager _entities = default!; - - public string Command => "startevent"; - public string Description => "starting a new event"; - public string Help => "startevent "; - public void Execute(IConsoleShell shell, string argStr, string[] args) - { - if (args.Length < 1) - { - shell.WriteError("Not enough args!"); - } - - if(!_entities.System().TryStartEvent(args[0])) - shell.WriteError("Oopsie! error on starting event!"); - else - shell.WriteLine("Done!"); - - } - - public CompletionResult GetCompletion(IConsoleShell shell, string[] args) - { - return CompletionResult.FromHintOptions(CompletionHelper.PrototypeIDs(), - ""); - } -} diff --git a/Content.Server/White/ServerEvent/ServerEventSystem.cs b/Content.Server/White/ServerEvent/ServerEventSystem.cs deleted file mode 100644 index 5e80cb841a..0000000000 --- a/Content.Server/White/ServerEvent/ServerEventSystem.cs +++ /dev/null @@ -1,122 +0,0 @@ -using System.Diagnostics.CodeAnalysis; -using Content.Server.GameTicking; -using Content.Shared.GameTicking; -using Content.Shared.White.ServerEvent; -using Robust.Shared.Prototypes; -using Robust.Shared.Timing; - -namespace Content.Server.White.ServerEvent; - -public sealed class ServerEventSystem : EntitySystem -{ - [Dependency] private readonly IPrototypeManager _prototype = default!; - [Dependency] private readonly IGameTiming _timing = default!; - [Dependency] private readonly GameTicker _gameTicker = default!; - - private readonly Dictionary _eventCache = new(); - - public override void Initialize() - { - SubscribeLocalEvent(OnEnd); - } - - private void OnEnd(RoundRestartCleanupEvent ev) - { - foreach (var eventPrototype in GetActiveEvents()) - { - BreakEvent(eventPrototype); - } - - _eventCache.Clear(); - } - - public bool TryGetEvent(string eventName,[MaybeNullWhen(false)] out ServerEventPrototype prototype) - { - if (!_eventCache.TryGetValue(eventName, out prototype)) - { - if (!_prototype.TryIndex(eventName, out prototype)) - { - Logger.Debug("Failed load " + eventName); - return false; - } - Logger.Debug("Caching " + eventName); - _eventCache.Add(eventName,prototype); - } - - Logger.Debug("Successful get " + eventName); - return true; - } - - public bool IsEventRunning(string eventName) - { - if (!TryGetEvent(eventName, out var prototype)) - return false; - - return IsEventRunning(prototype); - } - - private bool IsEventRunning(ServerEventPrototype prototype) - { - return prototype.EndPlayerGatherTime.HasValue && !prototype.IsBreak; - } - - public IEnumerable GetActiveEvents() - { - foreach (var (_,prototype) in _eventCache) - { - if (IsEventRunning(prototype)) - yield return prototype; - } - } - - public void BreakEvent(string eventName) - { - if(!TryGetEvent(eventName,out var prototype)) - return; - BreakEvent(prototype); - } - - private void BreakEvent(ServerEventPrototype prototype) - { - Logger.Debug("Event is break! " + prototype.ID); - prototype.CurrentPlayerGatherTime = null; - prototype.EndPlayerGatherTime = null; - prototype.IsBreak = true; - } - - public bool TryStartEvent(string eventName) - { - if (!TryGetEvent(eventName, out var prototype) || IsEventRunning(prototype) || _gameTicker.RunLevel != GameRunLevel.InRound) - return false; - - prototype.IsBreak = false; - prototype.EndPlayerGatherTime = _timing.CurTime + prototype.PlayerGatherTime; - - Logger.Debug("Event is started " + eventName); - return true; - } - - public override void Update(float frameTime) - { - base.Update(frameTime); - - foreach (var prototype in GetActiveEvents()) - { - if (!prototype.CurrentPlayerGatherTime.HasValue) - { - Logger.Debug("Started with " + prototype.CurrentPlayerGatherTime + " " + prototype.EndPlayerGatherTime + " " + prototype.IsBreak ); - RaiseLocalEvent(new EventStarted(prototype.ID)); - prototype.OnStart?.Execute(prototype); - } - prototype.CurrentPlayerGatherTime = _timing.CurTime; - - if (prototype.CurrentPlayerGatherTime > prototype.EndPlayerGatherTime) - { - prototype.OnEnd?.Execute(prototype); - RaiseLocalEvent(new EventEnded(prototype.ID)); - Logger.Debug("Ended with " + prototype.CurrentPlayerGatherTime + " " + prototype.EndPlayerGatherTime + " " + prototype.IsBreak ); - BreakEvent(prototype); - } - } - } -} diff --git a/Content.Shared/White/AuthPanel/AuthPanelComponent.cs b/Content.Shared/White/AuthPanel/AuthPanelComponent.cs index efa585b545..01f1d3dd4b 100644 --- a/Content.Shared/White/AuthPanel/AuthPanelComponent.cs +++ b/Content.Shared/White/AuthPanel/AuthPanelComponent.cs @@ -1,7 +1,7 @@ namespace Content.Shared.White.AuthPanel; [RegisterComponent] -public sealed class AuthPanelComponent : Component +public sealed partial class AuthPanelComponent : Component { } diff --git a/Content.Shared/White/GhostRecruitment/GhostRecruitedComponent.cs b/Content.Shared/White/GhostRecruitment/GhostRecruitedComponent.cs index a097e3bd92..16faaad869 100644 --- a/Content.Shared/White/GhostRecruitment/GhostRecruitedComponent.cs +++ b/Content.Shared/White/GhostRecruitment/GhostRecruitedComponent.cs @@ -2,7 +2,7 @@ namespace Content.Shared.White.GhostRecruitment; //this for ghosts [RegisterComponent] -public sealed class GhostRecruitedComponent : Component +public sealed partial class GhostRecruitedComponent : Component { [DataField("recruitmentName")] public string RecruitmentName = "default"; diff --git a/Content.Shared/White/GhostRecruitment/GhostRecruitmentEvents.cs b/Content.Shared/White/GhostRecruitment/GhostRecruitmentEvents.cs index edfcc7d05e..8ae25eadf6 100644 --- a/Content.Shared/White/GhostRecruitment/GhostRecruitmentEvents.cs +++ b/Content.Shared/White/GhostRecruitment/GhostRecruitmentEvents.cs @@ -13,27 +13,6 @@ public sealed class GhostsRecruitmentSuccessEvent } } -[Serializable,NetSerializable] -public sealed class GhostsRecruitmentFailEvent -{ - public string RecruitmentName; - - public GhostsRecruitmentFailEvent(string recruitmentName) - { - RecruitmentName = recruitmentName; - } -} - -[Serializable,NetSerializable] -public sealed class GhostRecruitmentAttemptEvent : CancelableEventArgs -{ - public string RecruitmentName; - - public GhostRecruitmentAttemptEvent(string recruitmentName) - { - RecruitmentName = recruitmentName; - } -} [Serializable,NetSerializable] diff --git a/Content.Shared/White/GhostRecruitment/GhostRecruitmentSpawnPointComponent.cs b/Content.Shared/White/GhostRecruitment/GhostRecruitmentSpawnPointComponent.cs index 5a9a2d9bed..279fc17518 100644 --- a/Content.Shared/White/GhostRecruitment/GhostRecruitmentSpawnPointComponent.cs +++ b/Content.Shared/White/GhostRecruitment/GhostRecruitmentSpawnPointComponent.cs @@ -4,7 +4,7 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototy namespace Content.Shared.White.GhostRecruitment; [RegisterComponent] -public sealed class GhostRecruitmentSpawnPointComponent : Component +public sealed partial class GhostRecruitmentSpawnPointComponent : Component { [DataField("prototype", customTypeSerializer:typeof(PrototypeIdSerializer),required:true)] public string EntityPrototype = default!; diff --git a/Content.Shared/White/GhostRecruitment/RecruitedComponent.cs b/Content.Shared/White/GhostRecruitment/RecruitedComponent.cs index ed693e43eb..670d91b49a 100644 --- a/Content.Shared/White/GhostRecruitment/RecruitedComponent.cs +++ b/Content.Shared/White/GhostRecruitment/RecruitedComponent.cs @@ -3,7 +3,7 @@ namespace Content.Shared.White.GhostRecruitment; // this for spawned prototype [RegisterComponent] -public sealed class RecruitedComponent : Component +public sealed partial class RecruitedComponent : Component { [DataField("recruitmentName")] public string RecruitmentName = "default"; diff --git a/Content.Shared/White/ServerEvent/Data/IEventAction.cs b/Content.Shared/White/ServerEvent/Data/IEventAction.cs deleted file mode 100644 index a36d1b68db..0000000000 --- a/Content.Shared/White/ServerEvent/Data/IEventAction.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Content.Shared.White.ServerEvent.Data; - -[ImplicitDataDefinitionForInheritors] -public interface IEventAction -{ - void Execute(ServerEventPrototype prototype); -} diff --git a/Content.Shared/White/ServerEvent/Events.cs b/Content.Shared/White/ServerEvent/Events.cs deleted file mode 100644 index 117bdb6d6b..0000000000 --- a/Content.Shared/White/ServerEvent/Events.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Robust.Shared.Serialization; - -namespace Content.Shared.White.ServerEvent; - -[Serializable, NetSerializable] -public sealed class EventStarted -{ - public string EventName; - - public EventStarted(string eventName) - { - EventName = eventName; - } -} - - -[Serializable, NetSerializable] -public sealed class EventEnded -{ - public string EventName; - - public EventEnded(string eventName) - { - EventName = eventName; - } -} diff --git a/Content.Shared/White/ServerEvent/ServerEventPrototype.cs b/Content.Shared/White/ServerEvent/ServerEventPrototype.cs deleted file mode 100644 index 94c2c333ac..0000000000 --- a/Content.Shared/White/ServerEvent/ServerEventPrototype.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Content.Shared.White.ServerEvent.Data; -using Robust.Shared.Prototypes; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; - -namespace Content.Shared.White.ServerEvent; - -[Prototype("serverEvent")] -public sealed class ServerEventPrototype : IPrototype -{ - [IdDataField] - public string ID { get; } = default!; - - [DataField("name")] - public string Name { get; } = string.Empty; - - [DataField("description")] - public string Description = string.Empty; - - [DataField("playerGatherTime", customTypeSerializer: typeof(TimeOffsetSerializer))] - public TimeSpan PlayerGatherTime = TimeSpan.FromSeconds(10); - - [DataField("onStart")] public IEventAction? OnStart; - [DataField("onEnd")] public IEventAction? OnEnd; - - [DataField("minPlayer")] public int MinPlayer; - - [ViewVariables] public TimeSpan? CurrentPlayerGatherTime = null; - [ViewVariables] public TimeSpan? EndPlayerGatherTime = null; - - [ViewVariables] public bool IsBreak; -} diff --git a/Content.Shared/White/WhiteCVars.cs b/Content.Shared/White/WhiteCVars.cs index 512d083c25..c3223e75c5 100644 --- a/Content.Shared/White/WhiteCVars.cs +++ b/Content.Shared/White/WhiteCVars.cs @@ -291,4 +291,12 @@ public sealed class WhiteCVars /// public static readonly CVarDef SlippedCountTopSlipper = CVarDef.Create("eorstats.slippedcount_topslipper", true, CVar.SERVERONLY); + + public static readonly CVarDef + ServerCulture = CVarDef.Create("white.culture", "ru-RU", CVar.REPLICATED | CVar.SERVER); + + /// + /// Should load a ERT map? + /// + public static readonly CVarDef LoadERTMap = CVarDef.Create("white.ert_load", false, CVar.SERVERONLY); } diff --git a/Resources/ConfigPresets/Build/development.toml b/Resources/ConfigPresets/Build/development.toml index 18a4b5202e..2d2ee4a5a9 100644 --- a/Resources/ConfigPresets/Build/development.toml +++ b/Resources/ConfigPresets/Build/development.toml @@ -29,3 +29,6 @@ see_own_notes = true [worldgen] enabled = false + +[white] +ert_load = false diff --git a/Resources/Prototypes/White/event_prototypes.yml b/Resources/Prototypes/White/event_prototypes.yml index bd12507630..84406e754a 100644 --- a/Resources/Prototypes/White/event_prototypes.yml +++ b/Resources/Prototypes/White/event_prototypes.yml @@ -1,5 +1,12 @@ -- type: serverEvent +- type: entity id: ERTRecruitment - name: ERT - description: Your tasks is meow! - minPlayer: 4 + parent: BaseGameRule + noSpawn: true + components: + - type: StationEvent + earliestStart: 25 + weight: 0 + minimumPlayers: 125 + duration: 20 + - type: ERTRecruitmentRule +