From 347a52eb52d9bb9b2f692212fc99069fc5d33636 Mon Sep 17 00:00:00 2001 From: tralezab <40974010+tralezab@users.noreply.github.com> Date: Wed, 24 Jul 2019 21:23:05 -0700 Subject: [PATCH] Chat Subsystem ported from TerraGov-Marine-Corps (#45354) * chat subsystem v0.1 * removes old tabulator * updates the check on to_chat * SSchat now initializes --- code/__DEFINES/subsystems.dm | 10 ++-- code/controllers/subsystem/chat.dm | 68 ++++++++++++++++++++++++++ code/modules/goonchat/browserOutput.dm | 10 +++- tgstation.dme | 1 + 4 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 code/controllers/subsystem/chat.dm diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 6727c64b570..e05e0d20c99 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -1,12 +1,12 @@ //! Defines for subsystems and overlays -//! +//! //! Lots of important stuff in here, make sure you have your brain switched on //! when editing this file //! ## DB defines /** * DB major schema version - * + * * Update this whenever the db schema changes * * make sure you add an update to the schema_version stable in the db changelog @@ -15,7 +15,7 @@ /** * DB minor schema version - * + * * Update this whenever the db schema changes * * make sure you add an update to the schema_version stable in the db changelog @@ -132,7 +132,8 @@ #define INIT_ORDER_MINOR_MAPPING -40 #define INIT_ORDER_PATH -50 #define INIT_ORDER_DISCORD -60 -#define INIT_ORDER_PERSISTENCE -100 +#define INIT_ORDER_PERSISTENCE -95 +#define INIT_ORDER_CHAT -100 //Should be last to ensure chat remains smooth during init. // Subsystem fire priority, from lowest to highest priority // If the subsystem isn't listed here it's either DEFAULT or PROCESS (if it's a processing subsystem child) @@ -161,6 +162,7 @@ #define FIRE_PRIORITY_TGUI 110 #define FIRE_PRIORITY_TICKER 200 #define FIRE_PRIORITY_ATMOS_ADJACENCY 300 +#define FIRE_PRIORITY_CHAT 400 #define FIRE_PRIORITY_OVERLAYS 500 #define FIRE_PRIORITY_INPUT 1000 // This must always always be the max highest priority. Player input must never be lost. diff --git a/code/controllers/subsystem/chat.dm b/code/controllers/subsystem/chat.dm new file mode 100644 index 00000000000..a103a0eaafe --- /dev/null +++ b/code/controllers/subsystem/chat.dm @@ -0,0 +1,68 @@ +SUBSYSTEM_DEF(chat) + name = "Chat" + flags = SS_TICKER|SS_NO_INIT + wait = 1 + priority = FIRE_PRIORITY_CHAT + init_order = INIT_ORDER_CHAT + + var/list/payload = list() + + +/datum/controller/subsystem/chat/fire() + for(var/i in payload) + var/client/C = i + C << output(payload[C], "browseroutput:output") + payload -= C + + if(MC_TICK_CHECK) + return + + +/datum/controller/subsystem/chat/proc/queue(target, message, handle_whitespace = TRUE) + if(!target || !message) + return + + if(!istext(message)) + stack_trace("to_chat called with invalid input type") + return + + if(target == world) + target = GLOB.clients + + //Some macros remain in the string even after parsing and fuck up the eventual output + message = replacetext(message, "\improper", "") + message = replacetext(message, "\proper", "") + if(handle_whitespace) + message = replacetext(message, "\n", "
") + message = replacetext(message, "\t", "[FOURSPACES][FOURSPACES]") + message += "
" + + + //url_encode it TWICE, this way any UTF-8 characters are able to be decoded by the Javascript. + //Do the double-encoding here to save nanoseconds + var/twiceEncoded = url_encode(url_encode(message)) + + if(islist(target)) + for(var/I in target) + var/client/C = CLIENT_FROM_VAR(I) //Grab us a client if possible + + if(!C?.chatOutput || C.chatOutput.broken) //A player who hasn't updated his skin file. + continue + + if(!C.chatOutput.loaded) //Client still loading, put their messages in a queue + C.chatOutput.messageQueue += message + continue + + payload[C] += twiceEncoded + + else + var/client/C = CLIENT_FROM_VAR(target) //Grab us a client if possible + + if(!C?.chatOutput || C.chatOutput.broken) //A player who hasn't updated his skin file. + return + + if(!C.chatOutput.loaded) //Client still loading, put their messages in a queue + C.chatOutput.messageQueue += message + return + + payload[C] += twiceEncoded diff --git a/code/modules/goonchat/browserOutput.dm b/code/modules/goonchat/browserOutput.dm index 2a4b37cd2b3..f3b0fbffc2f 100644 --- a/code/modules/goonchat/browserOutput.dm +++ b/code/modules/goonchat/browserOutput.dm @@ -205,8 +205,8 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico log_world("\[[time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")]\] Client: [(src.owner.key ? src.owner.key : src.owner)] triggered JS error: [error]") //Global chat procs -/proc/to_chat(target, message, handle_whitespace=TRUE) - if(!target) +/proc/to_chat_immediate(target, message, handle_whitespace = TRUE) + if(!target || !message) return if(target == world) @@ -258,6 +258,12 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico // url_encode it TWICE, this way any UTF-8 characters are able to be decoded by the Javascript. C << output(url_encode(url_encode(message)), "browseroutput:output") +/proc/to_chat(target, message, handle_whitespace = TRUE) + if(Master.current_runlevel == RUNLEVEL_INIT || !SSchat?.initialized) + to_chat_immediate(target, message, handle_whitespace) + return + SSchat.queue(target, message, handle_whitespace) + /datum/chatOutput/proc/swaptolightmode() //Dark mode light mode stuff. Yell at KMC if this breaks! (See darkmode.dm for documentation) owner.force_white_theme() diff --git a/tgstation.dme b/tgstation.dme index 4dd91d01001..e747e1e4d4b 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -230,6 +230,7 @@ #include "code\controllers\subsystem\atoms.dm" #include "code\controllers\subsystem\augury.dm" #include "code\controllers\subsystem\blackbox.dm" +#include "code\controllers\subsystem\chat.dm" #include "code\controllers\subsystem\communications.dm" #include "code\controllers\subsystem\dbcore.dm" #include "code\controllers\subsystem\dcs.dm"