Skip to content

Commit

Permalink
[MIRROR] Split persistence into subfiles [MDB IGNORE] (#24797) (#455)
Browse files Browse the repository at this point in the history
* Split persistence into subfiles

* Skyrat Edits

---------

Co-authored-by: SkyratBot <[email protected]>
Co-authored-by: Tim <[email protected]>
Co-authored-by: Giz <[email protected]>
  • Loading branch information
4 people authored Nov 5, 2023
1 parent 12d60c0 commit 030c8a9
Show file tree
Hide file tree
Showing 12 changed files with 640 additions and 632 deletions.
631 changes: 0 additions & 631 deletions code/controllers/subsystem/persistence.dm

This file was deleted.

108 changes: 108 additions & 0 deletions code/controllers/subsystem/persistence/_persistence.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#define FILE_RECENT_MAPS "data/RecentMaps.json"
#define KEEP_ROUNDS_MAP 3

SUBSYSTEM_DEF(persistence)
name = "Persistence"
init_order = INIT_ORDER_PERSISTENCE
flags = SS_NO_FIRE

///instantiated wall engraving components
var/list/wall_engravings = list()
///all saved persistent engravings loaded from JSON
var/list/saved_engravings = list()
///tattoo stories that we're saving.
var/list/prison_tattoos_to_save = list()
///tattoo stories that have been selected for this round.
var/list/prison_tattoos_to_use = list()
var/list/saved_messages = list()
var/list/saved_modes = list(1,2,3)
var/list/saved_maps = list()
var/list/blocked_maps = list()
var/list/saved_trophies = list()
var/list/picture_logging_information = list()
var/list/obj/structure/sign/picture_frame/photo_frames
var/list/obj/item/storage/photo_album/photo_albums
var/rounds_since_engine_exploded = 0
var/delam_highscore = 0
var/tram_hits_this_round = 0
var/tram_hits_last_round = 0

/datum/controller/subsystem/persistence/Initialize()
load_poly()
load_wall_engravings()
load_prisoner_tattoos()
load_trophies()
load_recent_maps()
load_photo_persistence()
load_randomized_recipes()
load_custom_outfits()
load_delamination_counter()
load_panic_bunker() //SKYRAT EDIT ADDITION - PANICBUNKER
load_tram_counter()
load_adventures()
return SS_INIT_SUCCESS

///Collects all data to persist.
/datum/controller/subsystem/persistence/proc/collect_data()
save_wall_engravings()
save_prisoner_tattoos()
collect_trophies()
collect_maps()
save_photo_persistence() //THIS IS PERSISTENCE, NOT THE LOGGING PORTION.
save_randomized_recipes()
save_scars()
save_custom_outfits()
save_modular_persistence() // SKYRAT EDIT ADDITION - MODULAR_PERSISTENCE
save_delamination_counter()
if(SStransport.can_fire)
for(var/datum/transport_controller/linear/tram/transport as anything in SStransport.transports_by_type[TRANSPORT_TYPE_TRAM])
save_tram_history(transport.specific_transport_id)
save_tram_counter()
save_panic_bunker() //SKYRAT EDIT ADDITION - PANICBUNKER

///Loads up Poly's speech buffer.
/datum/controller/subsystem/persistence/proc/load_poly()
for(var/mob/living/simple_animal/parrot/poly/P in GLOB.alive_mob_list)
twitterize(P.speech_buffer, "polytalk")
break //Who's been duping the bird?!

/// Loads up the amount of times maps appeared to alter their appearance in voting and rotation.
/datum/controller/subsystem/persistence/proc/load_recent_maps()
var/map_sav = FILE_RECENT_MAPS
if(!fexists(FILE_RECENT_MAPS))
return
var/list/json = json_decode(file2text(map_sav))
if(!json)
return
saved_maps = json["data"]

//Convert the mapping data to a shared blocking list, saves us doing this in several places later.
for(var/map in config.maplist)
var/datum/map_config/VM = config.maplist[map]
var/run = 0
if(VM.map_name == SSmapping.config.map_name)
run++
for(var/name in SSpersistence.saved_maps)
if(VM.map_name == name)
run++
if(run >= 2) //If run twice in the last KEEP_ROUNDS_MAP + 1 (including current) rounds, disable map for voting and rotation.
blocked_maps += VM.map_name

///Updates the list of the most recent maps.
/datum/controller/subsystem/persistence/proc/collect_maps()
if(length(saved_maps) > KEEP_ROUNDS_MAP) //Get rid of extras from old configs.
saved_maps.Cut(KEEP_ROUNDS_MAP+1)
var/mapstosave = min(length(saved_maps)+1, KEEP_ROUNDS_MAP)
if(length(saved_maps) < mapstosave) //Add extras if too short, one per round.
saved_maps += mapstosave
for(var/i = mapstosave; i > 1; i--)
saved_maps[i] = saved_maps[i-1]
saved_maps[1] = SSmapping.config.map_name
var/json_file = file(FILE_RECENT_MAPS)
var/list/file_data = list()
file_data["data"] = saved_maps
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))

#undef FILE_RECENT_MAPS
#undef KEEP_ROUNDS_MAP
20 changes: 20 additions & 0 deletions code/controllers/subsystem/persistence/counter_delamination.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/// Location where we save the information about how many rounds it has been since the engine blew up
#define DELAMINATION_COUNT_FILEPATH "data/rounds_since_delamination.txt"
#define DELAMINATION_HIGHSCORE_FILEPATH "data/delamination_highscore.txt"

/datum/controller/subsystem/persistence/proc/load_delamination_counter()
if(!fexists(DELAMINATION_COUNT_FILEPATH))
return
rounds_since_engine_exploded = text2num(file2text(DELAMINATION_COUNT_FILEPATH))
if(fexists(DELAMINATION_HIGHSCORE_FILEPATH))
delam_highscore = text2num(file2text(DELAMINATION_HIGHSCORE_FILEPATH))
for(var/obj/machinery/incident_display/sign as anything in GLOB.map_delamination_counters)
sign.update_delam_count(rounds_since_engine_exploded, delam_highscore)

/datum/controller/subsystem/persistence/proc/save_delamination_counter()
rustg_file_write("[rounds_since_engine_exploded + 1]", DELAMINATION_COUNT_FILEPATH)
if((rounds_since_engine_exploded + 1) > delam_highscore)
rustg_file_write("[rounds_since_engine_exploded + 1]", DELAMINATION_HIGHSCORE_FILEPATH)

#undef DELAMINATION_COUNT_FILEPATH
#undef DELAMINATION_HIGHSCORE_FILEPATH
64 changes: 64 additions & 0 deletions code/controllers/subsystem/persistence/counter_tram_hits.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/// Location where we save the information about how many times the tram hit on previous round
#define TRAM_COUNT_FILEPATH "data/tram_hits_last_round.txt"
#define MAX_TRAM_SAVES 4

// Loads historical tram data
/datum/controller/subsystem/persistence/proc/load_tram_history(specific_transport_id)
var/list/raw_saved_trams = list()
var/json_file = file("data/tram_data/[specific_transport_id].json")
if(!fexists(json_file))
return
var/list/json = json_decode(file2text(json_file))
if(!json)
return
raw_saved_trams = json["data"]

var/list/previous_tram_data = list()
for(var/raw_json in raw_saved_trams)
var/datum/tram_mfg_info/parsed_tram_data = new
parsed_tram_data.load_from_json(raw_json)
previous_tram_data += parsed_tram_data
return previous_tram_data

// Saves historical tram data
/datum/controller/subsystem/persistence/proc/save_tram_history(specific_transport_id)
var/list/packaged_tram_data = list()
for(var/datum/transport_controller/linear/tram/transport as anything in SStransport.transports_by_type[TRANSPORT_TYPE_TRAM])
if(transport.specific_transport_id == specific_transport_id)
packaged_tram_data = package_tram_data(transport)
break

var/json_file = file("data/tram_data/[specific_transport_id].json")
var/list/file_data = list()
var/list/converted_data = list()

for(var/datum/tram_mfg_info/data in packaged_tram_data)
converted_data += list(data.export_to_json())

file_data["data"] = converted_data
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))

/datum/controller/subsystem/persistence/proc/package_tram_data(datum/transport_controller/linear/tram/tram_controller)
var/list/packaged_data = list()
var/list/tram_list = tram_controller.tram_history
if(!isnull(tram_list))
while(tram_list.len > MAX_TRAM_SAVES)
tram_list.Cut(1,2)

for(var/datum/tram_mfg_info/data as anything in tram_list)
packaged_data += data

packaged_data += tram_controller.tram_registration
return packaged_data

/datum/controller/subsystem/persistence/proc/load_tram_counter()
if(!fexists(TRAM_COUNT_FILEPATH))
return
tram_hits_last_round = text2num(file2text(TRAM_COUNT_FILEPATH))

/datum/controller/subsystem/persistence/proc/save_tram_counter()
rustg_file_write("[tram_hits_this_round]", TRAM_COUNT_FILEPATH)

#undef TRAM_COUNT_FILEPATH
#undef MAX_TRAM_SAVES
32 changes: 32 additions & 0 deletions code/controllers/subsystem/persistence/custom_outfits.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
///Loads the custom outfits of every admin.
/datum/controller/subsystem/persistence/proc/load_custom_outfits()
var/file = file("data/custom_outfits.json")
if(!fexists(file))
return
var/outfits_json = file2text(file)
var/list/outfits = json_decode(outfits_json)
if(!islist(outfits))
return

for(var/outfit_data in outfits)
if(!islist(outfit_data))
continue

var/outfittype = text2path(outfit_data["outfit_type"])
if(!ispath(outfittype, /datum/outfit))
continue
var/datum/outfit/outfit = new outfittype
if(!outfit.load_from(outfit_data))
continue
GLOB.custom_outfits += outfit

///Saves each admin's custom outfit list
/datum/controller/subsystem/persistence/proc/save_custom_outfits()
var/file = file("data/custom_outfits.json")
fdel(file)

var/list/data = list()
for(var/datum/outfit/outfit in GLOB.custom_outfits)
data += list(outfit.get_json_data())

WRITE_FILE(file, json_encode(data))
84 changes: 84 additions & 0 deletions code/controllers/subsystem/persistence/engravings.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
///Loads all engravings, and places a select amount in maintenance and the prison.
/datum/controller/subsystem/persistence/proc/load_wall_engravings()
var/json_file = file(ENGRAVING_SAVE_FILE)
if(!fexists(json_file))
return

var/list/json = json_decode(file2text(json_file))
if(!json)
return

if(json["version"] < ENGRAVING_PERSISTENCE_VERSION)
update_wall_engravings(json)

saved_engravings = json["entries"]

if(!saved_engravings.len)
log_world("Failed to load engraved messages on map [SSmapping.config.map_name]")
return

var/list/viable_turfs = get_area_turfs(/area/station/maintenance, subtypes = TRUE) + get_area_turfs(/area/station/security/prison, subtypes = TRUE)
var/list/turfs_to_pick_from = list()

for(var/turf/T as anything in viable_turfs)
if(!isclosedturf(T))
continue
turfs_to_pick_from += T

var/successfully_loaded_engravings = 0

for(var/iteration in 1 to rand(MIN_PERSISTENT_ENGRAVINGS, MAX_PERSISTENT_ENGRAVINGS))
var/engraving = pick_n_take(saved_engravings)
if(!islist(engraving))
stack_trace("something's wrong with the engraving data! one of the saved engravings wasn't a list!")
continue

var/turf/closed/engraved_wall = pick(turfs_to_pick_from)

if(HAS_TRAIT(engraved_wall, TRAIT_NOT_ENGRAVABLE))
continue

engraved_wall.AddComponent(/datum/component/engraved, engraving["story"], FALSE, engraving["story_value"])
successfully_loaded_engravings++
turfs_to_pick_from -= engraved_wall

log_world("Loaded [successfully_loaded_engravings] engraved messages on map [SSmapping.config.map_name]")

///Saves all new engravings in the world.
/datum/controller/subsystem/persistence/proc/save_wall_engravings()
var/list/saved_data = list()

saved_data["version"] = ENGRAVING_PERSISTENCE_VERSION
saved_data["entries"] = list()


var/json_file = file(ENGRAVING_SAVE_FILE)
if(fexists(json_file))
var/list/old_json = json_decode(file2text(json_file))
if(old_json)
saved_data["entries"] = old_json["entries"]

for(var/datum/component/engraved/engraving in wall_engravings)
if(!engraving.persistent_save)
continue
var/area/engraved_area = get_area(engraving.parent)
if(!(engraved_area.area_flags & PERSISTENT_ENGRAVINGS))
continue
saved_data["entries"] += engraving.save_persistent()

fdel(json_file)

WRITE_FILE(json_file, json_encode(saved_data))

///This proc can update entries if the format has changed at some point.
/datum/controller/subsystem/persistence/proc/update_wall_engravings(json)
for(var/engraving_entry in json["entries"])
continue //no versioning yet

//Save it to the file
var/json_file = file(ENGRAVING_SAVE_FILE)
fdel(json_file)
WRITE_FILE(json_file, json_encode(json))

return json

86 changes: 86 additions & 0 deletions code/controllers/subsystem/persistence/photo_albums.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
///Loads up the photo album source file.
/datum/controller/subsystem/persistence/proc/get_photo_albums()
var/album_path = file("data/photo_albums.json")
if(fexists(album_path))
return json_decode(file2text(album_path))

///Loads up the photo frames source file.
/datum/controller/subsystem/persistence/proc/get_photo_frames()
var/frame_path = file("data/photo_frames.json")
if(fexists(frame_path))
return json_decode(file2text(frame_path))

/// Removes the identifier of a persistent photo frame from the json.
/datum/controller/subsystem/persistence/proc/remove_photo_frames(identifier)
var/frame_path = file("data/photo_frames.json")
if(!fexists(frame_path))
return

var/frame_json = json_decode(file2text(frame_path))
frame_json -= identifier

frame_json = json_encode(frame_json)
fdel(frame_path)
WRITE_FILE(frame_path, frame_json)

///Loads photo albums, and populates them; also loads and applies frames to picture frames.
/datum/controller/subsystem/persistence/proc/load_photo_persistence()
var/album_path = file("data/photo_albums.json")
var/frame_path = file("data/photo_frames.json")
if(fexists(album_path))
var/list/json = json_decode(file2text(album_path))
if(json.len)
for(var/i in photo_albums)
var/obj/item/storage/photo_album/A = i
if(!A.persistence_id)
continue
if(json[A.persistence_id])
A.populate_from_id_list(json[A.persistence_id])

if(fexists(frame_path))
var/list/json = json_decode(file2text(frame_path))
if(json.len)
for(var/i in photo_frames)
var/obj/structure/sign/picture_frame/PF = i
if(!PF.persistence_id)
continue
if(json[PF.persistence_id])
PF.load_from_id(json[PF.persistence_id])

///Saves the contents of photo albums and the picture frames.
/datum/controller/subsystem/persistence/proc/save_photo_persistence()
var/album_path = file("data/photo_albums.json")
var/frame_path = file("data/photo_frames.json")

var/list/frame_json = list()
var/list/album_json = list()

if(fexists(album_path))
album_json = json_decode(file2text(album_path))
fdel(album_path)

for(var/i in photo_albums)
var/obj/item/storage/photo_album/A = i
if(!istype(A) || !A.persistence_id)
continue
var/list/L = A.get_picture_id_list()
album_json[A.persistence_id] = L

album_json = json_encode(album_json)

WRITE_FILE(album_path, album_json)

if(fexists(frame_path))
frame_json = json_decode(file2text(frame_path))
fdel(frame_path)

for(var/i in photo_frames)
var/obj/structure/sign/picture_frame/F = i
if(!istype(F) || !F.persistence_id)
continue
frame_json[F.persistence_id] = F.get_photo_id()

frame_json = json_encode(frame_json)

WRITE_FILE(frame_path, frame_json)

Loading

0 comments on commit 030c8a9

Please sign in to comment.