mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-25 05:51:56 +01:00
Lag War 2: Revengeance (#21950)
<img width="750" height="449" alt="image" src="https://github.com/user-attachments/assets/29c06609-eb62-42be-9b9c-334f9fe88636" /> Ports: tgstation/tgstation#75769, tgstation/tgstation#72572, tgstation/tgstation#93054 Fixes the holodeck causing 800 trillion hard dels that brings the server to its knees. Stops turrets, weather system, and overmap contacts from generating 500+ timers every tick by just using vars instead. --------- Signed-off-by: Wildkins <john.wildkins@gmail.com>
This commit is contained in:
@@ -203,6 +203,7 @@
|
||||
#include "code\__HELPERS\atoms.dm"
|
||||
#include "code\__HELPERS\data_structures.dm"
|
||||
#include "code\__HELPERS\dll_call.dm"
|
||||
#include "code\__HELPERS\duplicating.dm"
|
||||
#include "code\__HELPERS\emissives.dm"
|
||||
#include "code\__HELPERS\files.dm"
|
||||
#include "code\__HELPERS\functional.dm"
|
||||
|
||||
@@ -632,4 +632,4 @@
|
||||
/// Recharges from external lighting. Slower at recharging from external sources.
|
||||
#define POWER_SUPPLY_SOLAR 8
|
||||
|
||||
|
||||
#define WEATHER_COOLDOWN_TIME (5 SECONDS)
|
||||
|
||||
@@ -110,8 +110,7 @@
|
||||
|
||||
for (var/thing in ST)
|
||||
var/atom/movable/AM = thing
|
||||
var/atom/movable/copy = DuplicateObject(AM, 1)
|
||||
copy.forceMove(TT)
|
||||
var/atom/movable/copy = duplicate_object(AM, TT)
|
||||
. += copy
|
||||
|
||||
SSair.mark_for_update(TT)
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
///List of all vars that will not be copied over when using duplicate_object()
|
||||
GLOBAL_LIST_INIT(duplicate_forbidden_vars, list("actions",
|
||||
"_active_timers",
|
||||
"appearance",
|
||||
"area",
|
||||
"bodyparts",
|
||||
"ckey",
|
||||
"computer_id",
|
||||
"contents",
|
||||
"cooldowns",
|
||||
"_datum_components",
|
||||
"emissive_overlay",
|
||||
"group",
|
||||
"hud_list",
|
||||
"important_recursive_contents",
|
||||
"internal_organs",
|
||||
"internal_organs_by_name",
|
||||
"_listen_lookup",
|
||||
"organs",
|
||||
"organs_by_name",
|
||||
"key",
|
||||
"lastKnownIP",
|
||||
"loc",
|
||||
"locs",
|
||||
"overlays",
|
||||
"parent",
|
||||
"parent_type",
|
||||
"pixloc",
|
||||
"power_supply",
|
||||
"reagents",
|
||||
"_signal_procs",
|
||||
"status_traits",
|
||||
"stat",
|
||||
"tag",
|
||||
"tgui_shared_states",
|
||||
"type",
|
||||
"vars",
|
||||
"verbs",
|
||||
"x", "y", "z",
|
||||
))
|
||||
GLOBAL_PROTECT(duplicate_forbidden_vars)
|
||||
|
||||
/**
|
||||
* # duplicate_object
|
||||
*
|
||||
* Makes a copy of an item and transfers most vars over, barring GLOB.duplicate_forbidden_vars
|
||||
* Args:
|
||||
* original - Atom being duplicated
|
||||
* spawning_location - Turf where the duplicated atom will be spawned at.
|
||||
*/
|
||||
/proc/duplicate_object(atom/original, turf/spawning_location)
|
||||
RETURN_TYPE(original.type)
|
||||
if(!original)
|
||||
return
|
||||
|
||||
var/atom/made_copy = new original.type(spawning_location)
|
||||
|
||||
for(var/atom_vars in (original.vars - GLOB.duplicate_forbidden_vars))
|
||||
var/var_value = original.vars[atom_vars]
|
||||
if(isdatum(var_value))
|
||||
continue // this would reference the original's object, that will break when it is used or deleted.
|
||||
|
||||
if(islist(var_value))
|
||||
var/list/var_list = var_value
|
||||
var_value = var_list.Copy()
|
||||
|
||||
made_copy.vars[atom_vars] = var_value
|
||||
|
||||
if(!iscarbon(made_copy))
|
||||
return made_copy
|
||||
|
||||
var/mob/living/carbon/original_carbon = original
|
||||
var/mob/living/carbon/copied_carbon = made_copy
|
||||
var/obj/item/organ/internal/brain/original_brain = original_carbon.internal_organs_by_name[BP_BRAIN]
|
||||
original_brain.transfer_identity(copied_carbon)
|
||||
|
||||
if(!ishuman(made_copy))
|
||||
return made_copy
|
||||
|
||||
var/mob/living/carbon/human/original_human = original
|
||||
//transfer implants, we do this so the original's implants being removed won't destroy ours.
|
||||
for(var/obj/item/organ/external/limb in original_human.organs)
|
||||
var/list/implants = limb.implants
|
||||
for(var/obj/item/implant/original_implants as anything in implants)
|
||||
var/obj/item/implant/copied_implant = new original_implants.type
|
||||
copied_implant.implantInMob(made_copy)
|
||||
|
||||
return made_copy
|
||||
@@ -782,24 +782,6 @@ Turf and target are seperate in case you want to teleport some distance from a t
|
||||
if(A.vars.Find(lowertext(varname))) return 1
|
||||
else return 0
|
||||
|
||||
/proc/DuplicateObject(obj/original, var/perfectcopy = 0 , var/sameloc = 0)
|
||||
if(!original)
|
||||
return null
|
||||
|
||||
var/obj/O = null
|
||||
|
||||
if(sameloc)
|
||||
O=new original.type(original.loc)
|
||||
else
|
||||
O=new original.type(locate(0,0,0))
|
||||
|
||||
if(perfectcopy)
|
||||
if((O) && (original))
|
||||
for(var/V in original.vars)
|
||||
if(!(V in list("type","loc","locs","vars", "parent", "parent_type","verbs","ckey","key")))
|
||||
O.vars[V] = original.vars[V]
|
||||
return O
|
||||
|
||||
/proc/get_cardinal_dir(atom/A, atom/B)
|
||||
var/dx = abs(B.x - A.x)
|
||||
var/dy = abs(B.y - A.y)
|
||||
|
||||
@@ -547,14 +547,10 @@
|
||||
|
||||
/obj/machinery/porta_turret/process()
|
||||
//the main machinery process
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
//if the turret has no power or is broken, make the turret pop down if it hasn't already
|
||||
popDown()
|
||||
return
|
||||
|
||||
if(!enabled)
|
||||
//if the turret is off, make it pop down
|
||||
popDown()
|
||||
if((stat & (NOPOWER|BROKEN)) || !enabled)
|
||||
//if the turret has no power, is broken, or off, make the turret pop down if it hasn't already
|
||||
if(raised || raising)
|
||||
popDown()
|
||||
return
|
||||
|
||||
if(auto_repair && (health < maxhealth))
|
||||
@@ -579,7 +575,7 @@
|
||||
if(!tryToShootAt(targets))
|
||||
tryToShootAt(secondarytargets)
|
||||
|
||||
if(!targets.len && !secondarytargets.len)
|
||||
if(raised && !targets.len && !secondarytargets.len)
|
||||
resetting = addtimer(CALLBACK(src, PROC_REF(reset)), 6 SECONDS, TIMER_UNIQUE | TIMER_STOPPABLE) // no valid targets, close the cover
|
||||
else if(resetting)
|
||||
deltimer(resetting)
|
||||
|
||||
@@ -315,6 +315,8 @@ GLOBAL_LIST_EMPTY_TYPED(holodeck_controls, /obj/machinery/computer/holodeck_cont
|
||||
active = 1
|
||||
update_use_power(POWER_USE_ACTIVE)
|
||||
|
||||
QDEL_LIST(holodeck_landmarks)
|
||||
|
||||
for(var/item in holographic_objs)
|
||||
derez(item)
|
||||
|
||||
|
||||
@@ -220,7 +220,8 @@
|
||||
// Handle physical effects of weather.
|
||||
var/singleton/state/weather/weather_state
|
||||
var/obj/abstract/weather_system/weather = get_affecting_weather()
|
||||
if(weather)
|
||||
if(weather_cooldown_time <= world.time && weather)
|
||||
weather_cooldown_time = world.time + WEATHER_COOLDOWN_TIME
|
||||
weather_state = weather.weather_system.current_state
|
||||
if(istype(weather_state))
|
||||
weather_state.handle_exposure(src, get_weather_exposure(weather), weather)
|
||||
|
||||
@@ -103,3 +103,6 @@
|
||||
|
||||
/// If true, ignores weather effects
|
||||
var/resists_weather = FALSE
|
||||
|
||||
/// Time since last weather effect
|
||||
var/weather_cooldown_time = 0
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
var/name = "Unknown" // Contact name.
|
||||
var/image/marker // Image overlay attached to the contact.
|
||||
var/pinged = FALSE // Used to animate overmap effects.
|
||||
var/pinged_until = 0 // Used to animate overmap effects.
|
||||
var/list/images = list() // Our list of images to cast to users.
|
||||
var/image/radar // Radar image for sonar esque effect
|
||||
|
||||
@@ -70,18 +70,15 @@
|
||||
M.client.images |= images
|
||||
|
||||
|
||||
/datum/overmap_contact/proc/ping()
|
||||
if(pinged)
|
||||
/datum/overmap_contact/proc/ping(time_delay = 0)
|
||||
if(pinged_until > world.time)
|
||||
return
|
||||
pinged = TRUE
|
||||
pinged_until = world.time + time_delay + 1 SECOND
|
||||
effect.opacity = initial(effect.opacity)
|
||||
show()
|
||||
animate(marker, alpha=255, 0.5 SECOND, 1, LINEAR_EASING)
|
||||
addtimer(CALLBACK(src, PROC_REF(unping)), 1 SECOND)
|
||||
|
||||
/datum/overmap_contact/proc/unping()
|
||||
animate(marker, alpha=75, 2 SECOND, 1, LINEAR_EASING)
|
||||
pinged = FALSE
|
||||
animate(marker, alpha=75, time_delay, 1, flags = ANIMATION_END_NOW)
|
||||
animate(alpha=255, 1 SECOND, 1)
|
||||
animate(alpha=75, 2 SECOND, 1)
|
||||
|
||||
/datum/overmap_contact/Destroy()
|
||||
if(owner)
|
||||
|
||||
@@ -139,10 +139,9 @@
|
||||
continue
|
||||
// Update identification information for this record.
|
||||
record.update_marker_icon()
|
||||
|
||||
var/time_delay = max((SENSOR_TIME_DELAY * get_dist(linked, contact)),1)
|
||||
if(!record.pinged)
|
||||
addtimer(CALLBACK(record, PROC_REF(ping)), time_delay)
|
||||
if(record.pinged_until <= world.time)
|
||||
var/time_delay = max((SENSOR_TIME_DELAY * get_dist(linked, contact)), 1 SECOND)
|
||||
record.ping(time_delay)
|
||||
|
||||
/**
|
||||
* Adds an overmap object to the known contacts.
|
||||
|
||||
@@ -70,7 +70,7 @@ ABSTRACT_TYPE(/singleton/state/weather)
|
||||
if(!weather.show_weather(M))
|
||||
weather.show_wind(M)
|
||||
|
||||
if(exposure != WEATHER_IGNORE && weather.set_cooldown(M))
|
||||
if(exposure != WEATHER_IGNORE)
|
||||
if(exposure == WEATHER_EXPOSED)
|
||||
handle_exposure_effects(M, weather)
|
||||
else if(exposure == WEATHER_ROOFED)
|
||||
|
||||
@@ -1,23 +1,9 @@
|
||||
|
||||
GLOBAL_LIST_EMPTY(current_mob_ambience)
|
||||
/obj/abstract/weather_system
|
||||
|
||||
// Weakref lists used to track mobs within our weather
|
||||
// system; alternative to keeping big lists of actual mobs or
|
||||
// having mobs constantly poked by weather systems.
|
||||
|
||||
var/tmp/list/mobs_on_cooldown = list() // Has this mob recently been messed with by the weather?
|
||||
var/tmp/list/mob_shown_weather = list() // Has this mob been sent the summary message about the current weather?
|
||||
var/tmp/list/mob_shown_wind = list() // Has this mob been sent the summary message about the current wind?
|
||||
|
||||
// 'cooldown' in this context refers to weather effects like hail damage or being shown cosmetic messages.
|
||||
/obj/abstract/weather_system/proc/set_cooldown(var/mob/living/M, var/delay = 5 SECONDS)
|
||||
var/mobref = WEAKREF(M)
|
||||
if(!(mobref in mobs_on_cooldown))
|
||||
mobs_on_cooldown[mobref] = TRUE
|
||||
addtimer(CALLBACK(src, PROC_REF(clear_cooldown), mobref), delay)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/abstract/weather_system/proc/clear_cooldown(var/mobref)
|
||||
mobs_on_cooldown -= mobref
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# Your name.
|
||||
author: JohnWildkins
|
||||
|
||||
# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
|
||||
delete-after: True
|
||||
|
||||
# Any changes you've made. See valid prefix list above.
|
||||
# INDENT WITH TWO SPACES. NOT TABS. SPACES.
|
||||
# SCREW THIS UP AND IT WON'T WORK.
|
||||
# Also, this gets changed to [] after reading. Just remove the brackets when you add new shit.
|
||||
# Please surround your changes in double quotes ("). It works without them, but if you use certain characters it screws up compiling. The quotes will not show up in the changelog.
|
||||
changes:
|
||||
- refactor: "Ported object duplication handling from /tg/ to fix holodeck generating massive lag spikes."
|
||||
- refactor: "Refactored weather, turrets, and overmap contacts to not use timers to reduce the number created + deleted over a round substantially."
|
||||
Reference in New Issue
Block a user