mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 18:22:39 +00:00
Rewrote maploader to act faster and better handle set variables.
Most notably : * better loading times, less processing loops * lists variables are now taken into account (simples and associatives) * every character can now be used inside a string without fear of breaking the loading process
This commit is contained in:
@@ -1,325 +1,322 @@
|
||||
dmm_suite
|
||||
///////////////////////////////////////////////////////////////
|
||||
//SS13 Optimized Map loader
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
var/debug_file = file("maploader_debug.txt")
|
||||
|
||||
load_map(var/dmm_file as file, var/z_offset as num, var/y_offset as num, var/x_offset as num, var/load_speed = 0 as num)
|
||||
if(!z_offset)
|
||||
z_offset = world.maxz + 1
|
||||
/**
|
||||
* Construct the model map and control the loading process
|
||||
*
|
||||
* WORKING :
|
||||
*
|
||||
* 1) Makes an associative mapping of model_keys with model
|
||||
* e.g aa = /turf/unsimulated/wall{icon_state = "rock"}
|
||||
* 2) Read the map line by line, parsing the result (using parse_grid)
|
||||
*
|
||||
*/
|
||||
/dmm_suite/load_map(var/dmm_file as file, var/z_offset as num)
|
||||
if(!z_offset)//what z_level we are creating the map on
|
||||
z_offset = world.maxz+1
|
||||
|
||||
//Ensure values are sane.
|
||||
else if(z_offset < 0)
|
||||
z_offset = abs(z_offset)
|
||||
else if(!isnum(z_offset))
|
||||
z_offset = 0
|
||||
var/quote = ascii2text(34)
|
||||
var/tfile = file2text(dmm_file)//the map file we're creating
|
||||
var/tfile_len = length(tfile)
|
||||
var/lpos = 1 // the models definition index
|
||||
|
||||
if(x_offset < 0)
|
||||
x_offset = abs(x_offset)
|
||||
else if(!isnum(x_offset))
|
||||
x_offset = 0
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//first let's map model keys (e.g "aa") to their contents (e.g /turf/space{variables})
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
var/list/grid_models = list()
|
||||
var/key_len = length(copytext(tfile,2,findtext(tfile,quote,2,0)))//the length of the model key (e.g "aa" or "aba")
|
||||
|
||||
if(y_offset < 0)
|
||||
y_offset = abs(y_offset)
|
||||
else if(!isnum(y_offset))
|
||||
y_offset = 0
|
||||
//proceed line by line
|
||||
for(lpos=1; lpos<tfile_len; lpos=findtext(tfile,"\n",lpos,0)+1)
|
||||
var/tline = copytext(tfile,lpos,findtext(tfile,"\n",lpos,0))
|
||||
if(copytext(tline,1,2) != quote)//we reached the map "layout"
|
||||
break
|
||||
var/model_key = copytext(tline,2,2+key_len)
|
||||
var/model_contents = copytext(tline,findtext(tfile,"=")+3,length(tline))
|
||||
grid_models[model_key] = model_contents
|
||||
sleep(-1)
|
||||
|
||||
debug_file << "Starting Map Load @ ([x_offset], [y_offset], [z_offset]), [load_speed] tiles per second."
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//now let's fill the map with turf and objects using the constructed model map
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//Handle slowed loading.
|
||||
var/delay_chance = 0
|
||||
if(load_speed > 0)
|
||||
//Chance out of 100 every tenth of a second.
|
||||
delay_chance = 1000 / load_speed
|
||||
//position of the currently processed square
|
||||
var/zcrd=-1
|
||||
var/ycrd=0
|
||||
var/xcrd=0
|
||||
|
||||
//String holding a quotation mark.
|
||||
var/quote = ascii2text(34)
|
||||
for(var/zpos=findtext(tfile,"\n(1,1,",lpos,0);zpos!=0;zpos=findtext(tfile,"\n(1,1,",zpos+1,0)) //in case there's several maps to load
|
||||
|
||||
var/input_file = file2text(dmm_file)
|
||||
var/input_file_len = length(input_file)
|
||||
zcrd++
|
||||
world.maxz = max(world.maxz, zcrd+z_offset)//create a new z_level if needed
|
||||
|
||||
//Stores the contents of each tile model in the map
|
||||
var/list/grid_models = list()
|
||||
//Length of the tile model code. e.g. "aaa" is 3 long.
|
||||
var/key_len = length(copytext(input_file, 2 ,findtext(input_file, quote, 2)))
|
||||
//The key of the default tile model. (In SS13 this is: "/turf/space,/area")
|
||||
var/default_key
|
||||
var/zgrid = copytext(tfile,findtext(tfile,quote+"\n",zpos,0)+2,findtext(tfile,"\n"+quote,zpos,0)+1) //copy the whole map grid
|
||||
var/z_depth = length(zgrid)
|
||||
|
||||
debug_file << " Building turf array."
|
||||
//if exceeding the world max x or y, increase it
|
||||
var/x_depth = length(copytext(zgrid,1,findtext(zgrid,"\n",2,0)))
|
||||
if(world.maxx<x_depth)
|
||||
world.maxx=x_depth
|
||||
|
||||
//Iterates through the mapfile to build the model tiles for the map.
|
||||
for(var/line_position = 1; line_position < input_file_len; line_position = findtext(input_file,"\n", line_position) + 1)
|
||||
var/next_line = copytext(input_file, line_position, findtext(input_file,"\n", line_position) - 1)
|
||||
var/y_depth = z_depth / (x_depth+1)//x_depth + 1 because we're counting the '\n' characters in z_depth
|
||||
if(world.maxy<y_depth)
|
||||
world.maxy=y_depth
|
||||
|
||||
//If the first character in the line is not a quote, the model tiles are all defined.
|
||||
if(copytext(next_line, 1, 2) != quote)
|
||||
//then proceed it line by line, starting from top
|
||||
ycrd = y_depth
|
||||
|
||||
for(var/gpos=1;gpos!=0;gpos=findtext(zgrid,"\n",gpos,0)+1)
|
||||
var/grid_line = copytext(zgrid,gpos,findtext(zgrid,"\n",gpos,0))
|
||||
|
||||
//fill the current square using the model map
|
||||
xcrd=0
|
||||
for(var/mpos=1;mpos<=x_depth;mpos+=key_len)
|
||||
xcrd++
|
||||
var/model_key = copytext(grid_line,mpos,mpos+key_len)
|
||||
parse_grid(grid_models[model_key],xcrd,ycrd,zcrd+z_offset)
|
||||
|
||||
//reached end of current map
|
||||
if(gpos+x_depth+1>z_depth)
|
||||
break
|
||||
|
||||
//Copy contents of the model into the grid_models list.
|
||||
var/model_key = copytext(next_line, 2, findtext(input_file, quote, 2))
|
||||
var/model_contents = copytext(next_line, findtext(next_line, "=" ) + 3)
|
||||
if(!default_key && model_contents == "[world.turf],[world.area]")
|
||||
default_key = model_key
|
||||
grid_models[model_key] = model_contents
|
||||
if(prob(delay_chance))
|
||||
sleep(1)
|
||||
|
||||
//Co-ordinates of the tile being loaded.
|
||||
var/z_coordinate = -1
|
||||
var/y_coordinate = 0
|
||||
var/x_coordinate = 0
|
||||
|
||||
//Store the
|
||||
var/y_depth = 0
|
||||
|
||||
//Iterate through all z-levels to load the tiles.
|
||||
for(var/z_position = findtext(input_file, "\n(1,1,"); TRUE; z_position = findtext(input_file, "\n(1,1,", z_position + 1))
|
||||
//break when there are no more z-levels.
|
||||
if(z_position == 0)
|
||||
break
|
||||
|
||||
//Increment the z_coordinate and update the world's borders
|
||||
z_coordinate++
|
||||
world.maxz = max(world.maxz, z_coordinate + z_offset)
|
||||
|
||||
//Here we go!
|
||||
y_coordinate = 0
|
||||
y_depth = 0
|
||||
var/z_level = copytext(input_file, \
|
||||
findtext(input_file, quote + "\n", z_position) + 2,\
|
||||
findtext(input_file, "\n" + quote, z_position) + 1)
|
||||
|
||||
//Iterate through each line, increasing the y_coordinate.
|
||||
for(var/grid_position = 1; grid_position != 0; grid_position = findtext(z_level, "\n", grid_position) + 1)
|
||||
//Grab this line of data.
|
||||
var/grid_line = copytext(z_level, grid_position, findtext(z_level, "\n", grid_position))
|
||||
|
||||
//Compute the size of the z-levels y axis.
|
||||
if(!y_depth)
|
||||
y_depth = length(z_level) / (length(grid_line) + 1)
|
||||
y_depth += y_offset
|
||||
if(y_depth != round(y_depth, 1))
|
||||
debug_file << " Warning: y_depth is not a round number"
|
||||
|
||||
//And update the worlds variables.
|
||||
if(world.maxy < y_depth)
|
||||
world.maxy = y_depth
|
||||
//The top of the map is the highest "y" co-ordinate, so we start there and iterate downwards
|
||||
if(!y_coordinate)
|
||||
y_coordinate = y_depth + 1
|
||||
|
||||
//Decrement and load this line of the map.
|
||||
y_coordinate--
|
||||
x_coordinate = x_offset
|
||||
|
||||
//Iterate through the line loading the model tile data.
|
||||
for(var/model_position = 1; model_position <= length(grid_line); model_position += key_len)
|
||||
x_coordinate++
|
||||
|
||||
//Find the model key and load that model.
|
||||
var/model_key = copytext(grid_line, model_position, model_position + key_len)
|
||||
//If the key is the default one, skip it and save the computation time.
|
||||
if(model_key == default_key)
|
||||
continue
|
||||
|
||||
if(world.maxx < x_coordinate)
|
||||
world.maxx = x_coordinate
|
||||
parse_grid(grid_models[model_key], x_coordinate, y_coordinate, z_coordinate + z_offset)
|
||||
|
||||
if(prob(delay_chance))
|
||||
sleep(1)
|
||||
|
||||
//If we hit the last tile in this z-level, we should break out of the loop.
|
||||
if(grid_position + length(grid_line) + 1 > length(z_level))
|
||||
break
|
||||
|
||||
//Break out of the loop when we hit the end of the file.
|
||||
if(findtext(input_file, quote + "}", z_position) + 2 >= input_file_len)
|
||||
break
|
||||
|
||||
|
||||
proc/parse_grid(var/model as text, var/x_coordinate as num, var/y_coordinate as num, var/z_coordinate as num)
|
||||
//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/text_strings = list()
|
||||
for(var/index = 1; findtext(model, quote); index++)
|
||||
/*Loop: Stores quoted portions of text in text_strings, and replaces them with an
|
||||
index to that list.
|
||||
- Each iteration represents one quoted section of text.
|
||||
*/
|
||||
//Add the next section of quoted text to the list
|
||||
var/first_quote = findtext(model, quote)
|
||||
var/second_quote = findtext(model, quote, first_quote + 1)
|
||||
var/quoted_chunk = copytext(model, first_quote + 1, second_quote)
|
||||
text_strings += quoted_chunk
|
||||
//Then remove the quoted section.
|
||||
model = copytext(model, 1, first_quote) + "~[index]" + copytext(model, second_quote + 1)
|
||||
|
||||
var/debug_output = 0
|
||||
//if(x_coordinate == 86 && y_coordinate == 88 && z_coordinate == 7)
|
||||
// debug_output = 1
|
||||
|
||||
if(debug_output)
|
||||
debug_file << " Now debugging turf: [model] ([x_coordinate], [y_coordinate], [z_coordinate])"
|
||||
|
||||
var/next_position = 1
|
||||
for(var/data_position = 1, next_position || data_position != 1, data_position = next_position + 1)
|
||||
next_position = findtext(model, ",/", data_position)
|
||||
|
||||
var/full_def = copytext(model, data_position, next_position)
|
||||
|
||||
if(debug_output)
|
||||
debug_file << " Current Line: [full_def] -- ([data_position] - [next_position])"
|
||||
|
||||
/*Loop: Identifies each object's data, instantiates it, and reconstitues it's fields.
|
||||
- Each iteration represents one object's data, including type path and field values.
|
||||
*/
|
||||
|
||||
//Load the attribute data.
|
||||
var/attribute_position = findtext(full_def,"{")
|
||||
var/atom_def = text2path(copytext(full_def, 1, attribute_position))
|
||||
|
||||
var/list/attributes = list()
|
||||
if(attribute_position)
|
||||
full_def = copytext(full_def, attribute_position + 1)
|
||||
if(debug_output)
|
||||
debug_file << " Atom Def: [atom_def]"
|
||||
debug_file << " Parameters: [full_def]"
|
||||
|
||||
var/next_attribute = 1
|
||||
for(attribute_position = 1, next_attribute || attribute_position != 1, attribute_position = next_attribute + 1)
|
||||
next_attribute = findtext(full_def, ";", attribute_position)
|
||||
|
||||
//Loop: Identifies each attribute/value pair, and stores it in attributes[].
|
||||
attributes += copytext(full_def, attribute_position, next_attribute)
|
||||
|
||||
//Construct attributes associative list
|
||||
var/list/fields = list()
|
||||
for(var/attribute in attributes)
|
||||
var/trim_left = trim_text(copytext(attribute, 1, findtext(attribute, "=")))
|
||||
var/trim_right = trim_text(copytext(attribute, findtext(attribute, "=") + 1))
|
||||
|
||||
if(findtext(trim_right, "list("))
|
||||
trim_right = get_list(trim_right, text_strings)
|
||||
|
||||
else if(findtext(trim_right, "~"))//Check for strings
|
||||
while(findtext(trim_right,"~"))
|
||||
var/reference_index = copytext(trim_right, findtext(trim_right, "~") + 1)
|
||||
trim_right = text_strings[text2num(reference_index)]
|
||||
|
||||
//Check for numbers
|
||||
else if(isnum(text2num(trim_right)))
|
||||
trim_right = text2num(trim_right)
|
||||
|
||||
//Check for file
|
||||
else if(copytext(trim_right,1,2) == "'")
|
||||
trim_right = file(copytext(trim_right, 2, length(trim_right)))
|
||||
|
||||
fields[trim_left] = trim_right
|
||||
sleep(-1)
|
||||
|
||||
|
||||
if(debug_output)
|
||||
var/return_data = " Debug Fields:"
|
||||
for(var/item in fields)
|
||||
return_data += " [item] = [fields[item]];"
|
||||
debug_file << return_data
|
||||
|
||||
//Begin Instanciation
|
||||
var/atom/instance
|
||||
|
||||
if(ispath(atom_def,/area))
|
||||
instance = locate(atom_def)
|
||||
if(!istype(instance, atom_def))
|
||||
instance = new atom_def
|
||||
instance.contents.Add(locate(x_coordinate,y_coordinate,z_coordinate))
|
||||
|
||||
else
|
||||
instance = new atom_def(locate(x_coordinate,y_coordinate,z_coordinate))
|
||||
if(instance)
|
||||
for(var/item in fields)
|
||||
instance.vars[item] = fields[item]
|
||||
else if(!(atom_def in borked_paths))
|
||||
borked_paths += atom_def
|
||||
var/return_data = " Failure [atom_def] @ ([x_coordinate], [y_coordinate], [z_coordinate]) fields:"
|
||||
for(var/item in fields)
|
||||
return_data += " [item] = [fields[item]];"
|
||||
debug_file << return_data
|
||||
ycrd--
|
||||
|
||||
sleep(-1)
|
||||
return 1
|
||||
|
||||
var/list/borked_paths = list()
|
||||
//reached End Of File
|
||||
if(findtext(tfile,quote+"}",zpos,0)+2==tfile_len)
|
||||
break
|
||||
sleep(-1)
|
||||
|
||||
proc/trim_text(var/what as text)
|
||||
while(length(what) && findtext(what, " ", 1, 2))
|
||||
what = copytext(what, 2)
|
||||
/**
|
||||
* Fill a given tile with its area/turf/objects/mobs
|
||||
* Variable model is one full map line (e.g /turf/unsimulated/wall{icon_state = "rock"},/area/mine/explored)
|
||||
*
|
||||
* WORKING :
|
||||
*
|
||||
* 1) Read the model string, member by member (delimiter is ',')
|
||||
*
|
||||
* 2) Get the path of the atom and store it into a list
|
||||
*
|
||||
* 3) a) Check if the member has variables (text within '{' and '}')
|
||||
*
|
||||
* 3) b) Construct an associative list with found variables, if any (the atom index in members is the same as its variables in members_attributes)
|
||||
*
|
||||
* 4) Instanciates the atom with its variables
|
||||
*
|
||||
*/
|
||||
/dmm_suite/proc/parse_grid(var/model as text,var/xcrd as num,var/ycrd as num,var/zcrd as num)
|
||||
/*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.
|
||||
*/
|
||||
|
||||
while(length(what) && findtext(what, " ", length(what)))
|
||||
what = copytext(what, 1, length(what))
|
||||
var/list/members = list()//will contain all members (paths) in model (in our example : /turf/unsimulated/wall and /area/mine/explored)
|
||||
var/list/members_attributes = list()//will contain lists filled with corresponding variables, if any (in our example : list(icon_state = "rock") and list())
|
||||
|
||||
return what
|
||||
|
||||
proc/get_list(var/text, var/list/text_strings)
|
||||
//First, trim the data to just the list contents
|
||||
var/list_start = findtext(text, "(") + 1
|
||||
var/list_end = findtext(text, ")", list_start)
|
||||
var/list_contents = copytext(text, list_start, list_end)
|
||||
/////////////////////////////////////////////////////////
|
||||
//Constructing members and corresponding variables lists
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
//Then, we seperate it into the individual entries
|
||||
var/index=1
|
||||
var/old_position = 1
|
||||
var/dpos
|
||||
|
||||
var/list/entries = list()
|
||||
var/entry_end = 1
|
||||
do
|
||||
//finding next member (e.g /turf/unsimulated/wall{icon_state = "rock"} or /area/mine/explored)
|
||||
dpos= find_next_delimiter_position(model,old_position,",","{","}")//find next delimiter (comma here) that's not within {...}
|
||||
|
||||
for(var/entry_start = 1, entry_end || entry_start != 1, entry_start = entry_end + 1)
|
||||
entry_end = findtext(list_contents, ",", entry_start)
|
||||
entries += copytext(list_contents, entry_start, entry_end)
|
||||
var/full_def = copytext(model,old_position,dpos)//full definition, e.g : /obj/foo/bar{variables=derp}
|
||||
var/atom_def = text2path(copytext(full_def,1,findtext(full_def,"{")))//path definition, e.g /obj/foo/bar
|
||||
members.Add(atom_def)
|
||||
old_position = dpos + 1
|
||||
|
||||
//Finally, we assemble the completed list.
|
||||
var/list/final_list = list()
|
||||
for(var/entry in entries)
|
||||
var/equals_position = findtext(entry, "=")
|
||||
//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(equals_position)
|
||||
var/trim_left = trim_text(copytext(entry, 1, equals_position))
|
||||
var/trim_right = trim_text(copytext(entry, equals_position + 1))
|
||||
var/variables_start = findtext(full_def,"{")
|
||||
if(variables_start)//if there's any variable
|
||||
full_def = copytext(full_def,variables_start+1,length(full_def))//removing the last '}'
|
||||
fields = text2list(full_def,";")
|
||||
|
||||
if(findtext(trim_right, "list("))
|
||||
trim_right = get_list(trim_right, text_strings)
|
||||
//then fill the members_attributes list with the corresponding variables
|
||||
members_attributes.len++
|
||||
members_attributes[index++] = fields
|
||||
|
||||
else if(findtext(trim_right, "~"))//Check for strings
|
||||
while(findtext(trim_right,"~"))
|
||||
var/reference_index = copytext(trim_right, findtext(trim_right, "~") + 1)
|
||||
trim_right = text_strings[text2num(reference_index)]
|
||||
sleep(-1)
|
||||
while(dpos != 0)
|
||||
|
||||
//Check for numbers
|
||||
else if(isnum(text2num(trim_right)))
|
||||
trim_right = text2num(trim_right)
|
||||
|
||||
//Check for file
|
||||
else if(copytext(trim_right,1,2) == "'")
|
||||
trim_right = file(copytext(trim_right, 2, length(trim_right)))
|
||||
////////////////
|
||||
//Instanciation
|
||||
////////////////
|
||||
|
||||
if(findtext(trim_left, "~"))//Check for strings
|
||||
while(findtext(trim_left,"~"))
|
||||
var/reference_index = copytext(trim_left, findtext(trim_left, "~") + 1)
|
||||
trim_left = text_strings[text2num(reference_index)]
|
||||
//The next part of the code assumes there's ALWAYS an /area AND a /turf on a given tile
|
||||
|
||||
final_list[trim_left] = trim_right
|
||||
//first instance the /area and remove it from the members list
|
||||
var/length = members.len
|
||||
var/atom/instance
|
||||
var/dmm_suite/preloader/_preloader = new(members_attributes[length])//preloader for assigning set variables on atom creation
|
||||
|
||||
else
|
||||
if(findtext(entry, "~"))//Check for strings
|
||||
while(findtext(entry, "~"))
|
||||
var/reference_index = copytext(entry, findtext(entry, "~") + 1)
|
||||
entry = text_strings[text2num(reference_index)]
|
||||
instance = locate(members[length])
|
||||
instance.contents.Add(locate(xcrd,ycrd,zcrd))
|
||||
|
||||
//Check for numbers
|
||||
else if(isnum(text2num(entry)))
|
||||
entry = text2num(entry)
|
||||
if(_preloader && instance)
|
||||
_preloader.load(instance)
|
||||
|
||||
//Check for file
|
||||
else if(copytext(entry, 1, 2) == "'")
|
||||
entry = file(copytext(entry, 2, length(entry)))
|
||||
members.Remove(members[length])
|
||||
|
||||
final_list += entry
|
||||
//then instance the /turf and remove it from the members list
|
||||
length = members.len
|
||||
|
||||
return final_list
|
||||
instance_atom(members[length],members_attributes[length],xcrd,ycrd,zcrd)
|
||||
members.Remove(members[length])
|
||||
|
||||
//Replace the previous part of the code with this if it's unsafe to assume tiles have ALWAYS an /area AND a /turf
|
||||
/*while(members.len > 0)
|
||||
var/length = members.len
|
||||
var/member = members[length]
|
||||
|
||||
if(ispath(member,/area))
|
||||
var/atom/instance
|
||||
var/dmm_suite/preloader/_preloader = new(members_attributes[length])
|
||||
|
||||
instance = locate(member)
|
||||
instance.contents.Add(locate(xcrd,ycrd,zcrd))
|
||||
|
||||
if(_preloader && instance)
|
||||
_preloader.load(instance)
|
||||
|
||||
members.Remove(member)
|
||||
continue
|
||||
|
||||
else if(ispath(member,/turf))
|
||||
instance_atom(member,members_attributes[length],xcrd,ycrd,zcrd)
|
||||
members.Remove(member)
|
||||
continue
|
||||
|
||||
else
|
||||
break
|
||||
*/
|
||||
|
||||
//finally instance all remainings objects/mobs
|
||||
for(var/k=1,k<=members.len,k++)
|
||||
instance_atom(members[k],members_attributes[k],xcrd,ycrd,zcrd)
|
||||
|
||||
////////////////
|
||||
//Helpers procs
|
||||
////////////////
|
||||
|
||||
//Instance an atom at (x,y,z) and gives it the variables in attributes
|
||||
/dmm_suite/proc/instance_atom(var/path,var/list/attributes, var/x, var/y, var/z)
|
||||
var/atom/instance
|
||||
var/dmm_suite/preloader/_preloader = new(attributes)
|
||||
|
||||
instance = new path (locate(x,y,z), _preloader)//first preloader pass
|
||||
|
||||
if(_preloader && instance)//second preloader pass, as some variables may have been reset/changed by New()
|
||||
_preloader.load(instance)
|
||||
|
||||
//text trimming (both directions) helper proc
|
||||
//optionally removes quotes before and after the text (for variable name)
|
||||
/dmm_suite/proc/trim_text(var/what as text,var/trim_quotes=0)
|
||||
while(length(what) && (findtext(what," ",1,2)))// || findtext(what,quote,1,2)))
|
||||
what=copytext(what,2,0)
|
||||
while(length(what) && (findtext(what," ",length(what),0)))// || findtext(what,quote,length(what),0)))
|
||||
what=copytext(what,1,length(what))
|
||||
if(trim_quotes)
|
||||
while(length(what) && (findtext(what,quote,1,2)))
|
||||
what=copytext(what,2,0)
|
||||
while(length(what) && (findtext(what,quote,length(what),0)))
|
||||
what=copytext(what,1,length(what))
|
||||
return 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(var/text as text,var/initial_position as num, var/delimiter=",",var/opening_escape=quote,var/closing_escape=quote)
|
||||
var/position = initial_position
|
||||
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)
|
||||
|
||||
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/text2list(var/text as text,var/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)
|
||||
|
||||
//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
|
||||
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
|
||||
|
||||
//Check for string
|
||||
if(findtext(trim_right,quote,1,2))
|
||||
trim_right = copytext(trim_right,2,findtext(trim_right,quote,3,0))
|
||||
|
||||
//Check for number
|
||||
else if(isnum(text2num(trim_right)))
|
||||
trim_right = text2num(trim_right)
|
||||
|
||||
//Check for file
|
||||
else if(copytext(trim_right,1,2) == "'")
|
||||
trim_right = file(copytext(trim_right,2,length(trim_right)))
|
||||
|
||||
//Check for list
|
||||
else if(copytext(trim_right,1,5) == "list")
|
||||
trim_right = text2list(copytext(trim_right,6,length(trim_right)))
|
||||
|
||||
to_return[trim_left] = trim_right
|
||||
|
||||
else//simple var
|
||||
to_return[trim_left] = null
|
||||
|
||||
while(position != 0)
|
||||
|
||||
return to_return
|
||||
|
||||
//atom creation method that preloads variables before creation
|
||||
atom/New(atom/loc, dmm_suite/preloader/_dmm_preloader)
|
||||
if(istype(_dmm_preloader, /dmm_suite/preloader))
|
||||
_dmm_preloader.load(src)
|
||||
. = ..()
|
||||
|
||||
//////////////////
|
||||
//Preloader datum
|
||||
//////////////////
|
||||
|
||||
/dmm_suite/preloader
|
||||
parent_type = /datum
|
||||
var/list/attributes
|
||||
|
||||
/dmm_suite/preloader/New(list/the_attributes)
|
||||
.=..()
|
||||
if(!the_attributes.len)
|
||||
Del()
|
||||
attributes = the_attributes
|
||||
|
||||
/dmm_suite/preloader/proc/load(atom/what)
|
||||
for(var/attribute in attributes)
|
||||
what.vars[attribute] = attributes[attribute]
|
||||
Del()
|
||||
Reference in New Issue
Block a user