mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-11 10:11:09 +00:00
Optimized vine spawning (#93648)
## About The Pull Request Tin, the current algorithm is very greedy and can call Enter() on thousands of turfs potentially depending on how your map is set up. This really isn't necessary and leads to spess lag and sometimes spess crashes. Instead of doing that we can test a smaller random subset of tiles with Enter() and achieve basically the same results. This basically just puts a safe bound on how many Enter() calls we can do. <img width="1307" height="739" alt="dreamseeker_6nE6Hjad7B" src="https://github.com/user-attachments/assets/3405ee8f-1af8-4dce-b253-1fcbf47412ea" /> ## Why It's Good For The Game Less spess lag ## Changelog 🆑 code: optimizes space vine spawning to create less lag. /🆑 --------- Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
This commit is contained in:
@@ -541,6 +541,27 @@
|
||||
. = pick_weight(list_to_pick)
|
||||
list_to_pick[.]--
|
||||
|
||||
/**
|
||||
* Picks n items from a list. The same index will not be chosen more than once.
|
||||
* e.g. pick_n(list_of_stuff, 10) would return a list of 10 items from the list, chosen randomly.
|
||||
*/
|
||||
/proc/pick_n(list/list_to_pick, n)
|
||||
var/list_to_pick_length = length(list_to_pick)
|
||||
if(!islist(list_to_pick) || !list_to_pick_length || n <= 0)
|
||||
return list()
|
||||
|
||||
/// The final list that gets returned
|
||||
var/list/result
|
||||
/// length of our list_to_pick
|
||||
n = min(n, list_to_pick_length)
|
||||
|
||||
// Shuffle and slice the first n indices
|
||||
var/list/copy_to_shuffle = list_to_pick.Copy()
|
||||
shuffle(copy_to_shuffle)
|
||||
result = copy_to_shuffle.Copy(1, n + 1)
|
||||
|
||||
return result
|
||||
|
||||
/**
|
||||
* Given a list, return a copy where values without defined weights are given weight 1.
|
||||
* For example, fill_with_ones(list(A, B=2, C)) = list(A=1, B=2, C=1)
|
||||
|
||||
@@ -29,23 +29,31 @@
|
||||
var/production
|
||||
|
||||
/datum/round_event/spacevine/start()
|
||||
var/list/turfs = list() //list of all the empty floor turfs in the hallway areas
|
||||
|
||||
var/list/final_turf_candidates = list() // final list of eligible empty floor turfs in the hallway areas that can be chosen
|
||||
|
||||
if(override_turf)
|
||||
turfs += override_turf
|
||||
final_turf_candidates += override_turf
|
||||
else
|
||||
var/obj/structure/spacevine/vine = new()
|
||||
|
||||
for(var/area/station/hallway/area in GLOB.areas)
|
||||
var/list/floor_candidates = list()
|
||||
for(var/area/station/hallway/area in shuffle(GLOB.areas.Copy()))
|
||||
for(var/turf/open/floor in area.get_turfs_from_all_zlevels())
|
||||
if(!isopenspaceturf(floor) && floor.Enter(vine))
|
||||
turfs += floor
|
||||
if(isopenspaceturf(floor))
|
||||
continue
|
||||
floor_candidates += floor
|
||||
|
||||
// Enter() is expensive to call on potentially hundreds to thousands of turfs at once and can even lead to server crashes.
|
||||
// We can pick() a subset instead and get close enough results at a fraction of the cost.
|
||||
var/turfs_to_test = 100
|
||||
var/list/sampled_floor_candidates = pick_n(floor_candidates, min(turfs_to_test, length(floor_candidates))) // results in at most 100 calls of Enter(), a reasonable amount while still feeling random.
|
||||
|
||||
for(var/turf/open/floor as anything in sampled_floor_candidates)
|
||||
if(floor.Enter(vine))
|
||||
final_turf_candidates += floor
|
||||
qdel(vine)
|
||||
|
||||
if(length(turfs)) //Pick a turf to spawn at if we can
|
||||
var/turf/floor = pick(turfs)
|
||||
if(length(final_turf_candidates)) //Pick a turf to spawn at if we can
|
||||
var/turf/floor = pick(final_turf_candidates)
|
||||
var/list/selected_mutations = list()
|
||||
|
||||
if(mutations_overridden == FALSE)
|
||||
|
||||
Reference in New Issue
Block a user