diff --git a/code/controllers/subsystem/persistence.dm b/code/controllers/subsystem/persistence.dm index 05062a6314..97c569b99b 100644 --- a/code/controllers/subsystem/persistence.dm +++ b/code/controllers/subsystem/persistence.dm @@ -2,15 +2,13 @@ SUBSYSTEM_DEF(persistence) name = "Persistence" init_order = INIT_ORDER_PERSISTENCE flags = SS_NO_FIRE - var/savefile/secret_satchels var/list/satchel_blacklist = list() //this is a typecache var/list/new_secret_satchels = list() //these are objects - var/old_secret_satchels = "" + var/list/old_secret_satchels = list() var/list/obj/structure/chisel_message/chisel_messages = list() var/list/saved_messages = list() - var/savefile/trophy_sav var/list/saved_trophies = list() /datum/controller/subsystem/persistence/Initialize() @@ -21,67 +19,77 @@ SUBSYSTEM_DEF(persistence) ..() /datum/controller/subsystem/persistence/proc/LoadSatchels() - secret_satchels = new /savefile("data/npc_saves/SecretSatchels.sav") - satchel_blacklist = typecacheof(list(/obj/item/stack/tile/plasteel, /obj/item/crowbar)) - secret_satchels[SSmapping.config.map_name] >> old_secret_satchels - - var/list/expanded_old_satchels = list() - var/placed_satchels = 0 - - if(!isnull(old_secret_satchels)) - expanded_old_satchels = splittext(old_secret_satchels,"#") - if(PlaceSecretSatchel(expanded_old_satchels)) - placed_satchels++ + var/placed_satchel = 0 + var/path + var/obj/item/storage/backpack/satchel/flat/F = new() + if(fexists("data/npc_saves/SecretSatchels.sav")) //legacy compatability to convert old format to new + var/savefile/secret_satchels = new /savefile("data/npc_saves/SecretSatchels.sav") + var/sav_text + secret_satchels[SSmapping.config.map_name] >> sav_text + fdel(secret_satchels) + if(sav_text) + old_secret_satchels = splittext(sav_text,"#") + if(old_secret_satchels.len >= 20) + var/satchel_string = pick_n_take(old_secret_satchels) + var/list/chosen_satchel = splittext(satchel_string,"|") + if(chosen_satchel.len == 3) + F.x = text2num(chosen_satchel[1]) + F.y = text2num(chosen_satchel[2]) + F.z = ZLEVEL_STATION + path = text2path(chosen_satchel[3]) else - expanded_old_satchels.len = 0 - + var/json_file = file("data/npc_saves/SecretSatchels[SSmapping.config.map_name].json") + if(!fexists(json_file)) + return + var/list/json = list() + json = json_decode(file2text(json_file)) + old_secret_satchels = json["data"] + if(old_secret_satchels.len) + if(old_secret_satchels.len >= 20) //guards against low drop pools assuring that one player cannot reliably find his own gear. + var/pos = rand(1, old_secret_satchels.len) + old_secret_satchels.Cut(pos, pos+1) + F.x = old_secret_satchels[pos]["x"] + F.y = old_secret_satchels[pos]["y"] + F.z = ZLEVEL_STATION + path = text2path(old_secret_satchels[pos]["saved_obj"]) + if(!ispath(path)) + return + if(isfloorturf(F.loc) && !istype(F.loc, /turf/open/floor/plating/)) + F.hide(1) + new path(F) + placed_satchel++ var/list/free_satchels = list() for(var/turf/T in shuffle(block(locate(TRANSITIONEDGE,TRANSITIONEDGE,ZLEVEL_STATION), locate(world.maxx-TRANSITIONEDGE,world.maxy-TRANSITIONEDGE,ZLEVEL_STATION)))) //Nontrivially expensive but it's roundstart only if(isfloorturf(T) && !istype(T, /turf/open/floor/plating/)) free_satchels += new /obj/item/storage/backpack/satchel/flat/secret(T) - if(!isemptylist(free_satchels) && ((free_satchels.len + placed_satchels) >= (50 - expanded_old_satchels.len) * 0.1)) //up to six tiles, more than enough to kill anything that moves + if(!isemptylist(free_satchels) && ((free_satchels.len + placed_satchel) >= (50 - old_secret_satchels.len) * 0.1)) //up to six tiles, more than enough to kill anything that moves break -/datum/controller/subsystem/persistence/proc/PlaceSecretSatchel(list/expanded_old_satchels) - var/satchel_string - - if(expanded_old_satchels.len >= 20) //guards against low drop pools assuring that one player cannot reliably find his own gear. - satchel_string = pick_n_take(expanded_old_satchels) - - old_secret_satchels = jointext(expanded_old_satchels,"#") - WRITE_FILE(secret_satchels[SSmapping.config.map_name], old_secret_satchels) - - var/list/chosen_satchel = splittext(satchel_string,"|") - if(!chosen_satchel || isemptylist(chosen_satchel) || chosen_satchel.len != 3) //Malformed - return 0 - - var/path = text2path(chosen_satchel[3]) //If the item no longer exist, this returns null - if(!path) - return 0 - - var/obj/item/storage/backpack/satchel/flat/F = new() - F.x = text2num(chosen_satchel[1]) - F.y = text2num(chosen_satchel[2]) - F.z = ZLEVEL_STATION - if(isfloorturf(F.loc) && !istype(F.loc, /turf/open/floor/plating/)) - F.hide(1) - new path(F) - return 1 - /datum/controller/subsystem/persistence/proc/LoadPoly() for(var/mob/living/simple_animal/parrot/Poly/P in GLOB.living_mob_list) twitterize(P.speech_buffer, "polytalk") break //Who's been duping the bird?! /datum/controller/subsystem/persistence/proc/LoadChiselMessages() - var/savefile/chisel_messages_sav = new /savefile("data/npc_saves/ChiselMessages.sav") - var/saved_json - chisel_messages_sav[SSmapping.config.map_name] >> saved_json + var/list/saved_messages = list() + if(fexists("data/npc_saves/ChiselMessages.sav")) //legacy compatability to convert old format to new + var/savefile/chisel_messages_sav = new /savefile("data/npc_saves/ChiselMessages.sav") + var/saved_json + chisel_messages_sav[SSmapping.config.map_name] >> saved_json + if(!saved_json) + return + saved_messages = json_decode(saved_json) + fdel(chisel_messages_sav) + else + var/json_file = file("data/npc_saves/ChiselMessages[SSmapping.config.map_name].json") + if(!fexists(json_file)) + return + var/list/json + json = json_decode(file2text(json_file)) - if(!saved_json) - return - - var/list/saved_messages = json_decode(saved_json) + if(!json) + return + saved_messages = json["data"] for(var/item in saved_messages) if(!islist(item)) @@ -109,20 +117,23 @@ SUBSYSTEM_DEF(persistence) log_world("Loaded [saved_messages.len] engraved messages on map [SSmapping.config.map_name]") /datum/controller/subsystem/persistence/proc/LoadTrophies() - trophy_sav = new /savefile("data/npc_saves/TrophyItems.sav") - var/saved_json - trophy_sav >> saved_json - - if(!saved_json) - return - - var/decoded_json = json_decode(saved_json) - - if(!islist(decoded_json)) - return - - saved_trophies = decoded_json - + if(fexists("data/npc_saves/TrophyItems.sav")) //legacy compatability to convert old format to new + var/savefile/S = new /savefile("data/npc_saves/TrophyItems.sav") + var/saved_json + S >> saved_json + if(!saved_json) + return + saved_trophies = json_decode(saved_json) + fdel(S) + else + var/json_file = file("data/npc_saves/TrophyItems.json") + if(!fexists(json_file)) + return + var/list/json = list() + json = json_decode(file2text(json_file)) + if(!json) + return + saved_trophies = json["data"] SetUpTrophies(saved_trophies.Copy()) /datum/controller/subsystem/persistence/proc/SetUpTrophies(list/trophy_items) @@ -156,6 +167,8 @@ SUBSYSTEM_DEF(persistence) CollectTrophies() /datum/controller/subsystem/persistence/proc/CollectSecretSatchels() + var/list/satchels = list() + satchel_blacklist = typecacheof(list(/obj/item/stack/tile/plasteel, /obj/item/crowbar)) for(var/A in new_secret_satchels) var/obj/item/storage/backpack/satchel/flat/F = A if(QDELETED(F) || F.z != ZLEVEL_STATION || F.invisibility != INVISIBILITY_MAXIMUM) @@ -170,25 +183,39 @@ SUBSYSTEM_DEF(persistence) savable_obj += O.type if(isemptylist(savable_obj)) continue - old_secret_satchels += "[F.x]|[F.y]|[pick(savable_obj)]#" - WRITE_FILE(secret_satchels[SSmapping.config.map_name], old_secret_satchels) + var/list/data = list() + data["x"] = F.x + data["y"] = F.y + data["saved_obj"] = pick(savable_obj) + satchels += list(data) + var/json_file = file("data/npc_saves/SecretSatchels[SSmapping.config.map_name].json") + var/list/file_data = list() + file_data["data"] = satchels + fdel(json_file) + WRITE_FILE(json_file, json_encode(file_data)) /datum/controller/subsystem/persistence/proc/CollectChiselMessages() - var/savefile/chisel_messages_sav = new /savefile("data/npc_saves/ChiselMessages.sav") + var/json_file = file("data/npc_saves/ChiselMessages[SSmapping.config.map_name].json") for(var/obj/structure/chisel_message/M in chisel_messages) saved_messages += list(M.pack()) log_world("Saved [saved_messages.len] engraved messages on map [SSmapping.config.map_name]") - - WRITE_FILE(chisel_messages_sav[SSmapping.config.map_name], json_encode(saved_messages)) + var/list/file_data = list() + file_data["data"] = saved_messages + fdel(json_file) + WRITE_FILE(json_file, json_encode(file_data)) /datum/controller/subsystem/persistence/proc/SaveChiselMessage(obj/structure/chisel_message/M) saved_messages += list(M.pack()) // dm eats one list /datum/controller/subsystem/persistence/proc/CollectTrophies() - WRITE_FILE(trophy_sav, json_encode(saved_trophies)) + var/json_file = file("data/npc_saves/TrophyItems.json") + var/list/file_data = list() + file_data["data"] = saved_trophies + fdel(json_file) + WRITE_FILE(json_file, json_encode(file_data)) /datum/controller/subsystem/persistence/proc/SaveTrophy(obj/structure/displaycase/trophy/T) if(!T.added_roundstart && T.showpiece) diff --git a/code/modules/mob/living/carbon/human/interactive.dm b/code/modules/mob/living/carbon/human/interactive.dm index 18a4b3a7fb..b1eaa5349b 100644 --- a/code/modules/mob/living/carbon/human/interactive.dm +++ b/code/modules/mob/living/carbon/human/interactive.dm @@ -87,17 +87,28 @@ /// SNPC voice handling /mob/living/carbon/human/interactive/proc/loadVoice() - var/savefile/S = new /savefile("data/npc_saves/snpc.sav") - S["knownStrings"] >> knownStrings - + if(fexists("data/npc_saves/snpc.sav")) + var/savefile/S = new /savefile("data/npc_saves/snpc.sav") + S["knownStrings"] >> knownStrings + fdel(S) + else + var/json_file = file("data/npc_saves/snpc.json") + if(!fexists(json_file)) + return + var/list/json = list() + json = json_decode(file2text(json_file)) + knownStrings = json["knownStrings"] if(isnull(knownStrings)) knownStrings = list() /mob/living/carbon/human/interactive/proc/saveVoice() if(voice_saved) return - var/savefile/S = new /savefile("data/npc_saves/snpc.sav") - WRITE_FILE(S["knownStrings"], knownStrings) + var/json_file = file("data/npc_saves/snpc.json") + var/list/file_data = list() + file_data["knownStrings"] = knownStrings + fdel(json_file) + WRITE_FILE(json_file, json_encode(file_data)) //botPool funcs /mob/living/carbon/human/interactive/proc/takeDelegate(mob/living/carbon/human/interactive/from,doReset=TRUE) diff --git a/code/modules/mob/living/carbon/monkey/punpun.dm b/code/modules/mob/living/carbon/monkey/punpun.dm index b56028634f..da7ec5f186 100644 --- a/code/modules/mob/living/carbon/monkey/punpun.dm +++ b/code/modules/mob/living/carbon/monkey/punpun.dm @@ -24,7 +24,7 @@ ..() //These have to be after the parent new to ensure that the monkey - //bodyparts are actually created before we try to equip things to + //bodyparts are actually created before we try to equip things to //those slots if(relic_hat) equip_to_slot_or_del(new relic_hat, slot_head) @@ -42,32 +42,40 @@ ..() /mob/living/carbon/monkey/punpun/proc/Read_Memory() - var/savefile/S = new /savefile("data/npc_saves/Punpun.sav") - S["ancestor_name"] >> ancestor_name - S["ancestor_chain"] >> ancestor_chain - S["relic_hat"] >> relic_hat - S["relic_mask"] >> relic_mask + if(fexists("data/npc_saves/Punpun.sav")) + var/savefile/S = new /savefile("data/npc_saves/Punpun.sav") + S["ancestor_name"] >> ancestor_name + S["ancestor_chain"] >> ancestor_chain + S["relic_hat"] >> relic_hat + S["relic_mask"] >> relic_mask + fdel(S) + else + var/json_file = file("data/npc_saves/Punpun.json") + if(!fexists(json_file)) + return + var/list/json = list() + json = json_decode(file2text(json_file)) + ancestor_name = json["ancestor_name"] + ancestor_chain = json["ancestor_chain"] + relic_hat = json["relic_hat"] + relic_mask = json["relic_hat"] /mob/living/carbon/monkey/punpun/proc/Write_Memory(dead, gibbed) - var/savefile/S = new /savefile("data/npc_saves/Punpun.sav") + var/json_file = file("data/npc_saves/Punpun.json") + var/list/file_data = list() if(gibbed) - WRITE_FILE(S["ancestor_name"], null) - WRITE_FILE(S["ancestor_chain"], 1) - WRITE_FILE(S["relic_hat"], null) - WRITE_FILE(S["relic_mask"], null) - return + file_data["ancestor_name"] = null + file_data["ancestor_chain"] = null + file_data["relic_hat"] = null + file_data["relic_mask"] = null if(dead) - WRITE_FILE(S["ancestor_name"], ancestor_name) - WRITE_FILE(S["ancestor_chain"], ancestor_chain + 1) - if(!ancestor_name) //new monkey name this round - WRITE_FILE(S["ancestor_name"], name) - if(head) - WRITE_FILE(S["relic_hat"], head.type) - else - WRITE_FILE(S["relic_hat"], null) - if(wear_mask) - WRITE_FILE(S["relic_mask"], wear_mask.type) - else - WRITE_FILE(S["relic_mask"], null) + file_data["ancestor_name"] = ancestor_name + file_data["ancestor_chain"] = ancestor_chain + 1 + file_data["relic_hat"] = head ? head.type : null + file_data["relic_mask"] = wear_mask ? wear_mask.type : null + if(!ancestor_name) + file_data["ancestor_name"] = name + fdel(json_file) + WRITE_FILE(json_file, json_encode(json_file)) if(!dead) memory_saved = 1 diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm index c762bca6a0..bea25ebe6d 100644 --- a/code/modules/mob/living/simple_animal/friendly/cat.dm +++ b/code/modules/mob/living/simple_animal/friendly/cat.dm @@ -113,14 +113,22 @@ ..() /mob/living/simple_animal/pet/cat/Runtime/proc/Read_Memory() - var/savefile/S = new /savefile("data/npc_saves/Runtime.sav") - S["family"] >> family - + if(fexists("data/npc_saves/Runtime.sav")) //legacy compatability to convert old format to new + var/savefile/S = new /savefile("data/npc_saves/Runtime.sav") + S["family"] >> family + fdel(S) + else + var/json_file = file("data/npc_saves/Runtime.json") + if(!fexists(json_file)) + return + var/list/json = list() + json = json_decode(file2text(json_file)) + family = json["family"] if(isnull(family)) family = list() /mob/living/simple_animal/pet/cat/Runtime/proc/Write_Memory(dead) - var/savefile/S = new /savefile("data/npc_saves/Runtime.sav") + var/json_file = file("data/npc_saves/Runtime.json") family = list() if(!dead) for(var/mob/living/simple_animal/pet/cat/kitten/C in children) @@ -130,7 +138,8 @@ family[C.type] += 1 else family[C.type] = 1 - WRITE_FILE(S["family"], family) + fdel(json_file) + WRITE_FILE(json_file, json_encode(family)) memory_saved = 1 /mob/living/simple_animal/pet/cat/Runtime/proc/Deploy_The_Cats() diff --git a/code/modules/mob/living/simple_animal/friendly/dog.dm b/code/modules/mob/living/simple_animal/friendly/dog.dm index 5a6b00489e..370244f9d3 100644 --- a/code/modules/mob/living/simple_animal/friendly/dog.dm +++ b/code/modules/mob/living/simple_animal/friendly/dog.dm @@ -328,33 +328,44 @@ ..() /mob/living/simple_animal/pet/dog/corgi/Ian/proc/Read_Memory() - var/savefile/S = new /savefile("data/npc_saves/Ian.sav") - S["age"] >> age - S["record_age"] >> record_age - S["saved_head"] >> saved_head - + if(fexists("data/npc_saves/Ian.sav")) //legacy compatability to convert old format to new + var/savefile/S = new /savefile("data/npc_saves/Ian.sav") + S["age"] >> age + S["record_age"] >> record_age + S["saved_head"] >> saved_head + fdel(S) + else + var/json_file = file("data/npc_saves/Ian.json") + if(!fexists(json_file)) + return + var/list/json = list() + json = json_decode(file2text(json_file)) + age = json["age"] + record_age = json["record_age"] + saved_head = json["saved_head"] if(isnull(age)) age = 0 if(isnull(record_age)) record_age = 1 - if(saved_head) place_on_head(new saved_head) /mob/living/simple_animal/pet/dog/corgi/Ian/proc/Write_Memory(dead) - var/savefile/S = new /savefile("data/npc_saves/Ian.sav") + var/json_file = file("data/npc_saves/Ian.json") + var/list/file_data = list() if(!dead) - WRITE_FILE(S["age"], age + 1) + file_data["age"] = age + 1 if((age + 1) > record_age) - WRITE_FILE(S["record_age"], record_age + 1) + file_data["record_age"] = record_age + 1 if(inventory_head) - WRITE_FILE(S["saved_head"], inventory_head.type) + file_data["saved_head"] = inventory_head.type else - WRITE_FILE(S["age"], 0) - WRITE_FILE(S["saved_head"], null) + file_data["age"] = 0 + file_data["saved_head"] = null + fdel(json_file) + WRITE_FILE(json_file, json_encode(file_data)) memory_saved = 1 - /mob/living/simple_animal/pet/dog/corgi/Ian/Life() ..() diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index fd92cc17ff..78616fe007 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -277,19 +277,29 @@ Difficulty: Very Hard WriteMemory() /obj/machinery/smartfridge/black_box/proc/WriteMemory() - var/savefile/S = new /savefile("data/npc_saves/Blackbox.sav") + var/json_file = file("data/npc_saves/Blackbox.json") stored_items = list() for(var/obj/O in (contents-component_parts)) stored_items += O.type - - WRITE_FILE(S["stored_items"], stored_items) + var/list/file_data = list() + file_data["data"] = stored_items + fdel(json_file) + WRITE_FILE(json_file, json_encode(file_data)) memory_saved = TRUE /obj/machinery/smartfridge/black_box/proc/ReadMemory() - var/savefile/S = new /savefile("data/npc_saves/Blackbox.sav") - S["stored_items"] >> stored_items - + if(fexists("data/npc_saves/Blackbox.sav")) //legacy compatability to convert old format to new + var/savefile/S = new /savefile("data/npc_saves/Blackbox.sav") + S["stored_items"] >> stored_items + fdel(S) + else + var/json_file = file("data/npc_saves/Blackbox.json") + if(!fexists(json_file)) + return + var/list/json = list() + json = json_decode(file2text(json_file)) + stored_items = json["data"] if(isnull(stored_items)) stored_items = list() diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm index 66fbc8af8c..cd96dd2be8 100644 --- a/code/modules/mob/living/simple_animal/parrot.dm +++ b/code/modules/mob/living/simple_animal/parrot.dm @@ -924,22 +924,36 @@ ..(gibbed) /mob/living/simple_animal/parrot/Poly/proc/Read_Memory() - var/savefile/S = new /savefile("data/npc_saves/Poly.sav") - S["phrases"] >> speech_buffer - S["roundssurvived"] >> rounds_survived - S["longestsurvival"] >> longest_survival - S["longestdeathstreak"] >> longest_deathstreak - + if(fexists("data/npc_saves/Poly.sav")) //legacy compatability to convert old format to new + var/savefile/S = new /savefile("data/npc_saves/Poly.sav") + S["phrases"] >> speech_buffer + S["roundssurvived"] >> rounds_survived + S["longestsurvival"] >> longest_survival + S["longestdeathstreak"] >> longest_deathstreak + fdel(S) + else + var/json_file = file("data/npc_saves/Poly.json") + if(!fexists(json_file)) + return + var/list/json = list() + json = json_decode(file2text(json_file)) + speech_buffer = json["phrases"] + rounds_survived = json["roundssurvived"] + longest_survival = json["longestsurvival"] + longest_deathstreak = json["longestdeathstreak"] if(!islist(speech_buffer)) speech_buffer = list() /mob/living/simple_animal/parrot/Poly/proc/Write_Memory() - var/savefile/S = new /savefile("data/npc_saves/Poly.sav") + var/json_file = file("data/npc_saves/Punpun.json") + var/list/file_data = list() if(islist(speech_buffer)) - WRITE_FILE(S["phrases"], speech_buffer) - WRITE_FILE(S["roundssurvived"], rounds_survived) - WRITE_FILE(S["longestsurvival"], longest_survival) - WRITE_FILE(S["longestdeathstreak"], longest_deathstreak) + file_data["phrases"] = speech_buffer + file_data["roundssurvived"] = rounds_survived + file_data["longestsurvival"] = longest_survival + file_data["longestdeathstreak"] = longest_deathstreak + fdel(json_file) + WRITE_FILE(json_file, json_encode(file_data)) memory_saved = 1 /mob/living/simple_animal/parrot/Poly/ghost