Merge remote-tracking branch 'minetest/master'

master
Brandon 2017-05-29 20:02:46 -05:00
commit 811c22d1d6
317 changed files with 57712 additions and 23337 deletions

2
.gitignore vendored
View File

@ -43,6 +43,8 @@ gtags.files
!/mods/minetest/mods_here.txt !/mods/minetest/mods_here.txt
/worlds /worlds
/world/ /world/
/clientmods/mods.conf
/client/mod_storage/
## Configuration/log files ## Configuration/log files
minetest.conf minetest.conf

View File

@ -22,7 +22,7 @@ variables:
- make install - make install
artifacts: artifacts:
when: on_success when: on_success
expire_in: 14 day expire_in: 1h
paths: paths:
- artifact/* - artifact/*

View File

@ -26,6 +26,11 @@ elseif(DEVELOPMENT_BUILD)
set(VERSION_STRING "${VERSION_STRING}-dev") set(VERSION_STRING "${VERSION_STRING}-dev")
endif() endif()
if (CMAKE_BUILD_TYPE STREQUAL Debug)
# Append "-debug" to version string
set(VERSION_STRING "${VERSION_STRING}-debug")
endif()
message(STATUS "*** Will build version ${VERSION_STRING} ***") message(STATUS "*** Will build version ${VERSION_STRING} ***")

View File

@ -25,7 +25,6 @@ If you are planning to start some significant coding, you would benefit from ask
- Have a title which begins with a capital letter - Have a title which begins with a capital letter
- Be descriptive. (e.g. no `Update init.lua` or `Fix a problem`) - Be descriptive. (e.g. no `Update init.lua` or `Fix a problem`)
- Have a first line with less than *80 characters* and have a second line that is *empty* - Have a first line with less than *80 characters* and have a second line that is *empty*
- Do **not** [sign your commits](https://git-scm.com/book/uz/v2/Git-Tools-Signing-Your-Work), as Minetest offers automatically built ppas over launchpad and it [would break](https://bugs.launchpad.net/bzr-git/+bug/1084403) if there were signed commits in master
4. Once you are happy with your changes, submit a pull request. 4. Once you are happy with your changes, submit a pull request.
- Open the [pull-request form](https://github.com/minetest/minetest/pull/new/master) - Open the [pull-request form](https://github.com/minetest/minetest/pull/new/master)

View File

@ -206,7 +206,7 @@ IRRLICHT_LIBRARY - Path to libIrrlicht.a/libIrrlicht.so/libIrrlic
LEVELDB_INCLUDE_DIR - Only when building with LevelDB; directory that contains db.h LEVELDB_INCLUDE_DIR - Only when building with LevelDB; directory that contains db.h
LEVELDB_LIBRARY - Only when building with LevelDB; path to libleveldb.a/libleveldb.so/libleveldb.dll.a LEVELDB_LIBRARY - Only when building with LevelDB; path to libleveldb.a/libleveldb.so/libleveldb.dll.a
LEVELDB_DLL - Only when building with LevelDB on Windows; path to libleveldb.dll LEVELDB_DLL - Only when building with LevelDB on Windows; path to libleveldb.dll
POSTGRESQL_INCLUDE_DIR - Only when building with PostgreSQL; directory that contains libpq-fe.h PostgreSQL_INCLUDE_DIR - Only when building with PostgreSQL; directory that contains libpq-fe.h
POSTGRESQL_LIBRARY - Only when building with PostgreSQL; path to libpq.a/libpq.so POSTGRESQL_LIBRARY - Only when building with PostgreSQL; path to libpq.a/libpq.so
REDIS_INCLUDE_DIR - Only when building with Redis; directory that contains hiredis.h REDIS_INCLUDE_DIR - Only when building with Redis; directory that contains hiredis.h
REDIS_LIBRARY - Only when building with Redis; path to libhiredis.a/libhiredis.so REDIS_LIBRARY - Only when building with Redis; path to libhiredis.a/libhiredis.so

View File

@ -84,14 +84,14 @@ OGG_TIMESTAMP = $(OGG_DIR)timestamp
OGG_TIMESTAMP_INT = $(ANDR_ROOT)/deps/ogg_timestamp OGG_TIMESTAMP_INT = $(ANDR_ROOT)/deps/ogg_timestamp
OGG_URL_GIT = https://github.com/vincentjames501/libvorbis-libogg-android OGG_URL_GIT = https://github.com/vincentjames501/libvorbis-libogg-android
IRRLICHT_REVISION = 5122 IRRLICHT_REVISION = 5145
IRRLICHT_DIR = $(ANDR_ROOT)/deps/irrlicht/ IRRLICHT_DIR = $(ANDR_ROOT)/deps/irrlicht/
IRRLICHT_LIB = $(IRRLICHT_DIR)lib/Android/libIrrlicht.a IRRLICHT_LIB = $(IRRLICHT_DIR)lib/Android/libIrrlicht.a
IRRLICHT_TIMESTAMP = $(IRRLICHT_DIR)timestamp IRRLICHT_TIMESTAMP = $(IRRLICHT_DIR)timestamp
IRRLICHT_TIMESTAMP_INT = $(ANDR_ROOT)/deps/irrlicht_timestamp IRRLICHT_TIMESTAMP_INT = $(ANDR_ROOT)/deps/irrlicht_timestamp
IRRLICHT_URL_SVN = https://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@$(IRRLICHT_REVISION) IRRLICHT_URL_SVN = https://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@$(IRRLICHT_REVISION)
OPENSSL_VERSION = 1.0.2j OPENSSL_VERSION = 1.0.2k
OPENSSL_BASEDIR = openssl-$(OPENSSL_VERSION) OPENSSL_BASEDIR = openssl-$(OPENSSL_VERSION)
OPENSSL_DIR = $(ANDR_ROOT)/deps/$(OPENSSL_BASEDIR)/ OPENSSL_DIR = $(ANDR_ROOT)/deps/$(OPENSSL_BASEDIR)/
OPENSSL_LIB = $(OPENSSL_DIR)/libssl.so.1.0.0 OPENSSL_LIB = $(OPENSSL_DIR)/libssl.so.1.0.0
@ -99,7 +99,7 @@ OPENSSL_TIMESTAMP = $(OPENSSL_DIR)timestamp
OPENSSL_TIMESTAMP_INT = $(ANDR_ROOT)/deps/openssl_timestamp OPENSSL_TIMESTAMP_INT = $(ANDR_ROOT)/deps/openssl_timestamp
OPENSSL_URL = https://www.openssl.org/source/openssl-$(OPENSSL_VERSION).tar.gz OPENSSL_URL = https://www.openssl.org/source/openssl-$(OPENSSL_VERSION).tar.gz
CURL_VERSION = 7.52.0 CURL_VERSION = 7.54.0
CURL_DIR = $(ANDR_ROOT)/deps/curl-$(CURL_VERSION) CURL_DIR = $(ANDR_ROOT)/deps/curl-$(CURL_VERSION)
CURL_LIB = $(CURL_DIR)/lib/.libs/libcurl.a CURL_LIB = $(CURL_DIR)/lib/.libs/libcurl.a
CURL_TIMESTAMP = $(CURL_DIR)/timestamp CURL_TIMESTAMP = $(CURL_DIR)/timestamp
@ -126,8 +126,8 @@ ICONV_TIMESTAMP = $(ICONV_DIR)timestamp
ICONV_TIMESTAMP_INT = $(ANDR_ROOT)/deps/iconv_timestamp ICONV_TIMESTAMP_INT = $(ANDR_ROOT)/deps/iconv_timestamp
ICONV_URL_HTTP = https://ftp.gnu.org/pub/gnu/libiconv/libiconv-$(ICONV_VERSION).tar.gz ICONV_URL_HTTP = https://ftp.gnu.org/pub/gnu/libiconv/libiconv-$(ICONV_VERSION).tar.gz
SQLITE3_FOLDER = sqlite-amalgamation-3150200 SQLITE3_FOLDER = sqlite-amalgamation-3180000
SQLITE3_URL = https://www.sqlite.org/2016/$(SQLITE3_FOLDER).zip SQLITE3_URL = https://www.sqlite.org/2017/$(SQLITE3_FOLDER).zip
ANDROID_SDK = $(shell grep '^sdk\.dir' local.properties | sed 's/^.*=[[:space:]]*//') ANDROID_SDK = $(shell grep '^sdk\.dir' local.properties | sed 's/^.*=[[:space:]]*//')
ANDROID_NDK = $(shell grep '^ndk\.dir' local.properties | sed 's/^.*=[[:space:]]*//') ANDROID_NDK = $(shell grep '^ndk\.dir' local.properties | sed 's/^.*=[[:space:]]*//')
@ -680,8 +680,7 @@ deps/${SQLITE3_FOLDER}/sqlite3.c :
wget ${SQLITE3_URL}; \ wget ${SQLITE3_URL}; \
unzip ${SQLITE3_FOLDER}.zip; \ unzip ${SQLITE3_FOLDER}.zip; \
ln -s ${SQLITE3_FOLDER} sqlite; \ ln -s ${SQLITE3_FOLDER} sqlite; \
cd ${SQLITE3_FOLDER}; \ cd ${SQLITE3_FOLDER};
patch sqlite3.c < ${ANDR_ROOT}/patches/sqlite3-readonly-fix.patch
clean_sqlite3: clean_sqlite3:
cd deps && $(RM) -rf ${SQLITE3_FOLDER} && $(RM) -f ${SQLITE3_FOLDER}.zip && \ cd deps && $(RM) -rf ${SQLITE3_FOLDER} && $(RM) -f ${SQLITE3_FOLDER}.zip && \

View File

@ -134,6 +134,7 @@ LOCAL_SRC_FILES := \
jni/src/convert_json.cpp \ jni/src/convert_json.cpp \
jni/src/craftdef.cpp \ jni/src/craftdef.cpp \
jni/src/database-dummy.cpp \ jni/src/database-dummy.cpp \
jni/src/database-files.cpp \
jni/src/database-sqlite3.cpp \ jni/src/database-sqlite3.cpp \
jni/src/database.cpp \ jni/src/database.cpp \
jni/src/debug.cpp \ jni/src/debug.cpp \
@ -142,6 +143,7 @@ LOCAL_SRC_FILES := \
jni/src/dungeongen.cpp \ jni/src/dungeongen.cpp \
jni/src/emerge.cpp \ jni/src/emerge.cpp \
jni/src/environment.cpp \ jni/src/environment.cpp \
jni/src/face_position_cache.cpp \
jni/src/filecache.cpp \ jni/src/filecache.cpp \
jni/src/filesys.cpp \ jni/src/filesys.cpp \
jni/src/fontengine.cpp \ jni/src/fontengine.cpp \
@ -268,6 +270,7 @@ LOCAL_SRC_FILES := \
jni/src/settings.cpp \ jni/src/settings.cpp \
jni/src/wieldmesh.cpp \ jni/src/wieldmesh.cpp \
jni/src/client/clientlauncher.cpp \ jni/src/client/clientlauncher.cpp \
jni/src/client/inputhandler.cpp \
jni/src/client/tile.cpp \ jni/src/client/tile.cpp \
jni/src/client/joystick_controller.cpp \ jni/src/client/joystick_controller.cpp \
jni/src/irrlicht_changes/static_text.cpp jni/src/irrlicht_changes/static_text.cpp
@ -304,6 +307,7 @@ LOCAL_SRC_FILES += \
jni/src/script/cpp_api/s_server.cpp \ jni/src/script/cpp_api/s_server.cpp \
jni/src/script/lua_api/l_areastore.cpp \ jni/src/script/lua_api/l_areastore.cpp \
jni/src/script/lua_api/l_base.cpp \ jni/src/script/lua_api/l_base.cpp \
jni/src/script/lua_api/l_camera.cpp \
jni/src/script/lua_api/l_client.cpp \ jni/src/script/lua_api/l_client.cpp \
jni/src/script/lua_api/l_craft.cpp \ jni/src/script/lua_api/l_craft.cpp \
jni/src/script/lua_api/l_env.cpp \ jni/src/script/lua_api/l_env.cpp \
@ -328,8 +332,8 @@ LOCAL_SRC_FILES += \
jni/src/script/lua_api/l_storage.cpp \ jni/src/script/lua_api/l_storage.cpp \
jni/src/script/lua_api/l_util.cpp \ jni/src/script/lua_api/l_util.cpp \
jni/src/script/lua_api/l_vmanip.cpp \ jni/src/script/lua_api/l_vmanip.cpp \
jni/src/script/clientscripting.cpp \ jni/src/script/scripting_client.cpp \
jni/src/script/serverscripting.cpp \ jni/src/script/scripting_server.cpp \
jni/src/script/scripting_mainmenu.cpp jni/src/script/scripting_mainmenu.cpp
#freetype2 support #freetype2 support

View File

@ -1,17 +0,0 @@
--- sqlite3.c 2016-11-29 02:29:24.000000000 +0000
+++ sqlite3.c 2016-12-08 22:54:54.206465377 +0000
@@ -30445,7 +30445,14 @@
#if OS_VXWORKS
struct vxworksFileId *pId; /* Unique file ID for vxworks. */
#else
- ino_t ino; /* Inode number */
+ #ifdef ANDROID
+ // Bionic's struct stat has a 64 bit st_ino on both 32 and
+ // 64 bit architectures. ino_t remains 32 bits wide on 32 bit
+ // architectures and can lead to inode truncation.
+ unsigned long long ino; /* Inode number */
+ #else
+ ino_t ino; /* Inode number */
+ #endif
#endif
};

View File

@ -51,3 +51,15 @@ core.register_chatcommand("disconnect", {
core.disconnect() core.disconnect()
end, end,
}) })
core.register_chatcommand("clear_chat_queue", {
description = core.gettext("Clear the out chat queue"),
func = function(param)
core.clear_out_chat_queue()
return true, core.gettext("The out chat queue is now empty")
end,
})
function core.run_server_chatcommand(cmd, param)
core.send_chat_message("/" .. cmd .. " " .. param)
end

View File

@ -69,3 +69,5 @@ core.registered_on_damage_taken, core.register_on_damage_taken = make_registrati
core.registered_on_formspec_input, core.register_on_formspec_input = make_registration() core.registered_on_formspec_input, core.register_on_formspec_input = make_registration()
core.registered_on_dignode, core.register_on_dignode = make_registration() core.registered_on_dignode, core.register_on_dignode = make_registration()
core.registered_on_punchnode, core.register_on_punchnode = make_registration() core.registered_on_punchnode, core.register_on_punchnode = make_registration()
core.registered_on_placenode, core.register_on_placenode = make_registration()
core.registered_on_item_use, core.register_on_item_use = make_registration()

View File

@ -289,6 +289,9 @@ function sort_mod_list(self)
table.sort(self.m_processed_list, function(a, b) table.sort(self.m_processed_list, function(a, b)
-- Show game mods at bottom -- Show game mods at bottom
if a.typ ~= b.typ then if a.typ ~= b.typ then
if b.typ == "game" then
return a.typ ~= "game_mod"
end
return b.typ == "game_mod" return b.typ == "game_mod"
end end
-- If in same or no modpack, sort by name -- If in same or no modpack, sort by name

View File

@ -308,7 +308,7 @@ function core.formspec_escape(text)
end end
function core.splittext(text,charlimit) function core.wrap_text(text, charlimit)
local retval = {} local retval = {}
local current_idx = 1 local current_idx = 1
@ -463,7 +463,7 @@ if INIT == "game" then
core.rotate_node = function(itemstack, placer, pointed_thing) core.rotate_node = function(itemstack, placer, pointed_thing)
core.rotate_and_place(itemstack, placer, pointed_thing, core.rotate_and_place(itemstack, placer, pointed_thing,
core.setting_getbool("creative_mode"), core.settings:get_bool("creative_mode"),
{invert_wall = placer:get_player_control().sneak}) {invert_wall = placer:get_player_control().sneak})
return itemstack return itemstack
end end
@ -642,8 +642,8 @@ end
local ESCAPE_CHAR = string.char(0x1b) local ESCAPE_CHAR = string.char(0x1b)
-- Client-sided mods don't have access to getbool -- Client-side mods don't have access to settings
if core.setting_getbool and core.setting_getbool("disable_escape_sequences") then if core.settings and core.settings:get_bool("disable_escape_sequences") then
function core.get_color_escape_sequence(color) function core.get_color_escape_sequence(color)
return "" return ""

View File

@ -186,6 +186,10 @@ local safe_env = {
} }
function core.deserialize(str, safe) function core.deserialize(str, safe)
if type(str) ~= "string" then
return nil, "Cannot deserialize type '"..type(str)
.."'. Argument must be a string."
end
if str:byte(1) == 0x1B then if str:byte(1) == 0x1B then
return nil, "Bytecode prohibited" return nil, "Bytecode prohibited"
end end

View File

@ -167,7 +167,7 @@ local function switch_to_tab(self, index)
self.current_tab = self.tablist[index].name self.current_tab = self.tablist[index].name
if (self.autosave_tab) then if (self.autosave_tab) then
core.setting_set(self.name .. "_LAST",self.current_tab) core.settings:set(self.name .. "_LAST",self.current_tab)
end end
-- call for tab to enter -- call for tab to enter

View File

@ -106,7 +106,7 @@ core.builtin_auth_handler = {
end end
end end
-- For the admin, give everything -- For the admin, give everything
elseif name == core.setting_get("name") then elseif name == core.settings:get("name") then
for priv, def in pairs(core.registered_privileges) do for priv, def in pairs(core.registered_privileges) do
privileges[priv] = true privileges[priv] = true
end end
@ -125,7 +125,7 @@ core.builtin_auth_handler = {
core.log('info', "Built-in authentication handler adding player '"..name.."'") core.log('info', "Built-in authentication handler adding player '"..name.."'")
core.auth_table[name] = { core.auth_table[name] = {
password = password, password = password,
privileges = core.string_to_privs(core.setting_get("default_privs")), privileges = core.string_to_privs(core.settings:get("default_privs")),
last_login = os.time(), last_login = os.time(),
} }
save_auth_file() save_auth_file()
@ -148,7 +148,7 @@ core.builtin_auth_handler = {
if not core.auth_table[name] then if not core.auth_table[name] then
core.builtin_auth_handler.create_auth(name, core.builtin_auth_handler.create_auth(name,
core.get_password_hash(name, core.get_password_hash(name,
core.setting_get("default_password"))) core.settings:get("default_password")))
end end
core.auth_table[name].privileges = privileges core.auth_table[name].privileges = privileges
core.notify_authentication_modified(name) core.notify_authentication_modified(name)

View File

@ -39,7 +39,7 @@ core.register_on_chat_message(function(name, message)
return true -- Handled chat message return true -- Handled chat message
end) end)
if core.setting_getbool("profiler.load") then if core.settings:get_bool("profiler.load") then
-- Run after register_chatcommand and its register_on_chat_message -- Run after register_chatcommand and its register_on_chat_message
-- Before any chattcommands that should be profiled -- Before any chattcommands that should be profiled
profiler.init_chatcommand() profiler.init_chatcommand()
@ -82,7 +82,7 @@ core.register_chatcommand("me", {
core.register_chatcommand("admin", { core.register_chatcommand("admin", {
description = "Show the name of the server owner", description = "Show the name of the server owner",
func = function(name) func = function(name)
local admin = minetest.setting_get("name") local admin = minetest.settings:get("name")
if admin then if admin then
return true, "The administrator of this server is "..admin.."." return true, "The administrator of this server is "..admin.."."
else else
@ -119,7 +119,7 @@ local function handle_grant_command(caller, grantname, grantprivstr)
local privs = core.get_player_privs(grantname) local privs = core.get_player_privs(grantname)
local privs_unknown = "" local privs_unknown = ""
local basic_privs = local basic_privs =
core.string_to_privs(core.setting_get("basic_privs") or "interact,shout") core.string_to_privs(core.settings:get("basic_privs") or "interact,shout")
for priv, _ in pairs(grantprivs) do for priv, _ in pairs(grantprivs) do
if not basic_privs[priv] and not caller_privs.privs then if not basic_privs[priv] and not caller_privs.privs then
return false, "Your privileges are insufficient." return false, "Your privileges are insufficient."
@ -185,7 +185,7 @@ core.register_chatcommand("revoke", {
local revoke_privs = core.string_to_privs(revoke_priv_str) local revoke_privs = core.string_to_privs(revoke_priv_str)
local privs = core.get_player_privs(revoke_name) local privs = core.get_player_privs(revoke_name)
local basic_privs = local basic_privs =
core.string_to_privs(core.setting_get("basic_privs") or "interact,shout") core.string_to_privs(core.settings:get("basic_privs") or "interact,shout")
for priv, _ in pairs(revoke_privs) do for priv, _ in pairs(revoke_privs) do
if not basic_privs[priv] and if not basic_privs[priv] and
not core.check_player_privs(name, {privs=true}) then not core.check_player_privs(name, {privs=true}) then
@ -279,6 +279,31 @@ core.register_chatcommand("auth_reload", {
end, end,
}) })
core.register_chatcommand("remove_player", {
params = "<name>",
description = "Remove player data",
privs = {server=true},
func = function(name, param)
local toname = param
if toname == "" then
return false, "Name field required"
end
local rc = core.remove_player(toname)
if rc == 0 then
core.log("action", name .. " removed player data of " .. toname .. ".")
return true, "Player \"" .. toname .. "\" removed."
elseif rc == 1 then
return true, "No such player \"" .. toname .. "\" to remove."
elseif rc == 2 then
return true, "Player \"" .. toname .. "\" is connected, cannot remove."
end
return false, "Unhandled remove_player return code " .. rc .. ""
end,
})
core.register_chatcommand("teleport", { core.register_chatcommand("teleport", {
params = "<X>,<Y>,<Z> | <to_name> | <name> <X>,<Y>,<Z> | <name> <to_name>", params = "<X>,<Y>,<Z> | <to_name> | <name> <X>,<Y>,<Z> | <name> <to_name>",
description = "Teleport to player or position", description = "Teleport to player or position",
@ -394,20 +419,20 @@ core.register_chatcommand("set", {
func = function(name, param) func = function(name, param)
local arg, setname, setvalue = string.match(param, "(-[n]) ([^ ]+) (.+)") local arg, setname, setvalue = string.match(param, "(-[n]) ([^ ]+) (.+)")
if arg and arg == "-n" and setname and setvalue then if arg and arg == "-n" and setname and setvalue then
core.setting_set(setname, setvalue) core.settings:set(setname, setvalue)
return true, setname .. " = " .. setvalue return true, setname .. " = " .. setvalue
end end
local setname, setvalue = string.match(param, "([^ ]+) (.+)") local setname, setvalue = string.match(param, "([^ ]+) (.+)")
if setname and setvalue then if setname and setvalue then
if not core.setting_get(setname) then if not core.settings:get(setname) then
return false, "Failed. Use '/set -n <name> <value>' to create a new setting." return false, "Failed. Use '/set -n <name> <value>' to create a new setting."
end end
core.setting_set(setname, setvalue) core.settings:set(setname, setvalue)
return true, setname .. " = " .. setvalue return true, setname .. " = " .. setvalue
end end
local setname = string.match(param, "([^ ]+)") local setname = string.match(param, "([^ ]+)")
if setname then if setname then
local setvalue = core.setting_get(setname) local setvalue = core.settings:get(setname)
if not setvalue then if not setvalue then
setvalue = "<not set>" setvalue = "<not set>"
end end
@ -642,7 +667,7 @@ core.register_chatcommand("rollback_check", {
.. " seconds = 86400 = 24h, limit = 5", .. " seconds = 86400 = 24h, limit = 5",
privs = {rollback=true}, privs = {rollback=true},
func = function(name, param) func = function(name, param)
if not core.setting_getbool("enable_rollback_recording") then if not core.settings:get_bool("enable_rollback_recording") then
return false, "Rollback functions are disabled." return false, "Rollback functions are disabled."
end end
local range, seconds, limit = local range, seconds, limit =
@ -693,7 +718,7 @@ core.register_chatcommand("rollback", {
description = "Revert actions of a player. Default for <seconds> is 60", description = "Revert actions of a player. Default for <seconds> is 60",
privs = {rollback=true}, privs = {rollback=true},
func = function(name, param) func = function(name, param)
if not core.setting_getbool("enable_rollback_recording") then if not core.settings:get_bool("enable_rollback_recording") then
return false, "Rollback functions are disabled." return false, "Rollback functions are disabled."
end end
local target_name, seconds = string.match(param, ":([^ ]+) *(%d*)") local target_name, seconds = string.match(param, ":([^ ]+) *(%d*)")
@ -913,3 +938,31 @@ core.register_chatcommand("last-login", {
return false, "Last login time is unknown" return false, "Last login time is unknown"
end, end,
}) })
core.register_chatcommand("clearinv", {
params = "[name]",
description = "Clear the inventory of yourself or another player",
func = function(name, param)
local player
if param and param ~= "" and param ~= name then
if not core.check_player_privs(name, {server=true}) then
return false, "You don't have permission"
.. " to run this command (missing privilege: server)"
end
player = core.get_player_by_name(param)
core.chat_send_player(param, name.." cleared your inventory.")
else
player = core.get_player_by_name(name)
end
if player then
player:get_inventory():set_list("main", {})
player:get_inventory():set_list("craft", {})
player:get_inventory():set_list("craftpreview", {})
core.log("action", name.." clears "..player:get_player_name().."'s inventory")
return true, "Cleared "..player:get_player_name().."'s inventory."
else
return false, "Player must be online to clear inventory!"
end
end,
})

View File

@ -49,3 +49,24 @@ setmetatable(core.env, {
function core.rollback_get_last_node_actor(pos, range, seconds) function core.rollback_get_last_node_actor(pos, range, seconds)
return core.rollback_get_node_actions(pos, range, seconds, 1)[1] return core.rollback_get_node_actions(pos, range, seconds, 1)[1]
end end
--
-- core.setting_*
--
local settings = core.settings
local function setting_proxy(name)
return function(...)
core.log("deprecated", "WARNING: minetest.setting_* "..
"functions are deprecated. "..
"Use methods on the minetest.settings object.")
return settings[name](settings, ...)
end
end
core.setting_set = setting_proxy("set")
core.setting_get = setting_proxy("get")
core.setting_setbool = setting_proxy("set_bool")
core.setting_getbool = setting_proxy("get_bool")
core.setting_save = setting_proxy("write")

View File

@ -40,7 +40,7 @@ function core.forceload_block(pos, transient)
elseif other_table[hash] ~= nil then elseif other_table[hash] ~= nil then
relevant_table[hash] = 1 relevant_table[hash] = 1
else else
if total_forceloaded >= (tonumber(core.setting_get("max_forceloaded_blocks")) or 16) then if total_forceloaded >= (tonumber(core.settings:get("max_forceloaded_blocks")) or 16) then
return false return false
end end
total_forceloaded = total_forceloaded+1 total_forceloaded = total_forceloaded+1

View File

@ -13,7 +13,7 @@ dofile(gamepath.."constants.lua")
assert(loadfile(gamepath.."item.lua"))(builtin_shared) assert(loadfile(gamepath.."item.lua"))(builtin_shared)
dofile(gamepath.."register.lua") dofile(gamepath.."register.lua")
if core.setting_getbool("profiler.load") then if core.settings:get_bool("profiler.load") then
profiler = dofile(scriptpath.."profiler"..DIR_DELIM.."init.lua") profiler = dofile(scriptpath.."profiler"..DIR_DELIM.."init.lua")
end end

View File

@ -483,7 +483,7 @@ function core.node_dig(pos, node, digger)
wielded = wdef.after_use(wielded, digger, node, dp) or wielded wielded = wdef.after_use(wielded, digger, node, dp) or wielded
else else
-- Wear out tool -- Wear out tool
if not core.setting_getbool("creative_mode") then if not core.settings:get_bool("creative_mode") then
wielded:add_wear(dp.wear) wielded:add_wear(dp.wear)
if wielded:get_count() == 0 and wdef.sound and wdef.sound.breaks then if wielded:get_count() == 0 and wdef.sound and wdef.sound.breaks then
core.sound_play(wdef.sound.breaks, {pos = pos, gain = 0.5}) core.sound_play(wdef.sound.breaks, {pos = pos, gain = 0.5})

View File

@ -14,7 +14,7 @@ end
-- If item_entity_ttl is not set, enity will have default life time -- If item_entity_ttl is not set, enity will have default life time
-- Setting it to -1 disables the feature -- Setting it to -1 disables the feature
local time_to_live = tonumber(core.setting_get("item_entity_ttl")) local time_to_live = tonumber(core.settings:get("item_entity_ttl"))
if not time_to_live then if not time_to_live then
time_to_live = 900 time_to_live = 900
end end

View File

@ -121,7 +121,7 @@ function core.get_node_group(name, group)
end end
function core.setting_get_pos(name) function core.setting_get_pos(name)
local value = core.setting_get(name) local value = core.settings:get(name)
if not value then if not value then
return nil return nil
end end

View File

@ -1,5 +1,5 @@
-- cache setting -- cache setting
local enable_damage = core.setting_getbool("enable_damage") == true local enable_damage = core.settings:get_bool("enable_damage")
local health_bar_definition = local health_bar_definition =
{ {

View File

@ -1,10 +1,10 @@
-- Minetest: builtin/static_spawn.lua -- Minetest: builtin/static_spawn.lua
local function warn_invalid_static_spawnpoint() local function warn_invalid_static_spawnpoint()
if core.setting_get("static_spawnpoint") and if core.settings:get("static_spawnpoint") and
not core.setting_get_pos("static_spawnpoint") then not core.setting_get_pos("static_spawnpoint") then
core.log("error", "The static_spawnpoint setting is invalid: \"".. core.log("error", "The static_spawnpoint setting is invalid: \""..
core.setting_get("static_spawnpoint").."\"") core.settings:get("static_spawnpoint").."\"")
end end
end end

View File

@ -38,7 +38,7 @@ dofile(commonpath .. "misc_helpers.lua")
if INIT == "game" then if INIT == "game" then
dofile(gamepath .. "init.lua") dofile(gamepath .. "init.lua")
elseif INIT == "mainmenu" then elseif INIT == "mainmenu" then
local mm_script = core.setting_get("main_menu_script") local mm_script = core.settings:get("main_menu_script")
if mm_script and mm_script ~= "" then if mm_script and mm_script ~= "" then
dofile(mm_script) dofile(mm_script)
else else

View File

@ -43,10 +43,10 @@ end
local function configure_selected_world_params(idx) local function configure_selected_world_params(idx)
local worldconfig = modmgr.get_worldconfig(menudata.worldlist:get_list()[idx].path) local worldconfig = modmgr.get_worldconfig(menudata.worldlist:get_list()[idx].path)
if worldconfig.creative_mode then if worldconfig.creative_mode then
core.setting_set("creative_mode", worldconfig.creative_mode) core.settings:set("creative_mode", worldconfig.creative_mode)
end end
if worldconfig.enable_damage then if worldconfig.enable_damage then
core.setting_set("enable_damage", worldconfig.enable_damage) core.settings:set("enable_damage", worldconfig.enable_damage)
end end
end end
@ -164,8 +164,8 @@ end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
os.tempfolder = function() os.tempfolder = function()
if core.setting_get("TMPFolder") then if core.settings:get("TMPFolder") then
return core.setting_get("TMPFolder") .. DIR_DELIM .. "MT_" .. math.random(0,10000) return core.settings:get("TMPFolder") .. DIR_DELIM .. "MT_" .. math.random(0,10000)
end end
local filetocheck = os.tmpname() local filetocheck = os.tmpname()
@ -206,7 +206,7 @@ function menu_handle_key_up_down(fields, textlist, settingname)
oldidx < menudata.worldlist:size() then oldidx < menudata.worldlist:size() then
newidx = oldidx + 1 newidx = oldidx + 1
end end
core.setting_set(settingname, menudata.worldlist:get_raw_index(newidx)) core.settings:set(settingname, menudata.worldlist:get_raw_index(newidx))
configure_selected_world_params(newidx) configure_selected_world_params(newidx)
return true return true
end end
@ -250,7 +250,7 @@ end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function text2textlist(xpos, ypos, width, height, tl_name, textlen, text, transparency) function text2textlist(xpos, ypos, width, height, tl_name, textlen, text, transparency)
local textlines = core.splittext(text, textlen) local textlines = core.wrap_text(text, textlen)
local retval = "textlist[" .. xpos .. "," .. ypos .. ";" .. width .. local retval = "textlist[" .. xpos .. "," .. ypos .. ";" .. width ..
"," .. height .. ";" .. tl_name .. ";" "," .. height .. ";" .. tl_name .. ";"
@ -328,9 +328,9 @@ function menu_worldmt_legacy(selected)
for _, mode_name in pairs(modes_names) do for _, mode_name in pairs(modes_names) do
local mode_val = menu_worldmt(selected, mode_name) local mode_val = menu_worldmt(selected, mode_name)
if mode_val then if mode_val then
core.setting_set(mode_name, mode_val) core.settings:set(mode_name, mode_val)
else else
menu_worldmt(selected, mode_name, core.setting_get(mode_name)) menu_worldmt(selected, mode_name, core.settings:get(mode_name))
end end
end end
end end

View File

@ -49,7 +49,7 @@ local function get_formspec(data)
"button[3.25,7;2.5,0.5;btn_config_world_save;" .. fgettext("Save") .. "]" .. "button[3.25,7;2.5,0.5;btn_config_world_save;" .. fgettext("Save") .. "]" ..
"button[5.75,7;2.5,0.5;btn_config_world_cancel;" .. fgettext("Cancel") .. "]" "button[5.75,7;2.5,0.5;btn_config_world_cancel;" .. fgettext("Cancel") .. "]"
if mod and mod.name ~= "" and mod.typ ~= "game_mod" then if mod and mod.name ~= "" and not mod.is_game_content then
if mod.is_modpack then if mod.is_modpack then
local rawlist = data.list:get_raw_list() local rawlist = data.list:get_raw_list()
@ -97,7 +97,7 @@ end
local function enable_mod(this, toset) local function enable_mod(this, toset)
local mod = this.data.list:get_list()[this.data.selected_mod] local mod = this.data.list:get_list()[this.data.selected_mod]
if mod.typ == "game_mod" then if mod.is_game_content then
-- game mods can't be enabled or disabled -- game mods can't be enabled or disabled
elseif not mod.is_modpack then elseif not mod.is_modpack then
if toset == nil then if toset == nil then
@ -123,7 +123,7 @@ local function handle_buttons(this, fields)
if fields["world_config_modlist"] ~= nil then if fields["world_config_modlist"] ~= nil then
local event = core.explode_table_event(fields["world_config_modlist"]) local event = core.explode_table_event(fields["world_config_modlist"])
this.data.selected_mod = event.row this.data.selected_mod = event.row
core.setting_set("world_config_selected_mod", event.row) core.settings:set("world_config_selected_mod", event.row)
if event.type == "DCL" then if event.type == "DCL" then
enable_mod(this) enable_mod(this)
@ -162,7 +162,7 @@ local function handle_buttons(this, fields)
local i,mod local i,mod
for i,mod in ipairs(rawlist) do for i,mod in ipairs(rawlist) do
if not mod.is_modpack and if not mod.is_modpack and
mod.typ ~= "game_mod" then not mod.is_game_content then
if modname_valid(mod.name) then if modname_valid(mod.name) then
worldfile:set("load_mod_"..mod.name, tostring(mod.enabled)) worldfile:set("load_mod_"..mod.name, tostring(mod.enabled))
else else
@ -198,7 +198,8 @@ local function handle_buttons(this, fields)
local list = this.data.list:get_raw_list() local list = this.data.list:get_raw_list()
for i = 1, #list do for i = 1, #list do
if list[i].typ ~= "game_mod" and not list[i].is_modpack then if not list[i].is_game_content
and not list[i].is_modpack then
list[i].enabled = true list[i].enabled = true
end end
end end
@ -210,7 +211,8 @@ local function handle_buttons(this, fields)
local list = this.data.list:get_raw_list() local list = this.data.list:get_raw_list()
for i = 1, #list do for i = 1, #list do
if list[i].typ ~= "game_mod" and not list[i].is_modpack then if not list[i].is_game_content
and not list[i].is_modpack then
list[i].enabled = false list[i].enabled = false
end end
end end
@ -227,7 +229,7 @@ function create_configure_world_dlg(worldidx)
handle_buttons, handle_buttons,
nil) nil)
dlg.data.selected_mod = tonumber(core.setting_get("world_config_selected_mod")) dlg.data.selected_mod = tonumber(core.settings:get("world_config_selected_mod"))
if dlg.data.selected_mod == nil then if dlg.data.selected_mod == nil then
dlg.data.selected_mod = 0 dlg.data.selected_mod = 0
end end
@ -252,16 +254,16 @@ function create_configure_world_dlg(worldidx)
return true return true
end end
end, end,
function(element,criteria) function(element, criteria)
if criteria.hide_game and if criteria.hide_game and
element.typ == "game_mod" then element.is_game_content then
return false return false
end end
if criteria.hide_modpackcontents and if criteria.hide_modpackcontents and
element.modpack ~= nil then element.modpack ~= nil then
return false return false
end end
return true return true
end, --filter end, --filter
{ worldpath= dlg.data.worldspec.path, { worldpath= dlg.data.worldspec.path,

View File

@ -18,8 +18,8 @@
local function create_world_formspec(dialogdata) local function create_world_formspec(dialogdata)
local mapgens = core.get_mapgen_names() local mapgens = core.get_mapgen_names()
local current_seed = core.setting_get("fixed_map_seed") or "" local current_seed = core.settings:get("fixed_map_seed") or ""
local current_mg = core.setting_get("mg_name") local current_mg = core.settings:get("mg_name")
local mglist = "" local mglist = ""
local selindex = 1 local selindex = 1
@ -33,7 +33,7 @@ local function create_world_formspec(dialogdata)
end end
mglist = mglist:sub(1, -2) mglist = mglist:sub(1, -2)
local gameid = core.setting_get("menu_last_game") local gameid = core.settings:get("menu_last_game")
local game, gameidx = nil , 0 local game, gameidx = nil , 0
if gameid ~= nil then if gameid ~= nil then
@ -90,10 +90,10 @@ local function create_world_buttonhandler(this, fields)
local message = nil local message = nil
core.setting_set("fixed_map_seed", fields["te_seed"]) core.settings:set("fixed_map_seed", fields["te_seed"])
if not menudata.worldlist:uid_exists_raw(worldname) then if not menudata.worldlist:uid_exists_raw(worldname) then
core.setting_set("mg_name",fields["dd_mapgen"]) core.settings:set("mg_name",fields["dd_mapgen"])
message = core.create_world(worldname,gameindex) message = core.create_world(worldname,gameindex)
else else
message = fgettext("A world named \"$1\" already exists", worldname) message = fgettext("A world named \"$1\" already exists", worldname)
@ -102,13 +102,13 @@ local function create_world_buttonhandler(this, fields)
if message ~= nil then if message ~= nil then
gamedata.errormessage = message gamedata.errormessage = message
else else
core.setting_set("menu_last_game",gamemgr.games[gameindex].id) core.settings:set("menu_last_game",gamemgr.games[gameindex].id)
if this.data.update_worldlist_filter then if this.data.update_worldlist_filter then
menudata.worldlist:set_filtercriteria(gamemgr.games[gameindex].id) menudata.worldlist:set_filtercriteria(gamemgr.games[gameindex].id)
mm_texture.update("singleplayer", gamemgr.games[gameindex].id) mm_texture.update("singleplayer", gamemgr.games[gameindex].id)
end end
menudata.worldlist:refresh() menudata.worldlist:refresh()
core.setting_set("mainmenu_last_selected_world", core.settings:set("mainmenu_last_selected_world",
menudata.worldlist:raw_index_by_uid(worldname)) menudata.worldlist:raw_index_by_uid(worldname))
end end
else else

View File

@ -423,7 +423,7 @@ local settings = full_settings
local selected_setting = 1 local selected_setting = 1
local function get_current_value(setting) local function get_current_value(setting)
local value = core.setting_get(setting.name) local value = core.settings:get(setting.name)
if value == nil then if value == nil then
value = setting.default value = setting.default
end end
@ -539,11 +539,11 @@ local function handle_change_setting_buttons(this, fields)
if setting.type == "bool" then if setting.type == "bool" then
local new_value = fields["dd_setting_value"] local new_value = fields["dd_setting_value"]
-- Note: new_value is the actual (translated) value shown in the dropdown -- Note: new_value is the actual (translated) value shown in the dropdown
core.setting_setbool(setting.name, new_value == fgettext("Enabled")) core.settings:set_bool(setting.name, new_value == fgettext("Enabled"))
elseif setting.type == "enum" then elseif setting.type == "enum" then
local new_value = fields["dd_setting_value"] local new_value = fields["dd_setting_value"]
core.setting_set(setting.name, new_value) core.settings:set(setting.name, new_value)
elseif setting.type == "int" then elseif setting.type == "int" then
local new_value = tonumber(fields["te_setting_value"]) local new_value = tonumber(fields["te_setting_value"])
@ -565,7 +565,7 @@ local function handle_change_setting_buttons(this, fields)
core.update_formspec(this:get_formspec()) core.update_formspec(this:get_formspec())
return true return true
end end
core.setting_set(setting.name, new_value) core.settings:set(setting.name, new_value)
elseif setting.type == "float" then elseif setting.type == "float" then
local new_value = tonumber(fields["te_setting_value"]) local new_value = tonumber(fields["te_setting_value"])
@ -575,7 +575,7 @@ local function handle_change_setting_buttons(this, fields)
core.update_formspec(this:get_formspec()) core.update_formspec(this:get_formspec())
return true return true
end end
core.setting_set(setting.name, new_value) core.settings:set(setting.name, new_value)
elseif setting.type == "flags" then elseif setting.type == "flags" then
local new_value = fields["te_setting_value"] local new_value = fields["te_setting_value"]
@ -589,13 +589,13 @@ local function handle_change_setting_buttons(this, fields)
return true return true
end end
end end
core.setting_set(setting.name, new_value) core.settings:set(setting.name, new_value)
else else
local new_value = fields["te_setting_value"] local new_value = fields["te_setting_value"]
core.setting_set(setting.name, new_value) core.settings:set(setting.name, new_value)
end end
core.setting_save() core.settings:write()
this:delete() this:delete()
return true return true
end end
@ -629,7 +629,7 @@ local function create_settings_formspec(tabview, name, tabdata)
local current_level = 0 local current_level = 0
for _, entry in ipairs(settings) do for _, entry in ipairs(settings) do
local name local name
if not core.setting_getbool("main_menu_technical_settings") and entry.readable_name then if not core.settings:get_bool("main_menu_technical_settings") and entry.readable_name then
name = fgettext_ne(entry.readable_name) name = fgettext_ne(entry.readable_name)
else else
name = entry.name name = entry.name
@ -666,7 +666,7 @@ local function create_settings_formspec(tabview, name, tabdata)
"button[10,6;2,1;btn_edit;" .. fgettext("Edit") .. "]" .. "button[10,6;2,1;btn_edit;" .. fgettext("Edit") .. "]" ..
"button[7,6;3,1;btn_restore;" .. fgettext("Restore Default") .. "]" .. "button[7,6;3,1;btn_restore;" .. fgettext("Restore Default") .. "]" ..
"checkbox[0,5.3;cb_tech_settings;" .. fgettext("Show technical names") .. ";" "checkbox[0,5.3;cb_tech_settings;" .. fgettext("Show technical names") .. ";"
.. dump(core.setting_getbool("main_menu_technical_settings")) .. "]" .. dump(core.settings:get_bool("main_menu_technical_settings")) .. "]"
return formspec return formspec
end end
@ -680,8 +680,8 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
local setting = settings[selected_setting] local setting = settings[selected_setting]
if setting and setting.type == "bool" then if setting and setting.type == "bool" then
local current_value = get_current_value(setting) local current_value = get_current_value(setting)
core.setting_setbool(setting.name, not core.is_yes(current_value)) core.settings:set_bool(setting.name, not core.is_yes(current_value))
core.setting_save() core.settings:write()
return true return true
else else
list_enter = true list_enter = true
@ -736,8 +736,8 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
if fields["btn_restore"] then if fields["btn_restore"] then
local setting = settings[selected_setting] local setting = settings[selected_setting]
if setting and setting.type ~= "category" then if setting and setting.type ~= "category" then
core.setting_set(setting.name, setting.default) core.settings:set(setting.name, setting.default)
core.setting_save() core.settings:write()
core.update_formspec(this:get_formspec()) core.update_formspec(this:get_formspec())
end end
return true return true
@ -749,8 +749,8 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
end end
if fields["cb_tech_settings"] then if fields["cb_tech_settings"] then
core.setting_set("main_menu_technical_settings", fields["cb_tech_settings"]) core.settings:set("main_menu_technical_settings", fields["cb_tech_settings"])
core.setting_save() core.settings:write()
core.update_formspec(this:get_formspec()) core.update_formspec(this:get_formspec())
return true return true
end end

View File

@ -68,10 +68,10 @@ end
function gamemgr.gamelist() function gamemgr.gamelist()
local retval = "" local retval = ""
if #gamemgr.games > 0 then if #gamemgr.games > 0 then
retval = retval .. gamemgr.games[1].name retval = retval .. core.formspec_escape(gamemgr.games[1].name)
for i=2,#gamemgr.games,1 do for i=2,#gamemgr.games,1 do
retval = retval .. "," .. gamemgr.games[i].name retval = retval .. "," .. core.formspec_escape(gamemgr.games[i].name)
end end
end end
return retval return retval

View File

@ -56,9 +56,8 @@ tabs.credits = dofile(menupath .. DIR_DELIM .. "tab_credits.lua")
if PLATFORM == "Android" then if PLATFORM == "Android" then
tabs.simple_main = dofile(menupath .. DIR_DELIM .. "tab_simple_main.lua") tabs.simple_main = dofile(menupath .. DIR_DELIM .. "tab_simple_main.lua")
else else
tabs.singleplayer = dofile(menupath .. DIR_DELIM .. "tab_singleplayer.lua") tabs.local_game = dofile(menupath .. DIR_DELIM .. "tab_local.lua")
tabs.multiplayer = dofile(menupath .. DIR_DELIM .. "tab_multiplayer.lua") tabs.play_online = dofile(menupath .. DIR_DELIM .. "tab_online.lua")
tabs.server = dofile(menupath .. DIR_DELIM .. "tab_server.lua")
tabs.texturepacks = dofile(menupath .. DIR_DELIM .. "tab_texturepacks.lua") tabs.texturepacks = dofile(menupath .. DIR_DELIM .. "tab_texturepacks.lua")
end end
@ -119,9 +118,9 @@ local function init_globals()
menudata.worldlist:add_sort_mechanism("alphabetic", sort_worlds_alphabetic) menudata.worldlist:add_sort_mechanism("alphabetic", sort_worlds_alphabetic)
menudata.worldlist:set_sortmode("alphabetic") menudata.worldlist:set_sortmode("alphabetic")
if not core.setting_get("menu_last_game") then if not core.settings:get("menu_last_game") then
local default_game = core.setting_get("default_game") or "minetest" local default_game = core.settings:get("default_game") or "minetest"
core.setting_set("menu_last_game", default_game) core.settings:set("menu_last_game", default_game)
end end
mm_texture.init() mm_texture.init()
@ -135,9 +134,8 @@ local function init_globals()
tv_main:add(tabs.settings) tv_main:add(tabs.settings)
else else
tv_main:set_autosave_tab(true) tv_main:set_autosave_tab(true)
tv_main:add(tabs.singleplayer) tv_main:add(tabs.local_game)
tv_main:add(tabs.multiplayer) tv_main:add(tabs.play_online)
tv_main:add(tabs.server)
tv_main:add(tabs.settings) tv_main:add(tabs.settings)
tv_main:add(tabs.texturepacks) tv_main:add(tabs.texturepacks)
end end
@ -149,7 +147,7 @@ local function init_globals()
tv_main:set_fixed_size(false) tv_main:set_fixed_size(false)
if PLATFORM ~= "Android" then if PLATFORM ~= "Android" then
tv_main:set_tab(core.setting_get("maintab_LAST")) tv_main:set_tab(core.settings:get("maintab_LAST"))
end end
ui.set_default("maintab") ui.set_default("maintab")
tv_main:show() tv_main:show()
@ -167,4 +165,3 @@ local function init_globals()
end end
init_globals() init_globals()

View File

@ -238,15 +238,7 @@ function modmgr.render_modlist(render_list)
local list = render_list:get_list() local list = render_list:get_list()
local last_modpack = nil local last_modpack = nil
local retval = {} local retval = {}
local in_game_mods = false
for i, v in ipairs(list) do for i, v in ipairs(list) do
if v.typ == "game_mod" and not in_game_mods then
in_game_mods = true
retval[#retval + 1] = mt_color_blue
retval[#retval + 1] = "0"
retval[#retval + 1] = fgettext("Subgame Mods")
end
local color = "" local color = ""
if v.is_modpack then if v.is_modpack then
local rawlist = render_list:get_raw_list() local rawlist = render_list:get_raw_list()
@ -260,7 +252,7 @@ function modmgr.render_modlist(render_list)
break break
end end
end end
elseif v.typ == "game_mod" then elseif v.is_game_content then
color = mt_color_blue color = mt_color_blue
elseif v.enabled then elseif v.enabled then
color = mt_color_green color = mt_color_green
@ -421,8 +413,18 @@ function modmgr.preparemodlist(data)
local gamespec = gamemgr.find_by_gameid(data.gameid) local gamespec = gamemgr.find_by_gameid(data.gameid)
gamemgr.get_game_mods(gamespec, game_mods) gamemgr.get_game_mods(gamespec, game_mods)
if #game_mods > 0 then
-- Add title
retval[#retval + 1] = {
typ = "game",
is_game_content = true,
name = fgettext("Subgame Mods")
}
end
for i=1,#game_mods,1 do for i=1,#game_mods,1 do
game_mods[i].typ = "game_mod" game_mods[i].typ = "game_mod"
game_mods[i].is_game_content = true
retval[#retval + 1] = game_mods[i] retval[#retval + 1] = game_mods[i]
end end

View File

@ -233,14 +233,14 @@ function modstore.handle_buttons(parent, fields, name, data)
if not core.handle_async( if not core.handle_async(
function(param) function(param)
local fullurl = core.setting_get("modstore_download_url") .. local fullurl = core.settings:get("modstore_download_url") ..
param.moddetails.download_url param.moddetails.download_url
if param.version ~= nil then if param.version ~= nil then
local found = false local found = false
for i=1,#param.moddetails.versions, 1 do for i=1,#param.moddetails.versions, 1 do
if param.moddetails.versions[i].date:sub(1,10) == param.version then if param.moddetails.versions[i].date:sub(1,10) == param.version then
fullurl = core.setting_get("modstore_download_url") .. fullurl = core.settings:get("modstore_download_url") ..
param.moddetails.versions[i].download_url param.moddetails.versions[i].download_url
found = true found = true
end end
@ -400,7 +400,7 @@ function modstore.getscreenshot(ypos,listentry)
listentry.texturename = "in progress" listentry.texturename = "in progress"
--prepare url and filename --prepare url and filename
local fullurl = core.setting_get("modstore_download_url") .. local fullurl = core.settings:get("modstore_download_url") ..
listentry.details.screenshot_url listentry.details.screenshot_url
local filename = os.tempfolder() .. "_MID_" .. listentry.id local filename = os.tempfolder() .. "_MID_" .. listentry.id

View File

@ -20,7 +20,6 @@
local core_developers = { local core_developers = {
"Perttu Ahola (celeron55) <celeron55@gmail.com>", "Perttu Ahola (celeron55) <celeron55@gmail.com>",
"Ryan Kwolek (kwolekr) <kwolekr@minetest.net>", "Ryan Kwolek (kwolekr) <kwolekr@minetest.net>",
"PilzAdam <pilzadam@minetest.net>",
"sfan5 <sfan5@live.de>", "sfan5 <sfan5@live.de>",
"kahrl <kahrl@gmx.net>", "kahrl <kahrl@gmx.net>",
"sapier", "sapier",
@ -54,6 +53,7 @@ local previous_core_developers = {
"Lisa Milne (darkrose) <lisa@ltmnet.com>", "Lisa Milne (darkrose) <lisa@ltmnet.com>",
"proller", "proller",
"Ilya Zhuravlev (xyz) <xyz@minetest.net>", "Ilya Zhuravlev (xyz) <xyz@minetest.net>",
"PilzAdam <pilzadam@minetest.net>",
} }
local previous_contributors = { local previous_contributors = {

View File

@ -16,9 +16,9 @@
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
local function current_game() local function current_game()
local last_game_id = core.setting_get("menu_last_game") local last_game_id = core.settings:get("menu_last_game")
local game, index = gamemgr.find_by_gameid(last_game_id) local game, index = gamemgr.find_by_gameid(last_game_id)
return game return game
end end
@ -36,10 +36,10 @@ local function singleplayer_refresh_gamebar()
if ("game_btnbar_" .. gamemgr.games[j].id == key) then if ("game_btnbar_" .. gamemgr.games[j].id == key) then
mm_texture.update("singleplayer", gamemgr.games[j]) mm_texture.update("singleplayer", gamemgr.games[j])
core.set_topleft_text(gamemgr.games[j].name) core.set_topleft_text(gamemgr.games[j].name)
core.setting_set("menu_last_game",gamemgr.games[j].id) core.settings:set("menu_last_game",gamemgr.games[j].id)
menudata.worldlist:set_filtercriteria(gamemgr.games[j].id) menudata.worldlist:set_filtercriteria(gamemgr.games[j].id)
local index = filterlist.get_current_index(menudata.worldlist, local index = filterlist.get_current_index(menudata.worldlist,
tonumber(core.setting_get("mainmenu_last_selected_world"))) tonumber(core.settings:get("mainmenu_last_selected_world")))
if not index or index < 1 then if not index or index < 1 then
local selected = core.get_textlist_index("sp_worlds") local selected = core.get_textlist_index("sp_worlds")
if selected ~= nil and selected < #menudata.worldlist:get_list() then if selected ~= nil and selected < #menudata.worldlist:get_list() then
@ -61,20 +61,20 @@ local function singleplayer_refresh_gamebar()
for i=1,#gamemgr.games,1 do for i=1,#gamemgr.games,1 do
local btn_name = "game_btnbar_" .. gamemgr.games[i].id local btn_name = "game_btnbar_" .. gamemgr.games[i].id
local image = nil local image = nil
local text = nil local text = nil
local tooltip = core.formspec_escape(gamemgr.games[i].name) local tooltip = core.formspec_escape(gamemgr.games[i].name)
if gamemgr.games[i].menuicon_path ~= nil and if gamemgr.games[i].menuicon_path ~= nil and
gamemgr.games[i].menuicon_path ~= "" then gamemgr.games[i].menuicon_path ~= "" then
image = core.formspec_escape(gamemgr.games[i].menuicon_path) image = core.formspec_escape(gamemgr.games[i].menuicon_path)
else else
local part1 = gamemgr.games[i].id:sub(1,5) local part1 = gamemgr.games[i].id:sub(1,5)
local part2 = gamemgr.games[i].id:sub(6,10) local part2 = gamemgr.games[i].id:sub(6,10)
local part3 = gamemgr.games[i].id:sub(11) local part3 = gamemgr.games[i].id:sub(11)
text = part1 .. "\n" .. part2 text = part1 .. "\n" .. part2
if part3 ~= nil and if part3 ~= nil and
part3 ~= "" then part3 ~= "" then
@ -89,28 +89,57 @@ local function get_formspec(tabview, name, tabdata)
local retval = "" local retval = ""
local index = filterlist.get_current_index(menudata.worldlist, local index = filterlist.get_current_index(menudata.worldlist,
tonumber(core.setting_get("mainmenu_last_selected_world")) tonumber(core.settings:get("mainmenu_last_selected_world"))
) )
retval = retval .. retval = retval ..
"button[4,4.15;2.6,0.5;world_delete;".. fgettext("Delete") .. "]" .. "button[4,4.15;2.6,0.5;world_delete;".. fgettext("Delete") .. "]" ..
"button[6.5,4.15;2.8,0.5;world_create;".. fgettext("New") .. "]" .. "button[6.5,4.15;2.8,0.5;world_create;".. fgettext("New") .. "]" ..
"button[9.2,4.15;2.55,0.5;world_configure;".. fgettext("Configure") .. "]" .. "button[9.2,4.15;2.55,0.5;world_configure;".. fgettext("Configure") .. "]" ..
"button[8.5,5;3.25,0.5;play;".. fgettext("Play") .. "]" ..
"label[4,-0.25;".. fgettext("Select World:") .. "]".. "label[4,-0.25;".. fgettext("Select World:") .. "]"..
"checkbox[0.25,0.25;cb_creative_mode;".. fgettext("Creative Mode") .. ";" .. "checkbox[0.25,0.25;cb_creative_mode;".. fgettext("Creative Mode") .. ";" ..
dump(core.setting_getbool("creative_mode")) .. "]".. dump(core.settings:get_bool("creative_mode")) .. "]"..
"checkbox[0.25,0.7;cb_enable_damage;".. fgettext("Enable Damage") .. ";" .. "checkbox[0.25,0.7;cb_enable_damage;".. fgettext("Enable Damage") .. ";" ..
dump(core.setting_getbool("enable_damage")) .. "]".. dump(core.settings:get_bool("enable_damage")) .. "]"..
"checkbox[0.25,1.15;cb_server;".. fgettext("Host Server") ..";" ..
dump(core.settings:get_bool("enable_server")) .. "]" ..
"textlist[4,0.25;7.5,3.7;sp_worlds;" .. "textlist[4,0.25;7.5,3.7;sp_worlds;" ..
menu_render_worldlist() .. menu_render_worldlist() ..
";" .. index .. "]" ";" .. index .. "]"
if core.settings:get_bool("enable_server") then
retval = retval ..
"button[8.5,5;3.25,0.5;play;".. fgettext("Host Game") .. "]" ..
"checkbox[0.25,1.6;cb_server_announce;" .. fgettext("Announce Server") .. ";" ..
dump(core.settings:get_bool("server_announce")) .. "]" ..
"label[0.25,2.2;" .. fgettext("Name/Password") .. "]" ..
"field[0.55,3.2;3.5,0.5;te_playername;;" ..
core.formspec_escape(core.settings:get("name")) .. "]" ..
"pwdfield[0.55,4;3.5,0.5;te_passwd;]"
local bind_addr = core.settings:get("bind_address")
if bind_addr ~= nil and bind_addr ~= "" then
retval = retval ..
"field[0.55,5.2;2.25,0.5;te_serveraddr;" .. fgettext("Bind Address") .. ";" ..
core.formspec_escape(core.settings:get("bind_address")) .. "]" ..
"field[2.8,5.2;1.25,0.5;te_serverport;" .. fgettext("Port") .. ";" ..
core.formspec_escape(core.settings:get("port")) .. "]"
else
retval = retval ..
"field[0.55,5.2;3.5,0.5;te_serverport;" .. fgettext("Server Port") .. ";" ..
core.formspec_escape(core.settings:get("port")) .. "]"
end
else
retval = retval ..
"button[8.5,5;3.25,0.5;play;".. fgettext("Play Game") .. "]"
end
return retval return retval
end end
local function main_button_handler(this, fields, name, tabdata) local function main_button_handler(this, fields, name, tabdata)
assert(name == "singleplayer") assert(name == "local")
local world_doubleclick = false local world_doubleclick = false
@ -125,7 +154,7 @@ local function main_button_handler(this, fields, name, tabdata)
end end
if event.type == "CHG" and selected ~= nil then if event.type == "CHG" and selected ~= nil then
core.setting_set("mainmenu_last_selected_world", core.settings:set("mainmenu_last_selected_world",
menudata.worldlist:get_raw_index(selected)) menudata.worldlist:get_raw_index(selected))
return true return true
end end
@ -136,7 +165,7 @@ local function main_button_handler(this, fields, name, tabdata)
end end
if fields["cb_creative_mode"] then if fields["cb_creative_mode"] then
core.setting_set("creative_mode", fields["cb_creative_mode"]) core.settings:set("creative_mode", fields["cb_creative_mode"])
local selected = core.get_textlist_index("sp_worlds") local selected = core.get_textlist_index("sp_worlds")
menu_worldmt(selected, "creative_mode", fields["cb_creative_mode"]) menu_worldmt(selected, "creative_mode", fields["cb_creative_mode"])
@ -144,27 +173,65 @@ local function main_button_handler(this, fields, name, tabdata)
end end
if fields["cb_enable_damage"] then if fields["cb_enable_damage"] then
core.setting_set("enable_damage", fields["cb_enable_damage"]) core.settings:set("enable_damage", fields["cb_enable_damage"])
local selected = core.get_textlist_index("sp_worlds") local selected = core.get_textlist_index("sp_worlds")
menu_worldmt(selected, "enable_damage", fields["cb_enable_damage"]) menu_worldmt(selected, "enable_damage", fields["cb_enable_damage"])
return true return true
end end
if fields["play"] ~= nil or if fields["cb_server"] then
world_doubleclick or core.settings:set("enable_server", fields["cb_server"])
fields["key_enter"] then
return true
end
if fields["cb_server_announce"] then
core.settings:set("server_announce", fields["cb_server_announce"])
local selected = core.get_textlist_index("srv_worlds")
menu_worldmt(selected, "server_announce", fields["cb_server_announce"])
return true
end
if fields["play"] ~= nil or world_doubleclick or fields["key_enter"] then
local selected = core.get_textlist_index("sp_worlds") local selected = core.get_textlist_index("sp_worlds")
gamedata.selected_world = menudata.worldlist:get_raw_index(selected) gamedata.selected_world = menudata.worldlist:get_raw_index(selected)
if selected ~= nil and gamedata.selected_world ~= 0 then if core.settings:get_bool("enable_server") then
gamedata.singleplayer = true if selected ~= nil and gamedata.selected_world ~= 0 then
core.start() gamedata.playername = fields["te_playername"]
gamedata.password = fields["te_passwd"]
gamedata.port = fields["te_serverport"]
gamedata.address = ""
core.settings:set("port",gamedata.port)
if fields["te_serveraddr"] ~= nil then
core.settings:set("bind_address",fields["te_serveraddr"])
end
--update last game
local world = menudata.worldlist:get_raw_element(gamedata.selected_world)
if world then
local game, index = gamemgr.find_by_gameid(world.gameid)
core.settings:set("menu_last_game", game.id)
end
core.start()
else
gamedata.errormessage =
fgettext("No world created or selected!")
end
else else
gamedata.errormessage = if selected ~= nil and gamedata.selected_world ~= 0 then
fgettext("No world created or selected!") gamedata.singleplayer = true
core.start()
else
gamedata.errormessage =
fgettext("No world created or selected!")
end
return true
end end
return true
end end
if fields["world_create"] ~= nil then if fields["world_create"] ~= nil then
@ -192,7 +259,7 @@ local function main_button_handler(this, fields, name, tabdata)
mm_texture.update("singleplayer",current_game()) mm_texture.update("singleplayer",current_game())
end end
end end
return true return true
end end
@ -202,7 +269,7 @@ local function main_button_handler(this, fields, name, tabdata)
local configdialog = local configdialog =
create_configure_world_dlg( create_configure_world_dlg(
menudata.worldlist:get_raw_index(selected)) menudata.worldlist:get_raw_index(selected))
if (configdialog ~= nil) then if (configdialog ~= nil) then
configdialog:set_parent(this) configdialog:set_parent(this)
this:hide() this:hide()
@ -210,22 +277,22 @@ local function main_button_handler(this, fields, name, tabdata)
mm_texture.update("singleplayer",current_game()) mm_texture.update("singleplayer",current_game())
end end
end end
return true return true
end end
end end
local function on_change(type, old_tab, new_tab) local function on_change(type, old_tab, new_tab)
local buttonbar = ui.find_by_name("game_button_bar") local buttonbar = ui.find_by_name("game_button_bar")
if ( buttonbar == nil ) then if ( buttonbar == nil ) then
singleplayer_refresh_gamebar() singleplayer_refresh_gamebar()
buttonbar = ui.find_by_name("game_button_bar") buttonbar = ui.find_by_name("game_button_bar")
end end
if (type == "ENTER") then if (type == "ENTER") then
local game = current_game() local game = current_game()
if game then if game then
menudata.worldlist:set_filtercriteria(game.id) menudata.worldlist:set_filtercriteria(game.id)
core.set_topleft_text(game.name) core.set_topleft_text(game.name)
@ -242,8 +309,8 @@ end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
return { return {
name = "singleplayer", name = "local",
caption = fgettext("Singleplayer"), caption = fgettext("Local Game"),
cbf_formspec = get_formspec, cbf_formspec = get_formspec,
cbf_button_handler = main_button_handler, cbf_button_handler = main_button_handler,
on_change = on_change on_change = on_change

View File

@ -75,7 +75,7 @@ local function get_formspec(tabview, name, tabdata)
if error == nil then if error == nil then
local descriptiontext = descriptionfile:read("*all") local descriptiontext = descriptionfile:read("*all")
descriptionlines = core.splittext(descriptiontext,42) descriptionlines = core.wrap_text(descriptiontext, 42)
descriptionfile:close() descriptionfile:close()
else else
descriptionlines = {} descriptionlines = {}

View File

@ -39,14 +39,14 @@ local function get_formspec(tabview, name, tabdata)
-- Address / Port -- Address / Port
"label[7.75,-0.25;" .. fgettext("Address / Port") .. "]" .. "label[7.75,-0.25;" .. fgettext("Address / Port") .. "]" ..
"field[8,0.65;3.25,0.5;te_address;;" .. "field[8,0.65;3.25,0.5;te_address;;" ..
core.formspec_escape(core.setting_get("address")) .. "]" .. core.formspec_escape(core.settings:get("address")) .. "]" ..
"field[11.1,0.65;1.4,0.5;te_port;;" .. "field[11.1,0.65;1.4,0.5;te_port;;" ..
core.formspec_escape(core.setting_get("remote_port")) .. "]" .. core.formspec_escape(core.settings:get("remote_port")) .. "]" ..
-- Name / Password -- Name / Password
"label[7.75,0.95;" .. fgettext("Name / Password") .. "]" .. "label[7.75,0.95;" .. fgettext("Name / Password") .. "]" ..
"field[8,1.85;2.9,0.5;te_name;;" .. "field[8,1.85;2.9,0.5;te_name;;" ..
core.formspec_escape(core.setting_get("name")) .. "]" .. core.formspec_escape(core.settings:get("name")) .. "]" ..
"pwdfield[10.73,1.85;1.77,0.5;te_pwd;]" .. "pwdfield[10.73,1.85;1.77,0.5;te_pwd;]" ..
-- Description Background -- Description Background
@ -135,7 +135,7 @@ local function main_button_handler(tabview, fields, name, tabdata)
if fields.te_name then if fields.te_name then
gamedata.playername = fields.te_name gamedata.playername = fields.te_name
core.setting_set("name", fields.te_name) core.settings:set("name", fields.te_name)
end end
if fields.favourites then if fields.favourites then
@ -163,8 +163,8 @@ local function main_button_handler(tabview, fields, name, tabdata)
gamedata.serverdescription = fav.description gamedata.serverdescription = fav.description
if gamedata.address and gamedata.port then if gamedata.address and gamedata.port then
core.setting_set("address", gamedata.address) core.settings:set("address", gamedata.address)
core.setting_set("remote_port", gamedata.port) core.settings:set("remote_port", gamedata.port)
core.start() core.start()
end end
end end
@ -187,8 +187,8 @@ local function main_button_handler(tabview, fields, name, tabdata)
end end
if address and port then if address and port then
core.setting_set("address", address) core.settings:set("address", address)
core.setting_set("remote_port", port) core.settings:set("remote_port", port)
end end
tabdata.fav_selected = event.row tabdata.fav_selected = event.row
end end
@ -219,8 +219,8 @@ local function main_button_handler(tabview, fields, name, tabdata)
local port = fav.port local port = fav.port
gamedata.serverdescription = fav.description gamedata.serverdescription = fav.description
if address and port then if address and port then
core.setting_set("address", address) core.settings:set("address", address)
core.setting_set("remote_port", port) core.settings:set("remote_port", port)
end end
tabdata.fav_selected = fav_idx tabdata.fav_selected = fav_idx
@ -235,8 +235,8 @@ local function main_button_handler(tabview, fields, name, tabdata)
asyncOnlineFavourites() asyncOnlineFavourites()
tabdata.fav_selected = nil tabdata.fav_selected = nil
core.setting_set("address", "") core.settings:set("address", "")
core.setting_set("remote_port", "30000") core.settings:set("remote_port", "30000")
return true return true
end end
@ -293,13 +293,14 @@ local function main_button_handler(tabview, fields, name, tabdata)
end) end)
menudata.search_result = search_result menudata.search_result = search_result
local first_server = search_result[1] local first_server = search_result[1]
core.setting_set("address", first_server.address) core.settings:set("address", first_server.address)
core.setting_set("remote_port", first_server.port) core.settings:set("remote_port", first_server.port)
end end
return true return true
end end
if (fields.btn_mp_connect or fields.key_enter) and fields.te_address and fields.te_port then if (fields.btn_mp_connect or fields.key_enter)
and fields.te_address ~= "" and fields.te_port then
gamedata.playername = fields.te_name gamedata.playername = fields.te_name
gamedata.password = fields.te_pwd gamedata.password = fields.te_pwd
gamedata.address = fields.te_address gamedata.address = fields.te_address
@ -325,8 +326,8 @@ local function main_button_handler(tabview, fields, name, tabdata)
gamedata.serverdescription = "" gamedata.serverdescription = ""
end end
core.setting_set("address", fields.te_address) core.settings:set("address", fields.te_address)
core.setting_set("remote_port", fields.te_port) core.settings:set("remote_port", fields.te_port)
core.start() core.start()
return true return true
@ -341,8 +342,8 @@ end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
return { return {
name = "multiplayer", name = "online",
caption = fgettext("Client"), caption = fgettext("Play Online"),
cbf_formspec = get_formspec, cbf_formspec = get_formspec,
cbf_button_handler = main_button_handler, cbf_button_handler = main_button_handler,
on_change = on_change on_change = on_change

View File

@ -1,195 +0,0 @@
--Minetest
--Copyright (C) 2014 sapier
--
--This program is free software; you can redistribute it and/or modify
--it under the terms of the GNU Lesser General Public License as published by
--the Free Software Foundation; either version 2.1 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,
--but WITHOUT ANY WARRANTY; without even the implied warranty of
--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
--GNU Lesser General Public License for more details.
--
--You should have received a copy of the GNU Lesser General Public License along
--with this program; if not, write to the Free Software Foundation, Inc.,
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
--------------------------------------------------------------------------------
local function get_formspec(tabview, name, tabdata)
local index = menudata.worldlist:get_current_index(
tonumber(core.setting_get("mainmenu_last_selected_world"))
)
local retval =
"button[4,4.15;2.6,0.5;world_delete;" .. fgettext("Delete") .. "]" ..
"button[6.5,4.15;2.8,0.5;world_create;" .. fgettext("New") .. "]" ..
"button[9.2,4.15;2.55,0.5;world_configure;" .. fgettext("Configure") .. "]" ..
"button[8.5,5;3.25,0.5;start_server;" .. fgettext("Start Game") .. "]" ..
"label[4,-0.25;" .. fgettext("Select World:") .. "]" ..
"checkbox[0.25,0.25;cb_creative_mode;" .. fgettext("Creative Mode") .. ";" ..
dump(core.setting_getbool("creative_mode")) .. "]" ..
"checkbox[0.25,0.7;cb_enable_damage;" .. fgettext("Enable Damage") .. ";" ..
dump(core.setting_getbool("enable_damage")) .. "]" ..
"checkbox[0.25,1.15;cb_server_announce;" .. fgettext("Public") .. ";" ..
dump(core.setting_getbool("server_announce")) .. "]" ..
"label[0.25,2.2;" .. fgettext("Name/Password") .. "]" ..
"field[0.55,3.2;3.5,0.5;te_playername;;" ..
core.formspec_escape(core.setting_get("name")) .. "]" ..
"pwdfield[0.55,4;3.5,0.5;te_passwd;]"
local bind_addr = core.setting_get("bind_address")
if bind_addr ~= nil and bind_addr ~= "" then
retval = retval ..
"field[0.55,5.2;2.25,0.5;te_serveraddr;" .. fgettext("Bind Address") .. ";" ..
core.formspec_escape(core.setting_get("bind_address")) .. "]" ..
"field[2.8,5.2;1.25,0.5;te_serverport;" .. fgettext("Port") .. ";" ..
core.formspec_escape(core.setting_get("port")) .. "]"
else
retval = retval ..
"field[0.55,5.2;3.5,0.5;te_serverport;" .. fgettext("Server Port") .. ";" ..
core.formspec_escape(core.setting_get("port")) .. "]"
end
retval = retval ..
"textlist[4,0.25;7.5,3.7;srv_worlds;" ..
menu_render_worldlist() ..
";" .. index .. "]"
return retval
end
--------------------------------------------------------------------------------
local function main_button_handler(this, fields, name, tabdata)
local world_doubleclick = false
if fields["srv_worlds"] ~= nil then
local event = core.explode_textlist_event(fields["srv_worlds"])
local selected = core.get_textlist_index("srv_worlds")
menu_worldmt_legacy(selected)
if event.type == "DCL" then
world_doubleclick = true
end
if event.type == "CHG" then
core.setting_set("mainmenu_last_selected_world",
menudata.worldlist:get_raw_index(core.get_textlist_index("srv_worlds")))
return true
end
end
if menu_handle_key_up_down(fields,"srv_worlds","mainmenu_last_selected_world") then
return true
end
if fields["cb_creative_mode"] then
core.setting_set("creative_mode", fields["cb_creative_mode"])
local selected = core.get_textlist_index("srv_worlds")
menu_worldmt(selected, "creative_mode", fields["cb_creative_mode"])
return true
end
if fields["cb_enable_damage"] then
core.setting_set("enable_damage", fields["cb_enable_damage"])
local selected = core.get_textlist_index("srv_worlds")
menu_worldmt(selected, "enable_damage", fields["cb_enable_damage"])
return true
end
if fields["cb_server_announce"] then
core.setting_set("server_announce", fields["cb_server_announce"])
local selected = core.get_textlist_index("srv_worlds")
menu_worldmt(selected, "server_announce", fields["cb_server_announce"])
return true
end
if fields["start_server"] ~= nil or
world_doubleclick or
fields["key_enter"] then
local selected = core.get_textlist_index("srv_worlds")
gamedata.selected_world = menudata.worldlist:get_raw_index(selected)
if selected ~= nil and gamedata.selected_world ~= 0 then
gamedata.playername = fields["te_playername"]
gamedata.password = fields["te_passwd"]
gamedata.port = fields["te_serverport"]
gamedata.address = ""
core.setting_set("port",gamedata.port)
if fields["te_serveraddr"] ~= nil then
core.setting_set("bind_address",fields["te_serveraddr"])
end
--update last game
local world = menudata.worldlist:get_raw_element(gamedata.selected_world)
if world then
local game, index = gamemgr.find_by_gameid(world.gameid)
core.setting_set("menu_last_game", game.id)
end
core.start()
else
gamedata.errormessage =
fgettext("No world created or selected!")
end
return true
end
if fields["world_create"] ~= nil then
local create_world_dlg = create_create_world_dlg(true)
create_world_dlg:set_parent(this)
create_world_dlg:show()
this:hide()
return true
end
if fields["world_delete"] ~= nil then
local selected = core.get_textlist_index("srv_worlds")
if selected ~= nil and
selected <= menudata.worldlist:size() then
local world = menudata.worldlist:get_list()[selected]
if world ~= nil and
world.name ~= nil and
world.name ~= "" then
local index = menudata.worldlist:get_raw_index(selected)
local delete_world_dlg = create_delete_world_dlg(world.name,index)
delete_world_dlg:set_parent(this)
delete_world_dlg:show()
this:hide()
end
end
return true
end
if fields["world_configure"] ~= nil then
local selected = core.get_textlist_index("srv_worlds")
if selected ~= nil then
local configdialog =
create_configure_world_dlg(
menudata.worldlist:get_raw_index(selected))
if (configdialog ~= nil) then
configdialog:set_parent(this)
configdialog:show()
this:hide()
end
end
return true
end
return false
end
--------------------------------------------------------------------------------
return {
name = "server",
caption = fgettext("Server"),
cbf_formspec = get_formspec,
cbf_button_handler = main_button_handler,
on_change = nil
}

View File

@ -25,7 +25,8 @@ local labels = {
}, },
node_highlighting = { node_highlighting = {
fgettext("Node Outlining"), fgettext("Node Outlining"),
fgettext("Node Highlighting") fgettext("Node Highlighting"),
fgettext("None")
}, },
filters = { filters = {
fgettext("No Filter"), fgettext("No Filter"),
@ -52,7 +53,7 @@ local dd_options = {
}, },
node_highlighting = { node_highlighting = {
table.concat(labels.node_highlighting, ","), table.concat(labels.node_highlighting, ","),
{"box", "halo"} {"box", "halo", "none"}
}, },
filters = { filters = {
table.concat(labels.filters, ","), table.concat(labels.filters, ","),
@ -70,39 +71,39 @@ local dd_options = {
local getSettingIndex = { local getSettingIndex = {
Leaves = function() Leaves = function()
local style = core.setting_get("leaves_style") local style = core.settings:get("leaves_style")
for idx, name in pairs(dd_options.leaves[2]) do for idx, name in pairs(dd_options.leaves[2]) do
if style == name then return idx end if style == name then return idx end
end end
return 1 return 1
end, end,
NodeHighlighting = function() NodeHighlighting = function()
local style = core.setting_get("node_highlighting") local style = core.settings:get("node_highlighting")
for idx, name in pairs(dd_options.node_highlighting[2]) do for idx, name in pairs(dd_options.node_highlighting[2]) do
if style == name then return idx end if style == name then return idx end
end end
return 1 return 1
end, end,
Filter = function() Filter = function()
if core.setting_get(dd_options.filters[2][3]) == "true" then if core.settings:get(dd_options.filters[2][3]) == "true" then
return 3 return 3
elseif core.setting_get(dd_options.filters[2][3]) == "false" and elseif core.settings:get(dd_options.filters[2][3]) == "false" and
core.setting_get(dd_options.filters[2][2]) == "true" then core.settings:get(dd_options.filters[2][2]) == "true" then
return 2 return 2
end end
return 1 return 1
end, end,
Mipmap = function() Mipmap = function()
if core.setting_get(dd_options.mipmap[2][3]) == "true" then if core.settings:get(dd_options.mipmap[2][3]) == "true" then
return 3 return 3
elseif core.setting_get(dd_options.mipmap[2][3]) == "false" and elseif core.settings:get(dd_options.mipmap[2][3]) == "false" and
core.setting_get(dd_options.mipmap[2][2]) == "true" then core.settings:get(dd_options.mipmap[2][2]) == "true" then
return 2 return 2
end end
return 1 return 1
end, end,
Antialiasing = function() Antialiasing = function()
local antialiasing_setting = core.setting_get("fsaa") local antialiasing_setting = core.settings:get("fsaa")
for i = 1, #dd_options.antialiasing[2] do for i = 1, #dd_options.antialiasing[2] do
if antialiasing_setting == dd_options.antialiasing[2][i] then if antialiasing_setting == dd_options.antialiasing[2][i] then
return i return i
@ -177,20 +178,20 @@ local function formspec(tabview, name, tabdata)
local tab_string = local tab_string =
"box[0,0;3.5,4.5;#999999]" .. "box[0,0;3.5,4.5;#999999]" ..
"checkbox[0.25,0;cb_smooth_lighting;" .. fgettext("Smooth Lighting") .. ";" "checkbox[0.25,0;cb_smooth_lighting;" .. fgettext("Smooth Lighting") .. ";"
.. dump(core.setting_getbool("smooth_lighting")) .. "]" .. .. dump(core.settings:get_bool("smooth_lighting")) .. "]" ..
"checkbox[0.25,0.5;cb_particles;" .. fgettext("Particles") .. ";" "checkbox[0.25,0.5;cb_particles;" .. fgettext("Particles") .. ";"
.. dump(core.setting_getbool("enable_particles")) .. "]" .. .. dump(core.settings:get_bool("enable_particles")) .. "]" ..
"checkbox[0.25,1;cb_3d_clouds;" .. fgettext("3D Clouds") .. ";" "checkbox[0.25,1;cb_3d_clouds;" .. fgettext("3D Clouds") .. ";"
.. dump(core.setting_getbool("enable_3d_clouds")) .. "]" .. .. dump(core.settings:get_bool("enable_3d_clouds")) .. "]" ..
"checkbox[0.25,1.5;cb_opaque_water;" .. fgettext("Opaque Water") .. ";" "checkbox[0.25,1.5;cb_opaque_water;" .. fgettext("Opaque Water") .. ";"
.. dump(core.setting_getbool("opaque_water")) .. "]" .. .. dump(core.settings:get_bool("opaque_water")) .. "]" ..
"checkbox[0.25,2.0;cb_connected_glass;" .. fgettext("Connected Glass") .. ";" "checkbox[0.25,2.0;cb_connected_glass;" .. fgettext("Connected Glass") .. ";"
.. dump(core.setting_getbool("connected_glass")) .. "]" .. .. dump(core.settings:get_bool("connected_glass")) .. "]" ..
"dropdown[0.25,2.8;3.3;dd_node_highlighting;" .. dd_options.node_highlighting[1] .. ";" "dropdown[0.25,2.8;3.3;dd_node_highlighting;" .. dd_options.node_highlighting[1] .. ";"
.. getSettingIndex.NodeHighlighting() .. "]" .. .. getSettingIndex.NodeHighlighting() .. "]" ..
"dropdown[0.25,3.6;3.3;dd_leaves_style;" .. dd_options.leaves[1] .. ";" "dropdown[0.25,3.6;3.3;dd_leaves_style;" .. dd_options.leaves[1] .. ";"
.. getSettingIndex.Leaves() .. "]" .. .. getSettingIndex.Leaves() .. "]" ..
"box[3.75,0;3.75,3.45;#999999]" .. "box[3.75,0;3.75,4.45;#999999]" ..
"label[3.85,0.1;" .. fgettext("Texturing:") .. "]" .. "label[3.85,0.1;" .. fgettext("Texturing:") .. "]" ..
"dropdown[3.85,0.55;3.85;dd_filters;" .. dd_options.filters[1] .. ";" "dropdown[3.85,0.55;3.85;dd_filters;" .. dd_options.filters[1] .. ";"
.. getSettingIndex.Filter() .. "]" .. .. getSettingIndex.Filter() .. "]" ..
@ -199,9 +200,12 @@ local function formspec(tabview, name, tabdata)
"label[3.85,2.15;" .. fgettext("Antialiasing:") .. "]" .. "label[3.85,2.15;" .. fgettext("Antialiasing:") .. "]" ..
"dropdown[3.85,2.6;3.85;dd_antialiasing;" .. dd_options.antialiasing[1] .. ";" "dropdown[3.85,2.6;3.85;dd_antialiasing;" .. dd_options.antialiasing[1] .. ";"
.. getSettingIndex.Antialiasing() .. "]" .. .. getSettingIndex.Antialiasing() .. "]" ..
"label[3.85,3.45;" .. fgettext("Screen:") .. "]" ..
"checkbox[3.85,3.6;cb_autosave_screensize;" .. fgettext("Autosave screen size") .. ";"
.. dump(core.settings:get_bool("autosave_screensize")) .. "]" ..
"box[7.75,0;4,4.4;#999999]" .. "box[7.75,0;4,4.4;#999999]" ..
"checkbox[8,0;cb_shaders;" .. fgettext("Shaders") .. ";" "checkbox[8,0;cb_shaders;" .. fgettext("Shaders") .. ";"
.. dump(core.setting_getbool("enable_shaders")) .. "]" .. dump(core.settings:get_bool("enable_shaders")) .. "]"
if PLATFORM == "Android" then if PLATFORM == "Android" then
tab_string = tab_string .. tab_string = tab_string ..
@ -218,29 +222,29 @@ local function formspec(tabview, name, tabdata)
.. fgettext("Advanced Settings") .. "]" .. fgettext("Advanced Settings") .. "]"
if core.setting_get("touchscreen_threshold") ~= nil then if core.settings:get("touchscreen_threshold") ~= nil then
tab_string = tab_string .. tab_string = tab_string ..
"label[4.3,4.1;" .. fgettext("Touchthreshold (px)") .. "]" .. "label[4.3,4.1;" .. fgettext("Touchthreshold (px)") .. "]" ..
"dropdown[3.85,4.55;3.85;dd_touchthreshold;0,10,20,30,40,50;" .. "dropdown[3.85,4.55;3.85;dd_touchthreshold;0,10,20,30,40,50;" ..
((tonumber(core.setting_get("touchscreen_threshold")) / 10) + 1) .. "]" ((tonumber(core.settings:get("touchscreen_threshold")) / 10) + 1) .. "]"
end end
if core.setting_getbool("enable_shaders") then if core.settings:get_bool("enable_shaders") then
tab_string = tab_string .. tab_string = tab_string ..
"checkbox[8,0.5;cb_bumpmapping;" .. fgettext("Bump Mapping") .. ";" "checkbox[8,0.5;cb_bumpmapping;" .. fgettext("Bump Mapping") .. ";"
.. dump(core.setting_getbool("enable_bumpmapping")) .. "]" .. .. dump(core.settings:get_bool("enable_bumpmapping")) .. "]" ..
"checkbox[8,1;cb_tonemapping;" .. fgettext("Tone Mapping") .. ";" "checkbox[8,1;cb_tonemapping;" .. fgettext("Tone Mapping") .. ";"
.. dump(core.setting_getbool("tone_mapping")) .. "]" .. .. dump(core.settings:get_bool("tone_mapping")) .. "]" ..
"checkbox[8,1.5;cb_generate_normalmaps;" .. fgettext("Normal Mapping") .. ";" "checkbox[8,1.5;cb_generate_normalmaps;" .. fgettext("Normal Mapping") .. ";"
.. dump(core.setting_getbool("generate_normalmaps")) .. "]" .. .. dump(core.settings:get_bool("generate_normalmaps")) .. "]" ..
"checkbox[8,2;cb_parallax;" .. fgettext("Parallax Occlusion") .. ";" "checkbox[8,2;cb_parallax;" .. fgettext("Parallax Occlusion") .. ";"
.. dump(core.setting_getbool("enable_parallax_occlusion")) .. "]" .. .. dump(core.settings:get_bool("enable_parallax_occlusion")) .. "]" ..
"checkbox[8,2.5;cb_waving_water;" .. fgettext("Waving Water") .. ";" "checkbox[8,2.5;cb_waving_water;" .. fgettext("Waving Water") .. ";"
.. dump(core.setting_getbool("enable_waving_water")) .. "]" .. .. dump(core.settings:get_bool("enable_waving_water")) .. "]" ..
"checkbox[8,3;cb_waving_leaves;" .. fgettext("Waving Leaves") .. ";" "checkbox[8,3;cb_waving_leaves;" .. fgettext("Waving Leaves") .. ";"
.. dump(core.setting_getbool("enable_waving_leaves")) .. "]" .. .. dump(core.settings:get_bool("enable_waving_leaves")) .. "]" ..
"checkbox[8,3.5;cb_waving_plants;" .. fgettext("Waving Plants") .. ";" "checkbox[8,3.5;cb_waving_plants;" .. fgettext("Waving Plants") .. ";"
.. dump(core.setting_getbool("enable_waving_plants")) .. "]" .. dump(core.settings:get_bool("enable_waving_plants")) .. "]"
else else
tab_string = tab_string .. tab_string = tab_string ..
"tablecolumns[color;text]" .. "tablecolumns[color;text]" ..
@ -271,60 +275,64 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
return true return true
end end
if fields["cb_smooth_lighting"] then if fields["cb_smooth_lighting"] then
core.setting_set("smooth_lighting", fields["cb_smooth_lighting"]) core.settings:set("smooth_lighting", fields["cb_smooth_lighting"])
return true return true
end end
if fields["cb_particles"] then if fields["cb_particles"] then
core.setting_set("enable_particles", fields["cb_particles"]) core.settings:set("enable_particles", fields["cb_particles"])
return true return true
end end
if fields["cb_3d_clouds"] then if fields["cb_3d_clouds"] then
core.setting_set("enable_3d_clouds", fields["cb_3d_clouds"]) core.settings:set("enable_3d_clouds", fields["cb_3d_clouds"])
return true return true
end end
if fields["cb_opaque_water"] then if fields["cb_opaque_water"] then
core.setting_set("opaque_water", fields["cb_opaque_water"]) core.settings:set("opaque_water", fields["cb_opaque_water"])
return true return true
end end
if fields["cb_connected_glass"] then if fields["cb_connected_glass"] then
core.setting_set("connected_glass", fields["cb_connected_glass"]) core.settings:set("connected_glass", fields["cb_connected_glass"])
return true
end
if fields["cb_autosave_screensize"] then
core.settings:set("autosave_screensize", fields["cb_autosave_screensize"])
return true return true
end end
if fields["cb_shaders"] then if fields["cb_shaders"] then
if (core.setting_get("video_driver") == "direct3d8" or if (core.settings:get("video_driver") == "direct3d8" or
core.setting_get("video_driver") == "direct3d9") then core.settings:get("video_driver") == "direct3d9") then
core.setting_set("enable_shaders", "false") core.settings:set("enable_shaders", "false")
gamedata.errormessage = fgettext("To enable shaders the OpenGL driver needs to be used.") gamedata.errormessage = fgettext("To enable shaders the OpenGL driver needs to be used.")
else else
core.setting_set("enable_shaders", fields["cb_shaders"]) core.settings:set("enable_shaders", fields["cb_shaders"])
end end
return true return true
end end
if fields["cb_bumpmapping"] then if fields["cb_bumpmapping"] then
core.setting_set("enable_bumpmapping", fields["cb_bumpmapping"]) core.settings:set("enable_bumpmapping", fields["cb_bumpmapping"])
return true return true
end end
if fields["cb_tonemapping"] then if fields["cb_tonemapping"] then
core.setting_set("tone_mapping", fields["cb_tonemapping"]) core.settings:set("tone_mapping", fields["cb_tonemapping"])
return true return true
end end
if fields["cb_generate_normalmaps"] then if fields["cb_generate_normalmaps"] then
core.setting_set("generate_normalmaps", fields["cb_generate_normalmaps"]) core.settings:set("generate_normalmaps", fields["cb_generate_normalmaps"])
return true return true
end end
if fields["cb_parallax"] then if fields["cb_parallax"] then
core.setting_set("enable_parallax_occlusion", fields["cb_parallax"]) core.settings:set("enable_parallax_occlusion", fields["cb_parallax"])
return true return true
end end
if fields["cb_waving_water"] then if fields["cb_waving_water"] then
core.setting_set("enable_waving_water", fields["cb_waving_water"]) core.settings:set("enable_waving_water", fields["cb_waving_water"])
return true return true
end end
if fields["cb_waving_leaves"] then if fields["cb_waving_leaves"] then
core.setting_set("enable_waving_leaves", fields["cb_waving_leaves"]) core.settings:set("enable_waving_leaves", fields["cb_waving_leaves"])
end end
if fields["cb_waving_plants"] then if fields["cb_waving_plants"] then
core.setting_set("enable_waving_plants", fields["cb_waving_plants"]) core.settings:set("enable_waving_plants", fields["cb_waving_plants"])
return true return true
end end
if fields["btn_change_keys"] then if fields["btn_change_keys"] then
@ -332,7 +340,7 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
return true return true
end end
if fields["cb_touchscreen_target"] then if fields["cb_touchscreen_target"] then
core.setting_set("touchtarget", fields["cb_touchscreen_target"]) core.settings:set("touchtarget", fields["cb_touchscreen_target"])
return true return true
end end
if fields["btn_reset_singleplayer"] then if fields["btn_reset_singleplayer"] then
@ -345,49 +353,49 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
for i = 1, #labels.leaves do for i = 1, #labels.leaves do
if fields["dd_leaves_style"] == labels.leaves[i] then if fields["dd_leaves_style"] == labels.leaves[i] then
core.setting_set("leaves_style", dd_options.leaves[2][i]) core.settings:set("leaves_style", dd_options.leaves[2][i])
ddhandled = true ddhandled = true
end end
end end
for i = 1, #labels.node_highlighting do for i = 1, #labels.node_highlighting do
if fields["dd_node_highlighting"] == labels.node_highlighting[i] then if fields["dd_node_highlighting"] == labels.node_highlighting[i] then
core.setting_set("node_highlighting", dd_options.node_highlighting[2][i]) core.settings:set("node_highlighting", dd_options.node_highlighting[2][i])
ddhandled = true ddhandled = true
end end
end end
if fields["dd_filters"] == labels.filters[1] then if fields["dd_filters"] == labels.filters[1] then
core.setting_set("bilinear_filter", "false") core.settings:set("bilinear_filter", "false")
core.setting_set("trilinear_filter", "false") core.settings:set("trilinear_filter", "false")
ddhandled = true ddhandled = true
elseif fields["dd_filters"] == labels.filters[2] then elseif fields["dd_filters"] == labels.filters[2] then
core.setting_set("bilinear_filter", "true") core.settings:set("bilinear_filter", "true")
core.setting_set("trilinear_filter", "false") core.settings:set("trilinear_filter", "false")
ddhandled = true ddhandled = true
elseif fields["dd_filters"] == labels.filters[3] then elseif fields["dd_filters"] == labels.filters[3] then
core.setting_set("bilinear_filter", "false") core.settings:set("bilinear_filter", "false")
core.setting_set("trilinear_filter", "true") core.settings:set("trilinear_filter", "true")
ddhandled = true ddhandled = true
end end
if fields["dd_mipmap"] == labels.mipmap[1] then if fields["dd_mipmap"] == labels.mipmap[1] then
core.setting_set("mip_map", "false") core.settings:set("mip_map", "false")
core.setting_set("anisotropic_filter", "false") core.settings:set("anisotropic_filter", "false")
ddhandled = true ddhandled = true
elseif fields["dd_mipmap"] == labels.mipmap[2] then elseif fields["dd_mipmap"] == labels.mipmap[2] then
core.setting_set("mip_map", "true") core.settings:set("mip_map", "true")
core.setting_set("anisotropic_filter", "false") core.settings:set("anisotropic_filter", "false")
ddhandled = true ddhandled = true
elseif fields["dd_mipmap"] == labels.mipmap[3] then elseif fields["dd_mipmap"] == labels.mipmap[3] then
core.setting_set("mip_map", "true") core.settings:set("mip_map", "true")
core.setting_set("anisotropic_filter", "true") core.settings:set("anisotropic_filter", "true")
ddhandled = true ddhandled = true
end end
if fields["dd_antialiasing"] then if fields["dd_antialiasing"] then
core.setting_set("fsaa", core.settings:set("fsaa",
antialiasing_fname_to_name(fields["dd_antialiasing"])) antialiasing_fname_to_name(fields["dd_antialiasing"]))
ddhandled = true ddhandled = true
end end
if fields["dd_touchthreshold"] then if fields["dd_touchthreshold"] then
core.setting_set("touchscreen_threshold", fields["dd_touchthreshold"]) core.settings:set("touchscreen_threshold", fields["dd_touchthreshold"])
ddhandled = true ddhandled = true
end end

View File

@ -25,12 +25,12 @@ local function get_formspec(tabview, name, tabdata)
local retval = local retval =
"label[9.5,0;".. fgettext("Name / Password") .. "]" .. "label[9.5,0;".. fgettext("Name / Password") .. "]" ..
"field[0.25,3.35;5.5,0.5;te_address;;" .. "field[0.25,3.35;5.5,0.5;te_address;;" ..
core.formspec_escape(core.setting_get("address")) .."]" .. core.formspec_escape(core.settings:get("address")) .."]" ..
"field[5.75,3.35;2.25,0.5;te_port;;" .. "field[5.75,3.35;2.25,0.5;te_port;;" ..
core.formspec_escape(core.setting_get("remote_port")) .."]" .. core.formspec_escape(core.settings:get("remote_port")) .."]" ..
"button[10,2.6;2,1.5;btn_mp_connect;".. fgettext("Connect") .. "]" .. "button[10,2.6;2,1.5;btn_mp_connect;".. fgettext("Connect") .. "]" ..
"field[9.8,1;2.6,0.5;te_name;;" .. "field[9.8,1;2.6,0.5;te_name;;" ..
core.formspec_escape(core.setting_get("name")) .."]" .. core.formspec_escape(core.settings:get("name")) .."]" ..
"pwdfield[9.8,2;2.6,0.5;te_pwd;]" "pwdfield[9.8,2;2.6,0.5;te_pwd;]"
@ -89,9 +89,9 @@ local function get_formspec(tabview, name, tabdata)
-- checkboxes -- checkboxes
retval = retval .. retval = retval ..
"checkbox[8.0,3.9;cb_creative;".. fgettext("Creative Mode") .. ";" .. "checkbox[8.0,3.9;cb_creative;".. fgettext("Creative Mode") .. ";" ..
dump(core.setting_getbool("creative_mode")) .. "]".. dump(core.settings:get_bool("creative_mode")) .. "]"..
"checkbox[8.0,4.4;cb_damage;".. fgettext("Enable Damage") .. ";" .. "checkbox[8.0,4.4;cb_damage;".. fgettext("Enable Damage") .. ";" ..
dump(core.setting_getbool("enable_damage")) .. "]" dump(core.settings:get_bool("enable_damage")) .. "]"
-- buttons -- buttons
retval = retval .. retval = retval ..
"button[0,3.7;8,1.5;btn_start_singleplayer;" .. fgettext("Start Singleplayer") .. "]" .. "button[0,3.7;8,1.5;btn_start_singleplayer;" .. fgettext("Start Singleplayer") .. "]" ..
@ -128,8 +128,8 @@ local function main_button_handler(tabview, fields, name, tabdata)
end end
if address and port then if address and port then
core.setting_set("address", address) core.settings:set("address", address)
core.setting_set("remote_port", port) core.settings:set("remote_port", port)
end end
tabdata.fav_selected = event.row tabdata.fav_selected = event.row
end end
@ -145,18 +145,18 @@ local function main_button_handler(tabview, fields, name, tabdata)
asyncOnlineFavourites() asyncOnlineFavourites()
tabdata.fav_selected = nil tabdata.fav_selected = nil
core.setting_set("address", "") core.settings:set("address", "")
core.setting_set("remote_port", "30000") core.settings:set("remote_port", "30000")
return true return true
end end
if fields.cb_creative then if fields.cb_creative then
core.setting_set("creative_mode", fields.cb_creative) core.settings:set("creative_mode", fields.cb_creative)
return true return true
end end
if fields.cb_damage then if fields.cb_damage then
core.setting_set("enable_damage", fields.cb_damage) core.settings:set("enable_damage", fields.cb_damage)
return true return true
end end
@ -186,12 +186,12 @@ local function main_button_handler(tabview, fields, name, tabdata)
gamedata.selected_world = 0 gamedata.selected_world = 0
core.setting_set("address", fields.te_address) core.settings:set("address", fields.te_address)
core.setting_set("remote_port", fields.te_port) core.settings:set("remote_port", fields.te_port)
core.start() core.start()
return true return true
end end
if fields.btn_config_sp_world then if fields.btn_config_sp_world then
local configdialog = create_configure_world_dlg(1) local configdialog = create_configure_world_dlg(1)

View File

@ -54,9 +54,9 @@ local function get_formspec(tabview, name, tabdata)
local retval = "label[4,-0.25;" .. fgettext("Select texture pack:") .. "]" .. local retval = "label[4,-0.25;" .. fgettext("Select texture pack:") .. "]" ..
"textlist[4,0.25;7.5,5.0;TPs;" "textlist[4,0.25;7.5,5.0;TPs;"
local current_texture_path = core.setting_get("texture_path") local current_texture_path = core.settings:get("texture_path")
local list = filter_texture_pack_list(core.get_dir_list(core.get_texturepath(), true)) local list = filter_texture_pack_list(core.get_dir_list(core.get_texturepath(), true))
local index = tonumber(core.setting_get("mainmenu_last_selected_TP")) local index = tonumber(core.settings:get("mainmenu_last_selected_TP"))
if not index then index = 1 end if not index then index = 1 end
@ -106,7 +106,7 @@ local function main_button_handler(tabview, fields, name, tabdata)
local event = core.explode_textlist_event(fields["TPs"]) local event = core.explode_textlist_event(fields["TPs"])
if event.type == "CHG" or event.type == "DCL" then if event.type == "CHG" or event.type == "DCL" then
local index = core.get_textlist_index("TPs") local index = core.get_textlist_index("TPs")
core.setting_set("mainmenu_last_selected_TP", index) core.settings:set("mainmenu_last_selected_TP", index)
local list = filter_texture_pack_list(core.get_dir_list(core.get_texturepath(), true)) local list = filter_texture_pack_list(core.get_dir_list(core.get_texturepath(), true))
local current_index = core.get_textlist_index("TPs") local current_index = core.get_textlist_index("TPs")
if current_index and #list >= current_index then if current_index and #list >= current_index then
@ -114,7 +114,7 @@ local function main_button_handler(tabview, fields, name, tabdata)
if list[current_index] == fgettext("None") then if list[current_index] == fgettext("None") then
new_path = "" new_path = ""
end end
core.setting_set("texture_path", new_path) core.settings:set("texture_path", new_path)
end end
end end
return true return true

View File

@ -24,7 +24,7 @@ function mm_texture.init()
DIR_DELIM .. "pack" .. DIR_DELIM DIR_DELIM .. "pack" .. DIR_DELIM
mm_texture.basetexturedir = mm_texture.defaulttexturedir mm_texture.basetexturedir = mm_texture.defaulttexturedir
mm_texture.texturepack = core.setting_get("texture_path") mm_texture.texturepack = core.settings:get("texture_path")
mm_texture.gameid = nil mm_texture.gameid = nil
end end
@ -61,7 +61,7 @@ function mm_texture.reset()
mm_texture.set_generic("header") mm_texture.set_generic("header")
if not have_bg then if not have_bg then
if core.setting_getbool("menu_clouds") then if core.settings:get_bool("menu_clouds") then
core.set_clouds(true) core.set_clouds(true)
else else
mm_texture.set_dirt_bg() mm_texture.set_dirt_bg()
@ -88,7 +88,7 @@ function mm_texture.update_game(gamedetails)
if not have_bg then if not have_bg then
if core.setting_getbool("menu_clouds") then if core.settings:get_bool("menu_clouds") then
core.set_clouds(true) core.set_clouds(true)
else else
mm_texture.set_dirt_bg() mm_texture.set_dirt_bg()

View File

@ -15,10 +15,18 @@
--with this program; if not, write to the Free Software Foundation, Inc., --with this program; if not, write to the Free Software Foundation, Inc.,
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
local function get_bool_default(name, default)
local val = core.settings:get_bool(name)
if val == nil then
return default
end
return val
end
local profiler_path = core.get_builtin_path()..DIR_DELIM.."profiler"..DIR_DELIM local profiler_path = core.get_builtin_path()..DIR_DELIM.."profiler"..DIR_DELIM
local profiler = {} local profiler = {}
local sampler = assert(loadfile(profiler_path .. "sampling.lua"))(profiler) local sampler = assert(loadfile(profiler_path .. "sampling.lua"))(profiler)
local instrumentation = assert(loadfile(profiler_path .. "instrumentation.lua"))(profiler, sampler) local instrumentation = assert(loadfile(profiler_path .. "instrumentation.lua"))(profiler, sampler, get_bool_default)
local reporter = dofile(profiler_path .. "reporter.lua") local reporter = dofile(profiler_path .. "reporter.lua")
profiler.instrument = instrumentation.instrument profiler.instrument = instrumentation.instrument
@ -27,7 +35,7 @@ profiler.instrument = instrumentation.instrument
-- Is called later, after `core.register_chatcommand` was set up. -- Is called later, after `core.register_chatcommand` was set up.
-- --
function profiler.init_chatcommand() function profiler.init_chatcommand()
local instrument_profiler = core.setting_getbool("instrument.profiler") or false local instrument_profiler = get_bool_default("instrument.profiler", false)
if instrument_profiler then if instrument_profiler then
instrumentation.init_chatcommand() instrumentation.init_chatcommand()
end end

View File

@ -17,8 +17,9 @@
local format, pairs, type = string.format, pairs, type local format, pairs, type = string.format, pairs, type
local core, get_current_modname = core, core.get_current_modname local core, get_current_modname = core, core.get_current_modname
local profiler, sampler = ... local profiler, sampler, get_bool_default = ...
local instrument_builtin = core.setting_getbool("instrument.builtin") or false
local instrument_builtin = get_bool_default("instrument.builtin", false)
local register_functions = { local register_functions = {
register_globalstep = 0, register_globalstep = 0,
@ -137,7 +138,7 @@ local function instrument_register(func, func_name)
end end
local function init_chatcommand() local function init_chatcommand()
if core.setting_getbool("instrument.chatcommand") or true then if get_bool_default("instrument.chatcommand", true) then
local orig_register_chatcommand = core.register_chatcommand local orig_register_chatcommand = core.register_chatcommand
core.register_chatcommand = function(cmd, def) core.register_chatcommand = function(cmd, def)
def.func = instrument { def.func = instrument {
@ -153,8 +154,7 @@ end
-- Start instrumenting selected functions -- Start instrumenting selected functions
-- --
local function init() local function init()
local is_set = core.setting_getbool if get_bool_default("instrument.entity", true) then
if is_set("instrument.entity") or true then
-- Explicitly declare entity api-methods. -- Explicitly declare entity api-methods.
-- Simple iteration would ignore lookup via __index. -- Simple iteration would ignore lookup via __index.
local entity_instrumentation = { local entity_instrumentation = {
@ -180,7 +180,7 @@ local function init()
end end
end end
if is_set("instrument.abm") or true then if get_bool_default("instrument.abm", true) then
-- Wrap register_abm() to automatically instrument abms. -- Wrap register_abm() to automatically instrument abms.
local orig_register_abm = core.register_abm local orig_register_abm = core.register_abm
core.register_abm = function(spec) core.register_abm = function(spec)
@ -193,7 +193,7 @@ local function init()
end end
end end
if is_set("instrument.lbm") or true then if get_bool_default("instrument.lbm", true) then
-- Wrap register_lbm() to automatically instrument lbms. -- Wrap register_lbm() to automatically instrument lbms.
local orig_register_lbm = core.register_lbm local orig_register_lbm = core.register_lbm
core.register_lbm = function(spec) core.register_lbm = function(spec)
@ -206,13 +206,13 @@ local function init()
end end
end end
if is_set("instrument.global_callback") or true then if get_bool_default("instrument.global_callback", true) then
for func_name, _ in pairs(register_functions) do for func_name, _ in pairs(register_functions) do
core[func_name] = instrument_register(core[func_name], func_name) core[func_name] = instrument_register(core[func_name], func_name)
end end
end end
if is_set("instrument.profiler") or false then if get_bool_default("instrument.profiler", false) then
-- Measure overhead of instrumentation, but keep it down for functions -- Measure overhead of instrumentation, but keep it down for functions
-- So keep the `return` for better optimization. -- So keep the `return` for better optimization.
profiler.empty_instrument = instrument { profiler.empty_instrument = instrument {

View File

@ -18,7 +18,7 @@
local DIR_DELIM, LINE_DELIM = DIR_DELIM, "\n" local DIR_DELIM, LINE_DELIM = DIR_DELIM, "\n"
local table, unpack, string, pairs, io, os = table, unpack, string, pairs, io, os local table, unpack, string, pairs, io, os = table, unpack, string, pairs, io, os
local rep, sprintf, tonumber = string.rep, string.format, tonumber local rep, sprintf, tonumber = string.rep, string.format, tonumber
local core, setting_get = core, core.setting_get local core, settings = core, core.settings
local reporter = {} local reporter = {}
--- ---
@ -229,7 +229,7 @@ end
local worldpath = core.get_worldpath() local worldpath = core.get_worldpath()
local function get_save_path(format, filter) local function get_save_path(format, filter)
local report_path = setting_get("profiler.report_path") or "" local report_path = settings:get("profiler.report_path") or ""
if report_path ~= "" then if report_path ~= "" then
core.mkdir(sprintf("%s%s%s", worldpath, DIR_DELIM, report_path)) core.mkdir(sprintf("%s%s%s", worldpath, DIR_DELIM, report_path))
end end
@ -249,7 +249,7 @@ end
-- --
function reporter.save(profile, format, filter) function reporter.save(profile, format, filter)
if not format or format == "" then if not format or format == "" then
format = setting_get("profiler.default_report_format") or "txt" format = settings:get("profiler.default_report_format") or "txt"
end end
if filter == "" then if filter == "" then
filter = nil filter = nil

View File

@ -185,7 +185,7 @@ end
function sampler.init() function sampler.init()
sampler.reset() sampler.reset()
if core.setting_getbool("instrument.profiler") then if core.settings:get_bool("instrument.profiler") then
core.register_globalstep(function() core.register_globalstep(function()
if logged_time == 0 then if logged_time == 0 then
return return

View File

@ -186,6 +186,26 @@ keymap_fastmove (Fast key) key KEY_KEY_J
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_noclip (Noclip key) key KEY_KEY_H keymap_noclip (Noclip key) key KEY_KEY_H
# Key for selecting the next item in the hotbar.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_hotbar_next (Hotbar next key) key KEY_KEY_N
# Key for selecting the previous item in the hotbar.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_hotbar_previous (Hotbar previous key) key KEY_KEY_B
# Key for muting the game.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_mute (Mute key) key KEY_KEY_M
# Key for increasing the volume.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_increase_volume (Inc. volume key) key
# Key for decreasing the volume.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_decrease_volume (Dec. volume key) key
# Key for toggling autorun. # Key for toggling autorun.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_autorun (Autorun key) key keymap_autorun (Autorun key) key
@ -292,6 +312,9 @@ serverlist_url (Serverlist URL) string servers.minetest.net
# File in client/serverlist/ that contains your favorite servers displayed in the Multiplayer Tab. # File in client/serverlist/ that contains your favorite servers displayed in the Multiplayer Tab.
serverlist_file (Serverlist file) string favoriteservers.txt serverlist_file (Serverlist file) string favoriteservers.txt
# Maximum size of the out chat queue. 0 to disable queueing and -1 to make the queue size unlimited
max_out_chat_queue_size (Maximum size of the out chat queue) int 20
[*Graphics] [*Graphics]
[**In-Game] [**In-Game]
@ -324,7 +347,7 @@ enable_clouds (Clouds) bool true
enable_3d_clouds (3D clouds) bool true enable_3d_clouds (3D clouds) bool true
# Method used to highlight selected object. # Method used to highlight selected object.
node_highlighting (Node highlighting) enum box box,halo node_highlighting (Node highlighting) enum box box,halo,none
# Adds particles when digging a node. # Adds particles when digging a node.
enable_particles (Digging particles) bool true enable_particles (Digging particles) bool true
@ -459,6 +482,9 @@ screenW (Screen width) int 800
# Height component of the initial window size. # Height component of the initial window size.
screenH (Screen height) int 600 screenH (Screen height) int 600
# Save window size automatically when modified.
autosave_screensize (Autosave Screen Size) bool true
# Fullscreen mode. # Fullscreen mode.
fullscreen (Full screen) bool false fullscreen (Full screen) bool false
@ -492,10 +518,7 @@ cloud_height (Cloud height) int 120
# Values larger than 26 will start to produce sharp cutoffs at cloud area corners. # Values larger than 26 will start to produce sharp cutoffs at cloud area corners.
cloud_radius (Cloud radius) int 12 cloud_radius (Cloud radius) int 12
# Enables view bobbing when walking. # Enable view bobbing and amount of view bobbing.
view_bobbing (Enable view bobbing) bool true
# Multiplier for view bobbing.
# For example: 0 for no view bobbing; 1.0 for normal; 2.0 for double. # For example: 0 for no view bobbing; 1.0 for normal; 2.0 for double.
view_bobbing_amount (View bobbing factor) float 1.0 view_bobbing_amount (View bobbing factor) float 1.0
@ -1445,7 +1468,7 @@ language (Language) enum ,be,ca,cs,da,de,en,eo,es,et,fr,he,hu,id,it,ja,jbo,ko,
# - action # - action
# - info # - info
# - verbose # - verbose
debug_log_level (Debug log level) enum action ,warning,action,info,verbose debug_log_level (Debug log level) enum action ,none,error,warning,action,info,verbose
# IPv6 support. # IPv6 support.
enable_ipv6 (IPv6) bool true enable_ipv6 (IPv6) bool true

View File

@ -1,176 +0,0 @@
uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D textureFlags;
uniform vec4 skyBgColor;
uniform float fogDistance;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 worldPosition;
varying vec3 eyeVec;
varying vec3 tsEyeVec;
varying vec3 lightVec;
varying vec3 tsLightVec;
bool normalTexturePresent = false;
bool texTileableHorizontal = false;
bool texTileableVertical = false;
bool texSeamless = false;
const float e = 2.718281828459;
const float BS = 10.0;
const float fogStart = FOG_START;
const float fogShadingParameter = 1 / ( 1 - fogStart);
#ifdef ENABLE_TONE_MAPPING
/* Hable's UC2 Tone mapping parameters
A = 0.22;
B = 0.30;
C = 0.10;
D = 0.20;
E = 0.01;
F = 0.30;
W = 11.2;
equation used: ((x * (A * x + C * B) + D * E) / (x * (A * x + B) + D * F)) - E / F
*/
vec3 uncharted2Tonemap(vec3 x)
{
return ((x * (0.22 * x + 0.03) + 0.002) / (x * (0.22 * x + 0.3) + 0.06)) - 0.03334;
}
vec4 applyToneMapping(vec4 color)
{
color = vec4(pow(color.rgb, vec3(2.2)), color.a);
const float gamma = 1.6;
const float exposureBias = 5.5;
color.rgb = uncharted2Tonemap(exposureBias * color.rgb);
// Precalculated white_scale from
//vec3 whiteScale = 1.0 / uncharted2Tonemap(vec3(W));
vec3 whiteScale = vec3(1.036015346);
color.rgb *= whiteScale;
return vec4(pow(color.rgb, vec3(1.0 / gamma)), color.a);
}
#endif
void get_texture_flags()
{
vec4 flags = texture2D(textureFlags, vec2(0.0, 0.0));
if (flags.r > 0.5) {
normalTexturePresent = true;
}
if (flags.g > 0.5) {
texTileableHorizontal = true;
}
if (flags.b > 0.5) {
texTileableVertical = true;
}
if (texTileableHorizontal && texTileableVertical) {
texSeamless = true;
}
}
float intensity(vec3 color)
{
return (color.r + color.g + color.b) / 3.0;
}
float get_rgb_height(vec2 uv)
{
return intensity(texture2D(baseTexture,uv).rgb);
}
vec4 get_normal_map(vec2 uv)
{
vec4 bump = texture2D(normalTexture, uv).rgba;
bump.xyz = normalize(bump.xyz * 2.0 -1.0);
bump.y = -bump.y;
return bump;
}
void main(void)
{
vec3 color;
vec4 bump;
vec2 uv = gl_TexCoord[0].st;
bool use_normalmap = false;
get_texture_flags();
#ifdef ENABLE_PARALLAX_OCCLUSION
if (normalTexturePresent) {
vec3 tsEye = normalize(tsEyeVec);
float height = PARALLAX_OCCLUSION_SCALE * texture2D(normalTexture, uv).a - PARALLAX_OCCLUSION_BIAS;
uv = uv + texture2D(normalTexture, uv).z * height * vec2(tsEye.x,-tsEye.y);
}
#endif
#ifdef USE_NORMALMAPS
if (normalTexturePresent) {
bump = get_normal_map(uv);
use_normalmap = true;
}
#endif
#if GENERATE_NORMALMAPS == 1
if (use_normalmap == false) {
float tl = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y+SAMPLE_STEP));
float t = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y-SAMPLE_STEP));
float tr = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y+SAMPLE_STEP));
float r = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y));
float br = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y-SAMPLE_STEP));
float b = get_rgb_height (vec2(uv.x,uv.y-SAMPLE_STEP));
float bl = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y-SAMPLE_STEP));
float l = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y));
float dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl);
float dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr);
bump = vec4 (normalize(vec3 (dX, -dY, NORMALMAPS_STRENGTH)),1.0);
use_normalmap = true;
}
#endif
vec4 base = texture2D(baseTexture, uv).rgba;
#ifdef ENABLE_BUMPMAPPING
if (use_normalmap) {
vec3 L = normalize(lightVec);
vec3 E = normalize(eyeVec);
float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0),0.5);
float diffuse = dot(E,bump.xyz);
/* Mathematic optimization
* Original: color = 0.05*base.rgb + diffuse*base.rgb + 0.2*specular*base.rgb;
* This optimization save 2 multiplications (orig: 4 multiplications + 3 additions
* end: 2 multiplications + 3 additions)
*/
color = (0.05 + diffuse + 0.2 * specular) * base.rgb;
} else {
color = base.rgb;
}
#else
color = base.rgb;
#endif
vec4 col = vec4(color.rgb * gl_Color.rgb, 1.0);
#ifdef ENABLE_TONE_MAPPING
col = applyToneMapping(col);
#endif
// Due to a bug in some (older ?) graphics stacks (possibly in the glsl compiler ?),
// the fog will only be rendered correctly if the last operation before the
// clamp() is an addition. Else, the clamp() seems to be ignored.
// E.g. the following won't work:
// float clarity = clamp(fogShadingParameter
// * (fogDistance - length(eyeVec)) / fogDistance), 0.0, 1.0);
// As additions usually come for free following a multiplication, the new formula
// should be more efficient as well.
// Note: clarity = (1 - fogginess)
float clarity = clamp(fogShadingParameter
- fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0);
col = mix(skyBgColor, col, clarity);
col = vec4(col.rgb, base.a);
gl_FragColor = col;
}

View File

@ -1,137 +0,0 @@
uniform mat4 mWorldViewProj;
uniform mat4 mWorld;
// Color of the light emitted by the sun.
uniform vec3 dayLight;
uniform vec3 eyePosition;
uniform float animationTimer;
varying vec3 vPosition;
varying vec3 worldPosition;
varying vec3 eyeVec;
varying vec3 lightVec;
varying vec3 tsEyeVec;
varying vec3 tsLightVec;
// Color of the light emitted by the light sources.
const vec3 artificialLight = vec3(1.04, 1.04, 1.04);
const float e = 2.718281828459;
const float BS = 10.0;
float smoothCurve(float x)
{
return x * x * (3.0 - 2.0 * x);
}
float triangleWave(float x)
{
return abs(fract( x + 0.5 ) * 2.0 - 1.0);
}
float smoothTriangleWave(float x)
{
return smoothCurve(triangleWave( x )) * 2.0 - 1.0;
}
void main(void)
{
gl_TexCoord[0] = gl_MultiTexCoord0;
#if (MATERIAL_TYPE == TILE_MATERIAL_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_LIQUID_OPAQUE) && ENABLE_WAVING_WATER
vec4 pos = gl_Vertex;
pos.y -= 2.0;
float posYbuf = (pos.z / WATER_WAVE_LENGTH + animationTimer * WATER_WAVE_SPEED * WATER_WAVE_LENGTH);
pos.y -= sin(posYbuf) * WATER_WAVE_HEIGHT + sin(posYbuf / 7.0) * WATER_WAVE_HEIGHT;
gl_Position = mWorldViewProj * pos;
#elif MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES && ENABLE_WAVING_LEAVES
vec4 pos = gl_Vertex;
vec4 pos2 = mWorld * gl_Vertex;
/*
* Mathematic optimization: pos2.x * A + pos2.z * A (2 multiplications + 1 addition)
* replaced with: (pos2.x + pos2.z) * A (1 addition + 1 multiplication)
* And bufferize calcul to a float
*/
float pos2XpZ = pos2.x + pos2.z;
pos.x += (smoothTriangleWave(animationTimer*10.0 + pos2XpZ * 0.01) * 2.0 - 1.0) * 0.4;
pos.y += (smoothTriangleWave(animationTimer*15.0 + pos2XpZ * -0.01) * 2.0 - 1.0) * 0.2;
pos.z += (smoothTriangleWave(animationTimer*10.0 + pos2XpZ * -0.01) * 2.0 - 1.0) * 0.4;
gl_Position = mWorldViewProj * pos;
#elif MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS && ENABLE_WAVING_PLANTS
vec4 pos = gl_Vertex;
vec4 pos2 = mWorld * gl_Vertex;
if (gl_TexCoord[0].y < 0.05) {
/*
* Mathematic optimization: pos2.x * A + pos2.z * A (2 multiplications + 1 addition)
* replaced with: (pos2.x + pos2.z) * A (1 addition + 1 multiplication)
* And bufferize calcul to a float
*/
float pos2XpZ = pos2.x + pos2.z;
pos.x += (smoothTriangleWave(animationTimer * 20.0 + pos2XpZ * 0.1) * 2.0 - 1.0) * 0.8;
pos.y -= (smoothTriangleWave(animationTimer * 10.0 + pos2XpZ * -0.5) * 2.0 - 1.0) * 0.4;
}
gl_Position = mWorldViewProj * pos;
#else
gl_Position = mWorldViewProj * gl_Vertex;
#endif
vPosition = gl_Position.xyz;
worldPosition = (mWorld * gl_Vertex).xyz;
vec3 sunPosition = vec3 (0.0, eyePosition.y * BS + 900.0, 0.0);
vec3 normal, tangent, binormal;
normal = normalize(gl_NormalMatrix * gl_Normal);
if (gl_Normal.x > 0.5) {
// 1.0, 0.0, 0.0
tangent = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, -1.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
} else if (gl_Normal.x < -0.5) {
// -1.0, 0.0, 0.0
tangent = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
} else if (gl_Normal.y > 0.5) {
// 0.0, 1.0, 0.0
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
} else if (gl_Normal.y < -0.5) {
// 0.0, -1.0, 0.0
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
} else if (gl_Normal.z > 0.5) {
// 0.0, 0.0, 1.0
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
} else if (gl_Normal.z < -0.5) {
// 0.0, 0.0, -1.0
tangent = normalize(gl_NormalMatrix * vec3(-1.0, 0.0, 0.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
}
mat3 tbnMatrix = mat3(tangent.x, binormal.x, normal.x,
tangent.y, binormal.y, normal.y,
tangent.z, binormal.z, normal.z);
lightVec = sunPosition - worldPosition;
tsLightVec = lightVec * tbnMatrix;
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
tsEyeVec = eyeVec * tbnMatrix;
// Calculate color.
// Red, green and blue components are pre-multiplied with
// the brightness, so now we have to multiply these
// colors with the color of the incoming light.
// The pre-baked colors are halved to prevent overflow.
vec4 color;
// The alpha gives the ratio of sunlight in the incoming light.
float nightRatio = 1 - gl_Color.a;
color.rgb = gl_Color.rgb * (gl_Color.a * dayLight.rgb +
nightRatio * artificialLight.rgb) * 2;
color.a = 1;
// Emphase blue a bit in darker places
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
float brightness = (color.r + color.g + color.b) / 3;
color.b += max(0.0, 0.021 - abs(0.2 * brightness - 0.021) +
0.07 * brightness);
gl_FrontColor = gl_BackColor = clamp(color, 0.0, 1.0);
}

View File

@ -8,6 +8,25 @@ end)
core.register_on_connect(function() core.register_on_connect(function()
print("[PREVIEW] Player connection completed") print("[PREVIEW] Player connection completed")
local server_info = core.get_server_info()
print("Server version: " .. server_info.protocol_version)
print("Server ip: " .. server_info.ip)
print("Server address: " .. server_info.address)
print("Server port: " .. server_info.port)
end)
core.register_on_placenode(function(pointed_thing, node)
print("The local player place a node!")
print("pointed_thing :" .. dump(pointed_thing))
print("node placed :" .. dump(node))
return false
end)
core.register_on_item_use(function(itemstack, pointed_thing)
print("The local player used an item!")
print("pointed_thing :" .. dump(pointed_thing))
print("item = " .. itemstack:get_name())
return false
end) end)
-- This is an example function to ensure it's working properly, should be removed before merge -- This is an example function to ensure it's working properly, should be removed before merge
@ -59,6 +78,10 @@ core.register_chatcommand("test_node", {
local function preview_minimap() local function preview_minimap()
local minimap = core.ui.minimap local minimap = core.ui.minimap
if not minimap then
print("[PREVIEW] Minimap is disabled. Skipping.")
return
end
minimap:set_mode(4) minimap:set_mode(4)
minimap:show() minimap:show()
minimap:set_pos({x=5, y=50, z=5}) minimap:set_pos({x=5, y=50, z=5})
@ -73,12 +96,13 @@ core.after(2, function()
print("[PREVIEW] loaded " .. modname .. " mod") print("[PREVIEW] loaded " .. modname .. " mod")
modstorage:set_string("current_mod", modname) modstorage:set_string("current_mod", modname)
print(modstorage:get_string("current_mod")) print(modstorage:get_string("current_mod"))
print("Server version:" .. core.get_protocol_version())
preview_minimap() preview_minimap()
end) end)
core.after(5, function() core.after(5, function()
core.ui.minimap:show() if core.ui.minimap then
core.ui.minimap:show()
end
print("[PREVIEW] Day count: " .. core.get_day_count() .. print("[PREVIEW] Day count: " .. core.get_day_count() ..
" time of day " .. core.get_timeofday()) " time of day " .. core.get_timeofday())

View File

@ -202,7 +202,7 @@ For helper functions see "Vector helpers".
### pointed_thing ### pointed_thing
* `{type="nothing"}` * `{type="nothing"}`
* `{type="node", under=pos, above=pos}` * `{type="node", under=pos, above=pos}`
* `{type="object", ref=ObjectRef}` * `{type="object", id=ObjectID}`
Flag Specifier Format Flag Specifier Format
--------------------- ---------------------
@ -590,17 +590,24 @@ Helper functions
* `math.sign(x, tolerance)` * `math.sign(x, tolerance)`
* Get the sign of a number. * Get the sign of a number.
Optional: Also returns `0` when the absolute value is within the tolerance (default: `0`) Optional: Also returns `0` when the absolute value is within the tolerance (default: `0`)
* `string.split(str, separator=",", include_empty=false, max_splits=-1, * `string.split(str, separator=",", include_empty=false, max_splits=-1, sep_is_pattern=false)`
* sep_is_pattern=false)`
* If `max_splits` is negative, do not limit splits. * If `max_splits` is negative, do not limit splits.
* `sep_is_pattern` specifies if separator is a plain string or a pattern (regex). * `sep_is_pattern` specifies if separator is a plain string or a pattern (regex).
* e.g. `string:split("a,b", ",") == {"a","b"}` * e.g. `string:split("a,b", ",") == {"a","b"}`
* `string:trim()` * `string:trim()`
* e.g. `string.trim("\n \t\tfoo bar\t ") == "foo bar"` * e.g. `string.trim("\n \t\tfoo bar\t ") == "foo bar"`
* `minetest.wrap_text(str, limit)`: returns a string
* Adds new lines to the string to keep it within the specified character limit
* limit: Maximal amount of characters in one line
* `minetest.pos_to_string({x=X,y=Y,z=Z}, decimal_places))`: returns string `"(X,Y,Z)"`
* Convert position to a printable string
Optional: 'decimal_places' will round the x, y and z of the pos to the given decimal place.
* `minetest.string_to_pos(string)`: returns a position
* Same but in reverse. Returns `nil` if the string can't be parsed to a position.
* `minetest.string_to_area("(X1, Y1, Z1) (X2, Y2, Z2)")`: returns two positions
* Converts a string representing an area box into two positions
* `minetest.is_yes(arg)` * `minetest.is_yes(arg)`
* returns whether `arg` can be interpreted as yes * returns whether `arg` can be interpreted as yes
* `minetest.get_us_time()`
* returns time with microsecond precision. May not return wall time.
* `table.copy(table)`: returns a table * `table.copy(table)`: returns a table
* returns a deep copy of `table` * returns a deep copy of `table`
@ -649,6 +656,8 @@ Call these functions only at load time!
* Return `true` to mark the message as handled, which means that it will not be sent to server * Return `true` to mark the message as handled, which means that it will not be sent to server
* `minetest.register_chatcommand(cmd, chatcommand definition)` * `minetest.register_chatcommand(cmd, chatcommand definition)`
* Adds definition to minetest.registered_chatcommands * Adds definition to minetest.registered_chatcommands
* `minetest.unregister_chatcommand(name)`
* Unregisters a chatcommands registered with register_chatcommand.
* `minetest.register_on_death(func())` * `minetest.register_on_death(func())`
* Called when the local player dies * Called when the local player dies
* `minetest.register_on_hp_modification(func(hp))` * `minetest.register_on_hp_modification(func(hp))`
@ -667,6 +676,12 @@ Call these functions only at load time!
* Called when the local player punches a node * Called when the local player punches a node
* Newest functions are called first * Newest functions are called first
* If any function returns true, the punch is ignored * If any function returns true, the punch is ignored
* `minetest.register_on_placenode(function(pointed_thing, node))`
* Called when a node has been placed
* `minetest.register_on_item_use(func(item, pointed_thing))`
* Called when the local player uses an item.
* Newest functions are called first.
* If any function returns true, the item use is not sent to server.
### Sounds ### Sounds
* `minetest.sound_play(spec, parameters)`: returns a handle * `minetest.sound_play(spec, parameters)`: returns a handle
* `spec` is a `SimpleSoundSpec` * `spec` is a `SimpleSoundSpec`
@ -677,6 +692,12 @@ Call these functions only at load time!
* `minetest.after(time, func, ...)` * `minetest.after(time, func, ...)`
* Call the function `func` after `time` seconds, may be fractional * Call the function `func` after `time` seconds, may be fractional
* Optional: Variable number of arguments that are passed to `func` * Optional: Variable number of arguments that are passed to `func`
* `minetest.get_us_time()`
* Returns time with microsecond precision. May not return wall time.
* `minetest.get_day_count()`
* Returns number days elapsed since world was created, accounting for time changes.
* `minetest.get_timeofday()`
* Returns the time of day: `0` for midnight, `0.5` for midday
### Map ### Map
* `minetest.get_node(pos)` * `minetest.get_node(pos)`
@ -685,14 +706,29 @@ Call these functions only at load time!
for unloaded areas. for unloaded areas.
* `minetest.get_node_or_nil(pos)` * `minetest.get_node_or_nil(pos)`
* Same as `get_node` but returns `nil` for unloaded areas. * Same as `get_node` but returns `nil` for unloaded areas.
* `minetest.find_node_near(pos, radius, nodenames, [search_center])`: returns pos or `nil`
* `radius`: using a maximum metric
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
* `search_center` is an optional boolean (default: `false`)
If true `pos` is also checked for the nodes
* `minetest.get_meta(pos)` * `minetest.get_meta(pos)`
* Get a `NodeMetaRef` at that position * Get a `NodeMetaRef` at that position
* `minetest.get_node_level(pos)`
* get level of leveled node (water, snow)
* `minetest.get_node_max_level(pos)`
* get max available level for leveled node
### Player ### Player
* `minetest.get_wielded_item()` * `minetest.get_wielded_item()`
* Returns the itemstack the local player is holding * Returns the itemstack the local player is holding
* `minetest.send_chat_message(message)`
* Act as if `message` was typed by the player into the terminal.
* `minetest.run_server_chatcommand(cmd, param)`
* Alias for `minetest.send_chat_message("/" .. cmd .. " " .. param)`
* `minetest.clear_out_chat_queue()`
* Clears the out chat queue
* `minetest.localplayer` * `minetest.localplayer`
* Reference to the LocalPlayer object. See `LocalPlayer` class reference for methods. * Reference to the LocalPlayer object. See [`LocalPlayer`](#localplayer) class reference for methods.
### Client Environment ### Client Environment
* `minetest.get_player_names()` * `minetest.get_player_names()`
@ -700,9 +736,17 @@ Call these functions only at load time!
* `minetest.disconnect()` * `minetest.disconnect()`
* Disconnect from the server and exit to main menu. * Disconnect from the server and exit to main menu.
* Returns `false` if the client is already disconnecting otherwise returns `true`. * Returns `false` if the client is already disconnecting otherwise returns `true`.
* `minetest.get_protocol_version()` * `minetest.take_screenshot()`
* Returns the protocol version of the server. * Take a screenshot.
* Might not be accurate at start up as the client might not be connected to the server yet, in that case it will return 0. * `minetest.get_server_info()`
* Returns [server info](#server-info).
* `minetest.send_respawn()`
* Sends a respawn request to the server.
### Storage API
* `minetest.get_mod_storage()`:
* returns reference to mod private `StorageRef`
* must be called during mod load time
### Misc. ### Misc.
* `minetest.parse_json(string[, nullvalue])`: returns something * `minetest.parse_json(string[, nullvalue])`: returns something
@ -747,7 +791,7 @@ Call these functions only at load time!
* Encodes a string in base64. * Encodes a string in base64.
* `minetest.decode_base64(string)`: returns string * `minetest.decode_base64(string)`: returns string
* Decodes a string encoded in base64. * Decodes a string encoded in base64.
* `minetest.gettext(string) : returns string * `minetest.gettext(string)` : returns string
* look up the translation of a string in the gettext message catalog * look up the translation of a string in the gettext message catalog
* `fgettext_ne(string, ...)` * `fgettext_ne(string, ...)`
* call minetest.gettext(string), replace "$1"..."$9" with the given * call minetest.gettext(string), replace "$1"..."$9" with the given
@ -756,10 +800,15 @@ Call these functions only at load time!
* same as fgettext_ne(), but calls minetest.formspec_escape before returning result * same as fgettext_ne(), but calls minetest.formspec_escape before returning result
* `minetest.pointed_thing_to_face_pos(placer, pointed_thing)`: returns a position * `minetest.pointed_thing_to_face_pos(placer, pointed_thing)`: returns a position
* returns the exact position on the surface of a pointed node * returns the exact position on the surface of a pointed node
* `minetest.global_exists(name)`
* Checks if a global variable has been set, without triggering a warning.
### UI ### UI
* `minetest.ui.minimap` * `minetest.ui.minimap`
* Reference to the minimap object. See `Minimap` class reference for methods. * Reference to the minimap object. See [`Minimap`](#minimap) class reference for methods.
* If client disabled minimap (using enable_minimap setting) this reference will be nil.
* `minetest.camera`
* Reference to the camera object. See [`Camera`](#camera) class reference for methods.
* `minetest.show_formspec(formname, formspec)` : returns true on success * `minetest.show_formspec(formname, formspec)` : returns true on success
* Shows a formspec to the player * Shows a formspec to the player
* `minetest.display_chat_message(message)` returns true on success * `minetest.display_chat_message(message)` returns true on success
@ -782,6 +831,40 @@ An interface to manipulate minimap on client UI
* `set_shape(shape)`: Sets the minimap shape. (0 = square, 1 = round) * `set_shape(shape)`: Sets the minimap shape. (0 = square, 1 = round)
* `get_shape()`: Gets the minimap shape. (0 = square, 1 = round) * `get_shape()`: Gets the minimap shape. (0 = square, 1 = round)
### Camera
An interface to get or set information about the camera and cameranode.
Please do not try to access the reference until the camera is initialized, otherwise the reference will be nil.
#### Methods
* `set_camera_mode(mode)`
* Pass `0` for first-person, `1` for third person, and `2` for third person front
* `get_camera_mode()`
* Returns with same syntax as above
* `get_fov()`
* Returns:
```lua
{
x = number,
y = number,
max = number,
actual = number
}
```
* `get_pos()`
* Returns position of camera with view bobbing
* `get_offset()`
* Returns eye offset vector
* `get_look_dir()`
* Returns eye direction unit vector
* `get_look_vertical()`
* Returns pitch in radians
* `get_look_horizontal()`
* Returns yaw in radians
* `get_aspect_ratio()`
* Returns aspect ratio of screen
### LocalPlayer ### LocalPlayer
An interface to retrieve information about the player. The player is An interface to retrieve information about the player. The player is
not accessible until the client is fully done loading and therefore not accessible until the client is fully done loading and therefore
@ -806,8 +889,6 @@ Methods:
* returns player HP * returns player HP
* `get_name()` * `get_name()`
* returns player name * returns player name
* `got_teleported()`
* returns true if player was teleported
* `is_attached()` * `is_attached()`
* returns true if player is attached * returns true if player is attached
* `is_touching_ground()` * `is_touching_ground()`
@ -843,16 +924,6 @@ Methods:
* returns last player speed * returns last player speed
* `get_breath()` * `get_breath()`
* returns the player's breath * returns the player's breath
* `get_look_dir()`
* returns look direction vector
* `get_look_horizontal()`
* returns look horizontal angle
* `get_look_vertical()`
* returns look vertical angle
* `get_eye_pos()`
* returns the player's eye position
* `get_eye_offset()`
* returns the player's eye shift vector
* `get_movement_acceleration()` * `get_movement_acceleration()`
* returns acceleration of the player in different environments: * returns acceleration of the player in different environments:
@ -924,15 +995,114 @@ Can be obtained via `minetest.get_meta(pos)`.
* `inventory`: `{list1 = {}, ...}}` * `inventory`: `{list1 = {}, ...}}`
----------------- -----------------
### Definitions
* `minetest.get_node_def(nodename)`
* Returns [node definition](#node-definition) table of `nodename`
* `minetest.get_item_def(itemstring)`
* Returns item definition table of `itemstring`
#### Node Definition
```lua
{
has_on_construct = bool, -- Whether the node has the on_construct callback defined
has_on_destruct = bool, -- Whether the node has the on_destruct callback defined
has_after_destruct = bool, -- Whether the node has the after_destruct callback defined
name = string, -- The name of the node e.g. "air", "default:dirt"
groups = table, -- The groups of the node
paramtype = string, -- Paramtype of the node
paramtype2 = string, -- ParamType2 of the node
drawtype = string, -- Drawtype of the node
mesh = <string>, -- Mesh name if existant
minimap_color = <Color>, -- Color of node on minimap *May not exist*
visual_scale = number, -- Visual scale of node
alpha = number, -- Alpha of the node. Only used for liquids
color = <Color>, -- Color of node *May not exist*
palette_name = <string>, -- Filename of palette *May not exist*
palette = <{ -- List of colors
Color,
Color
}>,
waving = number, -- 0 of not waving, 1 if waving
connect_sides = number, -- Used for connected nodes
connects_to = { -- List of nodes to connect to
"node1",
"node2"
},
post_effect_color = Color, -- Color overlayed on the screen when the player is in the node
leveled = number, -- Max level for node
sunlight_propogates = bool, -- Whether light passes through the block
light_source = number, -- Light emitted by the block
is_ground_content = bool, -- Whether caves should cut through the node
walkable = bool, -- Whether the player collides with the node
pointable = bool, -- Whether the player can select the node
diggable = bool, -- Whether the player can dig the node
climbable = bool, -- Whether the player can climb up the node
buildable_to = bool, -- Whether the player can replace the node by placing a node on it
rightclickable = bool, -- Whether the player can place nodes pointing at this node
damage_per_second = number, -- HP of damage per second when the player is in the node
liquid_type = <string>, -- A string containing "none", "flowing", or "source" *May not exist*
liquid_alternative_flowing = <string>, -- Alternative node for liquid *May not exist*
liquid_alternative_source = <string>, -- Alternative node for liquid *May not exist*
liquid_viscosity = <number>, -- How fast the liquid flows *May not exist*
liquid_renewable = <boolean>, -- Whether the liquid makes an infinite source *May not exist*
liquid_range = <number>, -- How far the liquid flows *May not exist*
drowning = bool, -- Whether the player will drown in the node
floodable = bool, -- Whether nodes will be replaced by liquids (flooded)
node_box = table, -- Nodebox to draw the node with
collision_box = table, -- Nodebox to set the collision area
selection_box = table, -- Nodebox to set the area selected by the player
sounds = { -- Table of sounds that the block makes
sound_footstep = SimpleSoundSpec,
sound_dig = SimpleSoundSpec,
sound_dug = SimpleSoundSpec
},
legacy_facedir_simple = bool, -- Whether to use old facedir
legacy_wallmounted = bool -- Whether to use old wallmounted
}
```
#### Item Definition
```lua
{
name = string, -- Name of the item e.g. "default:stone"
description = string, -- Description of the item e.g. "Stone"
type = string, -- Item type: "none", "node", "craftitem", "tool"
inventory_image = string, -- Image in the inventory
wield_image = string, -- Image in wieldmesh
palette_image = string, -- Image for palette
color = Color, -- Color for item
wield_scale = Vector, -- Wieldmesh scale
stack_max = number, -- Number of items stackable together
usable = bool, -- Has on_use callback defined
liquids_pointable = bool, -- Whether you can point at liquids with the item
tool_capabilities = <table>, -- If the item is a tool, tool capabiltites of the item
groups = table, -- Groups of the item
sound_place = SimpleSoundSpec, -- Sound played when placed
sound_place_failed = SimpleSoundSpec, -- Sound played when placement failed
node_placement_prediction = string -- Node placed in client until server catches up
}
```
-----------------
### Chat command definition (`register_chatcommand`) ### Chat command definition (`register_chatcommand`)
{ {
params = "<name> <privilege>", -- Short parameter description params = "<name> <privilege>", -- Short parameter description
description = "Remove privilege from player", -- Full description description = "Remove privilege from player", -- Full description
func = function(param), -- Called when command is run. func = function(param), -- Called when command is run.
-- Returns boolean success and text output. -- Returns boolean success and text output.
} }
### Server info
```lua
{
address = "minetest.example.org", -- The domain name/IP address of a remote server or "" for a local server.
ip = "203.0.113.156", -- The IP address of the server.
port = 30000, -- The port the client is connected to.
protocol_version = 30 -- Will not be accurate at start up as the client might not be connected to the server yet, in that case it will be 0.
}
```
Escape sequences Escape sequences
---------------- ----------------
@ -940,7 +1110,7 @@ Most text can contain escape sequences, that can for example color the text.
There are a few exceptions: tab headers, dropdowns and vertical labels can't. There are a few exceptions: tab headers, dropdowns and vertical labels can't.
The following functions provide escape sequences: The following functions provide escape sequences:
* `minetest.get_color_escape_sequence(color)`: * `minetest.get_color_escape_sequence(color)`:
* `color` is a ColorString * `color` is a [ColorString](#colorstring)
* The escape sequence sets the text color to `color` * The escape sequence sets the text color to `color`
* `minetest.colorize(color, message)`: * `minetest.colorize(color, message)`:
* Equivalent to: * Equivalent to:
@ -948,7 +1118,7 @@ The following functions provide escape sequences:
message .. message ..
minetest.get_color_escape_sequence("#ffffff")` minetest.get_color_escape_sequence("#ffffff")`
* `color.get_background_escape_sequence(color)` * `color.get_background_escape_sequence(color)`
* `color` is a ColorString * `color` is a [ColorString](#colorstring)
* The escape sequence sets the background of the whole text element to * The escape sequence sets the background of the whole text element to
`color`. Only defined for item descriptions and tooltips. `color`. Only defined for item descriptions and tooltips.
* `color.strip_foreground_colors(str)` * `color.strip_foreground_colors(str)`
@ -973,3 +1143,7 @@ Named colors are also supported and are equivalent to
To specify the value of the alpha channel, append `#AA` to the end of the color name To specify the value of the alpha channel, append `#AA` to the end of the color name
(e.g. `colorname#08`). For named colors the hexadecimal string representing the alpha (e.g. `colorname#08`). For named colors the hexadecimal string representing the alpha
value must (always) be two hexadecimal digits. value must (always) be two hexadecimal digits.
`Color`
-------------
`{a = alpha, r = red, g = green, b = blue}` defines an ARGB8 color.

View File

@ -172,8 +172,8 @@ The main Lua script. Running this script should register everything it
wants to register. Subsequent execution depends on minetest calling the wants to register. Subsequent execution depends on minetest calling the
registered callbacks. registered callbacks.
`minetest.setting_get(name)` and `minetest.setting_getbool(name)` can be used `minetest.settings` can be used to read custom or existing settings at load
to read custom or existing settings at load time, if necessary. time, if necessary. (See `Settings`)
### `models` ### `models`
Models for entities or meshnodes. Models for entities or meshnodes.
@ -456,13 +456,13 @@ Examples of sound parameter tables:
-- Play locationless on all clients -- Play locationless on all clients
{ {
gain = 1.0, -- default gain = 1.0, -- default
fade = 0, -- default, change to a value > 0 to fade the sound in fade = 0.0, -- default, change to a value > 0 to fade the sound in
} }
-- Play locationless to one player -- Play locationless to one player
{ {
to_player = name, to_player = name,
gain = 1.0, -- default gain = 1.0, -- default
fade = 0, -- default, change to a value > 0 to fade the sound in fade = 0.0, -- default, change to a value > 0 to fade the sound in
} }
-- Play locationless to one player, looped -- Play locationless to one player, looped
{ {
@ -1232,9 +1232,9 @@ Another example: Make red wool from white wool and red dye:
from destroyed nodes. from destroyed nodes.
* `0` is something that is directly accessible at the start of gameplay * `0` is something that is directly accessible at the start of gameplay
* There is no upper limit * There is no upper limit
* `dig_immediate`: (player can always pick up node without tool wear) * `dig_immediate`: (player can always pick up node without reducing tool wear)
* `2`: node is removed without tool wear after 0.5 seconds (rail, sign) * `2`: the node always gets the digging time 0.5 seconds (rail, sign)
* `3`: node is removed without tool wear after 0.15 seconds (torch) * `3`: the node always gets the digging time 0 seconds (torch)
* `disable_jump`: Player (and possibly other things) cannot jump from node * `disable_jump`: Player (and possibly other things) cannot jump from node
* `fall_damage_add_percent`: damage speed = `speed * (1 + value/100)` * `fall_damage_add_percent`: damage speed = `speed * (1 + value/100)`
* `bouncy`: value is bounce speed in percent * `bouncy`: value is bounce speed in percent
@ -1335,6 +1335,10 @@ result in the tool to be able to dig nodes that have a rating of `2` or `3`
for this group, and unable to dig the rating `1`, which is the toughest. for this group, and unable to dig the rating `1`, which is the toughest.
Unless there is a matching group that enables digging otherwise. Unless there is a matching group that enables digging otherwise.
If the result digging time is 0, a delay of 0.15 seconds is added between
digging nodes; If the player releases LMB after digging, this delay is set to 0,
i.e. players can more quickly click the nodes away instead of holding LMB.
#### Damage groups #### Damage groups
List of damage for groups of entities. See "Entity damage mechanism". List of damage for groups of entities. See "Entity damage mechanism".
@ -1582,7 +1586,7 @@ examples.
* Sets default background color of tooltips * Sets default background color of tooltips
* Sets default font color of tooltips * Sets default font color of tooltips
#### `tooltip[<gui_element_name>;<tooltip_text>;<bgcolor>,<fontcolor>]` #### `tooltip[<gui_element_name>;<tooltip_text>;<bgcolor>;<fontcolor>]`
* Adds tooltip for an element * Adds tooltip for an element
* `<bgcolor>` tooltip background color as `ColorString` (optional) * `<bgcolor>` tooltip background color as `ColorString` (optional)
* `<fontcolor>` tooltip font color as `ColorString` (optional) * `<fontcolor>` tooltip font color as `ColorString` (optional)
@ -1868,14 +1872,14 @@ Escape sequences
Most text can contain escape sequences, that can for example color the text. Most text can contain escape sequences, that can for example color the text.
There are a few exceptions: tab headers, dropdowns and vertical labels can't. There are a few exceptions: tab headers, dropdowns and vertical labels can't.
The following functions provide escape sequences: The following functions provide escape sequences:
* `core.get_color_escape_sequence(color)`: * `minetest.get_color_escape_sequence(color)`:
* `color` is a ColorString * `color` is a ColorString
* The escape sequence sets the text color to `color` * The escape sequence sets the text color to `color`
* `core.colorize(color, message)`: * `minetest.colorize(color, message)`:
* Equivalent to: * Equivalent to:
`core.get_color_escape_sequence(color) .. `minetest.get_color_escape_sequence(color) ..
message .. message ..
core.get_color_escape_sequence("#ffffff")` minetest.get_color_escape_sequence("#ffffff")`
* `color.get_background_escape_sequence(color)` * `color.get_background_escape_sequence(color)`
* `color` is a ColorString * `color` is a ColorString
* The escape sequence sets the background of the whole text element to * The escape sequence sets the background of the whole text element to
@ -1921,14 +1925,16 @@ Helper functions
* `math.sign(x, tolerance)` * `math.sign(x, tolerance)`
* Get the sign of a number. * Get the sign of a number.
Optional: Also returns `0` when the absolute value is within the tolerance (default: `0`) Optional: Also returns `0` when the absolute value is within the tolerance (default: `0`)
* `string.split(str, separator=",", include_empty=false, max_splits=-1, * `string.split(str, separator=",", include_empty=false, max_splits=-1, sep_is_pattern=false)`
* sep_is_pattern=false)`
* If `max_splits` is negative, do not limit splits. * If `max_splits` is negative, do not limit splits.
* `sep_is_pattern` specifies if separator is a plain string or a pattern (regex). * `sep_is_pattern` specifies if separator is a plain string or a pattern (regex).
* e.g. `string:split("a,b", ",") == {"a","b"}` * e.g. `string:split("a,b", ",") == {"a","b"}`
* `string:trim()` * `string:trim()`
* e.g. `string.trim("\n \t\tfoo bar\t ") == "foo bar"` * e.g. `string.trim("\n \t\tfoo bar\t ") == "foo bar"`
* `minetest.pos_to_string({x=X,y=Y,z=Z}, decimal_places))`: returns `"(X,Y,Z)"` * `minetest.wrap_text(str, limit)`: returns a string
* Adds new lines to the string to keep it within the specified character limit
* limit: Maximal amount of characters in one line
* `minetest.pos_to_string({x=X,y=Y,z=Z}, decimal_places))`: returns string `"(X,Y,Z)"`
* Convert position to a printable string * Convert position to a printable string
Optional: 'decimal_places' will round the x, y and z of the pos to the given decimal place. Optional: 'decimal_places' will round the x, y and z of the pos to the given decimal place.
* `minetest.string_to_pos(string)`: returns a position * `minetest.string_to_pos(string)`: returns a position
@ -1994,11 +2000,11 @@ Helper functions
max_jitter = 0.5, -- maximum packet time jitter max_jitter = 0.5, -- maximum packet time jitter
avg_jitter = 0.03, -- average packet time jitter avg_jitter = 0.03, -- average packet time jitter
connection_uptime = 200, -- seconds since client connected connection_uptime = 200, -- seconds since client connected
prot_vers = 31, -- protocol version used by client
-- following information is available on debug build only!!! -- following information is available on debug build only!!!
-- DO NOT USE IN MODS -- DO NOT USE IN MODS
--ser_vers = 26, -- serialization version used by client --ser_vers = 26, -- serialization version used by client
--prot_vers = 23, -- protocol version used by client
--major = 0, -- major version number --major = 0, -- major version number
--minor = 4, -- minor version number --minor = 4, -- minor version number
--patch = 10, -- patch version number --patch = 10, -- patch version number
@ -2023,7 +2029,7 @@ Helper functions
reliable or verifyable. Compatible forks will have a different name and reliable or verifyable. Compatible forks will have a different name and
version entirely. To check for the presence of engine features, test version entirely. To check for the presence of engine features, test
whether the functions exported by the wanted features exist. For example: whether the functions exported by the wanted features exist. For example:
`if core.nodeupdate then ... end`. `if minetest.nodeupdate then ... end`.
### Logging ### Logging
* `minetest.debug(...)` * `minetest.debug(...)`
@ -2174,16 +2180,10 @@ Call these functions only at load time!
* See `minetest.builtin_auth_handler` in `builtin.lua` for reference * See `minetest.builtin_auth_handler` in `builtin.lua` for reference
### Setting-related ### Setting-related
* `minetest.setting_set(name, value)` * `minetest.settings`: Settings object containing all of the settings from the
* Setting names can't contain whitespace or any of `="{}#`. main config file (`minetest.conf`).
* Setting values can't contain the sequence `\n"""`. * `minetest.setting_get_pos(name)`: Loads a setting from the main settings and
* Setting names starting with "secure." can't be set. parses it as a position (in the format `(1,2,3)`). Returns a position or nil.
* `minetest.setting_get(name)`: returns string or `nil`
* `minetest.setting_setbool(name, value)`
* See documentation on `setting_set` for restrictions.
* `minetest.setting_getbool(name)`: returns boolean or `nil`
* `minetest.setting_get_pos(name)`: returns position or nil
* `minetest.setting_save()`, returns `nil`, save all settings to config file
### Authentication ### Authentication
* `minetest.notify_authentication_modified(name)` * `minetest.notify_authentication_modified(name)`
@ -2277,9 +2277,11 @@ and `minetest.auth_reload` call the authetification handler.
* `minetest.get_gametime()`: returns the time, in seconds, since the world was created * `minetest.get_gametime()`: returns the time, in seconds, since the world was created
* `minetest.get_day_count()`: returns number days elapsed since world was created, * `minetest.get_day_count()`: returns number days elapsed since world was created,
* accounting for time changes. * accounting for time changes.
* `minetest.find_node_near(pos, radius, nodenames)`: returns pos or `nil` * `minetest.find_node_near(pos, radius, nodenames, [search_center])`: returns pos or `nil`
* `radius`: using a maximum metric * `radius`: using a maximum metric
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"` * `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
* `search_center` is an optional boolean (default: `false`)
If true `pos` is also checked for the nodes
* `minetest.find_nodes_in_area(minp, maxp, nodenames)`: returns a list of positions * `minetest.find_nodes_in_area(minp, maxp, nodenames)`: returns a list of positions
* returns as second value a table with the count of the individual nodes found * returns as second value a table with the count of the individual nodes found
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"` * `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
@ -2360,8 +2362,8 @@ and `minetest.auth_reload` call the authetification handler.
* `function EmergeAreaCallback(blockpos, action, calls_remaining, param)` * `function EmergeAreaCallback(blockpos, action, calls_remaining, param)`
* - `blockpos` is the *block* coordinates of the block that had been emerged * - `blockpos` is the *block* coordinates of the block that had been emerged
* - `action` could be one of the following constant values: * - `action` could be one of the following constant values:
* `core.EMERGE_CANCELLED`, `core.EMERGE_ERRORED`, `core.EMERGE_FROM_MEMORY`, * `minetest.EMERGE_CANCELLED`, `minetest.EMERGE_ERRORED`, `minetest.EMERGE_FROM_MEMORY`,
* `core.EMERGE_FROM_DISK`, `core.EMERGE_GENERATED` * `minetest.EMERGE_FROM_DISK`, `minetest.EMERGE_GENERATED`
* - `calls_remaining` is the number of callbacks to be expected after this one * - `calls_remaining` is the number of callbacks to be expected after this one
* - `param` is the user-defined parameter passed to emerge_area (or nil if the * - `param` is the user-defined parameter passed to emerge_area (or nil if the
* parameter was absent) * parameter was absent)
@ -2416,11 +2418,11 @@ and `minetest.auth_reload` call the authetification handler.
might be removed. might be removed.
* returns `false` if the area is not fully generated, * returns `false` if the area is not fully generated,
`true` otherwise `true` otherwise
* `core.check_single_for_falling(pos)` * `minetest.check_single_for_falling(pos)`
* causes an unsupported `group:falling_node` node to fall and causes an * causes an unsupported `group:falling_node` node to fall and causes an
unattached `group:attached_node` node to fall. unattached `group:attached_node` node to fall.
* does not spread these updates to neighbours. * does not spread these updates to neighbours.
* `core.check_for_falling(pos)` * `minetest.check_for_falling(pos)`
* causes an unsupported `group:falling_node` node to fall and causes an * causes an unsupported `group:falling_node` node to fall and causes an
unattached `group:attached_node` node to fall. unattached `group:attached_node` node to fall.
* spread these updates to neighbours and can cause a cascade * spread these updates to neighbours and can cause a cascade
@ -2586,10 +2588,11 @@ These functions return the leftover itemstack.
* `spec` is a `SimpleSoundSpec` * `spec` is a `SimpleSoundSpec`
* `parameters` is a sound parameter table * `parameters` is a sound parameter table
* `minetest.sound_stop(handle)` * `minetest.sound_stop(handle)`
* `minetest.sound_fade(handle,step,gain)` * `minetest.sound_fade(handle, step, gain)`
* `handle` is a handle returned by minetest.sound_play * `handle` is a handle returned by minetest.sound_play
* `step` determines how fast a sound will fade. Negative step will lower the sound volume, positive step will increase the sound volume * `step` determines how fast a sound will fade.
* `gain` the target gain for the fade. Negative step will lower the sound volume, positive step will increase the sound volume
* `gain` the target gain for the fade.
### Timing ### Timing
* `minetest.after(time, func, ...)` * `minetest.after(time, func, ...)`
@ -2605,6 +2608,8 @@ These functions return the leftover itemstack.
* `minetest.cancel_shutdown_requests()`: cancel current delayed shutdown * `minetest.cancel_shutdown_requests()`: cancel current delayed shutdown
* `minetest.get_server_status()`: returns server status string * `minetest.get_server_status()`: returns server status string
* `minetest.get_server_uptime()`: returns the server uptime in seconds * `minetest.get_server_uptime()`: returns the server uptime in seconds
* `minetest.remove_player(name)`: remove player from database (if he is not connected).
* Returns a code (0: successful, 1: no such player, 2: player is connected)
### Bans ### Bans
* `minetest.get_ban_list()`: returns the ban list (same as `minetest.get_ban_description("")`) * `minetest.get_ban_list()`: returns the ban list (same as `minetest.get_ban_description("")`)
@ -2893,6 +2898,10 @@ Can be obtained via `minetest.get_meta(pos)`.
#### Methods #### Methods
* All methods in MetaDataRef * All methods in MetaDataRef
* `get_inventory()`: returns `InvRef` * `get_inventory()`: returns `InvRef`
* `mark_as_private(name or {name1, name2, ...})`: Mark specific vars as private
This will prevent them from being sent to the client. Note that the "private"
status will only be remembered if an associated key-value pair exists, meaning
it's best to call this when initializing all other meta (e.g. on_construct).
### `ItemStackMetaRef` ### `ItemStackMetaRef`
ItemStack metadata: reference extra data and functionality stored in a stack. ItemStack metadata: reference extra data and functionality stored in a stack.
@ -3026,7 +3035,9 @@ This is basically a reference to a C++ `ServerActiveObject`
* `0`: player is drowning, * `0`: player is drowning,
* `1`-`10`: remaining number of bubbles * `1`-`10`: remaining number of bubbles
* `11`: bubbles bar is not shown * `11`: bubbles bar is not shown
* `set_attribute(attribute, value)`: sets an extra attribute with value on player * `set_attribute(attribute, value)`:
* Sets an extra attribute with value on player.
* If value is nil, remove attribute from player.
* `get_attribute(attribute)`: returns value for extra attribute. Returns nil if no attribute found. * `get_attribute(attribute)`: returns value for extra attribute. Returns nil if no attribute found.
* `set_inventory_formspec(formspec)` * `set_inventory_formspec(formspec)`
* Redefine player's inventory form * Redefine player's inventory form
@ -3071,13 +3082,24 @@ This is basically a reference to a C++ `ServerActiveObject`
* `hud_set_hotbar_selected_image(texturename)` * `hud_set_hotbar_selected_image(texturename)`
* sets image for selected item of hotbar * sets image for selected item of hotbar
* `hud_get_hotbar_selected_image`: returns texturename * `hud_get_hotbar_selected_image`: returns texturename
* `set_sky(bgcolor, type, {texture names})` * `set_sky(bgcolor, type, {texture names}, clouds)`
* `bgcolor`: ColorSpec, defaults to white * `bgcolor`: ColorSpec, defaults to white
* Available types: * `type`: Available types:
* `"regular"`: Uses 0 textures, `bgcolor` ignored * `"regular"`: Uses 0 textures, `bgcolor` ignored
* `"skybox"`: Uses 6 textures, `bgcolor` used * `"skybox"`: Uses 6 textures, `bgcolor` used
* `"plain"`: Uses 0 textures, `bgcolor` used * `"plain"`: Uses 0 textures, `bgcolor` used
* `get_sky()`: returns bgcolor, type and a table with the textures * `clouds`: Boolean for whether clouds appear in front of `"skybox"` or
`"plain"` custom skyboxes (default: `true`)
* `get_sky()`: returns bgcolor, type, table of textures, clouds
* `set_clouds(parameters)`: set cloud parameters
* `parameters` is a table with the following optional fields:
* `density`: from `0` (no clouds) to `1` (full clouds) (default `0.4`)
* `color`: basic cloud color, with alpha channel (default `#fff0f0e5`)
* `ambient`: cloud color lower bound, use for a "glow at night" effect (default `#000000`)
* `height`: cloud height, i.e. y of cloud base (default per conf, usually `120`)
* `thickness`: cloud thickness in nodes (default `16`)
* `speed`: 2D cloud speed + direction in nodes per second (default `{x=0, y=-2}`)
* `get_clouds()`: returns a table with the current cloud parameters as in `set_clouds`
* `override_day_night_ratio(ratio or nil)` * `override_day_night_ratio(ratio or nil)`
* `0`...`1`: Overrides day-night ratio, controlling sunlight to a specific amount * `0`...`1`: Overrides day-night ratio, controlling sunlight to a specific amount
* `nil`: Disables override, defaulting to sunlight based on day-night cycle * `nil`: Disables override, defaulting to sunlight based on day-night cycle
@ -3389,9 +3411,9 @@ Note that the node being queried needs to have already been been registered.
The following builtin node types have their Content IDs defined as constants: The following builtin node types have their Content IDs defined as constants:
``` ```
core.CONTENT_UNKNOWN (ID for "unknown" nodes) minetest.CONTENT_UNKNOWN (ID for "unknown" nodes)
core.CONTENT_AIR (ID for "air" nodes) minetest.CONTENT_AIR (ID for "air" nodes)
core.CONTENT_IGNORE (ID for "ignore" nodes) minetest.CONTENT_IGNORE (ID for "ignore" nodes)
``` ```
##### Mapgen VoxelManip objects ##### Mapgen VoxelManip objects
@ -3450,7 +3472,7 @@ will place the schematic inside of the VoxelManip.
If `light` is false, no light calculations happen, and you should correct If `light` is false, no light calculations happen, and you should correct
all modified blocks with `minetest.fix_light()` as soon as possible. all modified blocks with `minetest.fix_light()` as soon as possible.
Keep in mind that modifying the map where light is incorrect can cause Keep in mind that modifying the map where light is incorrect can cause
more lighting bugs. more lighting bugs.
* `get_node_at(pos)`: Returns a `MapNode` table of the node currently loaded in * `get_node_at(pos)`: Returns a `MapNode` table of the node currently loaded in
the `VoxelManip` at that position the `VoxelManip` at that position
* `set_node_at(pos, node)`: Sets a specific `MapNode` in the `VoxelManip` at that position * `set_node_at(pos, node)`: Sets a specific `MapNode` in the `VoxelManip` at that position
@ -3517,10 +3539,15 @@ It can be created via `Settings(filename)`.
* `get(key)`: returns a value * `get(key)`: returns a value
* `get_bool(key)`: returns a boolean * `get_bool(key)`: returns a boolean
* `set(key, value)` * `set(key, value)`
* Setting names can't contain whitespace or any of `="{}#`.
* Setting values can't contain the sequence `\n"""`.
* Setting names starting with "secure." can't be set on the main settings object (`minetest.settings`).
* `set_bool(key, value)`
* See documentation for set() above.
* `remove(key)`: returns a boolean (`true` for success) * `remove(key)`: returns a boolean (`true` for success)
* `get_names()`: returns `{key1,...}` * `get_names()`: returns `{key1,...}`
* `write()`: returns a boolean (`true` for success) * `write()`: returns a boolean (`true` for success)
* write changes to file * Writes changes to file.
* `to_table()`: returns `{[key1]=value1,...}` * `to_table()`: returns `{[key1]=value1,...}`
Mapgen objects Mapgen objects
@ -3682,24 +3709,26 @@ Definition tables
{ {
hp_max = 1, hp_max = 1,
physical = true, physical = true,
collide_with_objects = true, -- collide with other objects if physical=true collide_with_objects = true, -- collide with other objects if physical = true
weight = 5, weight = 5,
collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5}, collisionbox = {-0.5, 0.0, -0.5, 0.5, 1.0, 0.5},
visual = "cube"/"sprite"/"upright_sprite"/"mesh"/"wielditem", visual = "cube" / "sprite" / "upright_sprite" / "mesh" / "wielditem",
visual_size = {x=1, y=1}, visual_size = {x = 1, y = 1},
mesh = "model", mesh = "model",
textures = {}, -- number of required textures depends on visual textures = {}, -- number of required textures depends on visual
colors = {}, -- number of required colors depends on visual colors = {}, -- number of required colors depends on visual
spritediv = {x=1, y=1}, spritediv = {x = 1, y = 1},
initial_sprite_basepos = {x=0, y=0}, initial_sprite_basepos = {x = 0, y = 0},
is_visible = true, is_visible = true,
makes_footstep_sound = false, makes_footstep_sound = false,
automatic_rotate = false, automatic_rotate = false,
stepheight = 0, stepheight = 0,
automatic_face_movement_dir = 0.0, automatic_face_movement_dir = 0.0,
-- ^ automatically set yaw to movement direction; offset in degrees; false to disable -- ^ Automatically set yaw to movement direction, offset in degrees,
-- 'false' to disable.
automatic_face_movement_max_rotation_per_sec = -1, automatic_face_movement_max_rotation_per_sec = -1,
-- ^ limit automatic rotation to this value in degrees per second. values < 0 no limit -- ^ Limit automatic rotation to this value in degrees per second,
-- value < 0 no limit.
backface_culling = true, -- false to disable backface_culling for model backface_culling = true, -- false to disable backface_culling for model
nametag = "", -- by default empty, for players their name is shown if empty nametag = "", -- by default empty, for players their name is shown if empty
nametag_color = <color>, -- sets color of nametag as ColorSpec nametag_color = <color>, -- sets color of nametag as ColorSpec
@ -3947,7 +3976,9 @@ Definition tables
diggable = true, -- If false, can never be dug diggable = true, -- If false, can never be dug
climbable = false, -- If true, can be climbed on (ladder) climbable = false, -- If true, can be climbed on (ladder)
buildable_to = false, -- If true, placed nodes can replace this node buildable_to = false, -- If true, placed nodes can replace this node
floodable = false, -- If true, liquids flow into and replace this node floodable = false, --[[
^ If true, liquids flow into and replace this node.
^ Warning: making a liquid node 'floodable' does not work and may cause problems. ]]
liquidtype = "none", -- "none"/"source"/"flowing" liquidtype = "none", -- "none"/"source"/"flowing"
liquid_alternative_flowing = "", -- Flowing version of source liquid liquid_alternative_flowing = "", -- Flowing version of source liquid
liquid_alternative_source = "", -- Source version of flowing liquid liquid_alternative_source = "", -- Source version of flowing liquid
@ -3976,6 +4007,12 @@ Definition tables
^ If drawtype "nodebox" is used and selection_box is nil, then node_box is used. ]] ^ If drawtype "nodebox" is used and selection_box is nil, then node_box is used. ]]
legacy_facedir_simple = false, -- Support maps made in and before January 2012 legacy_facedir_simple = false, -- Support maps made in and before January 2012
legacy_wallmounted = false, -- Support maps made in and before January 2012 legacy_wallmounted = false, -- Support maps made in and before January 2012
waving = 0, --[[ valid for mesh, nodebox, plantlike, allfaces_optional nodes
^ 1 - wave node like plants (top of node moves, bottom is fixed)
^ 2 - wave node like leaves (whole node moves side-to-side synchronously)
^ caveats: not all models will properly wave
^ plantlike drawtype nodes can only wave like plants
^ allfaces_optional drawtype nodes can only wave like leaves --]]
sounds = { sounds = {
footstep = <SimpleSoundSpec>, footstep = <SimpleSoundSpec>,
dig = <SimpleSoundSpec>, -- "__group" = group-based sound (default) dig = <SimpleSoundSpec>, -- "__group" = group-based sound (default)
@ -4014,7 +4051,8 @@ Definition tables
^ node placement (i.e. schematics and VoxelManip) or air nodes. If ^ node placement (i.e. schematics and VoxelManip) or air nodes. If
^ return true the node is not flooded, but on_flood callback will ^ return true the node is not flooded, but on_flood callback will
^ most likely be called over and over again every liquid update ^ most likely be called over and over again every liquid update
^ interval. Default: nil ]] ^ interval. Default: nil.
^ Warning: making a liquid node 'floodable' does not work and may cause problems. ]]
after_place_node = func(pos, placer, itemstack, pointed_thing) --[[ after_place_node = func(pos, placer, itemstack, pointed_thing) --[[
^ Called after constructing node when node was placed using ^ Called after constructing node when node was placed using

View File

@ -18,6 +18,8 @@ dofile(minetest.get_modpath("default").."/mapgen.lua")
minetest.register_on_joinplayer(function(player) minetest.register_on_joinplayer(function(player)
local cb = function(player) local cb = function(player)
minetest.chat_send_player(player:get_player_name(), "This is the [minimal] \"Minimal Development Test\" game. Use [minetest_game] for the real thing.") minetest.chat_send_player(player:get_player_name(), "This is the [minimal] \"Minimal Development Test\" game. Use [minetest_game] for the real thing.")
player:set_attribute("test_attribute", "test_me")
player:set_attribute("remove_this", nil)
end end
minetest.after(2.0, cb, player) minetest.after(2.0, cb, player)
end) end)
@ -990,37 +992,37 @@ minetest.register_node("default:cloud", {
minetest.register_node("default:water_flowing", { minetest.register_node("default:water_flowing", {
description = "Water (flowing)", description = "Water (flowing)",
inventory_image = minetest.inventorycube("default_water.png"),
drawtype = "flowingliquid", drawtype = "flowingliquid",
tiles ={"default_water.png"}, tiles = {"default_water.png"},
special_tiles = { special_tiles = {
{name="default_water.png", backface_culling=false}, {name = "default_water.png", backface_culling = false},
{name="default_water.png", backface_culling=true}, {name = "default_water.png", backface_culling = true},
}, },
alpha = WATER_ALPHA, alpha = WATER_ALPHA,
paramtype = "light", paramtype = "light",
paramtype2 = "flowingliquid",
walkable = false, walkable = false,
pointable = false, pointable = false,
diggable = false, diggable = false,
buildable_to = true, buildable_to = true,
is_ground_content = false, is_ground_content = false,
drop = "",
drowning = 1, drowning = 1,
liquidtype = "flowing", liquidtype = "flowing",
liquid_alternative_flowing = "default:water_flowing", liquid_alternative_flowing = "default:water_flowing",
liquid_alternative_source = "default:water_source", liquid_alternative_source = "default:water_source",
liquid_viscosity = WATER_VISC, liquid_viscosity = WATER_VISC,
post_effect_color = {a=64, r=100, g=100, b=200}, post_effect_color = {a = 64, r = 100, g = 100, b = 200},
groups = {water=3, liquid=3}, groups = {water = 3, liquid = 3},
}) })
minetest.register_node("default:water_source", { minetest.register_node("default:water_source", {
description = "Water", description = "Water",
inventory_image = minetest.inventorycube("default_water.png"),
drawtype = "liquid", drawtype = "liquid",
tiles ={"default_water.png"}, tiles = {"default_water.png"},
special_tiles = { special_tiles = {
-- New-style water source material (mostly unused) -- New-style water source material (mostly unused)
{name="default_water.png", backface_culling=false}, {name = "default_water.png", backface_culling = false},
}, },
alpha = WATER_ALPHA, alpha = WATER_ALPHA,
paramtype = "light", paramtype = "light",
@ -1029,13 +1031,70 @@ minetest.register_node("default:water_source", {
diggable = false, diggable = false,
buildable_to = true, buildable_to = true,
is_ground_content = false, is_ground_content = false,
drop = "",
drowning = 1, drowning = 1,
liquidtype = "source", liquidtype = "source",
liquid_alternative_flowing = "default:water_flowing", liquid_alternative_flowing = "default:water_flowing",
liquid_alternative_source = "default:water_source", liquid_alternative_source = "default:water_source",
liquid_viscosity = WATER_VISC, liquid_viscosity = WATER_VISC,
post_effect_color = {a=64, r=100, g=100, b=200}, post_effect_color = {a = 64, r = 100, g = 100, b = 200},
groups = {water=3, liquid=3}, groups = {water = 3, liquid = 3},
})
minetest.register_node("default:river_water_source", {
description = "River Water Source",
drawtype = "liquid",
tiles = {"default_river_water.png"},
special_tiles = {
-- New-style water source material (mostly unused)
{name = "default_river_water.png", backface_culling = false},
},
alpha = 160,
paramtype = "light",
walkable = false,
pointable = false,
diggable = false,
buildable_to = true,
is_ground_content = false,
drop = "",
drowning = 1,
liquidtype = "source",
liquid_alternative_flowing = "default:river_water_flowing",
liquid_alternative_source = "default:river_water_source",
liquid_viscosity = 1,
liquid_renewable = false,
liquid_range = 2,
post_effect_color = {a = 103, r = 30, g = 76, b = 90},
groups = {water = 3, liquid = 3, puts_out_fire = 1, cools_lava = 1},
})
minetest.register_node("default:river_water_flowing", {
description = "Flowing River Water",
drawtype = "flowingliquid",
tiles = {"default_river_water.png"},
special_tiles = {
{name = "default_river_water.png", backface_culling = false},
{name = "default_river_water.png", backface_culling = true},
},
alpha = 160,
paramtype = "light",
paramtype2 = "flowingliquid",
walkable = false,
pointable = false,
diggable = false,
buildable_to = true,
is_ground_content = false,
drop = "",
drowning = 1,
liquidtype = "flowing",
liquid_alternative_flowing = "default:river_water_flowing",
liquid_alternative_source = "default:river_water_source",
liquid_viscosity = 1,
liquid_renewable = false,
liquid_range = 2,
post_effect_color = {a = 103, r = 30, g = 76, b = 90},
groups = {water = 3, liquid = 3, puts_out_fire = 1,
not_in_creative_inventory = 1, cools_lava = 1},
}) })
minetest.register_node("default:lava_flowing", { minetest.register_node("default:lava_flowing", {
@ -1226,6 +1285,8 @@ minetest.register_node("default:chest_locked", {
meta:set_string("owner", "") meta:set_string("owner", "")
local inv = meta:get_inventory() local inv = meta:get_inventory()
inv:set_size("main", 8*4) inv:set_size("main", 8*4)
-- this is not really the intended usage but works for testing purposes:
meta:mark_as_private("owner")
end, end,
can_dig = function(pos,player) can_dig = function(pos,player)
local meta = minetest.get_meta(pos); local meta = minetest.get_meta(pos);
@ -1387,13 +1448,13 @@ minetest.register_abm({
local srclist = inv:get_list("src") local srclist = inv:get_list("src")
local cooked = nil local cooked = nil
if srclist then if srclist then
cooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist}) cooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
end end
local was_active = false local was_active = false
if meta:get_float("fuel_time") < meta:get_float("fuel_totaltime") then if meta:get_float("fuel_time") < meta:get_float("fuel_totaltime") then
was_active = true was_active = true
meta:set_float("fuel_time", meta:get_float("fuel_time") + 1) meta:set_float("fuel_time", meta:get_float("fuel_time") + 1)
@ -1413,7 +1474,7 @@ minetest.register_abm({
meta:set_string("src_time", 0) meta:set_string("src_time", 0)
end end
end end
if meta:get_float("fuel_time") < meta:get_float("fuel_totaltime") then if meta:get_float("fuel_time") < meta:get_float("fuel_totaltime") then
local percent = math.floor(meta:get_float("fuel_time") / local percent = math.floor(meta:get_float("fuel_time") /
meta:get_float("fuel_totaltime") * 100) meta:get_float("fuel_totaltime") * 100)
@ -1438,7 +1499,7 @@ minetest.register_abm({
local cooked = nil local cooked = nil
local fuellist = inv:get_list("fuel") local fuellist = inv:get_list("fuel")
local srclist = inv:get_list("src") local srclist = inv:get_list("src")
if srclist then if srclist then
cooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist}) cooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
end end
@ -1464,7 +1525,7 @@ minetest.register_abm({
meta:set_string("fuel_totaltime", fuel.time) meta:set_string("fuel_totaltime", fuel.time)
meta:set_string("fuel_time", 0) meta:set_string("fuel_time", 0)
local stack = inv:get_stack("fuel", 1) local stack = inv:get_stack("fuel", 1)
stack:take_item() stack:take_item()
inv:set_stack("fuel", 1, stack) inv:set_stack("fuel", 1, stack)
@ -1571,7 +1632,7 @@ function default.grow_tree(data, a, pos, is_apple_tree, seed)
y = y+th-1 -- (x, y, z) is now last piece of trunk y = y+th-1 -- (x, y, z) is now last piece of trunk
local leaves_a = VoxelArea:new{MinEdge={x=-2, y=-1, z=-2}, MaxEdge={x=2, y=2, z=2}} local leaves_a = VoxelArea:new{MinEdge={x=-2, y=-1, z=-2}, MaxEdge={x=2, y=2, z=2}}
local leaves_buffer = {} local leaves_buffer = {}
-- Force leaves near the trunk -- Force leaves near the trunk
local d = 1 local d = 1
for xi = -d, d do for xi = -d, d do
@ -1581,14 +1642,14 @@ function default.grow_tree(data, a, pos, is_apple_tree, seed)
end end
end end
end end
-- Add leaves randomly -- Add leaves randomly
for iii = 1, 8 do for iii = 1, 8 do
local d = 1 local d = 1
local xx = pr:next(leaves_a.MinEdge.x, leaves_a.MaxEdge.x - d) local xx = pr:next(leaves_a.MinEdge.x, leaves_a.MaxEdge.x - d)
local yy = pr:next(leaves_a.MinEdge.y, leaves_a.MaxEdge.y - d) local yy = pr:next(leaves_a.MinEdge.y, leaves_a.MaxEdge.y - d)
local zz = pr:next(leaves_a.MinEdge.z, leaves_a.MaxEdge.z - d) local zz = pr:next(leaves_a.MinEdge.z, leaves_a.MaxEdge.z - d)
for xi = 0, d do for xi = 0, d do
for yi = 0, d do for yi = 0, d do
for zi = 0, d do for zi = 0, d do
@ -1597,7 +1658,7 @@ function default.grow_tree(data, a, pos, is_apple_tree, seed)
end end
end end
end end
-- Add the leaves -- Add the leaves
for xi = leaves_a.MinEdge.x, leaves_a.MaxEdge.x do for xi = leaves_a.MinEdge.x, leaves_a.MaxEdge.x do
for yi = leaves_a.MinEdge.y, leaves_a.MaxEdge.y do for yi = leaves_a.MinEdge.y, leaves_a.MaxEdge.y do

View File

@ -8,6 +8,7 @@ minetest.register_alias("mapgen_dirt", "default:dirt")
minetest.register_alias("mapgen_dirt_with_grass", "default:dirt_with_grass") minetest.register_alias("mapgen_dirt_with_grass", "default:dirt_with_grass")
minetest.register_alias("mapgen_sand", "default:sand") minetest.register_alias("mapgen_sand", "default:sand")
minetest.register_alias("mapgen_water_source", "default:water_source") minetest.register_alias("mapgen_water_source", "default:water_source")
minetest.register_alias("mapgen_river_water_source", "default:river_water_source")
minetest.register_alias("mapgen_lava_source", "default:lava_source") minetest.register_alias("mapgen_lava_source", "default:lava_source")
minetest.register_alias("mapgen_gravel", "default:gravel") minetest.register_alias("mapgen_gravel", "default:gravel")

Binary file not shown.

After

Width:  |  Height:  |  Size: 716 B

View File

@ -502,10 +502,16 @@ minetest.register_craftitem("experimental:tester_tool_1", {
on_use = function(itemstack, user, pointed_thing) on_use = function(itemstack, user, pointed_thing)
--print(dump(pointed_thing)) --print(dump(pointed_thing))
if pointed_thing.type == "node" then if pointed_thing.type == "node" then
if minetest.get_node(pointed_thing.under).name == "experimental:tester_node_1" then local node = minetest.get_node(pointed_thing.under)
if node.name == "experimental:tester_node_1" or node.name == "default:chest" then
local p = pointed_thing.under local p = pointed_thing.under
minetest.log("action", "Tester tool used at "..minetest.pos_to_string(p)) minetest.log("action", "Tester tool used at "..minetest.pos_to_string(p))
minetest.dig_node(p) if node.name == "experimental:tester_node_1" then
minetest.dig_node(p)
else
minetest.get_meta(p):mark_as_private({"infotext", "formspec"})
minetest.chat_send_player(user:get_player_name(), "Verify that chest is unusable now.")
end
else else
local p = pointed_thing.above local p = pointed_thing.above
minetest.log("action", "Tester tool used at "..minetest.pos_to_string(p)) minetest.log("action", "Tester tool used at "..minetest.pos_to_string(p))

View File

@ -186,6 +186,31 @@
# type: key # type: key
# keymap_noclip = KEY_KEY_H # keymap_noclip = KEY_KEY_H
# Key for selecting the next item in the hotbar.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
# type: key
# keymap_hotbar_next = KEY_KEY_N
# Key for selecting the previous item in the hotbar.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
# type: key
# keymap_hotbar_previous = KEY_KEY_B
# Key for muting the game.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
# type: key
# keymap_mute = KEY_KEY_M
# Key for increasing the volume.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
# type: key
# keymap_increase_volume =
# Key for decreasing the volume.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
# type: key
# keymap_decrease_volume =
# Key for toggling autorun. # Key for toggling autorun.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
# type: key # type: key
@ -318,6 +343,10 @@
# type: string # type: string
# serverlist_file = favoriteservers.txt # serverlist_file = favoriteservers.txt
# Maximum size of the out chat queue. 0 to disable queueing and -1 to make the queue size unlimited
# type: int min: -1
max_out_chat_queue_size = 20
## Graphics ## Graphics
### In-Game ### In-Game
@ -357,7 +386,7 @@
# enable_3d_clouds = true # enable_3d_clouds = true
# Method used to highlight selected object. # Method used to highlight selected object.
# type: enum values: box, halo # type: enum values: box, halo, none
# node_highlighting = box # node_highlighting = box
# Adds particles when digging a node. # Adds particles when digging a node.
@ -526,6 +555,10 @@
# type: int # type: int
# screenH = 600 # screenH = 600
# Save the window size automatically when modified.
# type: bool
# autosave_screensize = true
# Fullscreen mode. # Fullscreen mode.
# type: bool # type: bool
# fullscreen = false # fullscreen = false
@ -569,11 +602,7 @@
# type: int # type: int
# cloud_radius = 12 # cloud_radius = 12
# Enables view bobbing when walking. # Enable view bobbing and amount of view bobbing.
# type: bool
# view_bobbing = true
# Multiplier for view bobbing.
# For example: 0 for no view bobbing; 1.0 for normal; 2.0 for double. # For example: 0 for no view bobbing; 1.0 for normal; 2.0 for double.
# type: float # type: float
# view_bobbing_amount = 1.0 # view_bobbing_amount = 1.0
@ -1763,7 +1792,7 @@
# - action # - action
# - info # - info
# - verbose # - verbose
# type: enum values: , warning, action, info, verbose # type: enum values: , none, error, warning, action, info, verbose
# debug_log_level = action # debug_log_level = action
# IPv6 support. # IPv6 support.
@ -1815,4 +1844,3 @@
# Print the engine's profiling data in regular intervals (in seconds). 0 = disable. Useful for developers. # Print the engine's profiling data in regular intervals (in seconds). 0 = disable. Useful for developers.
# type: int # type: int
# profiler_print_interval = 0 # profiler_print_interval = 0

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

4688
po/dv/minetest.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

4702
po/sv/minetest.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -377,6 +377,7 @@ set(common_SRCS
convert_json.cpp convert_json.cpp
craftdef.cpp craftdef.cpp
database-dummy.cpp database-dummy.cpp
database-files.cpp
database-leveldb.cpp database-leveldb.cpp
database-postgresql.cpp database-postgresql.cpp
database-redis.cpp database-redis.cpp
@ -387,6 +388,7 @@ set(common_SRCS
dungeongen.cpp dungeongen.cpp
emerge.cpp emerge.cpp
environment.cpp environment.cpp
face_position_cache.cpp
filesys.cpp filesys.cpp
genericobject.cpp genericobject.cpp
gettext.cpp gettext.cpp
@ -753,12 +755,12 @@ else()
set(OTHER_FLAGS "${OTHER_FLAGS} -mthreads -fexceptions") set(OTHER_FLAGS "${OTHER_FLAGS} -mthreads -fexceptions")
endif() endif()
set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG ${RELEASE_WARNING_FLAGS} ${WARNING_FLAGS} ${OTHER_FLAGS} -ffast-math -Wall -pipe -funroll-loops") set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG ${RELEASE_WARNING_FLAGS} ${WARNING_FLAGS} ${OTHER_FLAGS} -Wall -pipe -funroll-loops")
if(APPLE) if(CMAKE_SYSTEM_NAME MATCHES "(Darwin|FreeBSD)")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Os") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Os")
else() else()
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -fomit-frame-pointer") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -ffast-math -fomit-frame-pointer")
endif(APPLE) endif(CMAKE_SYSTEM_NAME MATCHES "(Darwin|FreeBSD)")
set(CMAKE_CXX_FLAGS_SEMIDEBUG "-g -O1 -Wall -Wabi ${WARNING_FLAGS} ${OTHER_FLAGS}") set(CMAKE_CXX_FLAGS_SEMIDEBUG "-g -O1 -Wall -Wabi ${WARNING_FLAGS} ${OTHER_FLAGS}")
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wabi ${WARNING_FLAGS} ${OTHER_FLAGS}") set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wabi ${WARNING_FLAGS} ${OTHER_FLAGS}")

View File

@ -28,9 +28,9 @@ enum ActiveObjectType {
ACTIVEOBJECT_TYPE_TEST = 1, ACTIVEOBJECT_TYPE_TEST = 1,
// Deprecated stuff // Deprecated stuff
ACTIVEOBJECT_TYPE_ITEM = 2, ACTIVEOBJECT_TYPE_ITEM = 2,
ACTIVEOBJECT_TYPE_RAT = 3, // ACTIVEOBJECT_TYPE_RAT = 3,
ACTIVEOBJECT_TYPE_OERKKI1 = 4, // ACTIVEOBJECT_TYPE_OERKKI1 = 4,
ACTIVEOBJECT_TYPE_FIREFLY = 5, // ACTIVEOBJECT_TYPE_FIREFLY = 5,
ACTIVEOBJECT_TYPE_MOBV2 = 6, ACTIVEOBJECT_TYPE_MOBV2 = 6,
// End deprecated stuff // End deprecated stuff
ACTIVEOBJECT_TYPE_LUAENTITY = 7, ACTIVEOBJECT_TYPE_LUAENTITY = 7,

View File

@ -41,12 +41,12 @@ public:
void add(const std::string &ip, const std::string &name); void add(const std::string &ip, const std::string &name);
void remove(const std::string &ip_or_name); void remove(const std::string &ip_or_name);
bool isModified(); bool isModified();
private: private:
Mutex m_mutex; Mutex m_mutex;
std::string m_banfilepath; std::string m_banfilepath;
StringMap m_ips; StringMap m_ips;
bool m_modified; bool m_modified;
}; };
#endif #endif

View File

@ -33,6 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/numeric.h" #include "util/numeric.h"
#include "constants.h" #include "constants.h"
#include "fontengine.h" #include "fontengine.h"
#include "script/scripting_client.h"
#define CAMERA_OFFSET_STEP 200 #define CAMERA_OFFSET_STEP 200
@ -102,7 +103,6 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control,
m_cache_view_bobbing_amount = g_settings->getFloat("view_bobbing_amount"); m_cache_view_bobbing_amount = g_settings->getFloat("view_bobbing_amount");
m_cache_fov = g_settings->getFloat("fov"); m_cache_fov = g_settings->getFloat("fov");
m_cache_zoom_fov = g_settings->getFloat("zoom_fov"); m_cache_zoom_fov = g_settings->getFloat("zoom_fov");
m_cache_view_bobbing = g_settings->getBool("view_bobbing");
m_nametags.clear(); m_nametags.clear();
} }
@ -126,6 +126,10 @@ bool Camera::successfullyCreated(std::string &error_message)
} else { } else {
error_message.clear(); error_message.clear();
} }
if (g_settings->getBool("enable_client_modding")) {
m_client->getScript()->on_camera_ready(this);
}
return error_message.empty(); return error_message.empty();
} }
@ -280,8 +284,8 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime,
v3f rel_cam_target = v3f(0,0,1); v3f rel_cam_target = v3f(0,0,1);
v3f rel_cam_up = v3f(0,1,0); v3f rel_cam_up = v3f(0,1,0);
if (m_view_bobbing_anim != 0 && m_camera_mode < CAMERA_MODE_THIRD) if (m_cache_view_bobbing_amount != 0.0f && m_view_bobbing_anim != 0.0f &&
{ m_camera_mode < CAMERA_MODE_THIRD) {
f32 bobfrac = my_modf(m_view_bobbing_anim * 2); f32 bobfrac = my_modf(m_view_bobbing_anim * 2);
f32 bobdir = (m_view_bobbing_anim < 0.5) ? 1.0 : -1.0; f32 bobdir = (m_view_bobbing_anim < 0.5) ? 1.0 : -1.0;
@ -467,9 +471,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime,
const bool swimming = (movement_XZ || player->swimming_vertical) && player->in_liquid; const bool swimming = (movement_XZ || player->swimming_vertical) && player->in_liquid;
const bool climbing = movement_Y && player->is_climbing; const bool climbing = movement_Y && player->is_climbing;
if ((walking || swimming || climbing) && if ((walking || swimming || climbing) &&
m_cache_view_bobbing && (!g_settings->getBool("free_move") || !m_client->checkLocalPrivilege("fly"))) {
(!g_settings->getBool("free_move") || !m_client->checkLocalPrivilege("fly")))
{
// Start animation // Start animation
m_view_bobbing_state = 1; m_view_bobbing_state = 1;
m_view_bobbing_speed = MYMIN(speed.getLength(), 70); m_view_bobbing_speed = MYMIN(speed.getLength(), 70);

View File

@ -64,22 +64,6 @@ public:
Client *client); Client *client);
~Camera(); ~Camera();
// Get player scene node.
// This node is positioned at the player's torso (without any view bobbing),
// as given by Player::m_position. Yaw is applied but not pitch.
inline scene::ISceneNode* getPlayerNode() const
{
return m_playernode;
}
// Get head scene node.
// It has the eye transformation and pitch applied,
// but no view bobbing.
inline scene::ISceneNode* getHeadNode() const
{
return m_headnode;
}
// Get camera scene node. // Get camera scene node.
// It has the eye transformation, pitch and view bobbing applied. // It has the eye transformation, pitch and view bobbing applied.
inline scene::ICameraSceneNode* getCameraNode() const inline scene::ICameraSceneNode* getCameraNode() const
@ -161,6 +145,12 @@ public:
m_camera_mode = CAMERA_MODE_FIRST; m_camera_mode = CAMERA_MODE_FIRST;
} }
// Set the current camera mode
inline void setCameraMode(CameraMode mode)
{
m_camera_mode = mode;
}
//read the current camera mode //read the current camera mode
inline CameraMode getCameraMode() inline CameraMode getCameraMode()
{ {
@ -231,7 +221,6 @@ private:
f32 m_cache_view_bobbing_amount; f32 m_cache_view_bobbing_amount;
f32 m_cache_fov; f32 m_cache_fov;
f32 m_cache_zoom_fov; f32 m_cache_zoom_fov;
bool m_cache_view_bobbing;
std::list<Nametag *> m_nametags; std::list<Nametag *> m_nametags;
}; };

View File

@ -160,9 +160,9 @@ CavernsNoise::CavernsNoise(
{ {
assert(nodedef); assert(nodedef);
m_ndef = nodedef; m_ndef = nodedef;
m_csize = chunksize; m_csize = chunksize;
m_cavern_limit = cavern_limit; m_cavern_limit = cavern_limit;
m_cavern_taper = cavern_taper; m_cavern_taper = cavern_taper;
m_cavern_threshold = cavern_threshold; m_cavern_threshold = cavern_threshold;
@ -207,7 +207,7 @@ bool CavernsNoise::generateCaverns(MMVManip *vm, v3s16 nmin, v3s16 nmax)
} }
//// Place nodes //// Place nodes
bool has_cavern = false; bool near_cavern = false;
v3s16 em = vm->m_area.getExtent(); v3s16 em = vm->m_area.getExtent();
u32 index2d = 0; u32 index2d = 0;
@ -229,20 +229,22 @@ bool CavernsNoise::generateCaverns(MMVManip *vm, v3s16 nmin, v3s16 nmax)
vm->m_area.add_y(em, vi, -1), vm->m_area.add_y(em, vi, -1),
cavern_amp_index++) { cavern_amp_index++) {
content_t c = vm->m_data[vi].getContent(); content_t c = vm->m_data[vi].getContent();
float nabs_cavern = fabs(noise_cavern->result[index3d]); float n_absamp_cavern = fabs(noise_cavern->result[index3d]) *
// Caverns generate first but still remove lava and water in case cavern_amp[cavern_amp_index];
// of overgenerated classic caves. // Disable CavesRandomWalk at a safe distance from caverns
if (nabs_cavern * cavern_amp[cavern_amp_index] > m_cavern_threshold && // to avoid excessively spreading liquids in caverns.
(m_ndef->get(c).is_ground_content || if (n_absamp_cavern > m_cavern_threshold - 0.1f) {
c == c_lava_source || c == c_water_source)) { near_cavern = true;
vm->m_data[vi] = MapNode(CONTENT_AIR); if (n_absamp_cavern > m_cavern_threshold &&
has_cavern = true; m_ndef->get(c).is_ground_content)
vm->m_data[vi] = MapNode(CONTENT_AIR);
} }
} }
} }
delete[] cavern_amp; delete[] cavern_amp;
return has_cavern;
return near_cavern;
} }

View File

@ -37,11 +37,12 @@ class GenerateNotifier;
TODO(hmmmm): Remove dependency on biomes TODO(hmmmm): Remove dependency on biomes
TODO(hmmmm): Find alternative to overgeneration as solution for sunlight issue TODO(hmmmm): Find alternative to overgeneration as solution for sunlight issue
*/ */
class CavesNoiseIntersection { class CavesNoiseIntersection
{
public: public:
CavesNoiseIntersection(INodeDefManager *nodedef, BiomeManager *biomemgr, CavesNoiseIntersection(INodeDefManager *nodedef, BiomeManager *biomemgr,
v3s16 chunksize, NoiseParams *np_cave1, NoiseParams *np_cave2, v3s16 chunksize, NoiseParams *np_cave1, NoiseParams *np_cave2,
s32 seed, float cave_width); s32 seed, float cave_width);
~CavesNoiseIntersection(); ~CavesNoiseIntersection();
void generateCaves(MMVManip *vm, v3s16 nmin, v3s16 nmax, u8 *biomemap); void generateCaves(MMVManip *vm, v3s16 nmin, v3s16 nmax, u8 *biomemap);
@ -65,10 +66,12 @@ private:
/* /*
CavernsNoise is a cave digging algorithm CavernsNoise is a cave digging algorithm
*/ */
class CavernsNoise { class CavernsNoise
{
public: public:
CavernsNoise(INodeDefManager *nodedef, v3s16 chunksize, NoiseParams *np_cavern, CavernsNoise(INodeDefManager *nodedef, v3s16 chunksize, NoiseParams *np_cavern,
s32 seed, float cavern_limit, float cavern_taper, float cavern_threshold); s32 seed, float cavern_limit, float cavern_taper,
float cavern_threshold);
~CavernsNoise(); ~CavernsNoise();
bool generateCaverns(MMVManip *vm, v3s16 nmin, v3s16 nmax); bool generateCaverns(MMVManip *vm, v3s16 nmin, v3s16 nmax);
@ -105,7 +108,8 @@ private:
This algorithm is very fast, executing in less than 1ms on average for an This algorithm is very fast, executing in less than 1ms on average for an
80x80x80 chunk of map on a modern processor. 80x80x80 chunk of map on a modern processor.
*/ */
class CavesRandomWalk { class CavesRandomWalk
{
public: public:
MMVManip *vm; MMVManip *vm;
INodeDefManager *ndef; INodeDefManager *ndef;
@ -150,18 +154,16 @@ public:
// ndef is a mandatory parameter. // ndef is a mandatory parameter.
// If gennotify is NULL, generation events are not logged. // If gennotify is NULL, generation events are not logged.
CavesRandomWalk(INodeDefManager *ndef, CavesRandomWalk(INodeDefManager *ndef, GenerateNotifier *gennotify = NULL,
GenerateNotifier *gennotify = NULL, s32 seed = 0, int water_level = 1,
s32 seed = 0, content_t water_source = CONTENT_IGNORE,
int water_level = 1, content_t lava_source = CONTENT_IGNORE);
content_t water_source = CONTENT_IGNORE,
content_t lava_source = CONTENT_IGNORE);
// vm and ps are mandatory parameters. // vm and ps are mandatory parameters.
// If heightmap is NULL, the surface level at all points is assumed to // If heightmap is NULL, the surface level at all points is assumed to
// be water_level. // be water_level.
void makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax, PseudoRandom *ps, void makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax, PseudoRandom *ps,
bool is_large_cave, int max_stone_height, s16 *heightmap); bool is_large_cave, int max_stone_height, s16 *heightmap);
private: private:
void makeTunnel(bool dirswitch); void makeTunnel(bool dirswitch);
@ -183,7 +185,8 @@ private:
tl;dr, tl;dr,
*** DO NOT TOUCH THIS CLASS UNLESS YOU KNOW WHAT YOU ARE DOING *** *** DO NOT TOUCH THIS CLASS UNLESS YOU KNOW WHAT YOU ARE DOING ***
*/ */
class CavesV6 { class CavesV6
{
public: public:
MMVManip *vm; MMVManip *vm;
INodeDefManager *ndef; INodeDefManager *ndef;
@ -222,18 +225,16 @@ public:
// ndef is a mandatory parameter. // ndef is a mandatory parameter.
// If gennotify is NULL, generation events are not logged. // If gennotify is NULL, generation events are not logged.
CavesV6(INodeDefManager *ndef, CavesV6(INodeDefManager *ndef, GenerateNotifier *gennotify = NULL,
GenerateNotifier *gennotify = NULL, int water_level = 1, content_t water_source = CONTENT_IGNORE,
int water_level = 1, content_t lava_source = CONTENT_IGNORE);
content_t water_source = CONTENT_IGNORE,
content_t lava_source = CONTENT_IGNORE);
// vm, ps, and ps2 are mandatory parameters. // vm, ps, and ps2 are mandatory parameters.
// If heightmap is NULL, the surface level at all points is assumed to // If heightmap is NULL, the surface level at all points is assumed to
// be water_level. // be water_level.
void makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax, void makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax, PseudoRandom *ps,
PseudoRandom *ps, PseudoRandom *ps2, PseudoRandom *ps2, bool is_large_cave, int max_stone_height,
bool is_large_cave, int max_stone_height, s16 *heightmap = NULL); s16 *heightmap = NULL);
private: private:
void makeTunnel(bool dirswitch); void makeTunnel(bool dirswitch);

View File

@ -77,11 +77,6 @@ u32 ChatBuffer::getLineCount() const
return m_unformatted.size(); return m_unformatted.size();
} }
u32 ChatBuffer::getScrollback() const
{
return m_scrollback;
}
const ChatLine& ChatBuffer::getLine(u32 index) const const ChatLine& ChatBuffer::getLine(u32 index) const
{ {
assert(index < getLineCount()); // pre-condition assert(index < getLineCount()); // pre-condition
@ -336,7 +331,7 @@ u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols,
while (frag_length < remaining_in_input && while (frag_length < remaining_in_input &&
frag_length < remaining_in_output) frag_length < remaining_in_output)
{ {
if (isspace(line.text.getString()[in_pos + frag_length])) if (iswspace(line.text.getString()[in_pos + frag_length]))
space_pos = frag_length; space_pos = frag_length;
++frag_length; ++frag_length;
} }
@ -493,9 +488,9 @@ void ChatPrompt::nickCompletion(const std::list<std::string>& names, bool backwa
{ {
// no previous nick completion is active // no previous nick completion is active
prefix_start = prefix_end = m_cursor; prefix_start = prefix_end = m_cursor;
while (prefix_start > 0 && !isspace(m_line[prefix_start-1])) while (prefix_start > 0 && !iswspace(m_line[prefix_start-1]))
--prefix_start; --prefix_start;
while (prefix_end < m_line.size() && !isspace(m_line[prefix_end])) while (prefix_end < m_line.size() && !iswspace(m_line[prefix_end]))
++prefix_end; ++prefix_end;
if (prefix_start == prefix_end) if (prefix_start == prefix_end)
return; return;
@ -524,7 +519,7 @@ void ChatPrompt::nickCompletion(const std::list<std::string>& names, bool backwa
u32 replacement_index = 0; u32 replacement_index = 0;
if (!initial) if (!initial)
{ {
while (word_end < m_line.size() && !isspace(m_line[word_end])) while (word_end < m_line.size() && !iswspace(m_line[word_end]))
++word_end; ++word_end;
std::wstring word = m_line.substr(prefix_start, word_end - prefix_start); std::wstring word = m_line.substr(prefix_start, word_end - prefix_start);
@ -543,7 +538,7 @@ void ChatPrompt::nickCompletion(const std::list<std::string>& names, bool backwa
} }
} }
std::wstring replacement = completions[replacement_index]; std::wstring replacement = completions[replacement_index];
if (word_end < m_line.size() && isspace(word_end)) if (word_end < m_line.size() && iswspace(m_line[word_end]))
++word_end; ++word_end;
// replace existing word with replacement word, // replace existing word with replacement word,
@ -598,17 +593,17 @@ void ChatPrompt::cursorOperation(CursorOp op, CursorOpDir dir, CursorOpScope sco
case CURSOROP_SCOPE_WORD: case CURSOROP_SCOPE_WORD:
if (dir == CURSOROP_DIR_RIGHT) { if (dir == CURSOROP_DIR_RIGHT) {
// skip one word to the right // skip one word to the right
while (new_cursor < length && isspace(m_line[new_cursor])) while (new_cursor < length && iswspace(m_line[new_cursor]))
new_cursor++; new_cursor++;
while (new_cursor < length && !isspace(m_line[new_cursor])) while (new_cursor < length && !iswspace(m_line[new_cursor]))
new_cursor++; new_cursor++;
while (new_cursor < length && isspace(m_line[new_cursor])) while (new_cursor < length && iswspace(m_line[new_cursor]))
new_cursor++; new_cursor++;
} else { } else {
// skip one word to the left // skip one word to the left
while (new_cursor >= 1 && isspace(m_line[new_cursor - 1])) while (new_cursor >= 1 && iswspace(m_line[new_cursor - 1]))
new_cursor--; new_cursor--;
while (new_cursor >= 1 && !isspace(m_line[new_cursor - 1])) while (new_cursor >= 1 && !iswspace(m_line[new_cursor - 1]))
new_cursor--; new_cursor--;
} }
break; break;

Some files were not shown because too many files have changed in this diff Show More