Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add server/client annotations to settingtypes.txt and use them #15756

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions builtin/common/settings/components.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
37 changes: 29 additions & 8 deletions builtin/common/settings/dlg_settings.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -174,18 +176,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

Expand Down Expand Up @@ -352,7 +360,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_local_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
Expand Down Expand Up @@ -411,11 +430,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
Expand All @@ -437,20 +456,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
Expand Down
93 changes: 84 additions & 9 deletions builtin/common/settings/settingtypes.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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", "")
Expand All @@ -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.
Expand Down Expand Up @@ -102,17 +137,28 @@ 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
.. "("
.. "([" .. CHAR_CLASSES.VARIABLE .. "+)" -- variable name
.. 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"
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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")
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions builtin/common/settings/shadows_component.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Loading
Loading