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