2023-11-05 18:19:59 -08:00
using System.Diagnostics.CodeAnalysis ;
2020-09-13 14:23:52 +02:00
using System.Linq ;
2023-10-14 02:02:56 -07:00
using System.Runtime.InteropServices ;
2022-01-19 13:35:31 +11:00
using Content.Server.Administration.Logs ;
2021-06-09 22:19:39 +02:00
using Content.Server.Administration.Managers ;
2023-03-23 10:10:49 -05:00
using Content.Server.Administration.Systems ;
2021-06-09 22:19:39 +02:00
using Content.Server.MoMMI ;
2024-06-21 00:13:02 +02:00
using Content.Server.Players.RateLimiting ;
2021-06-09 22:19:39 +02:00
using Content.Server.Preferences.Managers ;
2021-02-14 11:59:56 -03:00
using Content.Shared.Administration ;
2021-06-13 14:52:40 +02:00
using Content.Shared.CCVar ;
2019-04-13 09:45:09 +02:00
using Content.Shared.Chat ;
2022-01-19 13:35:31 +11:00
using Content.Shared.Database ;
2023-08-30 21:46:11 -07:00
using Content.Shared.Mind ;
2024-09-30 01:19:00 +13:00
using Content.Shared.Players.RateLimiting ;
2021-02-16 20:14:32 +01:00
using Robust.Shared.Configuration ;
2021-02-11 01:13:03 -08:00
using Robust.Shared.Network ;
2021-11-22 22:34:48 +00:00
using Robust.Shared.Player ;
2022-11-23 00:52:19 +13:00
using Robust.Shared.Replays ;
2021-02-28 18:51:30 +01:00
using Robust.Shared.Utility ;
2019-04-13 09:45:09 +02:00
2024-08-15 20:26:57 +02:00
namespace Content.Server.Chat.Managers ;
/// <summary>
/// Dispatches chat messages to clients.
/// </summary>
internal sealed partial class ChatManager : IChatManager
2019-04-13 09:45:09 +02:00
{
2024-08-15 20:26:57 +02:00
private static readonly Dictionary < string , string > PatronOocColors = new ( )
{
// I had plans for multiple colors and those went nowhere so...
{ "nuclear_operative" , "#aa00ff" } ,
{ "syndicate_agent" , "#aa00ff" } ,
{ "revolutionary" , "#aa00ff" }
} ;
[Dependency] private readonly IReplayRecordingManager _replay = default ! ;
[Dependency] private readonly IServerNetManager _netManager = default ! ;
[Dependency] private readonly IMoMMILink _mommiLink = default ! ;
[Dependency] private readonly IAdminManager _adminManager = default ! ;
[Dependency] private readonly IAdminLogManager _adminLogger = default ! ;
[Dependency] private readonly IServerPreferencesManager _preferencesManager = default ! ;
[Dependency] private readonly IConfigurationManager _configurationManager = default ! ;
[Dependency] private readonly INetConfigurationManager _netConfigManager = default ! ;
[Dependency] private readonly IEntityManager _entityManager = default ! ;
[Dependency] private readonly PlayerRateLimitManager _rateLimitManager = default ! ;
2019-04-13 09:45:09 +02:00
/// <summary>
2024-08-15 20:26:57 +02:00
/// The maximum length a player-sent message can be sent
2019-04-13 09:45:09 +02:00
/// </summary>
2024-08-15 20:26:57 +02:00
public int MaxMessageLength = > _configurationManager . GetCVar ( CCVars . ChatMaxMessageLength ) ;
private bool _oocEnabled = true ;
private bool _adminOocEnabled = true ;
private readonly Dictionary < NetUserId , ChatUser > _players = new ( ) ;
public void Initialize ( )
2019-04-13 09:45:09 +02:00
{
2024-08-15 20:26:57 +02:00
_netManager . RegisterNetMessage < MsgChatMessage > ( ) ;
_netManager . RegisterNetMessage < MsgDeleteChatMessagesBy > ( ) ;
2020-08-25 17:09:39 +02:00
2024-08-15 20:26:57 +02:00
_configurationManager . OnValueChanged ( CCVars . OocEnabled , OnOocEnabledChanged , true ) ;
_configurationManager . OnValueChanged ( CCVars . AdminOocEnabled , OnAdminOocEnabledChanged , true ) ;
2023-11-27 04:08:30 +01:00
2024-08-15 20:26:57 +02:00
RegisterRateLimits ( ) ;
}
2021-02-16 20:14:32 +01:00
2024-08-15 20:26:57 +02:00
private void OnOocEnabledChanged ( bool val )
{
if ( _oocEnabled = = val ) return ;
2022-01-19 13:35:31 +11:00
2024-08-15 20:26:57 +02:00
_oocEnabled = val ;
DispatchServerAnnouncement ( Loc . GetString ( val ? "chat-manager-ooc-chat-enabled-message" : "chat-manager-ooc-chat-disabled-message" ) ) ;
}
2021-02-16 20:14:32 +01:00
2024-08-15 20:26:57 +02:00
private void OnAdminOocEnabledChanged ( bool val )
{
if ( _adminOocEnabled = = val ) return ;
2022-01-19 13:35:31 +11:00
2024-08-15 20:26:57 +02:00
_adminOocEnabled = val ;
DispatchServerAnnouncement ( Loc . GetString ( val ? "chat-manager-admin-ooc-chat-enabled-message" : "chat-manager-admin-ooc-chat-disabled-message" ) ) ;
}
2019-04-13 09:45:09 +02:00
2024-08-31 11:38:03 +00:00
public void DeleteMessagesBy ( NetUserId uid )
{
if ( ! _players . TryGetValue ( uid , out var user ) )
return ;
2023-10-14 02:02:56 -07:00
2024-08-15 20:26:57 +02:00
var msg = new MsgDeleteChatMessagesBy { Key = user . Key , Entities = user . Entities } ;
_netManager . ServerSendToAll ( msg ) ;
}
2023-10-14 02:02:56 -07:00
2024-08-15 20:26:57 +02:00
[return: NotNullIfNotNull(nameof(author))]
public ChatUser ? EnsurePlayer ( NetUserId ? author )
{
if ( author = = null )
return null ;
2023-11-05 18:19:59 -08:00
2024-08-15 20:26:57 +02:00
ref var user = ref CollectionsMarshal . GetValueRefOrAddDefault ( _players , author . Value , out var exists ) ;
if ( ! exists | | user = = null )
user = new ChatUser ( _players . Count ) ;
2023-11-05 18:19:59 -08:00
2024-08-15 20:26:57 +02:00
return user ;
}
2023-11-05 18:19:59 -08:00
2024-08-15 20:26:57 +02:00
#region Server Announcements
2022-03-30 22:21:58 -07:00
2024-08-15 20:26:57 +02:00
public void DispatchServerAnnouncement ( string message , Color ? colorOverride = null )
{
var wrappedMessage = Loc . GetString ( "chat-manager-server-wrap-message" , ( "message" , FormattedMessage . EscapeText ( message ) ) ) ;
ChatMessageToAll ( ChatChannel . Server , message , wrappedMessage , EntityUid . Invalid , hideChat : false , recordReplay : true , colorOverride : colorOverride ) ;
Logger . InfoS ( "SERVER" , message ) ;
2022-01-19 13:35:31 +11:00
2024-08-15 20:26:57 +02:00
_adminLogger . Add ( LogType . Chat , LogImpact . Low , $"Server announcement: {message}" ) ;
}
2019-04-13 09:45:09 +02:00
2024-08-15 20:26:57 +02:00
public void DispatchServerMessage ( ICommonSession player , string message , bool suppressLog = false )
{
var wrappedMessage = Loc . GetString ( "chat-manager-server-wrap-message" , ( "message" , FormattedMessage . EscapeText ( message ) ) ) ;
ChatMessageToOne ( ChatChannel . Server , message , wrappedMessage , default , false , player . Channel ) ;
2022-01-25 10:38:52 +01:00
2024-08-15 20:26:57 +02:00
if ( ! suppressLog )
_adminLogger . Add ( LogType . Chat , LogImpact . Low , $"Server message to {player:Player}: {message}" ) ;
}
2022-01-25 10:38:52 +01:00
2024-08-15 20:26:57 +02:00
public void SendAdminAnnouncement ( string message , AdminFlags ? flagBlacklist , AdminFlags ? flagWhitelist )
{
var clients = _adminManager . ActiveAdmins . Where ( p = >
2019-04-13 09:45:09 +02:00
{
2024-08-15 20:26:57 +02:00
var adminData = _adminManager . GetAdminData ( p ) ;
2024-03-24 17:39:53 +02:00
2024-08-15 20:26:57 +02:00
DebugTools . AssertNotNull ( adminData ) ;
2024-03-24 17:39:53 +02:00
2024-08-15 20:26:57 +02:00
if ( adminData = = null )
return false ;
2024-03-24 17:39:53 +02:00
2024-08-15 20:26:57 +02:00
if ( flagBlacklist ! = null & & adminData . HasFlag ( flagBlacklist . Value ) )
return false ;
2024-03-24 17:39:53 +02:00
2024-08-15 20:26:57 +02:00
return flagWhitelist = = null | | adminData . HasFlag ( flagWhitelist . Value ) ;
2024-03-24 17:39:53 +02:00
2024-08-15 20:26:57 +02:00
} ) . Select ( p = > p . Channel ) ;
2021-12-05 18:09:01 +01:00
2024-08-15 20:26:57 +02:00
var wrappedMessage = Loc . GetString ( "chat-manager-send-admin-announcement-wrap-message" ,
( "adminChannelName" , Loc . GetString ( "chat-manager-admin-channel-name" ) ) , ( "message" , FormattedMessage . EscapeText ( message ) ) ) ;
2021-09-29 19:02:27 +10:00
2024-08-15 20:26:57 +02:00
ChatMessageToMany ( ChatChannel . Admin , message , wrappedMessage , default , false , true , clients ) ;
_adminLogger . Add ( LogType . Chat , LogImpact . Low , $"Admin announcement: {message}" ) ;
}
2019-04-13 09:45:09 +02:00
2024-08-15 20:26:57 +02:00
public void SendAdminAnnouncementMessage ( ICommonSession player , string message , bool suppressLog = true )
{
var wrappedMessage = Loc . GetString ( "chat-manager-send-admin-announcement-wrap-message" ,
( "adminChannelName" , Loc . GetString ( "chat-manager-admin-channel-name" ) ) ,
( "message" , FormattedMessage . EscapeText ( message ) ) ) ;
ChatMessageToOne ( ChatChannel . Admin , message , wrappedMessage , default , false , player . Channel ) ;
}
2024-05-26 08:18:05 +12:00
2024-08-15 20:26:57 +02:00
public void SendAdminAlert ( string message )
{
var clients = _adminManager . ActiveAdmins . Select ( p = > p . Channel ) ;
2023-03-23 10:10:49 -05:00
2024-08-15 20:26:57 +02:00
var wrappedMessage = Loc . GetString ( "chat-manager-send-admin-announcement-wrap-message" ,
( "adminChannelName" , Loc . GetString ( "chat-manager-admin-channel-name" ) ) , ( "message" , FormattedMessage . EscapeText ( message ) ) ) ;
2023-03-23 10:10:49 -05:00
2024-08-15 20:26:57 +02:00
ChatMessageToMany ( ChatChannel . AdminAlert , message , wrappedMessage , default , false , true , clients ) ;
}
2023-03-23 10:10:49 -05:00
2024-08-15 20:26:57 +02:00
public void SendAdminAlert ( EntityUid player , string message )
{
var mindSystem = _entityManager . System < SharedMindSystem > ( ) ;
if ( ! mindSystem . TryGetMind ( player , out var mindId , out var mind ) )
2023-03-23 10:10:49 -05:00
{
2024-08-15 20:26:57 +02:00
SendAdminAlert ( message ) ;
return ;
}
2023-03-23 10:10:49 -05:00
2024-08-15 20:26:57 +02:00
var adminSystem = _entityManager . System < AdminSystem > ( ) ;
var antag = mind . UserId ! = null & & ( adminSystem . GetCachedPlayerInfo ( mind . UserId . Value ) ? . Antag ? ? false ) ;
2023-03-23 10:10:49 -05:00
2024-08-15 20:26:57 +02:00
SendAdminAlert ( $"{mind.Session?.Name}{(antag ? " ( ANTAG ) " : " ")} {message}" ) ;
}
2023-03-23 10:10:49 -05:00
2024-08-15 20:26:57 +02:00
public void SendHookOOC ( string sender , string message )
{
if ( ! _oocEnabled & & _configurationManager . GetCVar ( CCVars . DisablingOOCDisablesRelay ) )
2022-01-11 06:48:18 -08:00
{
2024-08-15 20:26:57 +02:00
return ;
2019-04-13 09:45:09 +02:00
}
2024-08-15 20:26:57 +02:00
var wrappedMessage = Loc . GetString ( "chat-manager-send-hook-ooc-wrap-message" , ( "senderName" , sender ) , ( "message" , FormattedMessage . EscapeText ( message ) ) ) ;
ChatMessageToAll ( ChatChannel . OOC , message , wrappedMessage , source : EntityUid . Invalid , hideChat : false , recordReplay : true ) ;
_adminLogger . Add ( LogType . Chat , LogImpact . Low , $"Hook OOC from {sender}: {message}" ) ;
}
2019-04-13 09:45:09 +02:00
2024-08-15 20:26:57 +02:00
#endregion
2019-10-30 21:49:07 +01:00
2024-08-15 20:26:57 +02:00
#region Public OOC Chat API
2022-01-11 06:48:18 -08:00
2024-08-15 20:26:57 +02:00
/// <summary>
/// Called for a player to attempt sending an OOC, out-of-game. message.
/// </summary>
/// <param name="player">The player sending the message.</param>
/// <param name="message">The message.</param>
/// <param name="type">The type of message.</param>
public void TrySendOOCMessage ( ICommonSession player , string message , OOCChatType type )
{
if ( HandleRateLimit ( player ) ! = RateLimitStatus . Allowed )
return ;
2023-11-27 04:08:30 +01:00
2024-08-15 20:26:57 +02:00
// Check if message exceeds the character limit
if ( message . Length > MaxMessageLength )
{
DispatchServerMessage ( player , Loc . GetString ( "chat-manager-max-message-length-exceeded-message" , ( "limit" , MaxMessageLength ) ) ) ;
return ;
}
2022-01-11 16:29:55 +03:00
2024-08-15 20:26:57 +02:00
switch ( type )
{
case OOCChatType . OOC :
SendOOC ( player , message ) ;
break ;
case OOCChatType . Admin :
SendAdminChat ( player , message ) ;
break ;
2022-03-30 22:21:58 -07:00
}
2024-08-15 20:26:57 +02:00
}
2022-01-27 00:18:56 +11:00
2024-08-15 20:26:57 +02:00
#endregion
2022-01-19 13:35:31 +11:00
2024-08-15 20:26:57 +02:00
#region Private API
2022-01-11 06:48:18 -08:00
2024-08-15 20:26:57 +02:00
private void SendOOC ( ICommonSession player , string message )
{
if ( _adminManager . IsAdmin ( player ) )
2019-04-13 09:45:09 +02:00
{
2024-08-15 20:26:57 +02:00
if ( ! _adminOocEnabled )
2021-02-16 20:14:32 +01:00
{
return ;
}
2019-04-17 23:31:43 +02:00
}
2024-08-15 20:26:57 +02:00
else if ( ! _oocEnabled )
2021-01-03 12:13:31 -03:00
{
2024-08-15 20:26:57 +02:00
return ;
}
2021-01-03 12:13:31 -03:00
2024-08-15 20:26:57 +02:00
Color ? colorOverride = null ;
var wrappedMessage = Loc . GetString ( "chat-manager-send-ooc-wrap-message" , ( "playerName" , player . Name ) , ( "message" , FormattedMessage . EscapeText ( message ) ) ) ;
if ( _adminManager . HasAdminFlag ( player , AdminFlags . Admin ) )
{
var prefs = _preferencesManager . GetPreferences ( player . UserId ) ;
colorOverride = prefs . AdminOOCColor ;
}
if ( _netConfigManager . GetClientCVar ( player . Channel , CCVars . ShowOocPatronColor ) & & player . Channel . UserData . PatronTier is { } patron & & PatronOocColors . TryGetValue ( patron , out var patronColor ) )
{
wrappedMessage = Loc . GetString ( "chat-manager-send-ooc-patron-wrap-message" , ( "patronColor" , patronColor ) , ( "playerName" , player . Name ) , ( "message" , FormattedMessage . EscapeText ( message ) ) ) ;
}
2023-10-14 02:02:56 -07:00
2024-08-15 20:26:57 +02:00
//TODO: player.Name color, this will need to change the structure of the MsgChatMessage
ChatMessageToAll ( ChatChannel . OOC , message , wrappedMessage , EntityUid . Invalid , hideChat : false , recordReplay : true , colorOverride : colorOverride , author : player . UserId ) ;
_mommiLink . SendOOCMessage ( player . Name , message . Replace ( "@" , "\\@" ) . Replace ( "<" , "\\<" ) . Replace ( "/" , "\\/" ) ) ; // @ and < are both problematic for discord due to pinging. / is sanitized solely to kneecap links to murder embeds via blunt force
_adminLogger . Add ( LogType . Chat , LogImpact . Low , $"OOC from {player:Player}: {message}" ) ;
}
2022-01-19 13:35:31 +11:00
2024-08-15 20:26:57 +02:00
private void SendAdminChat ( ICommonSession player , string message )
{
if ( ! _adminManager . IsAdmin ( player ) )
{
_adminLogger . Add ( LogType . Chat , LogImpact . Extreme , $"{player:Player} attempted to send admin message but was not admin" ) ;
return ;
2020-07-08 05:18:16 -05:00
}
2024-08-15 20:26:57 +02:00
var clients = _adminManager . ActiveAdmins . Select ( p = > p . Channel ) ;
var wrappedMessage = Loc . GetString ( "chat-manager-send-admin-chat-wrap-message" ,
( "adminChannelName" , Loc . GetString ( "chat-manager-admin-channel-name" ) ) ,
( "playerName" , player . Name ) , ( "message" , FormattedMessage . EscapeText ( message ) ) ) ;
2020-11-01 23:56:35 +01:00
2024-08-15 20:26:57 +02:00
foreach ( var client in clients )
2022-03-30 22:21:58 -07:00
{
2024-08-15 20:26:57 +02:00
var isSource = client ! = player . Channel ;
ChatMessageToOne ( ChatChannel . AdminChat ,
message ,
wrappedMessage ,
default ,
false ,
client ,
audioPath : isSource ? _netConfigManager . GetClientCVar ( client , CCVars . AdminChatSoundPath ) : default ,
audioVolume : isSource ? _netConfigManager . GetClientCVar ( client , CCVars . AdminChatSoundVolume ) : default ,
author : player . UserId ) ;
}
2023-11-05 18:19:59 -08:00
2024-08-15 20:26:57 +02:00
_adminLogger . Add ( LogType . Chat , $"Admin chat from {player:Player}: {message}" ) ;
}
2022-11-23 00:52:19 +13:00
2024-08-15 20:26:57 +02:00
#endregion
2023-06-05 16:33:49 +12:00
2024-08-15 20:26:57 +02:00
#region Utility
public void ChatMessageToOne ( ChatChannel channel , string message , string wrappedMessage , EntityUid source , bool hideChat , INetChannel client , Color ? colorOverride = null , bool recordReplay = false , string? audioPath = null , float audioVolume = 0 , NetUserId ? author = null )
{
var user = author = = null ? null : EnsurePlayer ( author ) ;
var netSource = _entityManager . GetNetEntity ( source ) ;
user ? . AddEntity ( netSource ) ;
2021-02-28 18:51:30 +01:00
2024-08-15 20:26:57 +02:00
var msg = new ChatMessage ( channel , message , wrappedMessage , netSource , user ? . Key , hideChat , colorOverride , audioPath , audioVolume ) ;
_netManager . ServerSendMessage ( new MsgChatMessage ( ) { Message = msg } , client ) ;
2022-11-23 00:52:19 +13:00
2024-08-15 20:26:57 +02:00
if ( ! recordReplay )
return ;
if ( ( channel & ChatChannel . AdminRelated ) = = 0 | |
_configurationManager . GetCVar ( CCVars . ReplayRecordAdminChat ) )
2022-01-11 06:48:18 -08:00
{
2024-08-15 20:26:57 +02:00
_replay . RecordServerMessage ( msg ) ;
}
}
2023-11-05 18:19:59 -08:00
2024-08-15 20:26:57 +02:00
public void ChatMessageToMany ( ChatChannel channel , string message , string wrappedMessage , EntityUid source , bool hideChat , bool recordReplay , IEnumerable < INetChannel > clients , Color ? colorOverride = null , string? audioPath = null , float audioVolume = 0 , NetUserId ? author = null )
= > ChatMessageToMany ( channel , message , wrappedMessage , source , hideChat , recordReplay , clients . ToList ( ) , colorOverride , audioPath , audioVolume , author ) ;
2022-11-23 00:52:19 +13:00
2024-08-15 20:26:57 +02:00
public void ChatMessageToMany ( ChatChannel channel , string message , string wrappedMessage , EntityUid source , bool hideChat , bool recordReplay , List < INetChannel > clients , Color ? colorOverride = null , string? audioPath = null , float audioVolume = 0 , NetUserId ? author = null )
{
var user = author = = null ? null : EnsurePlayer ( author ) ;
var netSource = _entityManager . GetNetEntity ( source ) ;
user ? . AddEntity ( netSource ) ;
2023-06-05 16:33:49 +12:00
2024-08-15 20:26:57 +02:00
var msg = new ChatMessage ( channel , message , wrappedMessage , netSource , user ? . Key , hideChat , colorOverride , audioPath , audioVolume ) ;
_netManager . ServerSendToMany ( new MsgChatMessage ( ) { Message = msg } , clients ) ;
if ( ! recordReplay )
return ;
2022-01-11 06:48:18 -08:00
2024-08-15 20:26:57 +02:00
if ( ( channel & ChatChannel . AdminRelated ) = = 0 | |
_configurationManager . GetCVar ( CCVars . ReplayRecordAdminChat ) )
2022-06-03 21:37:35 +10:00
{
2024-08-15 20:26:57 +02:00
_replay . RecordServerMessage ( msg ) ;
}
}
2022-06-03 21:37:35 +10:00
2024-08-15 20:26:57 +02:00
public void ChatMessageToManyFiltered ( Filter filter , ChatChannel channel , string message , string wrappedMessage , EntityUid source ,
bool hideChat , bool recordReplay , Color ? colorOverride = null , string? audioPath = null , float audioVolume = 0 )
{
if ( ! recordReplay & & ! filter . Recipients . Any ( ) )
return ;
2022-06-03 21:37:35 +10:00
2024-08-15 20:26:57 +02:00
var clients = new List < INetChannel > ( ) ;
foreach ( var recipient in filter . Recipients )
{
clients . Add ( recipient . Channel ) ;
2022-06-03 21:37:35 +10:00
}
2024-08-15 20:26:57 +02:00
ChatMessageToMany ( channel , message , wrappedMessage , source , hideChat , recordReplay , clients , colorOverride , audioPath , audioVolume ) ;
}
2023-11-05 18:19:59 -08:00
2024-08-15 20:26:57 +02:00
public void ChatMessageToAll ( ChatChannel channel , string message , string wrappedMessage , EntityUid source , bool hideChat , bool recordReplay , Color ? colorOverride = null , string? audioPath = null , float audioVolume = 0 , NetUserId ? author = null )
{
var user = author = = null ? null : EnsurePlayer ( author ) ;
var netSource = _entityManager . GetNetEntity ( source ) ;
user ? . AddEntity ( netSource ) ;
2022-11-23 00:52:19 +13:00
2024-08-15 20:26:57 +02:00
var msg = new ChatMessage ( channel , message , wrappedMessage , netSource , user ? . Key , hideChat , colorOverride , audioPath , audioVolume ) ;
_netManager . ServerSendToAll ( new MsgChatMessage ( ) { Message = msg } ) ;
2023-06-05 16:33:49 +12:00
2024-08-15 20:26:57 +02:00
if ( ! recordReplay )
return ;
2020-08-17 14:45:02 +02:00
2024-08-15 20:26:57 +02:00
if ( ( channel & ChatChannel . AdminRelated ) = = 0 | |
_configurationManager . GetCVar ( CCVars . ReplayRecordAdminChat ) )
2020-08-25 17:09:39 +02:00
{
2024-08-15 20:26:57 +02:00
_replay . RecordServerMessage ( msg ) ;
}
}
2022-01-11 06:48:18 -08:00
2024-08-15 20:26:57 +02:00
public bool MessageCharacterLimit ( ICommonSession ? player , string message )
{
var isOverLength = false ;
2022-03-30 22:21:58 -07:00
2024-08-15 20:26:57 +02:00
// Non-players don't need to be checked.
if ( player = = null )
return false ;
2022-01-11 06:48:18 -08:00
2024-08-15 20:26:57 +02:00
// Check if message exceeds the character limit if the sender is a player
if ( message . Length > MaxMessageLength )
{
var feedback = Loc . GetString ( "chat-manager-max-message-length-exceeded-message" , ( "limit" , MaxMessageLength ) ) ;
2022-01-11 06:48:18 -08:00
2024-08-15 20:26:57 +02:00
DispatchServerMessage ( player , feedback ) ;
2022-01-11 06:48:18 -08:00
2024-08-15 20:26:57 +02:00
isOverLength = true ;
2022-01-11 06:48:18 -08:00
}
2024-08-15 20:26:57 +02:00
return isOverLength ;
2022-03-30 22:21:58 -07:00
}
2022-01-11 06:48:18 -08:00
2024-08-15 20:26:57 +02:00
#endregion
}
public enum OOCChatType : byte
{
OOC ,
Admin
2019-04-13 09:45:09 +02:00
}