Merge pull request #6760 from VOREStation/aro-vchatpingy

Some VChat Tweaks
This commit is contained in:
Novacat
2020-03-05 13:34:49 -05:00
committed by GitHub
5 changed files with 109 additions and 46 deletions

View File

@@ -428,6 +428,7 @@ client/verb/character_setup()
//Log, disable //Log, disable
log_debug("[key_name(src)] reloaded VChat.") 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 //The hard way
qdel_null(src.chatOutput) qdel_null(src.chatOutput)

View File

@@ -18,8 +18,8 @@
<body> <body>
<div id="loader"> <div id="loader">
<p>VChat is still loading. If you see this for a very long time, try the OOC 'Reload VChat' verb, or reconnecting.</p> <p>You probably shouldn't see this page. This generally means chat is very broken.</p>
<p>Sometimes if you're still caching resources, it will take longer than usual.</p> <p>You can wait a few seconds to see if it loads, or try OOC > Reload VChat.</p>
</div> </div>
<div id="app" @mouseup="on_mouseup" style="display: none;" :class="{ inverted: inverted }"> <div id="app" @mouseup="on_mouseup" style="display: none;" :class="{ inverted: inverted }">
@@ -41,7 +41,13 @@
<div class="item" @click="editmode" title="Edit Mode"> <div class="item" @click="editmode" title="Edit Mode">
<i class="icon-cog-outline" :class="{ blinkwarn: editing }"></i> <i class="icon-cog-outline" :class="{ blinkwarn: editing }"></i>
</div> </div>
<div class="item"><span class="ui circular label" title="VChat Latency (Not exactly network latency)" :class="ping_classes">{{latency}}ms</span></div> <div class="item" title="Click to test latency">
<span class="ui circular label" :class="ping_classes" @click="do_latency_test">
<template v-if="latency">
{{latency}}ms
</template>
</span>
</div>
</div> </div>
</div> </div>
@@ -78,7 +84,6 @@
</div> </div>
<div class="eight wide column"> <div class="eight wide column">
<h3>Global Settings</h3> <h3>Global Settings</h3>
<p>Clicking anywhere in VChat saves your settings.</p>
<div class="ui form" :class="{ inverted: inverted }"> <div class="ui form" :class="{ inverted: inverted }">
<div class="grouped fields"> <div class="grouped fields">
<div class="field"> <div class="field">
@@ -116,19 +121,19 @@
<div class="inline fields"> <div class="inline fields">
<div class="field" title="Font size (Min 0.2, Max 5, Default 0.9)"> <div class="field" title="Font size (Min 0.2, Max 5, Default 0.9)">
<label>Font Scale</label> <label>Font Scale</label>
<input class="inputbox" type="number" name="fontsize" placeholder="0.9" v-model.lazy.number="fontsize" required> <input class="inputbox" type="number" name="fontsize" placeholder="0.9" v-model.lazy.number="fontsize" required @keyup.enter="blur_this($event)">
</div> </div>
</div> </div>
<div class="inline fields"> <div class="inline fields">
<div class="field" title="Line height % (Min 100, Max 200, Default 130)"> <div class="field" title="Line height % (Min 100, Max 200, Default 130)">
<label>Line Height %</label> <label>Line Height %</label>
<input class="inputbox" type="number" name="lineheight" placeholder="130" v-model.lazy.number="lineheight" required> <input class="inputbox" type="number" name="lineheight" placeholder="130" v-model.lazy.number="lineheight" required @keyup.enter="blur_this($event)">
</div> </div>
</div> </div>
<div class="inline fields"> <div class="inline fields">
<div class="field" title="Hides messages for performance (Min 50, Max 2000, Default 200)"> <div class="field" title="Hides messages for performance (Min 50, Max 2000, Default 200)">
<label># Stored Messages</label> <label># Stored Messages</label>
<input class="inputbox" type="number" name="showingnum" placeholder="200" v-model.lazy.number="showingnum" required> <input class="inputbox" type="number" name="showingnum" placeholder="200" v-model.lazy.number="showingnum" required @keyup.enter="blur_this($event)">
</div> </div>
</div> </div>
</div> </div>

View File

@@ -24,8 +24,7 @@
//Options for vchat //Options for vchat
var vchat_opts = { var vchat_opts = {
pingThisOften: 10000, //ms msBeforeDropped: 30000, //No ping for this long, and the server must be gone
pingDropsAllowed: 2,
cookiePrefix: "vst-", //If you're another server, you can change this if you want. 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 alwaysShow: ["vc_looc", "vc_system"] //Categories to always display on every tab
}; };
@@ -75,11 +74,8 @@ var vchat_state = {
byond_ckey: null, byond_ckey: null,
//Ping status //Ping status
lastPingAttempt: 0, lastPingReceived: 0,
lastPingReply: 0, latency_sent: 0,
missedPings: 0,
latency: 0,
reconnecting: false,
//Last ID //Last ID
lastId: 0 lastId: 0
@@ -99,8 +95,7 @@ function start_vchat() {
doWinset("chatloadlabel", {"is-visible": false}); doWinset("chatloadlabel", {"is-visible": false});
//Commence the pingening //Commence the pingening
send_ping(); setInterval(check_ping, vchat_opts.msBeforeDropped);
setInterval(send_ping, vchat_opts.pingThisOften);
//For fun //For fun
send_debug("VChat Loaded!"); send_debug("VChat Loaded!");
@@ -125,6 +120,7 @@ function start_vue() {
editing: false, //If we're in settings edit mode editing: false, //If we're in settings edit mode
paused: false, //Autoscrolling paused: false, //Autoscrolling
latency: 0, //Not necessarily network latency, since the game server has to align the responses into ticks 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 ext_styles: "", //Styles for chat downloaded files
is_admin: false, is_admin: false,
@@ -261,6 +257,13 @@ function start_vue() {
} }
}, },
watch: { 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 //Save the inverted setting to LS
inverted: function (newSetting) { inverted: function (newSetting) {
set_storage("darkmode",newSetting); set_storage("darkmode",newSetting);
@@ -335,11 +338,15 @@ function start_vue() {
}, },
//What color does the latency pip get? //What color does the latency pip get?
ping_classes: function() { 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 < 0 ) {return "red"; }
else if(this.latency <= 200) { return "green"; } else if(this.latency <= 200) { return "green"; }
else if(this.latency <= 400) { return "yellow"; } else if(this.latency <= 400) { return "yellow"; }
else { return "red"; } else { return "grey"; }
}, },
current_categories: function() { current_categories: function() {
if(this.active_tab == this.tabs[0]) { if(this.active_tab == this.tabs[0]) {
@@ -620,6 +627,12 @@ function start_vue() {
let blob = new Blob([textToSave], {type: 'text/html;charset=utf8;'}); let blob = new Blob([textToSave], {type: 'text/html;charset=utf8;'});
saved = window.navigator.msSaveOrOpenBlob(blob, filename); saved = window.navigator.msSaveOrOpenBlob(blob, filename);
} }
},
do_latency_test: function() {
send_latency_check();
},
blur_this: function(event) {
event.target.blur();
} }
} }
}); });
@@ -630,21 +643,37 @@ function start_vue() {
* Actual Methods * Actual Methods
* *
************/ ************/
//Send a 'ping' to byond and check to see if we got the last one back in a timely manner function check_ping() {
function send_ping() { var time_ago = Date.now() - vchat_state.lastPingReceived;
vchat_state.latency = (Math.min(Math.max(vchat_state.lastPingReply - vchat_state.lastPingAttempt, -1), 999)); if(time_ago > vchat_opts.msBeforeDropped)
//If their last reply was in the previous ping window or earlier. vueapp.reconnecting = true;
if(vchat_state.latency < 0) { }
vchat_state.missedPings++;
if((vchat_state.missedPings >= vchat_opts.pingDropsAllowed) && !vchat_state.reconnecting) { //Send a 'ping' to byond
system_message("Your client has lost connection with the server. It will reconnect automatically if possible."); function send_latency_check() {
vchat_state.reconnecting = true; 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; vueapp.latency = Date.now() - vchat_state.latency_sent;
push_Topic("keepalive_client");
vchat_state.lastPingAttempt = Date.now();
} }
//We accept double-url-encoded JSON strings because Byond is garbage and UTF-8 encoded url_encode() text has crazy garbage in it. //We accept double-url-encoded JSON strings because Byond is garbage and UTF-8 encoded url_encode() text has crazy garbage in it.
@@ -695,7 +724,7 @@ function send_debug(message) {
//A side-channel to send events over that aren't just chat messages, if necessary. //A side-channel to send events over that aren't just chat messages, if necessary.
function get_event(event) { function get_event(event) {
if(!vchat_state.ready) { if(!vchat_state.ready) {
push_Topic('not_ready'); push_Topic("not_ready");
return; return;
} }
@@ -721,10 +750,19 @@ function get_event(event) {
break; break;
//Just a ping. //Just a ping.
case 'keepalive_server': case 'keepalive':
vchat_state.lastPingReply = Date.now(); vchat_state.lastPingReceived = Date.now();
vchat_state.missedPings = 0; vueapp.reconnecting = false;
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; break;
default: default:

View File

@@ -46,7 +46,6 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("data/iconCache.sav")) //Cache of ic
. = ..() . = ..()
owner = C owner = C
update_vis()
/datum/chatOutput/Destroy() /datum/chatOutput/Destroy()
owner = null owner = null
@@ -78,14 +77,20 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("data/iconCache.sav")) //Cache of ic
become_broken() become_broken()
return FALSE 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 if(!owner) // In case the client vanishes before winexists returns
qdel(src) qdel(src)
return FALSE return FALSE
if(!resources_sent) if(!loaded)
send_resources() update_vis()
if(!resources_sent)
load() send_resources()
load()
return TRUE return TRUE
@@ -115,7 +120,7 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("data/iconCache.sav")) //Cache of ic
owner.chatOutputLoadedAt = world.time owner.chatOutputLoadedAt = world.time
//update_vis() //It does it's own winsets //update_vis() //It does it's own winsets
ping_cycle()
send_playerinfo() send_playerinfo()
load_database() 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) /datum/chatOutput/proc/send_event(var/event, var/client/C = owner)
C << output(jsEncode(event), "htmloutput:get_event") 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 //Just produces a message for using in keepalives from the server to the client
/datum/chatOutput/proc/keepalive() /datum/chatOutput/proc/keep_alive()
return list("evttype" = "keepalive_server") 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") //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) /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!") CRASH("Tried to send a message to [owner.ckey] chatOutput before it was ready!")
if("done_loading") if("done_loading")
data = done_loading(arglist(params)) data = done_loading(arglist(params))
if("keepalive_client") if("ping")
data = keepalive(arglist(params)) data = latency_check(arglist(params))
if("ident") if("ident")
data = bancheck(arglist(params)) data = bancheck(arglist(params))
if("unloading") if("unloading")

View File

@@ -1226,7 +1226,7 @@ window "outputwindow"
background-color = #222222 background-color = #222222
is-visible = true is-visible = true
saved-params = "" 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" elem "htmloutput"
type = BROWSER type = BROWSER
pos = 0,0 pos = 0,0