diff --git a/code/modules/vchat/js/vchat.js b/code/modules/vchat/js/vchat.js
index 905505bcb8..bf1d2a16a4 100644
--- a/code/modules/vchat/js/vchat.js
+++ b/code/modules/vchat/js/vchat.js
@@ -24,8 +24,7 @@
//Options for vchat
var vchat_opts = {
- pingThisOften: 10000, //ms
- pingDropsAllowed: 2,
+ msBeforeDropped: 30000, //No ping for this long, and the server must be gone
cookiePrefix: "vst-", //If you're another server, you can change this if you want.
alwaysShow: ["vc_looc", "vc_system"] //Categories to always display on every tab
};
@@ -75,11 +74,8 @@ var vchat_state = {
byond_ckey: null,
//Ping status
- lastPingAttempt: 0,
- lastPingReply: 0,
- missedPings: 0,
- latency: 0,
- reconnecting: false,
+ lastPingReceived: 0,
+ latency_sent: 0,
//Last ID
lastId: 0
@@ -99,8 +95,7 @@ function start_vchat() {
doWinset("chatloadlabel", {"is-visible": false});
//Commence the pingening
- send_ping();
- setInterval(send_ping, vchat_opts.pingThisOften);
+ setInterval(check_ping, vchat_opts.msBeforeDropped);
//For fun
send_debug("VChat Loaded!");
@@ -125,6 +120,7 @@ function start_vue() {
editing: false, //If we're in settings edit mode
paused: false, //Autoscrolling
latency: 0, //Not necessarily network latency, since the game server has to align the responses into ticks
+ reconnecting: false, //If we've lost our connection
ext_styles: "", //Styles for chat downloaded files
is_admin: false,
@@ -261,6 +257,13 @@ function start_vue() {
}
},
watch: {
+ reconnecting: function(newSetting, oldSetting) {
+ if(newSetting == true && oldSetting == false) {
+ this.internal_message("Your client has lost connection to the server, or there is severe lag. Your client will reconnect if possible.");
+ } else if (newSetting == false && oldSetting == true) {
+ this.internal_message("Your client has reconnected to the server.");
+ }
+ },
//Save the inverted setting to LS
inverted: function (newSetting) {
set_storage("darkmode",newSetting);
@@ -335,11 +338,15 @@ function start_vue() {
},
//What color does the latency pip get?
ping_classes: function() {
- if(this.latency === 0) { return "grey"; }
+ if(!this.latency) {
+ return this.reconnecting ? "red" : "green"; //Standard
+ }
+
+ if (this.latency == "?") { return "grey"; } //Waiting for latency test reply
else if(this.latency < 0 ) {return "red"; }
else if(this.latency <= 200) { return "green"; }
else if(this.latency <= 400) { return "yellow"; }
- else { return "red"; }
+ else { return "grey"; }
},
current_categories: function() {
if(this.active_tab == this.tabs[0]) {
@@ -603,6 +610,12 @@ function start_vue() {
let blob = new Blob([textToSave], {type: 'text/html;charset=utf8;'});
saved = window.navigator.msSaveBlob(blob, filename);
}
+ },
+ do_latency_test: function() {
+ send_latency_check();
+ },
+ blur_this: function(event) {
+ event.target.blur();
}
}
});
@@ -613,21 +626,37 @@ function start_vue() {
* Actual Methods
*
************/
-//Send a 'ping' to byond and check to see if we got the last one back in a timely manner
-function send_ping() {
- vchat_state.latency = (Math.min(Math.max(vchat_state.lastPingReply - vchat_state.lastPingAttempt, -1), 999));
- //If their last reply was in the previous ping window or earlier.
- if(vchat_state.latency < 0) {
- vchat_state.missedPings++;
- if((vchat_state.missedPings >= vchat_opts.pingDropsAllowed) && !vchat_state.reconnecting) {
- system_message("Your client has lost connection with the server. It will reconnect automatically if possible.");
- vchat_state.reconnecting = true;
+function check_ping() {
+ var time_ago = Date.now() - vchat_state.lastPingReceived;
+ if(time_ago > vchat_opts.msBeforeDropped)
+ vueapp.reconnecting = true;
+}
+
+//Send a 'ping' to byond
+function send_latency_check() {
+ if(vchat_state.latency_sent)
+ return;
+
+ vchat_state.latency_sent = Date.now();
+ vueapp.latency = "?";
+ push_Topic("ping");
+ setTimeout(function() {
+ if(vchat_state.latency_ms == "?") {
+ vchat_state.latency_ms = 999;
}
+ }, 1000); // 1 second to reply otherwise we mark it as bad
+ setTimeout(function() {
+ vchat_state.latency_sent = 0;
+ vueapp.latency = 0;
+ }, 5000); //5 seconds to display ping time overall
+}
+
+function get_latency_check() {
+ if(!vchat_state.latency_sent) {
+ return; //Too late
}
- vueapp.latency = vchat_state.latency;
- push_Topic("keepalive_client");
- vchat_state.lastPingAttempt = Date.now();
+ vueapp.latency = Date.now() - vchat_state.latency_sent;
}
//We accept double-url-encoded JSON strings because Byond is garbage and UTF-8 encoded url_encode() text has crazy garbage in it.
@@ -678,7 +707,7 @@ function send_debug(message) {
//A side-channel to send events over that aren't just chat messages, if necessary.
function get_event(event) {
if(!vchat_state.ready) {
- push_Topic('not_ready');
+ push_Topic("not_ready");
return;
}
@@ -704,10 +733,19 @@ function get_event(event) {
break;
//Just a ping.
- case 'keepalive_server':
- vchat_state.lastPingReply = Date.now();
- vchat_state.missedPings = 0;
- reconnecting = false;
+ case 'keepalive':
+ vchat_state.lastPingReceived = Date.now();
+ vueapp.reconnecting = false;
+ break;
+
+ //Response to a latency test.
+ case 'pong':
+ get_latency_check();
+ break;
+
+ //The server doesn't know if we're loaded or not (we bail above if we're not, so we must be).
+ case 'availability':
+ push_Topic("done_loading");
break;
default:
diff --git a/code/modules/vchat/vchat_client.dm b/code/modules/vchat/vchat_client.dm
index ec32c08118..23900f2d3c 100644
--- a/code/modules/vchat/vchat_client.dm
+++ b/code/modules/vchat/vchat_client.dm
@@ -46,7 +46,6 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("data/iconCache.sav")) //Cache of ic
. = ..()
owner = C
- update_vis()
/datum/chatOutput/Destroy()
owner = null
@@ -78,14 +77,20 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("data/iconCache.sav")) //Cache of ic
become_broken()
return FALSE
+ //Could be loaded from a previous round, are you still there?
+ if(winget(owner,"outputwindow.htmloutput","is-visible") == "true") //Winget returns strings
+ send_event(event = list("evttype" = "availability"))
+ sleep(3 SECONDS)
+
if(!owner) // In case the client vanishes before winexists returns
qdel(src)
return FALSE
- if(!resources_sent)
- send_resources()
-
- load()
+ if(!loaded)
+ update_vis()
+ if(!resources_sent)
+ send_resources()
+ load()
return TRUE
@@ -115,7 +120,7 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("data/iconCache.sav")) //Cache of ic
owner.chatOutputLoadedAt = world.time
//update_vis() //It does it's own winsets
-
+ ping_cycle()
send_playerinfo()
load_database()
@@ -163,9 +168,23 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("data/iconCache.sav")) //Cache of ic
/datum/chatOutput/proc/send_event(var/event, var/client/C = owner)
C << output(jsEncode(event), "htmloutput:get_event")
+//Looping sleeping proc that just pings the client and dies when we die
+/datum/chatOutput/proc/ping_cycle()
+ set waitfor = FALSE
+ while(!QDELING(src))
+ if(!owner)
+ qdel(src)
+ return
+ send_event(event = keep_alive())
+ sleep(20 SECONDS) //Make sure this makes sense with what the js client is expecting
+
//Just produces a message for using in keepalives from the server to the client
-/datum/chatOutput/proc/keepalive()
- return list("evttype" = "keepalive_server")
+/datum/chatOutput/proc/keep_alive()
+ return list("evttype" = "keepalive")
+
+//A response to a latency check from the client
+/datum/chatOutput/proc/latency_check()
+ return list("evttype" = "pong")
//Redirected from client/Topic when the user clicks a link that pertains directly to the chat (when src == "chat")
/datum/chatOutput/Topic(var/href, var/list/href_list)
@@ -197,8 +216,8 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("data/iconCache.sav")) //Cache of ic
CRASH("Tried to send a message to [owner.ckey] chatOutput before it was ready!")
if("done_loading")
data = done_loading(arglist(params))
- if("keepalive_client")
- data = keepalive(arglist(params))
+ if("ping")
+ data = latency_check(arglist(params))
if("ident")
data = bancheck(arglist(params))
if("unloading")
diff --git a/interface/skin.dmf b/interface/skin.dmf
index 865853f15c..917ff0455e 100644
--- a/interface/skin.dmf
+++ b/interface/skin.dmf
@@ -1226,7 +1226,7 @@ window "outputwindow"
background-color = #222222
is-visible = true
saved-params = ""
- text = "Chat is loading.\nIf nothing happens after 60s,\nuse OOC > \"Reload VChat\"."
+ text = "Chat is loading.\nIf nothing happens after 20s,\nuse OOC > \"Reload VChat\"."
elem "htmloutput"
type = BROWSER
pos = 0,0