From a2d8fc1ef9712df21c69ab053082218c695cf330 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Wed, 2 Oct 2019 10:45:06 +0200 Subject: [PATCH] Sandbox panel --- Content.Client/EntryPoint.cs | 4 + Content.Client/Sandbox/ISandboxManager.cs | 7 ++ Content.Client/Sandbox/SandboxManager.cs | 111 ++++++++++++++++++ Content.Client/Sandbox/SandboxWindow.cs | 45 +++++++ Content.Client/UserInterface/GameHud.cs | 2 +- Content.Server/EntryPoint.cs | 3 + .../GameTicking/GamePresets/PresetSandbox.cs | 10 +- Content.Server/GameTicking/GameTicker.cs | 3 +- Content.Server/Sandbox/ISandboxManager.cs | 8 ++ Content.Server/Sandbox/SandboxManager.cs | 80 +++++++++++++ .../Sandbox/SharedSandboxManager.cs | 51 ++++++++ 11 files changed, 320 insertions(+), 4 deletions(-) create mode 100644 Content.Client/Sandbox/ISandboxManager.cs create mode 100644 Content.Client/Sandbox/SandboxManager.cs create mode 100644 Content.Client/Sandbox/SandboxWindow.cs create mode 100644 Content.Server/Sandbox/ISandboxManager.cs create mode 100644 Content.Server/Sandbox/SandboxManager.cs create mode 100644 Content.Shared/Sandbox/SharedSandboxManager.cs diff --git a/Content.Client/EntryPoint.cs b/Content.Client/EntryPoint.cs index 0321584f53..4e4ec61789 100644 --- a/Content.Client/EntryPoint.cs +++ b/Content.Client/EntryPoint.cs @@ -7,6 +7,7 @@ using Content.Client.Interfaces; using Content.Client.Interfaces.Chat; using Content.Client.Interfaces.Parallax; using Content.Client.Parallax; +using Content.Client.Sandbox; using Content.Client.UserInterface; using Content.Shared.GameObjects.Components; using Content.Shared.GameObjects.Components.Chemistry; @@ -134,6 +135,8 @@ namespace Content.Client IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); + IoCManager.Register(); + if (TestingCallbacks != null) { var cast = (ClientModuleTestingCallbacks) TestingCallbacks; @@ -195,6 +198,7 @@ namespace Content.Client IoCManager.Resolve().Initialize(); IoCManager.Resolve().AddOverlay(new ParallaxOverlay()); IoCManager.Resolve().Initialize(); + IoCManager.Resolve().Initialize(); } public override void Update(ModUpdateLevel level, FrameEventArgs frameEventArgs) diff --git a/Content.Client/Sandbox/ISandboxManager.cs b/Content.Client/Sandbox/ISandboxManager.cs new file mode 100644 index 0000000000..95be885f6a --- /dev/null +++ b/Content.Client/Sandbox/ISandboxManager.cs @@ -0,0 +1,7 @@ +namespace Content.Client.Sandbox +{ + public interface ISandboxManager + { + void Initialize(); + } +} diff --git a/Content.Client/Sandbox/SandboxManager.cs b/Content.Client/Sandbox/SandboxManager.cs new file mode 100644 index 0000000000..841e555489 --- /dev/null +++ b/Content.Client/Sandbox/SandboxManager.cs @@ -0,0 +1,111 @@ +using Content.Client.UserInterface; +using Content.Shared.Sandbox; +using Robust.Client.Interfaces.Placement; +using Robust.Client.Interfaces.ResourceManagement; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.CustomControls; +using Robust.Shared.Interfaces.Map; +using Robust.Shared.Interfaces.Network; +using Robust.Shared.IoC; +using Robust.Shared.Localization; +using Robust.Shared.Prototypes; + +namespace Content.Client.Sandbox +{ + internal sealed class SandboxManager : SharedSandboxManager, ISandboxManager + { +#pragma warning disable 649 + [Dependency] private readonly IGameHud _gameHud; + [Dependency] private readonly IClientNetManager _netManager; + [Dependency] private readonly ILocalizationManager _localization; + [Dependency] private readonly IPlacementManager _placementManager; + [Dependency] private readonly IPrototypeManager _prototypeManager; + [Dependency] private readonly IResourceCache _resourceCache; + [Dependency] private readonly ITileDefinitionManager _tileDefinitionManager; +#pragma warning restore 649 + + private bool _sandboxAllowed; + private SandboxWindow _window; + + public void Initialize() + { + _netManager.RegisterNetMessage(nameof(MsgSandboxStatus), + message => SetAllowed(message.SandboxAllowed)); + + _gameHud.SandboxButtonToggled = SandboxButtonToggled; + } + + private void SandboxButtonToggled(bool newValue) + { + if (newValue) + { + if (_sandboxAllowed) + { + OpenWindow(); + } + } + else + { + _window?.Close(); + } + } + + private void SetAllowed(bool newAllowed) + { + if (newAllowed == _sandboxAllowed) + { + return; + } + + _sandboxAllowed = newAllowed; + _gameHud.SandboxButtonVisible = newAllowed; + + if (!newAllowed) + { + // Sandbox permission revoked, close window. + _window?.Close(); + } + } + + private void OpenWindow() + { + if (_window != null) + { + return; + } + + _window = new SandboxWindow(_localization); + + _window.OnClose += WindowOnOnClose; + + _window.RespawnButton.OnPressed += OnRespawnButtonOnOnPressed; + _window.SpawnTilesButton.OnPressed += OnSpawnTilesButtonClicked; + _window.SpawnEntitiesButton.OnPressed += OnSpawnEntitiesButtonClicked; + + _window.Open(); + } + + private void WindowOnOnClose() + { + _window = null; + _gameHud.SandboxButtonDown = false; + } + + private void OnRespawnButtonOnOnPressed(BaseButton.ButtonEventArgs args) + { + _netManager.ClientSendMessage(_netManager.CreateNetMessage()); + } + + private void OnSpawnEntitiesButtonClicked(BaseButton.ButtonEventArgs args) + { + var window = new EntitySpawnWindow(_placementManager, _prototypeManager, _resourceCache, _localization); + window.OpenToLeft(); + } + + private void OnSpawnTilesButtonClicked(BaseButton.ButtonEventArgs args) + { + var window = new TileSpawnWindow(_tileDefinitionManager, _placementManager, _resourceCache); + window.OpenToLeft(); + } + } +} diff --git a/Content.Client/Sandbox/SandboxWindow.cs b/Content.Client/Sandbox/SandboxWindow.cs new file mode 100644 index 0000000000..9520135077 --- /dev/null +++ b/Content.Client/Sandbox/SandboxWindow.cs @@ -0,0 +1,45 @@ +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.CustomControls; +using Robust.Shared.Localization; + +namespace Content.Client.Sandbox +{ + public sealed class SandboxWindow : SS14Window + { + public Button RespawnButton { get; } + public Button SpawnEntitiesButton { get; } + public Button SpawnTilesButton { get; } + + public SandboxWindow(ILocalizationManager loc) + { + Title = loc.GetString("Sandbox Panel"); + + RespawnButton = new Button + { + Text = loc.GetString("Respawn") + }; + + SpawnEntitiesButton = new Button + { + Text = loc.GetString("Spawn Entities") + }; + + SpawnTilesButton = new Button + { + Text = loc.GetString("Spawn Tiles") + }; + + Contents.AddChild(new VBoxContainer + { + Children = + { + RespawnButton, + SpawnEntitiesButton, + SpawnTilesButton + } + }); + + Size = CombinedMinimumSize; + } + } +} diff --git a/Content.Client/UserInterface/GameHud.cs b/Content.Client/UserInterface/GameHud.cs index 3c4182b77b..2475e80ec1 100644 --- a/Content.Client/UserInterface/GameHud.cs +++ b/Content.Client/UserInterface/GameHud.cs @@ -182,7 +182,7 @@ namespace Content.Client.UserInterface _buttonSandboxMenu = new TopButton(sandboxTexture, "B") { ToolTip = _loc.GetString("Open sandbox menu."), - Visible = true + Visible = false }; _topButtonsContainer.AddChild(_buttonSandboxMenu); diff --git a/Content.Server/EntryPoint.cs b/Content.Server/EntryPoint.cs index 201659a0fe..46fa5e311f 100644 --- a/Content.Server/EntryPoint.cs +++ b/Content.Server/EntryPoint.cs @@ -3,6 +3,7 @@ using Content.Server.GameTicking; using Content.Server.Interfaces; using Content.Server.Interfaces.Chat; using Content.Server.Interfaces.GameTicking; +using Content.Server.Sandbox; using Content.Shared.Interfaces; using Robust.Server.Interfaces.Player; using Robust.Shared.ContentPack; @@ -48,6 +49,7 @@ namespace Content.Server IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); + IoCManager.Register(); if (TestingCallbacks != null) { var cast = (ServerModuleTestingCallbacks) TestingCallbacks; @@ -73,6 +75,7 @@ namespace Content.Server base.PostInit(); _gameTicker.Initialize(); + IoCManager.Resolve().Initialize(); } public override void Update(ModUpdateLevel level, FrameEventArgs frameEventArgs) diff --git a/Content.Server/GameTicking/GamePresets/PresetSandbox.cs b/Content.Server/GameTicking/GamePresets/PresetSandbox.cs index fa9d4ae76b..cde4f725fb 100644 --- a/Content.Server/GameTicking/GamePresets/PresetSandbox.cs +++ b/Content.Server/GameTicking/GamePresets/PresetSandbox.cs @@ -1,10 +1,18 @@ +using Content.Server.Interfaces.GameTicking; +using Content.Server.Sandbox; +using Robust.Shared.IoC; + namespace Content.Server.GameTicking.GamePresets { public sealed class PresetSandbox : GamePreset { +#pragma warning disable 649 + [Dependency] private readonly ISandboxManager _sandboxManager; +#pragma warning restore 649 + public override void Start() { - // Nothing yet. + _sandboxManager.IsSandboxEnabled = true; } } } diff --git a/Content.Server/GameTicking/GameTicker.cs b/Content.Server/GameTicking/GameTicker.cs index 19aa4b5024..a286ae1bb0 100644 --- a/Content.Server/GameTicking/GameTicker.cs +++ b/Content.Server/GameTicking/GameTicker.cs @@ -156,8 +156,7 @@ namespace Content.Server.GameTicking RunLevel = GameRunLevel.InRound; - // TODO: Allow other presets to be selected. - var preset = (GamePreset)_dynamicTypeFactory.CreateInstance(_presetType ?? typeof(PresetSandbox)); + var preset = _dynamicTypeFactory.CreateInstance(_presetType ?? typeof(PresetSandbox)); preset.Start(); foreach (var (playerSession, ready) in _playersInLobby.ToList()) diff --git a/Content.Server/Sandbox/ISandboxManager.cs b/Content.Server/Sandbox/ISandboxManager.cs new file mode 100644 index 0000000000..ba55ed0a8f --- /dev/null +++ b/Content.Server/Sandbox/ISandboxManager.cs @@ -0,0 +1,8 @@ +namespace Content.Server.Sandbox +{ + public interface ISandboxManager + { + bool IsSandboxEnabled { get; set; } + void Initialize(); + } +} diff --git a/Content.Server/Sandbox/SandboxManager.cs b/Content.Server/Sandbox/SandboxManager.cs new file mode 100644 index 0000000000..e4a3449b26 --- /dev/null +++ b/Content.Server/Sandbox/SandboxManager.cs @@ -0,0 +1,80 @@ +using Content.Server.GameTicking; +using Content.Server.Interfaces.GameTicking; +using Content.Shared.Sandbox; +using Robust.Server.Interfaces.Player; +using Robust.Server.Player; +using Robust.Shared.Enums; +using Robust.Shared.Interfaces.Network; +using Robust.Shared.IoC; + +namespace Content.Server.Sandbox +{ + internal sealed class SandboxManager : SharedSandboxManager, ISandboxManager + { +#pragma warning disable 649 + [Dependency] private readonly IPlayerManager _playerManager; + [Dependency] private readonly IServerNetManager _netManager; + [Dependency] private readonly IGameTicker _gameTicker; +#pragma warning restore 649 + + private bool _isSandboxEnabled; + + public bool IsSandboxEnabled + { + get => _isSandboxEnabled; + set + { + _isSandboxEnabled = value; + UpdateSandboxStatusForAll(); + } + } + + public void Initialize() + { + _netManager.RegisterNetMessage(nameof(MsgSandboxStatus)); + _netManager.RegisterNetMessage(nameof(MsgSandboxRespawn), SandboxRespawnReceived); + + _playerManager.PlayerStatusChanged += OnPlayerStatusChanged; + _gameTicker.OnRunLevelChanged += GameTickerOnOnRunLevelChanged; + } + + private void GameTickerOnOnRunLevelChanged(GameRunLevelChangedEventArgs obj) + { + // Automatically clear sandbox state when round resets. + if (obj.NewRunLevel == GameRunLevel.PreRoundLobby) + { + IsSandboxEnabled = false; + } + } + + private void OnPlayerStatusChanged(object sender, SessionStatusEventArgs e) + { + if (e.NewStatus != SessionStatus.Connected || e.OldStatus != SessionStatus.Connecting) + { + return; + } + + var msg = _netManager.CreateNetMessage(); + msg.SandboxAllowed = IsSandboxEnabled; + _netManager.ServerSendMessage(msg, e.Session.ConnectedClient); + } + + private void SandboxRespawnReceived(MsgSandboxRespawn message) + { + if (!IsSandboxEnabled) + { + return; + } + + var player = _playerManager.GetSessionByChannel(message.MsgChannel); + _gameTicker.Respawn(player); + } + + private void UpdateSandboxStatusForAll() + { + var msg = _netManager.CreateNetMessage(); + msg.SandboxAllowed = IsSandboxEnabled; + _netManager.ServerSendToAll(msg); + } + } +} diff --git a/Content.Shared/Sandbox/SharedSandboxManager.cs b/Content.Shared/Sandbox/SharedSandboxManager.cs new file mode 100644 index 0000000000..adbef38d6a --- /dev/null +++ b/Content.Shared/Sandbox/SharedSandboxManager.cs @@ -0,0 +1,51 @@ +using Lidgren.Network; +using Robust.Shared.Interfaces.Network; +using Robust.Shared.Network; + +namespace Content.Shared.Sandbox +{ + public abstract class SharedSandboxManager + { + protected sealed class MsgSandboxStatus : NetMessage + { + #region REQUIRED + + public const MsgGroups GROUP = MsgGroups.Command; + public const string NAME = nameof(MsgSandboxStatus); + public MsgSandboxStatus(INetChannel channel) : base(NAME, GROUP) { } + + #endregion + + public bool SandboxAllowed { get; set; } + + public override void ReadFromBuffer(NetIncomingMessage buffer) + { + SandboxAllowed = buffer.ReadBoolean(); + } + + public override void WriteToBuffer(NetOutgoingMessage buffer) + { + buffer.Write(SandboxAllowed); + } + } + + protected sealed class MsgSandboxRespawn : NetMessage + { + #region REQUIRED + + public const MsgGroups GROUP = MsgGroups.Command; + public const string NAME = nameof(MsgSandboxRespawn); + public MsgSandboxRespawn(INetChannel channel) : base(NAME, GROUP) { } + + #endregion + + public override void ReadFromBuffer(NetIncomingMessage buffer) + { + } + + public override void WriteToBuffer(NetOutgoingMessage buffer) + { + } + } + } +}