mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-27 18:12:00 +00:00
* Macro Optimizes Map Saving (100x) DO NOT CHURN STRINGS Edition (#80845) ## About The Pull Request Yello! This one is reasonably quick, tho I did some fixes too This is the big one, fixes the buildmode tool sometimes locking disabled for the whole round. We do this by replacing the static var on buildmode with global var and a global proc This keeps a harddel on the buildmode datum from permalocking is_running to TRUE Also makes flipping the var BACK if something breaks significantly easier for admins, so that's nice Alright, smaller things now Fixes lists of numbers failing to encoded improperly This was fixed on shiptest, we failed to actually port their most recent revision Fixes the shuttle flag not actually working because it used istype instead of ispath Changes obj_blacklist to a typecache for optimization's sake Renames/moves some vars around to prevent weird double typing things Removes a checktick in key gen, it's just costing more time then it would save in overtime Properly handles lists. We were only doing var encoding one layer deep, need to do it alll the way down Alright, now the optimizations This proc is fucking HOT, and it's for really dumb reasons This is a text gen proc, and it makes the mistake of generating text and concatinating it with MORE text. This is HORRIFICALLY EXPENSIVE because byond caches strings (can only be one of each) and string churn fucks up that caching system something fierce Moving from strings to lists of strings we join at the end takes us from like idk 100 seconds to save bare metastation to like 1.5 This is applied basically everywhere for obvious reasons While I'm here, storing keys in a flat list and then using find to find them, then using that index to lookup into another flat list is a bit silly. Let's just make it an assoc list. Faster lookup, cleaner. Oh also rather then iterating over all the vars on an object, let's iterate over just the ones we care about yeah? Let's see... no sense genning a key we'll never use, and having suffixes be often non existent is silly just embrace the slight mess. That's it I think, this takes us from 100 seconds to save metastation to 2.5 seconds to save ALL of metastation (I removed the vars limiter so I could make sure var saving didn't fuck me up) ## Why It's Good For The Game Cleans up some issues that we failed to port the fixes for, MASSIVELY optimizes this (so it can finish in like 5/10 seconds and not 300!) and ensures admins can always use the thing and don't risk dropping their pet buildastation to the void. Worth noting, this tool really should not be used for station mapping outside an event context. It produces sorta buggy var edits, and WILL fail to pull over context for shit. Please don't use it as such Profiles (csv files I promise) [Before](https://github.com/tgstation/tgstation/files/13853313/profiler.json) [After](https://github.com/tgstation/tgstation/files/13853271/profiler.json) I'd include my line by lines but I don't know how much you'd get out of them. Here's an image tho  ## Changelog 🆑 fix: The map saving tool will no longer lock up and prevent all further action at random fix: Map saving now takes on the order of seconds, not minutes fix: Fixes an issue with lists that caused strongdmm to report saved maps as broken /🆑 * Macro Optimizes Map Saving (100x) DO NOT CHURN STRINGS Edition --------- Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
92 lines
3.9 KiB
Plaintext
92 lines
3.9 KiB
Plaintext
/datum/buildmode_mode/map_export
|
|
key = "mapexport"
|
|
use_corner_selection = TRUE
|
|
/// Variable with the flag value to understand how to treat the shuttle zones.
|
|
var/shuttle_flag = SAVE_SHUTTLEAREA_DONTCARE
|
|
/// Variable with a flag value to indicate what should be saved (for example, only objects or only mobs).
|
|
var/save_flag = ALL
|
|
|
|
/datum/buildmode_mode/map_export/change_settings(client/builder)
|
|
var/static/list/options = list(
|
|
"Object Saving" = SAVE_OBJECTS,
|
|
"Mob Saving" = SAVE_MOBS,
|
|
"Turf Saving" = SAVE_TURFS,
|
|
"Area Saving" = SAVE_AREAS,
|
|
"Space Turf Saving" = SAVE_SPACE,
|
|
"Object Property Saving" = SAVE_OBJECT_PROPERTIES,
|
|
)
|
|
var/what_to_change = tgui_input_list(builder, "What export setting would you like to toggle?", "Map Exporter", options)
|
|
if (!what_to_change)
|
|
return
|
|
save_flag ^= options[what_to_change]
|
|
to_chat(builder, "<span class='notice'>[what_to_change] is now [save_flag & options[what_to_change] ? "ENABLED" : "DISABLED"].</span>")
|
|
|
|
/datum/buildmode_mode/map_export/show_help(client/builder)
|
|
to_chat(builder, span_purple(examine_block(
|
|
"[span_bold("Select corner")] -> Left Mouse Button on obj/turf/mob\n\
|
|
[span_bold("Set export options")] -> Right Mouse Button on buildmode button"))
|
|
)
|
|
|
|
/datum/buildmode_mode/map_export/handle_selected_area(client/builder, params)
|
|
var/list/listed_params = params2list(params)
|
|
var/left_click = listed_params.Find("left")
|
|
|
|
//Ensure the selection is actually done
|
|
if(!left_click)
|
|
to_chat(builder, span_warning("Invalid selection."))
|
|
return
|
|
|
|
//If someone somehow gets build mode, stop them from using this.
|
|
if(!check_rights(R_DEBUG))
|
|
message_admins("[ckey(builder)] tried to run the map save generator but was rejected due to insufficient perms.")
|
|
to_chat(builder, span_warning("You must have +ADMIN rights to use this."))
|
|
return
|
|
//Emergency check
|
|
if(get_dist(cornerA, cornerB) > 60 || cornerA.z != cornerB.z)
|
|
var/confirm = tgui_alert(builder, "Are you sure about this? Exporting large maps may take quite a while.", "Map Exporter", list("Yes", "No"))
|
|
if(confirm != "Yes")
|
|
return
|
|
|
|
if(cornerA == cornerB)
|
|
return
|
|
|
|
INVOKE_ASYNC(GLOBAL_PROC, GLOBAL_PROC_REF(_save_map), cornerA, cornerB, save_flag, shuttle_flag)
|
|
|
|
/// A guard variable to prevent more than one map export process from occurring at the same time.
|
|
GLOBAL_VAR_INIT(map_writing_running, FALSE)
|
|
/// Hey bud don't call this directly, it exists so we can invoke async and prevent the buildmode datum being qdel'd from halting this proc
|
|
/proc/_save_map(turf/cornerA, turf/cornerB, save_flag, shuttle_flag)
|
|
if(!check_rights(R_DEBUG))
|
|
message_admins("[ckey(usr)] tried to run the map save generator but was rejected due to insufficient perms.")
|
|
to_chat(usr, span_warning("You must have +ADMIN rights to use this."))
|
|
return
|
|
if(GLOB.map_writing_running)
|
|
to_chat(usr, span_warning("Someone is already running the generator! Try again in a little bit."))
|
|
return
|
|
|
|
to_chat(usr, span_warning("Saving, please wait..."))
|
|
GLOB.map_writing_running = TRUE
|
|
|
|
//I put this before the actual saving of the map because it likely won't log if it crashes the fucking server
|
|
log_admin("Build Mode: [key_name(usr)] is exporting the map area from [AREACOORD(cornerA)] through [AREACOORD(cornerB)]")
|
|
|
|
//oversimplified for readability and understandibility
|
|
|
|
var/minx = min(cornerA.x, cornerB.x)
|
|
var/miny = min(cornerA.y, cornerB.y)
|
|
var/minz = min(cornerA.z, cornerB.z)
|
|
|
|
var/maxx = max(cornerA.x, cornerB.x)
|
|
var/maxy = max(cornerA.y, cornerB.y)
|
|
var/maxz = max(cornerA.z, cornerB.z)
|
|
|
|
//Step 1: Get the data (This can take a while)
|
|
var/dat = write_map(minx, miny, minz, maxx, maxy, maxz, save_flag, shuttle_flag)
|
|
|
|
//Step 2: Write the data to a file and give map to client
|
|
var/date = time2text(world.timeofday, "YYYY-MM-DD_hh-mm-ss")
|
|
var/file_name = sanitize_filename(tgui_input_text(usr, "Filename?", "Map Exporter", "exported_map_[date]"))
|
|
send_exported_map(usr, file_name, dat)
|
|
to_chat(usr, span_green("The map was successfully saved!"))
|
|
GLOB.map_writing_running = FALSE
|