mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-18 19:44:58 +01:00
@@ -80,6 +80,7 @@
|
||||
/code/__DEFINES/chat.dm @stylemistake
|
||||
/code/__DEFINES/tgui.dm @stylemistake
|
||||
/code/controllers/subsystem/chat.dm @stylemistake
|
||||
/code/controllers/subsystem/ping.dm @stylemistake
|
||||
/code/controllers/subsystem/tgui.dm @stylemistake
|
||||
/code/modules/tgchat @stylemistake
|
||||
/code/modules/tgui @stylemistake
|
||||
|
||||
@@ -165,6 +165,7 @@
|
||||
// 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)
|
||||
|
||||
#define FIRE_PRIORITY_PING 10
|
||||
#define FIRE_PRIORITY_IDLE_NPC 10
|
||||
#define FIRE_PRIORITY_SERVER_MAINT 10
|
||||
#define FIRE_PRIORITY_RESEARCH 10
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*!
|
||||
* Copyright (c) 2022 Aleksej Komarov
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
SUBSYSTEM_DEF(ping)
|
||||
name = "Ping"
|
||||
priority = FIRE_PRIORITY_PING
|
||||
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
|
||||
@@ -545,6 +545,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
active_mousedown_item = null
|
||||
SSambience.remove_ambience_client(src)
|
||||
SSmouse_entered.hovers -= src
|
||||
SSping.currentrun -= src
|
||||
QDEL_NULL(view_size)
|
||||
QDEL_NULL(void)
|
||||
QDEL_NULL(tooltips)
|
||||
|
||||
@@ -317,7 +317,7 @@
|
||||
if(initialized)
|
||||
send_full_update()
|
||||
initialized = TRUE
|
||||
if("pingReply")
|
||||
if("ping/reply")
|
||||
initialized = TRUE
|
||||
if("suspend")
|
||||
close(can_be_suspended = TRUE)
|
||||
|
||||
@@ -325,7 +325,7 @@
|
||||
// If not locked, handle these message types
|
||||
switch(type)
|
||||
if("ping")
|
||||
send_message("pingReply", payload)
|
||||
send_message("ping/reply", payload)
|
||||
if("suspend")
|
||||
close(can_be_suspended = TRUE)
|
||||
if("close")
|
||||
|
||||
@@ -482,6 +482,7 @@
|
||||
#include "code\controllers\subsystem\pathfinder.dm"
|
||||
#include "code\controllers\subsystem\persistence.dm"
|
||||
#include "code\controllers\subsystem\persistent_paintings.dm"
|
||||
#include "code\controllers\subsystem\ping.dm"
|
||||
#include "code\controllers\subsystem\points_of_interest.dm"
|
||||
#include "code\controllers\subsystem\profiler.dm"
|
||||
#include "code\controllers\subsystem\radiation.dm"
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
export const CONNECTION_LOST_AFTER = 15000;
|
||||
export const CONNECTION_LOST_AFTER = 20000;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { pingSuccess } from '../ping/actions';
|
||||
import { pingSoft, pingSuccess } from '../ping/actions';
|
||||
import { connectionLost, connectionRestored, roundRestarted } from './actions';
|
||||
import { selectGame } from './selectors';
|
||||
import { CONNECTION_LOST_AFTER } from './constants';
|
||||
@@ -19,6 +19,7 @@ const withTimestamp = action => ({
|
||||
|
||||
export const gameMiddleware = store => {
|
||||
let lastPingedAt;
|
||||
|
||||
setInterval(() => {
|
||||
const state = store.getState();
|
||||
if (!state) {
|
||||
@@ -34,15 +35,19 @@ export const gameMiddleware = store => {
|
||||
store.dispatch(withTimestamp(connectionRestored()));
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
return next => action => {
|
||||
const { type, payload, meta } = action;
|
||||
if (type === pingSuccess.type) {
|
||||
lastPingedAt = meta.now;
|
||||
const { type } = action;
|
||||
|
||||
if (type === pingSuccess.type || type === pingSoft.type) {
|
||||
lastPingedAt = Date.now();
|
||||
return next(action);
|
||||
}
|
||||
|
||||
if (type === roundRestarted.type) {
|
||||
return next(withTimestamp(action));
|
||||
}
|
||||
|
||||
return next(action);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -6,20 +6,20 @@
|
||||
|
||||
import { createAction } from 'common/redux';
|
||||
|
||||
export const pingSuccess = createAction(
|
||||
'ping/success',
|
||||
ping => {
|
||||
const now = Date.now();
|
||||
const roundtrip = (now - ping.sentAt) * 0.5;
|
||||
return {
|
||||
payload: {
|
||||
lastId: ping.id,
|
||||
roundtrip,
|
||||
},
|
||||
meta: { now },
|
||||
};
|
||||
}
|
||||
);
|
||||
export const pingReply = createAction('ping/reply');
|
||||
|
||||
/**
|
||||
* Soft ping from the server.
|
||||
* It's intended to send periodic server-side metadata about the client,
|
||||
* e.g. its AFK status.
|
||||
*/
|
||||
export const pingSoft = createAction('ping/soft');
|
||||
|
||||
export const pingSuccess = createAction('ping/success', (ping) => ({
|
||||
payload: {
|
||||
lastId: ping.id,
|
||||
roundtrip: (Date.now() - ping.sentAt) * 0.5,
|
||||
},
|
||||
}));
|
||||
|
||||
export const pingFail = createAction('ping/fail');
|
||||
export const pingReply = createAction('ping/reply');
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
export const PING_INTERVAL = 2500;
|
||||
export const PING_TIMEOUT = 2000;
|
||||
export const PING_MAX_FAILS = 3;
|
||||
export const PING_QUEUE_SIZE = 8;
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { pingFail, pingSuccess } from './actions';
|
||||
import { PING_INTERVAL, PING_QUEUE_SIZE, PING_TIMEOUT } from './constants';
|
||||
import { pingFail, pingReply, pingSoft, pingSuccess } from './actions';
|
||||
import { PING_QUEUE_SIZE, PING_TIMEOUT } from './constants';
|
||||
|
||||
export const pingMiddleware = store => {
|
||||
let initialized = false;
|
||||
let index = 0;
|
||||
let interval;
|
||||
const pings = [];
|
||||
|
||||
const sendPing = () => {
|
||||
for (let i = 0; i < PING_QUEUE_SIZE; i++) {
|
||||
const ping = pings[i];
|
||||
@@ -25,20 +25,26 @@ export const pingMiddleware = store => {
|
||||
Byond.sendMessage('ping', { index });
|
||||
index = (index + 1) % PING_QUEUE_SIZE;
|
||||
};
|
||||
|
||||
return next => action => {
|
||||
const { type, payload } = action;
|
||||
|
||||
if (!initialized) {
|
||||
initialized = true;
|
||||
interval = setInterval(sendPing, PING_INTERVAL);
|
||||
sendPing();
|
||||
}
|
||||
if (type === 'roundrestart') {
|
||||
// Stop pinging because dreamseeker is currently reconnecting.
|
||||
// Topic calls in the middle of reconnect will crash the connection.
|
||||
clearInterval(interval);
|
||||
|
||||
if (type === pingSoft.type) {
|
||||
const { afk } = payload;
|
||||
// On each soft ping where client is not flagged as afk,
|
||||
// initiate a new ping.
|
||||
if (!afk) {
|
||||
sendPing();
|
||||
}
|
||||
return next(action);
|
||||
}
|
||||
if (type === 'pingReply') {
|
||||
|
||||
if (type === pingReply.type) {
|
||||
const { index } = payload;
|
||||
const ping = pings[index];
|
||||
// Received a timed out ping
|
||||
@@ -48,6 +54,7 @@ export const pingMiddleware = store => {
|
||||
pings[index] = null;
|
||||
return next(pingSuccess(ping));
|
||||
}
|
||||
|
||||
return next(action);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -10,6 +10,7 @@ import { PING_MAX_FAILS, PING_ROUNDTRIP_BEST, PING_ROUNDTRIP_WORST } from './con
|
||||
|
||||
export const pingReducer = (state = {}, action) => {
|
||||
const { type, payload } = action;
|
||||
|
||||
if (type === pingSuccess.type) {
|
||||
const { roundtrip } = payload;
|
||||
const prevRoundtrip = state.roundtripAvg || roundtrip;
|
||||
@@ -23,6 +24,7 @@ export const pingReducer = (state = {}, action) => {
|
||||
networkQuality,
|
||||
};
|
||||
}
|
||||
|
||||
if (type === pingFail.type) {
|
||||
const { failCount = 0 } = state;
|
||||
const networkQuality = clamp01(state.networkQuality
|
||||
@@ -38,5 +40,6 @@ export const pingReducer = (state = {}, action) => {
|
||||
}
|
||||
return nextState;
|
||||
}
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
@@ -134,7 +134,7 @@ export const backendMiddleware = store => {
|
||||
}
|
||||
|
||||
if (type === 'ping') {
|
||||
Byond.sendMessage('pingReply');
|
||||
Byond.sendMessage('ping/reply');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user