From dba841092051131abf8d73f9dd5dbcf0278b06e7 Mon Sep 17 00:00:00 2001 From: Ethan Moffat Date: Thu, 31 Mar 2022 14:05:04 -0700 Subject: [PATCH] Add periodic emote for AFK players --- .../Controllers/MapInteractionController.cs | 13 ++++++--- .../HUD/Controls/HudControlsFactory.cs | 7 +++-- .../Input/IUserInputTimeRepository.cs | 9 +++++-- .../Rendering/Character/CharacterAnimator.cs | 27 +++++++++++++++++++ .../Rendering/MouseCursorRenderer.cs | 8 +++--- .../Rendering/OldCharacterRenderer.cs | 22 +-------------- 6 files changed, 54 insertions(+), 32 deletions(-) diff --git a/EndlessClient/Controllers/MapInteractionController.cs b/EndlessClient/Controllers/MapInteractionController.cs index a83e9bffa..a275a21cc 100644 --- a/EndlessClient/Controllers/MapInteractionController.cs +++ b/EndlessClient/Controllers/MapInteractionController.cs @@ -6,6 +6,7 @@ using EndlessClient.HUD.Controls; using EndlessClient.HUD.Inventory; using EndlessClient.HUD.Panels; +using EndlessClient.Input; using EndlessClient.Rendering; using EndlessClient.Rendering.Character; using EndlessClient.Rendering.Factories; @@ -33,6 +34,7 @@ public class MapInteractionController : IMapInteractionController private readonly IHudControlProvider _hudControlProvider; private readonly ICharacterRendererProvider _characterRendererProvider; private readonly IContextMenuRepository _contextMenuRepository; + private readonly IUserInputTimeRepository _userInputTimeRepository; private readonly IEOMessageBoxFactory _eoMessageBoxFactory; private readonly IContextMenuRendererFactory _contextMenuRendererFactory; @@ -46,6 +48,7 @@ public MapInteractionController(IMapActions mapActions, IHudControlProvider hudControlProvider, ICharacterRendererProvider characterRendererProvider, IContextMenuRepository contextMenuRepository, + IUserInputTimeRepository userInputTimeRepository, IEOMessageBoxFactory eoMessageBoxFactory, IContextMenuRendererFactory contextMenuRendererFactory) { @@ -59,11 +62,12 @@ public MapInteractionController(IMapActions mapActions, _hudControlProvider = hudControlProvider; _characterRendererProvider = characterRendererProvider; _contextMenuRepository = contextMenuRepository; + _userInputTimeRepository = userInputTimeRepository; _eoMessageBoxFactory = eoMessageBoxFactory; _contextMenuRendererFactory = contextMenuRendererFactory; } - public async Task LeftClickAsync(IMapCellState cellState, IMouseCursorRenderer mouseRenderer) + public void LeftClick(IMapCellState cellState, IMouseCursorRenderer mouseRenderer) { if (!InventoryPanel.NoItemsDragging()) { @@ -89,7 +93,7 @@ public async Task LeftClickAsync(IMapCellState cellState, IMouseCursorRenderer m { var sign = cellState.Sign.ValueOr(Sign.None); var messageBox = _eoMessageBoxFactory.CreateMessageBox(sign.Message, sign.Title); - await messageBox.ShowDialogAsync(); + messageBox.ShowDialog(); } else if (cellState.Chest.HasValue) { /* TODO: chest interaction */ } else if (cellState.Character.HasValue) { /* TODO: character spell cast */ } @@ -99,6 +103,8 @@ public async Task LeftClickAsync(IMapCellState cellState, IMouseCursorRenderer m _hudControlProvider.GetComponent(HudControlIdentifier.CharacterAnimator) .StartMainCharacterWalkAnimation(Option.Some(cellState.Coordinate)); } + + _userInputTimeRepository.LastInputTime = DateTime.Now; } public void RightClick(IMapCellState cellState) @@ -111,6 +117,7 @@ public void RightClick(IMapCellState cellState) if (c == _characterProvider.MainCharacter) { _inGameDialogActions.ShowPaperdollDialog(_characterProvider.MainCharacter, isMainCharacter: true); + _userInputTimeRepository.LastInputTime = DateTime.Now; } else if (_characterRendererProvider.CharacterRenderers.ContainsKey(c.ID)) { @@ -160,7 +167,7 @@ private void HandlePickupResult(ItemPickupResult pickupResult, IItem item) public interface IMapInteractionController { - Task LeftClickAsync(IMapCellState cellState, IMouseCursorRenderer mouseRenderer); + void LeftClick(IMapCellState cellState, IMouseCursorRenderer mouseRenderer); void RightClick(IMapCellState cellState); } diff --git a/EndlessClient/HUD/Controls/HudControlsFactory.cs b/EndlessClient/HUD/Controls/HudControlsFactory.cs index 40dc94d08..348b80fd1 100644 --- a/EndlessClient/HUD/Controls/HudControlsFactory.cs +++ b/EndlessClient/HUD/Controls/HudControlsFactory.cs @@ -56,6 +56,7 @@ public class HudControlsFactory : IHudControlsFactory private readonly ICharacterActions _characterActions; private readonly IWalkValidationActions _walkValidationActions; private readonly IPacketSendService _packetSendService; + private readonly IUserInputTimeProvider _userInputTimeProvider; private IChatController _chatController; public HudControlsFactory(IHudButtonController hudButtonController, @@ -80,7 +81,8 @@ public HudControlsFactory(IHudButtonController hudButtonController, IPathFinder pathFinder, ICharacterActions characterActions, IWalkValidationActions walkValidationActions, - IPacketSendService packetSendService) + IPacketSendService packetSendService, + IUserInputTimeProvider userInputTimeProvider) { _hudButtonController = hudButtonController; _hudPanelFactory = hudPanelFactory; @@ -105,6 +107,7 @@ public HudControlsFactory(IHudButtonController hudButtonController, _characterActions = characterActions; _walkValidationActions = walkValidationActions; _packetSendService = packetSendService; + _userInputTimeProvider = userInputTimeProvider; } public void InjectChatController(IChatController chatController) @@ -387,7 +390,7 @@ private IUserInputHandler CreateUserInputHandler() private ICharacterAnimator CreateCharacterAnimator() { - return new CharacterAnimator(_endlessGameProvider, _characterRepository, _currentMapStateRepository, _currentMapProvider, _characterActions, _walkValidationActions, _pathFinder); + return new CharacterAnimator(_endlessGameProvider, _characterRepository, _currentMapStateRepository, _currentMapProvider, _userInputTimeProvider, _characterActions, _walkValidationActions, _pathFinder); } private INPCAnimator CreateNPCAnimator() diff --git a/EndlessClient/Input/IUserInputTimeRepository.cs b/EndlessClient/Input/IUserInputTimeRepository.cs index 95c24e468..5f8c6c4da 100644 --- a/EndlessClient/Input/IUserInputTimeRepository.cs +++ b/EndlessClient/Input/IUserInputTimeRepository.cs @@ -8,8 +8,13 @@ public interface IUserInputTimeRepository DateTime LastInputTime { get; set; } } - [MappedType(BaseType = typeof(IUserInputTimeRepository), IsSingleton = true)] - public class UserInputTimeRepository : IUserInputTimeRepository + public interface IUserInputTimeProvider + { + DateTime LastInputTime { get; } + } + + [AutoMappedType(IsSingleton = true)] + public class UserInputTimeRepository : IUserInputTimeRepository, IUserInputTimeProvider { public DateTime LastInputTime { get; set; } diff --git a/EndlessClient/Rendering/Character/CharacterAnimator.cs b/EndlessClient/Rendering/Character/CharacterAnimator.cs index 9f9b3b50c..db4021551 100644 --- a/EndlessClient/Rendering/Character/CharacterAnimator.cs +++ b/EndlessClient/Rendering/Character/CharacterAnimator.cs @@ -1,5 +1,6 @@ using EndlessClient.GameExecution; using EndlessClient.HUD; +using EndlessClient.Input; using EOLib; using EOLib.Domain.Character; using EOLib.Domain.Extensions; @@ -23,6 +24,7 @@ public class CharacterAnimator : GameComponent, ICharacterAnimator private readonly ICharacterRepository _characterRepository; private readonly ICurrentMapStateRepository _currentMapStateRepository; private readonly ICurrentMapProvider _currentMapProvider; + private readonly IUserInputTimeProvider _userInputTimeProvider; private readonly ICharacterActions _characterActions; private readonly IWalkValidationActions _walkValidationActions; private readonly IPathFinder _pathFinder; @@ -41,6 +43,8 @@ public class CharacterAnimator : GameComponent, ICharacterAnimator private int _drunkIntervalSeconds; private double _drunkTimeoutSeconds; + private Option _afkTimeSinceLastEmote; + private Queue _walkPath; private Option _targetCoordinate; @@ -48,6 +52,7 @@ public CharacterAnimator(IEndlessGameProvider gameProvider, ICharacterRepository characterRepository, ICurrentMapStateRepository currentMapStateRepository, ICurrentMapProvider currentMapProvider, + IUserInputTimeProvider userInputTimeProvider, ICharacterActions characterActions, IWalkValidationActions walkValidationActions, IPathFinder pathFinder) @@ -56,6 +61,7 @@ public CharacterAnimator(IEndlessGameProvider gameProvider, _characterRepository = characterRepository; _currentMapStateRepository = currentMapStateRepository; _currentMapProvider = currentMapProvider; + _userInputTimeProvider = userInputTimeProvider; _characterActions = characterActions; _walkValidationActions = walkValidationActions; _pathFinder = pathFinder; @@ -448,6 +454,7 @@ private void AnimateCharacterSpells() private void AnimateCharacterEmotes() { + // todo: drunk/afk stuff might be better suited in a different game component, since they don't strictly pertain to character animation _drunkStart.Match( some: ds => { @@ -488,6 +495,26 @@ private void AnimateCharacterEmotes() } }); + if ((DateTime.Now - _userInputTimeProvider.LastInputTime).TotalMinutes >= 5) + { + _afkTimeSinceLastEmote.Match( + some: at => + { + if (at.Elapsed.TotalMinutes >= 1) + { + if (Emote(_characterRepository.MainCharacter.ID, EOLib.Domain.Character.Emote.Moon)) + _characterActions.Emote(EOLib.Domain.Character.Emote.Moon); + _afkTimeSinceLastEmote = Option.Some(Stopwatch.StartNew()); + } + }, + none: () => + { + if (Emote(_characterRepository.MainCharacter.ID, EOLib.Domain.Character.Emote.Moon)) + _characterActions.Emote(EOLib.Domain.Character.Emote.Moon); + _afkTimeSinceLastEmote = Option.Some(Stopwatch.StartNew()); + }); + } + var playersDoneEmoting = new HashSet(); foreach (var pair in _startEmoteTimes.Values) { diff --git a/EndlessClient/Rendering/MouseCursorRenderer.cs b/EndlessClient/Rendering/MouseCursorRenderer.cs index ddd848ea2..5d14b39e7 100644 --- a/EndlessClient/Rendering/MouseCursorRenderer.cs +++ b/EndlessClient/Rendering/MouseCursorRenderer.cs @@ -110,7 +110,7 @@ public override void Initialize() #region Update and Helpers - public override async void Update(GameTime gameTime) + public override void Update(GameTime gameTime) { // prevents updates if there is a dialog if (!ShouldUpdate() || _activeDialogProvider.ActiveDialogs.Any(x => x.HasValue) || @@ -128,7 +128,7 @@ public override async void Update(GameTime gameTime) var cellState = _mapCellStateProvider.GetCellStateAt(_gridX, _gridY); UpdateCursorSourceRectangle(cellState); - await CheckForClicks(cellState); + CheckForClicks(cellState); } private void SetGridCoordsBasedOnMousePosition(int offsetX, int offsetY) @@ -285,7 +285,7 @@ private void UpdateCursorIndexForTileSpec(TileSpec tileSpec) } } - private async Task CheckForClicks(IMapCellState cellState) + private void CheckForClicks(IMapCellState cellState) { var currentMouseState = _userInputProvider.CurrentMouseState; var previousMouseState = _userInputProvider.PreviousMouseState; @@ -294,7 +294,7 @@ private async Task CheckForClicks(IMapCellState cellState) if (currentMouseState.LeftButton == ButtonState.Released && previousMouseState.LeftButton == ButtonState.Pressed) { - await _mapInteractionController.LeftClickAsync(cellState, this); + _mapInteractionController.LeftClick(cellState, this); } } diff --git a/EndlessClient/Rendering/OldCharacterRenderer.cs b/EndlessClient/Rendering/OldCharacterRenderer.cs index df0769ff7..c5308dff6 100644 --- a/EndlessClient/Rendering/OldCharacterRenderer.cs +++ b/EndlessClient/Rendering/OldCharacterRenderer.cs @@ -91,7 +91,6 @@ public EODirection Facing private readonly DamageCounter m_damageCounter; private DateTime? m_deadTime; - private DateTime m_lastActTime; private DateTime? _spellInvocationStartTime; @@ -221,8 +220,6 @@ public override void Initialize() _spellCastTimer = new Timer(_endSpellCast, null, Timeout.Infinite, Timeout.Infinite); } - - m_lastActTime = DateTime.Now; } protected override void UnloadContent() @@ -247,8 +244,7 @@ public override void Update(GameTime gameTime) if (EOGame.Instance.State == GameStates.PlayingTheGame && this == OldWorld.Instance.ActiveCharacterRenderer) { - _adjustSP(gameTime); - _checkAFKCharacter(); + _adjustSP(gameTime);; } } @@ -362,18 +358,6 @@ private void _adjustSP(GameTime gameTime) Character.Stats.SP = (short)(Character.Stats.SP + 1); } - private void _checkAFKCharacter() - { - //5-minute timeout: start sending emotes every minute - //if ((DateTime.Now - m_lastActTime).TotalMinutes > 5 && - // (m_lastEmoteTime == null || (DateTime.Now - m_lastEmoteTime.Value).TotalMinutes > 1)) - //{ - // m_lastEmoteTime = DateTime.Now; - // Character.Emote(Emote.Moon); - // PlayerEmote(); - //} - } - private bool _getMouseOverActual() { var skinDrawLoc = _getSkinDrawLoc(); @@ -485,10 +469,6 @@ public void PlayerAttack(bool isWaterTile) catch (ObjectDisposedException) { } } - public void UpdateInputTime(DateTime lastInputTime) - { - m_lastActTime = lastInputTime; - } public void Die() {