mirror of
https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13.git
synced 2025-12-10 18:02:57 +00:00
persistent module
This commit is contained in:
@@ -5,18 +5,9 @@ SUBSYSTEM_DEF(persistence)
|
|||||||
name = "Persistence"
|
name = "Persistence"
|
||||||
init_order = INIT_ORDER_PERSISTENCE
|
init_order = INIT_ORDER_PERSISTENCE
|
||||||
flags = SS_NO_FIRE
|
flags = SS_NO_FIRE
|
||||||
var/list/satchel_blacklist = list() //this is a typecache
|
|
||||||
var/list/new_secret_satchels = list() //these are objects
|
|
||||||
var/list/old_secret_satchels = list()
|
|
||||||
|
|
||||||
var/list/obj/structure/chisel_message/chisel_messages = list()
|
var/list/obj/structure/chisel_message/chisel_messages = list()
|
||||||
var/list/saved_messages = list()
|
var/list/saved_messages = list()
|
||||||
var/list/saved_modes = list(1,2,3)
|
|
||||||
var/list/saved_dynamic_rules = list(list(),list(),list())
|
|
||||||
var/list/saved_storytellers = list("foo","bar","baz")
|
|
||||||
var/list/average_dynamic_threat = 50
|
|
||||||
var/list/saved_maps
|
|
||||||
var/list/saved_trophies = list()
|
|
||||||
var/list/spawned_objects = list()
|
var/list/spawned_objects = list()
|
||||||
var/list/antag_rep = list()
|
var/list/antag_rep = list()
|
||||||
var/list/antag_rep_change = list()
|
var/list/antag_rep_change = list()
|
||||||
@@ -28,62 +19,71 @@ SUBSYSTEM_DEF(persistence)
|
|||||||
var/list/paintings = list()
|
var/list/paintings = list()
|
||||||
|
|
||||||
/datum/controller/subsystem/persistence/Initialize()
|
/datum/controller/subsystem/persistence/Initialize()
|
||||||
LoadSatchels()
|
LoadServerPersistence()
|
||||||
LoadPoly()
|
LoadGamePersistence()
|
||||||
LoadChiselMessages()
|
LoadMapPersistence()
|
||||||
LoadTrophies()
|
return ..()
|
||||||
LoadRecentModes()
|
|
||||||
LoadRecentStorytellers()
|
/datum/controller/subsystem/persistence/proc/CollectData()
|
||||||
LoadRecentRulesets()
|
SaveServerPersistence()
|
||||||
LoadRecentMaps()
|
SaveGamePersistence()
|
||||||
LoadPhotoPersistence()
|
SaveMapPersistence()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads persistent data relevant to the server: Configurations, past gamemodes, votes, etc
|
||||||
|
*/
|
||||||
|
/datum/controller/subsystem/persistence/proc/LoadServerPersistence()
|
||||||
for(var/client/C in GLOB.clients)
|
for(var/client/C in GLOB.clients)
|
||||||
LoadSavedVote(C.ckey)
|
LoadSavedVote(C.ckey)
|
||||||
if(CONFIG_GET(flag/use_antag_rep))
|
if(CONFIG_GET(flag/use_antag_rep))
|
||||||
LoadAntagReputation()
|
LoadAntagReputation()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves persistent data relevant to the server: Configurations, past gamemodes, votes, etc
|
||||||
|
*/
|
||||||
|
/datum/controller/subsystem/persistence/proc/SaveServerPersistence()
|
||||||
|
if(CONFIG_GET(flag/use_antag_rep))
|
||||||
|
CollectAntagReputation()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads persistent data relevant to the game in general: Trophies, antag reputation, etc
|
||||||
|
*
|
||||||
|
* Legacy map persistence systems also use this.
|
||||||
|
*/
|
||||||
|
/datum/controller/subsystem/persistence/proc/LoadGamePersistence()
|
||||||
|
LoadChiselMessages()
|
||||||
|
LoadPhotoPersistence()
|
||||||
LoadRandomizedRecipes()
|
LoadRandomizedRecipes()
|
||||||
LoadPanicBunker()
|
|
||||||
return ..()
|
|
||||||
|
|
||||||
/datum/controller/subsystem/persistence/proc/LoadSatchels()
|
/**
|
||||||
var/placed_satchel = 0
|
* Saves persistent data relevant to the game in general: Trophies, antag reputation, etc
|
||||||
var/path
|
*
|
||||||
|
* Legacy map persistence systems also use this.
|
||||||
|
*/
|
||||||
|
/datum/controller/subsystem/persistence/proc/SaveGamePersistence()
|
||||||
|
SaveRandomizedRecipes()
|
||||||
|
CollectChiselMessages()
|
||||||
|
SavePhotoPersistence() //THIS IS PERSISTENCE, NOT THE LOGGING PORTION.
|
||||||
|
SavePaintings()
|
||||||
|
SaveScars()
|
||||||
|
|
||||||
var/json_file = file("data/npc_saves/SecretSatchels[SSmapping.config.map_name].json")
|
/**
|
||||||
var/list/json = list()
|
* Loads persistent data relevant to the current map: Objects, etc.
|
||||||
if(fexists(json_file))
|
*
|
||||||
json = json_decode(file2text(json_file))
|
* @params
|
||||||
|
* data_directory - The data directory to use. Each map with a persistence key has its own, and this is based on the persistence key.
|
||||||
|
*/
|
||||||
|
/datum/controller/subsystem/persistence/proc/LoadMapPersistence(data_directory)
|
||||||
|
return
|
||||||
|
|
||||||
old_secret_satchels = json["data"]
|
/**
|
||||||
var/obj/item/storage/backpack/satchel/flat/F
|
* Saves persistent data relevant to the current map: Objects, etc.
|
||||||
if(old_secret_satchels && old_secret_satchels.len >= 10) //guards against low drop pools assuring that one player cannot reliably find his own gear.
|
*
|
||||||
var/pos = rand(1, old_secret_satchels.len)
|
* @params
|
||||||
F = new()
|
* data_directory - The data directory to use. Each map with a persistence key has its own, and this is based on the persistence key.
|
||||||
old_secret_satchels.Cut(pos, pos+1 % old_secret_satchels.len)
|
*/
|
||||||
F.x = old_secret_satchels[pos]["x"]
|
/datum/controller/subsystem/persistence/proc/SaveMapPersistence(data_directory)
|
||||||
F.y = old_secret_satchels[pos]["y"]
|
return
|
||||||
F.z = SSmapping.station_start
|
|
||||||
path = text2path(old_secret_satchels[pos]["saved_obj"])
|
|
||||||
|
|
||||||
if(F)
|
|
||||||
if(isfloorturf(F.loc) && !isplatingturf(F.loc))
|
|
||||||
F.hide(1)
|
|
||||||
if(ispath(path))
|
|
||||||
var/spawned_item = new path(F)
|
|
||||||
spawned_objects[spawned_item] = TRUE
|
|
||||||
placed_satchel++
|
|
||||||
var/free_satchels = 0
|
|
||||||
for(var/turf/T in shuffle(block(locate(TRANSITIONEDGE,TRANSITIONEDGE,SSmapping.station_start), locate(world.maxx-TRANSITIONEDGE,world.maxy-TRANSITIONEDGE,SSmapping.station_start)))) //Nontrivially expensive but it's roundstart only
|
|
||||||
if(isfloorturf(T) && !isplatingturf(T))
|
|
||||||
new /obj/item/storage/backpack/satchel/flat/secret(T)
|
|
||||||
free_satchels++
|
|
||||||
if((free_satchels + placed_satchel) == 10) //ten tiles, more than enough to kill anything that moves
|
|
||||||
break
|
|
||||||
|
|
||||||
/datum/controller/subsystem/persistence/proc/LoadPoly()
|
|
||||||
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?!
|
|
||||||
|
|
||||||
/datum/controller/subsystem/persistence/proc/LoadChiselMessages()
|
/datum/controller/subsystem/persistence/proc/LoadChiselMessages()
|
||||||
var/list/saved_messages = list()
|
var/list/saved_messages = list()
|
||||||
@@ -130,63 +130,6 @@ SUBSYSTEM_DEF(persistence)
|
|||||||
|
|
||||||
log_world("Loaded [saved_messages.len] engraved messages on map [SSmapping.config.map_name]")
|
log_world("Loaded [saved_messages.len] engraved messages on map [SSmapping.config.map_name]")
|
||||||
|
|
||||||
/datum/controller/subsystem/persistence/proc/LoadTrophies()
|
|
||||||
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("data/npc_saves/TrophyItems.sav")
|
|
||||||
else
|
|
||||||
var/json_file = file("data/npc_saves/TrophyItems.json")
|
|
||||||
if(!fexists(json_file))
|
|
||||||
return
|
|
||||||
var/list/json = json_decode(file2text(json_file))
|
|
||||||
if(!json)
|
|
||||||
return
|
|
||||||
saved_trophies = json["data"]
|
|
||||||
SetUpTrophies(saved_trophies.Copy())
|
|
||||||
|
|
||||||
/datum/controller/subsystem/persistence/proc/LoadRecentModes()
|
|
||||||
var/json_file = file("data/RecentModes.json")
|
|
||||||
if(!fexists(json_file))
|
|
||||||
return
|
|
||||||
var/list/json = json_decode(file2text(json_file))
|
|
||||||
if(!json)
|
|
||||||
return
|
|
||||||
saved_modes = json["data"]
|
|
||||||
|
|
||||||
/datum/controller/subsystem/persistence/proc/LoadRecentRulesets()
|
|
||||||
var/json_file = file("data/RecentRulesets.json")
|
|
||||||
if(!fexists(json_file))
|
|
||||||
return
|
|
||||||
var/list/json = json_decode(file2text(json_file))
|
|
||||||
if(!json)
|
|
||||||
return
|
|
||||||
saved_dynamic_rules = json["data"]
|
|
||||||
|
|
||||||
/datum/controller/subsystem/persistence/proc/LoadRecentStorytellers()
|
|
||||||
var/json_file = file("data/RecentStorytellers.json")
|
|
||||||
if(!fexists(json_file))
|
|
||||||
return
|
|
||||||
var/list/json = json_decode(file2text(json_file))
|
|
||||||
if(!json)
|
|
||||||
return
|
|
||||||
saved_storytellers = json["data"]
|
|
||||||
if(saved_storytellers.len > 3)
|
|
||||||
average_dynamic_threat = saved_storytellers[4]
|
|
||||||
saved_storytellers.len = 3
|
|
||||||
|
|
||||||
/datum/controller/subsystem/persistence/proc/LoadRecentMaps()
|
|
||||||
var/json_file = file("data/RecentMaps.json")
|
|
||||||
if(!fexists(json_file))
|
|
||||||
return
|
|
||||||
var/list/json = json_decode(file2text(json_file))
|
|
||||||
if(!json)
|
|
||||||
return
|
|
||||||
saved_maps = json["maps"]
|
|
||||||
|
|
||||||
/datum/controller/subsystem/persistence/proc/LoadAntagReputation()
|
/datum/controller/subsystem/persistence/proc/LoadAntagReputation()
|
||||||
var/json = file2text(FILE_ANTAG_REP)
|
var/json = file2text(FILE_ANTAG_REP)
|
||||||
@@ -207,59 +150,6 @@ SUBSYSTEM_DEF(persistence)
|
|||||||
return
|
return
|
||||||
saved_votes[ckey] = json["data"]
|
saved_votes[ckey] = json["data"]
|
||||||
|
|
||||||
/datum/controller/subsystem/persistence/proc/SetUpTrophies(list/trophy_items)
|
|
||||||
for(var/A in GLOB.trophy_cases)
|
|
||||||
var/obj/structure/displaycase/trophy/T = A
|
|
||||||
if (T.showpiece)
|
|
||||||
continue
|
|
||||||
T.added_roundstart = TRUE
|
|
||||||
|
|
||||||
var/trophy_data = pick_n_take(trophy_items)
|
|
||||||
|
|
||||||
if(!islist(trophy_data))
|
|
||||||
continue
|
|
||||||
|
|
||||||
var/list/chosen_trophy = trophy_data
|
|
||||||
|
|
||||||
if(!chosen_trophy || isemptylist(chosen_trophy)) //Malformed
|
|
||||||
continue
|
|
||||||
|
|
||||||
var/path = text2path(chosen_trophy["path"]) //If the item no longer exist, this returns null
|
|
||||||
if(!path)
|
|
||||||
continue
|
|
||||||
|
|
||||||
T.showpiece = new /obj/item/showpiece_dummy(T, path)
|
|
||||||
T.trophy_message = chosen_trophy["message"]
|
|
||||||
T.placer_key = chosen_trophy["placer_key"]
|
|
||||||
T.update_icon()
|
|
||||||
|
|
||||||
/datum/controller/subsystem/persistence/proc/CollectData()
|
|
||||||
CollectChiselMessages()
|
|
||||||
CollectSecretSatchels()
|
|
||||||
CollectTrophies()
|
|
||||||
CollectRoundtype()
|
|
||||||
if(istype(SSticker.mode, /datum/game_mode/dynamic))
|
|
||||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
|
||||||
CollectStoryteller(mode)
|
|
||||||
CollectRulesets(mode)
|
|
||||||
RecordMaps()
|
|
||||||
SavePhotoPersistence() //THIS IS PERSISTENCE, NOT THE LOGGING PORTION.
|
|
||||||
if(CONFIG_GET(flag/use_antag_rep))
|
|
||||||
CollectAntagReputation()
|
|
||||||
SaveRandomizedRecipes()
|
|
||||||
SavePanicBunker()
|
|
||||||
SavePaintings()
|
|
||||||
SaveScars()
|
|
||||||
|
|
||||||
/datum/controller/subsystem/persistence/proc/LoadPanicBunker()
|
|
||||||
var/bunker_path = file("data/bunker_passthrough.json")
|
|
||||||
if(fexists(bunker_path))
|
|
||||||
var/list/json = json_decode(file2text(bunker_path))
|
|
||||||
GLOB.bunker_passthrough = json["data"]
|
|
||||||
for(var/ckey in GLOB.bunker_passthrough)
|
|
||||||
if(daysSince(GLOB.bunker_passthrough[ckey]) >= CONFIG_GET(number/max_bunker_days))
|
|
||||||
GLOB.bunker_passthrough -= ckey
|
|
||||||
|
|
||||||
/datum/controller/subsystem/persistence/proc/GetPhotoAlbums()
|
/datum/controller/subsystem/persistence/proc/GetPhotoAlbums()
|
||||||
var/album_path = file("data/photo_albums.json")
|
var/album_path = file("data/photo_albums.json")
|
||||||
if(fexists(album_path))
|
if(fexists(album_path))
|
||||||
@@ -329,35 +219,6 @@ SUBSYSTEM_DEF(persistence)
|
|||||||
|
|
||||||
WRITE_FILE(frame_path, frame_json)
|
WRITE_FILE(frame_path, frame_json)
|
||||||
|
|
||||||
/datum/controller/subsystem/persistence/proc/CollectSecretSatchels()
|
|
||||||
satchel_blacklist = typecacheof(list(/obj/item/stack/tile/plasteel, /obj/item/crowbar))
|
|
||||||
var/list/satchels_to_add = list()
|
|
||||||
for(var/A in new_secret_satchels)
|
|
||||||
var/obj/item/storage/backpack/satchel/flat/F = A
|
|
||||||
if(QDELETED(F) || F.z != SSmapping.station_start || F.invisibility != INVISIBILITY_MAXIMUM)
|
|
||||||
continue
|
|
||||||
var/list/savable_obj = list()
|
|
||||||
for(var/obj/O in F)
|
|
||||||
if(is_type_in_typecache(O, satchel_blacklist) || (O.flags_1 & ADMIN_SPAWNED_1))
|
|
||||||
continue
|
|
||||||
if(O.persistence_replacement)
|
|
||||||
savable_obj += O.persistence_replacement
|
|
||||||
else
|
|
||||||
savable_obj += O.type
|
|
||||||
if(isemptylist(savable_obj))
|
|
||||||
continue
|
|
||||||
var/list/data = list()
|
|
||||||
data["x"] = F.x
|
|
||||||
data["y"] = F.y
|
|
||||||
data["saved_obj"] = pick(savable_obj)
|
|
||||||
satchels_to_add += list(data)
|
|
||||||
|
|
||||||
var/json_file = file("data/npc_saves/SecretSatchels[SSmapping.config.map_name].json")
|
|
||||||
var/list/file_data = list()
|
|
||||||
fdel(json_file)
|
|
||||||
file_data["data"] = old_secret_satchels + satchels_to_add
|
|
||||||
WRITE_FILE(json_file, json_encode(file_data))
|
|
||||||
|
|
||||||
/datum/controller/subsystem/persistence/proc/CollectChiselMessages()
|
/datum/controller/subsystem/persistence/proc/CollectChiselMessages()
|
||||||
var/json_file = file("data/npc_saves/ChiselMessages[SSmapping.config.map_name].json")
|
var/json_file = file("data/npc_saves/ChiselMessages[SSmapping.config.map_name].json")
|
||||||
|
|
||||||
@@ -374,82 +235,6 @@ SUBSYSTEM_DEF(persistence)
|
|||||||
saved_messages += list(M.pack()) // dm eats one list
|
saved_messages += list(M.pack()) // dm eats one list
|
||||||
|
|
||||||
|
|
||||||
/datum/controller/subsystem/persistence/proc/CollectTrophies()
|
|
||||||
var/json_file = file("data/npc_saves/TrophyItems.json")
|
|
||||||
var/list/file_data = list()
|
|
||||||
file_data["data"] = remove_duplicate_trophies(saved_trophies)
|
|
||||||
fdel(json_file)
|
|
||||||
WRITE_FILE(json_file, json_encode(file_data))
|
|
||||||
|
|
||||||
/datum/controller/subsystem/persistence/proc/SavePanicBunker()
|
|
||||||
var/json_file = file("data/bunker_passthrough.json")
|
|
||||||
var/list/file_data = list()
|
|
||||||
file_data["data"] = GLOB.bunker_passthrough
|
|
||||||
fdel(json_file)
|
|
||||||
WRITE_FILE(json_file,json_encode(file_data))
|
|
||||||
|
|
||||||
/datum/controller/subsystem/persistence/proc/remove_duplicate_trophies(list/trophies)
|
|
||||||
var/list/ukeys = list()
|
|
||||||
. = list()
|
|
||||||
for(var/trophy in trophies)
|
|
||||||
var/tkey = "[trophy["path"]]-[trophy["message"]]"
|
|
||||||
if(ukeys[tkey])
|
|
||||||
continue
|
|
||||||
else
|
|
||||||
. += list(trophy)
|
|
||||||
ukeys[tkey] = TRUE
|
|
||||||
|
|
||||||
/datum/controller/subsystem/persistence/proc/SaveTrophy(obj/structure/displaycase/trophy/T)
|
|
||||||
if(!T.added_roundstart && T.showpiece)
|
|
||||||
var/list/data = list()
|
|
||||||
data["path"] = T.showpiece.type
|
|
||||||
data["message"] = T.trophy_message
|
|
||||||
data["placer_key"] = T.placer_key
|
|
||||||
saved_trophies += list(data)
|
|
||||||
|
|
||||||
/datum/controller/subsystem/persistence/proc/CollectRoundtype()
|
|
||||||
saved_modes[3] = saved_modes[2]
|
|
||||||
saved_modes[2] = saved_modes[1]
|
|
||||||
saved_modes[1] = SSticker.mode.config_tag
|
|
||||||
var/json_file = file("data/RecentModes.json")
|
|
||||||
var/list/file_data = list()
|
|
||||||
file_data["data"] = saved_modes
|
|
||||||
fdel(json_file)
|
|
||||||
WRITE_FILE(json_file, json_encode(file_data))
|
|
||||||
|
|
||||||
/datum/controller/subsystem/persistence/proc/CollectStoryteller(var/datum/game_mode/dynamic/mode)
|
|
||||||
saved_storytellers.len = 3
|
|
||||||
saved_storytellers[3] = saved_storytellers[2]
|
|
||||||
saved_storytellers[2] = saved_storytellers[1]
|
|
||||||
saved_storytellers[1] = mode.storyteller.name
|
|
||||||
average_dynamic_threat = (mode.max_threat + average_dynamic_threat) / 2
|
|
||||||
var/json_file = file("data/RecentStorytellers.json")
|
|
||||||
var/list/file_data = list()
|
|
||||||
file_data["data"] = saved_storytellers + average_dynamic_threat
|
|
||||||
fdel(json_file)
|
|
||||||
WRITE_FILE(json_file, json_encode(file_data))
|
|
||||||
|
|
||||||
/datum/controller/subsystem/persistence/proc/CollectRulesets(var/datum/game_mode/dynamic/mode)
|
|
||||||
saved_dynamic_rules[3] = saved_dynamic_rules[2]
|
|
||||||
saved_dynamic_rules[2] = saved_dynamic_rules[1]
|
|
||||||
saved_dynamic_rules[1] = list()
|
|
||||||
for(var/r in mode.executed_rules)
|
|
||||||
var/datum/dynamic_ruleset/rule = r
|
|
||||||
saved_dynamic_rules[1] += rule.config_tag
|
|
||||||
var/json_file = file("data/RecentRulesets.json")
|
|
||||||
var/list/file_data = list()
|
|
||||||
file_data["data"] = saved_dynamic_rules
|
|
||||||
fdel(json_file)
|
|
||||||
WRITE_FILE(json_file, json_encode(file_data))
|
|
||||||
|
|
||||||
/datum/controller/subsystem/persistence/proc/RecordMaps()
|
|
||||||
saved_maps = saved_maps?.len ? list("[SSmapping.config.map_name]") | saved_maps : list("[SSmapping.config.map_name]")
|
|
||||||
var/json_file = file("data/RecentMaps.json")
|
|
||||||
var/list/file_data = list()
|
|
||||||
file_data["maps"] = saved_maps
|
|
||||||
fdel(json_file)
|
|
||||||
WRITE_FILE(json_file, json_encode(file_data))
|
|
||||||
|
|
||||||
|
|
||||||
/datum/controller/subsystem/persistence/proc/CollectAntagReputation()
|
/datum/controller/subsystem/persistence/proc/CollectAntagReputation()
|
||||||
var/ANTAG_REP_MAXIMUM = CONFIG_GET(number/antag_rep_maximum)
|
var/ANTAG_REP_MAXIMUM = CONFIG_GET(number/antag_rep_maximum)
|
||||||
26
code/controllers/subsystem/persistence/panic_bunker.dm
Normal file
26
code/controllers/subsystem/persistence/panic_bunker.dm
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* Persists panic bunker whitelisting for a configured period of time
|
||||||
|
*/
|
||||||
|
/datum/controller/subsystem/persistence/LoadServerPersistence()
|
||||||
|
. = ..()
|
||||||
|
LoadPanicBunker()
|
||||||
|
|
||||||
|
/datum/controller/subsystem/persistence/SaveServerPersistence()
|
||||||
|
. = ..()
|
||||||
|
SavePanicBunker()
|
||||||
|
|
||||||
|
/datum/controller/subsystem/persistence/proc/LoadPanicBunker()
|
||||||
|
var/bunker_path = file("data/bunker_passthrough.json")
|
||||||
|
if(fexists(bunker_path))
|
||||||
|
var/list/json = json_decode(file2text(bunker_path))
|
||||||
|
GLOB.bunker_passthrough = json["data"]
|
||||||
|
for(var/ckey in GLOB.bunker_passthrough)
|
||||||
|
if(daysSince(GLOB.bunker_passthrough[ckey]) >= CONFIG_GET(number/max_bunker_days))
|
||||||
|
GLOB.bunker_passthrough -= ckey
|
||||||
|
|
||||||
|
/datum/controller/subsystem/persistence/proc/SavePanicBunker()
|
||||||
|
var/json_file = file("data/bunker_passthrough.json")
|
||||||
|
var/list/file_data = list()
|
||||||
|
file_data["data"] = GLOB.bunker_passthrough
|
||||||
|
fdel(json_file)
|
||||||
|
WRITE_FILE(json_file,json_encode(file_data))
|
||||||
11
code/controllers/subsystem/persistence/poly_parrot.dm
Normal file
11
code/controllers/subsystem/persistence/poly_parrot.dm
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* Persists poly messages across rounds
|
||||||
|
*/
|
||||||
|
/datum/controller/subsystem/persistence/LoadGamePersistence()
|
||||||
|
. = ..()
|
||||||
|
LoadPoly()
|
||||||
|
|
||||||
|
/datum/controller/subsystem/persistence/proc/LoadPoly()
|
||||||
|
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?!
|
||||||
107
code/controllers/subsystem/persistence/recent_votes_etc.dm
Normal file
107
code/controllers/subsystem/persistence/recent_votes_etc.dm
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/**
|
||||||
|
* Stores recently played gamemodes, maps, etc.
|
||||||
|
*/
|
||||||
|
/datum/controller/subsystem/persistence
|
||||||
|
var/list/saved_modes = list(1,2,3)
|
||||||
|
var/list/saved_dynamic_rules = list(list(),list(),list())
|
||||||
|
var/list/saved_storytellers = list("foo","bar","baz")
|
||||||
|
var/list/average_dynamic_threat = 50
|
||||||
|
var/list/saved_maps
|
||||||
|
|
||||||
|
/datum/controller/subsystem/persistence/SaveServerPersistence()
|
||||||
|
. = ..()
|
||||||
|
CollectRoundtype()
|
||||||
|
if(istype(SSticker.mode, /datum/game_mode/dynamic))
|
||||||
|
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||||
|
CollectStoryteller(mode)
|
||||||
|
CollectRulesets(mode)
|
||||||
|
RecordMaps()
|
||||||
|
|
||||||
|
/datum/controller/subsystem/persistence/LoadServerPersistence()
|
||||||
|
. = ..()
|
||||||
|
LoadRecentModes()
|
||||||
|
LoadRecentStorytellers()
|
||||||
|
LoadRecentRulesets()
|
||||||
|
LoadRecentMaps()
|
||||||
|
|
||||||
|
/datum/controller/subsystem/persistence/proc/CollectRoundtype()
|
||||||
|
saved_modes[3] = saved_modes[2]
|
||||||
|
saved_modes[2] = saved_modes[1]
|
||||||
|
saved_modes[1] = SSticker.mode.config_tag
|
||||||
|
var/json_file = file("data/RecentModes.json")
|
||||||
|
var/list/file_data = list()
|
||||||
|
file_data["data"] = saved_modes
|
||||||
|
fdel(json_file)
|
||||||
|
WRITE_FILE(json_file, json_encode(file_data))
|
||||||
|
|
||||||
|
/datum/controller/subsystem/persistence/proc/CollectStoryteller(var/datum/game_mode/dynamic/mode)
|
||||||
|
saved_storytellers.len = 3
|
||||||
|
saved_storytellers[3] = saved_storytellers[2]
|
||||||
|
saved_storytellers[2] = saved_storytellers[1]
|
||||||
|
saved_storytellers[1] = mode.storyteller.name
|
||||||
|
average_dynamic_threat = (mode.max_threat + average_dynamic_threat) / 2
|
||||||
|
var/json_file = file("data/RecentStorytellers.json")
|
||||||
|
var/list/file_data = list()
|
||||||
|
file_data["data"] = saved_storytellers + average_dynamic_threat
|
||||||
|
fdel(json_file)
|
||||||
|
WRITE_FILE(json_file, json_encode(file_data))
|
||||||
|
|
||||||
|
/datum/controller/subsystem/persistence/proc/CollectRulesets(var/datum/game_mode/dynamic/mode)
|
||||||
|
saved_dynamic_rules[3] = saved_dynamic_rules[2]
|
||||||
|
saved_dynamic_rules[2] = saved_dynamic_rules[1]
|
||||||
|
saved_dynamic_rules[1] = list()
|
||||||
|
for(var/r in mode.executed_rules)
|
||||||
|
var/datum/dynamic_ruleset/rule = r
|
||||||
|
saved_dynamic_rules[1] += rule.config_tag
|
||||||
|
var/json_file = file("data/RecentRulesets.json")
|
||||||
|
var/list/file_data = list()
|
||||||
|
file_data["data"] = saved_dynamic_rules
|
||||||
|
fdel(json_file)
|
||||||
|
WRITE_FILE(json_file, json_encode(file_data))
|
||||||
|
|
||||||
|
/datum/controller/subsystem/persistence/proc/RecordMaps()
|
||||||
|
saved_maps = saved_maps?.len ? list("[SSmapping.config.map_name]") | saved_maps : list("[SSmapping.config.map_name]")
|
||||||
|
var/json_file = file("data/RecentMaps.json")
|
||||||
|
var/list/file_data = list()
|
||||||
|
file_data["maps"] = saved_maps
|
||||||
|
fdel(json_file)
|
||||||
|
WRITE_FILE(json_file, json_encode(file_data))
|
||||||
|
|
||||||
|
/datum/controller/subsystem/persistence/proc/LoadRecentModes()
|
||||||
|
var/json_file = file("data/RecentModes.json")
|
||||||
|
if(!fexists(json_file))
|
||||||
|
return
|
||||||
|
var/list/json = json_decode(file2text(json_file))
|
||||||
|
if(!json)
|
||||||
|
return
|
||||||
|
saved_modes = json["data"]
|
||||||
|
|
||||||
|
/datum/controller/subsystem/persistence/proc/LoadRecentRulesets()
|
||||||
|
var/json_file = file("data/RecentRulesets.json")
|
||||||
|
if(!fexists(json_file))
|
||||||
|
return
|
||||||
|
var/list/json = json_decode(file2text(json_file))
|
||||||
|
if(!json)
|
||||||
|
return
|
||||||
|
saved_dynamic_rules = json["data"]
|
||||||
|
|
||||||
|
/datum/controller/subsystem/persistence/proc/LoadRecentStorytellers()
|
||||||
|
var/json_file = file("data/RecentStorytellers.json")
|
||||||
|
if(!fexists(json_file))
|
||||||
|
return
|
||||||
|
var/list/json = json_decode(file2text(json_file))
|
||||||
|
if(!json)
|
||||||
|
return
|
||||||
|
saved_storytellers = json["data"]
|
||||||
|
if(saved_storytellers.len > 3)
|
||||||
|
average_dynamic_threat = saved_storytellers[4]
|
||||||
|
saved_storytellers.len = 3
|
||||||
|
|
||||||
|
/datum/controller/subsystem/persistence/proc/LoadRecentMaps()
|
||||||
|
var/json_file = file("data/RecentMaps.json")
|
||||||
|
if(!fexists(json_file))
|
||||||
|
return
|
||||||
|
var/list/json = json_decode(file2text(json_file))
|
||||||
|
if(!json)
|
||||||
|
return
|
||||||
|
saved_maps = json["maps"]
|
||||||
79
code/controllers/subsystem/persistence/secret_satchels.dm
Normal file
79
code/controllers/subsystem/persistence/secret_satchels.dm
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
/**
|
||||||
|
* Secret satchel persistence - allows storing of items in underfloor satchels that's loaded later.
|
||||||
|
*/
|
||||||
|
/datum/controller/subsystem/persistence
|
||||||
|
var/list/satchel_blacklist = list() //this is a typecache
|
||||||
|
var/list/new_secret_satchels = list() //these are objects
|
||||||
|
var/list/old_secret_satchels = list()
|
||||||
|
|
||||||
|
/datum/controller/subsystem/persistence/LoadGamePersistence()
|
||||||
|
. = ..()
|
||||||
|
LoadSatchels()
|
||||||
|
|
||||||
|
/datum/controller/subsystem/persistence/SaveGamePersistence()
|
||||||
|
. = ..()
|
||||||
|
CollectSecretSatchels()
|
||||||
|
|
||||||
|
/datum/controller/subsystem/persistence/proc/LoadSatchels()
|
||||||
|
var/placed_satchel = 0
|
||||||
|
var/path
|
||||||
|
|
||||||
|
var/json_file = file("data/npc_saves/SecretSatchels[SSmapping.config.map_name].json")
|
||||||
|
var/list/json = list()
|
||||||
|
if(fexists(json_file))
|
||||||
|
json = json_decode(file2text(json_file))
|
||||||
|
|
||||||
|
old_secret_satchels = json["data"]
|
||||||
|
var/obj/item/storage/backpack/satchel/flat/F
|
||||||
|
if(old_secret_satchels && old_secret_satchels.len >= 10) //guards against low drop pools assuring that one player cannot reliably find his own gear.
|
||||||
|
var/pos = rand(1, old_secret_satchels.len)
|
||||||
|
F = new()
|
||||||
|
old_secret_satchels.Cut(pos, pos+1 % old_secret_satchels.len)
|
||||||
|
F.x = old_secret_satchels[pos]["x"]
|
||||||
|
F.y = old_secret_satchels[pos]["y"]
|
||||||
|
F.z = SSmapping.station_start
|
||||||
|
path = text2path(old_secret_satchels[pos]["saved_obj"])
|
||||||
|
|
||||||
|
if(F)
|
||||||
|
if(isfloorturf(F.loc) && !isplatingturf(F.loc))
|
||||||
|
F.hide(1)
|
||||||
|
if(ispath(path))
|
||||||
|
var/spawned_item = new path(F)
|
||||||
|
spawned_objects[spawned_item] = TRUE
|
||||||
|
placed_satchel++
|
||||||
|
var/free_satchels = 0
|
||||||
|
for(var/turf/T in shuffle(block(locate(TRANSITIONEDGE,TRANSITIONEDGE,SSmapping.station_start), locate(world.maxx-TRANSITIONEDGE,world.maxy-TRANSITIONEDGE,SSmapping.station_start)))) //Nontrivially expensive but it's roundstart only
|
||||||
|
if(isfloorturf(T) && !isplatingturf(T))
|
||||||
|
new /obj/item/storage/backpack/satchel/flat/secret(T)
|
||||||
|
free_satchels++
|
||||||
|
if((free_satchels + placed_satchel) == 10) //ten tiles, more than enough to kill anything that moves
|
||||||
|
break
|
||||||
|
|
||||||
|
/datum/controller/subsystem/persistence/proc/CollectSecretSatchels()
|
||||||
|
satchel_blacklist = typecacheof(list(/obj/item/stack/tile/plasteel, /obj/item/crowbar))
|
||||||
|
var/list/satchels_to_add = list()
|
||||||
|
for(var/A in new_secret_satchels)
|
||||||
|
var/obj/item/storage/backpack/satchel/flat/F = A
|
||||||
|
if(QDELETED(F) || F.z != SSmapping.station_start || F.invisibility != INVISIBILITY_MAXIMUM)
|
||||||
|
continue
|
||||||
|
var/list/savable_obj = list()
|
||||||
|
for(var/obj/O in F)
|
||||||
|
if(is_type_in_typecache(O, satchel_blacklist) || (O.flags_1 & ADMIN_SPAWNED_1))
|
||||||
|
continue
|
||||||
|
if(O.persistence_replacement)
|
||||||
|
savable_obj += O.persistence_replacement
|
||||||
|
else
|
||||||
|
savable_obj += O.type
|
||||||
|
if(isemptylist(savable_obj))
|
||||||
|
continue
|
||||||
|
var/list/data = list()
|
||||||
|
data["x"] = F.x
|
||||||
|
data["y"] = F.y
|
||||||
|
data["saved_obj"] = pick(savable_obj)
|
||||||
|
satchels_to_add += list(data)
|
||||||
|
|
||||||
|
var/json_file = file("data/npc_saves/SecretSatchels[SSmapping.config.map_name].json")
|
||||||
|
var/list/file_data = list()
|
||||||
|
fdel(json_file)
|
||||||
|
file_data["data"] = old_secret_satchels + satchels_to_add
|
||||||
|
WRITE_FILE(json_file, json_encode(file_data))
|
||||||
84
code/controllers/subsystem/persistence/trophies.dm
Normal file
84
code/controllers/subsystem/persistence/trophies.dm
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
/**
|
||||||
|
* Stores trophies in curator display cases
|
||||||
|
*/
|
||||||
|
/datum/controller/subsystem/persistence
|
||||||
|
var/list/saved_trophies = list()
|
||||||
|
|
||||||
|
/datum/controller/subsystem/persistence/LoadGamePersistence()
|
||||||
|
. = ..()
|
||||||
|
LoadTrophies()
|
||||||
|
|
||||||
|
/datum/controller/subsystem/persistence/SaveGamePersistence()
|
||||||
|
. = ..()
|
||||||
|
CollectTrophies()
|
||||||
|
|
||||||
|
/datum/controller/subsystem/persistence/proc/LoadTrophies()
|
||||||
|
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("data/npc_saves/TrophyItems.sav")
|
||||||
|
else
|
||||||
|
var/json_file = file("data/npc_saves/TrophyItems.json")
|
||||||
|
if(!fexists(json_file))
|
||||||
|
return
|
||||||
|
var/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)
|
||||||
|
for(var/A in GLOB.trophy_cases)
|
||||||
|
var/obj/structure/displaycase/trophy/T = A
|
||||||
|
if (T.showpiece)
|
||||||
|
continue
|
||||||
|
T.added_roundstart = TRUE
|
||||||
|
|
||||||
|
var/trophy_data = pick_n_take(trophy_items)
|
||||||
|
|
||||||
|
if(!islist(trophy_data))
|
||||||
|
continue
|
||||||
|
|
||||||
|
var/list/chosen_trophy = trophy_data
|
||||||
|
|
||||||
|
if(!chosen_trophy || isemptylist(chosen_trophy)) //Malformed
|
||||||
|
continue
|
||||||
|
|
||||||
|
var/path = text2path(chosen_trophy["path"]) //If the item no longer exist, this returns null
|
||||||
|
if(!path)
|
||||||
|
continue
|
||||||
|
|
||||||
|
T.showpiece = new /obj/item/showpiece_dummy(T, path)
|
||||||
|
T.trophy_message = chosen_trophy["message"]
|
||||||
|
T.placer_key = chosen_trophy["placer_key"]
|
||||||
|
T.update_icon()
|
||||||
|
|
||||||
|
/datum/controller/subsystem/persistence/proc/CollectTrophies()
|
||||||
|
var/json_file = file("data/npc_saves/TrophyItems.json")
|
||||||
|
var/list/file_data = list()
|
||||||
|
file_data["data"] = remove_duplicate_trophies(saved_trophies)
|
||||||
|
fdel(json_file)
|
||||||
|
WRITE_FILE(json_file, json_encode(file_data))
|
||||||
|
|
||||||
|
/datum/controller/subsystem/persistence/proc/remove_duplicate_trophies(list/trophies)
|
||||||
|
var/list/ukeys = list()
|
||||||
|
. = list()
|
||||||
|
for(var/trophy in trophies)
|
||||||
|
var/tkey = "[trophy["path"]]-[trophy["message"]]"
|
||||||
|
if(ukeys[tkey])
|
||||||
|
continue
|
||||||
|
else
|
||||||
|
. += list(trophy)
|
||||||
|
ukeys[tkey] = TRUE
|
||||||
|
|
||||||
|
/datum/controller/subsystem/persistence/proc/SaveTrophy(obj/structure/displaycase/trophy/T)
|
||||||
|
if(!T.added_roundstart && T.showpiece)
|
||||||
|
var/list/data = list()
|
||||||
|
data["path"] = T.showpiece.type
|
||||||
|
data["message"] = T.trophy_message
|
||||||
|
data["placer_key"] = T.placer_key
|
||||||
|
saved_trophies += list(data)
|
||||||
@@ -340,7 +340,6 @@
|
|||||||
#include "code\controllers\subsystem\pai.dm"
|
#include "code\controllers\subsystem\pai.dm"
|
||||||
#include "code\controllers\subsystem\parallax.dm"
|
#include "code\controllers\subsystem\parallax.dm"
|
||||||
#include "code\controllers\subsystem\pathfinder.dm"
|
#include "code\controllers\subsystem\pathfinder.dm"
|
||||||
#include "code\controllers\subsystem\persistence.dm"
|
|
||||||
#include "code\controllers\subsystem\profiler.dm"
|
#include "code\controllers\subsystem\profiler.dm"
|
||||||
#include "code\controllers\subsystem\radiation.dm"
|
#include "code\controllers\subsystem\radiation.dm"
|
||||||
#include "code\controllers\subsystem\radio.dm"
|
#include "code\controllers\subsystem\radio.dm"
|
||||||
@@ -363,6 +362,12 @@
|
|||||||
#include "code\controllers\subsystem\vis_overlays.dm"
|
#include "code\controllers\subsystem\vis_overlays.dm"
|
||||||
#include "code\controllers\subsystem\vore.dm"
|
#include "code\controllers\subsystem\vore.dm"
|
||||||
#include "code\controllers\subsystem\vote.dm"
|
#include "code\controllers\subsystem\vote.dm"
|
||||||
|
#include "code\controllers\subsystem\persistence\_persistence.dm"
|
||||||
|
#include "code\controllers\subsystem\persistence\panic_bunker.dm"
|
||||||
|
#include "code\controllers\subsystem\persistence\poly_parrot.dm"
|
||||||
|
#include "code\controllers\subsystem\persistence\recent_votes_etc.dm"
|
||||||
|
#include "code\controllers\subsystem\persistence\secret_satchels.dm"
|
||||||
|
#include "code\controllers\subsystem\persistence\trophies.dm"
|
||||||
#include "code\controllers\subsystem\processing\chemistry.dm"
|
#include "code\controllers\subsystem\processing\chemistry.dm"
|
||||||
#include "code\controllers\subsystem\processing\circuit.dm"
|
#include "code\controllers\subsystem\processing\circuit.dm"
|
||||||
#include "code\controllers\subsystem\processing\fastprocess.dm"
|
#include "code\controllers\subsystem\processing\fastprocess.dm"
|
||||||
|
|||||||
Reference in New Issue
Block a user