From a67b95e5ddff26d30100850ef8f47071a1153212 Mon Sep 17 00:00:00 2001 From: Redox <69946827+wrefgtzweve@users.noreply.github.com> Date: Sun, 3 May 2026 14:48:54 +0200 Subject: [PATCH 1/2] Add loadtime to spawnin message --- lua/custom_chat/client/join_leave.lua | 19 +++++++++++----- lua/custom_chat/server/player_spawn.lua | 22 +++++++++++++++++++ .../localization/en/custom_chat.properties | 5 +++-- .../localization/pt-br/custom_chat.properties | 5 +++-- .../localization/ru/custom_chat.properties | 5 +++-- .../localization/tr/custom_chat.properties | 5 +++-- 6 files changed, 48 insertions(+), 13 deletions(-) diff --git a/lua/custom_chat/client/join_leave.lua b/lua/custom_chat/client/join_leave.lua index b6e6728..7aa7c26 100644 --- a/lua/custom_chat/client/join_leave.lua +++ b/lua/custom_chat/client/join_leave.lua @@ -99,7 +99,7 @@ hook.Add( "player_disconnect", "CustomChat.ShowDisconnectMessages", function( da chat.AddText( unpack( parts ) ) end, HOOK_LOW ) -local function OnPlayerActivated( ply, steamId, name, color, absenceLength ) +local function OnPlayerActivated( ply, steamId, name, color, absenceLength, timeToSpawn ) if ply:IsBot() and not JoinLeave.botConnectDisconnect then return end -- Only use a player block if Custom Chat is enabled @@ -115,6 +115,8 @@ local function OnPlayerActivated( ply, steamId, name, color, absenceLength ) } end + local niceTimeToSpawn = CustomChat.NiceTime( math.Round( timeToSpawn ) ) + -- Show a message if this player is a friend if CustomChat.GetConVarInt( "enable_friend_messages", 0 ) > 0 and @@ -124,7 +126,8 @@ local function OnPlayerActivated( ply, steamId, name, color, absenceLength ) chat.AddText( Color( 255, 255, 255 ), ":small_blue_diamond: " .. CustomChat.GetLanguageText( "friend_spawned1" ) .. " ", color, name, - Color( 255, 255, 255 ), " " .. CustomChat.GetLanguageText( "friend_spawned2" ) + Color( 255, 255, 255 ), " " .. CustomChat.GetLanguageText( "friend_spawned2" ), + Color( 150, 150, 150 ), " (" .. niceTimeToSpawn .. ")" ) end @@ -135,6 +138,8 @@ local function OnPlayerActivated( ply, steamId, name, color, absenceLength ) if absenceLength < 1 then chat.AddText( color, name, + Color( 150, 150, 150 ), " " .. CustomChat.GetLanguageText( "took" ), + Color( 200, 200, 200 ), " " .. niceTimeToSpawn, Color( 150, 150, 150 ), " " .. CustomChat.GetLanguageText( "first_seen" ) ) return @@ -148,6 +153,8 @@ local function OnPlayerActivated( ply, steamId, name, color, absenceLength ) chat.AddText( color, name, + Color( 150, 150, 150 ), " " .. CustomChat.GetLanguageText( "took" ), + Color( 200, 200, 200 ), " " .. niceTimeToSpawn, Color( 150, 150, 150 ), " " .. CustomChat.GetLanguageText( "last_seen1" ), Color( 200, 200, 200 ), " " .. lastSeenTime, Color( 150, 150, 150 ), " " .. CustomChat.GetLanguageText( "last_seen2" ) @@ -163,7 +170,7 @@ hook.Add( "NetworkEntityCreated", "CustomChat.HandlePlayerInitialSpawn", functio if not data then return end CustomChat.PlayerInitialSpawnWaiting[steamId] = nil - OnPlayerActivated( ent, steamId, data.name, data.color, data.absenceLength ) + OnPlayerActivated( ent, steamId, data.name, data.color, data.absenceLength, data.timeToSpawn ) end ) net.Receive( "customchat.player_spawned", function() @@ -171,16 +178,18 @@ net.Receive( "customchat.player_spawned", function() local name = net.ReadString() local color = net.ReadColor( false ) local absenceLength = net.ReadFloat() + local timeToSpawn = net.ReadFloat() local ply = player.GetBySteamID( steamId ) if IsValid( ply ) then - OnPlayerActivated( ply, steamId, name, color, absenceLength ) + OnPlayerActivated( ply, steamId, name, color, absenceLength, timeToSpawn ) return end CustomChat.PlayerInitialSpawnWaiting[steamId] = { name = name, color = color, - absenceLength = absenceLength + absenceLength = absenceLength, + timeToSpawn = timeToSpawn } end ) diff --git a/lua/custom_chat/server/player_spawn.lua b/lua/custom_chat/server/player_spawn.lua index 7aa6387..bffc6d9 100644 --- a/lua/custom_chat/server/player_spawn.lua +++ b/lua/custom_chat/server/player_spawn.lua @@ -1,5 +1,18 @@ util.AddNetworkString( "customchat.player_spawned" ) +local connectingSteamIDs = {} +gameevent.Listen( "player_connect" ) +hook.Add( "player_connect", "CustomChat.TrackConnectingPlayers", function( data ) + local steamId = data.networkid + connectingSteamIDs[steamId] = SysTime() +end ) + +gameevent.Listen( "player_disconnect" ) +hook.Add( "player_disconnect", "CustomChat.TrackDisconnectingPlayers", function( data ) + local steamId = data.networkid + connectingSteamIDs[steamId] = nil +end ) + hook.Add( "PlayerInitialSpawn", "CustomChat.BroadcastInitialSpawn", function( ply ) -- Give some time for other addons to assign the team timer.Simple( 3, function() @@ -18,12 +31,21 @@ hook.Add( "PlayerInitialSpawn", "CustomChat.BroadcastInitialSpawn", function( pl CustomChat:SetLastSeen( steamId, time ) + local timeToSpawn = 0 + if connectingSteamIDs[steamId] then + local connectTime = connectingSteamIDs[steamId] + timeToSpawn = SysTime() - connectTime + end + net.Start( "customchat.player_spawned", false ) net.WriteString( steamId ) net.WriteString( ply:Nick() ) net.WriteColor( color, false ) net.WriteFloat( absenceLength ) + net.WriteFloat( timeToSpawn ) net.Broadcast() + + hook.Run( "CustomChatPlayerInitialSpawn", ply, steamId, color, absenceLength, timeToSpawn ) end ) end, HOOK_LOW ) diff --git a/resource/localization/en/custom_chat.properties b/resource/localization/en/custom_chat.properties index 85f8f84..8c88cec 100644 --- a/resource/localization/en/custom_chat.properties +++ b/resource/localization/en/custom_chat.properties @@ -146,8 +146,9 @@ custom_chat.server_theme.remove=Remove custom_chat.server_theme.tip=This action will force all players (including those who join later) to use this theme. Are you sure? custom_chat.friend_spawned1=Your friend custom_chat.friend_spawned2=has spawned in. -custom_chat.last_seen1=spawned in, last played -custom_chat.first_seen=joined for the first time. +custom_chat.took=took +custom_chat.last_seen1=to load, last played +custom_chat.first_seen=to load, joined for the first time. custom_chat.time.years=years custom_chat.time.months=months custom_chat.time.weeks=weeks diff --git a/resource/localization/pt-br/custom_chat.properties b/resource/localization/pt-br/custom_chat.properties index 2f1e7ee..25427ff 100644 --- a/resource/localization/pt-br/custom_chat.properties +++ b/resource/localization/pt-br/custom_chat.properties @@ -145,8 +145,9 @@ custom_chat.server_theme.remove=Remover custom_chat.server_theme.tip=Esta ação forçará todos os jogadores (incluindo aqueles que entrarem depois) a usar este tema. Tem certeza? custom_chat.friend_spawned1=Seu amigo custom_chat.friend_spawned2=acabou de aparecer aqui. -custom_chat.last_seen1=apareceu, jogou pela última vez há -custom_chat.first_seen=entrou pela primeira vez. +custom_chat.took=levou +custom_chat.last_seen1=para carregar, jogou pela última vez há +custom_chat.first_seen=para carregar, entrou pela primeira vez. custom_chat.time.years=anos custom_chat.time.months=meses custom_chat.time.weeks=semanas diff --git a/resource/localization/ru/custom_chat.properties b/resource/localization/ru/custom_chat.properties index 70c9331..8440d18 100644 --- a/resource/localization/ru/custom_chat.properties +++ b/resource/localization/ru/custom_chat.properties @@ -146,8 +146,9 @@ custom_chat.server_theme.remove=Удалить custom_chat.server_theme.tip=Это действие заставит всех игроков (включая тех, кто зайдёт позже) использовать эту тему. Вы уверены? custom_chat.friend_spawned1=Ваш друг custom_chat.friend_spawned2=загрузился. -custom_chat.last_seen1=загрузился, заходил последний раз -custom_chat.first_seen=зашёл в первый раз. +custom_chat.took=загружался +custom_chat.last_seen1=, заходил последний раз +custom_chat.first_seen=, зашёл в первый раз. custom_chat.time.years=г. custom_chat.time.months=мес. custom_chat.time.weeks=нед. diff --git a/resource/localization/tr/custom_chat.properties b/resource/localization/tr/custom_chat.properties index 639410a..693309a 100644 --- a/resource/localization/tr/custom_chat.properties +++ b/resource/localization/tr/custom_chat.properties @@ -146,8 +146,9 @@ custom_chat.server_theme.remove=Kaldır custom_chat.server_theme.tip=Bu işlem, tüm oyuncuları (daha sonra katılanlar dahil) bu temayı kullanmaya zorlayacaktır. Emin misiniz? custom_chat.friend_spawned1=Arkadaşın custom_chat.friend_spawned2=burada. -custom_chat.last_seen1=doğdu, en son -custom_chat.first_seen=ilk kez katıldı. +custom_chat.took=yüklendi +custom_chat.last_seen1=sürede, en son +custom_chat.first_seen=sürede, ilk kez katıldı. custom_chat.time.years=yıl custom_chat.time.months=aylar custom_chat.time.weeks=hafta From 29a14ac04dd37e4109bd97b5ebbb9b58cea1f970 Mon Sep 17 00:00:00 2001 From: Redox <69946827+wrefgtzweve@users.noreply.github.com> Date: Sun, 3 May 2026 14:50:53 +0200 Subject: [PATCH 2/2] Add readme doc for CustomChatPlayerInitialSpawn --- README.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/README.md b/README.md index 43beb97..c3d3384 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ A simple and customizable chat box that can format text, display images and emoj - [OverrideCustomChatPlayerColor](#overridecustomchatplayercolor) - [CustomChatBlockInput](#customchatblockinput) - [CustomChatHideJoinMessage](#customchathidejoinmessage) + - [CustomChatPlayerInitialSpawn](#customchatplayerinitialspawn) - [Contributing](#contributing) ## Features @@ -77,6 +78,7 @@ By default, the chat box will only load pictures from trusted websites. You can - [OverrideCustomChatPlayerColor](#overridecustomchatplayercolor) - [CustomChatBlockInput](#customchatblockinput) - [CustomChatHideJoinMessage](#customchathidejoinmessage) +- [CustomChatPlayerInitialSpawn](#customchatplayerinitialspawn) - [PostPlayerSay](#postplayersay) ### CanEmbedCustomChat @@ -176,6 +178,30 @@ You can return `true` on this hook to block the "open chat" button(s). It runs o You can return `true` on this hook to dynamically prevent join/leave messages from showing up. It runs on the **client side**, and gives a `data` table as a argument, that contains the same keys given by the [player_connect_client](https://wiki.facepunch.com/gmod/gameevent/player_connect_client#members) hook. +### CustomChatPlayerInitialSpawn + +Runs on the **server side** after a player's initial spawn data has been gathered and broadcast to clients. Useful for reacting to join events with full absence/load-time context. + +Arguments: +- `ply` — the player entity +- `steamId` — the player's SteamID string +- `color` — the team `Color` assigned to the player at spawn time +- `absenceLength` — seconds since the player was last seen on this server (`0` for first-timers) +- `timeToSpawn` — seconds the player took to load into the server + +```lua +hook.Add( "CustomChatPlayerInitialSpawn", "example", function( ply, steamId, color, absenceLength, timeToSpawn ) + -- Example: print load time and absence to server console + print( ply:Nick() .. " took " .. math.Round( timeToSpawn ) .. "s to load" ) + + if absenceLength > 0 then + print( ply:Nick() .. " was last seen " .. math.Round( absenceLength ) .. "s ago" ) + else + print( ply:Nick() .. " joined for the first time" ) + end +end ) +``` + ### PostPlayerSay For getting the final contents of a chat message. Doesn't get ran if a message is blocked/edited away by PlayerSay