## About The Pull Request
Empy lists. There are a lot of 'em.
<img width="981" height="512" alt="image"
src="https://github.com/user-attachments/assets/b94b041a-2904-466b-ab89-54bd1de11b4e"
/>
Going through ways to reduce memory I found a few easy ones here. Wires,
the edible component, the seethrough component. None of these are really
a concern when it comes to needing lists in memory for performance
reasons. Wires aren't going to be cut most of the time for each door. A
lot of food does not have any junkiness. Seethrough component lies
dormant most of the round. Etc.
Making lists lazy in these cases should be a no brainer.
Everything I tested still seems to work exactly the same.
## Why It's Good For The Game
Frees memory that is just taking up space a lot of the time.
## Changelog
Not player-facing, this is all under-the-hood stuff.
## About The Pull Request
I've been meaning to do this for some time. I need this for
portable/handheld aquariums/fishtanks to be possible. I'll sprite and
code them before I call this PR ready, however suggestions and code
reviews are welcome in the meantime.
Being a pretty heavy refactor, some things might break (we have more
than a few unit tests so perhaps not) while others, coincidentally,
might be fixed without me knowing. Anyway I'm sure this PR fixes
aquarium beauty, which wasn't really working to begin with because the
code was so fucking bad. Nothing really worth of a CL entry tho.
TODO:
- [x] handheld aquariums, craftable with a kit and little plastic or
buyable from the fun vendor ig.
- [x] an aquarium upgrade for handheld aquariums to bypass possible
restrictions.
- [x] update the beauty element to consider items, which shouldn't
contribute to the area beauty when held or otherwise not on a turf.
## Why It's Good For The Game
This should make handheld aquariums possible.
## Changelog
🆑
refactor: refactored aquariums heavily. Please report any fishy bug.
add: Added portable/handheld fish tanks to the game. They can be crafted
with an aquarium kit and 5 sheets of plastic. While portable, they
cannot store fish that are too big or if there're too many already. This
restriction can be removed by using the new "bluespace fish tank kit"
techweb item.
map: Replaced the lawyer's stationary pet aquarium with a fish tank, so
you can carry McGill around.
balance: Reduced the iron cost of stationary aquariums a little.
/🆑
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>
ELEMENT_DETACH is **not** a requirement to having `Detach` called.
Detach is always called when the element itself is destroyed.
ELEMENT_DETACH is a flag that when set, makes sure Detach is called when
the atom destroys.
Sometimes you want this, for instance:
```dm
/datum/element/point_of_interest/Detach(datum/target)
SSpoints_of_interest.on_poi_element_removed(target)
return ..()
```
This Detach cleans up a reference that would have hung if target was
destroyed without this being called.
However, most uses of Detach are cleaning up signals. Signals are
automatically cleaned up when something is destroyed. You do not need
ELEMENT_DETACH in this case, and it slows down init. This also includes
somewhat more complex stuff, like removing overlays on the source
object. It's getting deleted anyway, you don't care!
I have removed all uses of ELEMENT_DETACH that seemed superfluous. I
have also renamed it to `ELEMENT_DETACH_ON_HOST_DESTROY` to make its
purpose more clear, as me and a lot of other maintainers misunderstood
what it did,
---
An update to this, ELEMENT_DETACH *is* needed for anything that can
register to a turf, as turfs do not clear their signals on destroy.
a month or two ago i realized that on master the reason why get_hearers_in_view() overtimes so much (ie one of our highest overtiming procs at highpop) is because when you transmit a radio signal over the common channel, it can take ~20 MILLISECONDS, which isnt good when 1. player verbs and commands usually execute after SendMaps processes for that tick, meaning they can execute AFTER the tick was supposed to start if master is overloaded and theres a lot of maptick 2. each of our server ticks are only 50 ms, so i started on optimizing this.
the main optimization was SSspatial_grid which allows searching through 15x15 spatial_grid_cell datums (one set for each z level) far faster than iterating over movables in view() to look for what you want. now all hearing sensitive movables in the 5x5 areas associated with each spatial_grid_cell datum are stored in the datum (so are client mobs). when you search for one of the stored "types" (hearable or client mob) in a radius around a center, it just needs to
iterate over the cell datums in range
add the content type you want from the datums to a list
subtract contents that arent in range, then contents not in line of sight
return the list
from benchmarks, this makes short range searches like what is used with radio code (it goes over every radio connected to a radio channel that can hear the signal then calls get_hearers_in_view() to search in the radios canhear_range which is at most 3) about 3-10 times faster depending on workload. the line of sight algorithm scales well with range but not very well if it has to check LOS to > 100 objects, which seems incredibly rare for this workload, the largest range any radio in the game searches through is only 3 tiles
the second optimization is to enforce complex setter vars for radios that removes them from the global radio list if they couldnt actually receive any radio transmissions from a given frequency in the first place.
the third optimization i did was massively reduce the number of hearables on the station by making hologram projectors not hear if dont have an active call/anything that would make them need hearing. so one of hte most common non player hearables that require view iteration to find is crossed out.
also implements a variation of an idea oranges had on how to speed up get_hearers_in_view() now that ive realized that view() cant be replicated by a raycasting algorithm. it distributes pregenerated abstract /mob/oranges_ear instances to all hearables in range such that theres at max one per turf and then iterates through only those mobs to take advantage of type-specific view() optimizations and just adds up the references in each one to create the list of hearing atoms, then puts the oranges_ear mobs back into nullspace. this is about 2x as fast as the get_hearers_in_view() on master
holy FUCK its fast. like really fucking fast. the only costly part of the radio transmission pipeline i dont touch is mob/living/Hear() which takes ~100 microseconds on live but searching through every radio in the world with get_hearers_in_radio_ranges() -> get_hearers_in_view() is much faster, as well as the filtering radios step
the spatial grid searching proc is about 36 microseconds/call at 10 range and 16 microseconds at 3 range in the captains office (relatively many hearables in view), the new get_hearers_in_view() was 4.16 times faster than get_hearers_in_view_old() at 10 range and 4.59 times faster at 3 range
SSspatial_grid could be used for a lot more things other than just radio and say code, i just didnt implement it. for example since the cells are datums you could get all cells in a radius then register for new objects entering them then activate when a player enters your radius. this is something that would require either very expensive view() calls or iterating over every player in the global list and calling get_dist() on them which isnt that expensive but is still worse than it needs to be
on normal get_hearers_in_view cost the new version that uses /mob/oranges_ear instances is about 2x faster than the old version, especially since the number of hearing sensitive movables has been brought down dramatically.
with get_hearers_in_view_oranges_ear() being the benchmark proc that implements this system and get_hearers_in_view() being a slightly optimized version of the version we have on master, get_hearers_in_view_as() being a more optimized version of the one we have on master, and get_hearers_in_LOS() being the raycasting version currently only used for radios because it cant replicate view()'s behavior perfectly.
* pass correct material amount to on_removed
* skip detach logic in beauty element for objects that don't actually have beauty
* always remove area-sensitive trait when detaching beauty element