From 74a02b1f99ae78280f3b5ec3386cfdf05903736c Mon Sep 17 00:00:00 2001 From: FabianK3 <21039694+FabianK3@users.noreply.github.com> Date: Wed, 22 Apr 2026 22:21:39 +0200 Subject: [PATCH] Fix persistence on non-Horizon and admin persistence toggle admin verb (#22301) # Summary This PR fixes persistence on non-Horizon maps and adds an admin verb to toggle saving at round end. ## Changes - Fixed persistency being used on non-Horizon maps, prevents loading and saving. - Added admin verb "Toggle persistence" to prevent saving at round end. ## Verb preview Verb location Screenshot 2026-04-20 204519 Input to disable Screenshot 2026-04-20 204628 Disable output Screenshot 2026-04-20 204644 Input to re-enable Screenshot 2026-04-20 204653 Re-enable output Screenshot 2026-04-20 204709 --------- Signed-off-by: FabianK3 <21039694+FabianK3@users.noreply.github.com> Co-authored-by: SleepyGemmy <99297919+SleepyGemmy@users.noreply.github.com> --- .github/workflows/byond.yml | 159 ++++++++++-------- .../subsystems/persistence/persistence.dm | 39 ++++- .../persistence/persistence_objects.dm | 10 ++ .../persistence/persistence_objects_public.dm | 2 +- code/modules/admin/admin_verbs.dm | 3 +- ...abiank3-fix-persistence-on-non-horizon.yml | 7 + 6 files changed, 147 insertions(+), 73 deletions(-) create mode 100644 html/changelogs/fabiank3-fix-persistence-on-non-horizon.yml diff --git a/.github/workflows/byond.yml b/.github/workflows/byond.yml index abeb258dfb3..3c0012a9ce5 100644 --- a/.github/workflows/byond.yml +++ b/.github/workflows/byond.yml @@ -4,18 +4,18 @@ on: workflow_dispatch: merge_group: branches: - - master + - master push: branches: - - master + - master pull_request: branches: - - master + - master env: MACRO_COUNT: 0 GENDER_COUNT: 6 - TO_WORLD_COUNT: 176 + TO_WORLD_COUNT: 178 #These variables are filled from dependencies.sh inside the steps, DO NOT SET THEM HERE BYOND_MAJOR: "" @@ -40,10 +40,9 @@ concurrency: cancel-in-progress: true jobs: - -########################################### -################# BASH/AWK ################ -########################################### + ########################################### + ################# BASH/AWK ################ + ########################################### validate-structure: name: Validate Structure outputs: @@ -56,7 +55,6 @@ jobs: cancel-in-progress: true steps: - #Checkout the repository - name: Checkout repository uses: actions/checkout@v4 @@ -121,9 +119,9 @@ jobs: echo "Continuing with CI." fi -########################################### -############### EditorConfig ############## -########################################### + ########################################### + ############### EditorConfig ############## + ########################################### megalinter: name: Validate EditorConfig Compliance runs-on: ubuntu-24.04 @@ -143,7 +141,6 @@ jobs: APPLY_FIXES_MODE: commit steps: - #Checkout the repository - name: Checkout repository uses: actions/checkout@v4 @@ -177,10 +174,9 @@ jobs: mega-linter.log retention-days: 5 - -########################################### -############### SPACEMANDMM ############### -########################################### + ########################################### + ############### SPACEMANDMM ############### + ########################################### lint-spacemandmm: name: Lint SpacemanDMM runs-on: ubuntu-24.04 @@ -192,7 +188,6 @@ jobs: cancel-in-progress: true steps: - #Checkout the repository - name: Checkout repository uses: actions/checkout@v4 @@ -224,10 +219,9 @@ jobs: with: outputFile: output-annotations.txt - -########################################### -################ OPENDREAM ################ -########################################### + ########################################### + ################ OPENDREAM ################ + ########################################### lint-opendream: name: Lint OpenDream runs-on: ubuntu-24.04 @@ -239,7 +233,6 @@ jobs: cancel-in-progress: true steps: - #Checkout the repository - name: Checkout repository uses: actions/checkout@v4 @@ -266,9 +259,9 @@ jobs: run: | dotnet $HOME/DMCompiler_linux-x64/DMCompiler.dll --suppress-unimplemented aurorastation.dme -########################################### -############### TGUI LINTING ############## -########################################### + ########################################### + ############### TGUI LINTING ############## + ########################################### lint-tgui: name: Lint TGUI runs-on: ubuntu-24.04 @@ -280,7 +273,6 @@ jobs: cancel-in-progress: true steps: - #Checkout the repository - name: Checkout repository uses: actions/checkout@v4 @@ -294,7 +286,7 @@ jobs: uses: actions/setup-node@v3 with: node-version: ${{ env.NODE_VERSION_LTS }} - cache: 'yarn' + cache: "yarn" cache-dependency-path: tgui/yarn.lock #Lint TGUI @@ -302,10 +294,9 @@ jobs: run: | tools/build/build --ci lint tgui-test - -########################################### -############### MISC LINTING ############## -########################################### + ########################################### + ############### MISC LINTING ############## + ########################################### lint-misc: name: Lint Misc runs-on: ubuntu-24.04 @@ -317,7 +308,6 @@ jobs: cancel-in-progress: true steps: - #Checkout the repository - name: Checkout repository uses: actions/checkout@v4 @@ -331,7 +321,7 @@ jobs: uses: actions/setup-python@v4 with: python-version: ${{ env.PYTHON_VERSION }} - cache: 'pip' + cache: "pip" #Install python packages and tools - name: Install Python Packages @@ -356,14 +346,21 @@ jobs: tools/bootstrap/python -m mapmerge2.dmm_test tools/bootstrap/python -m tools.maplint.source -########################################### -############## GENERIC TESTS ############## -########################################### + ########################################### + ############## GENERIC TESTS ############## + ########################################### generic-tests: name: Generic Tests runs-on: ubuntu-24.04 if: ${{ !failure() }} - needs: [validate-structure, lint-spacemandmm, lint-opendream, lint-tgui, lint-misc] + needs: + [ + validate-structure, + lint-spacemandmm, + lint-opendream, + lint-tgui, + lint-misc, + ] services: mariadb: @@ -387,7 +384,6 @@ jobs: fail-fast: false steps: - - name: "Check if CI or UT ignored" id: check if: ${{ needs.validate-structure.outputs.skipci == 'true' || needs.validate-structure.outputs.skiput == 'true' }} @@ -495,14 +491,21 @@ jobs: path: ./data/logs/**/condensed.log retention-days: 5 -########################################### -########### CREATE AND DESTROY ############ -########################################### + ########################################### + ########### CREATE AND DESTROY ############ + ########################################### create-and-destroy: name: Create and Destroy Test runs-on: ubuntu-24.04 if: ${{ !failure() }} - needs: [validate-structure, lint-spacemandmm, lint-opendream, lint-tgui, lint-misc] + needs: + [ + validate-structure, + lint-spacemandmm, + lint-opendream, + lint-tgui, + lint-misc, + ] services: mariadb: @@ -526,7 +529,6 @@ jobs: fail-fast: false steps: - - name: "Check if CI or UT ignored" id: check if: ${{ needs.validate-structure.outputs.skipci == 'true' || needs.validate-structure.outputs.skiput == 'true' }} @@ -634,16 +636,21 @@ jobs: path: ./data/logs/**/condensed.log retention-days: 5 - - -########################################### -################ TEST MAPS ################ -########################################### + ########################################### + ################ TEST MAPS ################ + ########################################### map-tests: name: Run Map Tests runs-on: ubuntu-24.04 if: ${{ !failure() }} - needs: [validate-structure, lint-spacemandmm, lint-opendream, lint-tgui, lint-misc] + needs: + [ + validate-structure, + lint-spacemandmm, + lint-opendream, + lint-tgui, + lint-misc, + ] services: mariadb: @@ -667,7 +674,6 @@ jobs: fail-fast: false steps: - - name: "Check if CI or UT ignored" id: check if: ${{ needs.validate-structure.outputs.skipci == 'true' || needs.validate-structure.outputs.skiput == 'true' }} @@ -775,16 +781,21 @@ jobs: path: ./data/logs/**/condensed.log retention-days: 5 - - -########################################### -############# EXOPLANETS TESTS ############ -########################################### + ########################################### + ############# EXOPLANETS TESTS ############ + ########################################### exoplanet_testing: name: Run Exoplanet Tests runs-on: ubuntu-24.04 if: ${{ !failure() }} - needs: [validate-structure, lint-spacemandmm, lint-opendream, lint-tgui, lint-misc] + needs: + [ + validate-structure, + lint-spacemandmm, + lint-opendream, + lint-tgui, + lint-misc, + ] services: mariadb: @@ -808,7 +819,6 @@ jobs: fail-fast: false steps: - - name: "Check if CI or UT ignored" id: check if: ${{ needs.validate-structure.outputs.skipci == 'true' || needs.validate-structure.outputs.skiput == 'true' }} @@ -916,15 +926,21 @@ jobs: path: ./data/logs/**/condensed.log retention-days: 5 - -########################################### -############# TEST AWAY SITES ############# -########################################### + ########################################### + ############# TEST AWAY SITES ############# + ########################################### away-sites-tests: name: Run Map Tests runs-on: ubuntu-24.04 if: ${{ !failure() }} - needs: [validate-structure, lint-spacemandmm, lint-opendream, lint-tgui, lint-misc] + needs: + [ + validate-structure, + lint-spacemandmm, + lint-opendream, + lint-tgui, + lint-misc, + ] services: mariadb: @@ -948,7 +964,6 @@ jobs: fail-fast: false steps: - - name: "Check if CI or UT ignored" id: check if: ${{ needs.validate-structure.outputs.skipci == 'true' || needs.validate-structure.outputs.skiput == 'true' }} @@ -1056,14 +1071,21 @@ jobs: path: ./data/logs/**/condensed.log retention-days: 5 -########################################### -################ TEST RUINS ############### -########################################### + ########################################### + ################ TEST RUINS ############### + ########################################### ruins-tests: name: Run Ruins Tests runs-on: ubuntu-24.04 if: ${{ !failure() }} - needs: [validate-structure, lint-spacemandmm, lint-opendream, lint-tgui, lint-misc] + needs: + [ + validate-structure, + lint-spacemandmm, + lint-opendream, + lint-tgui, + lint-misc, + ] services: mariadb: @@ -1087,7 +1109,6 @@ jobs: fail-fast: false steps: - - name: "Check if CI or UT ignored" id: check if: ${{ needs.validate-structure.outputs.skipci == 'true' || needs.validate-structure.outputs.skiput == 'true' }} diff --git a/code/controllers/subsystems/persistence/persistence.dm b/code/controllers/subsystems/persistence/persistence.dm index 5448d95507c..0a364309a92 100644 --- a/code/controllers/subsystems/persistence/persistence.dm +++ b/code/controllers/subsystems/persistence/persistence.dm @@ -13,13 +13,14 @@ SUBSYSTEM_DEF(persistence) name = "Persistence" init_order = INIT_ORDER_PERSISTENCE // The order is tied with the init and maploading subsystem. flags = SS_NO_FIRE // This subsystem has no continues workload, it's init and shutdown only. + var/prevent_saving = FALSE // Toggle to prevent saving at round end, changed by toggle_persistence proc, used for admin purposes. /** * Subsystem info stub message generation. */ /datum/controller/subsystem/persistence/stat_entry(msg) - msg = ("Tracked object register: [length(GLOB.persistence_object_track_register)]") - return ..() + msg = ("Register: [length(GLOB.persistence_object_track_register)] | Prevent saving: [SSpersistence.prevent_saving ? "TRUE" : "FALSE"]") + return msg /** * Helper method to check and log database connection. @@ -48,6 +49,36 @@ SUBSYSTEM_DEF(persistence) return FALSE return TRUE +/datum/admins/proc/toggle_persistence() + set name = "Toggle Persistence" + set category = "Special Verbs" + + if(!check_rights(R_ADMIN)) + return + + var/message = "" + var/options = list() + if(SSpersistence.prevent_saving) + message = "The persistence subsystem will NOT save at the end of the round. Do you want to re-enable it?" + options = list("Re-enable saving", "Cancel") + else + message = "The persistence subsystem will save at the end of the round. Do you want to prevent this? This can be un-done before the round ends." + options = list("Prevent saving", "Cancel") + + var/confirm = tgui_alert(usr, message, "Toggle Persistence Saving", options) + if(confirm == "Prevent saving") + SSpersistence.prevent_saving = TRUE + to_world(FONT_LARGE(EXAMINE_BLOCK_RED("Persistence saving at the end of the round has been [SPAN_BOLD(SPAN_WARNING("disabled"))] by an administrator."))) + log_and_message_admins("has toggled persistence saving at round end, it is now disabled", usr) + else if (confirm == "Re-enable saving") + SSpersistence.prevent_saving = FALSE + to_world(FONT_LARGE(EXAMINE_BLOCK_RED("Persistence saving at the end of the round has been [SPAN_BOLD(SPAN_GOOD("re-enabled"))] by an administrator."))) + log_and_message_admins("has toggled persistence saving at round end, it is now re-enabled", usr) + else + return + + feedback_add_details("admin_verb","TP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + /** * Initialization of the persistence subsystem. * Includes generic startup checks and init of the different persistent data types. @@ -74,6 +105,10 @@ SUBSYSTEM_DEF(persistence) * The shutdown consists of finalization steps for each persistent data type. */ /datum/controller/subsystem/persistence/Shutdown() + if(prevent_saving) + log_subsystem_persistence_warning("Persistence subsystem was toggled to not save. Skipping subsystem finalization.") + return + if(!databaseCheckConnection("subsystem shutdown")) log_subsystem_persistence_panic("SQL error during persistence subsystem shutdown. Cannot finalise persistence of the round.") return diff --git a/code/controllers/subsystems/persistence/persistence_objects.dm b/code/controllers/subsystems/persistence/persistence_objects.dm index 5e0d8a59e73..24fb3e05665 100644 --- a/code/controllers/subsystems/persistence/persistence_objects.dm +++ b/code/controllers/subsystems/persistence/persistence_objects.dm @@ -6,6 +6,10 @@ 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() @@ -36,6 +40,12 @@ /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) diff --git a/code/controllers/subsystems/persistence/persistence_objects_public.dm b/code/controllers/subsystems/persistence/persistence_objects_public.dm index 2a3452694b1..391f9ce97fc 100644 --- a/code/controllers/subsystems/persistence/persistence_objects_public.dm +++ b/code/controllers/subsystems/persistence/persistence_objects_public.dm @@ -10,7 +10,7 @@ return var/turf/T = get_turf(new_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 + if(!T || !is_station_level(T.z) || 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 return new_track.persistent_objects_track_active = TRUE diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 48f9c973ae0..cc2a6f8f3f1 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -146,7 +146,8 @@ GLOBAL_LIST_INIT(admin_verbs_fun, list( /client/proc/apply_sunstate, /datum/admins/proc/ccannoucment, /datum/admins/proc/set_odyssey, - /datum/admins/proc/set_odyssey_canonicity + /datum/admins/proc/set_odyssey_canonicity, + /datum/admins/proc/toggle_persistence )) GLOBAL_LIST_INIT(admin_verbs_spawn, list( diff --git a/html/changelogs/fabiank3-fix-persistence-on-non-horizon.yml b/html/changelogs/fabiank3-fix-persistence-on-non-horizon.yml new file mode 100644 index 00000000000..fc17f3e08e1 --- /dev/null +++ b/html/changelogs/fabiank3-fix-persistence-on-non-horizon.yml @@ -0,0 +1,7 @@ +author: FabianK3 + +delete-after: True + +changes: + - bugfix: "Fixed persistence being used on non-Horizon maps." + - rscadd: "Added an admin verb to toggle persistence saving."