mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-29 16:18:01 +01:00
Fix map_export admin verb not saving objects properly (#90998)
## About The Pull Request When using the `map_export` admin verb the following things are fixed: - All objects density, anchored, opacity, atom_integrity, and resistance_flags vars are saved - Multi-tile objects being spammed on all tiles the sprite reaches - Dirt decals error icon - Airlocks error icon and to save welded state - Dark Wizard Simple Mobs error icon - Closets to save welded, open, and locked states - Air alarms to save name - Air scrubbers/vents to save name and welded states - APCs to save name, charge, cell, lighting, equipment, and environmental states - APCs spawning a duplicated terminal underneath it when one already exists - SMES to save charge, input, and output states - Holodecks to revert any holodeck turfs to the empty turf and skip saving any hologram items - Photos and Paintings error icons - Bloody Footprints error icons - False Walls error icons - Docking Ports runtimes because the map template var would change - Effects (lasers, portals, beams, sparks, etc.) saving when they should be omitted I would have loved to get `component_parts` to save for machines and turf decals, but perhaps that is for another day since it requires complicated solutions. Here are some before and after pictures:     ## Why It's Good For The Game Better map saving code. ## Changelog 🆑 fix: Fix `map_export` admin verb not properly saving a massive amount of objects. /🆑
This commit is contained in:
@@ -37,6 +37,9 @@
|
||||
fire = 90
|
||||
acid = 70
|
||||
|
||||
/obj/machinery/button/get_save_vars()
|
||||
return ..() + NAMEOF(src, id)
|
||||
|
||||
/**
|
||||
* INITIALIZATION
|
||||
*/
|
||||
|
||||
@@ -157,6 +157,12 @@
|
||||
flags_1 = HTML_USE_INITAL_ICON_1
|
||||
rad_insulation = RAD_MEDIUM_INSULATION
|
||||
|
||||
/obj/machinery/door/airlock/get_save_vars()
|
||||
. = ..()
|
||||
. -= NAMEOF(src, icon_state) // airlocks ignore icon_state and instead use get_airlock_overlay()
|
||||
// TODO save the wire data but need to include states for cute wires, signalers attached to wires, etc.
|
||||
return .
|
||||
|
||||
/obj/machinery/door/airlock/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
|
||||
@@ -82,6 +82,11 @@
|
||||
fire = 80
|
||||
acid = 70
|
||||
|
||||
/obj/machinery/door/get_save_vars()
|
||||
. = ..()
|
||||
. += NAMEOF(src, welded)
|
||||
return .
|
||||
|
||||
/obj/machinery/door/Initialize(mapload)
|
||||
AddElement(/datum/element/blocks_explosives)
|
||||
. = ..()
|
||||
@@ -118,6 +123,7 @@
|
||||
)
|
||||
AddElement(/datum/element/connect_loc, loc_connections)
|
||||
AddElement(/datum/element/can_barricade)
|
||||
update_appearance()
|
||||
|
||||
/obj/machinery/door/examine(mob/user)
|
||||
. = ..()
|
||||
|
||||
@@ -293,6 +293,9 @@
|
||||
dryname = "dried footprints"
|
||||
drydesc = "HMM... SOMEONE WAS HERE!"
|
||||
|
||||
/obj/effect/decal/cleanable/blood/footprints/get_save_vars()
|
||||
return ..() - NAMEOF(src, icon_state)
|
||||
|
||||
/obj/effect/decal/cleanable/blood/footprints/Initialize(mapload, footprint_sprite)
|
||||
src.footprint_sprite = footprint_sprite
|
||||
. = ..()
|
||||
|
||||
@@ -109,6 +109,14 @@ GLOBAL_LIST_EMPTY(roundstart_station_closets)
|
||||
fire = 70
|
||||
acid = 60
|
||||
|
||||
/obj/structure/closet/get_save_vars()
|
||||
. = ..()
|
||||
. += NAMEOF(src, welded)
|
||||
. += NAMEOF(src, opened)
|
||||
. += NAMEOF(src, locked)
|
||||
. += NAMEOF(src, anchorable)
|
||||
return .
|
||||
|
||||
/obj/structure/closet/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
|
||||
@@ -26,6 +26,10 @@
|
||||
var/girder_type = /obj/structure/girder/displaced
|
||||
var/opening = FALSE
|
||||
|
||||
/obj/structure/falsewall/get_save_vars()
|
||||
. = ..()
|
||||
. -= NAMEOF(src, icon)
|
||||
return .
|
||||
|
||||
/obj/structure/falsewall/Initialize(mapload)
|
||||
. = ..()
|
||||
@@ -33,6 +37,7 @@
|
||||
set_custom_materials(initialized_mineral.mats_per_unit, mineral_amount)
|
||||
qdel(initialized_mineral)
|
||||
air_update_turf(TRUE, TRUE)
|
||||
update_appearance()
|
||||
|
||||
/obj/structure/falsewall/attack_hand(mob/user, list/modifiers)
|
||||
if(opening)
|
||||
|
||||
@@ -74,44 +74,63 @@ ADMIN_VERB(map_export, R_DEBUG, "Map Export", "Select a part of the map by coord
|
||||
**/
|
||||
|
||||
/atom/proc/get_save_vars()
|
||||
return list(
|
||||
NAMEOF(src, color),
|
||||
NAMEOF(src, dir),
|
||||
NAMEOF(src, icon),
|
||||
NAMEOF(src, icon_state),
|
||||
NAMEOF(src, name),
|
||||
NAMEOF(src, pixel_x),
|
||||
NAMEOF(src, pixel_y),
|
||||
)
|
||||
. = list()
|
||||
. += NAMEOF(src, color)
|
||||
. += NAMEOF(src, dir)
|
||||
. += NAMEOF(src, icon)
|
||||
. += NAMEOF(src, icon_state)
|
||||
. += NAMEOF(src, name)
|
||||
. += NAMEOF(src, pixel_x)
|
||||
. += NAMEOF(src, pixel_y)
|
||||
. += NAMEOF(src, density)
|
||||
. += NAMEOF(src, opacity)
|
||||
|
||||
if(uses_integrity)
|
||||
if(atom_integrity != max_integrity) // Only save if atom_integrity differs from max_integrity to avoid redundant saving
|
||||
. += NAMEOF(src, atom_integrity)
|
||||
. += NAMEOF(src, max_integrity)
|
||||
. += NAMEOF(src, integrity_failure)
|
||||
. += NAMEOF(src, damage_deflection)
|
||||
. += NAMEOF(src, resistance_flags)
|
||||
|
||||
return .
|
||||
|
||||
/atom/movable/get_save_vars()
|
||||
. = ..()
|
||||
. += NAMEOF(src, anchored)
|
||||
return .
|
||||
|
||||
/obj/get_save_vars()
|
||||
return ..() + list(NAMEOF(src, req_access), NAMEOF(src, id_tag))
|
||||
. = ..()
|
||||
. += NAMEOF(src, req_access)
|
||||
. += NAMEOF(src, id_tag)
|
||||
return .
|
||||
|
||||
/obj/item/stack/get_save_vars()
|
||||
return ..() + NAMEOF(src, amount)
|
||||
. = ..()
|
||||
. += NAMEOF(src, amount)
|
||||
return .
|
||||
|
||||
/obj/docking_port/get_save_vars()
|
||||
return ..() + list(
|
||||
NAMEOF(src, dheight),
|
||||
NAMEOF(src, dwidth),
|
||||
NAMEOF(src, height),
|
||||
NAMEOF(src, shuttle_id),
|
||||
NAMEOF(src, width),
|
||||
)
|
||||
/obj/docking_port/stationary/get_save_vars()
|
||||
return ..() + NAMEOF(src, roundstart_template)
|
||||
. = ..()
|
||||
. += NAMEOF(src, dheight)
|
||||
. += NAMEOF(src, dwidth)
|
||||
. += NAMEOF(src, height)
|
||||
. += NAMEOF(src, shuttle_id)
|
||||
. += NAMEOF(src, width)
|
||||
return .
|
||||
|
||||
/obj/machinery/atmospherics/get_save_vars()
|
||||
return ..() + list(
|
||||
NAMEOF(src, piping_layer),
|
||||
NAMEOF(src, pipe_color),
|
||||
)
|
||||
. = ..()
|
||||
. += NAMEOF(src, piping_layer)
|
||||
. += NAMEOF(src, pipe_color)
|
||||
return .
|
||||
|
||||
/obj/item/pipe/get_save_vars()
|
||||
return ..() + list(
|
||||
NAMEOF(src, piping_layer),
|
||||
NAMEOF(src, pipe_color),
|
||||
)
|
||||
. = ..()
|
||||
. += NAMEOF(src, piping_layer)
|
||||
. += NAMEOF(src, pipe_color)
|
||||
return .
|
||||
|
||||
GLOBAL_LIST_INIT(save_file_chars, list(
|
||||
"a","b","c","d","e",
|
||||
@@ -176,12 +195,20 @@ GLOBAL_LIST_INIT(save_file_chars, list(
|
||||
maxz,
|
||||
save_flag = ALL,
|
||||
shuttle_area_flag = SAVE_SHUTTLEAREA_DONTCARE,
|
||||
list/obj_blacklist = list(),
|
||||
list/obj_blacklist = typesof(/obj/effect),
|
||||
)
|
||||
var/width = maxx - minx
|
||||
var/height = maxy - miny
|
||||
var/depth = maxz - minz
|
||||
|
||||
if(!islist(obj_blacklist))
|
||||
CRASH("Non-list being used as object blacklist for map writing")
|
||||
|
||||
// we want to keep crayon writings, blood splatters, cobwebs, etc.
|
||||
obj_blacklist -= typesof(/obj/effect/decal)
|
||||
obj_blacklist -= typesof(/obj/effect/turf_decal)
|
||||
obj_blacklist -= typesof(/obj/effect/landmark) // most landmarks get deleted except for latejoin arrivals shuttle
|
||||
|
||||
//Step 0: Calculate the amount of letters we need (26 ^ n > turf count)
|
||||
var/turfs_needed = width * height
|
||||
var/layers = FLOOR(log(GLOB.save_file_chars.len, turfs_needed) + 0.999,1)
|
||||
@@ -221,6 +248,10 @@ GLOBAL_LIST_INIT(save_file_chars, list(
|
||||
place = /turf/template_noop
|
||||
location = /area/template_noop
|
||||
pull_from = null
|
||||
//====Saving holodeck areas====
|
||||
// All hologram objects get skipped and floor tiles get replaced with empty plating
|
||||
if(ispath(location, /area/station/holodeck) && istype(place, /turf/open/floor/holofloor))
|
||||
place = /turf/open/floor/holofloor/plating
|
||||
//====For toggling not saving areas and turfs====
|
||||
if(!(save_flag & SAVE_AREAS))
|
||||
location = /area/template_noop
|
||||
@@ -239,6 +270,11 @@ GLOBAL_LIST_INIT(save_file_chars, list(
|
||||
CHECK_TICK
|
||||
if(obj_blacklist[thing.type])
|
||||
continue
|
||||
if(thing.flags_1 & HOLOGRAM_1)
|
||||
continue
|
||||
if(is_multi_tile_object(thing) && (thing.loc != pull_from))
|
||||
continue
|
||||
|
||||
var/metadata = generate_tgm_metadata(thing)
|
||||
current_header += "[empty ? "" : ",\n"][thing.type][metadata]"
|
||||
empty = FALSE
|
||||
@@ -272,8 +308,8 @@ GLOBAL_LIST_INIT(save_file_chars, list(
|
||||
|
||||
/proc/generate_tgm_metadata(atom/object)
|
||||
var/list/data_to_add = list()
|
||||
|
||||
var/list/vars_to_save = object.get_save_vars()
|
||||
|
||||
for(var/variable in vars_to_save)
|
||||
CHECK_TICK
|
||||
var/value = object.vars[variable]
|
||||
@@ -281,6 +317,8 @@ GLOBAL_LIST_INIT(save_file_chars, list(
|
||||
continue
|
||||
if(variable == "icon_state" && object.smoothing_flags)
|
||||
continue
|
||||
if(variable == "icon" && object.smoothing_flags)
|
||||
continue
|
||||
|
||||
var/text_value = tgm_encode(value)
|
||||
if(!text_value)
|
||||
|
||||
@@ -706,6 +706,9 @@
|
||||
/// the type of wallframe it 'disassembles' into
|
||||
var/wallframe_type = /obj/item/wallframe/painting
|
||||
|
||||
/obj/structure/sign/painting/get_save_vars()
|
||||
return ..() - NAMEOF(src, icon)
|
||||
|
||||
/obj/structure/sign/painting/Initialize(mapload, dir, building)
|
||||
. = ..()
|
||||
SSpersistent_paintings.painting_frames += src
|
||||
|
||||
@@ -87,6 +87,9 @@ GLOBAL_LIST_EMPTY_TYPED(air_alarms, /obj/machinery/airalarm)
|
||||
fire = 90
|
||||
acid = 30
|
||||
|
||||
/obj/machinery/airalarm/get_save_vars()
|
||||
return ..() - NAMEOF(src, name)
|
||||
|
||||
/obj/machinery/airalarm/Initialize(mapload, ndir, nbuild)
|
||||
. = ..()
|
||||
set_wires(new /datum/wires/airalarm(src))
|
||||
|
||||
@@ -19,6 +19,18 @@
|
||||
///Handles whether the custom reconcilation handling should be used
|
||||
var/custom_reconcilation = FALSE
|
||||
|
||||
/obj/machinery/atmospherics/components/get_save_vars()
|
||||
. = ..()
|
||||
if(!override_naming)
|
||||
// Prevents saving the dynamic name with \proper due to it converting to "???"
|
||||
. -= NAMEOF(src, name)
|
||||
. += NAMEOF(src, welded)
|
||||
return .
|
||||
|
||||
/obj/machinery/atmospherics/components/Initialize(mapload)
|
||||
. = ..()
|
||||
update_appearance()
|
||||
|
||||
/obj/machinery/atmospherics/components/New()
|
||||
parents = new(device_type)
|
||||
airs = new(device_type)
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
unsuitable_heat_damage = 0
|
||||
ai_controller = /datum/ai_controller/basic_controller/dark_wizard
|
||||
|
||||
/mob/living/basic/dark_wizard/get_save_vars()
|
||||
return ..() - NAMEOF(src, icon_state) // icon_state is applied via apply_dynamic_human_appearance()
|
||||
|
||||
/mob/living/basic/dark_wizard/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
var/datum/picture/picture
|
||||
var/scribble //Scribble on the back.
|
||||
|
||||
/obj/item/photo/get_save_vars()
|
||||
return ..() - NAMEOF(src, icon)
|
||||
|
||||
/obj/item/photo/Initialize(mapload, datum/picture/P, datum_name = TRUE, datum_desc = TRUE)
|
||||
set_picture(P, datum_name, datum_desc, TRUE)
|
||||
//Photos are quite rarer than papers, so they're more likely to be added to the queue to make things even.
|
||||
|
||||
@@ -151,6 +151,26 @@
|
||||
fire = 90
|
||||
acid = 50
|
||||
|
||||
/obj/machinery/power/apc/get_save_vars()
|
||||
. = ..()
|
||||
if(!auto_name)
|
||||
. -= NAMEOF(src, name)
|
||||
. += NAMEOF(src, opened)
|
||||
. += NAMEOF(src, coverlocked)
|
||||
. += NAMEOF(src, lighting)
|
||||
. += NAMEOF(src, equipment)
|
||||
. += NAMEOF(src, environ)
|
||||
|
||||
. += NAMEOF(src, cell_type)
|
||||
if(cell_type)
|
||||
start_charge = cell.charge / cell.maxcharge // only used in Initialize() so direct edit is fine
|
||||
. += NAMEOF(src, start_charge)
|
||||
|
||||
// TODO save the wire data but need to include states for cute wires, signalers attached to wires, etc.
|
||||
//. += NAMEOF(src, shorted)
|
||||
//. += NAMEOF(src, locked)
|
||||
return .
|
||||
|
||||
/obj/machinery/power/apc/Initialize(mapload, ndir)
|
||||
. = ..()
|
||||
//APCs get added to their own processing tasks for the machines subsystem.
|
||||
@@ -212,7 +232,8 @@
|
||||
if(cell_type)
|
||||
cell = new cell_type(src)
|
||||
cell.charge = start_charge * cell.maxcharge / 100 // (convert percentage to actual value)
|
||||
make_terminal()
|
||||
if(!locate(/obj/machinery/power/terminal) in loc)
|
||||
make_terminal()
|
||||
///This is how we test to ensure that mappers use the directional subtypes of APCs, rather than use the parent and pixel-shift it themselves.
|
||||
if(abs(offset_old) != APC_PIXEL_OFFSET)
|
||||
log_mapping("APC: ([src]) at [AREACOORD(src)] with dir ([dir] | [uppertext(dir2text(dir))]) has pixel_[dir & (WEST|EAST) ? "x" : "y"] value [offset_old] - should be [dir & (SOUTH|EAST) ? "-" : ""][APC_PIXEL_OFFSET]. Use the directional/ helpers!")
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
/obj/machinery/power/apc/proc/make_terminal(terminal_cable_layer = cable_layer)
|
||||
// create a terminal object at the same position as original turf loc
|
||||
// wires will attach to this
|
||||
terminal = new/obj/machinery/power/terminal(loc)
|
||||
terminal = new /obj/machinery/power/terminal(loc)
|
||||
terminal.cable_layer = terminal_cable_layer
|
||||
terminal.setDir(dir)
|
||||
terminal.master = src
|
||||
|
||||
@@ -38,6 +38,12 @@
|
||||
/obj/item/stock_parts/power_store/get_cell()
|
||||
return src
|
||||
|
||||
/obj/item/stock_parts/power_store/get_save_vars()
|
||||
. = ..()
|
||||
. += NAMEOF(src, charge)
|
||||
. += NAMEOF(src, rigged)
|
||||
return .
|
||||
|
||||
/obj/item/stock_parts/power_store/Initialize(mapload, override_maxcharge)
|
||||
. = ..()
|
||||
create_reagents(5, INJECTABLE | DRAINABLE)
|
||||
|
||||
@@ -49,6 +49,14 @@
|
||||
if(!terminal)
|
||||
. += span_warning("This [src] has no power terminal!")
|
||||
|
||||
/obj/machinery/power/smes/get_save_vars()
|
||||
. = ..()
|
||||
. += NAMEOF(src, charge)
|
||||
. += NAMEOF(src, capacity)
|
||||
. += NAMEOF(src, input_level)
|
||||
. += NAMEOF(src, output_level)
|
||||
return .
|
||||
|
||||
/obj/machinery/power/smes/Initialize(mapload)
|
||||
. = ..()
|
||||
dir_loop:
|
||||
|
||||
@@ -6,11 +6,16 @@
|
||||
|
||||
/// Map template to load when the dock is loaded
|
||||
var/datum/map_template/shuttle/roundstart_template
|
||||
/// The shuttle template id to use after roundstart
|
||||
var/shuttle_template_id
|
||||
/// Used to check if the shuttle template is enabled in the config file
|
||||
var/json_key
|
||||
///If true, the shuttle can always dock at this docking port, despite its area checks, or if something is already docked
|
||||
var/override_can_dock_checks = FALSE
|
||||
|
||||
/obj/docking_port/stationary/get_save_vars()
|
||||
return ..() + NAMEOF(src, roundstart_template)
|
||||
|
||||
/obj/docking_port/stationary/Initialize(mapload)
|
||||
. = ..()
|
||||
register()
|
||||
@@ -76,18 +81,18 @@
|
||||
/obj/docking_port/stationary/proc/load_roundstart()
|
||||
if(json_key)
|
||||
var/sid = SSmapping.current_map.shuttles[json_key]
|
||||
roundstart_template = SSmapping.shuttle_templates[sid]
|
||||
if(!roundstart_template)
|
||||
shuttle_template_id = SSmapping.shuttle_templates[sid]
|
||||
if(!shuttle_template_id)
|
||||
CRASH("json_key:[json_key] value \[[sid]\] resulted in a null shuttle template for [src]")
|
||||
else if(roundstart_template) // passed a PATH
|
||||
var/sid = "[initial(roundstart_template.port_id)]_[initial(roundstart_template.suffix)]"
|
||||
|
||||
roundstart_template = SSmapping.shuttle_templates[sid]
|
||||
if(!roundstart_template)
|
||||
CRASH("Invalid path ([sid]/[roundstart_template]) passed to docking port.")
|
||||
shuttle_template_id = SSmapping.shuttle_templates[sid]
|
||||
if(!shuttle_template_id)
|
||||
CRASH("Invalid path ([sid]/[shuttle_template_id]) passed to docking port.")
|
||||
|
||||
if(roundstart_template)
|
||||
SSshuttle.action_load(roundstart_template, src)
|
||||
if(shuttle_template_id)
|
||||
SSshuttle.action_load(shuttle_template_id, src)
|
||||
|
||||
//returns first-found touching shuttleport
|
||||
/obj/docking_port/stationary/get_docked()
|
||||
|
||||
Reference in New Issue
Block a user