From a014b4097218fe50886f12d23373ec5e88b204d9 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Wed, 8 May 2019 09:55:00 +0200 Subject: [PATCH 1/5] Update submodule --- .../GamePresets/PresetDeathMatch.cs | 18 ++++++++++++++++++ Content.Server/GameTicking/GameRule.cs | 7 +++++++ .../GameTicking/GameRules/RuleDeathMatch.cs | 7 +++++++ RobustToolbox | 2 +- 4 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 Content.Server/GameTicking/GamePresets/PresetDeathMatch.cs create mode 100644 Content.Server/GameTicking/GameRule.cs create mode 100644 Content.Server/GameTicking/GameRules/RuleDeathMatch.cs diff --git a/Content.Server/GameTicking/GamePresets/PresetDeathMatch.cs b/Content.Server/GameTicking/GamePresets/PresetDeathMatch.cs new file mode 100644 index 0000000000..29745d4321 --- /dev/null +++ b/Content.Server/GameTicking/GamePresets/PresetDeathMatch.cs @@ -0,0 +1,18 @@ +using Content.Server.GameTicking.GameRules; +using Content.Server.Interfaces.GameTicking; +using Robust.Shared.IoC; + +namespace Content.Server.GameTicking.GamePresets +{ + public sealed class PresetDeathMatch : GamePreset + { +#pragma warning disable 649 + [Dependency] private readonly IGameTicker _gameTicker; +#pragma warning restore 649 + + public override void Start() + { + _gameTicker.AddGameRule(); + } + } +} diff --git a/Content.Server/GameTicking/GameRule.cs b/Content.Server/GameTicking/GameRule.cs new file mode 100644 index 0000000000..942184b516 --- /dev/null +++ b/Content.Server/GameTicking/GameRule.cs @@ -0,0 +1,7 @@ +namespace Content.Server.GameTicking +{ + public class GameRule + { + + } +} diff --git a/Content.Server/GameTicking/GameRules/RuleDeathMatch.cs b/Content.Server/GameTicking/GameRules/RuleDeathMatch.cs new file mode 100644 index 0000000000..570af7c63e --- /dev/null +++ b/Content.Server/GameTicking/GameRules/RuleDeathMatch.cs @@ -0,0 +1,7 @@ +namespace Content.Server.GameTicking.GameRules +{ + public class DeathMatch + { + + } +} diff --git a/RobustToolbox b/RobustToolbox index c83ad3ab94..0340cecd6d 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit c83ad3ab9439da2ec81f1dddea86f619922c73cc +Subproject commit 0340cecd6d3823db386b553aa27cb61478e7a1bb From 90620db5f84ba47aae78ac7873870a47348725c3 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Wed, 8 May 2019 09:55:36 +0200 Subject: [PATCH 2/5] Adds shoddy death match system. It barely even works but oh well. --- .../GameObjects/Components/Mobs/SpeciesUI.cs | 1 - Content.Server/Content.Server.csproj | 3 + .../Components/Mobs/DamageStates.cs | 8 ++ .../Components/Mobs/SpeciesComponent.cs | 18 +++ Content.Server/GameTicking/GameRule.cs | 15 ++- .../GameTicking/GameRules/RuleDeathMatch.cs | 109 +++++++++++++++++- Content.Server/GameTicking/GameTicker.cs | 37 +++++- .../Interfaces/GameTicking/IGameTicker.cs | 6 + 8 files changed, 191 insertions(+), 6 deletions(-) diff --git a/Content.Client/GameObjects/Components/Mobs/SpeciesUI.cs b/Content.Client/GameObjects/Components/Mobs/SpeciesUI.cs index be9df9e606..1aecd91c6c 100644 --- a/Content.Client/GameObjects/Components/Mobs/SpeciesUI.cs +++ b/Content.Client/GameObjects/Components/Mobs/SpeciesUI.cs @@ -67,7 +67,6 @@ namespace Content.Client.GameObjects { base.OnAdd(); - IoCManager.InjectDependencies(this); _window = new SpeciesWindow(); EffectsDictionary = new Dictionary() diff --git a/Content.Server/Content.Server.csproj b/Content.Server/Content.Server.csproj index f7ebce47ec..735f47fc61 100644 --- a/Content.Server/Content.Server.csproj +++ b/Content.Server/Content.Server.csproj @@ -141,7 +141,10 @@ + + + diff --git a/Content.Server/GameObjects/Components/Mobs/DamageStates.cs b/Content.Server/GameObjects/Components/Mobs/DamageStates.cs index 7cbd757679..9c94587403 100644 --- a/Content.Server/GameObjects/Components/Mobs/DamageStates.cs +++ b/Content.Server/GameObjects/Components/Mobs/DamageStates.cs @@ -13,6 +13,8 @@ namespace Content.Server.GameObjects void EnterState(IEntity entity); void ExitState(IEntity entity); + + bool IsConscious { get; } } /// @@ -28,6 +30,8 @@ namespace Content.Server.GameObjects { } + public bool IsConscious => true; + bool IActionBlocker.CanInteract() { return true; @@ -57,6 +61,8 @@ namespace Content.Server.GameObjects { } + public bool IsConscious => false; + bool IActionBlocker.CanInteract() { return false; @@ -96,6 +102,8 @@ namespace Content.Server.GameObjects } } + public bool IsConscious => false; + bool IActionBlocker.CanInteract() { return false; diff --git a/Content.Server/GameObjects/Components/Mobs/SpeciesComponent.cs b/Content.Server/GameObjects/Components/Mobs/SpeciesComponent.cs index 74a540fdf5..bb68d25f2f 100644 --- a/Content.Server/GameObjects/Components/Mobs/SpeciesComponent.cs +++ b/Content.Server/GameObjects/Components/Mobs/SpeciesComponent.cs @@ -112,6 +112,24 @@ namespace Content.Server.GameObjects CurrentDamageState.EnterState(Owner); currentstate = threshold; + + Owner.RaiseEvent(new MobDamageStateChangedMessage(this)); } } + + /// + /// Fired when changes. + /// + public sealed class MobDamageStateChangedMessage : EntitySystemMessage + { + public MobDamageStateChangedMessage(SpeciesComponent species) + { + Species = species; + } + + /// + /// The species component that was changed. + /// + public SpeciesComponent Species { get; } + } } diff --git a/Content.Server/GameTicking/GameRule.cs b/Content.Server/GameTicking/GameRule.cs index 942184b516..6e92818a77 100644 --- a/Content.Server/GameTicking/GameRule.cs +++ b/Content.Server/GameTicking/GameRule.cs @@ -1,7 +1,18 @@ +using JetBrains.Annotations; + namespace Content.Server.GameTicking { - public class GameRule + [PublicAPI] + public abstract class GameRule { - + public virtual void Added() + { + + } + + public virtual void Removed() + { + + } } } diff --git a/Content.Server/GameTicking/GameRules/RuleDeathMatch.cs b/Content.Server/GameTicking/GameRules/RuleDeathMatch.cs index 570af7c63e..cdc9e41d62 100644 --- a/Content.Server/GameTicking/GameRules/RuleDeathMatch.cs +++ b/Content.Server/GameTicking/GameRules/RuleDeathMatch.cs @@ -1,7 +1,112 @@ +using System; +using System.Threading; +using Content.Server.GameObjects; +using Content.Server.Interfaces.Chat; +using Content.Server.Interfaces.GameTicking; +using Robust.Server.Interfaces.Player; +using Robust.Server.Player; +using Robust.Shared.Enums; +using Robust.Shared.GameObjects; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; +using Timer = Robust.Shared.Timers.Timer; + namespace Content.Server.GameTicking.GameRules { - public class DeathMatch + /// + /// Simple GameRule that will do a free-for-all death match. + /// Kill everybody else to win. + /// + public sealed class RuleDeathMatch : GameRule, IEntityEventSubscriber { - + private static readonly TimeSpan DeadCheckDelay = TimeSpan.FromSeconds(5); + +#pragma warning disable 649 + [Dependency] private readonly IPlayerManager _playerManager; + [Dependency] private readonly IEntityManager _entityManager; + [Dependency] private readonly IChatManager _chatManager; + [Dependency] private readonly IGameTicker _gameTicker; +#pragma warning restore 649 + + private CancellationTokenSource _checkTimerCancel; + + public override void Added() + { + _chatManager.DispatchServerAnnouncement("The game is now a death match. Kill everybody else to win!"); + + _entityManager.SubscribeEvent(_onMobDamageStateChanged, this); + _playerManager.PlayerStatusChanged += PlayerManagerOnPlayerStatusChanged; + } + + public override void Removed() + { + base.Removed(); + + _entityManager.UnsubscribeEvent(this); + _playerManager.PlayerStatusChanged -= PlayerManagerOnPlayerStatusChanged; + } + + private void _onMobDamageStateChanged(object sender, MobDamageStateChangedMessage message) + { + _runDelayedCheck(); + } + + private void _checkForWinner() + { + _checkTimerCancel = null; + + IPlayerSession winner = null; + foreach (var playerSession in _playerManager.GetAllPlayers()) + { + if (playerSession.AttachedEntity == null + || !playerSession.AttachedEntity.TryGetComponent(out SpeciesComponent species)) + { + continue; + } + + if (!species.CurrentDamageState.IsConscious) + { + continue; + } + + if (winner != null) + { + // Found a second person alive, nothing decided yet! + return; + } + + winner = playerSession; + } + + if (winner == null) + { + _chatManager.DispatchServerAnnouncement("Everybody is dead, it's a stalemate!"); + } + else + { + // We have a winner! + _chatManager.DispatchServerAnnouncement($"{winner} wins the death match!"); + } + + _chatManager.DispatchServerAnnouncement($"Restarting in 10 seconds."); + + Timer.Spawn(TimeSpan.FromSeconds(10), () => _gameTicker.RestartRound()); + } + + private void PlayerManagerOnPlayerStatusChanged(object sender, SessionStatusEventArgs e) + { + if (e.NewStatus == SessionStatus.Disconnected) + { + _runDelayedCheck(); + } + } + + private void _runDelayedCheck() + { + _checkTimerCancel?.Cancel(); + _checkTimerCancel = new CancellationTokenSource(); + + Timer.Spawn(DeadCheckDelay, _checkForWinner, _checkTimerCancel.Token); + } } } diff --git a/Content.Server/GameTicking/GameTicker.cs b/Content.Server/GameTicking/GameTicker.cs index f9691c16c7..4830150745 100644 --- a/Content.Server/GameTicking/GameTicker.cs +++ b/Content.Server/GameTicking/GameTicker.cs @@ -79,6 +79,8 @@ namespace Content.Server.GameTicking private readonly Random _spawnRandom = new Random(); + [ViewVariables] private readonly List _gameRules = new List(); + #pragma warning disable 649 [Dependency] private IEntityManager _entityManager; [Dependency] private IMapManager _mapManager; @@ -88,6 +90,7 @@ namespace Content.Server.GameTicking [Dependency] private IPlayerManager _playerManager; [Dependency] private IChatManager _chatManager; [Dependency] private IServerNetManager _netManager; + [Dependency] private IDynamicTypeFactory _dynamicTypeFactory; #pragma warning restore 649 public void Initialize() @@ -150,7 +153,7 @@ namespace Content.Server.GameTicking RunLevel = GameRunLevel.InRound; // TODO: Allow other presets to be selected. - var preset = new PresetTraitor(); + var preset = _dynamicTypeFactory.CreateInstance(); preset.Start(); foreach (var (playerSession, ready) in _playersInLobby.ToList()) @@ -219,6 +222,30 @@ namespace Content.Server.GameTicking _netManager.ServerSendMessage(_getStatusMsg(player), player.ConnectedClient); } + public T AddGameRule() where T : GameRule, new() + { + var instance = _dynamicTypeFactory.CreateInstance(); + + _gameRules.Add(instance); + instance.Added(); + + return instance; + } + + public void RemoveGameRule(GameRule rule) + { + if (_gameRules.Contains(rule)) + { + return; + } + + rule.Removed(); + + _gameRules.Remove(rule); + } + + public IEnumerable ActiveGameRules => _gameRules; + private IEntity _spawnPlayerMob() { var entity = _entityManager.ForceSpawnEntityAt(PlayerPrototypeName, _getLateJoinSpawnPoint()); @@ -290,6 +317,14 @@ namespace Content.Server.GameTicking { unCastData.ContentData().WipeMind(); } + + // Clear up any game rules. + foreach (var rule in _gameRules) + { + rule.Removed(); + } + + _gameRules.Clear(); } private void _preRoundSetup() diff --git a/Content.Server/Interfaces/GameTicking/IGameTicker.cs b/Content.Server/Interfaces/GameTicking/IGameTicker.cs index 892d5dec0b..ba737643c4 100644 --- a/Content.Server/Interfaces/GameTicking/IGameTicker.cs +++ b/Content.Server/Interfaces/GameTicking/IGameTicker.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Content.Server.GameTicking; using Robust.Server.Interfaces.Player; using Robust.Server.Player; @@ -27,5 +28,10 @@ namespace Content.Server.Interfaces.GameTicking void MakeObserve(IPlayerSession player); void MakeJoinGame(IPlayerSession player); void ToggleReady(IPlayerSession player, bool ready); + + // GameRule system. + T AddGameRule() where T : GameRule, new(); + void RemoveGameRule(GameRule rule); + IEnumerable ActiveGameRules { get; } } } From d15998ed16a0746ae176ffb8ca20592aff0361ec Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Wed, 8 May 2019 15:32:30 +0200 Subject: [PATCH 3/5] Make sure SpeciesUI defaults to having a correct icon. --- Content.Client/GameObjects/Components/Mobs/SpeciesUI.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Content.Client/GameObjects/Components/Mobs/SpeciesUI.cs b/Content.Client/GameObjects/Components/Mobs/SpeciesUI.cs index 1aecd91c6c..2f823be196 100644 --- a/Content.Client/GameObjects/Components/Mobs/SpeciesUI.cs +++ b/Content.Client/GameObjects/Components/Mobs/SpeciesUI.cs @@ -16,6 +16,7 @@ using Robust.Shared.IoC; using Robust.Shared.Log; using Robust.Shared.Utility; using System.Collections.Generic; +using Content.Client.Utility; using Content.Shared.GameObjects.Components.Mobs; using Robust.Client.Graphics.Overlays; @@ -142,6 +143,8 @@ namespace Content.Client.GameObjects { SizeFlagsHorizontal = SizeFlags.ShrinkCenter; SizeFlagsVertical = SizeFlags.None; + + Texture = IoCManager.Resolve().GetTexture("/Textures/Mob/UI/Human/human0.png"); } public void SetIcon(HudStateChange changeMessage) From 29304a771464f56889c25c8f2ffe66c67c8f30e2 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Wed, 8 May 2019 16:42:36 +0200 Subject: [PATCH 4/5] Handle existing players on restartround correctly. --- Content.Server/GameTicking/GameTicker.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Content.Server/GameTicking/GameTicker.cs b/Content.Server/GameTicking/GameTicker.cs index 4830150745..5b98912752 100644 --- a/Content.Server/GameTicking/GameTicker.cs +++ b/Content.Server/GameTicking/GameTicker.cs @@ -142,6 +142,8 @@ namespace Content.Server.GameTicking { _roundStartTimeUtc = DateTime.UtcNow + TimeSpan.FromSeconds(LobbyDuration); } + + _sendStatusToAll(); } } @@ -158,7 +160,7 @@ namespace Content.Server.GameTicking foreach (var (playerSession, ready) in _playersInLobby.ToList()) { - if (!ready) + if (LobbyEnabled && !ready) { continue; } @@ -325,6 +327,17 @@ namespace Content.Server.GameTicking } _gameRules.Clear(); + + // Move everybody currently in the server to lobby. + foreach (var player in _playerManager.GetAllPlayers()) + { + if (_playersInLobby.ContainsKey(player)) + { + continue; + } + + _playerJoinLobby(player); + } } private void _preRoundSetup() @@ -369,7 +382,6 @@ namespace Content.Server.GameTicking case SessionStatus.InGame: { - //TODO: Check for existing mob and re-attach var data = session.ContentData(); if (data.Mind == null) { From 0ccefebc520c1516b9ffcb3c6175ff0ab3ee5941 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Wed, 8 May 2019 16:49:59 +0200 Subject: [PATCH 5/5] Entering text into lobby chat box does not release focus. --- Content.Client/Chat/ChatBox.cs | 8 +++++++- Content.Client/UserInterface/LobbyGui.cs | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Content.Client/Chat/ChatBox.cs b/Content.Client/Chat/ChatBox.cs index f9f9b46152..2060c1e4e9 100644 --- a/Content.Client/Chat/ChatBox.cs +++ b/Content.Client/Chat/ChatBox.cs @@ -38,6 +38,8 @@ namespace Content.Client.Chat /// public string DefaultChatFormat { get; set; } + public bool ReleaseFocusOnEnter { get; set; } = true; + protected override void Initialize() { base.Initialize(); @@ -151,7 +153,11 @@ namespace Content.Client.Chat _inputIndex = -1; Input.Clear(); - Input.ReleaseKeyboardFocus(); + + if (ReleaseFocusOnEnter) + { + Input.ReleaseKeyboardFocus(); + } } } } diff --git a/Content.Client/UserInterface/LobbyGui.cs b/Content.Client/UserInterface/LobbyGui.cs index 0ff209bba1..64f6e65402 100644 --- a/Content.Client/UserInterface/LobbyGui.cs +++ b/Content.Client/UserInterface/LobbyGui.cs @@ -28,7 +28,7 @@ namespace Content.Client.UserInterface base.Initialize(); var chatContainer = GetChild("Panel/VBoxContainer/HBoxContainer/LeftVBox"); - Chat = new ChatBox(); + Chat = new ChatBox {ReleaseFocusOnEnter = false}; chatContainer.AddChild(Chat); Chat.SizeFlagsVertical = SizeFlags.FillExpand; }