diff --git a/code/controllers/subsystems/ticker.dm b/code/controllers/subsystems/ticker.dm
index 29ea4aa9a8f..670d6c73e45 100644
--- a/code/controllers/subsystems/ticker.dm
+++ b/code/controllers/subsystems/ticker.dm
@@ -420,7 +420,7 @@ Helpers
if(dronecount)
to_world("There [dronecount>1 ? "were" : "was"] [dronecount] industrious maintenance drone\s at the end of this round.")
- if(SSmoney_accounts.all_glob_accounts.len)
+ if(length(SSmoney_accounts.all_glob_accounts))
var/datum/money_account/max_profit = SSmoney_accounts.all_glob_accounts[1]
var/datum/money_account/max_loss = SSmoney_accounts.all_glob_accounts[1]
for(var/datum/money_account/D in SSmoney_accounts.all_glob_accounts)
diff --git a/code/modules/economy/cael/related_accounts.dm b/code/modules/economy/cael/related_accounts.dm
index 88e5de2f3ad..16b876077bf 100644
--- a/code/modules/economy/cael/related_accounts.dm
+++ b/code/modules/economy/cael/related_accounts.dm
@@ -10,7 +10,7 @@
var/list/datum/money_account/child/children = list()
/datum/money_account/parent/Destroy(force)
- QDEL_NULL(children)
+ QDEL_NULL_LIST(children)
. = ..()
/datum/money_account/parent/can_afford(amount, datum/money_account/receiver)
@@ -55,9 +55,10 @@
var/datum/money_account/parent/parent_account
-/datum/money_account/child/New(account_type, p_account, n_interest, n_withdrawal_limit, n_transaction_fee)
- parent_account = p_account
- parent_account.children |= src
+/datum/money_account/child/New(account_type, datum/money_account/parent/p_account, n_interest, n_withdrawal_limit, n_transaction_fee)
+ if(istype(p_account))
+ parent_account = p_account
+ parent_account.children |= src
interest_rate = n_interest
withdrawal_limit = n_withdrawal_limit
transaction_fee = n_transaction_fee
@@ -150,7 +151,7 @@
if(!parent_account || !money) // Nothing to escrow!
return
- var/solvency = max(1, parent_account.money / parent_account.child_totals)
+ var/solvency = min(1, parent_account.money / parent_account.child_totals)
var/escrowed_money = FLOOR(min(solvency*money, parent_account.money))
var/datum/money_account/escrow/child_escrow = SSmoney_accounts.get_or_add_escrow(account_id, remote_access_pin, parent_account.owner_name)
diff --git a/code/modules/events/money_lotto.dm b/code/modules/events/money_lotto.dm
index 8e433309571..5eae9035967 100644
--- a/code/modules/events/money_lotto.dm
+++ b/code/modules/events/money_lotto.dm
@@ -7,7 +7,7 @@
/datum/event/money_lotto/start()
winner_sum = pick(5000, 10000, 50000, 100000, 500000, 1000000, 1500000)
if(prob(50))
- if(SSmoney_accounts.all_glob_accounts.len)
+ if(length(SSmoney_accounts.all_glob_accounts))
winner_account = pick(SSmoney_accounts.all_glob_accounts)
winner_name = winner_account.owner_name
deposit_success = winner_account.deposit(winner_sum, "Nyx Daily Loan Lottery winner!", "Biesel TCD Terminal #[rand(111,333)]")
diff --git a/code/modules/modular_computers/computers/subtypes/preset_console.dm b/code/modules/modular_computers/computers/subtypes/preset_console.dm
index 5f891efbde6..25c794d75f9 100644
--- a/code/modules/modular_computers/computers/subtypes/preset_console.dm
+++ b/code/modules/modular_computers/computers/subtypes/preset_console.dm
@@ -115,6 +115,18 @@
/datum/computer_file/program/docking
)
+/obj/machinery/computer/modular/preset/finance
+ default_software = list(
+ /datum/computer_file/program/finances,
+ /datum/computer_file/program/atm,
+ /datum/computer_file/program/accounts
+ )
+ uncreated_component_parts = list(
+ /obj/item/stock_parts/power/apc,
+ /obj/item/stock_parts/computer/card_slot,
+ /obj/item/stock_parts/computer/money_printer
+ )
+
/obj/machinery/computer/modular/preset/supply_public
default_software = list(
/datum/computer_file/program/supply
diff --git a/code/modules/modular_computers/networking/_network.dm b/code/modules/modular_computers/networking/_network.dm
index bc56b357eb2..ec7eb0b4723 100644
--- a/code/modules/modular_computers/networking/_network.dm
+++ b/code/modules/modular_computers/networking/_network.dm
@@ -255,6 +255,10 @@
SSnetworking.networks -= network_id
add_log("Network ID was changed from '[network_id]' to '[new_id]'")
network_id = new_id
+
+ if(parent_account)
+ parent_account.owner_name = network_id
+
SSnetworking.networks[network_id] = src
/datum/computer_network/proc/enable_network_feature(feature)
diff --git a/code/modules/modular_computers/networking/finance/money_accounts.dm b/code/modules/modular_computers/networking/finance/money_accounts.dm
index d58d2aec9ae..cbeeae1c17f 100644
--- a/code/modules/modular_computers/networking/finance/money_accounts.dm
+++ b/code/modules/modular_computers/networking/finance/money_accounts.dm
@@ -3,8 +3,6 @@
var/datum/computer_file/data/email_message/bankrupt_email
var/datum/computer_file/data/email_message/escrow_email
- var/get_network_error = FALSE // Network accounts need at least one money storage device and a banking mainframe to function.
-
/datum/money_account/parent/network/New(account_type, network_id)
owner_name = network_id
if(owner_name)
@@ -29,6 +27,7 @@
return err
. = ..()
+ // Network accounts need at least one money storage device and a banking mainframe to function.
/datum/money_account/parent/network/proc/get_network_error()
var/datum/computer_network/net = SSnetworking.networks[owner_name]
if(!net || !net.banking_mainframe)
@@ -51,10 +50,11 @@
An escrow account has been opened for you containing some or all of your outstanding balance of your account. \
Escrow accounts are accessible from any financial terminal using your prior account information, \
and the financial provider ID '[owner_name]'. Please contact your financial provider for further information."
+
/datum/money_account/child/network
var/weakref/network_account
-/datum/money_account/child/network/New(account_type, p_account, n_interest, n_withdrawal_limit, n_transaction_fee, datum/computer_file/data/account/attached_account)
+/datum/money_account/child/network/New(account_type, datum/money_account/parent/p_account, n_interest, n_withdrawal_limit, n_transaction_fee, datum/computer_file/data/account/attached_account)
if(attached_account)
account_name = "[attached_account.fullname]'s account"
account_id = attached_account.login
diff --git a/code/modules/modular_computers/networking/finance/money_cube.dm b/code/modules/modular_computers/networking/finance/money_cube.dm
index 019fb4ae444..0465be71566 100644
--- a/code/modules/modular_computers/networking/finance/money_cube.dm
+++ b/code/modules/modular_computers/networking/finance/money_cube.dm
@@ -126,6 +126,12 @@
var/stored_money // Money temporarily stored in the case that the parent account on the network vanishes.
internet_allowed = TRUE
+/datum/extension/network_device/money_cube/connect()
+ . = ..()
+ if(.)
+ var/obj/H = holder
+ H.queue_icon_update()
+
/datum/extension/network_device/money_cube/disconnect(net_down)
var/obj/H = holder
H.queue_icon_update()
diff --git a/mods/persistence/_persistence.dme b/mods/persistence/_persistence.dme
index 4dc7e7d8612..063093a7ba0 100644
--- a/mods/persistence/_persistence.dme
+++ b/mods/persistence/_persistence.dme
@@ -39,14 +39,14 @@
#include "datums\mind\mind.dm"
#include "datums\music_tracks\blood_loss.dm"
#include "datums\music_tracks\juno.dm"
-#include "datums\music_tracks\neon_koto.dm"
#include "datums\music_tracks\neogrotesque.dm"
+#include "datums\music_tracks\neon_koto.dm"
#include "datums\observation\saving.dm"
#include "datums\vending\stored_item.dm"
#include "datums\wires\wires.dm"
#include "game\antagonist\antagonist_helpers.dm"
-#include "game\area\areas.dm"
#include "game\area\area_space.dm"
+#include "game\area\areas.dm"
#include "game\gamemodes\persistence.dm"
#include "game\machinery\cryopod.dm"
#include "game\machinery\machinery.dm"
@@ -124,6 +124,7 @@
#include "modules\detectivework\evidence\_evidence_holder.dm"
#include "modules\detectivework\evidence\_evidence_type.dm"
#include "modules\detectivework\microscope\_forensic_machine.dm"
+#include "modules\economy\account.dm"
#include "modules\economy\economy.dm"
#include "modules\emotes\audible.dm"
#include "modules\emotes\human.dm"
@@ -140,10 +141,10 @@
#include "modules\hydroponics\spreading\spreading.dm"
#include "modules\integrated_electronics\printer.dm"
#include "modules\lighting\lighting_overlay.dm"
+#include "modules\materials\recipes_persistence.dm"
#include "modules\materials\definitions\materials_solid_metal.dm"
#include "modules\materials\definitions\materials_stone.dm"
#include "modules\materials\geology\_strata.dm"
-#include "modules\materials\recipes_persistence.dm"
#include "modules\mining\machinery\_material_processing.dm"
#include "modules\mining\machinery\material_compressor.dm"
#include "modules\mining\machinery\material_smelter.dm"
@@ -175,12 +176,15 @@
#include "modules\modular_computers\file_system\reports\crew_record.dm"
#include "modules\modular_computers\file_system\reports\report.dm"
#include "modules\modular_computers\hardware\battery_module.dm"
+#include "modules\modular_computers\networking\_network.dm"
#include "modules\modular_computers\networking\network_cable.dm"
#include "modules\modular_computers\networking\accounts\account.dm"
#include "modules\modular_computers\networking\accounts\email_message.dm"
#include "modules\modular_computers\networking\device_types\_network_device.dm"
#include "modules\modular_computers\networking\device_types\acl.dm"
#include "modules\modular_computers\networking\device_types\mainframe.dm"
+#include "modules\modular_computers\networking\finance\bank.dm"
+#include "modules\modular_computers\networking\finance\money_cube.dm"
#include "modules\modular_computers\networking\machines\_network_machine.dm"
#include "modules\modular_computers\networking\machines\area_controller.dm"
#include "modules\modular_computers\networking\machines\router.dm"
@@ -232,8 +236,8 @@
#include "modules\reagents\chems\chems.dm"
#include "modules\reagents\chems\recipes.dm"
#include "modules\reagents\heat_sources\heat_source.dm"
-#include "modules\reagents\reagent_containers\glass\bottle.dm"
#include "modules\reagents\reagent_containers\food\food.dm"
+#include "modules\reagents\reagent_containers\glass\bottle.dm"
#include "modules\science\_defines.dm"
#include "modules\science\recipe.dm"
#include "modules\science\research_overrides.dm"
@@ -269,6 +273,7 @@
#include "modules\world_save\wrappers\_wrapper_holder.dm"
#include "modules\world_save\wrappers\area_wrapper.dm"
#include "modules\world_save\wrappers\decl_wrapper.dm"
+#include "modules\world_save\wrappers\escrow_holder.dm"
#include "modules\world_save\wrappers\image_wrapper.dm"
#include "modules\world_save\wrappers\map_data_wrapper.dm"
#include "modules\world_save\wrappers\weakref_wrapper.dm"
diff --git a/mods/persistence/controllers/subsystems/persistence.dm b/mods/persistence/controllers/subsystems/persistence.dm
index 8657c6cd102..5be6bf12a19 100644
--- a/mods/persistence/controllers/subsystems/persistence.dm
+++ b/mods/persistence/controllers/subsystems/persistence.dm
@@ -108,10 +108,8 @@
if(QDELETED(current_mob))
continue
// Check to see if the mobs are already being saved.
- var/area/MA = get_area(current_mob)
- if(istype(MA) && !(MA.area_flags & AREA_FLAG_IS_NOT_PERSISTENT))
- if(((MA in SSpersistence.saved_areas) || (current_mob.z in SSpersistence.saved_levels)))
- continue
+ if(current_mob.in_saved_location())
+ continue
one_off.AddToLimbo(list(current_mob, char_mind), char_mind.unique_id, LIMBO_MIND, char_mind.key, current_mob.real_name, TRUE)
report_progress_serializer("Done adding player minds to limbo in [(REALTIMEOFDAY - time_start_limbo_minds) / (1 SECOND)]s.")
sleep(5)
@@ -318,6 +316,17 @@
report_progress_serializer("Extensions saved in [(REALTIMEOFDAY - time_start_extensions) / (1 SECOND)]s.")
sleep(5)
+ // Save escrow accounts which are normally held on the SSmoney_accounts subsystem
+ if(length(SSmoney_accounts.all_escrow_accounts))
+ report_progress_serializer("Saving escrow accounts...")
+ var/datum/wrapper_holder/escrow_holder/e_holder = new(SSmoney_accounts.all_escrow_accounts.Copy())
+ var/time_start_escrow = REALTIMEOFDAY
+
+ serializer.Serialize(e_holder)
+ serializer.Commit()
+
+ report_progress_serializer("Escrow accounts saved in [(REALTIMEOFDAY - time_start_escrow) / (1 SECOND)]s.")
+
//
// CLEANUP SECTION
//
diff --git a/mods/persistence/datums/extensions/extensions.dm b/mods/persistence/datums/extensions/extensions.dm
index 35a5e13e3b4..4a2ab0f371e 100644
--- a/mods/persistence/datums/extensions/extensions.dm
+++ b/mods/persistence/datums/extensions/extensions.dm
@@ -14,7 +14,14 @@
/datum/extension/proc/on_save()
SSpersistence.saved_extensions += src
-/datum/extension/should_save(object_parent)
+/datum/extension/should_save(object_parent, one_off = FALSE)
if(object_parent) // Extensions are saved manually, either by self-reporting or by the one off serializer checking. Don't permit saving from object vars.
return FALSE
- return should_save
\ No newline at end of file
+
+ // If the holder is a movable and wouldn't be saved, don't save this either.
+ if(!one_off && istype(holder, /atom/movable))
+ var/atom/movable/H = holder
+ if(!H.in_saved_location())
+ return FALSE
+
+ return ..()
\ No newline at end of file
diff --git a/mods/persistence/modules/detectivework/evidence/_evidence_holder.dm b/mods/persistence/modules/detectivework/evidence/_evidence_holder.dm
index 6d5b7b2b341..86ad8fda966 100644
--- a/mods/persistence/modules/detectivework/evidence/_evidence_holder.dm
+++ b/mods/persistence/modules/detectivework/evidence/_evidence_holder.dm
@@ -3,7 +3,7 @@
/datum/extension/forensic_evidence
should_save = TRUE
- var/last_updated
+ var/last_updated
/datum/extension/forensic_evidence/add_data(evidence_type, data)
. = ..()
@@ -13,7 +13,7 @@
. = ..()
last_updated = world.realtime
-/datum/extension/forensic_evidence/should_save(object_parent)
+/datum/extension/forensic_evidence/should_save(object_parent, one_off = FALSE)
if(world.realtime > (last_updated + EVIDENCE_SPOIL_TIME))
return FALSE
. = ..()
diff --git a/mods/persistence/modules/economy/account.dm b/mods/persistence/modules/economy/account.dm
new file mode 100644
index 00000000000..83d5155e38b
--- /dev/null
+++ b/mods/persistence/modules/economy/account.dm
@@ -0,0 +1,63 @@
+// Money accounts should not be flattened. Child accounts do some work with references post save,
+// and because both network accounts and transactions are flattened, could lead to absurdly large rows in the database.
+SAVED_VAR(/datum/money_account, account_name)
+SAVED_VAR(/datum/money_account, owner_name)
+SAVED_VAR(/datum/money_account, account_id)
+SAVED_VAR(/datum/money_account, remote_access_pin)
+SAVED_VAR(/datum/money_account, money)
+SAVED_VAR(/datum/money_account, transaction_log)
+SAVED_VAR(/datum/money_account, suspended)
+SAVED_VAR(/datum/money_account, security_level)
+SAVED_VAR(/datum/money_account, account_type)
+SAVED_VAR(/datum/money_account, currency)
+
+// Related accounts
+SAVED_VAR(/datum/money_account/parent, fractional_reserve)
+SAVED_VAR(/datum/money_account/parent, open_escrow_on_destroy)
+SAVED_VAR(/datum/money_account/parent, children)
+
+SAVED_VAR(/datum/money_account/child, withdrawal_limit)
+SAVED_VAR(/datum/money_account/child, current_withdrawal)
+SAVED_VAR(/datum/money_account/child, last_withdraw_period)
+SAVED_VAR(/datum/money_account/child, transaction_fee)
+SAVED_VAR(/datum/money_account/child, interest_rate)
+SAVED_VAR(/datum/money_account/child, last_interest_period)
+SAVED_VAR(/datum/money_account/child, parent_account)
+
+// Account modifications
+SAVED_FLATTEN(/datum/account_modification)
+SAVED_VAR(/datum/account_modification, name)
+SAVED_VAR(/datum/account_modification, start_time)
+SAVED_VAR(/datum/account_modification, mod_delay)
+SAVED_VAR(/datum/account_modification, affecting)
+SAVED_VAR(/datum/account_modification, suspends_withdrawal_limit)
+SAVED_VAR(/datum/account_modification, allow_early)
+SAVED_VAR(/datum/account_modification, allow_cancel)
+
+// Network accounts
+/datum/money_account/parent/network/after_deserialize()
+ . = ..()
+ // Don't bother saving these since we can easily regenerate them.
+ if(owner_name)
+ generate_emails()
+
+ for(var/datum/money_account/child/network/net_child in children)
+ var/datum/computer_file/data/account/attached_account = net_child.network_account?.resolve()
+
+ // The network account has gone missing - escrow the account and destroy it.
+ if(!istype(attached_account))
+ net_child.on_escrow(ignore_email = TRUE)
+ qdel(net_child)
+
+SAVED_VAR(/datum/money_account/child/network, network_account)
+// Transactions
+// TODO: These should disappear after some time to save space, even if they're flattened.
+SAVED_FLATTEN(/datum/transaction)
+SAVED_VAR(/datum/transaction, purpose)
+SAVED_VAR(/datum/transaction, amount)
+SAVED_VAR(/datum/transaction, date)
+SAVED_VAR(/datum/transaction, time)
+SAVED_VAR(/datum/transaction, target)
+SAVED_VAR(/datum/transaction, source)
+SAVED_VAR(/datum/transaction, target_name)
+SAVED_VAR(/datum/transaction, source_name)
\ No newline at end of file
diff --git a/mods/persistence/modules/economy/economy.dm b/mods/persistence/modules/economy/economy.dm
index 17702d70b38..77f7cb46f1b 100644
--- a/mods/persistence/modules/economy/economy.dm
+++ b/mods/persistence/modules/economy/economy.dm
@@ -1,6 +1,5 @@
-//EFPOS
-//#TODO: will need additional handling once we can rewrite how this thing inits
+//EFTPOS
SAVED_VAR(/obj/item/eftpos, machine_id)
SAVED_VAR(/obj/item/eftpos, eftpos_name)
SAVED_VAR(/obj/item/eftpos, transaction_locked)
@@ -11,12 +10,29 @@ SAVED_VAR(/obj/item/eftpos, access_code)
SAVED_VAR(/obj/item/eftpos, currency)
SAVED_VAR(/obj/item/eftpos, linked_account) //Can probably just save the account id
+// Network EFTPOS. For Persistence purposes, these deprecate the normal EFTPOS devices.
+SAVED_VAR(/obj/item/network_pos, account_id)
+SAVED_VAR(/obj/item/network_pos, account_provider)
+
//ATM
SAVED_VAR(/obj/machinery/atm, held_card)
SAVED_VAR(/obj/machinery/atm, machine_id)
SAVED_VAR(/obj/machinery/atm, view_screen)
SAVED_VAR(/obj/machinery/atm, authenticated_account) //Can probably just save the account id
+// These don't currently serve a purpose for us, so remove them from availability.
+/datum/fabricator_recipe/engineering/atm_board
+ fabricator_types = list()
+ path = /obj/item/stock_parts/circuitboard/requests_console/atm
+
+/datum/fabricator_recipe/engineering/atm_frame
+ fabricator_types = list()
+ path = /obj/item/frame/stock_offset/atm
+
+/datum/fabricator_recipe/engineering/atm_kit
+ fabricator_types = list()
+ path = /obj/item/frame/stock_offset/atm/kit
+
//Cash
SAVED_VAR(/obj/item/cash, absolute_worth)
SAVED_VAR(/obj/item/cash, currency)
@@ -27,3 +43,6 @@ SAVED_VAR(/obj/item/charge_stick, creator)
SAVED_VAR(/obj/item/charge_stick, id)
SAVED_VAR(/obj/item/charge_stick, currency)
SAVED_VAR(/obj/item/charge_stick, grade)
+
+// Money printer
+SAVED_VAR(/obj/item/stock_parts/computer/money_printer, stored_plastic)
\ No newline at end of file
diff --git a/mods/persistence/modules/modular_computers/networking/_network.dm b/mods/persistence/modules/modular_computers/networking/_network.dm
new file mode 100644
index 00000000000..c9a453bdacc
--- /dev/null
+++ b/mods/persistence/modules/modular_computers/networking/_network.dm
@@ -0,0 +1,18 @@
+// Some additional safety for parent accounts, recover the parent account if the banking mainframe wasn't saved
+// as long as a reference to the account was held elsewhere (normally, on a child account).
+/datum/computer_network/New(new_id)
+ . = ..()
+ recover_parent_account()
+
+/datum/computer_network/change_id(new_id)
+ . = ..()
+ recover_parent_account()
+
+/datum/computer_network/proc/recover_parent_account()
+ if(parent_account)
+ return
+
+ for(var/datum/money_account/parent/network/net_account in SSmoney_accounts.all_accounts)
+ if(net_account.owner_name == network_id)
+ parent_account = net_account
+ return
diff --git a/mods/persistence/modules/modular_computers/networking/accounts/account.dm b/mods/persistence/modules/modular_computers/networking/accounts/account.dm
index 4b02289ddc6..457c3468184 100644
--- a/mods/persistence/modules/modular_computers/networking/accounts/account.dm
+++ b/mods/persistence/modules/modular_computers/networking/accounts/account.dm
@@ -9,4 +9,5 @@ SAVED_VAR(/datum/computer_file/data/account, inbox)
SAVED_VAR(/datum/computer_file/data/account, outbox)
SAVED_VAR(/datum/computer_file/data/account, spam)
SAVED_VAR(/datum/computer_file/data/account, deleted)
-SAVED_VAR(/datum/computer_file/data/account, backup)
\ No newline at end of file
+SAVED_VAR(/datum/computer_file/data/account, backup)
+SAVED_VAR(/datum/computer_file/data/account, money_account)
\ No newline at end of file
diff --git a/mods/persistence/modules/modular_computers/networking/finance/bank.dm b/mods/persistence/modules/modular_computers/networking/finance/bank.dm
new file mode 100644
index 00000000000..44b200e2129
--- /dev/null
+++ b/mods/persistence/modules/modular_computers/networking/finance/bank.dm
@@ -0,0 +1,24 @@
+/datum/extension/network_device/bank
+ var/datum/money_account/parent/saved_backup
+
+/datum/extension/network_device/bank/before_save()
+ if(!backup)
+ // TODO: Unsure on using get_network() for this, it may be safer to access the network directly.
+ var/datum/computer_network/network = get_network()
+ if(network)
+ saved_backup = network.parent_account
+ . = ..()
+
+/datum/extension/network_device/bank/after_deserialize()
+ . = ..()
+ if(!backup)
+ backup = saved_backup
+ saved_backup = null
+
+SAVED_VAR(/datum/extension/network_device/bank, backup)
+SAVED_VAR(/datum/extension/network_device/bank, saved_backup)
+SAVED_VAR(/datum/extension/network_device/bank, admin_accounts)
+SAVED_VAR(/datum/extension/network_device/bank, auto_money_accounts)
+SAVED_VAR(/datum/extension/network_device/bank, auto_interest_rate)
+SAVED_VAR(/datum/extension/network_device/bank, auto_withdrawal_limit)
+SAVED_VAR(/datum/extension/network_device/bank, auto_transaction_fee)
\ No newline at end of file
diff --git a/mods/persistence/modules/modular_computers/networking/finance/money_cube.dm b/mods/persistence/modules/modular_computers/networking/finance/money_cube.dm
new file mode 100644
index 00000000000..5533f4e2cc2
--- /dev/null
+++ b/mods/persistence/modules/modular_computers/networking/finance/money_cube.dm
@@ -0,0 +1 @@
+SAVED_VAR(/datum/extension/network_device/money_cube, stored_money)
\ No newline at end of file
diff --git a/mods/persistence/modules/world_save/_persistence.dm b/mods/persistence/modules/world_save/_persistence.dm
index b475f8c8138..0cbc99d269f 100644
--- a/mods/persistence/modules/world_save/_persistence.dm
+++ b/mods/persistence/modules/world_save/_persistence.dm
@@ -27,13 +27,23 @@ SAVED_VAR(/datum, custom_saved)
custom_saved = null //Clear it since its no longer needed
#endif
-/**
+/**
* Called immediately after the datum has been loaded from save during SSMapping's init, and before Initialize().
* DO NOT call anything relying on subsystems being initialized in this!!
-*/
+*/
/datum/proc/after_deserialize()
return
/**Used to check and override whether an entity should be saved. */
/datum/proc/should_save()
return should_save
+
+//**Used to check if a movable will be saved by world save. */
+/atom/movable/proc/in_saved_location()
+ if(!should_save())
+ return FALSE
+
+ var/area/MA = get_area(src)
+ if(istype(MA) && !(MA.area_flags & AREA_FLAG_IS_NOT_PERSISTENT))
+ if(((MA in SSpersistence.saved_areas) || (z in SSpersistence.saved_levels)))
+ return TRUE
\ No newline at end of file
diff --git a/mods/persistence/modules/world_save/saved_vars/saved_misc.dm b/mods/persistence/modules/world_save/saved_vars/saved_misc.dm
index 19c67c3abb6..f4e32b8d838 100644
--- a/mods/persistence/modules/world_save/saved_vars/saved_misc.dm
+++ b/mods/persistence/modules/world_save/saved_vars/saved_misc.dm
@@ -148,17 +148,6 @@ SAVED_VAR(/datum/memory, owner)
SAVED_VAR(/datum/memory, _owner_name)
SAVED_VAR(/datum/memory, _owner_ckey)
-SAVED_VAR(/datum/money_account, account_name)
-SAVED_VAR(/datum/money_account, owner_name)
-SAVED_VAR(/datum/money_account, account_id)
-SAVED_VAR(/datum/money_account, remote_access_pin)
-SAVED_VAR(/datum/money_account, money)
-SAVED_VAR(/datum/money_account, transaction_log)
-SAVED_VAR(/datum/money_account, suspended)
-SAVED_VAR(/datum/money_account, security_level)
-SAVED_VAR(/datum/money_account, account_type)
-SAVED_VAR(/datum/money_account, currency)
-
SAVED_VAR(/datum/pipeline, air)
SAVED_VAR(/datum/reagents/metabolism, metabolism_class)
@@ -212,13 +201,6 @@ SAVED_VAR(/datum/stored_items, amount)
SAVED_VAR(/datum/stored_items, instances)
SAVED_VAR(/datum/stored_items, storing_object)
-SAVED_VAR(/datum/transaction, purpose)
-SAVED_VAR(/datum/transaction, amount)
-SAVED_VAR(/datum/transaction, date)
-SAVED_VAR(/datum/transaction, time)
-SAVED_VAR(/datum/transaction, target)
-SAVED_VAR(/datum/transaction, source)
-
SAVED_VAR(/datum/turbolift, current_floor)
SAVED_VAR(/datum/turbolift, doors)
SAVED_VAR(/datum/turbolift, floors)
diff --git a/mods/persistence/modules/world_save/serializers/json_serializer.dm b/mods/persistence/modules/world_save/serializers/json_serializer.dm
index 2cfa73716b7..fce814a01e1 100644
--- a/mods/persistence/modules/world_save/serializers/json_serializer.dm
+++ b/mods/persistence/modules/world_save/serializers/json_serializer.dm
@@ -41,11 +41,12 @@
else if(istext(VV) || isnum(VV) || isnull(VV))
results[V] = VV
else if(istype(VV, /datum))
- if(VV in object_parent)
- var/datum/VD = VV
- results[V] = "[SERIALIZER_TYPE_FLAT_REF]#[VD.persistent_id]"
- else if(should_flatten(VV))
- results[V] = "[SERIALIZER_TYPE_DATUM_FLAT]#[SerializeDatum(VV, object_parent)]"
+ if(should_flatten(VV))
+ if(VV in object_parent)
+ var/datum/VD = VV
+ results[V] = "[SERIALIZER_TYPE_FLAT_REF]#[VD.persistent_id]"
+ else
+ results[V] = "[SERIALIZER_TYPE_DATUM_FLAT]#[SerializeDatum(VV, object_parent)]"
else if(get_wrapper(VV))
var/wrapper_path = get_wrapper(VV)
var/datum/wrapper/GD = new wrapper_path
@@ -87,11 +88,12 @@
else if(ispath(K))
F_K = "[SERIALIZER_TYPE_PATH]#[K]"
else if(istype(K, /datum))
- if(K in list_parent)
- var/datum/KD = K
- F_K = "[SERIALIZER_TYPE_FLAT_REF]#[KD.persistent_id]"
- else if(should_flatten(K))
- F_K = "[SERIALIZER_TYPE_DATUM_FLAT]#[SerializeDatum(K, list_parent)]"
+ if(should_flatten(K))
+ if(K in list_parent)
+ var/datum/KD = K
+ F_K = "[SERIALIZER_TYPE_FLAT_REF]#[KD.persistent_id]"
+ else
+ F_K = "[SERIALIZER_TYPE_DATUM_FLAT]#[SerializeDatum(K, list_parent)]"
else if(get_wrapper(K))
var/wrapper_path = get_wrapper(K)
var/datum/wrapper/GD = new wrapper_path
@@ -100,7 +102,7 @@
GD.on_serialize(K, src)
if(!GD.key)
continue
- F_K = "[SERIALIZER_TYPE_WRAPPER]#[SerializeDatum(K, list_parent)]"
+ F_K = "[SERIALIZER_TYPE_WRAPPER]#[SerializeDatum(GD, list_parent)]"
else
// list_parent is intentionally not passed. See ./SerializeDatum
F_K = "[SERIALIZER_TYPE_DATUM]#[sql.SerializeDatum(K)]"
@@ -116,11 +118,12 @@
else if(istext(V) || isnum(V) || isnull(V))
F_V = V
else if(istype(V, /datum))
- if(V in list_parent)
- var/datum/VD = V
- F_V = "[SERIALIZER_TYPE_FLAT_REF]#[VD.persistent_id]"
- else if(should_flatten(V))
- F_V = "[SERIALIZER_TYPE_DATUM_FLAT]#[SerializeDatum(V, list_parent)]"
+ if(should_flatten(V))
+ if(V in list_parent)
+ var/datum/VD = V
+ F_V = "[SERIALIZER_TYPE_FLAT_REF]#[VD.persistent_id]"
+ else
+ F_V = "[SERIALIZER_TYPE_DATUM_FLAT]#[SerializeDatum(V, list_parent)]"
else if(get_wrapper(V))
var/wrapper_path = get_wrapper(V)
var/datum/wrapper/GD = new wrapper_path
@@ -129,7 +132,7 @@
GD.on_serialize(V, src)
if(!GD.key)
continue
- F_V = "[SERIALIZER_TYPE_WRAPPER]#[SerializeDatum(V, list_parent)]"
+ F_V = "[SERIALIZER_TYPE_WRAPPER]#[SerializeDatum(GD, list_parent)]"
else
// See above.
F_V = "[SERIALIZER_TYPE_DATUM]#[sql.SerializeDatum(V)]"
diff --git a/mods/persistence/modules/world_save/serializers/one_off_serializer.dm b/mods/persistence/modules/world_save/serializers/one_off_serializer.dm
index c1ea41d89c6..9002b37d187 100644
--- a/mods/persistence/modules/world_save/serializers/one_off_serializer.dm
+++ b/mods/persistence/modules/world_save/serializers/one_off_serializer.dm
@@ -13,7 +13,7 @@
if(extension_wrapper_holder && object.extensions)
for(var/key in object.extensions)
var/datum/extension/E = object.extensions[key]
- if(istype(E) && E.should_save())
+ if(istype(E) && E.should_save(one_off = TRUE))
extension_wrapper_holder.wrapped |= E
/serializer/sql/one_off/Commit(limbo_assoc)
@@ -31,7 +31,7 @@
query = dbcon_save.NewQuery("INSERT INTO `[SQLS_TABLE_LIMBO_DATUM_VARS]`(`thing_id`,`key`,`type`,`value`,`limbo_assoc`) VALUES["(" + jointext(var_inserts, ",'[limbo_assoc]'),(") + ",'[limbo_assoc]')"]")
SQLS_EXECUTE_AND_REPORT_ERROR(query, "LIMBO VAR SERIALIZATION FAILED:")
- if(length(element_inserts) > 0)
+ if(length(element_inserts) > 0)
tot_element_inserts += length(element_inserts)
var/raw_statement = "INSERT INTO `[SQLS_TABLE_LIMBO_LIST_ELEM]`(`list_id`,`key`,`key_type`,`value`,`value_type`,`limbo_assoc`) VALUES["(" + jointext(element_inserts, ",'[limbo_assoc]'),(") + ",'[limbo_assoc]')"]"
query = dbcon_save.NewQuery(raw_statement)
@@ -160,7 +160,7 @@
SerializeDatum(thing, null, limbo_assoc)
if(length(extension_wrapper_holder.wrapped))
SerializeDatum(extension_wrapper_holder, null, limbo_assoc)
-
+
try
Commit(limbo_assoc)
catch (var/exception/e)
@@ -169,7 +169,7 @@
// Get the persistent ID for the "parent" objects.
var/list/thing_p_ids = list()
-
+
for(var/datum/thing in things)
if(!thing.persistent_id)
thing.persistent_id = PERSISTENT_ID
@@ -180,24 +180,24 @@
// Insert into the limbo table, a metadata holder that allows for access to the limbo_assoc key by 'type' and 'key'.
var/DBQuery/insert_query
insert_query = dbcon_save.NewQuery("INSERT INTO `[SQLS_TABLE_LIMBO]` (`key`,`type`,`p_ids`,`metadata`,`limbo_assoc`, `metadata2`) VALUES('[key]', '[limbo_type]', '[encoded_p_ids]', '[metadata]', '[limbo_assoc]', '[metadata2]')")
-
+
try
SQLS_EXECUTE_AND_REPORT_ERROR(insert_query, "LIMBO ADDITION FAILED:")
catch (var/exception/insert_e)
Clear()
throw insert_e
-
+
// Final check, ensure each passed thing has been added to the limbo table
var/DBQuery/check_query
check_query = dbcon_save.NewQuery("SELECT COUNT(*) FROM `[SQLS_TABLE_LIMBO_DATUM]` WHERE `limbo_assoc` = '[limbo_assoc]' AND `p_id` IN ('[jointext(thing_p_ids, "', '")]');")
-
+
try
SQLS_EXECUTE_AND_REPORT_ERROR(check_query, "LIMBO CHECK FAILED:")
catch (var/exception/check_e)
Clear()
RemoveFromLimbo(key, limbo_type)
throw check_e
-
+
if(check_query.NextRow())
if(text2num(check_query.item[1]) == length(thing_p_ids))
. = TRUE // Success!
@@ -254,7 +254,7 @@
// Start initializing whatever we deserialized.
SSatoms.map_loader_stop()
SSatoms.InitializeAtoms()
-
+
Clear()
return targets
diff --git a/mods/persistence/modules/world_save/serializers/sql_serializer.dm b/mods/persistence/modules/world_save/serializers/sql_serializer.dm
index bcd407a97d1..e32dd865b0f 100644
--- a/mods/persistence/modules/world_save/serializers/sql_serializer.dm
+++ b/mods/persistence/modules/world_save/serializers/sql_serializer.dm
@@ -54,7 +54,7 @@
var/inserts_since_commit = 0
var/autocommit_threshold = 5000
- var/ref_tracker = TRUE // whevere or not this serializer does reference tracking and adds it to the thing insert list.
+ var/ref_tracker = TRUE // whether or not this serializer does reference tracking and adds it to the thing insert list.
var/inserts_since_ref_update = 0 // we automatically commit refs to the database in batches on load
var/ref_update_threshold = 200
@@ -208,10 +208,12 @@ var/global/list/serialization_time_spent_type
var/datum/VD = VV
if(!VD.should_save(object))
continue
- // Reference only vars do not serialize their target objects, and act only as pointers.
+ // Reference only vars do not serialize their target objects, only retaining the reference if its been serialized elsewhere.
if(V in global.reference_only_vars)
VT = SERIALIZER_TYPE_DATUM
- VV = VD.persistent_id ? VD.persistent_id : PERSISTENT_ID
+ if(!VD.persistent_id)
+ VD.persistent_id = PERSISTENT_ID
+ VV = VD.persistent_id
// Serialize it complex-like, baby.
else if(should_flatten(VV))
VT = SERIALIZER_TYPE_DATUM_FLAT // If we flatten an object, the var becomes json. This saves on indexes for simple objects.
diff --git a/mods/persistence/modules/world_save/wrappers/escrow_holder.dm b/mods/persistence/modules/world_save/wrappers/escrow_holder.dm
new file mode 100644
index 00000000000..6d52957bd8a
--- /dev/null
+++ b/mods/persistence/modules/world_save/wrappers/escrow_holder.dm
@@ -0,0 +1,6 @@
+// Escrow accounts aren't wrapped but this is a simple way to handle recovering escrow accounts.
+/datum/wrapper_holder/escrow_holder/after_deserialize()
+ . = ..()
+ if(length(wrapped))
+ SSmoney_accounts.all_escrow_accounts |= wrapped
+ wrapped.Cut()
\ No newline at end of file
diff --git a/mods/persistence/modules/world_save/wrappers/extensions/_extension_wrapper.dm b/mods/persistence/modules/world_save/wrappers/extensions/_extension_wrapper.dm
index 0b66fbf2ba8..f068186dbea 100644
--- a/mods/persistence/modules/world_save/wrappers/extensions/_extension_wrapper.dm
+++ b/mods/persistence/modules/world_save/wrappers/extensions/_extension_wrapper.dm
@@ -7,6 +7,7 @@
. = ..()
if(!object.holder)
return
+ object.before_save()
key = "[object.type]"
if(!object.holder.persistent_id)
object.holder.persistent_id = PERSISTENT_ID
diff --git a/nano/templates/atm_program.tmpl b/nano/templates/atm_program.tmpl
index 58424ea3093..50c079373a9 100644
--- a/nano/templates/atm_program.tmpl
+++ b/nano/templates/atm_program.tmpl
@@ -67,7 +67,7 @@
| Description | Activation time | Early trigger | Cancel + |
|---|---|---|---|
| Description | Activation time | Early trigger {{for data.pending_mods}} | |
| {{:value.desc}} | @@ -77,11 +77,6 @@ {{:helper.link('', 'alert', {'activate_modification' : value.index})}} {{/if}} -- {{if value.allow_cancel}} - {{:helper.link('', 'cancel', {'cancel_modification' : value.index})}} - {{/if}} - | {{/for}}