diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm index 3acd1443af..c6be8318fd 100644 --- a/code/__DEFINES/admin.dm +++ b/code/__DEFINES/admin.dm @@ -87,5 +87,5 @@ #define MAX_KEYPRESS_COMMANDLENGTH 16 ///Max amount of keypress messages per second over two seconds before client is autokicked #define MAX_KEYPRESS_AUTOKICK 100 -///Length of held key rolling buffer -#define HELD_KEY_BUFFER_LENGTH 15 +///Length of max held keys +#define MAX_HELD_KEYS 15 diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm index 2a59558bcd..52d2fe45cd 100644 --- a/code/controllers/subsystem/air.dm +++ b/code/controllers/subsystem/air.dm @@ -239,7 +239,6 @@ SUBSYSTEM_DEF(air) if (MC_TICK_CHECK) return - /datum/controller/subsystem/air/proc/remove_from_active(turf/open/T) active_turfs -= T SSair_turfs.currentrun -= T @@ -257,7 +256,7 @@ SUBSYSTEM_DEF(air) #ifdef VISUALIZE_ACTIVE_TURFS T.add_atom_colour("#00ff00", TEMPORARY_COLOUR_PRIORITY) #endif - T.excited = 1 + T.excited = TRUE active_turfs |= T SSair_turfs.currentrun |= T if(blockchanges && T.excited_group) diff --git a/code/controllers/subsystem/air_turfs.dm b/code/controllers/subsystem/air_turfs.dm index 2902940bf9..9dd41aede5 100644 --- a/code/controllers/subsystem/air_turfs.dm +++ b/code/controllers/subsystem/air_turfs.dm @@ -11,7 +11,6 @@ SUBSYSTEM_DEF(air_turfs) /datum/controller/subsystem/air_turfs/fire(resumed = 0) var/fire_count = times_fired - //cache for sanic speed if (!resumed) src.currentrun = SSair.active_turfs.Copy() //cache for sanic speed (lists are references anyways) diff --git a/code/controllers/subsystem/fail2topic.dm b/code/controllers/subsystem/fail2topic.dm index d17cce70f9..b358cc2c5f 100644 --- a/code/controllers/subsystem/fail2topic.dm +++ b/code/controllers/subsystem/fail2topic.dm @@ -34,7 +34,6 @@ SUBSYSTEM_DEF(fail2topic) for(var/i in 1 to length(rate_limiting)) var/ip = rate_limiting[i] var/last_attempt = rate_limiting[ip] - if (world.time - last_attempt > rate_limit) rate_limiting -= ip fail_counts -= ip diff --git a/code/controllers/subsystem/input.dm b/code/controllers/subsystem/input.dm index cc09ca816e..0970b23a16 100644 --- a/code/controllers/subsystem/input.dm +++ b/code/controllers/subsystem/input.dm @@ -114,6 +114,6 @@ SUBSYSTEM_DEF(input) /datum/controller/subsystem/input/fire() var/list/clients = GLOB.clients // Let's sing the list cache song - for(var/i in 1 to clients.len) + for(var/i in 1 to length(clients)) var/client/C = clients[i] C.keyLoop() diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index 8c8ad2d337..4850a67646 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -37,6 +37,8 @@ SUBSYSTEM_DEF(mapping) var/datum/space_level/empty_space var/num_of_res_levels = 1 + var/stat_map_name = "Loading..." + //dlete dis once #39770 is resolved /datum/controller/subsystem/mapping/proc/HACK_LoadMapConfig() if(!config) @@ -45,6 +47,7 @@ SUBSYSTEM_DEF(mapping) #else config = load_map_config(error_if_missing = FALSE) #endif + stat_map_name = config.map_name /datum/controller/subsystem/mapping/Initialize(timeofday) HACK_LoadMapConfig() @@ -330,7 +333,10 @@ GLOBAL_LIST_EMPTY(the_station_areas) return next_map_config = VM - return TRUE + + . = TRUE + + stat_map_name = "[config.map_name] (Next: [next_map_config.map_name])" /datum/controller/subsystem/mapping/proc/preloadTemplates(path = "_maps/templates/") //see master controller setup var/list/filelist = flist(path) diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm index b406a8ccad..4d9eefae5b 100644 --- a/code/controllers/subsystem/shuttle.dm +++ b/code/controllers/subsystem/shuttle.dm @@ -30,6 +30,7 @@ SUBSYSTEM_DEF(shuttle) var/list/hostileEnvironments = list() //Things blocking escape shuttle from leaving var/list/tradeBlockade = list() //Things blocking cargo from leaving. var/supplyBlocked = FALSE + var/emergency_shuttle_stat_text //supply shuttle stuff var/obj/docking_port/mobile/supply/supply @@ -118,6 +119,9 @@ SUBSYSTEM_DEF(shuttle) points += point_gain //Cargo stuff end + var/esETA = emergency?.getModeStr() + emergency_shuttle_stat_text = "[esETA? "[esETA] [emergency.getTimerStr()]" : ""]" + if(!SSmapping.clearing_reserved_turfs) while(transit_requesters.len) var/requester = popleft(transit_requesters) diff --git a/code/controllers/subsystem/time_track.dm b/code/controllers/subsystem/time_track.dm index 3b19ae31cd..779b186d08 100644 --- a/code/controllers/subsystem/time_track.dm +++ b/code/controllers/subsystem/time_track.dm @@ -1,6 +1,6 @@ SUBSYSTEM_DEF(time_track) name = "Time Tracking" - wait = 600 + wait = 1 SECONDS flags = SS_NO_INIT|SS_NO_TICK_CHECK runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT @@ -16,23 +16,33 @@ SUBSYSTEM_DEF(time_track) var/last_tick_byond_time = 0 var/last_tick_tickcount = 0 + var/last_measurement = 0 + var/measurement_delay = 60 + + var/stat_time_text + var/time_dilation_text + /datum/controller/subsystem/time_track/fire() + stat_time_text = "Server Time: [time2text(world.timeofday, "YYYY-MM-DD hh:mm:ss")]\n\nRound Time: [WORLDTIME2TEXT("hh:mm:ss")]\n\nStation Time: [STATION_TIME_TIMESTAMP("hh:mm:ss")]\n\n[time_dilation_text]" - var/current_realtime = REALTIMEOFDAY - var/current_byondtime = world.time - var/current_tickcount = world.time/world.tick_lag + if(++last_measurement == measurement_delay) + last_measurement = 0 + var/current_realtime = REALTIMEOFDAY + var/current_byondtime = world.time + var/current_tickcount = world.time/world.tick_lag - if (!first_run) - var/tick_drift = max(0, (((current_realtime - last_tick_realtime) - (current_byondtime - last_tick_byond_time)) / world.tick_lag)) + if (!first_run) + var/tick_drift = max(0, (((current_realtime - last_tick_realtime) - (current_byondtime - last_tick_byond_time)) / world.tick_lag)) - time_dilation_current = tick_drift / (current_tickcount - last_tick_tickcount) * 100 + time_dilation_current = tick_drift / (current_tickcount - last_tick_tickcount) * 100 - time_dilation_avg_fast = MC_AVERAGE_FAST(time_dilation_avg_fast, time_dilation_current) - time_dilation_avg = MC_AVERAGE(time_dilation_avg, time_dilation_avg_fast) - time_dilation_avg_slow = MC_AVERAGE_SLOW(time_dilation_avg_slow, time_dilation_avg) - else - first_run = FALSE - last_tick_realtime = current_realtime - last_tick_byond_time = current_byondtime - last_tick_tickcount = current_tickcount - SSblackbox.record_feedback("associative", "time_dilation_current", 1, list("[SQLtime()]" = list("current" = "[time_dilation_current]", "avg_fast" = "[time_dilation_avg_fast]", "avg" = "[time_dilation_avg]", "avg_slow" = "[time_dilation_avg_slow]"))) + time_dilation_avg_fast = MC_AVERAGE_FAST(time_dilation_avg_fast, time_dilation_current) + time_dilation_avg = MC_AVERAGE(time_dilation_avg, time_dilation_avg_fast) + time_dilation_avg_slow = MC_AVERAGE_SLOW(time_dilation_avg_slow, time_dilation_avg) + else + first_run = FALSE + last_tick_realtime = current_realtime + last_tick_byond_time = current_byondtime + last_tick_tickcount = current_tickcount + SSblackbox.record_feedback("associative", "time_dilation_current", 1, list("[SQLtime()]" = list("current" = "[time_dilation_current]", "avg_fast" = "[time_dilation_avg_fast]", "avg" = "[time_dilation_avg]", "avg_slow" = "[time_dilation_avg_slow]"))) + time_dilation_text = "Time Dilation: [round(time_dilation_current,1)]% AVG:([round(time_dilation_avg_fast,1)]%, [round(time_dilation_avg,1)]%, [round(time_dilation_avg_slow,1)]%)" diff --git a/code/modules/client/verbs/ping.dm b/code/modules/client/verbs/ping.dm index de19d0d52c..02c5b5a7fd 100644 --- a/code/modules/client/verbs/ping.dm +++ b/code/modules/client/verbs/ping.dm @@ -14,9 +14,9 @@ /client/verb/display_ping(time as num) set instant = TRUE set name = ".display_ping" - to_chat(src, "Round trip ping took [round(pingfromtime(time),1)]ms") + to_chat(src, "Round trip ping took [round(pingfromtime(time),1)]ms (Avg: [round(avgping, 1)]ms])") /client/verb/ping() set name = "Ping" set category = "OOC" - winset(src, null, "command=.display_ping+[world.time+world.tick_lag*TICK_USAGE_REAL/100]") \ No newline at end of file + winset(src, null, "command=.display_ping+[world.time+world.tick_lag*TICK_USAGE_REAL/100]") diff --git a/code/modules/keybindings/bindings_atom.dm b/code/modules/keybindings/bindings_atom.dm index 4aac76bd67..5f3e879237 100644 --- a/code/modules/keybindings/bindings_atom.dm +++ b/code/modules/keybindings/bindings_atom.dm @@ -15,4 +15,4 @@ movement_dir &= ~(NORTH|SOUTH) if((movement_dir & EAST) && (movement_dir & WEST)) movement_dir &= ~(EAST|WEST) - user.Move(get_step(src, movement_dir), movement_dir) \ No newline at end of file + user.Move(get_step(src, movement_dir), movement_dir) diff --git a/code/modules/keybindings/bindings_client.dm b/code/modules/keybindings/bindings_client.dm index dec5c25eb9..6030362a61 100644 --- a/code/modules/keybindings/bindings_client.dm +++ b/code/modules/keybindings/bindings_client.dm @@ -5,7 +5,7 @@ set hidden = TRUE client_keysend_amount += 1 - + var/cache = client_keysend_amount if(keysend_tripped && next_keysend_trip_reset <= world.time) @@ -20,7 +20,7 @@ //don't want to kick people if a lag spike results in a huge flood of commands being sent if(cache >= MAX_KEYPRESS_AUTOKICK) if(!keysend_tripped) - keysend_tripped = TRUE + keysend_tripped = TRUE next_keysend_trip_reset = world.time + (2 SECONDS) else log_admin("Client [ckey] was just autokicked for flooding keysends; likely abuse but potentially lagspike.") @@ -35,11 +35,10 @@ message_admins("Client [ckey] just attempted to send an invalid keypress. Keymessage was over [MAX_KEYPRESS_COMMANDLENGTH] characters, autokicking due to likely abuse.") QDEL_IN(src, 1) return - //offset by 1 because the buffer address is 0 indexed because the math was simpler - keys_held[current_key_address + 1] = _key - //the time a key was pressed isn't actually used anywhere (as of 2019-9-10) but this allows easier access usage/checking - keys_held[_key] = world.time - current_key_address = ((current_key_address + 1) % HELD_KEY_BUFFER_LENGTH) + + if(length(keys_held) > MAX_HELD_KEYS) + keys_held.Cut(1,2) + keys_held[_key] = TRUE var/movement = SSinput.movement_keys[_key] if(!(next_move_dir_sub & movement) && !keys_held["Ctrl"]) next_move_dir_add |= movement @@ -70,11 +69,7 @@ set instant = TRUE set hidden = TRUE - //Can't just do a remove because it would alter the length of the rolling buffer, instead search for the key then null it out if it exists - for(var/i in 1 to HELD_KEY_BUFFER_LENGTH) - if(keys_held[i] == _key) - keys_held[i] = null - break + keys_held -= _key var/movement = SSinput.movement_keys[_key] if(!(next_move_dir_add & movement)) next_move_dir_sub |= movement diff --git a/code/modules/keybindings/setup.dm b/code/modules/keybindings/setup.dm index 8433c9bf5a..9a13bfb11c 100644 --- a/code/modules/keybindings/setup.dm +++ b/code/modules/keybindings/setup.dm @@ -1,8 +1,6 @@ /client - /// A rolling buffer of any keys held currently + /// Keys currently held var/list/keys_held = list() - ///used to keep track of the current rolling buffer position - var/current_key_address = 0 /// These next two vars are to apply movement for keypresses and releases made while move delayed. /// Because discarding that input makes the game less responsive. /// On next move, add this dir to the move that would otherwise be done @@ -36,10 +34,7 @@ /client/proc/set_macros() set waitfor = FALSE - //Reset and populate the rolling buffer keys_held.Cut() - for(var/i in 1 to HELD_KEY_BUFFER_LENGTH) - keys_held += null erase_all_macros() diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 33cc2c6e20..333a7826d2 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -571,29 +571,23 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0) M.show_inv(user) /mob/proc/is_muzzled() - return 0 + return FALSE /mob/Stat() ..() - if(statpanel("Status")) - if (client) - stat(null, "Ping: [round(client.lastping, 1)]ms (Average: [round(client.avgping, 1)]ms)") - stat(null, "Map: [SSmapping.config?.map_name || "Loading..."]") - var/datum/map_config/cached = SSmapping.next_map_config - if(cached) - stat(null, "Next Map: [cached.map_name]") - stat(null, "Round ID: [GLOB.round_id ? GLOB.round_id : "NULL"]") - stat(null, "Server Time: [time2text(world.timeofday, "YYYY-MM-DD hh:mm:ss")]") - stat(null, "Round Time: [WORLDTIME2TEXT("hh:mm:ss")]") - stat(null, "Station Time: [STATION_TIME_TIMESTAMP("hh:mm:ss")]") - stat(null, "Time Dilation: [round(SStime_track.time_dilation_current,1)]% AVG:([round(SStime_track.time_dilation_avg_fast,1)]%, [round(SStime_track.time_dilation_avg,1)]%, [round(SStime_track.time_dilation_avg_slow,1)]%)") - if(SSshuttle.emergency) - var/ETA = SSshuttle.emergency.getModeStr() - if(ETA) - stat(null, "[ETA] [SSshuttle.emergency.getTimerStr()]") + //This is only called from client/Stat(), let's assume client exists. - if(client && client.holder) + if(statpanel("Status")) + var/list/L = list() + L += "Ping: [round(client.lastping,1)]ms (Avg: [round(client.avgping,1)]ms)" + L += SSmapping.stat_map_name + L += "Round ID: [GLOB.round_id || "NULL"]" + L += SStime_track.stat_time_text + L += SSshuttle.emergency_shuttle_stat_text + stat(null, "[L.Join("\n\n")]") + + if(client.holder) if(statpanel("MC")) var/turf/T = get_turf(client.eye) stat("Location:", COORD(T)) @@ -643,8 +637,6 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0) if(A.IsObscured()) continue statpanel(listed_turf.name, null, A) - - if(mind) add_spells_to_statpanel(mind.spell_list) var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling) diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index a1feb899c6..b11d1632c8 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -9,37 +9,36 @@ mob.dropItemToGround(mob.get_active_held_item()) return -/client/proc/Move_object(direct) +/client/proc/Move_object(direction) if(mob && mob.control_object) if(mob.control_object.density) - step(mob.control_object,direct) + step(mob.control_object,direction) if(!mob.control_object) return - mob.control_object.setDir(direct) + mob.control_object.setDir(direction) else - mob.control_object.forceMove(get_step(mob.control_object,direct)) + mob.control_object.forceMove(get_step(mob.control_object,direction)) #define MOVEMENT_DELAY_BUFFER 0.75 #define MOVEMENT_DELAY_BUFFER_DELTA 1.25 -/client/Move(n, direct) +/client/Move(n, direction) if(world.time < move_delay) //do not move anything ahead of this check please return FALSE else - next_move_dir_add = 0 - next_move_dir_sub = 0 + next_move_dir_add = next_move_dir_sub = NONE var/old_move_delay = move_delay move_delay = world.time + world.tick_lag //this is here because Move() can now be called mutiple times per tick - if(!mob || !mob.loc) - return FALSE - if(!n || !direct) + if(!n || !direction || !mob?.loc) return FALSE + //GET RID OF THIS SOON AS MOBILITY FLAGS IS DONE if(mob.notransform) - return FALSE //This is sota the goto stop mobs from moving var + return FALSE + if(mob.control_object) - return Move_object(direct) + return Move_object(direction) if(!isliving(mob)) - return mob.Move(n, direct) + return mob.Move(n, direction) if(mob.stat == DEAD) mob.ghostize() return FALSE @@ -48,29 +47,29 @@ var/mob/living/L = mob //Already checked for isliving earlier if(L.incorporeal_move) //Move though walls - Process_Incorpmove(direct) + Process_Incorpmove(direction) return FALSE if(mob.remote_control) //we're controlling something, our movement is relayed to it - return mob.remote_control.relaymove(mob, direct) + return mob.remote_control.relaymove(mob, direction) if(isAI(mob)) - return AIMove(n,direct,mob) + return AIMove(n,direction,mob) if(Process_Grab()) //are we restrained by someone's grip? return if(mob.buckled) //if we're buckled to something, tell it we moved. - return mob.buckled.relaymove(mob, direct) + return mob.buckled.relaymove(mob, direction) if(!mob.canmove) return FALSE if(isobj(mob.loc) || ismob(mob.loc)) //Inside an object, tell it we moved var/atom/O = mob.loc - return O.relaymove(mob, direct) + return O.relaymove(mob, direction) - if(!mob.Process_Spacemove(direct)) + if(!mob.Process_Spacemove(direction)) return FALSE //We are now going to move var/add_delay = mob.movement_delay() @@ -85,16 +84,16 @@ if(L.confused > 40) newdir = pick(GLOB.alldirs) else if(prob(L.confused * 1.5)) - newdir = angle2dir(dir2angle(direct) + pick(90, -90)) + newdir = angle2dir(dir2angle(direction) + pick(90, -90)) else if(prob(L.confused * 3)) - newdir = angle2dir(dir2angle(direct) + pick(45, -45)) + newdir = angle2dir(dir2angle(direction) + pick(45, -45)) if(newdir) - direct = newdir - n = get_step(L, direct) + direction = newdir + n = get_step(L, direction) . = ..() - if((direct & (direct - 1)) && mob.loc == n) //moved diagonally successfully + if((direction & (direction - 1)) && mob.loc == n) //moved diagonally successfully add_delay *= 2 move_delay += add_delay if(.) // If mob is null here, we deserve the runtime @@ -102,7 +101,7 @@ mob.throwing.finalize(FALSE) for(var/obj/O in mob.user_movement_hooks) - O.intercept_user_move(direct, mob, n, oldloc) + O.intercept_user_move(direction, mob, n, oldloc) var/atom/movable/P = mob.pulling if(P && !ismob(P) && P.density) @@ -126,22 +125,22 @@ ///Process_Incorpmove ///Called by client/Move() ///Allows mobs to run though walls -/client/proc/Process_Incorpmove(direct) +/client/proc/Process_Incorpmove(direction) var/turf/mobloc = get_turf(mob) if(!isliving(mob)) return var/mob/living/L = mob switch(L.incorporeal_move) if(INCORPOREAL_MOVE_BASIC) - var/T = get_step(L,direct) + var/T = get_step(L,direction) if(T) L.forceMove(T) - L.setDir(direct) + L.setDir(direction) if(INCORPOREAL_MOVE_SHADOW) if(prob(50)) var/locx var/locy - switch(direct) + switch(direction) if(NORTH) locx = mobloc.x locy = (mobloc.y+2) @@ -175,12 +174,12 @@ break else new /obj/effect/temp_visual/dir_setting/ninja/shadow(mobloc, L.dir) - var/T = get_step(L,direct) + var/T = get_step(L,direction) if(T) L.forceMove(T) - L.setDir(direct) + L.setDir(direction) if(INCORPOREAL_MOVE_JAUNT) //Incorporeal move, but blocked by holy-watered tiles and salt piles. - var/turf/open/floor/stepTurf = get_step(L, direct) + var/turf/open/floor/stepTurf = get_step(L, direction) if(stepTurf) for(var/obj/effect/decal/cleanable/salt/S in stepTurf) to_chat(L, "[S] bars your passage!") @@ -197,7 +196,7 @@ return L.forceMove(stepTurf) - L.setDir(direct) + L.setDir(direction) return TRUE