From 95742ef7f4a1bb48c65bcb69d97e271d69ac8a0c Mon Sep 17 00:00:00 2001 From: Gboster-0 <82319946+Gboster-0@users.noreply.github.com> Date: Fri, 3 May 2024 18:28:11 +0200 Subject: [PATCH] You should AFK yourself... NOW -- Ports soft-ping fixes from TG, AKF players kicked from lobby, SSD indicators (#2049) * tgui-panel: Soft ping (#66299) * tgui-panel: Soft ping * ports sex code * why are you like this linters * GOD DAMMIT SKYRAT, STOP MAKING ME BEND OVER * brings up up-to-date with ERP code * le fix * missed this one https://github.com/Skyrat-SS13/Skyrat-tg/pull/1678 --------- Co-authored-by: Aleksej Komarov Co-authored-by: Kirie Saito <77302679+Kitsunemitsu@users.noreply.github.com> --- ModularTegustation/ssd_indicator/code/mob.dm | 29 ++++++++ .../ssd_indicator/icons/ssd_indicator.dmi | Bin 0 -> 311 bytes ModularTegustation/ssd_indicator/readme.md | 28 ++++++++ code/__DEFINES/subsystems.dm | 63 +++++++++--------- code/controllers/subsystem/ping.dm | 39 +++++++++++ code/game/machinery/cryopod.dm | 6 ++ code/modules/client/client_procs.dm | 1 + .../mob/living/carbon/human/examine.dm | 3 +- code/modules/mob/living/death.dm | 2 + code/modules/tgui/tgui.dm | 2 +- code/modules/tgui/tgui_window.dm | 2 +- lobotomy-corp13.dme | 2 + tgui/packages/tgui-panel/game/constants.js | 2 +- tgui/packages/tgui-panel/game/middleware.js | 13 ++-- tgui/packages/tgui-panel/ping/actions.js | 30 ++++----- tgui/packages/tgui-panel/ping/constants.js | 1 - tgui/packages/tgui-panel/ping/middleware.js | 25 ++++--- tgui/packages/tgui-panel/ping/reducer.js | 3 + tgui/packages/tgui/backend.js | 2 +- 19 files changed, 188 insertions(+), 65 deletions(-) create mode 100644 ModularTegustation/ssd_indicator/code/mob.dm create mode 100644 ModularTegustation/ssd_indicator/icons/ssd_indicator.dmi create mode 100644 ModularTegustation/ssd_indicator/readme.md create mode 100644 code/controllers/subsystem/ping.dm diff --git a/ModularTegustation/ssd_indicator/code/mob.dm b/ModularTegustation/ssd_indicator/code/mob.dm new file mode 100644 index 000000000000..c4c88b257e17 --- /dev/null +++ b/ModularTegustation/ssd_indicator/code/mob.dm @@ -0,0 +1,29 @@ +GLOBAL_VAR_INIT(ssd_indicator_overlay, mutable_appearance('ModularTegustation/ssd_indicator/icons/ssd_indicator.dmi', "default0", FLY_LAYER)) + +/mob/living + var/ssd_indicator = FALSE + var/lastclienttime = 0 + +/mob/living/proc/set_ssd_indicator(state) + if(state == ssd_indicator) + return + ssd_indicator = state + if(ssd_indicator) + add_overlay(GLOB.ssd_indicator_overlay) + log_message("has went SSD and got their indicator!", INDIVIDUAL_ATTACK_LOG) + else + cut_overlay(GLOB.ssd_indicator_overlay) + log_message("is no longer SSD and lost their indicator!", INDIVIDUAL_ATTACK_LOG) + +/mob/living/Login() + . = ..() + set_ssd_indicator(FALSE) + +/mob/living/Logout() + lastclienttime = world.time + set_ssd_indicator(TRUE) + . = ..() + +/mob/living/ghostize(can_reenter_corpse = TRUE) + . = ..() + set_ssd_indicator(FALSE) diff --git a/ModularTegustation/ssd_indicator/icons/ssd_indicator.dmi b/ModularTegustation/ssd_indicator/icons/ssd_indicator.dmi new file mode 100644 index 0000000000000000000000000000000000000000..3f7d100b6c67e725055ef21a964cbcbb113dca6c GIT binary patch literal 311 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJ{HliLl8Vm$j4_H-qwSRlG-d9=Bb7470iYcT0gf&&Q+`DHA9k#g1nzrpr!Ksf{3onM7 zt~9UWyzn9_sPVDb6Mr#vp58;BU%iWc)ikAF(|NJtR<-gE?}Z*GC8T-FPfC$i=+qJG z0$Sbd>Eaj?(fam^A>RQ74%UGE9|QLOf3o&PfT5_*@}|@3hKi<|{#~sdQzl#Xud3cD(Xnp937P3qET zuudpu*edNf;oHvH1)_z&{9m+BU|`} /mob/living/carbon/human/examine() + ./code/modules/mob/living/death.dm > /mob/living/proc/death(gibbed) + +### Defines: + + - N/A + +### Master file additions + +- N/A + +### Included files that are not contained in this module: + +- N/A + +### Credits: +Azarak - original code & porting +Gboster - Porting it into LC13 diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index be40e3d71cdf..24eb294a075b 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -152,37 +152,38 @@ // 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_IDLE_NPC 10 -#define FIRE_PRIORITY_SERVER_MAINT 10 -#define FIRE_PRIORITY_RESEARCH 10 -#define FIRE_PRIORITY_VIS 10 -#define FIRE_PRIORITY_GARBAGE 15 -#define FIRE_PRIORITY_WET_FLOORS 20 -#define FIRE_PRIORITY_AIR 20 -#define FIRE_PRIORITY_NPC 20 -#define FIRE_PRIORITY_PROCESS 25 -#define FIRE_PRIORITY_THROWING 25 -#define FIRE_PRIORITY_SPACEDRIFT 30 -#define FIRE_PRIORITY_FIELDS 30 -#define FIRE_PRIOTITY_SMOOTHING 35 -#define FIRE_PRIORITY_NETWORKS 40 -#define FIRE_PRIORITY_OBJ 40 -#define FIRE_PRIORITY_ACID 40 -#define FIRE_PRIOTITY_BURNING 40 -#define FIRE_PRIORITY_DEFAULT 50 -#define FIRE_PRIORITY_PARALLAX 65 -#define FIRE_PRIORITY_INSTRUMENTS 80 -#define FIRE_PRIORITY_MOBS 100 -#define FIRE_PRIORITY_TGUI 110 -#define FIRE_PRIORITY_TICKER 200 -#define FIRE_PRIORITY_ATMOS_ADJACENCY 300 -#define FIRE_PRIORITY_STATPANEL 390 -#define FIRE_PRIORITY_CHAT 400 -#define FIRE_PRIORITY_RUNECHAT 410 -#define FIRE_PRIORITY_OVERLAYS 500 -#define FIRE_PRIORITY_EXPLOSIONS 666 -#define FIRE_PRIORITY_TIMER 700 -#define FIRE_PRIORITY_INPUT 1000 // This must always always be the max highest priority. Player input must never be lost. +#define FIRE_PRIORITY_PING 10 +#define FIRE_PRIORITY_IDLE_NPC 10 +#define FIRE_PRIORITY_SERVER_MAINT 10 +#define FIRE_PRIORITY_RESEARCH 10 +#define FIRE_PRIORITY_VIS 10 +#define FIRE_PRIORITY_GARBAGE 15 +#define FIRE_PRIORITY_WET_FLOORS 20 +#define FIRE_PRIORITY_AIR 20 +#define FIRE_PRIORITY_NPC 20 +#define FIRE_PRIORITY_PROCESS 25 +#define FIRE_PRIORITY_THROWING 25 +#define FIRE_PRIORITY_SPACEDRIFT 30 +#define FIRE_PRIORITY_FIELDS 30 +#define FIRE_PRIOTITY_SMOOTHING 35 +#define FIRE_PRIORITY_NETWORKS 40 +#define FIRE_PRIORITY_OBJ 40 +#define FIRE_PRIORITY_ACID 40 +#define FIRE_PRIOTITY_BURNING 40 +#define FIRE_PRIORITY_DEFAULT 50 +#define FIRE_PRIORITY_PARALLAX 65 +#define FIRE_PRIORITY_INSTRUMENTS 80 +#define FIRE_PRIORITY_MOBS 100 +#define FIRE_PRIORITY_TGUI 110 +#define FIRE_PRIORITY_TICKER 200 +#define FIRE_PRIORITY_ATMOS_ADJACENCY 300 +#define FIRE_PRIORITY_STATPANEL 390 +#define FIRE_PRIORITY_CHAT 400 +#define FIRE_PRIORITY_RUNECHAT 410 +#define FIRE_PRIORITY_OVERLAYS 500 +#define FIRE_PRIORITY_EXPLOSIONS 666 +#define FIRE_PRIORITY_TIMER 700 +#define FIRE_PRIORITY_INPUT 1000 // This must always always be the max highest priority. Player input must never be lost. // SS runlevels diff --git a/code/controllers/subsystem/ping.dm b/code/controllers/subsystem/ping.dm new file mode 100644 index 000000000000..78669c987ea9 --- /dev/null +++ b/code/controllers/subsystem/ping.dm @@ -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 diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index ef3143520a7e..6e73c1e6a17c 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -83,6 +83,8 @@ GLOBAL_LIST_EMPTY(cryopod_computers) var/on_store_message = "has entered long-term storage." var/on_store_name = "Cryogenic Oversight" + /// The minimum time someone needs to be SSD in order to be cryo'd by another person + var/minimum_ssd_time = 10 MINUTES /// Time until despawn when a mob enters a cryopod. You cannot other people in pods unless they're catatonic. var/time_till_despawn = 30 SECONDS /// Cooldown for when it's now safe to try an despawn the player. @@ -284,6 +286,10 @@ GLOBAL_LIST_EMPTY(cryopod_computers) if(target == user && (tgalert(target, "Would you like to enter cryosleep?", "Enter Cryopod?", "Yes", "No") != "Yes")) return + if(user != target && round(((world.time - target.lastclienttime) / (1 MINUTES)),1) <= minimum_ssd_time) + to_chat(user, span_danger("You can't put [target] into [src]. They might wake up soon.")) + return + if(target == user) var/datum/antagonist/antag = target.mind.has_antag_datum(/datum/antagonist) diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 27d1ea51ca63..a442fcdfdf40 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -499,6 +499,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( UNSETEMPTY(movingmob.client_mobs_in_contents) movingmob = null active_mousedown_item = null + SSping.currentrun -= src QDEL_NULL(view_size) QDEL_NULL(void) QDEL_NULL(tooltips) diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 637236f6e556..c05c72df14f5 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -365,7 +365,8 @@ if(!ghost || !ghost.client) msg += "[t_He] [t_is] totally catatonic. The stresses of life in deep-space must have been too much for [t_him]. Any recovery is unlikely.\n" else if(!client) - msg += "[t_He] [t_has] a blank, absent-minded stare and appears completely unresponsive to anything. [t_He] may snap out of it soon.\n" +// msg += "[t_He] [t_has] a blank, absent-minded stare and appears completely unresponsive to anything. [t_He] may snap out of it soon.\n" // LOBOTOMYCORPORATION EDIT OLD + msg += "[t_He] [t_has] a blank, absent-minded stare and [t_has] been completely unresponsive to anything for [round(((world.time - lastclienttime) / (1 MINUTES)),1)] minutes. [t_He] may snap out of it soon.\n" // LOBOTOMYCORPORATION EDIT NEW var/scar_severity = 0 for(var/i in all_scars) diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm index 3372a9de84ed..29d95e2a62cc 100644 --- a/code/modules/mob/living/death.dm +++ b/code/modules/mob/living/death.dm @@ -90,6 +90,8 @@ med_hud_set_status() stop_pulling() + set_ssd_indicator(FALSE) //LOBOTOMYCORPORATION ADDITION -- SSD INDICATOR + SEND_SIGNAL(src, COMSIG_LIVING_DEATH, gibbed) SEND_GLOBAL_SIGNAL(COMSIG_GLOB_MOB_DEATH, src, gibbed) diff --git a/code/modules/tgui/tgui.dm b/code/modules/tgui/tgui.dm index b99783f67ade..5438189c7520 100644 --- a/code/modules/tgui/tgui.dm +++ b/code/modules/tgui/tgui.dm @@ -297,7 +297,7 @@ switch(type) if("ready") initialized = TRUE - if("pingReply") + if("ping/reply") initialized = TRUE if("suspend") close(can_be_suspended = TRUE) diff --git a/code/modules/tgui/tgui_window.dm b/code/modules/tgui/tgui_window.dm index ae54b2dd3fca..e1763c9e1b10 100644 --- a/code/modules/tgui/tgui_window.dm +++ b/code/modules/tgui/tgui_window.dm @@ -308,7 +308,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") diff --git a/lobotomy-corp13.dme b/lobotomy-corp13.dme index 77bac1e1e835..8bff7373dcd1 100644 --- a/lobotomy-corp13.dme +++ b/lobotomy-corp13.dme @@ -339,6 +339,7 @@ #include "code\controllers\subsystem\parallax.dm" #include "code\controllers\subsystem\pathfinder.dm" #include "code\controllers\subsystem\persistence.dm" +#include "code\controllers\subsystem\ping.dm" #include "code\controllers\subsystem\profiler.dm" #include "code\controllers\subsystem\radiation.dm" #include "code\controllers\subsystem\radio.dm" @@ -3989,6 +3990,7 @@ #include "ModularTegustation\fishing\code\rod_components\fishing_lines.dm" #include "ModularTegustation\living\living.dm" #include "ModularTegustation\living\carbon\life.dm" +#include "ModularTegustation\ssd_indicator\code\mob.dm" #include "ModularTegustation\primitive_farming\farming_structures.dm" #include "ModularTegustation\tegu_borg_code\cyborg_upgrades.dm" #include "ModularTegustation\tegu_borg_code\medborg_holobed.dm" diff --git a/tgui/packages/tgui-panel/game/constants.js b/tgui/packages/tgui-panel/game/constants.js index 9df3a58d2946..f40a529a101a 100644 --- a/tgui/packages/tgui-panel/game/constants.js +++ b/tgui/packages/tgui-panel/game/constants.js @@ -4,4 +4,4 @@ * @license MIT */ -export const CONNECTION_LOST_AFTER = 15000; +export const CONNECTION_LOST_AFTER = 20000; diff --git a/tgui/packages/tgui-panel/game/middleware.js b/tgui/packages/tgui-panel/game/middleware.js index 854369dc54ea..ba1ec63f9ec5 100644 --- a/tgui/packages/tgui-panel/game/middleware.js +++ b/tgui/packages/tgui-panel/game/middleware.js @@ -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); }; }; diff --git a/tgui/packages/tgui-panel/ping/actions.js b/tgui/packages/tgui-panel/ping/actions.js index ba3582f131cd..08498a96dc16 100644 --- a/tgui/packages/tgui-panel/ping/actions.js +++ b/tgui/packages/tgui-panel/ping/actions.js @@ -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'); diff --git a/tgui/packages/tgui-panel/ping/constants.js b/tgui/packages/tgui-panel/ping/constants.js index 5d9a0472c5f1..54fd42fcd7fb 100644 --- a/tgui/packages/tgui-panel/ping/constants.js +++ b/tgui/packages/tgui-panel/ping/constants.js @@ -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; diff --git a/tgui/packages/tgui-panel/ping/middleware.js b/tgui/packages/tgui-panel/ping/middleware.js index b7d8e25a7672..5815ac2296d2 100644 --- a/tgui/packages/tgui-panel/ping/middleware.js +++ b/tgui/packages/tgui-panel/ping/middleware.js @@ -5,14 +5,14 @@ */ import { sendMessage } from 'tgui/backend'; -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]; @@ -29,20 +29,26 @@ export const pingMiddleware = store => { }); 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 @@ -52,6 +58,7 @@ export const pingMiddleware = store => { pings[index] = null; return next(pingSuccess(ping)); } + return next(action); }; }; diff --git a/tgui/packages/tgui-panel/ping/reducer.js b/tgui/packages/tgui-panel/ping/reducer.js index 22d146f8b815..874cb75a9b8d 100644 --- a/tgui/packages/tgui-panel/ping/reducer.js +++ b/tgui/packages/tgui-panel/ping/reducer.js @@ -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; }; diff --git a/tgui/packages/tgui/backend.js b/tgui/packages/tgui/backend.js index 06f45ad55e84..0cec05739943 100644 --- a/tgui/packages/tgui/backend.js +++ b/tgui/packages/tgui/backend.js @@ -144,7 +144,7 @@ export const backendMiddleware = store => { if (type === 'ping') { sendMessage({ - type: 'pingReply', + type: 'ping/reply', }); return; }