mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-07-12 08:27:13 +01:00
9f59d9dec5
# Summary This PR fixes two bugs with persistent items, trash and the persistent charge card. ## Changes - Fixed the prevention of trash in inventories becoming persistent also preventing any items on characters becoming persistent. - Fixed persistent charge card location on init. If the card is not in an command area, it will be moved into the XO office, if it is in a command area, it will stay there.
133 lines
6.3 KiB
Plaintext
133 lines
6.3 KiB
Plaintext
/**
|
|
* Initializes persistent objects.
|
|
* This includes cleaning up expired objects from the database and instanciating all active tracks.
|
|
*/
|
|
/datum/controller/subsystem/persistence/proc/objectsInitialize()
|
|
PRIVATE_PROC(TRUE)
|
|
GLOB.persistence_object_track_register = list()
|
|
|
|
if(SSatlas.current_map.path != "sccv_horizon") // The persistence system only supports objects from the main map levels for multiple reasons, e.g. Z level value, mapping support
|
|
log_subsystem_persistence_info("Persistent objects: Current map did not match SCCV Horizon, skipping persistent object initialization.")
|
|
return
|
|
|
|
// Delete all persistent objects in the database that have expired and have passed the cleanup grace period (PERSISTENT_EXPIRATION_CLEANUP_DELAY_DAYS)
|
|
objectsDatabaseCleanEntries()
|
|
|
|
// Retrieve all persistent data that is not expired
|
|
var/list/persistent_data = objectsDatabaseGetActiveEntries()
|
|
log_subsystem_persistence_info("Persistent objects: Retrieved [length(persistent_data)] entries for instancing this round.")
|
|
|
|
// Instantiate all remaining entries based of their type
|
|
// Assign persistence related vars found in /obj, apply content and add to live tracking list.
|
|
for (var/data in persistent_data)
|
|
CHECK_TICK
|
|
var/typepath = text2path(data["type"])
|
|
if (!ispath(typepath)) // Type checking
|
|
continue
|
|
// Note that the object here is instantiated without init args.
|
|
// Objects that require init args should fall back to INITALIZE_HINT_LATELOAD during Init,
|
|
// as this will give the subsystem the chance to apply the content and
|
|
// the object to continue with init logic after the subsystem is done in LateInitialize.
|
|
var/obj/instance = new typepath()
|
|
instance.persistent_objects_track_id = data["id"]
|
|
objectsApplyTrackContent(instance, data["content"], data["x"], data["y"], data["z"])
|
|
objectsRegisterTrack(instance, data["author_ckey"])
|
|
|
|
/**
|
|
* Finalize persistent object tracking.
|
|
* Adds new persistent objects, removes no longer existing persistent objects and updates changed persistent objects in the database.
|
|
*/
|
|
/datum/controller/subsystem/persistence/proc/objectsFinalize()
|
|
PRIVATE_PROC(TRUE)
|
|
|
|
if(SSatlas.current_map.path != "sccv_horizon") // The persistence system only supports objects from the main map levels for multiple reasons, e.g. Z level value, mapping support
|
|
log_subsystem_persistence_info("Persistent objects: Current map did not match SCCV Horizon, skipping persistent object finalization.")
|
|
if(length(GLOB.persistence_object_track_register) > 0)
|
|
log_subsystem_persistence_warning("Persistent objects: There are [length(GLOB.persistence_object_track_register)] tracked objects at finalization, while the map is not supported! These track will not be saved! Verify that SSatlas.current_map.path has not changed during the round!")
|
|
return
|
|
|
|
// Subsystem shutdown:
|
|
// Create new persistent records for objects that have been created in the round
|
|
// Update tracked objects that have an ID (already existing from previous rounds)
|
|
// Delete persistent records that no longer exist in the registry (removed during the round)
|
|
|
|
// Run checks on each track that might prevent further persistence
|
|
for (var/obj/track as anything in GLOB.persistence_object_track_register)
|
|
CHECK_TICK
|
|
var/turf/T = get_turf(track)
|
|
if(!T || !is_station_level(T.z)) // The persistence system only supports objects from the main map levels for multiple reasons, e.g. Z level value, mapping support
|
|
objectsDeregisterTrack(track)
|
|
|
|
var/created = 0
|
|
var/updated = 0
|
|
var/expired = 0
|
|
|
|
// Get already stored data before saving new tracks so we can compare what has been updated or removed during the round.
|
|
var/list/existing_data = objectsDatabaseGetActiveEntries()
|
|
|
|
for (var/obj/track as anything in GLOB.persistence_object_track_register)
|
|
CHECK_TICK
|
|
if (track.persistent_objects_track_id == 0)
|
|
// Tracked object has no ID meaning it is new, create a new persistent record for it
|
|
objectsDatabaseAddEntry(track)
|
|
created++
|
|
|
|
// Find tracks that have been removed during the round by trying to find the track by database ID
|
|
// If we find the track, we need to check if it requires an update instead
|
|
for (var/record in existing_data)
|
|
var/found = FALSE
|
|
for (var/obj/track as anything in GLOB.persistence_object_track_register)
|
|
CHECK_TICK
|
|
if (record["id"] == track.persistent_objects_track_id)
|
|
// A track with the same ID has been found in the register, it still exists, check if we need to update it instead
|
|
found = TRUE // Prevent expiration of track
|
|
var/changed = FALSE
|
|
var/turf/T = get_turf(track)
|
|
if (T && T.x != record["x"])
|
|
changed = TRUE
|
|
else if (T && T.y != record["y"])
|
|
changed = TRUE
|
|
else if (T && T.z != record["z"])
|
|
changed = TRUE
|
|
else if (objectsGetTrackContent(track) != record["content"])
|
|
changed = TRUE
|
|
if (changed)
|
|
objectsDatabaseUpdateEntry(track)
|
|
updated++
|
|
break // Track found (and perhaps updated), break off loop search as it won't need to be deleted anyways
|
|
if (!found)
|
|
// No track with the same ID has been found in the register, remove it from the database (expire)
|
|
objectsDatabaseExpireEntry(record["id"])
|
|
expired++
|
|
|
|
log_subsystem_persistence_info("Persistent objects: Created [created], updated [updated] and expired [expired] tracks.")
|
|
|
|
/**
|
|
* Safely get JSON persistent content of track.
|
|
* RETURN: JSON formatted content of track or null if an exception occured.
|
|
*/
|
|
/datum/controller/subsystem/persistence/proc/objectsGetTrackContent(obj/track)
|
|
PRIVATE_PROC(TRUE)
|
|
var/result = json_encode(list())
|
|
try
|
|
var/list/content = track.persistent_objects_get_content()
|
|
if(length(content))
|
|
result = json_encode(content)
|
|
catch(var/exception/e)
|
|
log_subsystem_persistence_error("Error during json serialization for persistent object. Failed to get/encode track content: [e]")
|
|
return result
|
|
|
|
/**
|
|
* Safely apply persistent content to track.
|
|
* PARAMS:
|
|
* track = Object to apply content to.
|
|
* json = Custom persistent content JSON to be applied.
|
|
* x,y,z = x-y-z coordinates of object, can be null.
|
|
*/
|
|
/datum/controller/subsystem/persistence/proc/objectsApplyTrackContent(obj/track, json, x, y, z)
|
|
PRIVATE_PROC(TRUE)
|
|
try
|
|
track.persistent_objects_apply_content(json_decode(json), x, y, z)
|
|
catch(var/exception/e)
|
|
log_subsystem_persistence_error("Error during json deserialization for persistent object. Failed to apply/decode track content: [e]")
|