mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2025-12-20 23:31:04 +00:00
Refactor dmm_suite for readability
Clean up arguments, comments and paths of /dmm_suite (now /datum/dmm_suite) to increase readability should other developers want to take a look at it
This commit is contained in:
@@ -17,7 +17,7 @@
|
||||
name = rename
|
||||
|
||||
/datum/map_template/proc/preload_size(path)
|
||||
var/bounds = GLOB.maploader.load_map(file(path), 1, 1, 1, cropMap = 0, measureOnly = 1)
|
||||
var/bounds = GLOB.maploader.load_map(file(path), 1, 1, 1, shouldCropMap = FALSE, measureOnly = TRUE)
|
||||
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]
|
||||
@@ -49,7 +49,7 @@
|
||||
// if given a multi-z template
|
||||
// it might need to be adapted for that when that time comes
|
||||
GLOB.space_manager.add_dirt(placement.z)
|
||||
var/list/bounds = GLOB.maploader.load_map(get_file(), min_x, min_y, placement.z, cropMap = 1)
|
||||
var/list/bounds = GLOB.maploader.load_map(get_file(), min_x, min_y, placement.z, shouldCropMap = TRUE)
|
||||
if(!bounds)
|
||||
return 0
|
||||
if(bot_left == null || top_right == null)
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
GLOBAL_DATUM_INIT(maploader, /dmm_suite, new())
|
||||
dmm_suite{
|
||||
/*
|
||||
/*
|
||||
|
||||
dmm_suite version 1.0
|
||||
Released January 30th, 2011.
|
||||
@@ -50,23 +48,9 @@ dmm_suite{
|
||||
code, and that the /dmm_reader trusts that files to be loaded are in fact valid
|
||||
.dmm files. Errors in the .dmm format will cause runtime errors.
|
||||
|
||||
*/
|
||||
*/
|
||||
|
||||
verb/load_map(var/dmm_file as file, var/x_offset as num, var/y_offset as num, var/z_offset as num, do_sleep as num){
|
||||
// dmm_file: A .dmm file to load (Required).
|
||||
// z_offset: A number representing the z-level on which to start loading the map (Optional).
|
||||
}
|
||||
verb/write_map(var/turf/t1 as turf, var/turf/t2 as turf, var/flags as num){
|
||||
// t1: A turf representing one corner of a three dimensional grid (Required).
|
||||
// t2: Another turf representing the other corner of the same grid (Required).
|
||||
// flags: Any, or a combination, of several bit flags (Optional, see documentation).
|
||||
}
|
||||
GLOBAL_DATUM_INIT(maploader, /datum/dmm_suite, new())
|
||||
|
||||
// save_map is included as a legacy proc. Use write_map instead.
|
||||
verb/save_map(var/turf/t1 as turf, var/turf/t2 as turf, var/map_name as text, var/flags as num){
|
||||
// t1: A turf representing one corner of a three dimensional grid (Required).
|
||||
// t2: Another turf representing the other corner of the same grid (Required).
|
||||
// map_name: A valid name for the map to be saved, such as "castle" (Required).
|
||||
// flags: Any, or a combination, of several bit flags (Optional, see documentation).
|
||||
}
|
||||
}
|
||||
/datum/dmm_suite
|
||||
var/static/quote = "\""
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
///////////////////////////////////////////////////////////////
|
||||
//SS13 Optimized Map loader
|
||||
// SS13 Optimized Map loader
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
//As of 3.6.2016
|
||||
//global datum that will preload variables on atoms instanciation
|
||||
// As of 3.6.2016
|
||||
// global datum that will preload variables on atoms instanciation
|
||||
GLOBAL_VAR_INIT(use_preloader, FALSE)
|
||||
GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
GLOBAL_DATUM_INIT(_preloader, /datum/dmm_suite/preloader, new())
|
||||
|
||||
/dmm_suite
|
||||
/datum/dmm_suite
|
||||
// These regexes are global - meaning that starting the maploader again mid-load will
|
||||
// reset progress - which means we need to track our index per-map, or we'll
|
||||
// eternally recurse
|
||||
@@ -37,13 +37,13 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
* atmos will attempt to start before it's ready, causing runtimes galore if init is
|
||||
* allowed to romp unchecked.
|
||||
*/
|
||||
/dmm_suite/load_map(dmm_file as file, x_offset as num, y_offset as num, z_offset as num, cropMap as num, measureOnly as num)
|
||||
var/tfile = dmm_file//the map file we're creating
|
||||
/datum/dmm_suite/proc/load_map(dmm_file, x_offset = 0, y_offset = 0, z_offset = 0, shouldCropMap = FALSE, measureOnly = FALSE)
|
||||
var/tfile = dmm_file// the map file we're creating
|
||||
var/fname = "Lambda"
|
||||
if(isfile(tfile))
|
||||
fname = "[tfile]"
|
||||
tfile = file2text(tfile)
|
||||
if(length(tfile) == 0)
|
||||
if(!length(tfile))
|
||||
throw EXCEPTION("Map path '[fname]' does not exist!")
|
||||
|
||||
if(!x_offset)
|
||||
@@ -57,7 +57,7 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
var/list/grid_models = list()
|
||||
var/key_len = 0
|
||||
|
||||
var/dmm_suite/loaded_map/LM = new
|
||||
var/datum/dmm_suite/loaded_map/LM = new
|
||||
// This try-catch is used as a budget "Finally" clause, as the dirt count
|
||||
// needs to be reset
|
||||
var/watch = start_watch()
|
||||
@@ -76,27 +76,27 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
if(!key_len)
|
||||
key_len = length(key)
|
||||
else
|
||||
throw EXCEPTION("Inconsistant key length in DMM")
|
||||
throw EXCEPTION("Inconsistent key length in DMM")
|
||||
if(!measureOnly)
|
||||
grid_models[key] = dmmRegex.group[2]
|
||||
|
||||
// (1,1,1) = {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}
|
||||
// (1, 1, 1) = {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}
|
||||
else if(dmmRegex.group[3]) // Coords
|
||||
if(!key_len)
|
||||
throw EXCEPTION("Coords before model definition in DMM")
|
||||
|
||||
var/xcrdStart = text2num(dmmRegex.group[3]) + x_offset - 1
|
||||
//position of the currently processed square
|
||||
// position of the currently processed square
|
||||
var/xcrd
|
||||
var/ycrd = text2num(dmmRegex.group[4]) + y_offset - 1
|
||||
var/zcrd = text2num(dmmRegex.group[5]) + z_offset - 1
|
||||
|
||||
if(!measureOnly)
|
||||
if(zcrd > world.maxz)
|
||||
if(cropMap)
|
||||
if(shouldCropMap)
|
||||
continue
|
||||
else
|
||||
GLOB.space_manager.increase_max_zlevel_to(zcrd) //create a new z_level if needed
|
||||
GLOB.space_manager.increase_max_zlevel_to(zcrd) // create a new z_level if needed
|
||||
|
||||
bounds[MAP_MINX] = min(bounds[MAP_MINX], xcrdStart)
|
||||
bounds[MAP_MINZ] = min(bounds[MAP_MINZ], zcrd)
|
||||
@@ -118,7 +118,7 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
bounds[MAP_MINY] = min(bounds[MAP_MINY], ycrd)
|
||||
ycrd += gridLines.len - 1 // Start at the top and work down
|
||||
|
||||
if(!cropMap && ycrd > world.maxy)
|
||||
if(!shouldCropMap && ycrd > world.maxy)
|
||||
if(!measureOnly)
|
||||
world.maxy = ycrd // Expand Y here. X is expanded in the loop below
|
||||
bounds[MAP_MAXY] = max(bounds[MAP_MAXY], ycrd)
|
||||
@@ -133,9 +133,9 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
for(var/line in gridLines)
|
||||
if(ycrd <= world.maxy && ycrd >= 1)
|
||||
xcrd = xcrdStart
|
||||
for(var/tpos = 1 to length(line) - key_len + 1 step key_len)
|
||||
for(var/tpos = 1 to (length(line) - key_len + 1) step key_len)
|
||||
if(xcrd > world.maxx)
|
||||
if(cropMap)
|
||||
if(shouldCropMap)
|
||||
break
|
||||
else
|
||||
world.maxx = xcrd
|
||||
@@ -152,7 +152,7 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
maxx = max(maxx, xcrd)
|
||||
++xcrd
|
||||
--ycrd
|
||||
bounds[MAP_MAXX] = max(bounds[MAP_MAXX], cropMap ? min(maxx, world.maxx) : maxx)
|
||||
bounds[MAP_MAXX] = max(bounds[MAP_MAXX], shouldCropMap ? min(maxx, world.maxx) : maxx)
|
||||
|
||||
CHECK_TICK
|
||||
catch(var/exception/e)
|
||||
@@ -175,8 +175,8 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
if(!measureOnly)
|
||||
for(var/t in block(locate(bounds[MAP_MINX], bounds[MAP_MINY], bounds[MAP_MINZ]), locate(bounds[MAP_MAXX], bounds[MAP_MAXY], bounds[MAP_MAXZ])))
|
||||
var/turf/T = t
|
||||
//we do this after we load everything in. if we don't; we'll have weird atmos bugs regarding atmos adjacent turfs
|
||||
T.AfterChange(1, keep_cabling = TRUE)
|
||||
// we do this after we load everything in. if we don't; we'll have weird atmos bugs regarding atmos adjacent turfs
|
||||
T.AfterChange(TRUE, keep_cabling = TRUE)
|
||||
return bounds
|
||||
|
||||
/**
|
||||
@@ -196,14 +196,14 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
* 4) Instanciates the atom with its variables
|
||||
*
|
||||
*/
|
||||
/dmm_suite/proc/parse_grid(model as text,xcrd as num,ycrd as num,zcrd as num, dmm_suite/loaded_map/LM)
|
||||
/datum/dmm_suite/proc/parse_grid(model = "", xcrd = 0, ycrd = 0, zcrd = 0, datum/dmm_suite/loaded_map/LM)
|
||||
/*Method parse_grid()
|
||||
- Accepts a text string containing a comma separated list of type paths of the
|
||||
same construction as those contained in a .dmm file, and instantiates them.
|
||||
*/
|
||||
|
||||
var/list/members //will contain all members (paths) in model (in our example : /turf/unsimulated/wall and /area/mine/dangerous/explored)
|
||||
var/list/members_attributes //will contain lists filled with corresponding variables, if any (in our example : list(icon_state = "rock") and list())
|
||||
var/list/members // will contain all members (paths) in model (in our example : /turf/unsimulated/wall and /area/mine/dangerous/explored)
|
||||
var/list/members_attributes // will contain lists filled with corresponding variables, if any (in our example : list(icon_state = "rock") and list())
|
||||
var/list/cached = modelCache[model]
|
||||
var/index
|
||||
|
||||
@@ -212,7 +212,7 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
members_attributes = cached[2]
|
||||
else
|
||||
/////////////////////////////////////////////////////////
|
||||
//Constructing members and corresponding variables lists
|
||||
// Constructing members and corresponding variables lists
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
members = list()
|
||||
@@ -223,13 +223,13 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
var/dpos
|
||||
|
||||
do
|
||||
//finding next member (e.g /turf/unsimulated/wall{icon_state = "rock"} or /area/mine/dangerous/explored)
|
||||
dpos = find_next_delimiter_position(model, old_position, ",", "{", "}") //find next delimiter (comma here) that's not within {...}
|
||||
// finding next member (e.g /turf/unsimulated/wall{icon_state = "rock"} or /area/mine/dangerous/explored)
|
||||
dpos = find_next_delimiter_position(model, old_position, ",", "{", "}") // find next delimiter (comma here) that's not within {...}
|
||||
|
||||
var/full_def = trim_text(copytext(model, old_position, dpos)) //full definition, e.g : /obj/foo/bar{variables=derp}
|
||||
var/full_def = trim_text(copytext(model, old_position, dpos)) // full definition, e.g : /obj/foo/bar{variables=derp}
|
||||
var/variables_start = findtext(full_def, "{")
|
||||
var/atom_text = trim_text(copytext(full_def, 1, variables_start))
|
||||
var/atom_def = text2path(atom_text) //path definition, e.g /obj/foo/bar
|
||||
var/atom_def = text2path(atom_text) // path definition, e.g /obj/foo/bar
|
||||
old_position = dpos + 1
|
||||
|
||||
if(!atom_def) // Skip the item if the path does not exist. Fix your crap, mappers!
|
||||
@@ -237,14 +237,14 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
continue
|
||||
members.Add(atom_def)
|
||||
|
||||
//transform the variables in text format into a list (e.g {var1="derp"; var2; var3=7} => list(var1="derp", var2, var3=7))
|
||||
// transform the variables in text format into a list (e.g {var1="derp"; var2; var3=7} => list(var1="derp", var2, var3=7))
|
||||
var/list/fields = list()
|
||||
|
||||
if(variables_start)//if there's any variable
|
||||
full_def = copytext(full_def,variables_start+1,length(full_def))//removing the last '}'
|
||||
if(variables_start) // if there's any variable
|
||||
full_def = copytext(full_def, variables_start + 1, length(full_def)) // removing the last '}'
|
||||
fields = readlist(full_def, ";")
|
||||
|
||||
//then fill the members_attributes list with the corresponding variables
|
||||
// then fill the members_attributes list with the corresponding variables
|
||||
members_attributes.len++
|
||||
members_attributes[index++] = fields
|
||||
|
||||
@@ -255,24 +255,23 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
|
||||
|
||||
////////////////
|
||||
//Instanciation
|
||||
// Instanciation
|
||||
////////////////
|
||||
|
||||
//The next part of the code assumes there's ALWAYS an /area AND a /turf on a given tile
|
||||
// The next part of the code assumes there's ALWAYS an /area AND a /turf on a given tile
|
||||
|
||||
//first instance the /area and remove it from the members list
|
||||
// first instance the /area and remove it from the members list
|
||||
index = members.len
|
||||
|
||||
var/turf/crds = locate(xcrd,ycrd,zcrd)
|
||||
var/turf/crds = locate(xcrd, ycrd, zcrd)
|
||||
if(members[index] != /area/template_noop)
|
||||
// We assume `members[index]` is an area path, as above, yes? I will operate
|
||||
// on that assumption.
|
||||
if(!ispath(members[index], /area))
|
||||
throw EXCEPTION("Oh no, I thought this was an area!")
|
||||
|
||||
var/atom/instance
|
||||
GLOB._preloader.setup(members_attributes[index])//preloader for assigning set variables on atom creation
|
||||
instance = LM.area_path_to_real_area(members[index])
|
||||
GLOB._preloader.setup(members_attributes[index]) // preloader for assigning set variables on atom creation
|
||||
var/atom/instance = LM.area_path_to_real_area(members[index])
|
||||
|
||||
if(crds)
|
||||
instance.contents.Add(crds)
|
||||
@@ -280,45 +279,45 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
if(GLOB.use_preloader && instance)
|
||||
GLOB._preloader.load(instance)
|
||||
|
||||
//then instance the /turf and, if multiple tiles are presents, simulates the DMM underlays piling effect
|
||||
// then instance the /turf and, if multiple tiles are presents, simulates the DMM underlays piling effect
|
||||
|
||||
var/first_turf_index = 1
|
||||
while(!ispath(members[first_turf_index],/turf)) //find first /turf object in members
|
||||
while(!ispath(members[first_turf_index], /turf)) // find first /turf object in members
|
||||
first_turf_index++
|
||||
|
||||
//instanciate the first /turf
|
||||
// instanciate the first /turf
|
||||
var/turf/T
|
||||
if(members[first_turf_index] != /turf/template_noop)
|
||||
T = instance_atom(members[first_turf_index],members_attributes[first_turf_index],xcrd,ycrd,zcrd)
|
||||
T = instance_atom(members[first_turf_index], members_attributes[first_turf_index], xcrd, ycrd, zcrd)
|
||||
|
||||
if(T)
|
||||
//if others /turf are presents, simulates the underlays piling effect
|
||||
// if others /turf are presents, simulates the underlays piling effect
|
||||
index = first_turf_index + 1
|
||||
while(index <= members.len - 1) // Last item is an /area
|
||||
var/underlay
|
||||
if(istype(T, /turf)) // I blame this on the stupid clown who coded the BYOND map editor
|
||||
underlay = T.appearance
|
||||
T = instance_atom(members[index],members_attributes[index],xcrd,ycrd,zcrd)//instance new turf
|
||||
if(ispath(members[index],/turf))
|
||||
T = instance_atom(members[index], members_attributes[index], xcrd, ycrd, zcrd) // instance new turf
|
||||
if(ispath(members[index], /turf))
|
||||
T.underlays += underlay
|
||||
|
||||
index++
|
||||
|
||||
//finally instance all remainings objects/mobs
|
||||
for(index in 1 to first_turf_index-1)
|
||||
instance_atom(members[index],members_attributes[index],xcrd,ycrd,zcrd)
|
||||
// finally instance all remainings objects/mobs
|
||||
for(index in 1 to first_turf_index - 1)
|
||||
instance_atom(members[index], members_attributes[index], xcrd, ycrd, zcrd)
|
||||
CHECK_TICK
|
||||
|
||||
////////////////
|
||||
//Helpers procs
|
||||
// Helpers procs
|
||||
////////////////
|
||||
|
||||
//Instance an atom at (x,y,z) and gives it the variables in attributes
|
||||
/dmm_suite/proc/instance_atom(path,list/attributes, x, y, z)
|
||||
// Instance an atom at (x, y, z) and gives it the variables in attributes
|
||||
/datum/dmm_suite/proc/instance_atom(path, list/attributes, x = 0, y = 0, z = 0)
|
||||
var/atom/instance
|
||||
GLOB._preloader.setup(attributes, path)
|
||||
|
||||
var/turf/T = locate(x,y,z)
|
||||
var/turf/T = locate(x, y, z)
|
||||
if(T)
|
||||
if(ispath(path, /turf))
|
||||
T.ChangeTurf(path, defer_change = TRUE, keep_icon = FALSE)
|
||||
@@ -326,115 +325,112 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
else if(ispath(path, /area))
|
||||
|
||||
else
|
||||
instance = new path (T)//first preloader pass
|
||||
instance = new path (T) // first preloader pass
|
||||
|
||||
if(GLOB.use_preloader && instance)//second preloader pass, for those atoms that don't ..() in New()
|
||||
if(GLOB.use_preloader && instance) // second preloader pass, for those atoms that don't ..() in New()
|
||||
GLOB._preloader.load(instance)
|
||||
|
||||
return instance
|
||||
|
||||
//text trimming (both directions) helper proc
|
||||
//optionally removes quotes before and after the text (for variable name)
|
||||
/dmm_suite/proc/trim_text(what as text,trim_quotes=0)
|
||||
// text trimming (both directions) helper proc
|
||||
// optionally removes quotes before and after the text (for variable name)
|
||||
/datum/dmm_suite/proc/trim_text(what = "", trim_quotes = FALSE)
|
||||
if(trim_quotes)
|
||||
return trimQuotesRegex.Replace(what, "")
|
||||
else
|
||||
return trimRegex.Replace(what, "")
|
||||
|
||||
|
||||
//find the position of the next delimiter,skipping whatever is comprised between opening_escape and closing_escape
|
||||
//returns 0 if reached the last delimiter
|
||||
/dmm_suite/proc/find_next_delimiter_position(text as text,initial_position as num, delimiter=",",opening_escape=quote,closing_escape=quote)
|
||||
// find the position of the next delimiter, skipping whatever is comprised between opening_escape and closing_escape
|
||||
// returns 0 if reached the last delimiter
|
||||
/datum/dmm_suite/proc/find_next_delimiter_position(text = "", initial_position = 0, delimiter = ",", opening_escape = quote, closing_escape = quote)
|
||||
var/position = initial_position
|
||||
var/next_delimiter = findtext(text,delimiter,position,0)
|
||||
var/next_opening = findtext(text,opening_escape,position,0)
|
||||
var/next_delimiter = findtext(text, delimiter, position, 0)
|
||||
var/next_opening = findtext(text, opening_escape, position, 0)
|
||||
|
||||
while((next_opening != 0) && (next_opening < next_delimiter))
|
||||
position = findtext(text,closing_escape,next_opening + 1,0)+1
|
||||
next_delimiter = findtext(text,delimiter,position,0)
|
||||
next_opening = findtext(text,opening_escape,position,0)
|
||||
position = findtext(text, closing_escape, next_opening + 1, 0) + 1
|
||||
next_delimiter = findtext(text, delimiter, position, 0)
|
||||
next_opening = findtext(text, opening_escape, position, 0)
|
||||
|
||||
return next_delimiter
|
||||
|
||||
|
||||
//build a list from variables in text form (e.g {var1="derp"; var2; var3=7} => list(var1="derp", var2, var3=7))
|
||||
//return the filled list
|
||||
/dmm_suite/proc/readlist(text as text, delimiter=",")
|
||||
|
||||
// build a list from variables in text form (e.g {var1="derp"; var2; var3=7} => list(var1="derp", var2, var3=7))
|
||||
// return the filled list
|
||||
/datum/dmm_suite/proc/readlist(text = "", delimiter = ",")
|
||||
var/list/to_return = list()
|
||||
|
||||
var/position
|
||||
var/old_position = 1
|
||||
|
||||
do
|
||||
//find next delimiter that is not within "..."
|
||||
position = find_next_delimiter_position(text,old_position,delimiter)
|
||||
// find next delimiter that is not within "..."
|
||||
position = find_next_delimiter_position(text, old_position, delimiter)
|
||||
|
||||
//check if this is a simple variable (as in list(var1, var2)) or an associative one (as in list(var1="foo",var2=7))
|
||||
var/equal_position = findtext(text,"=",old_position, position)
|
||||
// check if this is a simple variable (as in list(var1, var2)) or an associative one (as in list(var1="foo", var2=7))
|
||||
var/equal_position = findtext(text, "=", old_position, position)
|
||||
|
||||
var/trim_left = trim_text(copytext(text,old_position,(equal_position ? equal_position : position)),1)//the name of the variable, must trim quotes to build a BYOND compliant associatives list
|
||||
var/trim_left = trim_text(copytext(text, old_position, (equal_position ? equal_position : position)), 1) // the name of the variable, must trim quotes to build a BYOND compliant associatives list
|
||||
old_position = position + 1
|
||||
|
||||
if(equal_position)//associative var, so do the association
|
||||
var/trim_right = trim_text(copytext(text,equal_position+1,position))//the content of the variable
|
||||
if(equal_position) // associative var, so do the association
|
||||
var/trim_right = trim_text(copytext(text, equal_position + 1, position)) // the content of the variable
|
||||
|
||||
//Check for string
|
||||
// Check for string
|
||||
// Make it read to the next delimiter, instead of the quote
|
||||
if(findtext(trim_right,quote,1,2))
|
||||
var/endquote = findtext(trim_right,quote,-1)
|
||||
if(findtext(trim_right, quote, 1, 2))
|
||||
var/endquote = findtext(trim_right, quote, -1)
|
||||
if(!endquote)
|
||||
log_runtime(EXCEPTION("Terminating quote not found!"), src)
|
||||
// Our map writer escapes quotes and curly brackets to avoid
|
||||
// letting our simple parser choke on meanly-crafted names/etc
|
||||
// - so we decode it here so it's back to good ol' legibility
|
||||
trim_right = dmm_decode(copytext(trim_right,2,endquote))
|
||||
trim_right = dmm_decode(copytext(trim_right, 2, endquote))
|
||||
|
||||
//Check for number
|
||||
// Check for number
|
||||
else if(isnum(text2num(trim_right)))
|
||||
trim_right = text2num(trim_right)
|
||||
|
||||
//Check for null
|
||||
// Check for null
|
||||
else if(trim_right == "null")
|
||||
trim_right = null
|
||||
|
||||
//Check for list
|
||||
else if(copytext(trim_right,1,5) == "list")
|
||||
trim_right = readlist(copytext(trim_right,6,length(trim_right)))
|
||||
// Check for list
|
||||
else if(copytext(trim_right, 1, 5) == "list")
|
||||
trim_right = readlist(copytext(trim_right, 6, length(trim_right)))
|
||||
|
||||
//Check for file
|
||||
else if(copytext(trim_right,1,2) == "'")
|
||||
trim_right = file(copytext(trim_right,2,length(trim_right)))
|
||||
// Check for file
|
||||
else if(copytext(trim_right, 1, 2) == "'")
|
||||
trim_right = file(copytext(trim_right, 2, length(trim_right)))
|
||||
|
||||
//Check for path
|
||||
// Check for path
|
||||
else if(ispath(text2path(trim_right)))
|
||||
trim_right = text2path(trim_right)
|
||||
|
||||
to_return[trim_left] = trim_right
|
||||
|
||||
else//simple var
|
||||
else// simple var
|
||||
to_return[trim_left] = null
|
||||
|
||||
while(position != 0)
|
||||
|
||||
return to_return
|
||||
|
||||
/dmm_suite/Destroy()
|
||||
/datum/dmm_suite/Destroy()
|
||||
..()
|
||||
return QDEL_HINT_HARDDEL_NOW
|
||||
|
||||
//////////////////
|
||||
//Preloader datum
|
||||
// Preloader datum
|
||||
//////////////////
|
||||
|
||||
// This ain't re-entrant, but we had this before the maploader update
|
||||
/dmm_suite/preloader
|
||||
/datum/dmm_suite/preloader
|
||||
parent_type = /datum
|
||||
var/list/attributes
|
||||
var/target_path
|
||||
var/json_ready = 0
|
||||
|
||||
/dmm_suite/preloader/proc/setup(list/the_attributes, path)
|
||||
/datum/dmm_suite/preloader/proc/setup(list/the_attributes, path)
|
||||
if(the_attributes.len)
|
||||
json_ready = 0
|
||||
if("map_json_data" in the_attributes)
|
||||
@@ -443,25 +439,24 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
attributes = the_attributes
|
||||
target_path = path
|
||||
|
||||
/dmm_suite/preloader/proc/load(atom/what)
|
||||
/datum/dmm_suite/preloader/proc/load(atom/A)
|
||||
if(json_ready)
|
||||
var/json_data = attributes["map_json_data"]
|
||||
var/json_data = dmm_decode(attributes["map_json_data"])
|
||||
attributes -= "map_json_data"
|
||||
json_data = dmm_decode(json_data)
|
||||
try
|
||||
what.deserialize(json_decode(json_data))
|
||||
catch(var/exception/e)
|
||||
A.deserialize(json_decode(json_data))
|
||||
catch(var/exception/E)
|
||||
log_runtime(EXCEPTION("Bad json data: '[json_data]'"), src)
|
||||
throw e
|
||||
throw E
|
||||
for(var/attribute in attributes)
|
||||
var/value = attributes[attribute]
|
||||
if(islist(value))
|
||||
value = deepCopyList(value)
|
||||
what.vars[attribute] = value
|
||||
A.vars[attribute] = value
|
||||
GLOB.use_preloader = FALSE
|
||||
|
||||
// If the map loader fails, make this safe
|
||||
/dmm_suite/preloader/proc/reset()
|
||||
/datum/dmm_suite/preloader/proc/reset()
|
||||
GLOB.use_preloader = FALSE
|
||||
attributes = list()
|
||||
target_path = null
|
||||
@@ -470,12 +465,12 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
// so that one can have separate "unpowered" areas for ruins or whatever,
|
||||
// yet have a single area type for use of mapping, instead of creating
|
||||
// a new area type for each new ruin
|
||||
/dmm_suite/loaded_map
|
||||
/datum/dmm_suite/loaded_map
|
||||
parent_type = /datum
|
||||
var/list/area_list = list()
|
||||
var/index = 1 // To store the state of the regex
|
||||
|
||||
/dmm_suite/loaded_map/proc/area_path_to_real_area(area/A)
|
||||
/datum/dmm_suite/loaded_map/proc/area_path_to_real_area(area/A)
|
||||
if(!ispath(A, /area))
|
||||
throw EXCEPTION("Wrong argument to `area_path_to_real_area`")
|
||||
|
||||
|
||||
@@ -5,28 +5,27 @@
|
||||
#define DMM_IGNORE_PLAYERS 16
|
||||
#define DMM_IGNORE_MOBS 24
|
||||
#define DMM_USE_JSON 32
|
||||
/dmm_suite
|
||||
var/quote = "\""
|
||||
var/list/letter_digits = list(
|
||||
"a","b","c","d","e",
|
||||
"f","g","h","i","j",
|
||||
"k","l","m","n","o",
|
||||
"p","q","r","s","t",
|
||||
"u","v","w","x","y",
|
||||
/datum/dmm_suite
|
||||
var/static/list/letter_digits = list(
|
||||
"a", "b", "c", "d", "e",
|
||||
"f", "g", "h", "i", "j",
|
||||
"k", "l", "m", "n", "o",
|
||||
"p", "q", "r", "s", "t",
|
||||
"u", "v", "w", "x", "y",
|
||||
"z",
|
||||
"A","B","C","D","E",
|
||||
"F","G","H","I","J",
|
||||
"K","L","M","N","O",
|
||||
"P","Q","R","S","T",
|
||||
"U","V","W","X","Y",
|
||||
"A", "B", "C", "D", "E",
|
||||
"F", "G", "H", "I", "J",
|
||||
"K", "L", "M", "N", "O",
|
||||
"P", "Q", "R", "S", "T",
|
||||
"U", "V", "W", "X", "Y",
|
||||
"Z"
|
||||
)
|
||||
|
||||
/dmm_suite/save_map(var/turf/t1 as turf, var/turf/t2 as turf, var/map_name as text, var/flags as num)
|
||||
//Check for illegal characters in file name... in a cheap way.
|
||||
if(!((ckeyEx(map_name)==map_name) && ckeyEx(map_name)))
|
||||
/datum/dmm_suite/proc/save_map(turf/t1, turf/t2, map_name = "", flags = 0)
|
||||
// Check for illegal characters in file name... in a cheap way.
|
||||
if(!((ckeyEx(map_name) == map_name) && ckeyEx(map_name)))
|
||||
CRASH("Invalid text supplied to proc save_map, invalid characters or empty string.")
|
||||
//Check for valid turfs.
|
||||
// Check for valid turfs.
|
||||
if(!isturf(t1) || !isturf(t2))
|
||||
CRASH("Invalid arguments supplied to proc save_map, arguments were not turfs.")
|
||||
|
||||
@@ -35,17 +34,17 @@
|
||||
if(fexists(map_path))
|
||||
fdel(map_path)
|
||||
var/saved_map = file(map_path)
|
||||
var/map_text = write_map(t1,t2,flags,saved_map)
|
||||
var/map_text = write_map(t1, t2, flags, saved_map)
|
||||
saved_map << map_text
|
||||
return saved_map
|
||||
|
||||
/dmm_suite/write_map(var/turf/t1 as turf, var/turf/t2 as turf, var/flags as num)
|
||||
//Check for valid turfs.
|
||||
/datum/dmm_suite/proc/write_map(turf/t1, turf/t2, flags = 0)
|
||||
// Check for valid turfs.
|
||||
if(!isturf(t1) || !isturf(t2))
|
||||
CRASH("Invalid arguments supplied to proc write_map, arguments were not turfs.")
|
||||
|
||||
var/turf/ne = locate(max(t1.x,t2.x),max(t1.y,t2.y),max(t1.z,t2.z)) // Outer corner
|
||||
var/turf/sw = locate(min(t1.x,t2.x),min(t1.y,t2.y),min(t1.z,t2.z)) // Inner corner
|
||||
var/turf/ne = locate(max(t1.x, t2.x), max(t1.y, t2.y), max(t1.z, t2.z)) // Outer corner
|
||||
var/turf/sw = locate(min(t1.x, t2.x), min(t1.y, t2.y), min(t1.z, t2.z)) // Inner corner
|
||||
var/list/templates[0]
|
||||
var/list/template_buffer = list()
|
||||
var/template_buffer_text
|
||||
@@ -54,11 +53,12 @@
|
||||
var/total_timer = start_watch()
|
||||
var/timer = start_watch()
|
||||
log_debug("Reading turfs...")
|
||||
|
||||
// Read the contents of all the turfs we were given
|
||||
for(var/pos_z in sw.z to ne.z)
|
||||
for(var/pos_y in ne.y to sw.y step -1) // We're reversing this because the map format is silly
|
||||
for(var/pos_x in sw.x to ne.x)
|
||||
var/turf/test_turf = locate(pos_x,pos_y,pos_z)
|
||||
var/turf/test_turf = locate(pos_x, pos_y, pos_z)
|
||||
var/test_template = make_template(test_turf, flags)
|
||||
var/template_number = templates.Find(test_template)
|
||||
if(!template_number)
|
||||
@@ -66,25 +66,27 @@
|
||||
template_number = templates.len
|
||||
template_buffer += "[template_number],"
|
||||
CHECK_TICK
|
||||
|
||||
template_buffer += ";"
|
||||
|
||||
template_buffer += "."
|
||||
template_buffer_text = jointext(template_buffer,"")
|
||||
|
||||
template_buffer_text = jointext(template_buffer, "")
|
||||
log_debug("Reading turfs took [stop_watch(timer)]s.")
|
||||
|
||||
if(templates.len == 0)
|
||||
CRASH("No templates found!")
|
||||
var/key_length = round/*floor*/(log(letter_digits.len,templates.len-1)+1)
|
||||
|
||||
var/key_length = round/*floor*/(log(letter_digits.len, templates.len - 1) + 1)
|
||||
var/list/keys[templates.len]
|
||||
|
||||
// Write the list of key/model pairs to the file
|
||||
timer = start_watch()
|
||||
log_debug("Writing out key/model pairs to file header...")
|
||||
var/list/key_models = list()
|
||||
for(var/key_pos in 1 to templates.len)
|
||||
keys[key_pos] = get_model_key(key_pos,key_length)
|
||||
keys[key_pos] = get_model_key(key_pos, key_length)
|
||||
key_models += "\"[keys[key_pos]]\" = ([templates[key_pos]])\n"
|
||||
CHECK_TICK
|
||||
|
||||
dmm_text += jointext(key_models,"")
|
||||
log_debug("Writing key/model pairs complete, took [stop_watch(timer)]s.")
|
||||
|
||||
@@ -92,58 +94,69 @@
|
||||
// Loop over all z in our zone
|
||||
timer = start_watch()
|
||||
log_debug("Writing out key map...")
|
||||
|
||||
var/list/key_map = list()
|
||||
for(var/z_pos=1;TRUE;z_pos=findtext(template_buffer_text,".",z_pos)+1)
|
||||
if(z_pos>=length(template_buffer_text)) break
|
||||
if(z_level) key_map += "\n"
|
||||
key_map += "\n(1,1,[++z_level]) = {\"\n"
|
||||
var/z_block = copytext(template_buffer_text,z_pos,findtext(template_buffer_text,".",z_pos))
|
||||
for(var/y_pos=1;TRUE;y_pos=findtext(z_block,";",y_pos)+1)
|
||||
if(y_pos>=length(z_block)) break
|
||||
var/y_block = copytext(z_block,y_pos,findtext(z_block,";",y_pos))
|
||||
for(var/z_pos = 1; TRUE; z_pos = findtext(template_buffer_text, ".", z_pos) + 1)
|
||||
if(z_pos >= length(template_buffer_text))
|
||||
break
|
||||
|
||||
if(z_level)
|
||||
key_map += "\n"
|
||||
|
||||
key_map += "\n(1, 1,[++z_level]) = {\"\n"
|
||||
var/z_block = copytext(template_buffer_text, z_pos, findtext(template_buffer_text, ".", z_pos))
|
||||
for(var/y_pos = 1; TRUE; y_pos = findtext(z_block, ";", y_pos) + 1)
|
||||
if(y_pos >= length(z_block))
|
||||
break
|
||||
|
||||
var/y_block = copytext(z_block, y_pos, findtext(z_block, ";", y_pos))
|
||||
// A row of keys
|
||||
for(var/x_pos=1;TRUE;x_pos=findtext(y_block,",",x_pos)+1)
|
||||
if(x_pos>=length(y_block)) break
|
||||
var/x_block = copytext(y_block,x_pos,findtext(y_block,",",x_pos))
|
||||
for(var/x_pos = 1; TRUE; x_pos = findtext(y_block, ",", x_pos) + 1)
|
||||
if(x_pos >= length(y_block))
|
||||
break
|
||||
|
||||
var/x_block = copytext(y_block, x_pos, findtext(y_block, ",", x_pos))
|
||||
var/key_number = text2num(x_block)
|
||||
var/temp_key = keys[key_number]
|
||||
key_map += temp_key
|
||||
CHECK_TICK
|
||||
key_map += "\n"
|
||||
key_map += "\"}"
|
||||
dmm_text += jointext(key_map,"")
|
||||
|
||||
dmm_text += jointext(key_map, "")
|
||||
log_debug("Writing key map complete, took [stop_watch(timer)]s.")
|
||||
log_debug("TOTAL TIME: [stop_watch(total_timer)]s.")
|
||||
|
||||
return dmm_text
|
||||
|
||||
/dmm_suite/proc/make_template(var/turf/model as turf, var/flags as num)
|
||||
var/use_json = 0
|
||||
if(flags & DMM_USE_JSON)
|
||||
use_json = 1
|
||||
/datum/dmm_suite/proc/make_template(turf/model, flags = 0)
|
||||
var/use_json = flags & DMM_USE_JSON
|
||||
|
||||
var/template = ""
|
||||
var/turf_template = ""
|
||||
var/list/obj_template = list()
|
||||
var/list/mob_template = list()
|
||||
var/area_template = ""
|
||||
|
||||
|
||||
|
||||
// Turf
|
||||
if(!(flags & DMM_IGNORE_TURFS))
|
||||
turf_template = "[model.type][check_attributes(model,use_json=use_json)],"
|
||||
else turf_template = "[world.turf],"
|
||||
else
|
||||
turf_template = "[world.turf],"
|
||||
|
||||
// Objects loop
|
||||
if(!(flags & DMM_IGNORE_OBJS))
|
||||
for(var/obj/O in model.contents)
|
||||
if(O.dont_save || QDELETED(O))
|
||||
continue
|
||||
|
||||
obj_template += "[O.type][check_attributes(O,use_json=use_json)],"
|
||||
|
||||
// Mobs Loop
|
||||
for(var/mob/M in model.contents)
|
||||
if(M.dont_save || QDELETED(M))
|
||||
continue
|
||||
|
||||
if(M.client)
|
||||
if(!(flags & DMM_IGNORE_PLAYERS))
|
||||
mob_template += "[M.type][check_attributes(M,use_json=use_json)],"
|
||||
@@ -155,65 +168,68 @@
|
||||
if(!(flags & DMM_IGNORE_AREAS))
|
||||
var/area/m_area = model.loc
|
||||
area_template = "[m_area.type][check_attributes(m_area,use_json=use_json)]"
|
||||
else area_template = "[world.area]"
|
||||
else
|
||||
area_template = "[world.area]"
|
||||
|
||||
template = "[jointext(obj_template,"")][jointext(mob_template,"")][turf_template][area_template]"
|
||||
return template
|
||||
|
||||
/dmm_suite/proc/check_attributes(var/atom/A,use_json=0)
|
||||
/datum/dmm_suite/proc/check_attributes(atom/A, use_json = FALSE)
|
||||
var/attributes_text = "{"
|
||||
var/list/attributes = list()
|
||||
if(!use_json)
|
||||
for(var/V in A.vars)
|
||||
CHECK_TICK
|
||||
if((!issaved(A.vars[V])) || (A.vars[V]==initial(A.vars[V]))) continue
|
||||
if((!issaved(A.vars[V])) || (A.vars[V] == initial(A.vars[V])))
|
||||
continue
|
||||
|
||||
attributes += var_to_dmm(A.vars[V], V)
|
||||
else
|
||||
var/list/yeah = A.serialize()
|
||||
var/list/to_encode = A.serialize()
|
||||
// We'll want to write out vars that are important to the editor
|
||||
// So that the map is legible as before
|
||||
for(var/thing in A.map_important_vars())
|
||||
for(var/T in A.map_important_vars())
|
||||
// Save vars that are important for the map editor, so that
|
||||
// json-encoded maps are legible for standard editors
|
||||
if(A.vars[thing] != initial(A.vars[thing]))
|
||||
yeah -= thing
|
||||
attributes += var_to_dmm(A.vars[thing],thing)
|
||||
if(A.vars[T] != initial(A.vars[T]))
|
||||
to_encode -= T
|
||||
attributes += var_to_dmm(A.vars[T], T)
|
||||
|
||||
// Remove useless info
|
||||
yeah -= "type"
|
||||
if(yeah.len)
|
||||
var/json_stuff = json_encode(yeah)
|
||||
to_encode -= "type"
|
||||
if(to_encode.len)
|
||||
var/json_stuff = json_encode(to_encode)
|
||||
attributes += var_to_dmm(json_stuff, "map_json_data")
|
||||
|
||||
if(attributes.len == 0)
|
||||
return
|
||||
|
||||
// Trim a trailing semicolon - `var_to_dmm` always appends a semicolon,
|
||||
// so the last one will be trailing.
|
||||
if(copytext(attributes_text, length(attributes_text)-1, 0) == "; ")
|
||||
attributes_text = copytext(attributes_text, 1, length(attributes_text)-1)
|
||||
if(copytext(attributes_text, length(attributes_text) - 1, 0) == "; ")
|
||||
attributes_text = copytext(attributes_text, 1, length(attributes_text) - 1)
|
||||
|
||||
attributes_text = "{[jointext(attributes,"; ")]}"
|
||||
return attributes_text
|
||||
|
||||
|
||||
/dmm_suite/proc/get_model_key(var/which as num, var/key_length as num)
|
||||
/datum/dmm_suite/proc/get_model_key(which = 0, key_length = 0)
|
||||
var/list/key = list()
|
||||
var/working_digit = which-1
|
||||
var/working_digit = which - 1
|
||||
for(var/digit_pos in key_length to 1 step -1)
|
||||
var/place_value = round/*floor*/(working_digit/(letter_digits.len**(digit_pos-1)))
|
||||
working_digit-=place_value*(letter_digits.len**(digit_pos-1))
|
||||
key += letter_digits[place_value+1]
|
||||
var/place_value = round/*floor*/(working_digit / (letter_digits.len ** (digit_pos - 1)))
|
||||
working_digit -= place_value * (letter_digits.len ** (digit_pos - 1))
|
||||
key += letter_digits[place_value + 1]
|
||||
|
||||
return jointext(key,"")
|
||||
|
||||
|
||||
/dmm_suite/proc/var_to_dmm(attr, name)
|
||||
/datum/dmm_suite/proc/var_to_dmm(attr, name)
|
||||
if(istext(attr))
|
||||
// dmm_encode will strip out characters that would be capable of disrupting
|
||||
// parsing - namely, quotes and curly braces
|
||||
return "[name] = \"[dmm_encode(attr)]\""
|
||||
else if(isnum(attr)||ispath(attr))
|
||||
else if(isnum(attr) || ispath(attr))
|
||||
return "[name] = [attr]"
|
||||
else if(isicon(attr)||isfile(attr))
|
||||
else if(isicon(attr) || isfile(attr))
|
||||
if(length("[attr]") == 0)
|
||||
// The DM map reader is unable to read files that have a '' file/icon entry
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user