mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 01:34:01 +00:00
Makes the code compatible with 515.1594+
Few simple changes and one very painful one.
Let's start with the easy:
* puts call behind `LIBCALL` define, so call_ext is properly used in 515
* Adds `NAMEOF_STATIC(_,X)` macro for nameof in static definitions since
src is now invalid there.
* Fixes tgui and devserver. From 515 onward the tmp3333{procid} cache
directory is not appened to base path in browser controls so we don't
check for it in base js and put the dev server dummy window file in
actual directory not the byond root.
* Renames the few things that had /final/ in typepath to ultimate since
final is a new keyword
And the very painful change:
`.proc/whatever` format is no longer valid, so we're replacing it with
new nameof() function. All this wrapped in three new macros.
`PROC_REF(X)`,`TYPE_PROC_REF(TYPE,X)`,`GLOBAL_PROC_REF(X)`. Global is
not actually necessary but if we get nameof that does not allow globals
it would be nice validation.
This is pretty unwieldy but there's no real alternative.
If you notice anything weird in the commits let me know because majority
was done with regex replace.
@tgstation/commit-access Since the .proc/stuff is pretty big change.
Co-authored-by: san7890 <the@san7890.com>
Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com>
205 lines
8.0 KiB
Plaintext
205 lines
8.0 KiB
Plaintext
//This files deals with the generic sending and receiving of "alarms"
|
|
//This is a somewhat blanket term, it covers things like fire/power/atmos alarms, along with some oddballs
|
|
//Side effect of how the system is used, these are mostly things that are of interest to ais and borgs
|
|
//Though it could easily be expanded to cover other senders/revievers
|
|
//The system as a whole differs from reading off a global list in a few ways.
|
|
//In that A, it allows us to send cameras for ais/borgs/potentially others to jump to
|
|
//And B, it's not like we're giving you all the alarms that have been sent, because of the separate listing for each reviever
|
|
//You only receive alarms sent after you start to listen
|
|
//Also of note, due to an optimization done on areas, one alarm handler will only ever send one "on" or "off" alarm
|
|
//So the whole only receiving stuff sent post creation thing actually matters
|
|
//Honestly I'm not sure how much of this is a feature, and how much is just old code
|
|
//But I'm leaving it how I found it
|
|
|
|
///Represents a single source of alarms, one alarm handler will only ever count for one alarm per listener
|
|
/datum/alarm_handler
|
|
///A list of alarm type -> list of areas we currently have alarms in
|
|
var/list/sent_alarms = list()
|
|
///Our source atom
|
|
var/atom/source_atom
|
|
|
|
/datum/alarm_handler/New(atom/source_atom)
|
|
if(istype(source_atom))
|
|
src.source_atom = source_atom
|
|
else
|
|
var/source_type = (isdatum(source_atom)) ? source_atom.type : ""
|
|
stack_trace("a non atom was passed into alarm_handler! [source_atom] [source_type]")
|
|
return ..()
|
|
|
|
/datum/alarm_handler/Destroy()
|
|
for(var/alarm_type in sent_alarms)
|
|
for(var/area/area_to_clear as anything in sent_alarms[alarm_type])
|
|
//Yeet all connected alarms
|
|
clear_alarm_from_area(alarm_type, area_to_clear)
|
|
source_atom = null
|
|
return ..()
|
|
|
|
///Sends an alarm to any interested things, does some checks to prevent unneeded work
|
|
///Important to note is that source_atom is not held as a ref, we're used as a proxy to prevent hard deletes
|
|
///optional_camera should only be used when you have one camera you want to pass along to alarm listeners, most of the time you should have no use for it
|
|
/datum/alarm_handler/proc/send_alarm(alarm_type, atom/use_as_source_atom, optional_camera)
|
|
if(!use_as_source_atom)
|
|
use_as_source_atom = source_atom
|
|
if(!use_as_source_atom)
|
|
return
|
|
|
|
var/area/our_area = get_area(use_as_source_atom)
|
|
var/our_z_level = use_as_source_atom.z
|
|
|
|
var/list/existing_alarms = sent_alarms[alarm_type]
|
|
if(existing_alarms)
|
|
if(our_area in existing_alarms)
|
|
return FALSE
|
|
else
|
|
sent_alarms[alarm_type] = list()
|
|
existing_alarms = sent_alarms[alarm_type]
|
|
|
|
existing_alarms += our_area
|
|
|
|
our_area.active_alarms[alarm_type] += 1
|
|
|
|
SEND_SIGNAL(src, COMSIG_ALARM_TRIGGERED, alarm_type, our_area)
|
|
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_ALARM_FIRE(alarm_type), src, alarm_type, our_area, our_z_level, optional_camera)
|
|
|
|
return TRUE
|
|
|
|
///Clears an alarm from any interested listeners
|
|
/datum/alarm_handler/proc/clear_alarm(alarm_type, use_as_source_atom)
|
|
SIGNAL_HANDLER
|
|
if(!use_as_source_atom)
|
|
use_as_source_atom = source_atom
|
|
if(!use_as_source_atom)
|
|
return
|
|
|
|
return clear_alarm_from_area(alarm_type, get_area(use_as_source_atom))
|
|
|
|
///Exists so we can request that the alarms from an area are cleared, even if our source atom is no longer in that area
|
|
/datum/alarm_handler/proc/clear_alarm_from_area(alarm_type, area/our_area)
|
|
|
|
var/list/existing_alarms = sent_alarms[alarm_type]
|
|
if(!existing_alarms)
|
|
return FALSE
|
|
|
|
if(!(our_area in existing_alarms))
|
|
return FALSE
|
|
|
|
existing_alarms -= our_area
|
|
if(!length(existing_alarms))
|
|
sent_alarms -= alarm_type
|
|
|
|
our_area.active_alarms[alarm_type] -= 1
|
|
if(!length(our_area.active_alarms))
|
|
our_area.active_alarms -= alarm_type
|
|
|
|
SEND_SIGNAL(src, COMSIG_ALARM_CLEARED, alarm_type, our_area)
|
|
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_ALARM_CLEAR(alarm_type), src, alarm_type, our_area)
|
|
return TRUE
|
|
|
|
/datum/alarm_listener
|
|
///List of valid source z levels, ignored if null
|
|
var/list/allowed_z_levels
|
|
///List of allowed areas. if this is null it's ignored
|
|
var/list/allowed_areas
|
|
|
|
///List of alarm type -> list of area name -> list(area, ref to area's cameras, list(sources))
|
|
var/list/alarms = list()
|
|
///Should we allow alarm changes to go through or not
|
|
var/accepting_alarm_changes = TRUE
|
|
|
|
///Accepts a list of alarm types to pay attention to, a list of valid z levels, and a list of valid areas. areas and zlevels are ignored if null
|
|
/datum/alarm_listener/New(alarms_to_listen_for, allowed_z_levels, allowed_areas)
|
|
src.allowed_z_levels = allowed_z_levels
|
|
src.allowed_areas = allowed_areas
|
|
for(var/alarm_type in alarms_to_listen_for)
|
|
RegisterSignal(SSdcs, COMSIG_GLOB_ALARM_FIRE(alarm_type), PROC_REF(add_alarm))
|
|
RegisterSignal(SSdcs, COMSIG_GLOB_ALARM_CLEAR(alarm_type), PROC_REF(clear_alarm))
|
|
|
|
return ..()
|
|
|
|
///Adds an alarm to our alarms list, you shouldn't be calling this manually
|
|
///It should all be handled by the signal listening we do, unless you want to only send an alarm to one listener
|
|
/datum/alarm_listener/proc/add_alarm(datum/source, datum/alarm_handler/handler, alarm_type, area/source_area, source_z, optional_camera)
|
|
SIGNAL_HANDLER
|
|
|
|
if (!accepting_alarm_changes)
|
|
return
|
|
|
|
if(allowed_z_levels && !(source_z in allowed_z_levels))
|
|
return
|
|
|
|
if(allowed_areas && !(source_area.type in allowed_areas))
|
|
return
|
|
|
|
var/list/alarms_of_our_type = alarms[alarm_type]
|
|
if(!alarms_of_our_type)
|
|
alarms[alarm_type] = list()
|
|
alarms_of_our_type = alarms[alarm_type]
|
|
|
|
if(alarms_of_our_type[source_area.name])
|
|
var/list/alarm = alarms_of_our_type[source_area.name]
|
|
var/list/sources = alarm[3]
|
|
sources |= handler
|
|
//Return if a source already exists, we don't want to send a signal or add a new entry
|
|
return
|
|
|
|
//We normally directly pass in a ref to the area's camera's list to prevent hanging refs
|
|
var/list/cameras = source_area.cameras
|
|
if(optional_camera)
|
|
cameras = list(optional_camera) // This will cause harddels, so we need to clear manually
|
|
RegisterSignal(optional_camera, COMSIG_PARENT_QDELETING, PROC_REF(clear_camera_ref), override = TRUE) //It's just fine to override, cause we clear all refs in the proc
|
|
|
|
//This does mean that only the first alarm of that camera type in the area will send a ping, but jesus what else can ya do
|
|
alarms_of_our_type[source_area.name] = list(source_area, cameras, list(handler))
|
|
SEND_SIGNAL(src, COMSIG_ALARM_LISTENER_TRIGGERED, alarm_type, source_area)
|
|
|
|
///Removes an alarm to our alarms list, you probably shouldn't be calling this manually
|
|
///It should all be handled by the signal listening we do, unless you want to only remove an alarm to one listener
|
|
/datum/alarm_listener/proc/clear_alarm(datum/source, datum/alarm_handler/handler, alarm_type, area/source_area)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!accepting_alarm_changes)
|
|
return
|
|
|
|
var/list/alarms_of_our_type = alarms[alarm_type]
|
|
|
|
if(!alarms_of_our_type)
|
|
return
|
|
|
|
if(!alarms_of_our_type[source_area.name])
|
|
return
|
|
|
|
var/list/alarm = alarms_of_our_type[source_area.name]
|
|
var/list/sources = alarm[3]
|
|
sources -= handler
|
|
|
|
if (length(sources))
|
|
return //Return if there's still sources left, no sense clearing the list or bothering anyone about it
|
|
|
|
alarms_of_our_type -= source_area.name
|
|
|
|
if(!length(alarms_of_our_type))
|
|
alarms -= alarm_type
|
|
|
|
SEND_SIGNAL(src, COMSIG_ALARM_LISTENER_CLEARED, alarm_type, source_area)
|
|
|
|
///Does what it says on the tin, exists for signal hooking
|
|
/datum/alarm_listener/proc/prevent_alarm_changes()
|
|
SIGNAL_HANDLER
|
|
accepting_alarm_changes = FALSE
|
|
|
|
///Does what it says on the tin, exists for signal hooking
|
|
/datum/alarm_listener/proc/allow_alarm_changes()
|
|
SIGNAL_HANDLER
|
|
accepting_alarm_changes = TRUE
|
|
|
|
///Used to manually clear camera refs if one is ref'd directly
|
|
/datum/alarm_listener/proc/clear_camera_ref(obj/machinery/camera/source)
|
|
SIGNAL_HANDLER
|
|
var/list/alarms_cache = alarms //Cache for sonic speec
|
|
for(var/alarm_type in alarms_cache)
|
|
var/list/alarms_of_type = alarms_cache[alarm_type] //Sonic cache speed forads
|
|
for(var/area_name as anything in alarms_of_type)
|
|
var/list/alarm_packet = alarms_of_type[area_name]
|
|
var/list/cameras = alarm_packet[2]
|
|
cameras -= source // REF FOUND AND CLEARED BOYSSSS
|