Browse Source

Auto-save userdata periodically

This is pretty hacky due to not having an Introspection deep copy
operation.
filter-focus
Macoy Madson 1 year ago
parent
commit
61e6b38200
  1. 2
      Dependencies/gamelib
  2. 14
      src/FileHelper.cake
  3. 48
      src/LoadSave.cake

2
Dependencies/gamelib

@ -1 +1 @@
Subproject commit 0064e5820d6cff6860009e14314933cad298bf04
Subproject commit 17292433ae619aa3bd4e2ea063b0ba32ccabf232

14
src/FileHelper.cake

@ -27,7 +27,9 @@
;; Types and stuff
;;
(var-global g-is-first-time-run bool true)
(var-global g-is-first-time-run bool true) ;; Pops Help window on first run
(var c-check-save-userdata-interval-seconds (const float) 5.f)
(var g-treemap-multithreaded-state (* treemap-file-system-multithreaded-state) null)
(var g-treemap-request-refresh-time Uint64 0)
(defun-local treemap-request-refresh ()
@ -1373,12 +1375,21 @@ File helper is designed to have a very efficient user interface to assist you in
(var show-colorizers-editor bool true)
(var show-treemap bool true)
(var show-error-window bool g-save-disabled-due-to-error)
(var last-time-saved Uint64 (SDL_GetPerformanceCounter))
(timing-zone-stop initialize-zone))
(body ;; Once per frame
(profiler-mark-frame)
(time-this-scope scope-6 "User Frame")
(when (and should-save-load-user-config
(> (/ (- (SDL_GetPerformanceCounter) last-time-saved)
(type-cast (SDL_GetPerformanceFrequency) float))
c-check-save-userdata-interval-seconds))
(unless (save-state-s-expr)
(SDL_Log "error: failed to save state"))
(set last-time-saved (SDL_GetPerformanceCounter)))
;; Get keyboard input
(var num-sdl-keys int 0)
(var key-states (* (const (unsigned char)))
@ -1652,6 +1663,7 @@ Depending on the error, open the UserData.cakedata file in a text editor and see
(when should-save-load-user-config
(unless (save-state-s-expr)
(SDL_Log "error: failed to save state")))
(load-save-shutdown)
(destroy-directory-state (addr listing-state))
(strdict-free g-userdata-dict)

48
src/LoadSave.cake

@ -31,6 +31,10 @@
(var-global g-save-disabled-due-to-error bool false)
(var-global g-save-disabled-due-to-error-string ([] 256 char) (array 0))
(var g-last-saved-state file-helper-userdata (array 0))
(defun load-save-shutdown ()
(free-introspect-struct-fields file-helper-userdata--metadata (addr g-last-saved-state) free))
(defun save-state-s-expr (&return bool)
(when g-save-disabled-due-to-error
@ -44,14 +48,26 @@
(set (field userdata categorized-entries) g-userdata-dict)
(set (field userdata file-colorizers) g-file-colorizers)
;; Not saving: no difference
(when (introspect-struct-= file-helper-userdata--metadata
(addr g-last-saved-state)
(addr userdata))
;; (fprintf stderr "Not saving: no changes detected\n")
(return true))
(fprintf stderr "UserData changed. Saving...\n")
(var full-output-userdata ([] 1024 char) (array 0))
(snprintf full-output-userdata (sizeof full-output-userdata) "%s%s"
g-userdata-output-dir "UserData_TestWrite.cakedata")
;; Tests loading and saving. Note that this will prevent trashing the user file if it fails!
;; TODO: Remove once some scheme is devised to protect user data on bad write
(unless (introspect-test-struct file-helper-userdata--metadata (addr userdata)
full-output-userdata)
(unless (introspect-test-struct-quiet file-helper-userdata--metadata (addr userdata)
full-output-userdata)
(fprintf stderr "error: UserData cannot be written. introspect-test-struct failed.\n")
;; Now use the loud version so I can diagnose the issue
(introspect-test-struct file-helper-userdata--metadata (addr userdata)
full-output-userdata)
(return false))
(snprintf full-output-userdata (sizeof full-output-userdata) "%s%s"
@ -74,6 +90,30 @@
(fclose out-file)
(return false))
(fclose out-file)
(scope ;; TODO Hack: this should just be a deep copy
(var full-output-copy ([] 1024 char) (array 0))
(snprintf full-output-copy (sizeof full-output-copy) "%s%s"
g-userdata-output-dir "UserData_LastSaved.cakedata")
(var out-file (* FILE) (fopen full-output-copy "w"))
(unless out-file
(return false))
(unless (write-introspect-struct-s-expr file-helper-userdata--metadata
(addr userdata) out-file
write-introspect-struct-add-newline)
(fclose out-file)
(return false))
(fclose out-file)
(free-introspect-struct-fields file-helper-userdata--metadata (addr g-last-saved-state) free)
(var in-file (* FILE) (fopen full-output-copy "r"))
(unless in-file
(return false))
(var file-contents (* char) (read-file-into-memory in-file))
(fclose in-file)
(unless (read-introspect-struct-s-expr file-helper-userdata--metadata (addr g-last-saved-state)
file-contents malloc null)
(fprintf stderr "warning: failed to update g-last-saved-state. Unnecessary saves will occur\n"))
(free file-contents))
(return true))
(defun load-state-s-expr (&return bool)
@ -118,6 +158,10 @@
(free (type-cast file-contents (* void)))
(set g-save-disabled-due-to-error true)
(return false))
;; We know it succeeded the first time.
;; TODO This could use a (deep) copy Introspection function rather than having to re-parse the text
(read-introspect-struct-s-expr file-helper-userdata--metadata (addr g-last-saved-state)
(+ num-characters-read file-contents) malloc null)
(free (type-cast file-contents (* void)))
;; (write-introspect-struct-s-expr file-helper-userdata--metadata

Loading…
Cancel
Save