diff --git a/code/_helpers/text.dm b/code/_helpers/text.dm
index c0b6bd5001..055eb14b14 100644
--- a/code/_helpers/text.dm
+++ b/code/_helpers/text.dm
@@ -345,8 +345,8 @@
if(!text_tag_cache[tagname])
var/icon/tag = icon(text_tag_icons, tagname)
text_tag_cache[tagname] = bicon(tag, TRUE, "text_tag")
- if(C.chatOutput.broken)
- return "
"
+ //if(C.chatOutput.broken) TODO: Find out the equivalent for actual tgchat (if not already implemented in other code)
+ //return "
"
return text_tag_cache[tagname]
/proc/create_text_tag_old(var/tagname, var/tagdesc = tagname, var/client/C = null)
diff --git a/code/controllers/subsystems/chat.dm b/code/controllers/subsystems/chat.dm
index 92a1be2757..ddcdf86741 100644
--- a/code/controllers/subsystems/chat.dm
+++ b/code/controllers/subsystems/chat.dm
@@ -1,77 +1,43 @@
+/*!
+ * Copyright (c) 2020 Aleksej Komarov
+ * SPDX-License-Identifier: MIT
+ */
+
SUBSYSTEM_DEF(chat)
name = "Chat"
flags = SS_TICKER
- wait = 1 // SS_TICKER means this runs every tick
+ wait = 1
priority = FIRE_PRIORITY_CHAT
init_order = INIT_ORDER_CHAT
- var/list/list/msg_queue = list() //List of lists
+ var/list/payload_by_client = list()
-/datum/controller/subsystem/chat/Initialize(timeofday)
- init_vchat()
- ..()
+/datum/controller/subsystem/chat/Initialize()
+ // Just used by chat system to know that initialization is nearly finished.
+ // The to_chat checks could probably check the runlevel instead, but would require testing.
+ return SS_INIT_SUCCESS
/datum/controller/subsystem/chat/fire()
- var/list/msg_queue = src.msg_queue // Local variable for sanic speed.
- for(var/client/C as anything in msg_queue)
- var/list/messages = msg_queue[C]
- msg_queue -= C
- if (C)
- C << output(jsEncode(messages), "htmloutput:putmessage")
-
+ for(var/key in payload_by_client)
+ var/client/client = key
+ var/payload = payload_by_client[key]
+ payload_by_client -= key
+ if(client)
+ // Send to tgchat
+ client.tgui_panel?.window.send_message("chat/message", payload)
+ // Send to old chat
+ for(var/message in payload)
+ SEND_TEXT(client, message_to_html(message))
if(MC_TICK_CHECK)
return
-/datum/controller/subsystem/chat/stat_entry()
- ..("C:[msg_queue.len]")
-
-/datum/controller/subsystem/chat/proc/queue(target, time, message, handle_whitespace = TRUE)
- if(!target || !message)
- return
-
- if(!istext(message))
- stack_trace("to_chat called with invalid input type")
- return
-
- // Currently to_chat(world, ...) gets sent individually to each client. Consider.
- if(target == world)
- target = GLOB.clients
-
- //Some macros remain in the string even after parsing and fuck up the eventual output
- var/original_message = message
- message = replacetext(message, "\n", "
")
- message = replacetext(message, "\improper", "")
- message = replacetext(message, "\proper", "")
-
- if(isnull(time))
- time = world.time
-
- var/list/messageStruct = list("time" = time, "message" = message);
-
+/datum/controller/subsystem/chat/proc/queue(target, message)
if(islist(target))
- for(var/I in target)
- var/client/C = CLIENT_FROM_VAR(I) //Grab us a client if possible
-
- if(!C || !C.chatOutput)
- continue // No client? No care.
- else if(C.chatOutput.broken)
- DIRECT_OUTPUT(C, original_message)
- continue
- else if(!C.chatOutput.loaded)
- continue // If not loaded yet, do nothing and history-sending on load will get it.
-
- LAZYINITLIST(msg_queue[C])
- msg_queue[C][++msg_queue[C].len] = messageStruct
- else
- var/client/C = CLIENT_FROM_VAR(target) //Grab us a client if possible
-
- if(!C || !C.chatOutput)
- return // No client? No care.
- else if(C.chatOutput.broken)
- DIRECT_OUTPUT(C, original_message)
- return
- else if(!C.chatOutput.loaded)
- return // If not loaded yet, do nothing and history-sending on load will get it.
-
- LAZYINITLIST(msg_queue[C])
- msg_queue[C][++msg_queue[C].len] = messageStruct
+ for(var/_target in target)
+ var/client/client = CLIENT_FROM_VAR(_target)
+ if(client)
+ LAZYADD(payload_by_client[client], list(message))
+ return
+ var/client/client = CLIENT_FROM_VAR(target)
+ if(client)
+ LAZYADD(payload_by_client[client], list(message))
diff --git a/code/controllers/subsystems/ping.dm b/code/controllers/subsystems/ping.dm
new file mode 100644
index 0000000000..ccc0f67f61
--- /dev/null
+++ b/code/controllers/subsystems/ping.dm
@@ -0,0 +1,40 @@
+/*!
+ * Copyright (c) 2022 Aleksej Komarov
+ * SPDX-License-Identifier: MIT
+ */
+
+SUBSYSTEM_DEF(ping)
+ name = "Ping"
+ priority = FIRE_PRIORITY_PING
+ init_stage = INITSTAGE_EARLY
+ wait = 4 SECONDS
+ flags = SS_NO_INIT
+ runlevels = RUNLEVEL_LOBBY | RUNLEVEL_SETUP | RUNLEVEL_GAME | RUNLEVEL_POSTGAME
+
+ var/list/currentrun = list()
+
+/datum/controller/subsystem/ping/stat_entry()
+ ..("P:[GLOB.clients.len]")
+
+/datum/controller/subsystem/ping/fire(resumed = FALSE)
+ // Prepare the new batch of clients
+ if (!resumed)
+ src.currentrun = GLOB.clients.Copy()
+
+ // De-reference the list for sanic speeds
+ var/list/currentrun = src.currentrun
+
+ while (currentrun.len)
+ var/client/client = currentrun[currentrun.len]
+ currentrun.len--
+
+ if (client?.tgui_panel?.is_ready())
+ // Send a soft ping
+ client.tgui_panel.window.send_message("ping/soft", list(
+ // Slightly less than the subsystem timer (somewhat arbitrary)
+ // to prevent incoming pings from resetting the afk state
+ "afk" = client.is_afk(3.5 SECONDS),
+ ))
+
+ if (MC_TICK_CHECK)
+ return
diff --git a/code/game/world.dm b/code/game/world.dm
index 254621afa9..9f08a33380 100644
--- a/code/game/world.dm
+++ b/code/game/world.dm
@@ -33,7 +33,6 @@
GLOB.timezoneOffset = get_timezone_offset()
callHook("startup")
- init_vchat()
//Emergency Fix
load_mods()
//end-emergency fix
diff --git a/code/modules/asset_cache/assets/chat.dm b/code/modules/asset_cache/assets/chat.dm
new file mode 100644
index 0000000000..eba0e5418e
--- /dev/null
+++ b/code/modules/asset_cache/assets/chat.dm
@@ -0,0 +1,2 @@
+/datum/asset/spritesheet/chat
+ name = "chat"
diff --git a/code/modules/asset_cache/assets/tgui.dm b/code/modules/asset_cache/assets/tgui.dm
index 6874c24eea..6446471a30 100644
--- a/code/modules/asset_cache/assets/tgui.dm
+++ b/code/modules/asset_cache/assets/tgui.dm
@@ -5,11 +5,9 @@
"tgui.bundle.css" = file("tgui/public/tgui.bundle.css"),
)
-/* Comment will be removed in later part
/datum/asset/simple/tgui_panel
// keep_local_name = TRUE
assets = list(
"tgui-panel.bundle.js" = file("tgui/public/tgui-panel.bundle.js"),
"tgui-panel.bundle.css" = file("tgui/public/tgui-panel.bundle.css"),
)
-*/
diff --git a/code/modules/client/client defines.dm b/code/modules/client/client defines.dm
index a68740e965..e3e23af110 100644
--- a/code/modules/client/client defines.dm
+++ b/code/modules/client/client defines.dm
@@ -41,8 +41,10 @@
var/datum/admins/deadmin_holder = null
var/buildmode = 0
- var/last_message = "" //Contains the last message sent by this client - used to protect against copy-paste spamming.
- var/last_message_count = 0 //contins a number of how many times a message identical to last_message was sent.
+ ///Contains the last message sent by this client - used to protect against copy-paste spamming.
+ var/last_message = ""
+ ///contins a number of how many times a message identical to last_message was sent.
+ var/last_message_count = 0
var/ircreplyamount = 0
var/entity_narrate_holder //Holds /datum/entity_narrate when using the relevant admin verbs.
@@ -56,9 +58,7 @@
var/area = null
var/time_died_as_mouse = null //when the client last died as a mouse
var/datum/tooltip/tooltips = null
- var/datum/chatOutput/chatOutput
var/datum/volume_panel/volume_panel = null // Initialized by /client/verb/volume_panel()
- var/chatOutputLoadedAt
var/seen_news = 0
var/adminhelped = 0
diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm
index ff1c186eaa..867bbaa291 100644
--- a/code/modules/client/client procs.dm
+++ b/code/modules/client/client procs.dm
@@ -133,7 +133,6 @@
if("usr") hsrc = mob
if("prefs") return prefs.process_link(usr,href_list)
if("vars") return view_var_Topic(href,href_list,hsrc)
- if("chat") return chatOutput.Topic(href, href_list)
switch(href_list["action"])
if("openLink")
@@ -172,11 +171,6 @@
del(src)
return
- chatOutput = new /datum/chatOutput(src) //veechat
- chatOutput.send_resources()
- spawn()
- chatOutput.start()
-
//Only show this if they are put into a new_player mob. Otherwise, "what title screen?"
if(isnewplayer(src.mob))
to_chat(src, "If the title screen is black, resources are still downloading. Please be patient until the title screen appears.")
@@ -184,6 +178,9 @@
GLOB.clients += src
GLOB.directory[ckey] = src
+ // Instantiate tgui panel
+ tgui_panel = new(src, "browseroutput")
+
GLOB.ahelp_tickets.ClientLogin(src)
GLOB.mhelp_tickets.ClientLogin(src)
@@ -213,6 +210,9 @@
if(prefs)
prefs.selecting_slots = FALSE
+ // Initialize tgui panel
+ tgui_panel.initialize()
+
connection_time = world.time
connection_realtime = world.realtime
connection_timeofday = world.timeofday
@@ -484,29 +484,6 @@
return FALSE
return ..()
-/client/verb/reload_vchat()
- set name = "Reload VChat"
- set category = "OOC"
-
- //Timing
- if(src.chatOutputLoadedAt > (world.time - 10 SECONDS))
- tgui_alert_async(src, "You can only try to reload VChat every 10 seconds at most.")
- return
-
- verbs -= /client/proc/vchat_export_log
-
- //Log, disable
- log_debug("[key_name(src)] reloaded VChat.")
- winset(src, null, "outputwindow.htmloutput.is-visible=false;outputwindow.oldoutput.is-visible=false;outputwindow.chatloadlabel.is-visible=true")
-
- //The hard way
- qdel_null(src.chatOutput)
- chatOutput = new /datum/chatOutput(src) //veechat
- chatOutput.send_resources()
- spawn()
- chatOutput.start()
-
-
//This is for getipintel.net.
//You're welcome to replace this proc with your own that does your own cool stuff.
//Just set the client's ip_reputation var and make sure it makes sense with your config settings (higher numbers are worse results)
diff --git a/interface/skin.dmf b/interface/skin.dmf
index 3243245070..7a6eb04f46 100644
--- a/interface/skin.dmf
+++ b/interface/skin.dmf
@@ -1269,16 +1269,17 @@ window "outputwindow"
text-color = #ffffff
background-color = #222222
saved-params = ""
- text = "Chat is loading.\nIf nothing happens after 20s,\nuse OOC > \"Reload VChat\"."
- elem "htmloutput"
+ text = "Chat is loading.\nIf nothing happens after 20s,\nuse OOC > \"Fix chat\"."
+ elem "browseroutput"
type = BROWSER
pos = 0,0
size = 640x480
anchor1 = 0,0
anchor2 = 100,100
is-visible = false
+ is-disable = true
saved-params = ""
- elem "oldoutput"
+ elem "output"
type = OUTPUT
pos = 0,0
size = 640x480
diff --git a/vorestation.dme b/vorestation.dme
index e86623dbc9..22e6ae5d78 100644
--- a/vorestation.dme
+++ b/vorestation.dme
@@ -1849,6 +1849,7 @@
#include "code\modules\asset_cache\asset_cache_item.dm"
#include "code\modules\asset_cache\asset_list.dm"
#include "code\modules\asset_cache\asset_list_items.dm"
+#include "code\modules\asset_cache\assets\chat.dm"
#include "code\modules\asset_cache\assets\fontawesome.dm"
#include "code\modules\asset_cache\assets\jquery.dm"
#include "code\modules\asset_cache\assets\tgfont.dm"
@@ -4011,6 +4012,9 @@
#include "code\modules\telesci\telepad.dm"
#include "code\modules\telesci\telesci_computer.dm"
#include "code\modules\tension\tension.dm"
+#include "code\modules\tgchat\_legacy.dm"
+#include "code\modules\tgchat\message.dm"
+#include "code\modules\tgchat\to_chat.dm"
#include "code\modules\tgs\includes.dm"
#include "code\modules\tgui\external.dm"
#include "code\modules\tgui\modal.dm"
@@ -4067,6 +4071,10 @@
#include "code\modules\tgui_input\list.dm"
#include "code\modules\tgui_input\number.dm"
#include "code\modules\tgui_input\text.dm"
+#include "code\modules\tgui_panel\audio.dm"
+#include "code\modules\tgui_panel\external.dm"
+#include "code\modules\tgui_panel\telemetry.dm"
+#include "code\modules\tgui_panel\tgui_panel.dm"
#include "code\modules\tooltip\tooltip.dm"
#include "code\modules\turbolift\_turbolift.dm"
#include "code\modules\turbolift\turbolift.dm"
@@ -4078,8 +4086,6 @@
#include "code\modules\turbolift\turbolift_floor.dm"
#include "code\modules\turbolift\turbolift_map.dm"
#include "code\modules\turbolift\turbolift_turfs.dm"
-#include "code\modules\vchat\vchat_client.dm"
-#include "code\modules\vchat\vchat_db.dm"
#include "code\modules\vehicles\bike.dm"
#include "code\modules\vehicles\boat.dm"
#include "code\modules\vehicles\cargo_train.dm"