mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-07-16 09:34:52 +01:00
Replaces bapi-dmm with /tg/'s modernest maploader (#19122)
* Replaces bapi-dmm with /tg/'s modernest maploader * Fix workflows
This commit is contained in:
@@ -1,38 +0,0 @@
|
||||
//THIS FILE IS AUTOMATICALLY GENERATED BY BAPI_DMM_READER, PLEASE DO NOT TOUCH IT
|
||||
//PROC DEFINITIONS MAY MOVE AROUND, THIS IS NORMAL
|
||||
|
||||
/* This comment bypasses grep checks */ /var/__bapi_dmm_reader
|
||||
|
||||
/proc/__detect_bapi_dmm_reader()
|
||||
if (world.system_type == UNIX)
|
||||
if(fexists("./libbapi_dmm_reader.so"))
|
||||
// No need for LD_LIBRARY_PATH badness.
|
||||
return __bapi_dmm_reader = "./libbapi_dmm_reader.so"
|
||||
// It's not in the current directory, so try others
|
||||
return __bapi_dmm_reader = "libbapi_dmm_reader"
|
||||
else
|
||||
return __bapi_dmm_reader = "bapi_dmm_reader"
|
||||
|
||||
#define BAPI_DMM_READER (__bapi_dmm_reader || __detect_bapi_dmm_reader())
|
||||
|
||||
/proc/_bapidmm_test_connection()
|
||||
return call_ext(BAPI_DMM_READER, "byond:_bapidmm_test_connection_ffi")()
|
||||
|
||||
/proc/_bapidmm_parse_map_blocking(dmm_file, map_datum)
|
||||
return call_ext(BAPI_DMM_READER, "byond:_bapidmm_parse_map_blocking_ffi")(dmm_file, map_datum)
|
||||
|
||||
/proc/_bapidmm_load_map_buffered(parsed_map, x_offset, y_offset, z_offset, crop_map, no_changeturf, x_lower,
|
||||
x_upper, y_lower, y_upper, z_lower, z_upper, place_on_top, new_z)
|
||||
return call_ext(BAPI_DMM_READER, "byond:_bapidmm_load_map_buffered_ffi")(parsed_map, x_offset, y_offset, z_offset, crop_map, no_changeturf, x_lower,
|
||||
x_upper, y_lower, y_upper, z_lower, z_upper, place_on_top, new_z)
|
||||
|
||||
/proc/_bapidmm_work_commandbuffer(parsed_map, resume_key)
|
||||
return call_ext(BAPI_DMM_READER, "byond:_bapidmm_work_commandbuffer_ffi")(parsed_map, resume_key)
|
||||
|
||||
/proc/_bapidmm_clear_map_data()
|
||||
return call_ext(BAPI_DMM_READER, "byond:_bapidmm_clear_map_data_ffi")()
|
||||
|
||||
/proc/bapidmm_generate_automata(limit_x, limit_y, iterations, initial_wall_cell)
|
||||
return call_ext(BAPI_DMM_READER, "byond:bapidmm_generate_automata_ffi")(limit_x, limit_y, iterations, initial_wall_cell)
|
||||
|
||||
#undef BAPI_DMM_READER
|
||||
@@ -1,274 +0,0 @@
|
||||
// This file provides manually written utility types and such for the BAPI DMM Reader
|
||||
|
||||
GLOBAL_LIST_EMPTY(cached_maps)
|
||||
|
||||
GLOBAL_VAR_INIT(use_preloader, FALSE)
|
||||
GLOBAL_VAR_INIT(_preloader_path, null)
|
||||
GLOBAL_LIST_EMPTY(_preloader_attributes)
|
||||
|
||||
/world/proc/preloader_setup(list/the_attributes, path)
|
||||
if(LAZYLEN(the_attributes))
|
||||
GLOB.use_preloader = TRUE
|
||||
GLOB._preloader_attributes = the_attributes
|
||||
GLOB._preloader_path = path
|
||||
|
||||
/world/proc/preloader_load(atom/what)
|
||||
GLOB.use_preloader = FALSE
|
||||
var/list/attributes = GLOB._preloader_attributes
|
||||
for(var/attribute in attributes)
|
||||
var/value = attributes[attribute]
|
||||
if(islist(value))
|
||||
value = deepCopyList(value)
|
||||
#ifdef TESTING
|
||||
if(what.vars[attribute] == value)
|
||||
var/message = span_green("[what.type]") + " at [AREACOORD(what)] - " + span_bold("VAR:") + " " + span_red("[attribute] = [isnull(value) ? "null" : (isnum(value) ? value : "\"[value]\"")]")
|
||||
world.log << "DIRTY VAR: [message]"
|
||||
dirty_vars += message
|
||||
#endif
|
||||
what.vars[attribute] = value
|
||||
|
||||
#define MAP_DMM "dmm"
|
||||
/**
|
||||
* TGM SPEC:
|
||||
* TGM is a derevation of DMM, with restrictions placed on it
|
||||
* to make it easier to parse and to reduce merge conflicts/ease their resolution
|
||||
*
|
||||
* Requirements:
|
||||
* Each "statement" in a key's details ends with a new line, and wrapped in (...)
|
||||
* All paths end with either a comma or occasionally a {, then a new line
|
||||
* Excepting the area, who is listed last and ends with a ) to mark the end of the key
|
||||
*
|
||||
* {} denotes a list of variable edits applied to the path that came before the first {
|
||||
* the final } is followed by a comma, and then a new line
|
||||
* Variable edits have the form \tname = value;\n
|
||||
* Except the last edit, which has no final ;, and just ends in a newline
|
||||
* No extra padding is permitted
|
||||
* Many values are supported. See parse_constant()
|
||||
* Strings must be wrapped in "...", files in '...', and lists in list(...)
|
||||
* Files are kinda susy, and may not actually work. buyer beware
|
||||
* Lists support assoc values as expected
|
||||
* These constants can be further embedded into lists
|
||||
*
|
||||
* There can be no padding in front of, or behind a path
|
||||
*
|
||||
* Therefore:
|
||||
* "key" = (
|
||||
* /path,
|
||||
* /other/path{
|
||||
* var = list("name" = 'filepath');
|
||||
* other_var = /path
|
||||
* },
|
||||
* /turf,
|
||||
* /area)
|
||||
*
|
||||
*/
|
||||
#define MAP_TGM "tgm"
|
||||
#define MAP_UNKNOWN "unknown"
|
||||
|
||||
/// Returned from parse_map to give some metadata about the map
|
||||
/datum/bapi_parsed_map
|
||||
var/_internal_index = -1
|
||||
|
||||
var/original_path = ""
|
||||
var/map_format = MAP_UNKNOWN
|
||||
var/key_len = 0
|
||||
var/line_len = 0
|
||||
var/expanded_y = FALSE
|
||||
var/expanded_x = FALSE
|
||||
|
||||
/// Unoffset bounds. Null on parse failure.
|
||||
var/list/bounds = list()
|
||||
/// Offset bounds. Same as parsed_bounds until load().
|
||||
var/list/parsed_bounds = list()
|
||||
|
||||
///any turf in this list is skipped inside of build_coordinate. Lazy assoc list
|
||||
var/list/turf_blacklist
|
||||
|
||||
var/loading = FALSE
|
||||
var/loaded_warnings = list()
|
||||
|
||||
/**
|
||||
* Helper and recommened way to load a map file
|
||||
* - dmm_file: The path to the map file
|
||||
* - x_offset: The x offset to load the map at
|
||||
* - y_offset: The y offset to load the map at
|
||||
* - z_offset: The z offset to load the map at
|
||||
* - crop_map: If true, the map will be cropped to the world bounds
|
||||
* - measure_only: If true, the map will not be loaded, but the bounds will be calculated
|
||||
* - no_changeturf: If true, the map will not call /turf/AfterChange
|
||||
* - x_lower: The minimum x coordinate to load
|
||||
* - x_upper: The maximum x coordinate to load
|
||||
* - y_lower: The minimum y coordinate to load
|
||||
* - y_upper: The maximum y coordinate to load
|
||||
* - z_lower: The minimum z coordinate to load
|
||||
* - z_upper: The maximum z coordinate to load
|
||||
* - place_on_top: Whether to use /turf/proc/PlaceOnTop rather than /turf/proc/ChangeTurf
|
||||
* - new_z: If true, a new z level will be created for the map
|
||||
*/
|
||||
/proc/load_map_bapi(
|
||||
dmm_file,
|
||||
x_offset = 1,
|
||||
y_offset = 1,
|
||||
z_offset,
|
||||
crop_map = FALSE,
|
||||
measure_only = FALSE,
|
||||
no_changeturf = FALSE,
|
||||
x_lower = -INFINITY,
|
||||
x_upper = INFINITY,
|
||||
y_lower = -INFINITY,
|
||||
y_upper = INFINITY,
|
||||
z_lower = -INFINITY,
|
||||
z_upper = INFINITY,
|
||||
place_on_top = FALSE,
|
||||
new_z = FALSE,
|
||||
)
|
||||
if(isfile(dmm_file))
|
||||
log_mapping("bapi-dmm was passed a file instead of a path string: [dmm_file]")
|
||||
var/name = sanitize_filename("[dmm_file]")
|
||||
var/path = "data/baked_dmm_files/[name]"
|
||||
if(!fexists(path))
|
||||
var/text = file2text(dmm_file)
|
||||
rustg_file_write(text, path)
|
||||
dmm_file = path
|
||||
|
||||
if(!fexists(dmm_file))
|
||||
stack_trace("Invalid map path: [dmm_file]")
|
||||
return
|
||||
|
||||
if(!(dmm_file in GLOB.cached_maps))
|
||||
GLOB.cached_maps[dmm_file] = new /datum/bapi_parsed_map(dmm_file)
|
||||
|
||||
// Bay assumption
|
||||
if(!z_offset)
|
||||
z_offset = world.maxz + 1
|
||||
|
||||
var/datum/bapi_parsed_map/parsed_map = GLOB.cached_maps[dmm_file]
|
||||
parsed_map = parsed_map.copy()
|
||||
if(!measure_only && !isnull(parsed_map.bounds))
|
||||
parsed_map.load(x_offset, y_offset, z_offset, crop_map, no_changeturf, x_lower, x_upper, y_lower, y_upper, z_lower, z_upper, place_on_top, new_z)
|
||||
return parsed_map
|
||||
|
||||
/datum/bapi_parsed_map/New(tfile)
|
||||
if(isnull(tfile))
|
||||
return // create a new datum without loading a map
|
||||
var/ret = _bapidmm_parse_map_blocking(tfile, src)
|
||||
if(!ret)
|
||||
CRASH("Failed to load map [tfile], check rust_log.txt")
|
||||
|
||||
/datum/bapi_parsed_map/Destroy()
|
||||
..()
|
||||
SSatoms.map_loader_stop(REF(src)) // Just in case, I don't want to double up here
|
||||
if(turf_blacklist)
|
||||
turf_blacklist.Cut()
|
||||
parsed_bounds.Cut()
|
||||
bounds.Cut()
|
||||
return QDEL_HINT_HARDDEL_NOW
|
||||
|
||||
/datum/bapi_parsed_map/proc/copy()
|
||||
// Avoids duped work just in case
|
||||
var/datum/bapi_parsed_map/newfriend = new()
|
||||
// use the same under-the-hood data
|
||||
newfriend._internal_index = _internal_index
|
||||
newfriend.original_path = original_path
|
||||
newfriend.map_format = map_format
|
||||
newfriend.key_len = key_len
|
||||
newfriend.line_len = line_len
|
||||
newfriend.parsed_bounds = parsed_bounds.Copy()
|
||||
// Copy parsed bounds to reset to initial values
|
||||
newfriend.bounds = parsed_bounds.Copy()
|
||||
newfriend.turf_blacklist = turf_blacklist?.Copy()
|
||||
// Explicitly do NOT copy `loaded` and `loaded_warnings`
|
||||
return newfriend
|
||||
|
||||
/datum/bapi_parsed_map/proc/load(
|
||||
x_offset = 1,
|
||||
y_offset = 1,
|
||||
z_offset = 1,
|
||||
crop_map = FALSE,
|
||||
no_changeturf = FALSE,
|
||||
x_lower = -INFINITY,
|
||||
x_upper = INFINITY,
|
||||
y_lower = -INFINITY,
|
||||
y_upper = INFINITY,
|
||||
z_lower = -INFINITY,
|
||||
z_upper = INFINITY,
|
||||
place_on_top = FALSE,
|
||||
new_z = FALSE,
|
||||
)
|
||||
Master.StartLoadingMap()
|
||||
. = _load_impl(x_offset, y_offset, z_offset, crop_map, no_changeturf, x_lower, x_upper, y_lower, y_upper, z_lower, z_upper, place_on_top, new_z)
|
||||
Master.StopLoadingMap()
|
||||
|
||||
/datum/bapi_parsed_map/proc/_load_impl(
|
||||
x_offset = 1,
|
||||
y_offset = 1,
|
||||
z_offset = 1,
|
||||
crop_map = FALSE,
|
||||
no_changeturf = FALSE,
|
||||
x_lower = -INFINITY,
|
||||
x_upper = INFINITY,
|
||||
y_lower = -INFINITY,
|
||||
y_upper = INFINITY,
|
||||
z_lower = -INFINITY,
|
||||
z_upper = INFINITY,
|
||||
place_on_top = FALSE,
|
||||
new_z = FALSE,
|
||||
)
|
||||
PRIVATE_PROC(TRUE)
|
||||
SSatoms.map_loader_begin(REF(src))
|
||||
|
||||
// `loading` var handled by bapidmm
|
||||
var/resume_key = _bapidmm_load_map_buffered(
|
||||
src,
|
||||
x_offset,
|
||||
y_offset,
|
||||
z_offset,
|
||||
crop_map,
|
||||
no_changeturf,
|
||||
x_lower,
|
||||
x_upper,
|
||||
y_lower,
|
||||
y_upper,
|
||||
z_lower,
|
||||
z_upper,
|
||||
place_on_top,
|
||||
new_z
|
||||
)
|
||||
|
||||
if(!resume_key)
|
||||
SSatoms.map_loader_stop(REF(src))
|
||||
CRASH("Failed to generate command buffer, check rust_log.txt and other runtimes")
|
||||
|
||||
var/work_remaining = FALSE
|
||||
do
|
||||
work_remaining = _bapidmm_work_commandbuffer(src, resume_key)
|
||||
stoplag()
|
||||
while(work_remaining)
|
||||
|
||||
SSatoms.map_loader_stop(REF(src))
|
||||
|
||||
// if(new_z)
|
||||
// for(var/z_index in bounds[MAP_MINZ] to bounds[MAP_MAXZ])
|
||||
// SSmapping.build_area_turfs(z_index)
|
||||
|
||||
// if(!no_changeturf)
|
||||
// var/list/turfs = block(
|
||||
// locate(bounds[MAP_MINX], bounds[MAP_MINY], bounds[MAP_MINZ]),
|
||||
// locate(bounds[MAP_MAXX], bounds[MAP_MAXY], bounds[MAP_MAXZ]))
|
||||
// for(var/turf/T as anything in turfs)
|
||||
// //we do this after we load everything in. if we don't, we'll have weird atmos bugs regarding atmos adjacent turfs
|
||||
// T.AfterChange(CHANGETURF_IGNORE_AIR)
|
||||
|
||||
// if(expanded_x || expanded_y)
|
||||
// SEND_GLOBAL_SIGNAL(COMSIG_GLOB_EXPANDED_WORLD_BOUNDS, expanded_x, expanded_y)
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/bapi_parsed_map/proc/has_warnings()
|
||||
if(length(loaded_warnings))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
// #undef MAP_DMM
|
||||
// #undef MAP_TGM
|
||||
// #undef MAP_UNKNOWN
|
||||
@@ -1,110 +0,0 @@
|
||||
// Internal bapi-dmm helpers
|
||||
/datum/bapi_parsed_map/proc/_bapi_add_warning(warning)
|
||||
loaded_warnings += list(warning)
|
||||
|
||||
/datum/bapi_parsed_map/proc/_bapi_expand_map(x, y, z, new_z, z_offset)
|
||||
if(x > world.maxx)
|
||||
expanded_x = TRUE
|
||||
world.maxx = x
|
||||
// if(new_z)
|
||||
// world.increase_max_x(x, map_load_z_cutoff = z_offset - 1)
|
||||
// else
|
||||
// world.increase_max_x(x)
|
||||
if(y > world.maxy)
|
||||
expanded_y = TRUE
|
||||
world.maxy = y
|
||||
// if(new_z)
|
||||
// world.increase_max_y(y, map_load_z_cutoff = z_offset - 1)
|
||||
// else
|
||||
// world.increase_max_y(y)
|
||||
if(z > world.maxz)
|
||||
while(world.maxz < z)
|
||||
world.increment_max_z()
|
||||
|
||||
/proc/_bapi_helper_get_world_bounds()
|
||||
. = list(world.maxx, world.maxy, world.maxz)
|
||||
|
||||
/proc/_bapi_helper_text2path(text)
|
||||
. = text2path(text)
|
||||
|
||||
/proc/_bapi_helper_text2file(text)
|
||||
. = file(text)
|
||||
|
||||
/proc/_bapi_create_atom(path, crds)
|
||||
set waitfor = FALSE
|
||||
. = new path (crds)
|
||||
|
||||
/proc/_bapi_setup_preloader(list/attributes, path)
|
||||
world.preloader_setup(attributes, path)
|
||||
|
||||
/proc/_bapi_apply_preloader(atom/A)
|
||||
if(GLOB.use_preloader)
|
||||
world.preloader_load(A)
|
||||
|
||||
/proc/_bapi_new_atom(text_path, turf/crds, list/attributes)
|
||||
var/path = text2path(text_path)
|
||||
if(!path)
|
||||
CRASH("Bad atom path [text_path]")
|
||||
|
||||
if(attributes != null)
|
||||
world.preloader_setup(attributes, path)
|
||||
|
||||
var/atom/instance = _bapi_create_atom(path, crds) // first preloader pass
|
||||
|
||||
if(GLOB.use_preloader && instance) // second preloader pass for atoms that don't ..() in New()
|
||||
world.preloader_load(instance)
|
||||
|
||||
/proc/_bapi_create_or_get_area(text_path)
|
||||
var/path = text2path(text_path)
|
||||
if(!path)
|
||||
CRASH("Bad area path [text_path]")
|
||||
|
||||
var/area/area_instance = GLOB.areas_by_type[path]
|
||||
if(!area_instance)
|
||||
area_instance = new path(null)
|
||||
if(!area_instance)
|
||||
CRASH("[path] failed to be new'd, what'd you do?")
|
||||
|
||||
return area_instance
|
||||
|
||||
/proc/_bapi_handle_area_contain(turf/T, area/A)
|
||||
// var/area/old_area = T.loc
|
||||
// if(old_area == A)
|
||||
// return // no changing areas that already contain this turf, it'll confuse them
|
||||
// LISTASSERTLEN(old_area.turfs_to_uncontain_by_zlevel, T.z, list())
|
||||
// LISTASSERTLEN(A.turfs_by_zlevel, T.z, list())
|
||||
// old_area.turfs_to_uncontain_by_zlevel[T.z] += T
|
||||
// A.turfs_by_zlevel[T.z] += T
|
||||
|
||||
/proc/_bapi_create_turf(turf/crds, text_path, list/attributes, place_on_top, no_changeturf)
|
||||
var/path = text2path(text_path)
|
||||
if(!path)
|
||||
CRASH("Bad turf path [text_path]")
|
||||
|
||||
if(attributes != null)
|
||||
world.preloader_setup(attributes, path)
|
||||
|
||||
var/atom/instance
|
||||
if(no_changeturf)
|
||||
instance = _bapi_create_atom(path, crds)
|
||||
else
|
||||
instance = crds.ChangeTurf(path, FALSE, TRUE)
|
||||
|
||||
if(GLOB.use_preloader && instance) // second preloader pass for atoms that don't ..() in New()
|
||||
world.preloader_load(instance)
|
||||
|
||||
/proc/_bapi_add_turf_to_area(area/A, turf/T)
|
||||
if(!A || !T)
|
||||
return
|
||||
A.contents.Add(T)
|
||||
|
||||
/proc/_bapi_helper_get_world_type_turf()
|
||||
return "[world.turf]"
|
||||
|
||||
/proc/_bapi_helper_get_world_type_area()
|
||||
return "[world.area]"
|
||||
|
||||
/// Implement this to have bapi-dmm sleep occasionally
|
||||
/// by returning true
|
||||
/proc/_bapi_helper_tick_check()
|
||||
return TICK_CHECK
|
||||
@@ -1,12 +1,16 @@
|
||||
/datum/map_template
|
||||
var/name = "Default Template Name"
|
||||
var/desc = "Some text should go here. Maybe."
|
||||
var/name_alias // Override to what this map gets registered as in map_templates_loaded
|
||||
var/template_group = null // If this is set, no more than one template in the same group will be spawned, per submap seeding.
|
||||
var/width = 0
|
||||
var/height = 0
|
||||
var/mappath = null
|
||||
var/loaded = 0 // Times loaded this round
|
||||
var/datum/parsed_map/cached_map
|
||||
var/keep_cached_map = FALSE
|
||||
|
||||
// Virgo stuff
|
||||
var/desc = "Some text should go here. Maybe."
|
||||
var/name_alias // Override to what this map gets registered as in map_templates_loaded
|
||||
var/template_group = null // If this is set, no more than one template in the same group will be spawned, per submap seeding.
|
||||
var/annihilate = FALSE // If true, all (movable) atoms at the location where the map is loaded will be deleted before the map is loaded in.
|
||||
|
||||
var/cost = null /* The map generator has a set 'budget' it spends to place down different submaps. It will pick available submaps randomly until
|
||||
@@ -15,26 +19,28 @@
|
||||
var/allow_duplicates = FALSE // If false, only one map template will be spawned by the game. Doesn't affect admins spawning then manually.
|
||||
var/discard_prob = 0 // If non-zero, there is a chance that the map seeding algorithm will skip this template when selecting potential templates to use.
|
||||
|
||||
/datum/map_template/New(path = null, rename = null)
|
||||
/datum/map_template/New(path = null, rename = null, cache = FALSE)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
. = ..()
|
||||
if(path)
|
||||
mappath = path
|
||||
if(mappath)
|
||||
preload_size(mappath)
|
||||
preload_size(mappath, cache)
|
||||
if(rename)
|
||||
name = rename
|
||||
|
||||
/datum/map_template/proc/preload_size(path)
|
||||
var/datum/bapi_parsed_map/map = load_map_bapi(path, 1, 1, 1, crop_map=FALSE, measure_only=TRUE)
|
||||
var/list/bounds = map.parsed_bounds
|
||||
/datum/map_template/proc/preload_size(path, cache = FALSE)
|
||||
var/datum/parsed_map/parsed = new(file(path))
|
||||
var/bounds = parsed?.bounds
|
||||
if(bounds)
|
||||
width = bounds[MAP_MAXX] // Assumes all templates are rectangular, have a single Z level, and begin at 1,1,1
|
||||
height = bounds[MAP_MAXY]
|
||||
if(cache)
|
||||
cached_map = parsed
|
||||
return bounds
|
||||
|
||||
/datum/map_template/proc/initTemplateBounds(var/list/bounds)
|
||||
if (SSatoms.initialized == INITIALIZATION_INSSATOMS)
|
||||
/datum/map_template/proc/initTemplateBounds(list/bounds)
|
||||
if(SSatoms.initialized == INITIALIZATION_INSSATOMS)
|
||||
return // let proper initialisation handle it later
|
||||
|
||||
var/prev_shuttle_queue_state = SSshuttles.block_init_queue
|
||||
@@ -92,9 +98,20 @@
|
||||
x = round((world.maxx - width)/2)
|
||||
y = round((world.maxy - height)/2)
|
||||
|
||||
on_map_preload(world.maxz + 1) //VOREStation Edit
|
||||
var/datum/bapi_parsed_map/map = load_map_bapi(mappath, x, y, no_changeturf = TRUE)
|
||||
var/list/bounds = map.bounds
|
||||
// This would normally be handled by SSmapping
|
||||
world.increment_max_z()
|
||||
|
||||
on_map_preload(world.maxz) //VOREStation Edit
|
||||
var/datum/parsed_map/parsed = load_map(
|
||||
file(mappath),
|
||||
x,
|
||||
y,
|
||||
world.maxz,
|
||||
no_changeturf = TRUE, // (SSatoms.initialized == INITIALIZATION_INSSATOMS),
|
||||
place_on_top = FALSE, // should_place_on_top,
|
||||
new_z = TRUE,
|
||||
)
|
||||
var/list/bounds = parsed.bounds
|
||||
if(!bounds)
|
||||
return FALSE
|
||||
|
||||
@@ -120,11 +137,24 @@
|
||||
if(annihilate)
|
||||
annihilate_bounds(old_T, centered)
|
||||
|
||||
var/datum/bapi_parsed_map/map = load_map_bapi(mappath, T.x, T.y, T.z, crop_map = TRUE)
|
||||
var/list/bounds = map.bounds
|
||||
if(!bounds)
|
||||
// Accept cached maps, but don't save them automatically - we don't want
|
||||
// ruins clogging up memory for the whole round.
|
||||
var/datum/parsed_map/parsed = cached_map || new(file(mappath))
|
||||
cached_map = keep_cached_map ? parsed : null
|
||||
|
||||
if(!parsed.load(
|
||||
T.x,
|
||||
T.y,
|
||||
T.z,
|
||||
crop_map = TRUE,
|
||||
no_changeturf = FALSE, // (SSatoms.initialized == INITIALIZATION_INSSATOMS), // otherwise space turfs break
|
||||
place_on_top = FALSE, // should_place_on_top,
|
||||
))
|
||||
return
|
||||
|
||||
var/list/bounds = parsed.bounds
|
||||
if(!bounds)
|
||||
return
|
||||
// if(!SSmapping.loading_ruins) //Will be done manually during mapping ss init
|
||||
// repopulate_sorted_areas()
|
||||
|
||||
@@ -138,10 +168,10 @@
|
||||
/datum/map_template/proc/get_affected_turfs(turf/T, centered = FALSE)
|
||||
var/turf/placement = T
|
||||
if(centered)
|
||||
var/turf/corner = locate(placement.x - round((width)/2), placement.y - round((height)/2), placement.z) // %180 catches East/West (90,270) rotations on true, North/South (0,180) rotations on false
|
||||
var/turf/corner = locate(placement.x - round(width/2), placement.y - round(height/2), placement.z)
|
||||
if(corner)
|
||||
placement = corner
|
||||
return block(placement, locate(placement.x+(width)-1, placement.y+(height)-1, placement.z))
|
||||
return block(placement.x, placement.y, placement.z, placement.x+width-1, placement.y+height-1, placement.z)
|
||||
|
||||
/datum/map_template/proc/annihilate_bounds(turf/origin, centered = FALSE)
|
||||
var/deleted_atoms = 0
|
||||
@@ -154,12 +184,32 @@
|
||||
qdel(AM)
|
||||
admin_notice(span_danger("Annihilated [deleted_atoms] objects."), R_DEBUG)
|
||||
|
||||
/// Takes in a type path, locates an instance of that type in the cached map, and calculates its offset from the origin of the map, returns this offset in the form list(x, y).
|
||||
/datum/map_template/proc/discover_offset(obj/marker)
|
||||
var/key
|
||||
var/list/models = cached_map.grid_models
|
||||
for(key in models)
|
||||
if(findtext(models[key], "[marker]")) // Yay compile time checks
|
||||
break // This works by assuming there will ever only be one mobile dock in a template at most
|
||||
|
||||
for(var/datum/grid_set/gset as anything in cached_map.gridSets)
|
||||
var/ycrd = gset.ycrd
|
||||
for(var/line in gset.gridLines)
|
||||
var/xcrd = gset.xcrd
|
||||
for(var/j in 1 to length(line) step cached_map.key_len)
|
||||
if(key == copytext(line, j, j + cached_map.key_len))
|
||||
return list(xcrd, ycrd)
|
||||
++xcrd
|
||||
--ycrd
|
||||
|
||||
//for your ever biggening badminnery kevinz000
|
||||
//❤ - Cyberboss
|
||||
/proc/load_new_z_level(var/file, var/name)
|
||||
var/datum/map_template/template = new(file, name)
|
||||
var/datum/map_template/template = new(file, name, TRUE)
|
||||
if(!template.cached_map || template.cached_map.check_for_errors())
|
||||
return FALSE
|
||||
template.load_new_z()
|
||||
return TRUE
|
||||
|
||||
// Very similar to the /tg/ version.
|
||||
/proc/seed_submaps(var/list/z_levels, var/budget = 0, var/whitelist = /area/space, var/desired_map_template_type = null)
|
||||
@@ -307,10 +357,3 @@
|
||||
else
|
||||
admin_notice("Submaps loaded.", R_DEBUG)
|
||||
admin_notice("Loaded: [english_list(pretty_submap_list)]", R_DEBUG)
|
||||
|
||||
/area/template_noop
|
||||
name = "Area Passthrough"
|
||||
|
||||
/turf/template_noop
|
||||
name = "Turf Passthrough"
|
||||
icon_state = "template_void"
|
||||
@@ -0,0 +1,31 @@
|
||||
GLOBAL_VAR_INIT(use_preloader, FALSE)
|
||||
GLOBAL_VAR_INIT(_preloader_path, null)
|
||||
GLOBAL_LIST_EMPTY(_preloader_attributes)
|
||||
|
||||
/world/proc/preloader_setup(list/the_attributes, path)
|
||||
if(LAZYLEN(the_attributes))
|
||||
GLOB.use_preloader = TRUE
|
||||
GLOB._preloader_attributes = the_attributes
|
||||
GLOB._preloader_path = path
|
||||
|
||||
/world/proc/preloader_load(atom/what)
|
||||
GLOB.use_preloader = FALSE
|
||||
var/list/attributes = GLOB._preloader_attributes
|
||||
for(var/attribute in attributes)
|
||||
var/value = attributes[attribute]
|
||||
if(islist(value))
|
||||
value = deepCopyList(value)
|
||||
#ifdef TESTING
|
||||
if(what.vars[attribute] == value)
|
||||
var/message = span_green("[what.type]") + " at [AREACOORD(what)] - " + span_bold("VAR:") + " " + span_red("[attribute] = [isnull(value) ? "null" : (isnum(value) ? value : "\"[value]\"")]")
|
||||
world.log << "DIRTY VAR: [message]"
|
||||
// dirty_vars += message
|
||||
#endif
|
||||
what.vars[attribute] = value
|
||||
|
||||
/area/template_noop
|
||||
name = "Area Passthrough"
|
||||
|
||||
/turf/template_noop
|
||||
name = "Turf Passthrough"
|
||||
icon_state = "template_void"
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,109 @@
|
||||
/// Global list of map report datums
|
||||
GLOBAL_LIST_EMPTY(map_reports)
|
||||
|
||||
/// An error report generated by [/datum/parsed_map/proc/check_for_errors].
|
||||
/datum/map_report
|
||||
var/original_path
|
||||
var/list/bad_paths = list()
|
||||
var/list/bad_keys = list()
|
||||
/// Whether this map can be loaded safely despite the errors.
|
||||
var/loadable = TRUE
|
||||
var/crashed = TRUE
|
||||
|
||||
var/static/tag_number = 0
|
||||
|
||||
/datum/map_report/New(datum/parsed_map/map)
|
||||
original_path = map.original_path || "Untitled"
|
||||
GLOB.map_reports += src
|
||||
|
||||
/datum/map_report/Destroy(force)
|
||||
GLOB.map_reports -= src
|
||||
return ..()
|
||||
|
||||
|
||||
/// Show a rendered version of this report to a client.
|
||||
/datum/map_report/proc/show_to(client/C)
|
||||
var/list/html = list()
|
||||
if(crashed)
|
||||
html += "<p><b>Validation crashed</b>: check the runtime logs.</p>"
|
||||
if(!loadable)
|
||||
html += "<p><b>Not loadable</b>: some tiles are missing their turfs or areas.</p>"
|
||||
|
||||
if(bad_paths.len)
|
||||
html += "<p>Bad paths: <ol>"
|
||||
for(var/path in bad_paths)
|
||||
var/list/keys = bad_paths[path]
|
||||
html += "<li><tt>[path]</tt>: used in ([keys.len]): <tt>[keys.Join("</tt>, <tt>")]</tt>"
|
||||
html += "</ol></p>"
|
||||
|
||||
if(bad_keys.len)
|
||||
html += "<p>Bad keys: <ul>"
|
||||
for(var/key in bad_keys)
|
||||
var/list/messages = bad_keys[key]
|
||||
html += "<li><tt>[key]</tt>"
|
||||
if(messages.len == 1)
|
||||
html += ": [bad_keys[key][1]]"
|
||||
else
|
||||
html += "<ul><li>[messages.Join("</li><li>")]</li></ul>"
|
||||
html += "</li>"
|
||||
html += "</ul></p>"
|
||||
var/datum/browser/browser = new(C.mob, "[tag]", "Report for map file [original_path]", 600, 400)
|
||||
browser.set_content(html.Join())
|
||||
browser.open()
|
||||
|
||||
/datum/map_report/Topic(href, href_list)
|
||||
. = ..()
|
||||
if(. || !check_rights(R_ADMIN, FALSE) || !usr.client.holder.CheckAdminHref(href, href_list))
|
||||
return
|
||||
|
||||
if (href_list["show"])
|
||||
show_to(usr)
|
||||
|
||||
|
||||
/// Check a parsed but not yet loaded map for errors.
|
||||
///
|
||||
/// Returns a [/datum/map_report] if there are errors or `FALSE` otherwise.
|
||||
/datum/parsed_map/proc/check_for_errors()
|
||||
var/datum/map_report/report = new(src)
|
||||
. = report
|
||||
|
||||
// build_cache will check bad paths for us
|
||||
var/list/modelCache = build_cache(TRUE, report.bad_paths)
|
||||
|
||||
var/static/regex/area_or_turf = regex(@"/(turf|area)/")
|
||||
for(var/path in report.bad_paths)
|
||||
if(area_or_turf.Find("[path]", 1, 1))
|
||||
report.loadable = FALSE
|
||||
|
||||
// check for tiles with the wrong number of turfs or areas
|
||||
for(var/key in modelCache)
|
||||
if(key == SPACE_KEY)
|
||||
continue
|
||||
var/model = modelCache[key]
|
||||
var/list/members = model[1]
|
||||
|
||||
var/turfs = 0
|
||||
var/areas = 0
|
||||
for(var/i in 1 to members.len)
|
||||
var/atom/path = members[i]
|
||||
|
||||
turfs += ispath(path, /turf)
|
||||
areas += ispath(path, /area)
|
||||
|
||||
if(turfs == 0)
|
||||
report.loadable = FALSE
|
||||
LAZYADD(report.bad_keys[key], "no turf")
|
||||
else if(turfs > 1)
|
||||
LAZYADD(report.bad_keys[key], "[turfs] stacked turfs")
|
||||
|
||||
if(areas != 1)
|
||||
report.loadable = FALSE
|
||||
LAZYADD(report.bad_keys[key], "[areas] areas instead of 1")
|
||||
|
||||
// return the report
|
||||
if(report.bad_paths.len || report.bad_keys.len || !report.loadable)
|
||||
// keep the report around so it can be referenced later
|
||||
report.tag = "mapreport_[++report.tag_number]"
|
||||
report.crashed = FALSE
|
||||
else
|
||||
return FALSE
|
||||
Reference in New Issue
Block a user