diff --git a/.gitignore b/.gitignore
index 02f0c8cf790..9a9bbe0aafd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,7 @@ data/
/_maps/map_files/backup/*
/_maps/map_files/**/backup/*
/_maps/map_files/**/*.dmm.backup
+/_maps/quicksave/*
/nano/debug.html
*.db
stddef.dm
diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm
index a8a33784263..4224ad1aa5e 100644
--- a/code/game/dna/dna2.dm
+++ b/code/game/dna/dna2.dm
@@ -421,7 +421,7 @@ var/global/list/bad_blocks[0]
reg_dna[unique_enzymes] = character.real_name
// Hmm, I wonder how to go about this without a huge convention break
-/datum/dna/proc/serialize()
+/datum/dna/serialize()
var/data = list()
data["UE"] = unique_enzymes
data["SE"] = SE.Copy() // This is probably too lazy for my own good
@@ -432,7 +432,7 @@ var/global/list/bad_blocks[0]
data["real_name"] = real_name
return data
-/datum/dna/proc/deserialize(data)
+/datum/dna/deserialize(data)
unique_enzymes = data["UE"]
// The de-serializer is unlikely to tamper with the lists
SE = data["SE"]
@@ -441,4 +441,4 @@ var/global/list/bad_blocks[0]
UpdateSE()
species = data["species"]
b_type = data["b_type"]
- real_name = data["real_name"]
\ No newline at end of file
+ real_name = data["real_name"]
diff --git a/code/modules/admin/buildmode.dm b/code/modules/admin/buildmode.dm
index ed48b2dc6d0..f08121634d3 100644
--- a/code/modules/admin/buildmode.dm
+++ b/code/modules/admin/buildmode.dm
@@ -8,7 +8,8 @@
#define FILL_BUILDMODE 8
#define LINK_BUILDMODE 9
#define BOOM_BUILDMODE 10
-#define NUM_BUILDMODES 10
+#define SAVE_BUILDMODE 11
+#define NUM_BUILDMODES 11
/obj/screen/buildmode
icon = 'icons/misc/buildmode.dmi'
@@ -81,8 +82,11 @@
/obj/effect/buildmode_reticule/New(var/turf/t, var/client/c)
loc = t
I = image('icons/mob/blob.dmi', t, "marker",19.0,2) // Sprite reuse wooo
- cl = c
- cl.images += I
+ if(c)
+ cl = c
+ cl.images += I
+ else
+ log_debug("Buildmode reticule created without a client!")
/obj/effect/buildmode_reticule/proc/deselect()
qdel(src)
@@ -174,6 +178,8 @@
var/light = -1
var/flash = -1
var/flames = -1
+ // Saving mode
+ var/use_json = TRUE
/datum/click_intercept/buildmode/New(client/c)
..()
@@ -261,6 +267,13 @@
to_chat(user, "***********************************************************")
to_chat(user, "Mouse Button on obj = Kaboom")
to_chat(user, "***********************************************************")
+ if(SAVE_BUILDMODE)
+ to_chat(user, "***********************************************************")
+ to_chat(user, "Left Mouse Button on turf/obj/mob = Select corner")
+ to_chat(user, "***********************************************************")
+
+
+
/datum/click_intercept/buildmode/proc/change_settings(mob/user)
switch(mode)
@@ -345,6 +358,9 @@
var/flames = input("Range of flames. -1 to none", text("Input")) as num|null
if(flames == null) flames = -1
+ if(SAVE_BUILDMODE)
+ use_json = (alert("Would you like to use json (Default is \"Yes\")?",,"Yes","No") == "Yes")
+
/datum/click_intercept/buildmode/proc/change_dir()
switch(build_dir)
if(NORTH)
@@ -625,3 +641,27 @@
link_lines += L2
if(BOOM_BUILDMODE)
explosion(object, devastation, heavy, light, flash, null, null,flames)
+ if(SAVE_BUILDMODE)
+ if(!cornerA)
+ cornerA = select_tile(get_turf(object))
+ return
+ if(!cornerB)
+ cornerB = select_tile(get_turf(object))
+ if(left_click)
+ if(cornerA && cornerB)
+ var/turf/A = get_turf(cornerA)
+ var/turf/B = get_turf(cornerB)
+ deselect_region() // So we don't read our own reticules
+ var/map_name = input(holder, "Please select a name for your map", "Buildmode", "")
+ if(map_name == "")
+ return
+ var/map_flags = 0
+ if(use_json)
+ map_flags = 32 // Magic number defined in `writer.dm` that I can't use directly
+ // because #defines are for some reason our coding standard
+ var/our_map = maploader.save_map(A,B,map_name,map_flags)
+ holder << ftp(our_map) // send the map they've made! Or are stealing, whatever
+ to_chat(holder, "Map saving complete! [our_map]")
+ return
+
+ deselect_region()
diff --git a/code/modules/awaymissions/maploader/reader.dm b/code/modules/awaymissions/maploader/reader.dm
index ea59dd1d518..ff26e4071ac 100644
--- a/code/modules/awaymissions/maploader/reader.dm
+++ b/code/modules/awaymissions/maploader/reader.dm
@@ -373,6 +373,7 @@ var/global/dmm_suite/preloader/_preloader = new
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
+ log_debug(trim_left)
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
@@ -401,6 +402,7 @@ var/global/dmm_suite/preloader/_preloader = new
else if(ispath(text2path(trim_right)))
trim_right = text2path(trim_right)
+ log_debug(trim_right)
to_return[trim_left] = trim_right
else//simple var
@@ -430,19 +432,26 @@ var/global/dmm_suite/preloader/_preloader = new
parent_type = /datum
var/list/attributes
var/target_path
+ var/json_ready = 0
/dmm_suite/preloader/proc/setup(list/the_attributes, path)
if(the_attributes.len)
+ if("map_json_data" in the_attributes)
+ json_ready = 1
use_preloader = TRUE
attributes = the_attributes
target_path = path
/dmm_suite/preloader/proc/load(atom/what)
- for(var/attribute in attributes)
- var/value = attributes[attribute]
- if(islist(value))
- value = deepCopyList(value)
- what.vars[attribute] = value
+ if(json_ready)
+ log_debug(attributes["map_json_data"])
+ what.deserialize(json_decode(attributes["map_json_data"]))
+ else
+ for(var/attribute in attributes)
+ var/value = attributes[attribute]
+ if(islist(value))
+ value = deepCopyList(value)
+ what.vars[attribute] = value
use_preloader = FALSE
// If the map loader fails, make this safe
diff --git a/code/modules/awaymissions/maploader/writer.dm b/code/modules/awaymissions/maploader/writer.dm
index 208d0935a32..c3c0a1f8739 100644
--- a/code/modules/awaymissions/maploader/writer.dm
+++ b/code/modules/awaymissions/maploader/writer.dm
@@ -4,6 +4,7 @@
#define DMM_IGNORE_NPCS 8
#define DMM_IGNORE_PLAYERS 16
#define DMM_IGNORE_MOBS 24
+#define DMM_USE_JSON 32
dmm_suite{
var{
quote = "\""
@@ -31,11 +32,13 @@ dmm_suite{
if(!isturf(t1) || !isturf(t2)){
CRASH("Invalid arguments supplied to proc save_map, arguments were not turfs.")
}
+ var/map_prefix = "_maps/quicksave/"
+ var/map_path = "[map_prefix][map_name].dmm"
var/file_text = write_map(t1,t2,flags)
- if(fexists("[map_name].dmm")){
- fdel("[map_name].dmm")
+ if(fexists(map_path)){
+ fdel(map_path)
}
- var/saved_map = file("[map_name].dmm")
+ var/saved_map = file(map_path)
saved_map << file_text
return saved_map
}
@@ -44,17 +47,22 @@ dmm_suite{
if(!isturf(t1) || !isturf(t2)){
CRASH("Invalid arguments supplied to proc write_map, arguments were not turfs.")
}
- var/turf/nw = locate(min(t1.x,t2.x),max(t1.y,t2.y),min(t1.z,t2.z))
- var/turf/se = locate(max(t1.x,t2.x),min(t1.y,t2.y),max(t1.z,t2.z))
+ 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/template_buffer = {""}
var/dmm_text = {""}
- for(var/pos_z in nw.z to se.z){
- for(var/pos_y in nw.y to se.y){
- for(var/pos_x in nw.x to se.x){
+ for(var/pos_z in sw.z to ne.z){
+ // log_debug("z: [pos_z]")
+ for(var/pos_y in sw.y to ne.y){
+ // log_debug("y: [pos_y]")
+ for(var/pos_x in sw.x to ne.x){
+ // log_debug("x: [pos_x]")
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)
+ // log_debug("Template number: [template_number]")
+ // log_debug("Template string: [test_template]")
if(!template_number){
templates.Add(test_template)
template_number = templates.len
@@ -65,6 +73,10 @@ dmm_suite{
}
template_buffer += "."
}
+ // log_debug("[template_buffer]")
+ // log_debug("We are done with the loop, doing log")
+ if(templates.len == 0)
+ CRASH("No templates found!")
var/key_length = round/*floor*/(log(letter_digits.len,templates.len-1)+1)
var/list/keys[templates.len]
for(var/key_pos in 1 to templates.len){
@@ -98,57 +110,71 @@ 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
var/template = ""
var/obj_template = ""
var/mob_template = ""
var/turf_template = ""
if(!(flags & DMM_IGNORE_TURFS)){
- turf_template = "[model.type][check_attributes(model)],"
+ turf_template = "[model.type][check_attributes(model,use_json=use_json)],"
} else{ turf_template = "[world.turf],"}
var/area_template = ""
if(!(flags & DMM_IGNORE_OBJS)){
for(var/obj/O in model.contents){
- obj_template += "[O.type][check_attributes(O)],"
+ obj_template += "[O.type][check_attributes(O,use_json=use_json)],"
}
}
for(var/mob/M in model.contents){
if(M.client){
if(!(flags & DMM_IGNORE_PLAYERS)){
- mob_template += "[M.type][check_attributes(M)],"
+ mob_template += "[M.type][check_attributes(M,use_json=use_json)],"
}
}
else{
if(!(flags & DMM_IGNORE_NPCS)){
- mob_template += "[M.type][check_attributes(M)],"
+ mob_template += "[M.type][check_attributes(M,use_json=use_json)],"
}
}
}
if(!(flags & DMM_IGNORE_AREAS)){
var/area/m_area = model.loc
- area_template = "[m_area.type][check_attributes(m_area)]"
+ area_template = "[m_area.type][check_attributes(m_area,use_json=use_json)]"
} else{ area_template = "[world.area]"}
template = "[obj_template][mob_template][turf_template][area_template]"
return template
}
- check_attributes(var/atom/A){
+ check_attributes(var/atom/A,use_json=0){
var/attributes_text = {"{"}
- for(var/V in A.vars){
- sleep(-1)
- if((!issaved(A.vars[V])) || (A.vars[V]==initial(A.vars[V]))){continue}
- if(istext(A.vars[V])){
- attributes_text += {"[V] = "[A.vars[V]]""}
+ if(!use_json){
+ for(var/V in A.vars){
+ sleep(-1)
+ if((!issaved(A.vars[V])) || (A.vars[V]==initial(A.vars[V]))){continue}
+ if(istext(A.vars[V])){
+ attributes_text += {"[V] = "[A.vars[V]]""}
+ }
+ else if(isnum(A.vars[V])||ispath(A.vars[V])){
+ attributes_text += {"[V] = [A.vars[V]]"}
+ }
+ else if(isicon(A.vars[V])||isfile(A.vars[V])){
+ attributes_text += {"[V] = '[A.vars[V]]'"}
+ }
+ else{
+ continue
+ }
+ if(attributes_text != {"{"}){
+ attributes_text+={"; "}
+ }
}
- else if(isnum(A.vars[V])||ispath(A.vars[V])){
- attributes_text += {"[V] = [A.vars[V]]"}
- }
- else if(isicon(A.vars[V])||isfile(A.vars[V])){
- attributes_text += {"[V] = '[A.vars[V]]'"}
- }
- else{
- continue
- }
- if(attributes_text != {"{"}){
- attributes_text+={"; "}
+ } else {
+ var/list/yeah = A.serialize()
+ // Remove useless info
+ yeah -= "type"
+ var/json_stuff = json_encode(yeah)
+ if(yeah.len) {
+ log_debug(json_stuff)
+ attributes_text += {"map_json_data = "[json_stuff]""}
}
}
if(attributes_text=={"{"}){
@@ -171,4 +197,4 @@ dmm_suite{
return key
}
}
- }
\ No newline at end of file
+ }
diff --git a/code/modules/persistence/persistence.dm b/code/modules/persistence/persistence.dm
index cc5a7684947..8e05ef2432e 100644
--- a/code/modules/persistence/persistence.dm
+++ b/code/modules/persistence/persistence.dm
@@ -5,8 +5,9 @@
* If we want to store this info, we can pass it to `json_encode` or some other
* interface that suits our fancy, to make it into an easily-handled string
*/
-/atom/movable/proc/serialize()
- return list("type" = "[type]")
+/datum/proc/serialize()
+ var/data = list("type" = "[type]")
+ return data
/*
* This is given the byond list from above, to bring this atom to the state
@@ -17,9 +18,28 @@
* Also, this should only be called by `json_to_object` in persistence.dm - at least
* with current plans - that way it can actually initialize the type from the list
*/
-/atom/movable/proc/deserialize(var/data)
+/datum/proc/deserialize(var/list/data)
return
+
+/atom/movable
+ // This is so specific atoms can override these, and ignore certain ones
+ var/list/vars_to_save = list("dir","name","color","icon","icon_state")
+/atom/movable/serialize()
+ var/list/data = ..()
+ for(var/thing in vars_to_save)
+ if(vars[thing] != initial(vars[thing]))
+ data[thing] = vars[thing]
+ return data
+
+
+/atom/movable/deserialize(var/list/data)
+ for(var/thing in vars_to_save)
+ if(thing in data)
+ vars[thing] = data[thing]
+ ..()
+
+
/proc/json_to_object(var/json_data, var/loc)
var/data = json_decode(json_data)
return list_to_object(data, loc)
diff --git a/icons/misc/buildmode.dmi b/icons/misc/buildmode.dmi
index 062d5b404c8..cc54e5aec0f 100644
Binary files a/icons/misc/buildmode.dmi and b/icons/misc/buildmode.dmi differ