-
-
Notifications
You must be signed in to change notification settings - Fork 682
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Port chat reliability subsystem from /tg/ (#10367)
* Port chat reliability subsystem from /tg/ * This crash isn't needed, seems to just be a /tg/ "cleanup" runtime according to git blame
- Loading branch information
Showing
6 changed files
with
178 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,38 +1,98 @@ | ||
/** | ||
/*! | ||
* Copyright (c) 2020 Aleksej Komarov | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
SUBSYSTEM_DEF(chat) | ||
name = "Chat" | ||
flags = SS_TICKER | ||
flags = SS_TICKER | SS_NO_INIT | ||
wait = 1 | ||
priority = FIRE_PRIORITY_CHAT | ||
init_order = INIT_ORDER_CHAT | ||
|
||
var/list/payload_by_client = list() | ||
/// Assosciates a ckey with a list of messages to send to them. | ||
var/list/list/datum/chat_payload/client_to_payloads = list() | ||
|
||
/// Associates a ckey with an assosciative list of their last CHAT_RELIABILITY_HISTORY_SIZE messages. | ||
var/list/list/datum/chat_payload/client_to_reliability_history = list() | ||
|
||
/// Assosciates a ckey with their next sequence number. | ||
var/list/client_to_sequence_number = list() | ||
|
||
/datum/controller/subsystem/chat/proc/generate_payload(client/target, message_data) | ||
var/sequence = client_to_sequence_number[target.ckey] | ||
client_to_sequence_number[target.ckey] += 1 | ||
|
||
var/datum/chat_payload/payload = new | ||
payload.sequence = sequence | ||
payload.content = message_data | ||
|
||
if(!(target.ckey in client_to_reliability_history)) | ||
client_to_reliability_history[target.ckey] = list() | ||
var/list/client_history = client_to_reliability_history[target.ckey] | ||
client_history["[sequence]"] = payload | ||
|
||
if(length(client_history) > CHAT_RELIABILITY_HISTORY_SIZE) | ||
var/oldest = text2num(client_history[1]) | ||
for(var/index in 2 to length(client_history)) | ||
var/test = text2num(client_history[index]) | ||
if(test < oldest) | ||
oldest = test | ||
client_history -= "[oldest]" | ||
return payload | ||
|
||
/datum/controller/subsystem/chat/proc/send_payload_to_client(client/target, datum/chat_payload/payload) | ||
target.tgui_panel.window.send_message("chat/message", payload.into_message()) | ||
SEND_TEXT(target, payload.get_content_as_html()) | ||
|
||
/datum/controller/subsystem/chat/fire() | ||
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)) | ||
for(var/ckey in client_to_payloads) | ||
var/client/target = GLOB.directory[ckey] | ||
if(isnull(target)) // verify client still exists | ||
LAZYREMOVE(client_to_payloads, ckey) | ||
continue | ||
|
||
for(var/datum/chat_payload/payload as anything in client_to_payloads[ckey]) | ||
send_payload_to_client(target, payload) | ||
LAZYREMOVE(client_to_payloads, ckey) | ||
|
||
if(MC_TICK_CHECK) | ||
return | ||
|
||
/datum/controller/subsystem/chat/proc/queue(target, message) | ||
if(islist(target)) | ||
for(var/_target in target) | ||
var/client/client = CLIENT_FROM_VAR(_target) | ||
if(client) | ||
LAZYADD(payload_by_client[client], list(message)) | ||
/datum/controller/subsystem/chat/proc/queue(queue_target, list/message_data) | ||
var/list/targets = islist(queue_target) ? queue_target : list(queue_target) | ||
for(var/target in targets) | ||
var/client/client = CLIENT_FROM_VAR(target) | ||
if(isnull(client)) | ||
continue | ||
LAZYADDASSOCLIST(client_to_payloads, client.ckey, generate_payload(client, message_data)) | ||
|
||
/datum/controller/subsystem/chat/proc/send_immediate(send_target, list/message_data) | ||
var/list/targets = islist(send_target) ? send_target : list(send_target) | ||
for(var/target in targets) | ||
var/client/client = CLIENT_FROM_VAR(target) | ||
if(isnull(client)) | ||
continue | ||
send_payload_to_client(client, generate_payload(client, message_data)) | ||
|
||
/datum/controller/subsystem/chat/proc/handle_resend(client/client, sequence) | ||
var/list/client_history = client_to_reliability_history[client.ckey] | ||
sequence = "[sequence]" | ||
if(isnull(client_history) || !(sequence in client_history)) | ||
return | ||
var/client/client = CLIENT_FROM_VAR(target) | ||
if(client) | ||
LAZYADD(payload_by_client[client], list(message)) | ||
|
||
var/datum/chat_payload/payload = client_history[sequence] | ||
if(payload.resends > CHAT_RELIABILITY_MAX_RESENDS) | ||
return // we tried but byond said no | ||
|
||
payload.resends += 1 | ||
send_payload_to_client(client, client_history[sequence]) | ||
SSblackbox.record_feedback( | ||
"nested tally", | ||
"chat_resend_byond_version", | ||
1, | ||
list( | ||
"[client.byond_version]", | ||
"[client.byond_build]", | ||
), | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/// Stores information about a chat payload | ||
/datum/chat_payload | ||
/// Sequence number of this payload | ||
var/sequence = 0 | ||
/// Message we are sending | ||
var/list/content | ||
/// Resend count | ||
var/resends = 0 | ||
|
||
/// Converts the chat payload into a JSON string | ||
/datum/chat_payload/proc/into_message() | ||
return "{\"sequence\":[sequence],\"content\":[json_encode(content)]}" | ||
|
||
/// Returns an HTML-encoded message from our contents. | ||
/datum/chat_payload/proc/get_content_as_html() | ||
return message_to_html(content) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters