mirror of
https://github.com/luanti-org/luanti.git
synced 2025-08-01 17:38:41 +00:00
Add server/client annotations to settingtypes.txt and make use of them (#15756)
This commit is contained in:
parent
6724068659
commit
c30c94dfaa
12 changed files with 231 additions and 96 deletions
|
@ -447,8 +447,8 @@ if INIT == "pause_menu" then
|
|||
-- require porting "FSTK" (at least the dialog API) from the mainmenu formspec
|
||||
-- API to the in-game formspec API.
|
||||
-- There's no reason you'd want to adjust mapgen noise parameter settings
|
||||
-- in-game (they only apply to new worlds), so there's no reason to implement
|
||||
-- this.
|
||||
-- in-game (they only apply to new worlds, hidden as [world_creation]),
|
||||
-- so there's no reason to implement this.
|
||||
local empty = function()
|
||||
return { get_formspec = function() return "", 0 end }
|
||||
end
|
||||
|
|
|
@ -111,6 +111,7 @@ local function load()
|
|||
requires = {
|
||||
keyboard_mouse = true,
|
||||
},
|
||||
context = "client",
|
||||
get_formspec = function(self, avail_w)
|
||||
local btn_w = math.min(avail_w, 3)
|
||||
return ("button[0,0;%f,0.8;btn_change_keys;%s]"):format(btn_w, fgettext("Controls")), 0.8
|
||||
|
@ -127,6 +128,7 @@ local function load()
|
|||
requires = {
|
||||
touchscreen = true,
|
||||
},
|
||||
context = "client",
|
||||
get_formspec = function(self, avail_w)
|
||||
local btn_w = math.min(avail_w, 6)
|
||||
return ("button[0,0;%f,0.8;btn_touch_layout;%s]"):format(btn_w, fgettext("Touchscreen layout")), 0.8
|
||||
|
@ -173,18 +175,24 @@ local function load()
|
|||
table.insert(content, idx, shadows_component)
|
||||
|
||||
idx = table.indexof(content, "enable_auto_exposure") + 1
|
||||
local setting_info = get_setting_info("enable_auto_exposure")
|
||||
local note = component_funcs.note(fgettext_ne("(The game will need to enable automatic exposure as well)"))
|
||||
note.requires = get_setting_info("enable_auto_exposure").requires
|
||||
note.requires = setting_info.requires
|
||||
note.context = setting_info.context
|
||||
table.insert(content, idx, note)
|
||||
|
||||
idx = table.indexof(content, "enable_bloom") + 1
|
||||
setting_info = get_setting_info("enable_bloom")
|
||||
note = component_funcs.note(fgettext_ne("(The game will need to enable bloom as well)"))
|
||||
note.requires = get_setting_info("enable_bloom").requires
|
||||
note.requires = setting_info.requires
|
||||
note.context = setting_info.context
|
||||
table.insert(content, idx, note)
|
||||
|
||||
idx = table.indexof(content, "enable_volumetric_lighting") + 1
|
||||
setting_info = get_setting_info("enable_volumetric_lighting")
|
||||
note = component_funcs.note(fgettext_ne("(The game will need to enable volumetric lighting as well)"))
|
||||
note.requires = get_setting_info("enable_volumetric_lighting").requires
|
||||
note.requires = setting_info.requires
|
||||
note.context = setting_info.context
|
||||
table.insert(content, idx, note)
|
||||
end
|
||||
|
||||
|
@ -362,7 +370,18 @@ local function update_filtered_pages(query)
|
|||
end
|
||||
|
||||
|
||||
local function check_requirements(name, requires)
|
||||
local shown_contexts = {
|
||||
common = true,
|
||||
client = true,
|
||||
server = INIT ~= "pause_menu" or core.is_internal_server(),
|
||||
world_creation = INIT ~= "pause_menu",
|
||||
}
|
||||
|
||||
local function check_requirements(name, requires, context)
|
||||
if context and not shown_contexts[context] then
|
||||
return false
|
||||
end
|
||||
|
||||
if requires == nil then
|
||||
return true
|
||||
end
|
||||
|
@ -423,11 +442,11 @@ function page_has_contents(page, actual_content)
|
|||
elseif type(item) == "string" then
|
||||
local setting = get_setting_info(item)
|
||||
assert(setting, "Unknown setting: " .. item)
|
||||
if check_requirements(setting.name, setting.requires) then
|
||||
if check_requirements(setting.name, setting.requires, setting.context) then
|
||||
return true
|
||||
end
|
||||
elseif item.get_formspec then
|
||||
if check_requirements(item.id, item.requires) then
|
||||
if check_requirements(item.id, item.requires, item.context) then
|
||||
return true
|
||||
end
|
||||
else
|
||||
|
@ -449,20 +468,22 @@ local function build_page_components(page)
|
|||
elseif item.heading then
|
||||
last_heading = item
|
||||
else
|
||||
local name, requires
|
||||
local name, requires, context
|
||||
if type(item) == "string" then
|
||||
local setting = get_setting_info(item)
|
||||
assert(setting, "Unknown setting: " .. item)
|
||||
name = setting.name
|
||||
requires = setting.requires
|
||||
context = setting.context
|
||||
elseif item.get_formspec then
|
||||
name = item.id
|
||||
requires = item.requires
|
||||
context = item.context
|
||||
else
|
||||
error("Unknown content in page: " .. dump(item))
|
||||
end
|
||||
|
||||
if check_requirements(name, requires) then
|
||||
if check_requirements(name, requires, context) then
|
||||
if last_heading then
|
||||
content[#content + 1] = last_heading
|
||||
last_heading = nil
|
||||
|
|
|
@ -40,12 +40,24 @@ local CHAR_CLASSES = {
|
|||
FLAGS = "[%w_%-%.,]",
|
||||
}
|
||||
|
||||
local valid_contexts = {common = true, client = true, server = true, world_creation = true}
|
||||
|
||||
local function check_context_annotation(context, force_context)
|
||||
if force_context then
|
||||
return "Context annotations are not allowed, context is always " .. force_context
|
||||
end
|
||||
if not valid_contexts[context] then
|
||||
return "Unknown context"
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function flags_to_table(flags)
|
||||
return flags:gsub("%s+", ""):split(",", true) -- Remove all spaces and split
|
||||
end
|
||||
|
||||
-- returns error message, or nil
|
||||
local function parse_setting_line(settings, line, read_all, base_level, allow_secure)
|
||||
local function parse_setting_line(settings, line, read_all, base_level, allow_secure, force_context)
|
||||
|
||||
-- strip carriage returns (CR, /r)
|
||||
line = line:gsub("\r", "")
|
||||
|
@ -69,9 +81,32 @@ local function parse_setting_line(settings, line, read_all, base_level, allow_se
|
|||
|
||||
-- category
|
||||
local stars, category = line:match("^%[([%*]*)([^%]]+)%]$")
|
||||
local category_context
|
||||
if not category then
|
||||
stars, category, category_context = line:match("^%[([%*]*)([^%]]+)%] %[([^%]]+)%]$")
|
||||
end
|
||||
if category then
|
||||
local category_level = stars:len() + base_level
|
||||
|
||||
if settings.current_context_level and
|
||||
category_level <= settings.current_context_level then
|
||||
-- The start of this category marks the end of the context annotation's scope.
|
||||
settings.current_context_level = nil
|
||||
settings.current_context = nil
|
||||
end
|
||||
|
||||
if category_context then
|
||||
local err = check_context_annotation(category_context, force_context)
|
||||
if err then
|
||||
return err
|
||||
end
|
||||
if settings.current_context_level then
|
||||
return "Category context annotations cannot be nested"
|
||||
end
|
||||
settings.current_context_level = category_level
|
||||
settings.current_context = category_context
|
||||
end
|
||||
|
||||
if settings.current_hide_level then
|
||||
if settings.current_hide_level < category_level then
|
||||
-- Skip this category, it's inside a hidden category.
|
||||
|
@ -102,7 +137,8 @@ local function parse_setting_line(settings, line, read_all, base_level, allow_se
|
|||
end
|
||||
|
||||
-- settings
|
||||
local first_part, name, readable_name, setting_type = line:match("^"
|
||||
local function make_pattern(include_context)
|
||||
return "^"
|
||||
-- this first capture group matches the whole first part,
|
||||
-- so we can later strip it from the rest of the line
|
||||
.. "("
|
||||
|
@ -110,9 +146,19 @@ local function parse_setting_line(settings, line, read_all, base_level, allow_se
|
|||
.. CHAR_CLASSES.SPACE .. "*"
|
||||
.. "%(([^%)]*)%)" -- readable name
|
||||
.. CHAR_CLASSES.SPACE .. "*"
|
||||
.. (include_context and (
|
||||
"%[([^%]]+)%]" -- context annotation
|
||||
.. CHAR_CLASSES.SPACE .. "*"
|
||||
) or "")
|
||||
.. "(" .. CHAR_CLASSES.VARIABLE .. "+)" -- type
|
||||
.. CHAR_CLASSES.SPACE .. "*"
|
||||
.. ")")
|
||||
.. ")"
|
||||
end
|
||||
local first_part, name, readable_name, setting_type = line:match(make_pattern(false))
|
||||
local setting_context
|
||||
if not first_part then
|
||||
first_part, name, readable_name, setting_context, setting_type = line:match(make_pattern(true))
|
||||
end
|
||||
|
||||
if not first_part then
|
||||
return "Invalid line"
|
||||
|
@ -122,6 +168,26 @@ local function parse_setting_line(settings, line, read_all, base_level, allow_se
|
|||
return "Tried to add \"secure.\" setting"
|
||||
end
|
||||
|
||||
if setting_context then
|
||||
local err = check_context_annotation(setting_context, force_context)
|
||||
if err then
|
||||
return err
|
||||
end
|
||||
end
|
||||
|
||||
local context
|
||||
if force_context then
|
||||
context = force_context
|
||||
else
|
||||
if setting_context then
|
||||
context = setting_context
|
||||
elseif settings.current_context_level then
|
||||
context = settings.current_context
|
||||
else
|
||||
return "Missing context annotation"
|
||||
end
|
||||
end
|
||||
|
||||
local requires = {}
|
||||
local last_line = #current_comment > 0 and current_comment[#current_comment]:trim()
|
||||
if last_line and last_line:lower():sub(1, 9) == "requires:" then
|
||||
|
@ -170,6 +236,7 @@ local function parse_setting_line(settings, line, read_all, base_level, allow_se
|
|||
min = min,
|
||||
max = max,
|
||||
requires = requires,
|
||||
context = context,
|
||||
comment = comment,
|
||||
})
|
||||
return
|
||||
|
@ -193,6 +260,7 @@ local function parse_setting_line(settings, line, read_all, base_level, allow_se
|
|||
type = setting_type,
|
||||
default = default,
|
||||
requires = requires,
|
||||
context = context,
|
||||
comment = comment,
|
||||
})
|
||||
return
|
||||
|
@ -245,6 +313,7 @@ local function parse_setting_line(settings, line, read_all, base_level, allow_se
|
|||
},
|
||||
values = values,
|
||||
requires = requires,
|
||||
context = context,
|
||||
comment = comment,
|
||||
noise_params = true,
|
||||
flags = flags_to_table("defaults,eased,absvalue")
|
||||
|
@ -263,6 +332,7 @@ local function parse_setting_line(settings, line, read_all, base_level, allow_se
|
|||
type = "bool",
|
||||
default = remaining_line,
|
||||
requires = requires,
|
||||
context = context,
|
||||
comment = comment,
|
||||
})
|
||||
return
|
||||
|
@ -290,6 +360,7 @@ local function parse_setting_line(settings, line, read_all, base_level, allow_se
|
|||
min = min,
|
||||
max = max,
|
||||
requires = requires,
|
||||
context = context,
|
||||
comment = comment,
|
||||
})
|
||||
return
|
||||
|
@ -313,6 +384,7 @@ local function parse_setting_line(settings, line, read_all, base_level, allow_se
|
|||
default = default,
|
||||
values = values:split(",", true),
|
||||
requires = requires,
|
||||
context = context,
|
||||
comment = comment,
|
||||
})
|
||||
return
|
||||
|
@ -331,6 +403,7 @@ local function parse_setting_line(settings, line, read_all, base_level, allow_se
|
|||
type = setting_type,
|
||||
default = default,
|
||||
requires = requires,
|
||||
context = context,
|
||||
comment = comment,
|
||||
})
|
||||
return
|
||||
|
@ -361,6 +434,7 @@ local function parse_setting_line(settings, line, read_all, base_level, allow_se
|
|||
default = default,
|
||||
possible = flags_to_table(possible),
|
||||
requires = requires,
|
||||
context = context,
|
||||
comment = comment,
|
||||
})
|
||||
return
|
||||
|
@ -369,14 +443,14 @@ local function parse_setting_line(settings, line, read_all, base_level, allow_se
|
|||
return "Invalid setting type \"" .. setting_type .. "\""
|
||||
end
|
||||
|
||||
local function parse_single_file(file, filepath, read_all, result, base_level, allow_secure)
|
||||
local function parse_single_file(file, filepath, read_all, result, base_level, allow_secure, force_context)
|
||||
-- store this helper variable in the table so it's easier to pass to parse_setting_line()
|
||||
result.current_comment = {}
|
||||
result.current_hide_level = nil
|
||||
|
||||
local line = file:read("*line")
|
||||
while line do
|
||||
local error_msg = parse_setting_line(result, line, read_all, base_level, allow_secure)
|
||||
local error_msg = parse_setting_line(result, line, read_all, base_level, allow_secure, force_context)
|
||||
if error_msg then
|
||||
core.log("error", error_msg .. " in " .. filepath .. " \"" .. line .. "\"")
|
||||
end
|
||||
|
@ -411,7 +485,8 @@ function settingtypes.parse_config_file(read_all, parse_mods)
|
|||
-- TODO: Support game/mod settings in the pause menu too
|
||||
-- Note that this will need to work different from how it's done in the
|
||||
-- mainmenu:
|
||||
-- * Only if in singleplayer / on local server, not on remote servers
|
||||
-- * ~~Only if in singleplayer / on local server, not on remote servers~~
|
||||
-- (done now: context annotations)
|
||||
-- * Only show settings for the active game and mods
|
||||
-- (add API function to get them, can return nil if on a remote server)
|
||||
-- (names are probably not enough, will need paths for uniqueness)
|
||||
|
@ -441,7 +516,7 @@ function settingtypes.parse_config_file(read_all, parse_mods)
|
|||
type = "category",
|
||||
})
|
||||
|
||||
parse_single_file(file, path, read_all, settings, 2, false)
|
||||
parse_single_file(file, path, read_all, settings, 2, false, "server")
|
||||
|
||||
file:close()
|
||||
end
|
||||
|
@ -474,7 +549,7 @@ function settingtypes.parse_config_file(read_all, parse_mods)
|
|||
type = "category",
|
||||
})
|
||||
|
||||
parse_single_file(file, path, read_all, settings, 2, false)
|
||||
parse_single_file(file, path, read_all, settings, 2, false, "server")
|
||||
|
||||
file:close()
|
||||
end
|
||||
|
@ -505,7 +580,7 @@ function settingtypes.parse_config_file(read_all, parse_mods)
|
|||
type = "category",
|
||||
})
|
||||
|
||||
parse_single_file(file, path, read_all, settings, 2, false)
|
||||
parse_single_file(file, path, read_all, settings, 2, false, "client")
|
||||
|
||||
file:close()
|
||||
end
|
||||
|
|
|
@ -84,6 +84,7 @@ return {
|
|||
requires = {
|
||||
opengl = true,
|
||||
},
|
||||
context = "client",
|
||||
get_formspec = function(self, avail_w)
|
||||
local labels = table.copy(shadow_levels_labels)
|
||||
local idx = detect_mapping_idx()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue