mirror of
https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13.git
synced 2025-12-25 01:03:05 +00:00
178 lines
5.7 KiB
Plaintext
178 lines
5.7 KiB
Plaintext
/**
|
|
* Persistence for cleanable debris.
|
|
*/
|
|
/datum/controller/subsystem/persistence
|
|
/// tracks if we already loaded debris. Unlike everything else, this can actually be a major problem if some badmin procs it twice.
|
|
var/loaded_debris = FALSE
|
|
|
|
/datum/controller/subsystem/persistence/LoadMapPersistence()
|
|
. = ..()
|
|
if(CONFIG_GET(flag/persistent_debris))
|
|
LoadMapDebris()
|
|
|
|
/datum/controller/subsystem/persistence/SaveMapPersistence()
|
|
. = ..()
|
|
if(CONFIG_GET(flag/persistent_debris))
|
|
SaveMapDebris()
|
|
|
|
/datum/controller/subsystem/persistence/proc/LoadMapDebris()
|
|
if(CONFIG_GET(flag/persistent_debris_only))
|
|
wipe_existing_debris()
|
|
if(!fexists("[get_map_persistence_path()]/debris.json"))
|
|
return
|
|
if(loaded_debris)
|
|
return
|
|
loaded_debris = TRUE
|
|
var/list/allowed_turf_typecache = typecacheof(/turf/open) - typecacheof(/turf/open/space)
|
|
var/list/allowed_z_cache = list()
|
|
for(var/z in SSmapping.levels_by_trait(ZTRAIT_STATION))
|
|
allowed_z_cache[num2text(z)] = TRUE
|
|
var/list/data = json_decode(file2text("[get_map_persistence_path()]/debris.json"))
|
|
var/list/z_lookup = list()
|
|
var/loaded = 0
|
|
var/list/loaded_by_type = list()
|
|
var/nopath = 0
|
|
var/badloc = 0
|
|
var/noturf = 0
|
|
/// reverse it
|
|
for(var/z in SSmapping.z_to_station_z_index)
|
|
var/sz = SSmapping.z_to_station_z_index[z]
|
|
z_lookup[num2text(sz)] = text2num(z)
|
|
for(var/z in data)
|
|
var/actual_z = z_lookup[z]
|
|
var/list/L1 = data[z]
|
|
for(var/x in L1)
|
|
var/list/L2 = data[z][x]
|
|
for(var/y in L2)
|
|
var/turf/tile = locate(text2num(x), text2num(y), actual_z)
|
|
if(!tile)
|
|
noturf++
|
|
continue
|
|
var/list/objects = data[z][x][y]
|
|
for(var/_L in objects)
|
|
var/list/objdata
|
|
var/path
|
|
if(islist(_L))
|
|
objdata = _L
|
|
path = text2path(objdata["__PATH__"])
|
|
else
|
|
path = text2path(_L)
|
|
objdata = objects[_L]
|
|
if(!path)
|
|
nopath++
|
|
continue
|
|
if(!IsValidDebrisLocation(tile, allowed_turf_typecache, allowed_z_cache, path, TRUE))
|
|
badloc++
|
|
continue
|
|
var/obj/effect/decal/cleanable/instantiated = new path(tile)
|
|
loaded_by_type[path] += 1
|
|
loaded++
|
|
if(objdata)
|
|
instantiated.PersistenceLoad(objdata)
|
|
var/list/bytype = list()
|
|
for(var/path in loaded_by_type)
|
|
bytype += "[path] - [loaded_by_type[path]]"
|
|
subsystem_log(
|
|
{"Debris loading completed:
|
|
Errors:
|
|
No path: [nopath]
|
|
Invalid location: [badloc]
|
|
No turf on map: [noturf]
|
|
Total loaded: [loaded]
|
|
By type:
|
|
[bytype.Join("\n")]"}
|
|
)
|
|
|
|
/datum/controller/subsystem/persistence/proc/SaveMapDebris()
|
|
if(fexists("[get_map_persistence_path()]/debris.json"))
|
|
fdel("[get_map_persistence_path()]/debris.json")
|
|
if(CONFIG_GET(flag/persistent_debris_wipe_on_nuke) && station_was_destroyed)
|
|
return // local janitor cheers on nukeop team to save some work
|
|
var/list/data = list()
|
|
var/list/z_lookup = SSmapping.z_to_station_z_index
|
|
var/list/debris = RelevantPersistentDebris()
|
|
var/obj/effect/decal/cleanable/saving
|
|
var/global_max = CONFIG_GET(number/persistent_debris_global_max)
|
|
var/type_max = CONFIG_GET(number/persistent_debris_type_max)
|
|
var/stored = 0
|
|
var/list/stored_by_type = list()
|
|
for(var/i in debris)
|
|
saving = i
|
|
var/list/serializing = list()
|
|
var/path = saving.PersistenceSave(serializing)
|
|
if(!path)
|
|
continue
|
|
if(stored_by_type[path] > type_max)
|
|
continue
|
|
var/text_z = num2text(z_lookup[num2text(saving.z)])
|
|
var/text_y = num2text(saving.y)
|
|
var/text_x = num2text(saving.x)
|
|
LAZYINITLIST(data[text_z])
|
|
LAZYINITLIST(data[text_z][text_x])
|
|
LAZYINITLIST(data[text_z][text_x][text_y])
|
|
if(saving.persistence_allow_stacking)
|
|
serializing["__PATH__"] = path
|
|
data[text_z][text_x][text_y] += list(serializing)
|
|
else
|
|
data[text_z][text_x][text_y][path] = serializing
|
|
stored++
|
|
if(stored > global_max)
|
|
var/w = "Persistent debris saving globally aborted due to global max >= [global_max]. Either janitors never do their jobs or something is wrong."
|
|
message_admins(w)
|
|
subsystem_log(w)
|
|
return
|
|
stored_by_type[path] = stored_by_type[path]? stored_by_type[path] + 1 : 1
|
|
if(stored_by_type[path] > type_max)
|
|
var/w = "Persistent debris saving aborted for type [path] due to type max >= [global_max]. Either janitors never do their jobs or something is wrong."
|
|
message_admins(w)
|
|
subsystem_log(w)
|
|
|
|
var/list/bytype = list()
|
|
for(var/path in stored_by_type)
|
|
bytype += "[path] - [stored_by_type[path]]"
|
|
subsystem_log(
|
|
{"Debris saving completed:
|
|
Total: [stored]
|
|
By type:
|
|
[bytype.Join("\n")]"}
|
|
)
|
|
WRITE_FILE(file("[get_map_persistence_path()]/debris.json"), json_encode(data))
|
|
|
|
/datum/controller/subsystem/persistence/proc/IsValidDebrisLocation(turf/tile, list/allowed_typecache, list/allowed_zcache, obj/effect/decal/cleanable/type, loading = FALSE)
|
|
if(!allowed_typecache[tile.type])
|
|
return FALSE
|
|
var/area/A = tile.loc
|
|
if(!A.persistent_debris_allowed)
|
|
return FALSE
|
|
if(!allowed_zcache[num2text(tile.z)])
|
|
return FALSE
|
|
if(loading)
|
|
if(!initial(type.persistence_allow_stacking))
|
|
var/obj/effect/decal/cleanable/C = locate(type) in tile
|
|
if(!QDELETED(C))
|
|
return FALSE
|
|
// Saving verifies allow stacking in the save proc.
|
|
for(var/obj/structure/window/W in tile)
|
|
if(W.fulltile)
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/datum/controller/subsystem/persistence/proc/wipe_existing_debris()
|
|
var/list/existing = RelevantPersistentDebris()
|
|
QDEL_LIST(existing)
|
|
|
|
/datum/controller/subsystem/persistence/proc/RelevantPersistentDebris()
|
|
var/list/allowed_turf_typecache = typecacheof(/turf/open) - typecacheof(/turf/open/space)
|
|
var/list/allowed_z_cache = list()
|
|
for(var/z in SSmapping.levels_by_trait(ZTRAIT_STATION))
|
|
allowed_z_cache[num2text(z)] = TRUE
|
|
. = list()
|
|
for(var/obj/effect/decal/cleanable/C in world)
|
|
if(!C.loc || QDELETED(C))
|
|
continue
|
|
if(!C.persistent)
|
|
continue
|
|
if(!IsValidDebrisLocation(C.loc, allowed_turf_typecache, allowed_z_cache, C.type, FALSE))
|
|
continue
|
|
. += C
|