mirror of
https://github.com/luanti-org/luanti.git
synced 2025-06-27 16:36:03 +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()
|
||||
|
|
|
@ -2,9 +2,27 @@
|
|||
#
|
||||
# General format:
|
||||
# name (Readable name) type type_args
|
||||
# name (Readable name) [context] type type_args
|
||||
#
|
||||
# Note that the parts are separated by exactly one space
|
||||
#
|
||||
# `context` (optional) is used to document where the setting is read. It can be:
|
||||
# - common: Read by both client and server.
|
||||
# - client: Read by the client.
|
||||
# (Includes settings read by the mainmenu.)
|
||||
# - server: Read by the server.
|
||||
# - world_creation: Read at world creation, thus only applied to new worlds.
|
||||
# (Worlds are commonly created in the mainmenu (part of the client), but
|
||||
# world creation is conceptually a server-side thing...)
|
||||
# If not specified, the value is inherited from the context value of the containing
|
||||
# category instead.
|
||||
# For the builtin/settingtypes.txt file, every setting needs to have a context defined,
|
||||
# either via a category containing it or via the setting itself. In game/mod-provided
|
||||
# settingtypes.txt files, context annotations are invalid.
|
||||
# Note: For context annotations, it's irrelevant whether changes to a setting
|
||||
# after startup/game-join will be read. A separate mechanism for declaring that
|
||||
# is needed.
|
||||
#
|
||||
# `type` can be:
|
||||
# - int
|
||||
# - string
|
||||
|
@ -77,6 +95,8 @@
|
|||
# Sections are marked by a single line in the format: [Section Name]
|
||||
# Sub-section are marked by adding * in front of the section name: [*Sub-section]
|
||||
# Sub-sub-sections have two * etc.
|
||||
# A context (see above) can be specified optionally: [Section Name] [context]
|
||||
# Context annotations on categories cannot be nested.
|
||||
# There shouldn't be too many settings per category.
|
||||
#
|
||||
# The top-level categories "Advanced", "Client and Server" and "Mapgen" are
|
||||
|
@ -84,7 +104,7 @@
|
|||
# They contain settings not intended for the "average user".
|
||||
|
||||
|
||||
[Controls]
|
||||
[Controls] [client]
|
||||
|
||||
[*General]
|
||||
|
||||
|
@ -224,7 +244,7 @@ fixed_virtual_joystick (Fixed virtual joystick) bool false
|
|||
# Requires: touchscreen
|
||||
virtual_joystick_triggers_aux1 (Virtual joystick triggers Aux1 button) bool false
|
||||
|
||||
[Graphics and Audio]
|
||||
[Graphics and Audio] [client]
|
||||
|
||||
[*Graphics]
|
||||
|
||||
|
@ -762,13 +782,13 @@ contentdb_max_concurrent_downloads (ContentDB Max Concurrent Downloads) int 3 1
|
|||
|
||||
[Client and Server]
|
||||
|
||||
[*Client]
|
||||
[*Client] [client]
|
||||
|
||||
# Save the map received by the client on disk.
|
||||
enable_local_map_saving (Saving map received from server) bool false
|
||||
|
||||
# URL to the server list displayed in the Multiplayer Tab.
|
||||
serverlist_url (Serverlist URL) string https://servers.luanti.org
|
||||
serverlist_url (Serverlist URL) [common] string https://servers.luanti.org
|
||||
|
||||
# If enabled, server account registration is separate from login in the UI.
|
||||
# If disabled, connecting to a server will automatically register a new account.
|
||||
|
@ -778,7 +798,7 @@ enable_split_login_register (Enable split login/register) bool true
|
|||
# If this is empty the engine will never check for updates.
|
||||
update_information_url (Update information URL) string https://www.luanti.org/release_info.json
|
||||
|
||||
[*Server]
|
||||
[*Server] [server]
|
||||
|
||||
# Name of the player.
|
||||
# When running a server, a client connecting with this name is admin.
|
||||
|
@ -806,7 +826,7 @@ server_announce (Announce server) bool false
|
|||
server_announce_send_players (Send player names to the server list) bool true
|
||||
|
||||
# Announce to this serverlist.
|
||||
serverlist_url (Serverlist URL) string https://servers.luanti.org
|
||||
serverlist_url (Serverlist URL) [common] string https://servers.luanti.org
|
||||
|
||||
# Message of the day displayed to players connecting.
|
||||
motd (Message of the day) string
|
||||
|
@ -852,7 +872,7 @@ remote_media (Remote media) string
|
|||
# Requires: enable_ipv6
|
||||
ipv6_server (IPv6 server) bool true
|
||||
|
||||
[*Server Security]
|
||||
[*Server Security] [server]
|
||||
|
||||
# New users need to input this password.
|
||||
default_password (Default password) string
|
||||
|
@ -912,7 +932,7 @@ chat_message_limit_per_10sec (Chat message count limit) float 8.0 1.0
|
|||
# Kick players who sent more than X messages per 10 seconds.
|
||||
chat_message_limit_trigger_kick (Chat message kick threshold) int 50 1 65535
|
||||
|
||||
[*Server Gameplay]
|
||||
[*Server Gameplay] [server]
|
||||
|
||||
# Controls length of day/night cycle.
|
||||
# Examples:
|
||||
|
@ -920,7 +940,7 @@ chat_message_limit_trigger_kick (Chat message kick threshold) int 50 1 65535
|
|||
time_speed (Time speed) int 72 0
|
||||
|
||||
# Time of day when a new world is started, in millihours (0-23999).
|
||||
world_start_time (World start time) int 6125 0 23999
|
||||
world_start_time (World start time) [world_creation] int 6125 0 23999
|
||||
|
||||
# Time in seconds for item entity (dropped items) to live.
|
||||
# Setting it to -1 disables the feature.
|
||||
|
@ -975,7 +995,7 @@ movement_liquid_sink (Liquid sinking) float 10.0
|
|||
movement_gravity (Gravity) float 9.81
|
||||
|
||||
|
||||
[Mapgen]
|
||||
[Mapgen] [world_creation]
|
||||
|
||||
# A chosen map seed for a new map, leave empty for random.
|
||||
# Will be overridden when creating a new world in the main menu.
|
||||
|
@ -991,7 +1011,7 @@ mg_name (Mapgen name) enum v7 v7,valleys,carpathian,v5,flat,fractal,singlenode,v
|
|||
water_level (Water level) int 1 -31000 31000
|
||||
|
||||
# From how far blocks are generated for clients, stated in mapblocks (16 nodes).
|
||||
max_block_generate_distance (Max block generate distance) int 10 1 32767
|
||||
max_block_generate_distance (Max block generate distance) [server] int 10 1 32767
|
||||
|
||||
# Limit of map generation, in nodes, in all 6 directions from (0, 0, 0).
|
||||
# Only mapchunks completely within the mapgen limit are generated.
|
||||
|
@ -1704,12 +1724,12 @@ mgvalleys_np_dungeons (Dungeon noise) noise_params_3d 0.9, 0.5, (500, 500, 500),
|
|||
|
||||
# Enable Lua modding support on client.
|
||||
# This support is experimental and API can change.
|
||||
enable_client_modding (Client modding) bool false
|
||||
enable_client_modding (Client modding) [client] bool false
|
||||
|
||||
# Replaces the default main menu with a custom one.
|
||||
main_menu_script (Main menu script) string
|
||||
main_menu_script (Main menu script) [client] string
|
||||
|
||||
[**Mod Security]
|
||||
[**Mod Security] [server]
|
||||
|
||||
# Prevent mods from doing insecure things like running shell commands.
|
||||
secure.enable_security (Enable mod security) bool true
|
||||
|
@ -1733,33 +1753,33 @@ secure.http_mods (HTTP mods) string
|
|||
# - info
|
||||
# - verbose
|
||||
# - trace
|
||||
debug_log_level (Debug log level) enum action ,none,error,warning,action,info,verbose,trace
|
||||
debug_log_level (Debug log level) [common] enum action ,none,error,warning,action,info,verbose,trace
|
||||
|
||||
# If the file size of debug.txt exceeds the number of megabytes specified in
|
||||
# this setting when it is opened, the file is moved to debug.txt.1,
|
||||
# deleting an older debug.txt.1 if it exists.
|
||||
# debug.txt is only moved if this setting is positive.
|
||||
debug_log_size_max (Debug log file size threshold) int 50 1
|
||||
debug_log_size_max (Debug log file size threshold) [common] int 50 1
|
||||
|
||||
# Minimal level of logging to be written to chat.
|
||||
chat_log_level (Chat log level) enum error ,none,error,warning,action,info,verbose,trace
|
||||
chat_log_level (Chat log level) [client] enum error ,none,error,warning,action,info,verbose,trace
|
||||
|
||||
# Handling for deprecated Lua API calls:
|
||||
# - none: Do not log deprecated calls
|
||||
# - log: mimic and log backtrace of deprecated call (default).
|
||||
# - error: abort on usage of deprecated call (suggested for mod developers).
|
||||
deprecated_lua_api_handling (Deprecated Lua API handling) enum log none,log,error
|
||||
deprecated_lua_api_handling (Deprecated Lua API handling) [common] enum log none,log,error
|
||||
|
||||
# Enable random user input (only used for testing).
|
||||
random_input (Random input) bool false
|
||||
random_input (Random input) [client] bool false
|
||||
|
||||
# Enable random mod loading (mainly used for testing).
|
||||
random_mod_load_order (Random mod load order) bool false
|
||||
random_mod_load_order (Random mod load order) [server] bool false
|
||||
|
||||
# Enable mod channels support.
|
||||
enable_mod_channels (Mod channels) bool false
|
||||
enable_mod_channels (Mod channels) [server] bool false
|
||||
|
||||
[**Mod Profiler]
|
||||
[**Mod Profiler] [server]
|
||||
|
||||
# Load the game profiler to collect game profiling data.
|
||||
# Provides a /profiler command to access the compiled profile.
|
||||
|
@ -1799,7 +1819,7 @@ instrument.builtin (Builtin) bool false
|
|||
# * Instrument the sampler being used to update the statistics.
|
||||
instrument.profiler (Profiler) bool false
|
||||
|
||||
[**Engine Profiler]
|
||||
[**Engine Profiler] [common]
|
||||
|
||||
# Print the engine's profiling data in regular intervals (in seconds).
|
||||
# 0 = disable. Useful for developers.
|
||||
|
@ -1808,7 +1828,7 @@ profiler_print_interval (Engine profiling data print interval) int 0 0
|
|||
|
||||
[*Advanced]
|
||||
|
||||
[**Graphics]
|
||||
[**Graphics] [client]
|
||||
|
||||
# Enables debug and error-checking in the OpenGL driver.
|
||||
opengl_debug (OpenGL debug) bool false
|
||||
|
@ -1912,12 +1932,12 @@ shadow_update_frames (Map shadows update frames) int 16 1 32
|
|||
# Requires: enable_post_processing, enable_bloom
|
||||
enable_bloom_debug (Enable Bloom Debug) bool false
|
||||
|
||||
[**Sound]
|
||||
[**Sound] [client]
|
||||
# Comma-separated list of AL and ALC extensions that should not be used.
|
||||
# Useful for testing. See al_extensions.[h,cpp] for details.
|
||||
sound_extensions_blacklist (Sound Extensions Blacklist) string
|
||||
|
||||
[**Font]
|
||||
[**Font] [client]
|
||||
|
||||
font_bold (Font bold by default) bool false
|
||||
|
||||
|
@ -1967,7 +1987,7 @@ mono_font_path_bold_italic (Bold and italic monospace font path) filepath fonts/
|
|||
# This font will be used for certain languages or if the default font is unavailable.
|
||||
fallback_font_path (Fallback font path) filepath fonts/DroidSansFallbackFull.ttf
|
||||
|
||||
[**Lighting]
|
||||
[**Lighting] [client]
|
||||
|
||||
# Gradient of light curve at minimum light level.
|
||||
# Controls the contrast of the lowest light levels.
|
||||
|
@ -1995,47 +2015,47 @@ lighting_boost_spread (Light curve boost spread) float 0.2 0.0 0.4
|
|||
|
||||
# Enable IPv6 support (for both client and server).
|
||||
# Required for IPv6 connections to work at all.
|
||||
enable_ipv6 (IPv6) bool true
|
||||
enable_ipv6 (IPv6) [common] bool true
|
||||
|
||||
# Prometheus listener address.
|
||||
# If Luanti is compiled with ENABLE_PROMETHEUS option enabled,
|
||||
# enable metrics listener for Prometheus on that address.
|
||||
# Metrics can be fetched on http://127.0.0.1:30000/metrics
|
||||
prometheus_listener_address (Prometheus listener address) string 127.0.0.1:30000
|
||||
prometheus_listener_address (Prometheus listener address) [server] string 127.0.0.1:30000
|
||||
|
||||
# Maximum size of the outgoing chat queue.
|
||||
# Maximum size of the client's outgoing chat queue.
|
||||
# 0 to disable queueing and -1 to make the queue size unlimited.
|
||||
max_out_chat_queue_size (Maximum size of the outgoing chat queue) int 20 -1 32767
|
||||
max_out_chat_queue_size (Maximum size of the client's outgoing chat queue) [client] int 20 -1 32767
|
||||
|
||||
# Timeout for client to remove unused map data from memory, in seconds.
|
||||
client_unload_unused_data_timeout (Mapblock unload timeout) float 600.0 0.0
|
||||
client_unload_unused_data_timeout (Mapblock unload timeout) [client] float 600.0 0.0
|
||||
|
||||
# Maximum number of mapblocks for client to be kept in memory.
|
||||
# Note that there is an internal dynamic minimum number of blocks that
|
||||
# won't be deleted, depending on the current view range.
|
||||
# Set to -1 for no limit.
|
||||
client_mapblock_limit (Mapblock limit) int 7500 -1 2147483647
|
||||
client_mapblock_limit (Mapblock limit) [client] int 7500 -1 2147483647
|
||||
|
||||
# Maximum number of blocks that are simultaneously sent per client.
|
||||
# The maximum total count is calculated dynamically:
|
||||
# max_total = ceil((#clients + max_users) * per_client / 4)
|
||||
max_simultaneous_block_sends_per_client (Maximum simultaneous block sends per client) int 40 1 4294967295
|
||||
max_simultaneous_block_sends_per_client (Maximum simultaneous block sends per client) [server] int 40 1 4294967295
|
||||
|
||||
# To reduce lag, block transfers are slowed down when a player is building something.
|
||||
# This determines how long they are slowed down after placing or removing a node.
|
||||
full_block_send_enable_min_time_from_building (Delay in sending blocks after building) float 2.0 0.0
|
||||
full_block_send_enable_min_time_from_building (Delay in sending blocks after building) [server] float 2.0 0.0
|
||||
|
||||
# Maximum number of packets sent per send step in the low-level networking code.
|
||||
# You generally don't need to change this, however busy servers may benefit from a higher number.
|
||||
max_packets_per_iteration (Max. packets per iteration) int 1024 1 65535
|
||||
max_packets_per_iteration (Max. packets per iteration) [common] int 1024 1 65535
|
||||
|
||||
# Compression level to use when sending mapblocks to the client.
|
||||
# -1 - use default compression level
|
||||
# 0 - least compression, fastest
|
||||
# 9 - best compression, slowest
|
||||
map_compression_level_net (Map Compression Level for Network Transfer) int -1 -1 9
|
||||
map_compression_level_net (Map Compression Level for Network Transfer) [server] int -1 -1 9
|
||||
|
||||
[**Server]
|
||||
[**Server] [server]
|
||||
|
||||
# Format of player chat messages. The following strings are valid placeholders:
|
||||
# @name, @message, @timestamp (optional)
|
||||
|
@ -2055,7 +2075,7 @@ kick_msg_crash (Crash message) string This server has experienced an internal er
|
|||
# Set this to true if your server is set up to restart automatically.
|
||||
ask_reconnect_on_crash (Ask to reconnect after crash) bool false
|
||||
|
||||
[**Server/Env Performance]
|
||||
[**Server/Env Performance] [server]
|
||||
|
||||
# Length of a server tick (the interval at which everything is generally updated),
|
||||
# stated in seconds.
|
||||
|
@ -2148,7 +2168,7 @@ server_side_occlusion_culling (Server-side occlusion culling) bool true
|
|||
# Stated in MapBlocks (16 nodes).
|
||||
block_cull_optimize_distance (Block cull optimize distance) int 25 2 2047
|
||||
|
||||
[**Mapgen]
|
||||
[**Mapgen] [server]
|
||||
|
||||
# Size of mapchunks generated by mapgen, stated in mapblocks (16 nodes).
|
||||
# WARNING: There is no benefit, and there are several dangers, in
|
||||
|
@ -2156,7 +2176,7 @@ block_cull_optimize_distance (Block cull optimize distance) int 25 2 2047
|
|||
# Reducing this value increases cave and dungeon density.
|
||||
# Altering this value is for special usage, leaving it unchanged is
|
||||
# recommended.
|
||||
chunksize (Chunk size) int 5 1 10
|
||||
chunksize (Chunk size) [world_creation] int 5 1 10
|
||||
|
||||
# Dump the mapgen debug information.
|
||||
enable_mapgen_debug_info (Mapgen debug) bool false
|
||||
|
@ -2184,7 +2204,7 @@ emergequeue_limit_generate (Per-player limit of queued blocks to generate) int 1
|
|||
# 'on_generated'. For many users the optimum setting may be '1'.
|
||||
num_emerge_threads (Number of emerge threads) int 1 0 32767
|
||||
|
||||
[**cURL]
|
||||
[**cURL] [common]
|
||||
|
||||
# Maximum time an interactive request (e.g. server list fetch) may take, stated in milliseconds.
|
||||
curl_timeout (cURL interactive timeout) int 20000 1000 2147483647
|
||||
|
@ -2202,48 +2222,48 @@ curl_file_download_timeout (cURL file download timeout) int 300000 5000 21474836
|
|||
[**Miscellaneous]
|
||||
|
||||
# Clickable weblinks (middle-click or Ctrl+left-click) enabled in chat console output.
|
||||
clickable_chat_weblinks (Chat weblinks) bool true
|
||||
clickable_chat_weblinks (Chat weblinks) [client] bool true
|
||||
|
||||
# If enabled, invalid world data won't cause the server to shut down.
|
||||
# Only enable this if you know what you are doing.
|
||||
ignore_world_load_errors (Ignore world errors) bool false
|
||||
ignore_world_load_errors (Ignore world errors) [server] bool false
|
||||
|
||||
# Adjust the detected display density, used for scaling UI elements.
|
||||
display_density_factor (Display Density Scaling Factor) float 1 0.5 5.0
|
||||
display_density_factor (Display Density Scaling Factor) [client] float 1 0.5 5.0
|
||||
|
||||
# Windows systems only: Start Luanti with the command line window in the background.
|
||||
# Contains the same information as the file debug.txt (default name).
|
||||
enable_console (Enable console window) bool false
|
||||
enable_console (Enable console window) [common] bool false
|
||||
|
||||
# Number of extra blocks that can be loaded by /clearobjects at once.
|
||||
# This is a trade-off between SQLite transaction overhead and
|
||||
# memory consumption (4096=100MB, as a rule of thumb).
|
||||
max_clearobjects_extra_loaded_blocks (Max. clearobjects extra blocks) int 4096 0 4294967295
|
||||
max_clearobjects_extra_loaded_blocks (Max. clearobjects extra blocks) [server] int 4096 0 4294967295
|
||||
|
||||
# World directory (everything in the world is stored here).
|
||||
# Not needed if starting from the main menu.
|
||||
map-dir (Map directory) path
|
||||
map-dir (Map directory) [server] path
|
||||
|
||||
# See https://www.sqlite.org/pragma.html#pragma_synchronous
|
||||
sqlite_synchronous (Synchronous SQLite) enum 2 0,1,2
|
||||
sqlite_synchronous (Synchronous SQLite) [server] enum 2 0,1,2
|
||||
|
||||
# Compression level to use when saving mapblocks to disk.
|
||||
# -1 - use default compression level
|
||||
# 0 - least compression, fastest
|
||||
# 9 - best compression, slowest
|
||||
map_compression_level_disk (Map Compression Level for Disk Storage) int -1 -1 9
|
||||
map_compression_level_disk (Map Compression Level for Disk Storage) [server] int -1 -1 9
|
||||
|
||||
# Enable usage of remote media server (if provided by server).
|
||||
# Remote servers offer a significantly faster way to download media (e.g. textures)
|
||||
# when connecting to the server.
|
||||
enable_remote_media_server (Connect to external media server) bool true
|
||||
enable_remote_media_server (Connect to external media server) [client] bool true
|
||||
|
||||
# File in client/serverlist/ that contains your favorite servers displayed in the
|
||||
# Multiplayer Tab.
|
||||
serverlist_file (Serverlist file) string favoriteservers.json
|
||||
serverlist_file (Serverlist file) [client] string favoriteservers.json
|
||||
|
||||
|
||||
[*Gamepads]
|
||||
[*Gamepads] [client]
|
||||
|
||||
# Enable joysticks. Requires a restart to take effect
|
||||
enable_joysticks (Enable joysticks) bool false
|
||||
|
@ -2266,7 +2286,7 @@ joystick_deadzone (Joystick dead zone) int 2048 0 65535
|
|||
joystick_frustum_sensitivity (Joystick frustum sensitivity) float 170.0 0.001
|
||||
|
||||
|
||||
[*Hide: Temporary Settings]
|
||||
[*Hide: Temporary Settings] [common]
|
||||
|
||||
# Path to texture directory. All textures are first searched from here.
|
||||
texture_path (Texture path) path
|
||||
|
|
|
@ -367,8 +367,7 @@ Client::~Client()
|
|||
g_fontengine->clearMediaFonts();
|
||||
}
|
||||
|
||||
void Client::connect(const Address &address, const std::string &address_name,
|
||||
bool is_local_server)
|
||||
void Client::connect(const Address &address, const std::string &address_name)
|
||||
{
|
||||
if (m_con) {
|
||||
// can't do this if the connection has entered auth phase
|
||||
|
@ -389,7 +388,7 @@ void Client::connect(const Address &address, const std::string &address_name,
|
|||
|
||||
m_con->Connect(address);
|
||||
|
||||
initLocalMapSaving(address, m_address_name, is_local_server);
|
||||
initLocalMapSaving(address, m_address_name);
|
||||
}
|
||||
|
||||
void Client::step(float dtime)
|
||||
|
@ -917,11 +916,9 @@ void Client::request_media(const std::vector<std::string> &file_requests)
|
|||
<< pkt.getSize() << ")" << std::endl;
|
||||
}
|
||||
|
||||
void Client::initLocalMapSaving(const Address &address,
|
||||
const std::string &hostname,
|
||||
bool is_local_server)
|
||||
void Client::initLocalMapSaving(const Address &address, const std::string &hostname)
|
||||
{
|
||||
if (!g_settings->getBool("enable_local_map_saving") || is_local_server) {
|
||||
if (!g_settings->getBool("enable_local_map_saving") || m_internal_server) {
|
||||
return;
|
||||
}
|
||||
if (m_localdb) {
|
||||
|
|
|
@ -140,8 +140,7 @@ public:
|
|||
|
||||
bool isShutdown();
|
||||
|
||||
void connect(const Address &address, const std::string &address_name,
|
||||
bool is_local_server);
|
||||
void connect(const Address &address, const std::string &address_name);
|
||||
|
||||
/*
|
||||
Stuff that references the environment is valid only as
|
||||
|
@ -338,8 +337,17 @@ public:
|
|||
u16 getProtoVersion() const
|
||||
{ return m_proto_ver; }
|
||||
|
||||
// Whether the server is in "simple singleplayer mode".
|
||||
// This implies "m_internal_server = true".
|
||||
bool m_simple_singleplayer_mode;
|
||||
|
||||
// Whether the server is hosted by the same Luanti instance and singletons
|
||||
// like g_settings are shared between client and server.
|
||||
//
|
||||
// This is intentionally *not* true if we're just connecting to a localhost
|
||||
// server hosted by a different Luanti instance.
|
||||
bool m_internal_server;
|
||||
|
||||
float mediaReceiveProgress();
|
||||
|
||||
void drawLoadScreen(const std::wstring &text, float dtime, int percent);
|
||||
|
@ -441,9 +449,7 @@ private:
|
|||
void peerAdded(con::IPeer *peer) override;
|
||||
void deletingPeer(con::IPeer *peer, bool timeout) override;
|
||||
|
||||
void initLocalMapSaving(const Address &address,
|
||||
const std::string &hostname,
|
||||
bool is_local_server);
|
||||
void initLocalMapSaving(const Address &address, const std::string &hostname);
|
||||
|
||||
void ReceiveAll();
|
||||
|
||||
|
|
|
@ -508,7 +508,7 @@ protected:
|
|||
bool init(const std::string &map_dir, const std::string &address,
|
||||
u16 port, const SubgameSpec &gamespec);
|
||||
bool initSound();
|
||||
bool createSingleplayerServer(const std::string &map_dir,
|
||||
bool createServer(const std::string &map_dir,
|
||||
const SubgameSpec &gamespec, u16 port);
|
||||
void copyServerClientCache();
|
||||
|
||||
|
@ -908,7 +908,6 @@ bool Game::startup(bool *kill,
|
|||
|
||||
g_client_translations->clear();
|
||||
|
||||
// address can change if simple_singleplayer_mode
|
||||
if (!init(start_data.world_spec.path, start_data.address,
|
||||
start_data.socket_port, start_data.game_spec))
|
||||
return false;
|
||||
|
@ -1138,7 +1137,7 @@ bool Game::init(
|
|||
|
||||
// Create a server if not connecting to an existing one
|
||||
if (address.empty()) {
|
||||
if (!createSingleplayerServer(map_dir, gamespec, port))
|
||||
if (!createServer(map_dir, gamespec, port))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1173,7 +1172,7 @@ bool Game::initSound()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Game::createSingleplayerServer(const std::string &map_dir,
|
||||
bool Game::createServer(const std::string &map_dir,
|
||||
const SubgameSpec &gamespec, u16 port)
|
||||
{
|
||||
showOverlayMessage(N_("Creating server..."), 0, 5);
|
||||
|
@ -1389,7 +1388,6 @@ bool Game::connectToServer(const GameStartData &start_data,
|
|||
{
|
||||
*connect_ok = false; // Let's not be overly optimistic
|
||||
*connection_aborted = false;
|
||||
bool local_server_mode = false;
|
||||
const auto &address_name = start_data.address;
|
||||
|
||||
showOverlayMessage(N_("Resolving address..."), 0, 15);
|
||||
|
@ -1409,7 +1407,6 @@ bool Game::connectToServer(const GameStartData &start_data,
|
|||
} else {
|
||||
connect_address.setAddress(127, 0, 0, 1);
|
||||
}
|
||||
local_server_mode = true;
|
||||
}
|
||||
} catch (ResolveError &e) {
|
||||
*error_message = fmtgettext("Couldn't resolve address: %s", e.what());
|
||||
|
@ -1455,13 +1452,13 @@ bool Game::connectToServer(const GameStartData &start_data,
|
|||
|
||||
client->migrateModStorage();
|
||||
client->m_simple_singleplayer_mode = simple_singleplayer_mode;
|
||||
client->m_internal_server = !!server;
|
||||
|
||||
/*
|
||||
Wait for server to accept connection
|
||||
*/
|
||||
|
||||
client->connect(connect_address, address_name,
|
||||
simple_singleplayer_mode || local_server_mode);
|
||||
client->connect(connect_address, address_name);
|
||||
|
||||
try {
|
||||
input->clear();
|
||||
|
@ -1508,12 +1505,11 @@ bool Game::connectToServer(const GameStartData &start_data,
|
|||
}
|
||||
|
||||
wait_time += dtime;
|
||||
if (local_server_mode) {
|
||||
if (server) {
|
||||
// never time out
|
||||
} else if (wait_time > GAME_FALLBACK_TIMEOUT && !did_fallback) {
|
||||
if (!client->hasServerReplied() && fallback_address.isValid()) {
|
||||
client->connect(fallback_address, address_name,
|
||||
simple_singleplayer_mode || local_server_mode);
|
||||
client->connect(fallback_address, address_name);
|
||||
}
|
||||
did_fallback = true;
|
||||
} else if (wait_time > GAME_CONNECTION_TIMEOUT) {
|
||||
|
|
|
@ -25,6 +25,7 @@ enum class ELoginRegister {
|
|||
};
|
||||
|
||||
// Information processed by main menu
|
||||
// TODO: unify with MainMenuData
|
||||
struct GameStartData : GameParams
|
||||
{
|
||||
GameStartData() = default;
|
||||
|
@ -33,7 +34,11 @@ struct GameStartData : GameParams
|
|||
|
||||
std::string name;
|
||||
std::string password;
|
||||
// If empty, we're hosting a server.
|
||||
// This may or may not be in "simple singleplayer mode".
|
||||
std::string address;
|
||||
// If true, we're hosting a server and are *not* in "simple singleplayer
|
||||
// mode".
|
||||
bool local_server;
|
||||
|
||||
ELoginRegister allow_login_or_register = ELoginRegister::Any;
|
||||
|
|
|
@ -16,10 +16,13 @@ struct MainMenuDataForScript {
|
|||
std::string errormessage = "";
|
||||
};
|
||||
|
||||
// TODO: unify with GameStartData
|
||||
struct MainMenuData {
|
||||
// Client options
|
||||
std::string servername;
|
||||
std::string serverdescription;
|
||||
// If empty, we're hosting a server.
|
||||
// This may or may not be in "simple singleplayer mode".
|
||||
std::string address;
|
||||
std::string port;
|
||||
std::string name;
|
||||
|
@ -29,6 +32,7 @@ struct MainMenuData {
|
|||
|
||||
// Server options
|
||||
int selected_world = 0;
|
||||
// If true, we're hosting a server and *are* in "simple singleplayer mode".
|
||||
bool simple_singleplayer_mode = false;
|
||||
|
||||
// Data to be passed to the script
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "l_pause_menu.h"
|
||||
#include "gui/mainmenumanager.h"
|
||||
#include "lua_api/l_internal.h"
|
||||
#include "client/client.h"
|
||||
|
||||
|
||||
int ModApiPauseMenu::l_show_keys_menu(lua_State *L)
|
||||
|
@ -21,8 +22,16 @@ int ModApiPauseMenu::l_show_touchscreen_layout(lua_State *L)
|
|||
}
|
||||
|
||||
|
||||
int ModApiPauseMenu::l_is_internal_server(lua_State *L)
|
||||
{
|
||||
lua_pushboolean(L, getClient(L)->m_internal_server);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void ModApiPauseMenu::Initialize(lua_State *L, int top)
|
||||
{
|
||||
API_FCT(show_keys_menu);
|
||||
API_FCT(show_touchscreen_layout);
|
||||
API_FCT(is_internal_server);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ class ModApiPauseMenu: public ModApiBase
|
|||
private:
|
||||
static int l_show_keys_menu(lua_State *L);
|
||||
static int l_show_touchscreen_layout(lua_State *L);
|
||||
static int l_is_internal_server(lua_State *L);
|
||||
|
||||
public:
|
||||
static void Initialize(lua_State *L, int top);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue