From ea9a2ed9b9698d891769fa8598b8262aad97ed77 Mon Sep 17 00:00:00 2001 From: Tom Barham Date: Tue, 22 Feb 2022 08:33:50 +1000 Subject: Advanced chat: custom messages and client hooks (#217) Co-authored-by: EmmaM <27428383+emma-miler@users.noreply.github.com> --- Northstar.Client/mod.json | 11 ++ .../northstar_client_localisation_english.txt | 6 +- .../vscripts/_custom_codecallbacks_client.gnut | 126 +++++++++++++++++++++ Northstar.Client/mod/scripts/vscripts/chat.gnut | 18 +++ Northstar.CustomServers/mod.json | 7 ++ .../mod/scripts/vscripts/_chat.gnut | 51 +++++++++ .../scripts/vscripts/_custom_codecallbacks.gnut | 38 +++++-- 7 files changed, 244 insertions(+), 13 deletions(-) create mode 100644 Northstar.Client/mod/scripts/vscripts/_custom_codecallbacks_client.gnut create mode 100644 Northstar.Client/mod/scripts/vscripts/chat.gnut create mode 100644 Northstar.CustomServers/mod/scripts/vscripts/_chat.gnut diff --git a/Northstar.Client/mod.json b/Northstar.Client/mod.json index 1a2b5c01..ad850752 100644 --- a/Northstar.Client/mod.json +++ b/Northstar.Client/mod.json @@ -34,6 +34,17 @@ } ], "Scripts": [ + { + "Path": "_custom_codecallbacks_client.gnut", + "RunOn": "CLIENT", + "ClientCallback": { + "Before": "NSSetupChathooksClient" + } + }, + { + "Path": "chat.gnut", + "RunOn": "CLIENT" + }, { "Path": "ui/menu_ns_modmenu.nut", "RunOn": "UI", diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_english.txt b/Northstar.Client/mod/resource/northstar_client_localisation_english.txt index db83c6b7..fdda8bd8 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_english.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_english.txt @@ -299,8 +299,12 @@ Press Yes if you agree to this. This choice can be changed in the mods menu at a "SHOW_ALL" "All" "SHOW_ONLY_ENABLED" "Only Enabled" "SHOW_ONLY_DISABLED" "Only Disabled" - + // Maps menu "HIDE_LOCKED" "Hide locked" + + // In-game chat + "HUD_CHAT_WHISPER_PREFIX" "[WHISPER]" + "HUD_CHAT_SERVER_PREFIX" "[SERVER]" } } diff --git a/Northstar.Client/mod/scripts/vscripts/_custom_codecallbacks_client.gnut b/Northstar.Client/mod/scripts/vscripts/_custom_codecallbacks_client.gnut new file mode 100644 index 00000000..9241fcdf --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/_custom_codecallbacks_client.gnut @@ -0,0 +1,126 @@ +untyped + +global function AddCallback_OnReceivedSayTextMessage +global function NSSetupChathooksClient + +global struct ClClient_MessageStruct { + string message + entity player + string playerName + bool isTeam + bool isDead + bool isWhisper + bool shouldBlock +} + +struct { + array< ClClient_MessageStruct functionref( ClClient_MessageStruct ) > OnReceivedSayTextMessageCallbacks +} NsCustomCallbacksClient + +void function OnReceivedMessage(ClClient_MessageStruct localMessage) { + if (localMessage.player != null) + { + foreach (callbackFunc in NsCustomCallbacksClient.OnReceivedSayTextMessageCallbacks) + { + ClClient_MessageStruct returnStruct = callbackFunc(localMessage) + localMessage.message = returnStruct.message + localMessage.playerName = returnStruct.playerName + localMessage.isTeam = returnStruct.isTeam + localMessage.isDead = returnStruct.isDead + localMessage.isWhisper = returnStruct.isWhisper + localMessage.shouldBlock = localMessage.shouldBlock || returnStruct.shouldBlock + } + } + + if (localMessage.shouldBlock) + { + return + } + + NSChatWriteRaw(1, "\n") + + if (localMessage.player == null) NSChatWrite(1, "\x1b[95m") + else + { + bool isFriendly = localMessage.player.GetTeam() == GetLocalClientPlayer().GetTeam() + + if (isFriendly) NSChatWrite(1, "\x1b[111m") + else NSChatWrite(1, "\x1b[112m") + } + + if (localMessage.isWhisper) NSChatWriteRaw(1, Localize("#HUD_CHAT_WHISPER_PREFIX")) + if (localMessage.isDead) NSChatWriteRaw(1, Localize("#HUD_CHAT_DEAD_PREFIX")) + if (localMessage.isTeam) NSChatWriteRaw(1, Localize("#HUD_CHAT_TEAM_PREFIX")) + + if (localMessage.player == null) + { + NSChatWriteRaw(1, Localize("#HUD_CHAT_SERVER_PREFIX") + " ") + } + else { + NSChatWriteRaw(1, localMessage.playerName) + NSChatWriteRaw(1, ": ") + } + + NSChatWrite(1, "\x1b[0m") + + NSChatWrite(1, localMessage.message) +} + +void function CHudChat_ProcessMessageStartThread(int playerIndex, string message, bool isTeam, bool isDead, int messageType) +{ + thread CHudChat_OnReceivedSayTextMessageCallback(playerIndex, message, isTeam, isDead, messageType) +} + +void function CHudChat_OnReceivedSayTextMessageCallback(int fromPlayerIndex, string message, bool isTeam, bool isDead, int messageType) +{ + entity fromPlayer = null + string fromPlayerName = "" + + if (fromPlayerIndex >= 0 && fromPlayerIndex < GetPlayerArray().len()) + { + fromPlayer = GetEntByIndex(fromPlayerIndex + 1) + if (fromPlayer == null) { + print("Ignored chat message from invalid player index " + fromPlayerIndex + ": " + message) + return + } + + fromPlayerName = fromPlayer.GetPlayerName() + } + + if (messageType == 0 || messageType == 1) + { + ClClient_MessageStruct localMessage + localMessage.message = message + localMessage.player = fromPlayer + localMessage.playerName = fromPlayerName + localMessage.isTeam = isTeam + localMessage.isDead = isDead + localMessage.isWhisper = false + localMessage.shouldBlock = false + OnReceivedMessage(localMessage) + return + } + + if (messageType == 2) + { + ClClient_MessageStruct localMessage + localMessage.message = message + localMessage.player = fromPlayer + localMessage.playerName = fromPlayerName + localMessage.isTeam = isTeam + localMessage.isDead = isDead + localMessage.isWhisper = true + localMessage.shouldBlock = false + OnReceivedMessage(localMessage) + return + } +} + +void function AddCallback_OnReceivedSayTextMessage( ClClient_MessageStruct functionref (ClClient_MessageStruct) callbackFunc ) +{ + NsCustomCallbacksClient.OnReceivedSayTextMessageCallbacks.append(callbackFunc) +} + +void function NSSetupChathooksClient() { + getroottable().rawset("CHudChat_ProcessMessageStartThread", CHudChat_ProcessMessageStartThread) +} \ No newline at end of file diff --git a/Northstar.Client/mod/scripts/vscripts/chat.gnut b/Northstar.Client/mod/scripts/vscripts/chat.gnut new file mode 100644 index 00000000..ce26434c --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/chat.gnut @@ -0,0 +1,18 @@ +untyped +globalize_all_functions + +void function Chat_NetworkWriteLine(string text) { + NSChatWriteLine(0, text) +} + +void function Chat_GameWriteLine(string text) { + NSChatWriteLine(1, text) +} + +void function Chat_NetworkWrite(string text) { + NSChatWrite(0, text) +} + +void function Chat_GameWrite(string text) { + NSChatWrite(1, text) +} diff --git a/Northstar.CustomServers/mod.json b/Northstar.CustomServers/mod.json index e7c00daa..09d8fc2d 100644 --- a/Northstar.CustomServers/mod.json +++ b/Northstar.CustomServers/mod.json @@ -49,6 +49,13 @@ "Scripts": [ { "Path": "_custom_codecallbacks.gnut", + "RunOn": "SERVER", + "ServerCallback": { + "Before": "NSSetupChathooksServer" + } + }, + { + "Path": "_chat.gnut", "RunOn": "SERVER" }, { diff --git a/Northstar.CustomServers/mod/scripts/vscripts/_chat.gnut b/Northstar.CustomServers/mod/scripts/vscripts/_chat.gnut new file mode 100644 index 00000000..97ed959c --- /dev/null +++ b/Northstar.CustomServers/mod/scripts/vscripts/_chat.gnut @@ -0,0 +1,51 @@ +untyped +globalize_all_functions + +enum eChatMessageType +{ + CHAT = 1, + WHISPER = 2 +} + +// Displays a chat message as if the player sent it. +void function Chat_Impersonate(entity player, string text, bool isTeamChat) { + NSSendMessage(player.GetPlayerIndex(), text, isTeamChat) +} + +// Sends a whisper message from one player that is only shown to another. Will be shown as a whisper if whisper is set. +void function Chat_PrivateMessage(entity fromPlayer, entity toPlayer, string text, bool whisper) { + NSBroadcastMessage( + fromPlayer.GetPlayerIndex(), + toPlayer.GetPlayerIndex(), + text, + false, + false, + whisper ? eChatMessageType.WHISPER : eChatMessageType.CHAT + ) +} + +// Broadcasts a message from the server to all players. +void function Chat_ServerBroadcast(string text) +{ + NSBroadcastMessage( + -1, + -1, + text, + false, + false, + eChatMessageType.CHAT + ) +} + +// Sends a message from the server to one player. Will be shown as a whisper if whisper is set. +void function Chat_ServerPrivateMessage(entity toPlayer, string text, bool whisper) +{ + NSBroadcastMessage( + -1, + toPlayer.GetPlayerIndex(), + text, + false, + false, + whisper ? eChatMessageType.WHISPER : eChatMessageType.CHAT + ) +} diff --git a/Northstar.CustomServers/mod/scripts/vscripts/_custom_codecallbacks.gnut b/Northstar.CustomServers/mod/scripts/vscripts/_custom_codecallbacks.gnut index 7f102f6e..9e46f99a 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/_custom_codecallbacks.gnut +++ b/Northstar.CustomServers/mod/scripts/vscripts/_custom_codecallbacks.gnut @@ -1,11 +1,12 @@ untyped -globalize_all_functions +global function AddCallback_OnReceivedSayTextMessage +global function NSSetupChathooksServer global struct ClServer_MessageStruct { string message entity player - int channelId + bool isTeam bool shouldBlock } @@ -13,32 +14,45 @@ struct { array< ClServer_MessageStruct functionref( ClServer_MessageStruct ) > OnReceivedSayTextMessageCallbacks } NsCustomCallbacks -void function CServerGameDLL_ProcessMessageStartThread() +void function CServerGameDLL_ProcessMessageStartThread(int playerIndex, string message, bool isTeam) { - thread CServerGameDLL_OnReceivedSayTextMessageCallback() + thread CServerGameDLL_OnReceivedSayTextMessageCallback(playerIndex, message, isTeam) } -void function CServerGameDLL_OnReceivedSayTextMessageCallback() +void function CServerGameDLL_OnReceivedSayTextMessageCallback(int playerIndex, string message, bool isTeam) { + entity player = GetPlayerByIndex(playerIndex) + if (player == null) { + print("Ignored chat message from invalid player index " + playerIndex + ": " + message) + return + } + ClServer_MessageStruct localMessage - localMessage.message = NSChatGetCurrentMessage() - localMessage.player = GetPlayerByIndex(NSChatGetCurrentPlayer()) - localMessage.channelId = NSChatGetCurrentChannel() + localMessage.message = message + localMessage.player = player + localMessage.isTeam = isTeam localMessage.shouldBlock = false - foreach ( callbackFunc in NsCustomCallbacks.OnReceivedSayTextMessageCallbacks ) { ClServer_MessageStruct returnStruct = callbackFunc(localMessage) localMessage.message = returnStruct.message - localMessage.player = returnStruct.player - localMessage.channelId = returnStruct.channelId + localMessage.isTeam = returnStruct.isTeam localMessage.shouldBlock = localMessage.shouldBlock || returnStruct.shouldBlock } - NSSetMessage(localMessage.message, localMessage.player.GetPlayerIndex(), localMessage.channelId, localMessage.shouldBlock) + if (localMessage.shouldBlock) + { + return + } + + NSSendMessage(player.GetPlayerIndex(), localMessage.message, localMessage.isTeam) } void function AddCallback_OnReceivedSayTextMessage( ClServer_MessageStruct functionref (ClServer_MessageStruct) callbackFunc ) { NsCustomCallbacks.OnReceivedSayTextMessageCallbacks.append(callbackFunc) +} + +void function NSSetupChathooksServer() { + getroottable().rawset("CServerGameDLL_ProcessMessageStartThread", CServerGameDLL_ProcessMessageStartThread) } \ No newline at end of file -- cgit v1.2.3