openmw/files/builtin_scripts/scripts/omw/settings/common.lua

183 lines
5.5 KiB
Lua
Raw Normal View History

local storage = require('openmw.storage')
2022-03-07 21:28:05 +01:00
local core = require('openmw.core')
local types = require('openmw.types')
local selfObject
do
local success, result = pcall(function() return require('openmw.self') end)
selfObject = success and result or nil
end
local playerObject = selfObject and selfObject.type == types.Player and selfObject or nil
2022-03-07 21:28:05 +01:00
local eventPrefix = 'omwSettings'
2022-03-07 21:28:05 +01:00
local EVENTS = {
SettingChanged = eventPrefix .. 'Changed',
SetValue = eventPrefix .. 'GlobalSetValue',
GroupRegistered = eventPrefix .. 'GroupRegistered',
RegisterGroup = eventPrefix .. 'RegisterGroup',
Subscribe = eventPrefix .. 'Subscribe',
2022-03-07 21:28:05 +01:00
}
local SCOPE = {
Global = 'Global',
Player = 'Player',
SaveGlobal = 'SaveGlobal',
SavePlayer = 'SavePlayer',
}
local function isPlayerScope(scope)
return scope == SCOPE.Player or scope == SCOPE.SavePlayer
2022-03-07 21:28:05 +01:00
end
local function isSaveScope(scope)
return scope == SCOPE.SaveGlobal or scope == SCOPE.SavePlayer
2022-03-07 21:28:05 +01:00
end
local prefix = 'omw_settings_'
local settingsPattern = prefix .. 'settings_%s%s'
2022-03-07 21:28:05 +01:00
local groupsSection = storage.globalSection(prefix .. 'groups')
if groupsSection.removeOnExit then
groupsSection:removeOnExit()
2022-03-07 21:28:05 +01:00
end
local function values(groupKey, scope)
local player = isPlayerScope(scope)
local save = isSaveScope(scope)
local sectionKey = settingsPattern:format(groupKey, save and '_save' or '')
local section
if player then
section = storage.playerSection and storage.playerSection(sectionKey) or nil
else
section = storage.globalSection(sectionKey)
2022-03-07 21:28:05 +01:00
end
if save and section and section.removeOnExit then
section:removeOnExit()
2022-03-07 21:28:05 +01:00
end
return section
2022-03-07 21:28:05 +01:00
end
local function saveScope(scope)
local saved = {}
for _, group in pairs(groupsSection:asTable()) do
saved[group.key] = values(group.key, scope):asTable()
2022-03-07 21:28:05 +01:00
end
return saved
end
local function loadScope(scope, saved)
if not saved then return end
for _, group in pairs(saved) do
values(group.key, scope):reset(saved[group.key])
2022-03-07 21:28:05 +01:00
end
end
local function groupSubscribeEvent(groupKey)
return ('%sSubscribe%s'):format(eventPrefix, groupKey)
end
local subscriptions = {}
local function handleSubscription(event)
if not subscriptions[event.groupKey] then
subscriptions[event.groupKey] = {}
2022-03-07 21:28:05 +01:00
end
table.insert(subscriptions[event.groupKey], event.object or false)
2022-03-07 21:28:05 +01:00
end
local function subscribe(self)
local groupKey = rawget(self, 'groupKey')
2022-03-07 21:28:05 +01:00
local event = {
groupKey = groupKey,
object = selfObject,
2022-03-07 21:28:05 +01:00
}
core.sendGlobalEvent(EVENTS.Subscribe, event)
if playerObject then
playerObject:sendEvent(EVENTS.Subscribe, event)
2022-03-07 21:28:05 +01:00
end
return groupSubscribeEvent(groupKey)
2022-03-07 21:28:05 +01:00
end
local groupMeta = {
__newindex = function(self, settingKey, value)
local group = groupsSection:get(rawget(self, 'groupKey'))
local setting = group.settings[settingKey]
if not setting then
error(('Setting %s does not exist'):format(settingKey))
end
local section = values(group.key, setting.scope)
local event = {
groupKey = group.key,
settingKey = settingKey,
value = value,
}
if section.set then
section:set(settingKey, value)
if playerObject then
playerObject:sendEvent(EVENTS.SettingChanged, event)
else
core.sendGlobalEvent(EVENTS.SettingChanged, event)
end
if subscriptions[group.key] then
local eventKey = groupSubscribeEvent(group.key)
for _, object in ipairs(subscriptions[group.key]) do
if object then
object:sendEvent(eventKey, event)
else
core.sendGlobalEvent(eventKey, event)
end
end
2022-03-07 21:28:05 +01:00
end
else
if isPlayerScope(setting.scope) then
error(("Can't change player scope setting %s from global scope"):format(settingKey))
else
core.sendGlobalEvent(EVENTS.SetValue, event)
end
end
end,
__index = function(self, key)
if key == "subscribe" then return subscribe end
local settingKey = key
local group = groupsSection:get(rawget(self, 'groupKey'))
local setting = group.settings[settingKey]
if not setting then
error(('Unknown setting %s'):format(settingKey))
end
local section = rawget(self, 'sections')[setting.scope]
if not section then
error(("Can't access setting %s from scope %s"):format(settingKey, setting.scope))
end
return section:get(setting.key) or setting.default
end,
2022-03-07 21:28:05 +01:00
}
local function group(groupKey)
if not groupsSection:get(groupKey) then
print(("Settings group %s wasn't registered yet"):format(groupKey))
2022-03-07 21:28:05 +01:00
end
local s = {}
for _, scope in pairs(SCOPE) do
local section = values(groupKey, scope)
if section then
s[scope] = section
end
end
return setmetatable({
groupKey = groupKey,
sections = s,
}, groupMeta)
2022-03-07 21:28:05 +01:00
end
return {
SCOPE = SCOPE,
EVENTS = EVENTS,
isPlayerScope = isPlayerScope,
isSaveScope = isSaveScope,
values = values,
groups = function()
return groupsSection
end,
saveScope = saveScope,
loadScope = loadScope,
group = group,
handleSubscription = handleSubscription,
2022-03-07 21:28:05 +01:00
}