myspace / CommonLua /Core /GlobalStorageTables.lua
sirnii's picture
Upload 1816 files
b6a38d7 verified
raw
history blame
18.8 kB
--- Initializes global variables `g_FirstTimeUser` and `g_LocalStorageFile` based on the `FirstLoad` flag.
-- If `FirstLoad` is true, `g_FirstTimeUser` is set to false and `g_LocalStorageFile` is set to either "AppData/LocalStorageGed.lua" or "AppData/LocalStorage.lua" depending on the `Platform.ged` flag.
if FirstLoad then
g_FirstTimeUser = false
g_LocalStorageFile = "AppData/" .. (Platform.ged and "LocalStorageGed.lua" or "LocalStorage.lua")
end
-- All Set*Storage functions accept a table, or one of the strings "default" and "invalid"
--- Initializes a storage table with default values.
--
-- If `storage` is "invalid", it is set to `false`.
-- If `storage` is "default", it is set to an empty table.
-- Otherwise, `storage` is assumed to be a table and its values are set to the defaults in `default`.
-- If `default` has a metatable and `storage` does not have the same class, `storage` is converted to an object of the same class as `default`.
--
-- @param storage The storage table to initialize, or the string "default" or "invalid".
-- @param default The default values to use for initializing the storage table.
-- @return The initialized storage table.
local function InitWithDefault(storage, default)
assert(storage)
if storage == "invalid" then
storage = false
else
if storage == "default" then
storage = {}
end
assert(type(storage) == "table")
-- Convert the storage from dumb table to object (if needed)
if getmetatable(default) and not ObjectClass(storage) and ObjectClass(default) then
storage = g_Classes[default.class]:new(storage)
end
table.set_defaults(storage, default, "deep")
end
return storage
end
--- Returns a table with default values for option fixup metadata.
--
-- The returned table has the following fields:
-- - `AppliedOptionFixups`: A table of applied option fixups.
-- - `last_applied_fixup_revision`: The revision of the last applied fixup.
--
-- @return A table with default option fixup metadata.
function GetDefaultOptionFixupMeta()
return {AppliedOptionFixups={}, last_applied_fixup_revision=0}
end
--- Returns the default account options.
--
-- @return The default account options.
function GetDefaultAccountOptions()
return DefaultAccountStorage.Options
end
--- Sets the platform-specific default engine options.
--
-- This function overrides the default engine options with platform-specific defaults.
-- The resulting options are stored in the `PlatformDefaultEngineOptions` global variable.
--
-- The platform-specific defaults are defined in the `DefaultEngineOptions` table, with keys
-- corresponding to the different platforms (e.g. "steamdeck", "desktop", "xbox_one", etc.).
-- This function checks the current platform and selects the appropriate platform-specific
-- defaults to overwrite the main default options.
--
-- @function SetPlatformDefaultEngineOptions
-- @return none
function SetPlatformDefaultEngineOptions()
-- Overwrite default options with platform-specific defaults
local result_options = table.copy(DefaultEngineOptions["default_options"])
if Platform.steamdeck then
table.overwrite(result_options, DefaultEngineOptions["steamdeck"])
elseif Platform.desktop then
table.overwrite(result_options, DefaultEngineOptions["desktop"])
elseif Platform.xbox_one and not Platform.xbox_one_x then
table.overwrite(result_options, DefaultEngineOptions["xbox_one"])
elseif Platform.xbox_one and Platform.xbox_one_x then
table.overwrite(result_options, DefaultEngineOptions["xbox_one_x"])
elseif Platform.xbox_series and not Platform.xbox_series_x then
table.overwrite(result_options, DefaultEngineOptions["xbox_series_s"])
elseif Platform.xbox_series and Platform.xbox_series_x then
table.overwrite(result_options, DefaultEngineOptions["xbox_series_x"])
elseif Platform.ps4 and not Platform.ps4_pro then
table.overwrite(result_options, DefaultEngineOptions["ps4"])
elseif Platform.ps4 and Platform.ps4_pro then
table.overwrite(result_options, DefaultEngineOptions["ps4_pro"])
elseif Platform.ps5 then
table.overwrite(result_options, DefaultEngineOptions["ps5"])
elseif Platform.switch then
table.overwrite(result_options, DefaultEngineOptions["switch"])
end
PlatformDefaultEngineOptions = result_options
end
--- Returns the default engine options for the current platform.
--
-- If `platform_overwrites_only` is true, this function will return only the platform-specific
-- overrides of the default engine options, instead of the full set of default options.
--
-- The platform-specific overrides are defined in the `DefaultEngineOptions` table, with keys
-- corresponding to the different platforms (e.g. "steamdeck", "desktop", "xbox_one", etc.).
--
-- @param platform_overwrites_only boolean Whether to return only the platform-specific overrides.
-- @return table The default engine options for the current platform.
function GetDefaultEngineOptions(platform_overwrites_only)
if platform_overwrites_only then
if Platform.steamdeck then
return DefaultEngineOptions["steamdeck"]
elseif Platform.desktop then
return DefaultEngineOptions["desktop"]
elseif Platform.xbox_one and not Platform.xbox_one_x then
return DefaultEngineOptions["xbox_one"]
elseif Platform.xbox_one and Platform.xbox_one_x then
return DefaultEngineOptions["xbox_one_x"]
elseif Platform.xbox_series and not Platform.xbox_series_x then
return DefaultEngineOptions["xbox_series_s"]
elseif Platform.xbox_series and Platform.xbox_series_x then
return DefaultEngineOptions["xbox_series_x"]
elseif Platform.ps4 and not Platform.ps4_pro then
return DefaultEngineOptions["ps4"]
elseif Platform.ps4 and Platform.ps4_pro then
return DefaultEngineOptions["ps4_pro"]
elseif Platform.ps5 then
return DefaultEngineOptions["ps5"]
elseif Platform.switch then
return DefaultEngineOptions["switch"]
end
end
return PlatformDefaultEngineOptions
end
--- Returns a table containing the full set of engine options, including both the default options and any
-- user-defined overrides stored in the `EngineOptions` table.
--
-- This function creates a copy of the default engine options using `GetDefaultEngineOptions()`, and then
-- merges any user-defined overrides from the `EngineOptions` table into the copy using `table.overwrite()`.
--
-- @return table The full set of engine options, including both defaults and user overrides.
function GetFullEngineOptions()
local defaults = table.copy(GetDefaultEngineOptions())
return table.overwrite(defaults, EngineOptions)
end
--- Returns a table containing the full set of account options, including both the default options and any
-- user-defined overrides stored in the `AccountStorage.Options` table.
--
-- This function creates a copy of the default account options using `GetDefaultAccountOptions()`, and then
-- merges any user-defined overrides from the `AccountStorage.Options` table into the copy using `table.overwrite()`.
--
-- @return table The full set of account options, including both defaults and user overrides.
function GetFullAccountOptions()
local defaults = table.copy(GetDefaultAccountOptions())
return table.overwrite(defaults, AccountStorage.Options)
end
--- Sets the default engine options as the metatable for the `EngineOptions` table.
--
-- This allows the `EngineOptions` table to use the default options as a fallback, so that only the
-- options with a different value than the default need to be stored on disk. Any missing options
-- in `EngineOptions` will automatically use the default value from `GetDefaultEngineOptions()`.
--
-- This is used to efficiently store and load the engine options, as the full set of options does
-- not need to be serialized.
function SetDefaultEngineOptionsMetaTable()
setmetatable(EngineOptions, {__index=GetDefaultEngineOptions()})
end
--- Initializes the default engine options and sets up the metatable for the `EngineOptions` table.
--
-- This code block is executed on the first load of the file. It sets up the default engine options in the
-- `DefaultEngineOptions` table, which includes various video, audio, gameplay, and display settings.
--
-- The `DefaultEngineOptions` table also includes platform-specific overrides for certain settings, such as
-- resolution, fullscreen mode, and graphics API.
--
-- Additionally, this code sets up the metatable for the `EngineOptions` table, which allows the `EngineOptions`
-- table to use the default options as a fallback. This means that only the options with a different value than
-- the default need to be stored on disk, which improves efficiency when storing and loading the engine options.
if FirstLoad then
--[[
DefaultEngineOptions["default_options"] are the main engine option defaults. They are set
as a __index metatable to EngineOptions. This allows only the options with a different value
than the default to be saved on disk while any missing option fallbacks to the default value.
See SetDefaultEngineOptionsMetaTable().
Some of the defaults (Display options mainly) are used very early to initialize the engine in
InitRenderEngine() through LuaVars in the config. It's good to know that at that point only a
few lua files have been executed and there are no lua classes or game-specific options yet.
The other keys in DefaultEngineOptions (other than "default_options") specify
platform-specific overwrites of the default values.
]]
DefaultEngineOptions = {default_options={ -- Video
VideoPreset="High", Antialiasing="TAA", Upscaling="Off", ResolutionPercent="100", Shadows="High", Textures="High",
Anisotropy="4x", Terrain="High", Effects="High", Lights="High", Postprocess="High", Bloom="On", EyeAdaptation="On",
Vignette="On", ChromaticAberration="On", SSAO="On", SSR="High", ViewDistance="High", ObjectDetail="High",
FPSCounter="Off", Sharpness=const.DefaultSharpness or "Low", -- Audio
MasterVolume=const.MasterDefaultVolume or 500, Music=const.MusicDefaultVolume or 300,
Voice=const.VoiceDefaultVolume or 1000, Sound=const.SoundDefaultVolume or 650,
Ambience=const.AmbienceDefaultVolume or 1000, UI=const.UIDefaultVolume or 1000, MuteWhenMinimized=true,
RadioStation=const.MusicDefaultRadioStation or "", -- Gameplay
CameraShake="On", -- Display
FullscreenMode=0, Resolution=point(1920, 1080), Vsync=true, GraphicsApi=GetDefaultGraphicsApi(),
GraphicsAdapterIndex=0, MaxFps="240", DisplayAreaMargin=0, UIScale=100, Brightness=500,
-- Engine option fixup metadata
fixups_meta=GetDefaultOptionFixupMeta()}, -- Platform overwrites
desktop={Resolution=Platform.developer and point(1920, 1080) or false, FullscreenMode=Platform.developer and 0 or 1},
xbox_one={Resolution=point(1920, 1080), FullscreenMode=1, Vsync=true, GraphicsApi="d3d12", VideoPreset="XboxOne"},
xbox_one_x={Resolution=point(2560, 1440), FullscreenMode=1, Vsync=true, GraphicsApi="d3d12",
VideoPreset="XboxOneX"},
xbox_series_s={Resolution=point(2560, 1440), FullscreenMode=1, Vsync=true, GraphicsApi="d3d12",
VideoPreset="XboxSeriesS"},
xbox_series_x={Resolution=point(3840, 2160), FullscreenMode=1, Vsync=true, GraphicsApi="d3d12",
VideoPreset="XboxSeriesXQuality"},
ps4={Resolution=point(1920, 1080), FullscreenMode=1, Vsync=true, GraphicsApi="gnm", VideoPreset="PS4"},
ps4_pro={Resolution=point(2240, 1260), FullscreenMode=1, Vsync=true, GraphicsApi="gnm", VideoPreset="PS4Pro"},
ps5={Resolution=point(3840, 2160), FullscreenMode=1, Vsync=true, GraphicsApi="agc", VideoPreset="PS5Quality"},
switch={Resolution=point(1280, 720), FullscreenMode=1, Vsync=true, FPSCounter="Off", UIScale=100,
GraphicsApi="NVN", VideoPreset="Switch"},
steamdeck={Resolution=false, FullscreenMode=1, MaxFps="30", UIScale=const.MaxUserUIScaleHighRes,
VideoPreset="SteamDeck"}}
-- Some additional settings are inited in options.lua
DefaultAccountStorage = {Shortcuts={}, achievements={unlocked={}, progress={}, target={}}, tips={current_tip=0},
Options={ -- Account
Gamepad=(Platform.console or Platform.steamdeck) and true or false, -- Gameplay
-- Subtitles = true,
-- Colorblind = false,
Language="Auto", -- Account option fixup metadata
fixups_meta=GetDefaultOptionFixupMeta()}, LoadMods={}, PlayStationStartedActivities={}}
DefaultLocalStorage = {id_old_rect={}, dlgBugReport={}, MovieRecord={}, editor={}, FilteredCategories={},
LockedCategories={}}
PlatformDefaultEngineOptions = {}
SetPlatformDefaultEngineOptions()
EngineOptions = {}
SetDefaultEngineOptionsMetaTable()
end
---
--- Sets the account storage for the current session.
---
--- @param storage table The account storage to set.
---
function SetAccountStorage(storage)
storage = InitWithDefault(storage, DefaultAccountStorage)
AccountStorage = storage
Msg("AccountStorageChanged")
end
---
--- Initializes the local storage for the application.
---
--- If the local storage file does not exist, it creates a new local storage table using the `DefaultLocalStorage` table.
--- If the local storage file exists, it reads the contents of the file and initializes the local storage table.
--- If the local storage table is empty or corrupted, it creates a new local storage table using the `DefaultLocalStorage` table.
--- If the local storage table contains developer settings, it moves them to a separate `Developer` table.
--- If the local storage table's `LuaRevision` is 0 and the platform is not in developer mode, it creates a new local storage table using the `DefaultLocalStorage` table.
---
--- @return table The initialized local storage table.
---
function InitLocalStorage()
end
local function InitLocalStorage()
if not io.exists(g_LocalStorageFile) then
return InitWithDefault("default", DefaultLocalStorage)
end
local fenv = LuaValueEnv()
local t = dofile(g_LocalStorageFile, fenv)
assert(not t or type(t) == "table")
if not t then
g_FirstTimeUser = true
end
t = InitWithDefault(t or "default", DefaultLocalStorage)
-- move developer settings outside of options
if t.Options and not t.Developer then
t.Developer = {General=t.Options.General, EditorHiddenTextOptions=t.Options.EditorHiddenTextOptions,
MapStartup=t.Options.MapStartup}
t.Options.General = nil
t.Options.EditorHiddenTextOptions = nil
t.Options.MapStartup = nil
end
t.LuaRevision = t.LuaRevision or 0
if not Platform.developer and t.LuaRevision == 0 then
t = InitWithDefault("default", DefaultLocalStorage)
end
return t
end
---
--- Sets the account storage to `false` on first load.
---
--- This is likely used to initialize the account storage to a default value on the first run of the application.
---
if FirstLoad then
AccountStorage = false
end
---
--- Saves the current engine options to the local storage file.
---
--- This function is responsible for persisting the current engine options to the local storage file. It first updates the `LuaRevision` field in the `LocalStorage` table, then generates a Lua code string representing the `LocalStorage` table and writes it to the local storage file asynchronously.
---
--- If the write operation fails, this function will print an error message and return `false` along with the error message. Otherwise, it will return `true`.
---
--- @return boolean, string? True if the save operation was successful, false and an error message if it failed.
---
function SaveEngineOptions()
Msg("EngineOptionsSaved")
return SaveLocalStorage()
end
---
--- Initializes the local storage for the application on first load.
---
--- This code block is executed when the application is loaded for the first time. It performs the following actions:
---
--- 1. Checks if the local storage file exists. If not, it initializes the local storage with the default values.
--- 2. Loads the local storage from the file and initializes it with the default values if necessary.
--- 3. Moves the developer settings outside of the options table.
--- 4. Sets the `LuaRevision` field in the local storage table.
--- 5. If the `LuaRevision` is 0 and the application is not in developer mode, it resets the local storage to the default values.
--- 6. Assigns the initialized local storage table to the `LocalStorage` global variable.
--- 7. Sets the `EngineOptions` global variable to the `Options` field of the `LocalStorage` table.
--- 8. Calls the `SetDefaultEngineOptionsMetaTable()` function to set the default metadata for the `EngineOptions` table.
---
if FirstLoad then
DefaultLocalStorage.Options = EngineOptions
LocalStorage = InitLocalStorage()
EngineOptions = LocalStorage.Options
SetDefaultEngineOptionsMetaTable()
end
---
--- Saves the current local storage table to the local storage file.
---
--- This function is responsible for persisting the current local storage table to the local storage file. It first updates the `LuaRevision` field in the `LocalStorage` table, then generates a Lua code string representing the `LocalStorage` table and writes it to the local storage file asynchronously.
---
--- If the write operation fails, this function will print an error message and return `false` along with the error message. Otherwise, it will return `true`.
---
--- @return boolean, string? True if the save operation was successful, false and an error message if it failed.
---
function SaveLocalStorage()
LocalStorage.LuaRevision = LuaRevision
local code = pstr("return ", 1024)
TableToLuaCode(LocalStorage, nil, code)
ThreadLockKey(g_LocalStorageFile)
local err = AsyncStringToFile(g_LocalStorageFile, code, -2, 0)
ThreadUnlockKey(g_LocalStorageFile)
if err then
print("once", "Failed to save a storage table to", g_LocalStorageFile, ":", err)
return false, err
end
return true
end
---
--- Saves the local storage after a short delay.
---
--- This function is used to delay the saving of the local storage to avoid potential performance issues. It calls the `SaveLocalStorage()` function after a short delay of 0 seconds.
---
--- @return boolean, string? True if the save operation was successful, false and an error message if it failed.
---
function SaveLocalStorageDelayed()
DelayedCall(0, SaveLocalStorage)
end