-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Bwoink System Refactor #40989
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
Simyon264
wants to merge
39
commits into
space-wizards:master
Choose a base branch
from
Simyon264:bwoink-system-refactor
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+2,381
−1,860
Draft
Bwoink System Refactor #40989
Changes from 29 commits
Commits
Show all changes
39 commits
Select commit
Hold shift + click to select a range
0c74252
Nuke BwoinkSystem.cs
Simyon264 9bcdb38
WIP: Ahelp refactor
Simyon264 4cebe7c
Remove leftover AHelpMessage
Simyon264 0786290
Add doc-comment to Flags
Simyon264 6388982
Make message flags a byte
Simyon264 fec6130
Fix lobby button going out of sync if you close window manually
Simyon264 048194b
Clear text output when syncing lines
Simyon264 7fba8cf
add channel help text when clearing once again
Simyon264 71aadeb
Remove unused method for now
Simyon264 4a323d3
implement message sync
Simyon264 62ece7c
fix admins sending in their own channel resulting in no messages bein…
Simyon264 91772cd
don't send help text for manager panels
Simyon264 bbf28ab
properly handle rich text
Simyon264 a2edef7
convert into method group
Simyon264 5d2c31e
Make unreads work properly
Simyon264 e670e93
minor, make props readonly
Simyon264 c62b8c4
Fix some issues with UI lifetime (i think)
Simyon264 7ab24a5
Fix unclosed menu not keeping unread count
Simyon264 7680a2d
also do this for last message
Simyon264 9325c39
give nik the sound they deserve
Simyon264 fb9132b
ui manager isn't real
Simyon264 384f689
add support for channels without sound play
Simyon264 ad8d7bc
remove unused imports
Simyon264 9ffd69a
Register a shared instance for bwoink manager
Simyon264 deb6cff
there IS a better way of doing this
Simyon264 f777c84
it did, in fact, not work
Simyon264 3cb4c53
i have, the stupid
Simyon264 26ae3fd
i have the stupid disease
Simyon264 62f5457
implement typing status
Simyon264 5130470
Merge branch 'master' into bwoink-system-refactor
Simyon264 65b3e3c
fix conflicts
Simyon264 bfa77e9
cleanup and add more comments
Simyon264 65eda47
Add public API and toolshed command for bwoinking
Simyon264 1149532
properly switch to channel when getting bwoinked in that channel
Simyon264 b845dbd
add temporary testing channel
Simyon264 bd8c40f
half working implementation of better requirements for channels
Simyon264 ee2858e
finish list requirement and handling channel syncs
Simyon264 3c05c5e
Implement OperationMode.None
Simyon264 6bfc5c7
add sync command
Simyon264 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
213 changes: 213 additions & 0 deletions
213
Content.Client/Administration/Managers/ClientBwoinkManager.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,213 @@ | ||
using System.Linq; | ||
using Content.Shared.Administration.Managers.Bwoink; | ||
using Content.Shared.Administration.Managers.Bwoink.Features; | ||
using Robust.Client.Audio; | ||
using Robust.Client.ResourceManagement; | ||
using Robust.Shared.Audio.Sources; | ||
using Robust.Shared.Network; | ||
using Robust.Shared.Player; | ||
using Robust.Shared.Prototypes; | ||
using Robust.Shared.Timing; | ||
|
||
namespace Content.Client.Administration.Managers; | ||
|
||
public sealed class ClientBwoinkManager : SharedBwoinkManager | ||
{ | ||
[Dependency] private readonly INetManager _netManager = default!; | ||
[Dependency] private readonly ISharedPlayerManager _playerManager = default!; | ||
[Dependency] private readonly IResourceCache _res = default!; | ||
[Dependency] private readonly IAudioManager _audio = default!; | ||
[Dependency] private readonly IClientAdminManager _adminManager = default!; | ||
[Dependency] private readonly IGameTiming _gameTiming = default!; | ||
|
||
[ViewVariables] | ||
public readonly Dictionary<ProtoId<BwoinkChannelPrototype>, Dictionary<NetUserId, PlayerChannelProperties>> | ||
PlayerChannels = new(); | ||
|
||
/// <summary> | ||
/// Contains the ratelimits for each userchannel we send a typing status to. | ||
/// </summary> | ||
private Dictionary<NetUserId, TimeSpan> _typingRateLimits = new(); | ||
|
||
/// <summary> | ||
/// Dictionary that contains the sounds to play for a specified channel, source may be null. | ||
/// </summary> | ||
public readonly Dictionary<ProtoId<BwoinkChannelPrototype>, IAudioSource?> CachedSounds = new(); | ||
|
||
/// <summary> | ||
/// Called whenever our prototypes change, or a full state update is applied. | ||
/// </summary> | ||
public event Action? ReloadedData; | ||
|
||
/// <summary> | ||
/// Called whenever we receieve a <see cref="MsgBwoinkTypings"/> | ||
/// </summary> | ||
public event Action? TypingsUpdated; | ||
|
||
public override void Initialize() | ||
{ | ||
base.Initialize(); | ||
_netManager.RegisterNetMessage<MsgBwoinkNonAdmin>(BwoinkAttempted); | ||
_netManager.RegisterNetMessage<MsgBwoink>(AdminBwoinkAttempted); | ||
_netManager.RegisterNetMessage<MsgBwoinkSyncRequest>(); | ||
_netManager.RegisterNetMessage<MsgBwoinkSync>(SyncBwoinks); | ||
_netManager.RegisterNetMessage<MsgBwoinkTypingUpdate>(); | ||
_netManager.RegisterNetMessage<MsgBwoinkTypings>(SyncTypings); | ||
|
||
_adminManager.AdminStatusUpdated += StatusUpdated; | ||
} | ||
|
||
private void SyncTypings(MsgBwoinkTypings message) | ||
{ | ||
TypingStatuses[message.Channel] = message.Typings; | ||
TypingsUpdated?.Invoke(); | ||
} | ||
|
||
private void StatusUpdated() | ||
{ | ||
RequestSync(); | ||
} | ||
|
||
public PlayerChannelProperties GetOrCreatePlayerPropertiesForChannel(ProtoId<BwoinkChannelPrototype> channel, NetUserId userId) | ||
{ | ||
PlayerChannels.TryAdd(channel, new Dictionary<NetUserId, PlayerChannelProperties>()); | ||
|
||
if (PlayerChannels[channel].TryGetValue(userId, out var value)) | ||
return value; | ||
|
||
PlayerChannels[channel].Add(userId, new PlayerChannelProperties()); | ||
return PlayerChannels[channel][userId]; | ||
} | ||
|
||
protected override void UpdatedChannels() | ||
{ | ||
foreach (var (key, channel) in ProtoCache) | ||
{ | ||
foreach (var feature in channel.Features) | ||
{ | ||
if (feature is not SoundOnMessage soundOnMessage) | ||
continue; | ||
|
||
if (CachedSounds.TryGetValue(key, out var cachedSound)) | ||
cachedSound?.Dispose(); | ||
|
||
var sound = _audio.CreateAudioSource(_res.GetResource<AudioResource>(soundOnMessage.Sound.Path)); | ||
if (sound != null) | ||
sound.Global = true; | ||
|
||
CachedSounds[key] = sound; | ||
break; | ||
} | ||
} | ||
|
||
ReloadedData?.Invoke(); | ||
} | ||
|
||
private void SyncBwoinks(MsgBwoinkSync message) | ||
{ | ||
Log.Info($"Received full state! {message.Conversations.Count} channels with {message.Conversations.Values.Select(x => x.Count).Count()} conversations."); | ||
Conversations = message.Conversations; | ||
ReloadedData?.Invoke(); | ||
} | ||
|
||
private void AdminBwoinkAttempted(MsgBwoink message) | ||
{ | ||
InvokeMessageReceived(message.Channel, | ||
message.Target, | ||
message.Message.Content, | ||
message.Message.SenderId, | ||
message.Message.Sender, | ||
message.Message.Flags); | ||
} | ||
|
||
private void BwoinkAttempted(MsgBwoinkNonAdmin message) | ||
{ | ||
// This one is targeted to us, so we use our local session as the target. | ||
// ReSharper disable once NullableWarningSuppressionIsUsed | ||
// "The user Id of the local player. This will be null on the server.". | ||
// Null suppression because we will only ever receive this while being connected. If it is null, something has gone wrong. | ||
InvokeMessageReceived(message.Channel, | ||
_playerManager.LocalUser!.Value, | ||
message.Message.Content, | ||
message.Message.SenderId, | ||
message.Message.Sender, | ||
message.Message.Flags); | ||
} | ||
|
||
public void SendMessageNonAdmin(ProtoId<BwoinkChannelPrototype> channel, string text) | ||
{ | ||
_netManager.ClientSendMessage(new MsgBwoinkNonAdmin() | ||
{ | ||
// We can leave all of this null since the server will set all of this anyways. | ||
Message = new BwoinkMessage(string.Empty, null, DateTime.UtcNow, text, MessageFlags.None), | ||
Channel = channel, | ||
}); | ||
} | ||
|
||
public void SendMessageAdmin(BwoinkChannelPrototype channel, NetUserId user, string text) | ||
{ | ||
_netManager.ClientSendMessage(new MsgBwoink() | ||
{ | ||
// We can leave all of this null since the server will set all of this anyways. | ||
Message = new BwoinkMessage(string.Empty, null, DateTime.UtcNow, text, MessageFlags.None), | ||
Channel = channel, | ||
Target = user, | ||
}); | ||
} | ||
|
||
/// <summary> | ||
/// Updates your typing status for the client, this results in a <see cref="MsgBwoinkTypingUpdate"/> message. | ||
/// </summary> | ||
/// <remarks> | ||
/// This method has an internal ratelimit of 8 seconds. This ratelimit only applies for setting the typing state to true. | ||
/// </remarks> | ||
public void SetTypingStatus(ProtoId<BwoinkChannelPrototype> channel, bool typing, NetUserId? userChannel) | ||
{ | ||
const int rateLimit = 3; | ||
|
||
userChannel ??= _playerManager.LocalUser!.Value; | ||
// Check ratelimit | ||
if (_typingRateLimits.TryGetValue(userChannel.Value, out var limit)) | ||
{ | ||
if (typing && _gameTiming.RealTime < limit) | ||
return; | ||
|
||
if (!typing) | ||
{ | ||
// We are sending a "stopped typing" message. So: Remove current rate limit key so the next "i am typing" message can get through. | ||
_typingRateLimits.Remove(userChannel.Value); | ||
} | ||
else | ||
{ | ||
_typingRateLimits[userChannel.Value] = _gameTiming.RealTime + TimeSpan.FromSeconds(rateLimit); | ||
} | ||
} | ||
else | ||
{ | ||
_typingRateLimits.Add(userChannel.Value, _gameTiming.RealTime + TimeSpan.FromSeconds(rateLimit)); | ||
} | ||
|
||
_netManager.ClientSendMessage(new MsgBwoinkTypingUpdate() | ||
{ | ||
IsTyping = typing, | ||
Channel = channel, | ||
ChannelUserId = userChannel.Value, | ||
}); | ||
} | ||
|
||
/// <summary> | ||
/// Requests a full re-sync of all conversations we have. There is no locking so calling this while conversations are on-going may result in dropped or duplicated messages. | ||
/// </summary> | ||
public void RequestSync() | ||
{ | ||
// TODO: Maybe locking??? | ||
Log.Info("Resetting Bwoink state!"); | ||
_netManager.ClientSendMessage(new MsgBwoinkSyncRequest()); | ||
} | ||
} | ||
|
||
public sealed class PlayerChannelProperties | ||
{ | ||
public DateTime LastMessage { get; set; } = DateTime.MinValue; | ||
public int Unread { get; set; } = 0; | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please keep the quick actions for player interactions. Like follow, kick, ban, etc. I'm afraid that this will ruin the experience that admins have come to expect with the ahelp menu, also the player panel is frankly extremely slow and is unusable till data from the database is loaded in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, wasn't aware it was on the todo list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My opinion on the actions list is there's definitely a way better way to do it than hardcoded buttons lmao