diff --git a/code/controllers/subsystem/persistent_data.dm b/code/controllers/subsystem/persistent_data.dm new file mode 100644 index 00000000000..dcf9d7cb9fc --- /dev/null +++ b/code/controllers/subsystem/persistent_data.dm @@ -0,0 +1,58 @@ +/** + * # Persistent Data Subsystem + * + * Provides a centralised handler for persistent data reading and writing. + * The subsystem does not do any actual spawning itself, as this focuses on objects and mobs + * Should anything that is turf persistence related added in, that can be chucked into this SS + * Its quite a simple subsystem. For now, anyways. + * + */ +SUBSYSTEM_DEF(persistent_data) + name = "Persistent Data" + init_order = INIT_ORDER_PERSISTENCE // -95 | Loads after EVERYTHING else + flags = SS_NO_FIRE + /// List of atoms registered into the subsystem for persistent data storage. Can be anything at all + var/list/registered_atoms = list() + +/datum/controller/subsystem/persistent_data/Initialize() + // Load all the data of registered atoms + for(var/atom/A in registered_atoms) + A.PersistentLoad() + return ..() + +/datum/controller/subsystem/persistent_data/Shutdown() + // Save all the data of registered atoms + for(var/atom/A in registered_atoms) + A.PersistentSave() + + +/** + * Proc to register an atom with SSpersistent_data + * + * This will add any provided atom to the list of registered atoms, and add it to the Initialization queue + * If the system has already initialized, it calls PersistentLoad() at that moment + * + * Arguments: + * * A - Atom to register + */ +/datum/controller/subsystem/persistent_data/proc/register(atom/A) + registered_atoms |= A + if(initialized) + A.PersistentLoad() + +/** + * Atom Persistent Loader + * + * Overridden on every atom which needs to load persistent data + */ +/atom/proc/PersistentLoad() + stack_trace("PeristentLoad() called on an atom which does not have persistent data storage!") + +/** + * Atom Persistent Saver + * + * Overridden on every atom which needs to save persistent data + */ +/atom/proc/PersistentSave() + stack_trace("PeristentSave() called on an atom which does not have persistent data storage!") + diff --git a/code/modules/mining/lavaland/loot/colossus_loot.dm b/code/modules/mining/lavaland/loot/colossus_loot.dm index 3dfcb1fffdb..27107687e36 100644 --- a/code/modules/mining/lavaland/loot/colossus_loot.dm +++ b/code/modules/mining/lavaland/loot/colossus_loot.dm @@ -16,95 +16,6 @@ ..() new /obj/item/crusher_trophy/blaster_tubes(src) - -//Black Box - -/obj/machinery/smartfridge/black_box - name = "black box" - desc = "A completely indestructible chunk of crystal, rumoured to predate the start of this universe. It looks like you could store things inside it." - icon = 'icons/obj/lavaland/artefacts.dmi' - icon_state = "blackbox" - luminosity = 8 - max_n_of_items = INFINITY - resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF - pixel_y = -4 - use_power = NO_POWER_USE - var/memory_saved = FALSE - var/list/stored_items = list() - var/static/list/blacklist = typecacheof(list(/obj/item/spellbook)) - -/obj/machinery/smartfridge/black_box/update_icon() - return - -/obj/machinery/smartfridge/black_box/accept_check(obj/item/O) - if(!istype(O)) - return FALSE - if(is_type_in_typecache(O, blacklist)) - return FALSE - return TRUE - -/obj/machinery/smartfridge/black_box/New() - var/static/obj/machinery/smartfridge/black_box/current - if(current && current != src) - qdel(src, force=TRUE) - return - current = src - ReadMemory() - . = ..() - -/obj/machinery/smartfridge/black_box/process() - ..() - if(!memory_saved && SSticker.current_state == GAME_STATE_FINISHED) - WriteMemory() - -/obj/machinery/smartfridge/black_box/proc/WriteMemory() - var/savefile/S = new /savefile("data/npc_saves/Blackbox.sav") - stored_items = list() - - for(var/obj/O in (contents-component_parts)) - stored_items += O.type - - S["stored_items"] << stored_items - 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(isnull(stored_items)) - stored_items = list() - - for(var/item in stored_items) - create_item(item) - -//in it's own proc to avoid issues with items that nolonger exist in the code base. -//try catch doesn't always prevent byond runtimes from halting a proc, -/obj/machinery/smartfridge/black_box/proc/create_item(item_type) - new item_type(src) - -/obj/machinery/smartfridge/black_box/Destroy(force = FALSE) - if(force) - for(var/thing in src) - qdel(thing) - return ..() - else - return QDEL_HINT_LETMELIVE - - -//No taking it apart - -/obj/machinery/smartfridge/black_box/default_deconstruction_screwdriver() - return - -/obj/machinery/smartfridge/black_box/exchange_parts() - return - -/obj/machinery/smartfridge/black_box/default_unfasten_wrench() - return - -/obj/machinery/smartfridge/black_box/default_deconstruction_crowbar() - return - ///Anomolous Crystal/// /obj/machinery/anomalous_crystal diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm index f44244b7eae..314170f9cf5 100644 --- a/code/modules/mob/living/simple_animal/friendly/cat.dm +++ b/code/modules/mob/living/simple_animal/friendly/cat.dm @@ -40,20 +40,18 @@ gold_core_spawnable = NO_SPAWN unique_pet = TRUE var/list/family = list() - var/memory_saved = 0 var/list/children = list() //Actual mob instances of children - var/cats_deployed = 0 /mob/living/simple_animal/pet/cat/Runtime/New() - Read_Memory() + SSpersistent_data.register(src) ..() -/mob/living/simple_animal/pet/cat/Runtime/Life(seconds, times_fired) - if(!cats_deployed && SSticker.current_state >= GAME_STATE_SETTING_UP) - Deploy_The_Cats() - if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved) - Write_Memory() - ..() +/mob/living/simple_animal/pet/cat/Runtime/PersistentLoad() + Read_Memory() + Deploy_The_Cats() + +/mob/living/simple_animal/pet/cat/Runtime/PersistentSave() + Write_Memory(FALSE) /mob/living/simple_animal/pet/cat/Runtime/make_babies() var/mob/baby = ..() @@ -62,8 +60,9 @@ return baby /mob/living/simple_animal/pet/cat/Runtime/death() - if(can_die() && !memory_saved) - Write_Memory(1) + if(can_die()) + Write_Memory(TRUE) + SSpersistent_data.registered_atoms -= src // We just saved. Dont save at round end return ..() /mob/living/simple_animal/pet/cat/Runtime/proc/Read_Memory() @@ -72,6 +71,7 @@ if(isnull(family)) family = list() + log_debug("Persistent data for [src] loaded (family: [list2params(family)])") /mob/living/simple_animal/pet/cat/Runtime/proc/Write_Memory(dead) var/savefile/S = new /savefile("data/npc_saves/Runtime.sav") @@ -85,21 +85,18 @@ else family[C.type] = 1 S["family"] << family - memory_saved = 1 + log_debug("Persistent data for [src] saved (family: [list2params(family)])") /mob/living/simple_animal/pet/cat/Runtime/proc/Deploy_The_Cats() - cats_deployed = 1 for(var/cat_type in family) if(family[cat_type] > 0) for(var/i in 1 to min(family[cat_type],100)) //Limits to about 500 cats, you wouldn't think this would be needed (BUT IT IS) new cat_type(loc) - /mob/living/simple_animal/pet/cat/Life() ..() make_babies() - /mob/living/simple_animal/pet/cat/handle_automated_action() if(!stat && !buckled) if(prob(1)) diff --git a/code/modules/mob/living/simple_animal/friendly/dog.dm b/code/modules/mob/living/simple_animal/friendly/dog.dm index 915bf9ae2aa..5c12dc8ca5e 100644 --- a/code/modules/mob/living/simple_animal/friendly/dog.dm +++ b/code/modules/mob/living/simple_animal/friendly/dog.dm @@ -420,13 +420,18 @@ unique_pet = TRUE var/age = 0 var/record_age = 1 - var/memory_saved = FALSE var/saved_head //path /mob/living/simple_animal/pet/dog/corgi/Ian/Initialize(mapload) . = ..() - //parent call must happen first to ensure IAN - //is not in nullspace when child puppies spawn + SSpersistent_data.register(src) + +/mob/living/simple_animal/pet/dog/corgi/Ian/death() + Write_Memory(TRUE) + SSpersistent_data.registered_atoms -= src // We already wrote here, dont overwrite! + ..() + +/mob/living/simple_animal/pet/dog/corgi/Ian/PersistentLoad() Read_Memory() if(age == 0) var/turf/target = get_turf(loc) @@ -437,6 +442,7 @@ P.gender = MALE P.desc = "It's the HoP's beloved corgi puppy." Write_Memory(FALSE) + SSpersistent_data.registered_atoms -= src // We already wrote here, dont overwrite! qdel(src) return else if(age == record_age) @@ -446,16 +452,8 @@ desc = "At a ripe old age of [record_age], Ian's not as spry as he used to be, but he'll always be the HoP's beloved corgi." //RIP turns_per_move = 20 -/mob/living/simple_animal/pet/dog/corgi/Ian/Life() - if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved) - Write_Memory(FALSE) - memory_saved = TRUE - ..() - -/mob/living/simple_animal/pet/dog/corgi/Ian/death() - if(!memory_saved) - Write_Memory(TRUE) - ..() +/mob/living/simple_animal/pet/dog/corgi/Ian/PersistentSave() + Write_Memory(FALSE) /mob/living/simple_animal/pet/dog/corgi/Ian/proc/Read_Memory() if(fexists("data/npc_saves/Ian.sav")) //legacy compatability to convert old format to new @@ -478,6 +476,7 @@ record_age = 1 if(saved_head) place_on_head(new saved_head) + log_debug("Persistent data for [src] loaded (age: [age] | record_age: [record_age] | saved_head: [saved_head])") /mob/living/simple_animal/pet/dog/corgi/Ian/proc/Write_Memory(dead) var/json_file = file("data/npc_saves/Ian.json") @@ -498,6 +497,7 @@ file_data["saved_head"] = null fdel(json_file) WRITE_FILE(json_file, json_encode(file_data)) + log_debug("Persistent data for [src] saved (age: [age] | record_age: [record_age] | saved_head: [saved_head])") /mob/living/simple_animal/pet/dog/corgi/Ian/handle_automated_movement() . = ..() diff --git a/paradise.dme b/paradise.dme index 9732867adf5..87d44aa59ee 100644 --- a/paradise.dme +++ b/paradise.dme @@ -239,6 +239,7 @@ #include "code\controllers\subsystem\npcpool.dm" #include "code\controllers\subsystem\overlays.dm" #include "code\controllers\subsystem\parallax.dm" +#include "code\controllers\subsystem\persistent_data.dm" #include "code\controllers\subsystem\radio.dm" #include "code\controllers\subsystem\runechat.dm" #include "code\controllers\subsystem\shuttles.dm"