Merge 0.4.16 into stable-0.4

This commit is contained in:
ShadowNinja 2017-06-03 14:55:10 -04:00
commit caecdb681c
637 changed files with 95690 additions and 40930 deletions

28
.clang-format Normal file

@ -0,0 +1,28 @@
BasedOnStyle: LLVM
IndentWidth: 8
UseTab: Always
BreakBeforeBraces: Custom
Standard: Cpp03
BraceWrapping:
AfterClass: true
AfterControlStatement: false
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterStruct: true
AfterUnion: true
BeforeCatch: false
BeforeElse: false
AllowShortIfStatementsOnASingleLine: false
IndentCaseLabels: false
AccessModifierOffset: -8
ColumnLimit: 90
AllowShortFunctionsOnASingleLine: Inline
SortIncludes: false
IncludeCategories:
- Regex: '^".*'
Priority: 2
- Regex: '^<.*'
Priority: 1
AlignAfterOpenBracket: DontAlign
ContinuationIndentWidth: 16

14
.gitignore vendored

@ -22,9 +22,12 @@ tags
!tags/ !tags/
gtags.files gtags.files
.idea/* .idea/*
# Codelite
*.project
## Files related to minetest development cycle ## Files related to minetest development cycle
/*.patch /*.patch
*.diff
# GNU Patch reject file # GNU Patch reject file
*.rej *.rej
@ -43,11 +46,17 @@ gtags.files
!/mods/minetest/mods_here.txt !/mods/minetest/mods_here.txt
/worlds /worlds
/world/ /world/
/clientmods/*
!/clientmods/preview/
/client/mod_storage/
## Configuration/log files ## Configuration/log files
minetest.conf minetest.conf
debug.txt debug.txt
## Other files generated by minetest
screenshot_*.png
## Doxygen files ## Doxygen files
doc/Doxyfile doc/Doxyfile
doc/html/ doc/html/
@ -74,16 +83,19 @@ locale/
*.a *.a
*.ninja *.ninja
.ninja* .ninja*
*.gch
cmake-build-debug/
cmake-build-release/
## Android build files ## Android build files
build/android/src/main/assets build/android/src/main/assets
build/android/build build/android/build
build/android/deps build/android/deps
build/android/libs build/android/libs
build/android/jni/lib
build/android/jni/src build/android/jni/src
build/android/src/main/jniLibs build/android/src/main/jniLibs
build/android/obj build/android/obj
build/android/local.properties build/android/local.properties
build/android/.gradle build/android/.gradle
timestamp timestamp

223
.gitlab-ci.yml Normal file

@ -0,0 +1,223 @@
---
# Github repository is cloned every day on Gitlab.com
# https://gitlab.com/minetest/minetest
# Pipelines URL: https://gitlab.com/minetest/minetest/pipelines
stages:
- build
- package
- deploy
variables:
MINETEST_GAME_REPO: "https://github.com/minetest/minetest_game.git"
.build_template: &build_definition
stage: build
script:
- mkdir cmakebuild
- mkdir -p artifact/minetest/usr/
- cd cmakebuild
- cmake -DCMAKE_INSTALL_PREFIX=../artifact/minetest/usr/ -DCMAKE_BUILD_TYPE=Release -DRUN_IN_PLACE=FALSE -DENABLE_GETTEXT=TRUE -DBUILD_SERVER=TRUE ..
- make -j2
- make install
artifacts:
when: on_success
expire_in: 1h
paths:
- artifact/*
.debpkg_template: &debpkg_template
stage: package
before_script:
- apt-get update -y
- apt-get install -y git
- mkdir -p build/deb/minetest/DEBIAN/
- cp misc/debpkg-control build/deb/minetest/DEBIAN/control
- cp -Rp artifact/minetest/usr build/deb/minetest/
script:
- git clone $MINETEST_GAME_REPO build/deb/minetest/usr/share/minetest/games/minetest
- rm -Rf build/deb/minetest/usr/share/minetest/games/minetest/.git
- sed -i 's/DATEPLACEHOLDER/'$(date +%y.%m.%d)'/g' build/deb/minetest/DEBIAN/control
- sed -i 's/LEVELDB_PLACEHOLDER/'$LEVELDB_PKG'/g' build/deb/minetest/DEBIAN/control
- cd build/deb/ && dpkg-deb -b minetest/
artifacts:
when: on_success
expire_in: 30 day
paths:
- build/deb/*.deb
.debpkg_install: &debpkg_install
stage: deploy
before_script:
- apt-get update -y
- apt-get install -y libc6 libcurl3-gnutls libfreetype6 libirrlicht1.8 $LEVELDB_PKG liblua5.1-0 libluajit-5.1-2 libopenal1 libstdc++6 libvorbisfile3 libx11-6 zlib1g
script:
- dpkg -i build/deb/*.deb
##
## Debian
##
# Jessie
build:debian-8:
<<: *build_definition
image: debian:8
before_script:
- apt-get update -y
- apt-get -y install build-essential libirrlicht-dev cmake libbz2-dev libpng-dev libjpeg-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev libjsoncpp-dev
package:debian-8:
image: debian:8
dependencies:
- build:debian-8
variables:
LEVELDB_PKG: libleveldb1
<<: *debpkg_template
deploy:debian-8:
image: debian:8
dependencies:
- package:debian-8
variables:
LEVELDB_PKG: libleveldb1
<<: *debpkg_install
# Stretch
build:debian-9:
<<: *build_definition
image: debian:9
before_script:
- apt-get update -y
- apt-get -y install build-essential libirrlicht-dev cmake libbz2-dev libpng-dev libjpeg-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev libjsoncpp-dev
package:debian-9:
image: debian:9
dependencies:
- build:debian-9
variables:
LEVELDB_PKG: libleveldb1v5
<<: *debpkg_template
deploy:debian-9:
image: debian:9
dependencies:
- package:debian-9
variables:
LEVELDB_PKG: libleveldb1v5
<<: *debpkg_install
##
## Ubuntu
##
# Trusty
build:ubuntu-14.04:
<<: *build_definition
image: ubuntu:trusty
before_script:
- apt-get update -y
- apt-get -y install build-essential libirrlicht-dev cmake libbz2-dev libpng-dev libjpeg-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev libjsoncpp-dev
package:ubuntu-14.04:
image: ubuntu:trusty
dependencies:
- build:ubuntu-14.04
variables:
LEVELDB_PKG: libleveldb1
<<: *debpkg_template
deploy:ubuntu-14.04:
image: ubuntu:trusty
dependencies:
- package:ubuntu-14.04
variables:
LEVELDB_PKG: libleveldb1
<<: *debpkg_install
# Xenial
build:ubuntu-16.04:
<<: *build_definition
image: ubuntu:xenial
before_script:
- apt-get update -y
- apt-get -y install build-essential libirrlicht-dev cmake libbz2-dev libpng-dev libjpeg-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev libjsoncpp-dev
package:ubuntu-16.04:
image: ubuntu:xenial
dependencies:
- build:ubuntu-16.04
variables:
LEVELDB_PKG: libleveldb1v5
<<: *debpkg_template
deploy:ubuntu-16.04:
image: ubuntu:xenial
dependencies:
- package:ubuntu-16.04
variables:
LEVELDB_PKG: libleveldb1v5
<<: *debpkg_install
# Yakkety
build:ubuntu-16.10:
<<: *build_definition
image: ubuntu:yakkety
before_script:
- apt-get update -y
- apt-get -y install build-essential libirrlicht-dev cmake libbz2-dev libpng-dev libjpeg-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev libjsoncpp-dev
package:ubuntu-16.10:
image: ubuntu:yakkety
dependencies:
- build:ubuntu-16.10
variables:
LEVELDB_PKG: libleveldb1v5
<<: *debpkg_template
deploy:ubuntu-16.10:
image: ubuntu:yakkety
dependencies:
- package:ubuntu-16.10
variables:
LEVELDB_PKG: libleveldb1v5
<<: *debpkg_install
# Zesty
build:ubuntu-17.04:
<<: *build_definition
image: ubuntu:zesty
before_script:
- apt-get update -y
- apt-get -y install build-essential libirrlicht-dev cmake libbz2-dev libpng-dev libjpeg-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev libjsoncpp-dev
package:ubuntu-17.04:
image: ubuntu:zesty
dependencies:
- build:ubuntu-17.04
variables:
LEVELDB_PKG: libleveldb1v5
<<: *debpkg_template
deploy:ubuntu-17.04:
image: ubuntu:zesty
dependencies:
- package:ubuntu-17.04
variables:
LEVELDB_PKG: libleveldb1v5
<<: *debpkg_install
##
## Fedora
##
build:fedora-24:
<<: *build_definition
image: fedora:24
before_script:
- dnf -y install make automake gcc gcc-c++ kernel-devel cmake libcurl* openal* libvorbis* libXxf86vm-devel libogg-devel freetype-devel mesa-libGL-devel zlib-devel jsoncpp-devel irrlicht-devel bzip2-libs gmp-devel sqlite-devel luajit-devel leveldb-devel ncurses-devel doxygen spatialindex-devel bzip2-devel

@ -22,6 +22,14 @@ matrix:
- env: PLATFORM=Unix COMPILER=clang - env: PLATFORM=Unix COMPILER=clang
compiler: clang compiler: clang
os: linux os: linux
- env: PLATFORM=Unix COMPILER=clang VALGRIND=1
compiler: clang
os: linux
dist: trusty
- env: COMPILER=none LINT=1
compiler: clang
os: linux
dist: trusty
- env: PLATFORM=Unix COMPILER=g++-6 - env: PLATFORM=Unix COMPILER=g++-6
compiler: gcc compiler: gcc
os: linux os: linux

@ -13,7 +13,7 @@ set(PROJECT_NAME_CAPITALIZED "Minetest")
# Also remember to set PROTOCOL_VERSION in network/networkprotocol.h when releasing # Also remember to set PROTOCOL_VERSION in network/networkprotocol.h when releasing
set(VERSION_MAJOR 0) set(VERSION_MAJOR 0)
set(VERSION_MINOR 4) set(VERSION_MINOR 4)
set(VERSION_PATCH 15) set(VERSION_PATCH 16)
set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string") set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string")
# Change to false for releases # Change to false for releases
@ -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} ***")
@ -49,7 +54,6 @@ if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type: Debug or Release" FORCE) set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type: Debug or Release" FORCE)
endif() endif()
# Included stuff # Included stuff
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
@ -82,7 +86,7 @@ elseif(UNIX) # Linux, BSD etc
set(EXAMPLE_CONF_DIR ".") set(EXAMPLE_CONF_DIR ".")
set(MANDIR "unix/man") set(MANDIR "unix/man")
set(XDG_APPS_DIR "unix/applications") set(XDG_APPS_DIR "unix/applications")
set(APPDATADIR "unix/appdata") set(APPDATADIR "unix/metainfo")
set(ICONDIR "unix/icons") set(ICONDIR "unix/icons")
set(LOCALEDIR "locale") set(LOCALEDIR "locale")
else() else()
@ -92,7 +96,7 @@ elseif(UNIX) # Linux, BSD etc
set(MANDIR "${CMAKE_INSTALL_PREFIX}/share/man") set(MANDIR "${CMAKE_INSTALL_PREFIX}/share/man")
set(EXAMPLE_CONF_DIR ${DOCDIR}) set(EXAMPLE_CONF_DIR ${DOCDIR})
set(XDG_APPS_DIR "${CMAKE_INSTALL_PREFIX}/share/applications") set(XDG_APPS_DIR "${CMAKE_INSTALL_PREFIX}/share/applications")
set(APPDATADIR "${CMAKE_INSTALL_PREFIX}/share/appdata") set(APPDATADIR "${CMAKE_INSTALL_PREFIX}/share/metainfo")
set(ICONDIR "${CMAKE_INSTALL_PREFIX}/share/icons") set(ICONDIR "${CMAKE_INSTALL_PREFIX}/share/icons")
set(LOCALEDIR "${CMAKE_INSTALL_PREFIX}/share/${PROJECT_NAME}/locale") set(LOCALEDIR "${CMAKE_INSTALL_PREFIX}/share/${PROJECT_NAME}/locale")
endif() endif()
@ -152,6 +156,7 @@ endif()
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/builtin" DESTINATION "${SHAREDIR}") install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/builtin" DESTINATION "${SHAREDIR}")
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/client" DESTINATION "${SHAREDIR}") install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/client" DESTINATION "${SHAREDIR}")
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/clientmods" DESTINATION "${SHAREDIR}")
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/games" DESTINATION "${SHAREDIR}" PATTERN ".git*" EXCLUDE) install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/games" DESTINATION "${SHAREDIR}" PATTERN ".git*" EXCLUDE)
if(BUILD_CLIENT) if(BUILD_CLIENT)
@ -173,8 +178,8 @@ install(FILES "minetest.conf.example" DESTINATION "${EXAMPLE_CONF_DIR}")
if(UNIX AND NOT APPLE) if(UNIX AND NOT APPLE)
install(FILES "doc/minetest.6" "doc/minetestserver.6" DESTINATION "${MANDIR}/man6") install(FILES "doc/minetest.6" "doc/minetestserver.6" DESTINATION "${MANDIR}/man6")
install(FILES "misc/minetest.desktop" DESTINATION "${XDG_APPS_DIR}") install(FILES "misc/net.minetest.minetest.desktop" DESTINATION "${XDG_APPS_DIR}")
install(FILES "misc/minetest.appdata.xml" DESTINATION "${APPDATADIR}") install(FILES "misc/net.minetest.minetest.appdata.xml" DESTINATION "${APPDATADIR}")
install(FILES "misc/minetest.svg" DESTINATION "${ICONDIR}/hicolor/scalable/apps") install(FILES "misc/minetest.svg" DESTINATION "${ICONDIR}/hicolor/scalable/apps")
install(FILES "misc/minetest-xorg-icon-128.png" install(FILES "misc/minetest-xorg-icon-128.png"
DESTINATION "${ICONDIR}/hicolor/128x128/apps" DESTINATION "${ICONDIR}/hicolor/128x128/apps"
@ -186,6 +191,10 @@ if(APPLE)
install(FILES "misc/Info.plist" DESTINATION "${BUNDLE_PATH}/Contents") install(FILES "misc/Info.plist" DESTINATION "${BUNDLE_PATH}/Contents")
endif() endif()
# Library pack
find_package(GMP REQUIRED)
find_package(Json REQUIRED)
find_package(Lua REQUIRED)
# Subdirectories # Subdirectories
# Be sure to add all relevant definitions above this # Be sure to add all relevant definitions above this

@ -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)

@ -3,7 +3,7 @@ Minetest
An InfiniMiner/Minecraft inspired game. An InfiniMiner/Minecraft inspired game.
Copyright (c) 2010-2013 Perttu Ahola <celeron55@gmail.com> Copyright (c) 2010-2017 Perttu Ahola <celeron55@gmail.com>
and contributors (see source file comments and the version control log) and contributors (see source file comments and the version control log)
In case you downloaded the source code: In case you downloaded the source code:
@ -43,7 +43,7 @@ Default controls
- 0-9: Select item - 0-9: Select item
- Z: Zoom (needs zoom privilege) - Z: Zoom (needs zoom privilege)
- T: Chat - T: Chat
- /: Commad - /: Command
- Esc: Pause menu/abort/exit (pauses only singleplayer game) - Esc: Pause menu/abort/exit (pauses only singleplayer game)
- R: Enable/disable full range view - R: Enable/disable full range view
@ -85,7 +85,7 @@ $bin = /usr/bin
$share = /usr/share/minetest $share = /usr/share/minetest
$user = ~/.minetest $user = ~/.minetest
OS X: macOS:
$bin = Contents/MacOS $bin = Contents/MacOS
$share = Contents/Resources $share = Contents/Resources
$user = Contents/User OR ~/Library/Application Support/minetest $user = Contents/User OR ~/Library/Application Support/minetest
@ -102,6 +102,8 @@ Configuration file:
- It is created by Minetest when it is ran the first time. - It is created by Minetest when it is ran the first time.
- A specific file can be specified on the command line: - A specific file can be specified on the command line:
--config <path-to-file> --config <path-to-file>
- A run-in-place build will look for the configuration file in
$location_of_exe/../minetest.conf and also $location_of_exe/../../minetest.conf
Command-line options: Command-line options:
--------------------- ---------------------
@ -117,7 +119,7 @@ For Fedora users:
$ sudo dnf install make automake gcc gcc-c++ kernel-devel cmake libcurl* openal* libvorbis* libXxf86vm-devel libogg-devel freetype-devel mesa-libGL-devel zlib-devel jsoncpp-devel irrlicht-devel bzip2-libs gmp-devel sqlite-devel luajit-devel leveldb-devel ncurses-devel doxygen spatialindex-devel bzip2-devel $ sudo dnf install make automake gcc gcc-c++ kernel-devel cmake libcurl* openal* libvorbis* libXxf86vm-devel libogg-devel freetype-devel mesa-libGL-devel zlib-devel jsoncpp-devel irrlicht-devel bzip2-libs gmp-devel sqlite-devel luajit-devel leveldb-devel ncurses-devel doxygen spatialindex-devel bzip2-devel
You can install git for easily keeping your copy up to date. You can install git for easily keeping your copy up to date.
If you dont want git, read below on how to get the source without git. If you dont want git, read below on how to get the source without git.
This is an example for installing git on Debian/Ubuntu: This is an example for installing git on Debian/Ubuntu:
$ sudo apt-get install git $ sudo apt-get install git
@ -178,7 +180,7 @@ ENABLE_FREETYPE - Build with FreeType2; Allows using TTF fonts
ENABLE_GETTEXT - Build with Gettext; Allows using translations ENABLE_GETTEXT - Build with Gettext; Allows using translations
ENABLE_GLES - Search for Open GLES headers & libraries and use them ENABLE_GLES - Search for Open GLES headers & libraries and use them
ENABLE_LEVELDB - Build with LevelDB; Enables use of LevelDB map backend ENABLE_LEVELDB - Build with LevelDB; Enables use of LevelDB map backend
ENABLE_POSTGRESQL - Build with libpq; Enables use of PostgreSQL map backend (PostgreSQL 9.5 or greater required) ENABLE_POSTGRESQL - Build with libpq; Enables use of PostgreSQL map backend (PostgreSQL 9.5 or greater recommended)
ENABLE_REDIS - Build with libhiredis; Enables use of Redis map backend ENABLE_REDIS - Build with libhiredis; Enables use of Redis map backend
ENABLE_SPATIAL - Build with LibSpatial; Speeds up AreaStores ENABLE_SPATIAL - Build with LibSpatial; Speeds up AreaStores
ENABLE_SOUND - Build with OpenAL, libogg & libvorbis; in-game Sounds ENABLE_SOUND - Build with OpenAL, libogg & libvorbis; in-game Sounds
@ -212,7 +214,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
@ -427,7 +429,7 @@ License of Minetest source code
------------------------------- -------------------------------
Minetest Minetest
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com> Copyright (C) 2010-2017 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU Lesser General Public License as published by
@ -502,7 +504,7 @@ Lua is licensed under the terms of the MIT license reproduced below.
This means that Lua is free software and can be used for both academic This means that Lua is free software and can be used for both academic
and commercial purposes at absolutely no cost. and commercial purposes at absolutely no cost.
For details and rationale, see http://www.lua.org/license.html . For details and rationale, see https://www.lua.org/license.html .
Copyright (C) 1994-2008 Lua.org, PUC-Rio. Copyright (C) 1994-2008 Lua.org, PUC-Rio.
@ -527,25 +529,18 @@ THE SOFTWARE.
Fonts Fonts
--------------- ---------------
DejaVu Sans Mono:
Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below)
Bitstream Vera Fonts Copyright: Bitstream Vera Fonts Copyright:
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
a trademark of Bitstream, Inc. a trademark of Bitstream, Inc.
Arev Fonts Copyright: Arimo - Apache License, version 2.0
Digitized data copyright (c) 2010-2012 Google Corporation.
Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved. Cousine - Apache License, version 2.0
Digitized data copyright (c) 2010-2012 Google Corporation.
Liberation Fonts Copyright: DroidSansFallBackFull:
Copyright (c) 2007 Red Hat, Inc. All rights reserved. LIBERATION is a trademark of Red Hat, Inc.
DroidSansFallback:
Copyright (C) 2008 The Android Open Source Project Copyright (C) 2008 The Android Open Source Project

@ -35,7 +35,7 @@ TARGET_CXXFLAGS_ADDON = $(TARGET_CFLAGS_ADDON)
TARGET_ARCH = armv7 TARGET_ARCH = armv7
CROSS_PREFIX = arm-linux-androideabi- CROSS_PREFIX = arm-linux-androideabi-
COMPILER_VERSION = 4.9 COMPILER_VERSION = 4.9
HAVE_LEVELDB = 1 HAVE_LEVELDB = 0
################################################################################ ################################################################################
# toolchain config for little endian mips # toolchain config for little endian mips
@ -59,7 +59,7 @@ HAVE_LEVELDB = 1
#CROSS_PREFIX = i686-linux-android- #CROSS_PREFIX = i686-linux-android-
#TARGET_ARCH = x86 #TARGET_ARCH = x86
#COMPILER_VERSION = 4.9 #COMPILER_VERSION = 4.9
#HAVE_LEVELDB = 1 #HAVE_LEVELDB = 0
################################################################################ ################################################################################
ASSETS_TIMESTAMP = deps/assets_timestamp ASSETS_TIMESTAMP = deps/assets_timestamp
@ -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:]]*//')
@ -352,7 +352,7 @@ leveldb_download :
fi fi
leveldb : $(LEVELDB_LIB) leveldb : $(LEVELDB_LIB)
ifeq ($(HAVE_LEVELDB),1)
$(LEVELDB_LIB): $(LEVELDB_TIMESTAMP) $(LEVELDB_LIB): $(LEVELDB_TIMESTAMP)
@REFRESH=0; \ @REFRESH=0; \
if [ ! -e ${LEVELDB_TIMESTAMP_INT} ] ; then \ if [ ! -e ${LEVELDB_TIMESTAMP_INT} ] ; then \
@ -384,6 +384,7 @@ $(LEVELDB_LIB): $(LEVELDB_TIMESTAMP)
else \ else \
echo "nothing to be done for leveldb"; \ echo "nothing to be done for leveldb"; \
fi fi
endif
clean_leveldb : clean_leveldb :
$(RM) -rf deps/leveldb $(RM) -rf deps/leveldb
@ -679,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 && \
@ -781,7 +781,7 @@ apk: local.properties assets $(ICONV_LIB) $(IRRLICHT_LIB) $(CURL_LIB) $(GMP_LIB)
fi; \ fi; \
export VERSION_STR="${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}" && \ export VERSION_STR="${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}" && \
export BUILD_TYPE_C=$$(echo "$${BUILD_TYPE}" | sed 's/./\U&/') && \ export BUILD_TYPE_C=$$(echo "$${BUILD_TYPE}" | sed 's/./\U&/') && \
gradle assemble$$BUILD_TYPE_C && \ ./gradlew assemble$$BUILD_TYPE_C && \
echo "APK stored at: build/outputs/apk/Minetest-$$BUILD_TYPE.apk" && \ echo "APK stored at: build/outputs/apk/Minetest-$$BUILD_TYPE.apk" && \
echo "You can install it with \`make install_$$BUILD_TYPE\`" echo "You can install it with \`make install_$$BUILD_TYPE\`"
@ -796,10 +796,13 @@ install_release:
prep_srcdir : prep_srcdir :
@if [ ! -e ${ANDR_ROOT}/jni/src ]; then \ @if [ ! -e ${ANDR_ROOT}/jni/src ]; then \
ln -s ${PROJ_ROOT}/src ${ANDR_ROOT}/jni/src; \ ln -s ${PROJ_ROOT}/src ${ANDR_ROOT}/jni/src; \
fi; \
if [ ! -e ${ANDR_ROOT}/jni/lib ]; then \
ln -s ${PROJ_ROOT}/lib ${ANDR_ROOT}/jni/lib; \
fi fi
clean_apk : clean_apk :
gradle clean ./gradlew clean
clean_all : clean_all :
@$(MAKE) clean_apk; \ @$(MAKE) clean_apk; \

@ -10,11 +10,11 @@ buildscript {
apply plugin: "com.android.application" apply plugin: "com.android.application"
android { android {
compileSdkVersion 23 compileSdkVersion 25
buildToolsVersion "23.0.3" buildToolsVersion "25.0.3"
defaultConfig { defaultConfig {
versionCode 16 versionCode 17
versionName "${System.env.VERSION_STR}.${versionCode}" versionName "${System.env.VERSION_STR}.${versionCode}"
minSdkVersion 9 minSdkVersion 9
targetSdkVersion 9 targetSdkVersion 9
@ -46,4 +46,3 @@ android {
} }
} }
} }

Binary file not shown.

@ -0,0 +1,6 @@
#Sat Aug 27 20:10:09 CEST 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip

164
build/android/gradlew vendored Executable file

@ -0,0 +1,164 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

90
build/android/gradlew.bat vendored Normal file

@ -0,0 +1,90 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

@ -98,8 +98,8 @@ endif
LOCAL_C_INCLUDES := \ LOCAL_C_INCLUDES := \
jni/src \ jni/src \
jni/src/script \ jni/src/script \
jni/src/lua/src \ jni/lib/lua/src \
jni/src/jsoncpp \ jni/lib/jsoncpp \
jni/src/cguittfont \ jni/src/cguittfont \
deps/irrlicht/include \ deps/irrlicht/include \
deps/libiconv/include \ deps/libiconv/include \
@ -117,6 +117,7 @@ LOCAL_SRC_FILES := \
jni/src/cavegen.cpp \ jni/src/cavegen.cpp \
jni/src/chat.cpp \ jni/src/chat.cpp \
jni/src/client.cpp \ jni/src/client.cpp \
jni/src/clientenvironment.cpp \
jni/src/clientiface.cpp \ jni/src/clientiface.cpp \
jni/src/clientmap.cpp \ jni/src/clientmap.cpp \
jni/src/clientmedia.cpp \ jni/src/clientmedia.cpp \
@ -133,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 \
@ -141,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 \
@ -163,6 +166,7 @@ LOCAL_SRC_FILES := \
jni/src/inventory.cpp \ jni/src/inventory.cpp \
jni/src/inventorymanager.cpp \ jni/src/inventorymanager.cpp \
jni/src/itemdef.cpp \ jni/src/itemdef.cpp \
jni/src/itemstackmetadata.cpp \
jni/src/keycode.cpp \ jni/src/keycode.cpp \
jni/src/light.cpp \ jni/src/light.cpp \
jni/src/localplayer.cpp \ jni/src/localplayer.cpp \
@ -183,6 +187,8 @@ LOCAL_SRC_FILES := \
jni/src/mapnode.cpp \ jni/src/mapnode.cpp \
jni/src/mapsector.cpp \ jni/src/mapsector.cpp \
jni/src/mesh.cpp \ jni/src/mesh.cpp \
jni/src/mesh_generator_thread.cpp \
jni/src/metadata.cpp \
jni/src/mg_biome.cpp \ jni/src/mg_biome.cpp \
jni/src/mg_decoration.cpp \ jni/src/mg_decoration.cpp \
jni/src/mg_ore.cpp \ jni/src/mg_ore.cpp \
@ -203,12 +209,14 @@ LOCAL_SRC_FILES := \
jni/src/porting.cpp \ jni/src/porting.cpp \
jni/src/profiler.cpp \ jni/src/profiler.cpp \
jni/src/quicktune.cpp \ jni/src/quicktune.cpp \
jni/src/raycast.cpp \
jni/src/reflowscan.cpp \ jni/src/reflowscan.cpp \
jni/src/remoteplayer.cpp \ jni/src/remoteplayer.cpp \
jni/src/rollback.cpp \ jni/src/rollback.cpp \
jni/src/rollback_interface.cpp \ jni/src/rollback_interface.cpp \
jni/src/serialization.cpp \ jni/src/serialization.cpp \
jni/src/server.cpp \ jni/src/server.cpp \
jni/src/serverenvironment.cpp \
jni/src/serverlist.cpp \ jni/src/serverlist.cpp \
jni/src/serverobject.cpp \ jni/src/serverobject.cpp \
jni/src/shader.cpp \ jni/src/shader.cpp \
@ -218,6 +226,7 @@ LOCAL_SRC_FILES := \
jni/src/sound_openal.cpp \ jni/src/sound_openal.cpp \
jni/src/staticobject.cpp \ jni/src/staticobject.cpp \
jni/src/subgame.cpp \ jni/src/subgame.cpp \
jni/src/tileanimation.cpp \
jni/src/tool.cpp \ jni/src/tool.cpp \
jni/src/treegen.cpp \ jni/src/treegen.cpp \
jni/src/version.cpp \ jni/src/version.cpp \
@ -261,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
@ -284,6 +294,7 @@ LOCAL_SRC_FILES += \
jni/src/script/common/c_types.cpp \ jni/src/script/common/c_types.cpp \
jni/src/script/cpp_api/s_async.cpp \ jni/src/script/cpp_api/s_async.cpp \
jni/src/script/cpp_api/s_base.cpp \ jni/src/script/cpp_api/s_base.cpp \
jni/src/script/cpp_api/s_client.cpp \
jni/src/script/cpp_api/s_entity.cpp \ jni/src/script/cpp_api/s_entity.cpp \
jni/src/script/cpp_api/s_env.cpp \ jni/src/script/cpp_api/s_env.cpp \
jni/src/script/cpp_api/s_inventory.cpp \ jni/src/script/cpp_api/s_inventory.cpp \
@ -296,12 +307,18 @@ 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_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 \
jni/src/script/lua_api/l_inventory.cpp \ jni/src/script/lua_api/l_inventory.cpp \
jni/src/script/lua_api/l_item.cpp \ jni/src/script/lua_api/l_item.cpp \
jni/src/script/lua_api/l_itemstackmeta.cpp\
jni/src/script/lua_api/l_localplayer.cpp \
jni/src/script/lua_api/l_mainmenu.cpp \ jni/src/script/lua_api/l_mainmenu.cpp \
jni/src/script/lua_api/l_mapgen.cpp \ jni/src/script/lua_api/l_mapgen.cpp \
jni/src/script/lua_api/l_metadata.cpp \
jni/src/script/lua_api/l_minimap.cpp \
jni/src/script/lua_api/l_nodemeta.cpp \ jni/src/script/lua_api/l_nodemeta.cpp \
jni/src/script/lua_api/l_nodetimer.cpp \ jni/src/script/lua_api/l_nodetimer.cpp \
jni/src/script/lua_api/l_noise.cpp \ jni/src/script/lua_api/l_noise.cpp \
@ -310,10 +327,13 @@ LOCAL_SRC_FILES += \
jni/src/script/lua_api/l_rollback.cpp \ jni/src/script/lua_api/l_rollback.cpp \
jni/src/script/lua_api/l_server.cpp \ jni/src/script/lua_api/l_server.cpp \
jni/src/script/lua_api/l_settings.cpp \ jni/src/script/lua_api/l_settings.cpp \
jni/src/script/lua_api/l_sound.cpp \
jni/src/script/lua_api/l_http.cpp \ jni/src/script/lua_api/l_http.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/scripting_game.cpp \ jni/src/script/scripting_client.cpp \
jni/src/script/scripting_server.cpp \
jni/src/script/scripting_mainmenu.cpp jni/src/script/scripting_mainmenu.cpp
#freetype2 support #freetype2 support
@ -321,36 +341,36 @@ LOCAL_SRC_FILES += jni/src/cguittfont/xCGUITTFont.cpp
# Lua # Lua
LOCAL_SRC_FILES += \ LOCAL_SRC_FILES += \
jni/src/lua/src/lapi.c \ jni/lib/lua/src/lapi.c \
jni/src/lua/src/lauxlib.c \ jni/lib/lua/src/lauxlib.c \
jni/src/lua/src/lbaselib.c \ jni/lib/lua/src/lbaselib.c \
jni/src/lua/src/lcode.c \ jni/lib/lua/src/lcode.c \
jni/src/lua/src/ldblib.c \ jni/lib/lua/src/ldblib.c \
jni/src/lua/src/ldebug.c \ jni/lib/lua/src/ldebug.c \
jni/src/lua/src/ldo.c \ jni/lib/lua/src/ldo.c \
jni/src/lua/src/ldump.c \ jni/lib/lua/src/ldump.c \
jni/src/lua/src/lfunc.c \ jni/lib/lua/src/lfunc.c \
jni/src/lua/src/lgc.c \ jni/lib/lua/src/lgc.c \
jni/src/lua/src/linit.c \ jni/lib/lua/src/linit.c \
jni/src/lua/src/liolib.c \ jni/lib/lua/src/liolib.c \
jni/src/lua/src/llex.c \ jni/lib/lua/src/llex.c \
jni/src/lua/src/lmathlib.c \ jni/lib/lua/src/lmathlib.c \
jni/src/lua/src/lmem.c \ jni/lib/lua/src/lmem.c \
jni/src/lua/src/loadlib.c \ jni/lib/lua/src/loadlib.c \
jni/src/lua/src/lobject.c \ jni/lib/lua/src/lobject.c \
jni/src/lua/src/lopcodes.c \ jni/lib/lua/src/lopcodes.c \
jni/src/lua/src/loslib.c \ jni/lib/lua/src/loslib.c \
jni/src/lua/src/lparser.c \ jni/lib/lua/src/lparser.c \
jni/src/lua/src/lstate.c \ jni/lib/lua/src/lstate.c \
jni/src/lua/src/lstring.c \ jni/lib/lua/src/lstring.c \
jni/src/lua/src/lstrlib.c \ jni/lib/lua/src/lstrlib.c \
jni/src/lua/src/ltable.c \ jni/lib/lua/src/ltable.c \
jni/src/lua/src/ltablib.c \ jni/lib/lua/src/ltablib.c \
jni/src/lua/src/ltm.c \ jni/lib/lua/src/ltm.c \
jni/src/lua/src/lundump.c \ jni/lib/lua/src/lundump.c \
jni/src/lua/src/lvm.c \ jni/lib/lua/src/lvm.c \
jni/src/lua/src/lzio.c \ jni/lib/lua/src/lzio.c \
jni/src/lua/src/print.c jni/lib/lua/src/print.c
# SQLite3 # SQLite3
LOCAL_SRC_FILES += deps/sqlite/sqlite3.c LOCAL_SRC_FILES += deps/sqlite/sqlite3.c
@ -363,7 +383,7 @@ LOCAL_SRC_FILES += \
jni/src/threading/thread.cpp jni/src/threading/thread.cpp
# JSONCPP # JSONCPP
LOCAL_SRC_FILES += jni/src/jsoncpp/json/jsoncpp.cpp LOCAL_SRC_FILES += jni/lib/jsoncpp/jsoncpp.cpp
LOCAL_SHARED_LIBRARIES := iconv openal ogg vorbis gmp LOCAL_SHARED_LIBRARIES := iconv openal ogg vorbis gmp
LOCAL_STATIC_LIBRARIES := Irrlicht freetype curl ssl crypto android_native_app_glue $(PROFILER_LIBS) LOCAL_STATIC_LIBRARIES := Irrlicht freetype curl ssl crypto android_native_app_glue $(PROFILER_LIBS)
@ -380,4 +400,3 @@ ifdef GPROF
$(call import-module,android-ndk-profiler) $(call import-module,android-ndk-profiler)
endif endif
$(call import-module,android/native_app_glue) $(call import-module,android/native_app_glue)

@ -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
};

@ -0,0 +1,65 @@
-- Minetest: builtin/client/chatcommands.lua
core.register_on_sending_chat_messages(function(message)
if message:sub(1,2) == ".." then
return false
end
local first_char = message:sub(1,1)
if first_char == "/" or first_char == "." then
core.display_chat_message(core.gettext("issued command: ") .. message)
end
if first_char ~= "." then
return false
end
local cmd, param = string.match(message, "^%.([^ ]+) *(.*)")
param = param or ""
if not cmd then
core.display_chat_message(core.gettext("-!- Empty command"))
return true
end
local cmd_def = core.registered_chatcommands[cmd]
if cmd_def then
core.set_last_run_mod(cmd_def.mod_origin)
local _, message = cmd_def.func(param)
if message then
core.display_chat_message(message)
end
else
core.display_chat_message(core.gettext("-!- Invalid command: ") .. cmd)
end
return true
end)
core.register_chatcommand("list_players", {
description = core.gettext("List online players"),
func = function(param)
local players = table.concat(core.get_player_names(), ", ")
core.display_chat_message(core.gettext("Online players: ") .. players)
end
})
core.register_chatcommand("disconnect", {
description = core.gettext("Exit to main menu"),
func = function(param)
core.disconnect()
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

23
builtin/client/init.lua Normal file

@ -0,0 +1,23 @@
-- Minetest: builtin/client/init.lua
local scriptpath = core.get_builtin_path()..DIR_DELIM
local clientpath = scriptpath.."client"..DIR_DELIM
local commonpath = scriptpath.."common"..DIR_DELIM
dofile(clientpath .. "register.lua")
dofile(commonpath .. "after.lua")
dofile(commonpath .. "chatcommands.lua")
dofile(clientpath .. "chatcommands.lua")
dofile(commonpath .. "vector.lua")
core.register_on_death(function()
core.display_chat_message("You died.")
local formspec = "size[11,5.5]bgcolor[#320000b4;true]" ..
"label[4.85,1.35;" .. fgettext("You died.") .. "]button_exit[4,3;3,0.5;btn_respawn;".. fgettext("Respawn") .."]"
core.show_formspec("bultin:death", formspec)
end)
core.register_on_formspec_input(function(formname, fields)
if formname == "bultin:death" then
core.send_respawn()
end
end)

@ -0,0 +1,73 @@
core.callback_origins = {}
local getinfo = debug.getinfo
debug.getinfo = nil
function core.run_callbacks(callbacks, mode, ...)
assert(type(callbacks) == "table")
local cb_len = #callbacks
if cb_len == 0 then
if mode == 2 or mode == 3 then
return true
elseif mode == 4 or mode == 5 then
return false
end
end
local ret
for i = 1, cb_len do
local cb_ret = callbacks[i](...)
if mode == 0 and i == 1 or mode == 1 and i == cb_len then
ret = cb_ret
elseif mode == 2 then
if not cb_ret or i == 1 then
ret = cb_ret
end
elseif mode == 3 then
if cb_ret then
return cb_ret
end
ret = cb_ret
elseif mode == 4 then
if (cb_ret and not ret) or i == 1 then
ret = cb_ret
end
elseif mode == 5 and cb_ret then
return cb_ret
end
end
return ret
end
--
-- Callback registration
--
local function make_registration()
local t = {}
local registerfunc = function(func)
t[#t + 1] = func
core.callback_origins[func] = {
mod = core.get_current_modname() or "??",
name = getinfo(1, "n").name or "??"
}
--local origin = core.callback_origins[func]
--print(origin.name .. ": " .. origin.mod .. " registering cbk " .. tostring(func))
end
return t, registerfunc
end
core.registered_globalsteps, core.register_globalstep = make_registration()
core.registered_on_shutdown, core.register_on_shutdown = make_registration()
core.registered_on_connect, core.register_on_connect = make_registration()
core.registered_on_receiving_chat_messages, core.register_on_receiving_chat_messages = make_registration()
core.registered_on_sending_chat_messages, core.register_on_sending_chat_messages = make_registration()
core.registered_on_death, core.register_on_death = make_registration()
core.registered_on_hp_modification, core.register_on_hp_modification = make_registration()
core.registered_on_damage_taken, core.register_on_damage_taken = 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_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()

33
builtin/common/after.lua Normal file

@ -0,0 +1,33 @@
local jobs = {}
local time = 0.0
core.register_globalstep(function(dtime)
time = time + dtime
if #jobs < 1 then
return
end
-- Iterate backwards so that we miss any new timers added by
-- a timer callback, and so that we don't skip the next timer
-- in the list if we remove one.
for i = #jobs, 1, -1 do
local job = jobs[i]
if time >= job.expire then
core.set_last_run_mod(job.mod_origin)
job.func(unpack(job.arg))
table.remove(jobs, i)
end
end
end)
function core.after(after, func, ...)
assert(tonumber(after) and type(func) == "function",
"Invalid core.after invocation")
jobs[#jobs + 1] = {
func = func,
expire = time + after,
arg = {...},
mod_origin = core.get_last_run_mod()
}
end

@ -0,0 +1,112 @@
-- Minetest: builtin/common/chatcommands.lua
core.registered_chatcommands = {}
function core.register_chatcommand(cmd, def)
def = def or {}
def.params = def.params or ""
def.description = def.description or ""
def.privs = def.privs or {}
def.mod_origin = core.get_current_modname() or "??"
core.registered_chatcommands[cmd] = def
end
function core.unregister_chatcommand(name)
if core.registered_chatcommands[name] then
core.registered_chatcommands[name] = nil
else
core.log("warning", "Not unregistering chatcommand " ..name..
" because it doesn't exist.")
end
end
function core.override_chatcommand(name, redefinition)
local chatcommand = core.registered_chatcommands[name]
assert(chatcommand, "Attempt to override non-existent chatcommand "..name)
for k, v in pairs(redefinition) do
rawset(chatcommand, k, v)
end
core.registered_chatcommands[name] = chatcommand
end
local cmd_marker = "/"
local function gettext(...)
return ...
end
local function gettext_replace(text, replace)
return text:gsub("$1", replace)
end
if INIT == "client" then
cmd_marker = "."
gettext = core.gettext
gettext_replace = fgettext_ne
end
local function do_help_cmd(name, param)
local function format_help_line(cmd, def)
local msg = core.colorize("#00ffff", cmd_marker .. cmd)
if def.params and def.params ~= "" then
msg = msg .. " " .. def.params
end
if def.description and def.description ~= "" then
msg = msg .. ": " .. def.description
end
return msg
end
if param == "" then
local cmds = {}
for cmd, def in pairs(core.registered_chatcommands) do
if INIT == "client" or core.check_player_privs(name, def.privs) then
cmds[#cmds + 1] = cmd
end
end
table.sort(cmds)
return true, gettext("Available commands: ") .. table.concat(cmds, " ") .. "\n"
.. gettext_replace("Use '$1help <cmd>' to get more information,"
.. " or '$1help all' to list everything.", cmd_marker)
elseif param == "all" then
local cmds = {}
for cmd, def in pairs(core.registered_chatcommands) do
if INIT == "client" or core.check_player_privs(name, def.privs) then
cmds[#cmds + 1] = format_help_line(cmd, def)
end
end
table.sort(cmds)
return true, gettext("Available commands:").."\n"..table.concat(cmds, "\n")
elseif INIT == "game" and param == "privs" then
local privs = {}
for priv, def in pairs(core.registered_privileges) do
privs[#privs + 1] = priv .. ": " .. def.description
end
table.sort(privs)
return true, "Available privileges:\n"..table.concat(privs, "\n")
else
local cmd = param
local def = core.registered_chatcommands[cmd]
if not def then
return false, gettext("Command not available: ")..cmd
else
return true, format_help_line(cmd, def)
end
end
end
if INIT == "client" then
core.register_chatcommand("help", {
params = gettext("[all/<cmd>]"),
description = gettext("Get help for commands"),
func = function(param)
return do_help_cmd(nil, param)
end,
})
else
core.register_chatcommand("help", {
params = "[all/privs/<cmd>]",
description = "Get help for commands or list privileges",
func = do_help_cmd,
})
end

@ -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

@ -197,6 +197,7 @@ assert(table.indexof({"foo", "bar"}, "foo") == 1)
assert(table.indexof({"foo", "bar"}, "baz") == -1) assert(table.indexof({"foo", "bar"}, "baz") == -1)
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
if INIT ~= "client" then
function file_exists(filename) function file_exists(filename)
local f = io.open(filename, "r") local f = io.open(filename, "r")
if f == nil then if f == nil then
@ -206,7 +207,7 @@ function file_exists(filename)
return true return true
end end
end end
end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function string:trim() function string:trim()
return (self:gsub("^%s*(.-)%s*$", "%1")) return (self:gsub("^%s*(.-)%s*$", "%1"))
@ -307,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
@ -462,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
@ -606,7 +607,9 @@ if INIT == "mainmenu" then
return nil return nil
end end
end
if INIT == "client" or INIT == "mainmenu" then
function fgettext_ne(text, ...) function fgettext_ne(text, ...)
text = core.gettext(text) text = core.gettext(text)
local arg = {n=select('#', ...), ...} local arg = {n=select('#', ...), ...}
@ -637,3 +640,86 @@ if INIT == "mainmenu" then
end end
end end
local ESCAPE_CHAR = string.char(0x1b)
-- Client-side mods don't have access to settings
if core.settings and core.settings:get_bool("disable_escape_sequences") then
function core.get_color_escape_sequence(color)
return ""
end
function core.get_background_escape_sequence(color)
return ""
end
function core.colorize(color, message)
return message
end
else
function core.get_color_escape_sequence(color)
return ESCAPE_CHAR .. "(c@" .. color .. ")"
end
function core.get_background_escape_sequence(color)
return ESCAPE_CHAR .. "(b@" .. color .. ")"
end
function core.colorize(color, message)
local lines = tostring(message):split("\n", true)
local color_code = core.get_color_escape_sequence(color)
for i, line in ipairs(lines) do
lines[i] = color_code .. line
end
return table.concat(lines, "\n") .. core.get_color_escape_sequence("#ffffff")
end
end
function core.strip_foreground_colors(str)
return (str:gsub(ESCAPE_CHAR .. "%(c@[^)]+%)", ""))
end
function core.strip_background_colors(str)
return (str:gsub(ESCAPE_CHAR .. "%(b@[^)]+%)", ""))
end
function core.strip_colors(str)
return (str:gsub(ESCAPE_CHAR .. "%([bc]@[^)]+%)", ""))
end
--------------------------------------------------------------------------------
-- Returns the exact coordinate of a pointed surface
--------------------------------------------------------------------------------
function core.pointed_thing_to_face_pos(placer, pointed_thing)
local eye_offset_first = placer:get_eye_offset()
local node_pos = pointed_thing.under
local camera_pos = placer:get_pos()
local pos_off = vector.multiply(
vector.subtract(pointed_thing.above, node_pos), 0.5)
local look_dir = placer:get_look_dir()
local offset, nc
local oc = {}
for c, v in pairs(pos_off) do
if nc or v == 0 then
oc[#oc + 1] = c
else
offset = v
nc = c
end
end
local fine_pos = {[nc] = node_pos[nc] + offset}
camera_pos.y = camera_pos.y + 1.625 + eye_offset_first.y / 10
local f = (node_pos[nc] + offset - camera_pos[nc]) / look_dir[nc]
for i = 1, #oc do
fine_pos[oc[i]] = camera_pos[oc[i]] + look_dir[oc[i]] * f
end
return fine_pos
end

@ -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

@ -3,6 +3,7 @@
-- This ignores mod namespaces (variables with the same name as the current mod). -- This ignores mod namespaces (variables with the same name as the current mod).
local WARN_INIT = false local WARN_INIT = false
local getinfo = debug.getinfo
function core.global_exists(name) function core.global_exists(name)
if type(name) ~= "string" then if type(name) ~= "string" then
@ -18,7 +19,7 @@ local declared = {}
local warned = {} local warned = {}
function meta:__newindex(name, value) function meta:__newindex(name, value)
local info = debug.getinfo(2, "Sl") local info = getinfo(2, "Sl")
local desc = ("%s:%d"):format(info.short_src, info.currentline) local desc = ("%s:%d"):format(info.short_src, info.currentline)
if not declared[name] then if not declared[name] then
local warn_key = ("%s\0%d\0%s"):format(info.source, local warn_key = ("%s\0%d\0%s"):format(info.source,
@ -42,7 +43,7 @@ end
function meta:__index(name) function meta:__index(name)
local info = debug.getinfo(2, "Sl") local info = getinfo(2, "Sl")
local warn_key = ("%s\0%d\0%s"):format(info.source, info.currentline, name) local warn_key = ("%s\0%d\0%s"):format(info.source, info.currentline, name)
if not declared[name] and not warned[warn_key] and info.what ~= "C" then if not declared[name] and not warned[warn_key] and info.what ~= "C" then
core.log("warning", ("Undeclared global variable %q accessed at %s:%s") core.log("warning", ("Undeclared global variable %q accessed at %s:%s")

@ -138,3 +138,8 @@ function vector.divide(a, b)
z = a.z / b} z = a.z / b}
end end
end end
function vector.sort(a, b)
return {x = math.min(a.x, b.x), y = math.min(a.y, b.y), z = math.min(a.z, b.z)},
{x = math.max(a.x, b.x), y = math.max(a.y, b.y), z = math.max(a.z, b.z)}
end

@ -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

@ -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)

@ -1,27 +1,28 @@
-- Minetest: builtin/chatcommands.lua -- Minetest: builtin/game/chatcommands.lua
-- --
-- Chat command handler -- Chat command handler
-- --
core.chatcommands = {} core.chatcommands = core.registered_chatcommands -- BACKWARDS COMPATIBILITY
function core.register_chatcommand(cmd, def)
def = def or {}
def.params = def.params or ""
def.description = def.description or ""
def.privs = def.privs or {}
def.mod_origin = core.get_current_modname() or "??"
core.chatcommands[cmd] = def
end
core.register_on_chat_message(function(name, message) core.register_on_chat_message(function(name, message)
local cmd, param = string.match(message, "^/([^ ]+) *(.*)") if message:sub(1,1) ~= "/" then
if not param then return
param = ""
end end
local cmd_def = core.chatcommands[cmd]
local cmd, param = string.match(message, "^/([^ ]+) *(.*)")
if not cmd then
core.chat_send_player(name, "-!- Empty command")
return true
end
param = param or ""
local cmd_def = core.registered_chatcommands[cmd]
if not cmd_def then if not cmd_def then
return false core.chat_send_player(name, "-!- Invalid command: " .. cmd)
return true
end end
local has_privs, missing_privs = core.check_player_privs(name, cmd_def.privs) local has_privs, missing_privs = core.check_player_privs(name, cmd_def.privs)
if has_privs then if has_privs then
@ -38,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()
@ -70,7 +71,8 @@ end
-- --
core.register_chatcommand("me", { core.register_chatcommand("me", {
params = "<action>", params = "<action>",
description = "chat action (eg. /me orders a pizza)", description = "Display chat action (e.g., '/me orders a pizza' displays"
.. " '<player name> orders a pizza')",
privs = {shout=true}, privs = {shout=true},
func = function(name, param) func = function(name, param)
core.chat_send_all("* " .. name .. " " .. param) core.chat_send_all("* " .. name .. " " .. param)
@ -80,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
@ -89,64 +91,9 @@ core.register_chatcommand("admin", {
end, end,
}) })
core.register_chatcommand("help", {
privs = {},
params = "[all/privs/<cmd>]",
description = "Get help for commands or list privileges",
func = function(name, param)
local function format_help_line(cmd, def)
local msg = core.colorize("#00ffff", "/"..cmd)
if def.params and def.params ~= "" then
msg = msg .. " " .. def.params
end
if def.description and def.description ~= "" then
msg = msg .. ": " .. def.description
end
return msg
end
if param == "" then
local msg = ""
local cmds = {}
for cmd, def in pairs(core.chatcommands) do
if core.check_player_privs(name, def.privs) then
cmds[#cmds + 1] = cmd
end
end
table.sort(cmds)
return true, "Available commands: " .. table.concat(cmds, " ") .. "\n"
.. "Use '/help <cmd>' to get more information,"
.. " or '/help all' to list everything."
elseif param == "all" then
local cmds = {}
for cmd, def in pairs(core.chatcommands) do
if core.check_player_privs(name, def.privs) then
cmds[#cmds + 1] = format_help_line(cmd, def)
end
end
table.sort(cmds)
return true, "Available commands:\n"..table.concat(cmds, "\n")
elseif param == "privs" then
local privs = {}
for priv, def in pairs(core.registered_privileges) do
privs[#privs + 1] = priv .. ": " .. def.description
end
table.sort(privs)
return true, "Available privileges:\n"..table.concat(privs, "\n")
else
local cmd = param
local def = core.chatcommands[cmd]
if not def then
return false, "Command not available: "..cmd
else
return true, format_help_line(cmd, def)
end
end
end,
})
core.register_chatcommand("privs", { core.register_chatcommand("privs", {
params = "<name>", params = "<name>",
description = "print out privileges of player", description = "Print privileges of player",
func = function(caller, param) func = function(caller, param)
param = param:trim() param = param:trim()
local name = (param ~= "" and param or caller) local name = (param ~= "" and param or caller)
@ -162,7 +109,7 @@ local function handle_grant_command(caller, grantname, grantprivstr)
return false, "Your privileges are insufficient." return false, "Your privileges are insufficient."
end end
if not core.auth_table[grantname] then if not core.get_auth_handler().get_auth(grantname) then
return false, "Player " .. grantname .. " does not exist." return false, "Player " .. grantname .. " does not exist."
end end
local grantprivs = core.string_to_privs(grantprivstr) local grantprivs = core.string_to_privs(grantprivstr)
@ -172,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."
@ -232,13 +179,13 @@ core.register_chatcommand("revoke", {
local revoke_name, revoke_priv_str = string.match(param, "([^ ]+) (.+)") local revoke_name, revoke_priv_str = string.match(param, "([^ ]+) (.+)")
if not revoke_name or not revoke_priv_str then if not revoke_name or not revoke_priv_str then
return false, "Invalid parameters (see /help revoke)" return false, "Invalid parameters (see /help revoke)"
elseif not core.auth_table[revoke_name] then elseif not core.get_auth_handler().get_auth(revoke_name) then
return false, "Player " .. revoke_name .. " does not exist." return false, "Player " .. revoke_name .. " does not exist."
end end
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
@ -269,7 +216,7 @@ core.register_chatcommand("revoke", {
core.register_chatcommand("setpassword", { core.register_chatcommand("setpassword", {
params = "<name> <password>", params = "<name> <password>",
description = "set given password", description = "Set player's password",
privs = {password=true}, privs = {password=true},
func = function(name, param) func = function(name, param)
local toname, raw_password = string.match(param, "^([^ ]+) +(.+)$") local toname, raw_password = string.match(param, "^([^ ]+) +(.+)$")
@ -307,7 +254,7 @@ core.register_chatcommand("setpassword", {
core.register_chatcommand("clearpassword", { core.register_chatcommand("clearpassword", {
params = "<name>", params = "<name>",
description = "set empty password", description = "Set empty password",
privs = {password=true}, privs = {password=true},
func = function(name, param) func = function(name, param)
local toname = param local toname = param
@ -324,7 +271,7 @@ core.register_chatcommand("clearpassword", {
core.register_chatcommand("auth_reload", { core.register_chatcommand("auth_reload", {
params = "", params = "",
description = "reload authentication data", description = "Reload authentication data",
privs = {server=true}, privs = {server=true},
func = function(name, param) func = function(name, param)
local done = core.auth_reload() local done = core.auth_reload()
@ -332,9 +279,34 @@ 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 given position", description = "Teleport to player or position",
privs = {teleport=true}, privs = {teleport=true},
func = function(name, param) func = function(name, param)
-- Returns (pos, true) if found, otherwise (pos, false) -- Returns (pos, true) if found, otherwise (pos, false)
@ -365,7 +337,7 @@ core.register_chatcommand("teleport", {
p.y = tonumber(p.y) p.y = tonumber(p.y)
p.z = tonumber(p.z) p.z = tonumber(p.z)
if p.x and p.y and p.z then if p.x and p.y and p.z then
local lm = tonumber(minetest.setting_get("map_generation_limit") or 31000) local lm = 31000
if p.x < -lm or p.x > lm or p.y < -lm or p.y > lm or p.z < -lm or p.z > lm then if p.x < -lm or p.x > lm or p.y < -lm or p.y > lm or p.z < -lm or p.z > lm then
return false, "Cannot teleport out of map bounds!" return false, "Cannot teleport out of map bounds!"
end end
@ -442,25 +414,25 @@ core.register_chatcommand("teleport", {
core.register_chatcommand("set", { core.register_chatcommand("set", {
params = "[-n] <name> <value> | <name>", params = "[-n] <name> <value> | <name>",
description = "set or read server configuration setting", description = "Set or read server configuration setting",
privs = {server=true}, privs = {server=true},
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
@ -497,7 +469,7 @@ end
core.register_chatcommand("emergeblocks", { core.register_chatcommand("emergeblocks", {
params = "(here [radius]) | (<pos1> <pos2>)", params = "(here [radius]) | (<pos1> <pos2>)",
description = "starts loading (or generating, if inexistent) map blocks " description = "Load (or, if nonexistent, generate) map blocks "
.. "contained in area pos1 to pos2", .. "contained in area pos1 to pos2",
privs = {server=true}, privs = {server=true},
func = function(name, param) func = function(name, param)
@ -523,7 +495,7 @@ core.register_chatcommand("emergeblocks", {
core.register_chatcommand("deleteblocks", { core.register_chatcommand("deleteblocks", {
params = "(here [radius]) | (<pos1> <pos2>)", params = "(here [radius]) | (<pos1> <pos2>)",
description = "delete map blocks contained in area pos1 to pos2", description = "Delete map blocks contained in area pos1 to pos2",
privs = {server=true}, privs = {server=true},
func = function(name, param) func = function(name, param)
local p1, p2 = parse_range_str(name, param) local p1, p2 = parse_range_str(name, param)
@ -540,6 +512,25 @@ core.register_chatcommand("deleteblocks", {
end, end,
}) })
core.register_chatcommand("fixlight", {
params = "(here [radius]) | (<pos1> <pos2>)",
description = "Resets lighting in the area between pos1 and pos2",
privs = {server = true},
func = function(name, param)
local p1, p2 = parse_range_str(name, param)
if p1 == false then
return false, p2
end
if core.fix_light(p1, p2) then
return true, "Successfully reset light in the area ranging from " ..
core.pos_to_string(p1, 1) .. " to " .. core.pos_to_string(p2, 1)
else
return false, "Failed to load one or more blocks in area"
end
end,
})
core.register_chatcommand("mods", { core.register_chatcommand("mods", {
params = "", params = "",
description = "List mods installed on the server", description = "List mods installed on the server",
@ -587,7 +578,7 @@ end
core.register_chatcommand("give", { core.register_chatcommand("give", {
params = "<name> <ItemString>", params = "<name> <ItemString>",
description = "give item to player", description = "Give item to player",
privs = {give=true}, privs = {give=true},
func = function(name, param) func = function(name, param)
local toname, itemstring = string.match(param, "^([^ ]+) +(.+)$") local toname, itemstring = string.match(param, "^([^ ]+) +(.+)$")
@ -600,7 +591,7 @@ core.register_chatcommand("give", {
core.register_chatcommand("giveme", { core.register_chatcommand("giveme", {
params = "<ItemString>", params = "<ItemString>",
description = "give item to yourself", description = "Give item to yourself",
privs = {give=true}, privs = {give=true},
func = function(name, param) func = function(name, param)
local itemstring = string.match(param, "(.+)$") local itemstring = string.match(param, "(.+)$")
@ -671,12 +662,12 @@ end)
core.register_chatcommand("rollback_check", { core.register_chatcommand("rollback_check", {
params = "[<range>] [<seconds>] [limit]", params = "[<range>] [<seconds>] [limit]",
description = "Check who has last touched a node or near it," description = "Check who last touched a node or a node near it"
.. " max. <seconds> ago (default range=0," .. " within the time specified by <seconds>. Default: range = 0,"
.. " 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 =
@ -724,10 +715,10 @@ core.register_chatcommand("rollback_check", {
core.register_chatcommand("rollback", { core.register_chatcommand("rollback", {
params = "<player name> [<seconds>] | :<actor> [<seconds>]", params = "<player name> [<seconds>] | :<actor> [<seconds>]",
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*)")
@ -769,7 +760,7 @@ core.register_chatcommand("status", {
core.register_chatcommand("time", { core.register_chatcommand("time", {
params = "<0..23>:<0..59> | <0..24000>", params = "<0..23>:<0..59> | <0..24000>",
description = "set time of day", description = "Set time of day",
privs = {}, privs = {},
func = function(name, param) func = function(name, param)
if param == "" then if param == "" then
@ -815,12 +806,21 @@ core.register_chatcommand("days", {
}) })
core.register_chatcommand("shutdown", { core.register_chatcommand("shutdown", {
description = "shutdown server", description = "Shutdown server",
params = "[delay_in_seconds (non-negative number, or -1 to cancel)] [reconnect] [message]",
privs = {server=true}, privs = {server=true},
func = function(name, param) func = function(name, param)
local delay, reconnect, message = param:match("([^ ][-]?[0-9]+)([^ ]+)(.*)")
message = message or ""
if delay ~= "" then
delay = tonumber(param) or 0
else
delay = 0
core.log("action", name .. " shuts down server") core.log("action", name .. " shuts down server")
core.request_shutdown()
core.chat_send_all("*** Server shutting down (operator request).") core.chat_send_all("*** Server shutting down (operator request).")
end
core.request_shutdown(message:trim(), core.is_yes(reconnect), delay)
end, end,
}) })
@ -846,7 +846,7 @@ core.register_chatcommand("ban", {
core.register_chatcommand("unban", { core.register_chatcommand("unban", {
params = "<name/ip>", params = "<name/ip>",
description = "remove IP ban", description = "Remove IP ban",
privs = {ban=true}, privs = {ban=true},
func = function(name, param) func = function(name, param)
if not core.unban_player_or_ip(param) then if not core.unban_player_or_ip(param) then
@ -859,7 +859,7 @@ core.register_chatcommand("unban", {
core.register_chatcommand("kick", { core.register_chatcommand("kick", {
params = "<name> [reason]", params = "<name> [reason]",
description = "kick a player", description = "Kick a player",
privs = {kick=true}, privs = {kick=true},
func = function(name, param) func = function(name, param)
local tokick, reason = param:match("([^ ]+) (.+)") local tokick, reason = param:match("([^ ]+) (.+)")
@ -878,7 +878,7 @@ core.register_chatcommand("kick", {
core.register_chatcommand("clearobjects", { core.register_chatcommand("clearobjects", {
params = "[full|quick]", params = "[full|quick]",
description = "clear all objects in world", description = "Clear all objects in world",
privs = {server=true}, privs = {server=true},
func = function(name, param) func = function(name, param)
local options = {} local options = {}
@ -938,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,
})

@ -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")

@ -18,9 +18,11 @@ core.register_entity(":__builtin:falling_node", {
}, },
node = {}, node = {},
meta = {},
set_node = function(self, node) set_node = function(self, node, meta)
self.node = node self.node = node
self.meta = meta or {}
self.object:set_properties({ self.object:set_properties({
is_visible = true, is_visible = true,
textures = {node.name}, textures = {node.name},
@ -28,15 +30,21 @@ core.register_entity(":__builtin:falling_node", {
end, end,
get_staticdata = function(self) get_staticdata = function(self)
return core.serialize(self.node) local ds = {
node = self.node,
meta = self.meta,
}
return core.serialize(ds)
end, end,
on_activate = function(self, staticdata) on_activate = function(self, staticdata)
self.object:set_armor_groups({immortal = 1}) self.object:set_armor_groups({immortal = 1})
local node = core.deserialize(staticdata) local ds = core.deserialize(staticdata)
if node then if ds and ds.node then
self:set_node(node) self:set_node(ds.node, ds.meta)
elseif ds then
self:set_node(ds)
elseif staticdata ~= "" then elseif staticdata ~= "" then
self:set_node({name = staticdata}) self:set_node({name = staticdata})
end end
@ -83,7 +91,7 @@ core.register_entity(":__builtin:falling_node", {
-- it's drops -- it's drops
if n2.name ~= "air" and (not nd or nd.liquidtype == "none") then if n2.name ~= "air" and (not nd or nd.liquidtype == "none") then
core.remove_node(np) core.remove_node(np)
if nd.buildable_to == false then if nd and nd.buildable_to == false then
-- Add dropped items -- Add dropped items
local drops = core.get_node_drops(n2.name, "") local drops = core.get_node_drops(n2.name, "")
for _, dropped_item in pairs(drops) do for _, dropped_item in pairs(drops) do
@ -98,6 +106,10 @@ core.register_entity(":__builtin:falling_node", {
-- Create node and remove entity -- Create node and remove entity
if core.registered_nodes[self.node.name] then if core.registered_nodes[self.node.name] then
core.add_node(np, self.node) core.add_node(np, self.node)
if self.meta then
local meta = core.get_meta(np)
meta:from_table(self.meta)
end
end end
self.object:remove() self.object:remove()
core.check_for_falling(np) core.check_for_falling(np)
@ -111,13 +123,27 @@ core.register_entity(":__builtin:falling_node", {
end end
}) })
local function spawn_falling_node(p, node) local function spawn_falling_node(p, node, meta)
local obj = core.add_entity(p, "__builtin:falling_node") local obj = core.add_entity(p, "__builtin:falling_node")
if obj then if obj then
obj:get_luaentity():set_node(node) obj:get_luaentity():set_node(node, meta)
end end
end end
function core.spawn_falling_node(pos)
local node = core.get_node(pos)
if node.name == "air" or node.name == "ignore" then
return false
end
local obj = core.add_entity(pos, "__builtin:falling_node")
if obj then
obj:get_luaentity():set_node(node)
core.remove_node(pos)
return true
end
return false
end
local function drop_attached_node(p) local function drop_attached_node(p)
local nn = core.get_node(p).name local nn = core.get_node(p).name
core.remove_node(p) core.remove_node(p)
@ -134,7 +160,8 @@ end
function builtin_shared.check_attached_node(p, n) function builtin_shared.check_attached_node(p, n)
local def = core.registered_nodes[n.name] local def = core.registered_nodes[n.name]
local d = {x = 0, y = 0, z = 0} local d = {x = 0, y = 0, z = 0}
if def.paramtype2 == "wallmounted" then if def.paramtype2 == "wallmounted" or
def.paramtype2 == "colorwallmounted" then
-- The fallback vector here is in case 'wallmounted to dir' is nil due -- The fallback vector here is in case 'wallmounted to dir' is nil due
-- to voxelmanip placing a wallmounted node without resetting a -- to voxelmanip placing a wallmounted node without resetting a
-- pre-existing param2 value that is out-of-range for wallmounted. -- pre-existing param2 value that is out-of-range for wallmounted.
@ -174,8 +201,13 @@ function core.check_single_for_falling(p)
(not d_bottom.walkable or d_bottom.buildable_to) then (not d_bottom.walkable or d_bottom.buildable_to) then
n.level = core.get_node_level(p) n.level = core.get_node_level(p)
local meta = core.get_meta(p)
local metatable = {}
if meta ~= nil then
metatable = meta:to_table()
end
core.remove_node(p) core.remove_node(p)
spawn_falling_node(p, n) spawn_falling_node(p, n, metatable)
return true return true
end end
end end

@ -9,6 +9,8 @@ core.features = {
no_legacy_abms = true, no_legacy_abms = true,
texture_names_parens = true, texture_names_parens = true,
area_store_custom_ids = true, area_store_custom_ids = true,
add_entity_with_staticdata = true,
no_chat_message_prediction = true,
} }
function core.has_feature(arg) function core.has_feature(arg)

@ -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

@ -13,15 +13,17 @@ 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
dofile(commonpath .. "after.lua")
dofile(gamepath.."item_entity.lua") dofile(gamepath.."item_entity.lua")
dofile(gamepath.."deprecated.lua") dofile(gamepath.."deprecated.lua")
dofile(gamepath.."misc.lua") dofile(gamepath.."misc.lua")
dofile(gamepath.."privileges.lua") dofile(gamepath.."privileges.lua")
dofile(gamepath.."auth.lua") dofile(gamepath.."auth.lua")
dofile(commonpath .. "chatcommands.lua")
dofile(gamepath.."chatcommands.lua") dofile(gamepath.."chatcommands.lua")
dofile(gamepath.."static_spawn.lua") dofile(gamepath.."static_spawn.lua")
dofile(gamepath.."detached_inventory.lua") dofile(gamepath.."detached_inventory.lua")

@ -109,7 +109,7 @@ local facedir_to_dir_map = {
1, 4, 3, 2, 1, 4, 3, 2,
} }
function core.facedir_to_dir(facedir) function core.facedir_to_dir(facedir)
return facedir_to_dir[facedir_to_dir_map[facedir]] return facedir_to_dir[facedir_to_dir_map[facedir % 32]]
end end
function core.dir_to_wallmounted(dir) function core.dir_to_wallmounted(dir)
@ -144,11 +144,20 @@ local wallmounted_to_dir = {
{x = 0, y = 0, z = -1}, {x = 0, y = 0, z = -1},
} }
function core.wallmounted_to_dir(wallmounted) function core.wallmounted_to_dir(wallmounted)
return wallmounted_to_dir[wallmounted] return wallmounted_to_dir[wallmounted % 8]
end
function core.dir_to_yaw(dir)
return -math.atan2(dir.x, dir.z)
end
function core.yaw_to_dir(yaw)
return {x = -math.sin(yaw), y = 0, z = math.cos(yaw)}
end end
function core.get_node_drops(nodename, toolname) function core.get_node_drops(nodename, toolname)
local drop = ItemStack({name=nodename}):get_definition().drop local def = core.registered_nodes[nodename]
local drop = def and def.drop
if drop == nil then if drop == nil then
-- default drop -- default drop
return {nodename} return {nodename}
@ -197,7 +206,6 @@ function core.get_node_drops(nodename, toolname)
end end
function core.item_place_node(itemstack, placer, pointed_thing, param2) function core.item_place_node(itemstack, placer, pointed_thing, param2)
local item = itemstack:peek_item()
local def = itemstack:get_definition() local def = itemstack:get_definition()
if def.type ~= "node" or pointed_thing.type ~= "node" then if def.type ~= "node" or pointed_thing.type ~= "node" then
return itemstack, false return itemstack, false
@ -207,20 +215,21 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2)
local oldnode_under = core.get_node_or_nil(under) local oldnode_under = core.get_node_or_nil(under)
local above = pointed_thing.above local above = pointed_thing.above
local oldnode_above = core.get_node_or_nil(above) local oldnode_above = core.get_node_or_nil(above)
local playername = placer:get_player_name()
if not oldnode_under or not oldnode_above then if not oldnode_under or not oldnode_above then
core.log("info", placer:get_player_name() .. " tried to place" core.log("info", playername .. " tried to place"
.. " node in unloaded position " .. core.pos_to_string(above)) .. " node in unloaded position " .. core.pos_to_string(above))
return itemstack, false return itemstack, false
end end
local olddef_under = ItemStack({name=oldnode_under.name}):get_definition() local olddef_under = core.registered_nodes[oldnode_under.name]
olddef_under = olddef_under or core.nodedef_default olddef_under = olddef_under or core.nodedef_default
local olddef_above = ItemStack({name=oldnode_above.name}):get_definition() local olddef_above = core.registered_nodes[oldnode_above.name]
olddef_above = olddef_above or core.nodedef_default olddef_above = olddef_above or core.nodedef_default
if not olddef_above.buildable_to and not olddef_under.buildable_to then if not olddef_above.buildable_to and not olddef_under.buildable_to then
core.log("info", placer:get_player_name() .. " tried to place" core.log("info", playername .. " tried to place"
.. " node in invalid position " .. core.pos_to_string(above) .. " node in invalid position " .. core.pos_to_string(above)
.. ", replacing " .. oldnode_above.name) .. ", replacing " .. oldnode_above.name)
return itemstack, false return itemstack, false
@ -235,17 +244,17 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2)
place_to = {x = under.x, y = under.y, z = under.z} place_to = {x = under.x, y = under.y, z = under.z}
end end
if core.is_protected(place_to, placer:get_player_name()) and if core.is_protected(place_to, playername) and
not minetest.check_player_privs(placer, "protection_bypass") then not minetest.check_player_privs(placer, "protection_bypass") then
core.log("action", placer:get_player_name() core.log("action", playername
.. " tried to place " .. def.name .. " tried to place " .. def.name
.. " at protected position " .. " at protected position "
.. core.pos_to_string(place_to)) .. core.pos_to_string(place_to))
core.record_protection_violation(place_to, placer:get_player_name()) core.record_protection_violation(place_to, playername)
return itemstack return itemstack
end end
core.log("action", placer:get_player_name() .. " places node " core.log("action", playername .. " places node "
.. def.name .. " at " .. core.pos_to_string(place_to)) .. def.name .. " at " .. core.pos_to_string(place_to))
local oldnode = core.get_node(place_to) local oldnode = core.get_node(place_to)
@ -254,7 +263,8 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2)
-- Calculate direction for wall mounted stuff like torches and signs -- Calculate direction for wall mounted stuff like torches and signs
if def.place_param2 ~= nil then if def.place_param2 ~= nil then
newnode.param2 = def.place_param2 newnode.param2 = def.place_param2
elseif def.paramtype2 == 'wallmounted' and not param2 then elseif (def.paramtype2 == "wallmounted" or
def.paramtype2 == "colorwallmounted") and not param2 then
local dir = { local dir = {
x = under.x - above.x, x = under.x - above.x,
y = under.y - above.y, y = under.y - above.y,
@ -262,7 +272,8 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2)
} }
newnode.param2 = core.dir_to_wallmounted(dir) newnode.param2 = core.dir_to_wallmounted(dir)
-- Calculate the direction for furnaces and chests and stuff -- Calculate the direction for furnaces and chests and stuff
elseif def.paramtype2 == 'facedir' and not param2 then elseif (def.paramtype2 == "facedir" or
def.paramtype2 == "colorfacedir") and not param2 then
local placer_pos = placer:getpos() local placer_pos = placer:getpos()
if placer_pos then if placer_pos then
local dir = { local dir = {
@ -300,7 +311,6 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2)
end end
-- Run script hook -- Run script hook
local _, callback
for _, callback in ipairs(core.registered_on_placenodes) do for _, callback in ipairs(core.registered_on_placenodes) do
-- Deepcopy pos, node and pointed_thing because callback can modify them -- Deepcopy pos, node and pointed_thing because callback can modify them
local place_to_copy = {x=place_to.x, y=place_to.y, z=place_to.z} local place_to_copy = {x=place_to.x, y=place_to.y, z=place_to.z}
@ -441,8 +451,9 @@ function core.handle_node_drops(pos, drops, digger)
end end
function core.node_dig(pos, node, digger) function core.node_dig(pos, node, digger)
local def = ItemStack({name=node.name}):get_definition() local def = core.registered_nodes[node.name]
if not def.diggable or (def.can_dig and not def.can_dig(pos,digger)) then if def and (not def.diggable or
(def.can_dig and not def.can_dig(pos, digger))) then
core.log("info", digger:get_player_name() .. " tried to dig " core.log("info", digger:get_player_name() .. " tried to dig "
.. node.name .. " which is not diggable " .. node.name .. " which is not diggable "
.. core.pos_to_string(pos)) .. core.pos_to_string(pos))
@ -467,12 +478,12 @@ function core.node_dig(pos, node, digger)
local wdef = wielded:get_definition() local wdef = wielded:get_definition()
local tp = wielded:get_tool_capabilities() local tp = wielded:get_tool_capabilities()
local dp = core.get_dig_params(def.groups, tp) local dp = core.get_dig_params(def and def.groups, tp)
if wdef and wdef.after_use then if wdef and wdef.after_use then
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})
@ -485,7 +496,7 @@ function core.node_dig(pos, node, digger)
core.handle_node_drops(pos, drops, digger) core.handle_node_drops(pos, drops, digger)
local oldmetadata = nil local oldmetadata = nil
if def.after_dig_node then if def and def.after_dig_node then
oldmetadata = core.get_meta(pos):to_table() oldmetadata = core.get_meta(pos):to_table()
end end
@ -493,7 +504,7 @@ function core.node_dig(pos, node, digger)
core.remove_node(pos) core.remove_node(pos)
-- Run callback -- Run callback
if def.after_dig_node then if def and def.after_dig_node then
-- Copy pos and node because callback can modify them -- Copy pos and node because callback can modify them
local pos_copy = {x=pos.x, y=pos.y, z=pos.z} local pos_copy = {x=pos.x, y=pos.y, z=pos.z}
local node_copy = {name=node.name, param1=node.param1, param2=node.param2} local node_copy = {name=node.name, param1=node.param1, param2=node.param2}

@ -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
@ -53,6 +53,8 @@ core.register_entity(":__builtin:item", {
if itemtable then if itemtable then
itemname = stack:to_table().name itemname = stack:to_table().name
end end
-- Backwards compatibility: old clients use the texture
-- to get the type of the item
local item_texture = nil local item_texture = nil
local item_type = "" local item_type = ""
if core.registered_items[itemname] then if core.registered_items[itemname] then
@ -66,6 +68,7 @@ core.register_entity(":__builtin:item", {
visual_size = {x = s, y = s}, visual_size = {x = s, y = s},
collisionbox = {-c, -c, -c, c, c, c}, collisionbox = {-c, -c, -c, c, c, c},
automatic_rotate = math.pi * 0.5, automatic_rotate = math.pi * 0.5,
wield_item = itemstring,
} }
self.object:set_properties(prop) self.object:set_properties(prop)
end, end,
@ -101,31 +104,39 @@ core.register_entity(":__builtin:item", {
self:set_item(self.itemstring) self:set_item(self.itemstring)
end, end,
-- moves items from this stack to an other stack
try_merge_with = function(self, own_stack, object, obj) try_merge_with = function(self, own_stack, object, obj)
-- other item's stack
local stack = ItemStack(obj.itemstring) local stack = ItemStack(obj.itemstring)
if own_stack:get_name() == stack:get_name() and stack:get_free_space() > 0 then -- only merge if items are the same
if own_stack:get_name() == stack:get_name() and
own_stack:get_meta() == stack:get_meta() and
own_stack:get_wear() == stack:get_wear() and
stack:get_free_space() > 0 then
local overflow = false local overflow = false
local count = stack:get_count() + own_stack:get_count() local count = stack:get_count() + own_stack:get_count()
local max_count = stack:get_stack_max() local max_count = stack:get_stack_max()
if count > max_count then if count > max_count then
overflow = true overflow = true
stack:set_count(max_count)
count = count - max_count count = count - max_count
own_stack:set_count(count)
else else
self.itemstring = '' self.itemstring = ''
stack:set_count(count)
end end
local pos = object:getpos() local pos = object:getpos()
pos.y = pos.y + (count - stack:get_count()) / max_count * 0.15 pos.y = pos.y + (count - stack:get_count()) / max_count * 0.15
object:moveto(pos, false) object:moveto(pos, false)
local s, c local s, c
local max_count = stack:get_stack_max()
local name = stack:get_name()
if not overflow then if not overflow then
obj.itemstring = name .. " " .. count obj.itemstring = stack:to_string()
s = 0.2 + 0.1 * (count / max_count) s = 0.2 + 0.1 * (count / max_count)
c = s c = s
object:set_properties({ object:set_properties({
visual_size = {x = s, y = s}, visual_size = {x = s, y = s},
collisionbox = {-c, -c, -c, c, c, c} collisionbox = {-c, -c, -c, c, c, c},
wield_item = obj.itemstring
}) })
self.object:remove() self.object:remove()
-- merging succeeded -- merging succeeded
@ -133,18 +144,20 @@ core.register_entity(":__builtin:item", {
else else
s = 0.4 s = 0.4
c = 0.3 c = 0.3
obj.itemstring = stack:to_string()
object:set_properties({ object:set_properties({
visual_size = {x = s, y = s}, visual_size = {x = s, y = s},
collisionbox = {-c, -c, -c, c, c, c} collisionbox = {-c, -c, -c, c, c, c},
wield_item = obj.itemstring
}) })
obj.itemstring = name .. " " .. max_count
s = 0.2 + 0.1 * (count / max_count) s = 0.2 + 0.1 * (count / max_count)
c = s c = s
self.itemstring = own_stack:to_string()
self.object:set_properties({ self.object:set_properties({
visual_size = {x = s, y = s}, visual_size = {x = s, y = s},
collisionbox = {-c, -c, -c, c, c, c} collisionbox = {-c, -c, -c, c, c, c},
wield_item = self.itemstring
}) })
self.itemstring = name .. " " .. count
end end
end end
-- merging didn't succeed -- merging didn't succeed

@ -4,50 +4,6 @@
-- Misc. API functions -- Misc. API functions
-- --
local jobs = {}
local time = 0.0
local last = core.get_us_time() / 1000000
core.register_globalstep(function(dtime)
local new = core.get_us_time() / 1000000
if new > last then
time = time + (new - last)
else
-- Overflow, we may lose a little bit of time here but
-- only 1 tick max, potentially running timers slightly
-- too early.
time = time + new
end
last = new
if #jobs < 1 then
return
end
-- Iterate backwards so that we miss any new timers added by
-- a timer callback, and so that we don't skip the next timer
-- in the list if we remove one.
for i = #jobs, 1, -1 do
local job = jobs[i]
if time >= job.expire then
core.set_last_run_mod(job.mod_origin)
job.func(unpack(job.arg))
table.remove(jobs, i)
end
end
end)
function core.after(after, func, ...)
assert(tonumber(after) and type(func) == "function",
"Invalid core.after invocation")
jobs[#jobs + 1] = {
func = func,
expire = time + after,
arg = {...},
mod_origin = core.get_last_run_mod()
}
end
function core.check_player_privs(name, ...) function core.check_player_privs(name, ...)
local arg_type = type(name) local arg_type = type(name)
if (arg_type == "userdata" or arg_type == "table") and if (arg_type == "userdata" or arg_type == "table") and
@ -114,6 +70,10 @@ function core.get_connected_players()
return temp_table return temp_table
end end
function minetest.player_exists(name)
return minetest.get_auth_handler().get_auth(name) ~= nil
end
-- Returns two position vectors representing a box of `radius` in each -- Returns two position vectors representing a box of `radius` in each
-- direction centered around the player corresponding to `player_name` -- direction centered around the player corresponding to `player_name`
function core.get_player_radius_area(player_name, radius) function core.get_player_radius_area(player_name, radius)
@ -161,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
@ -210,38 +170,11 @@ function core.http_add_fetch(httpenv)
return httpenv return httpenv
end end
if minetest.setting_getbool("disable_escape_sequences") then
function core.get_color_escape_sequence(color)
return ""
end
function core.get_background_escape_sequence(color)
return ""
end
function core.colorize(color, message)
return message
end
else
local ESCAPE_CHAR = string.char(0x1b)
function core.get_color_escape_sequence(color)
return ESCAPE_CHAR .. "(c@" .. color .. ")"
end
function core.get_background_escape_sequence(color)
return ESCAPE_CHAR .. "(b@" .. color .. ")"
end
function core.colorize(color, message)
return core.get_color_escape_sequence(color) .. message .. core.get_color_escape_sequence("#ffffff")
end
end
function core.close_formspec(player_name, formname) function core.close_formspec(player_name, formname)
return minetest.show_formspec(player_name, formname, "") return minetest.show_formspec(player_name, formname, "")
end end
function core.cancel_shutdown_requests()
core.request_shutdown("", false, -1)
end

@ -331,8 +331,8 @@ core.register_item(":unknown", {
core.register_node(":air", { core.register_node(":air", {
description = "Air (you hacker you!)", description = "Air (you hacker you!)",
inventory_image = "unknown_node.png", inventory_image = "air.png",
wield_image = "unknown_node.png", wield_image = "air.png",
drawtype = "airlike", drawtype = "airlike",
paramtype = "light", paramtype = "light",
sunlight_propagates = true, sunlight_propagates = true,
@ -348,8 +348,8 @@ core.register_node(":air", {
core.register_node(":ignore", { core.register_node(":ignore", {
description = "Ignore (you hacker you!)", description = "Ignore (you hacker you!)",
inventory_image = "unknown_node.png", inventory_image = "ignore.png",
wield_image = "unknown_node.png", wield_image = "ignore.png",
drawtype = "airlike", drawtype = "airlike",
paramtype = "none", paramtype = "none",
sunlight_propagates = false, sunlight_propagates = false,

@ -1,3 +1,5 @@
-- cache setting
local enable_damage = core.settings:get_bool("enable_damage")
local health_bar_definition = local health_bar_definition =
{ {
@ -42,8 +44,7 @@ local function initialize_builtin_statbars(player)
player:hud_set_flags(player:hud_get_flags()) player:hud_set_flags(player:hud_get_flags())
end end
if player:hud_get_flags().healthbar and if player:hud_get_flags().healthbar and enable_damage then
core.is_yes(core.setting_get("enable_damage")) then
if hud_ids[name].id_healthbar == nil then if hud_ids[name].id_healthbar == nil then
health_bar_definition.number = player:get_hp() health_bar_definition.number = player:get_hp()
hud_ids[name].id_healthbar = player:hud_add(health_bar_definition) hud_ids[name].id_healthbar = player:hud_add(health_bar_definition)
@ -56,8 +57,7 @@ local function initialize_builtin_statbars(player)
end end
if (player:get_breath() < 11) then if (player:get_breath() < 11) then
if player:hud_get_flags().breathbar and if player:hud_get_flags().breathbar and enable_damage then
core.is_yes(core.setting_get("enable_damage")) then
if hud_ids[name].id_breathbar == nil then if hud_ids[name].id_breathbar == nil then
hud_ids[name].id_breathbar = player:hud_add(breath_bar_definition) hud_ids[name].id_breathbar = player:hud_add(breath_bar_definition)
end end

@ -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

@ -27,6 +27,7 @@ minetest = core
-- Load other files -- Load other files
local scriptdir = core.get_builtin_path() .. DIR_DELIM local scriptdir = core.get_builtin_path() .. DIR_DELIM
local gamepath = scriptdir .. "game" .. DIR_DELIM local gamepath = scriptdir .. "game" .. DIR_DELIM
local clientpath = scriptdir .. "client" .. DIR_DELIM
local commonpath = scriptdir .. "common" .. DIR_DELIM local commonpath = scriptdir .. "common" .. DIR_DELIM
local asyncpath = scriptdir .. "async" .. DIR_DELIM local asyncpath = scriptdir .. "async" .. DIR_DELIM
@ -37,15 +38,17 @@ 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 mainmenuscript = core.setting_get("main_menu_script") local mm_script = core.settings:get("main_menu_script")
if mainmenuscript ~= nil and mainmenuscript ~= "" then if mm_script and mm_script ~= "" then
dofile(mainmenuscript) dofile(mm_script)
else else
dofile(core.get_mainmenu_path() .. DIR_DELIM .. "init.lua") dofile(core.get_mainmenu_path() .. DIR_DELIM .. "init.lua")
end end
elseif INIT == "async" then elseif INIT == "async" then
dofile(asyncpath .. "init.lua") dofile(asyncpath .. "init.lua")
elseif INIT == "client" then
os.setlocale = nil
dofile(clientpath .. "init.lua")
else else
error(("Unrecognized builtin initialization type %s!"):format(tostring(INIT))) error(("Unrecognized builtin initialization type %s!"):format(tostring(INIT)))
end end

@ -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
@ -54,7 +54,12 @@ end
function image_column(tooltip, flagname) function image_column(tooltip, flagname)
return "image,tooltip=" .. core.formspec_escape(tooltip) .. "," .. return "image,tooltip=" .. core.formspec_escape(tooltip) .. "," ..
"0=" .. core.formspec_escape(defaulttexturedir .. "blank.png") .. "," .. "0=" .. core.formspec_escape(defaulttexturedir .. "blank.png") .. "," ..
"1=" .. core.formspec_escape(defaulttexturedir .. "server_flags_" .. flagname .. ".png") "1=" .. core.formspec_escape(defaulttexturedir ..
(flagname and "server_flags_" .. flagname .. ".png" or "blank.png")) .. "," ..
"2=" .. core.formspec_escape(defaulttexturedir .. "server_ping_4.png") .. "," ..
"3=" .. core.formspec_escape(defaulttexturedir .. "server_ping_3.png") .. "," ..
"4=" .. core.formspec_escape(defaulttexturedir .. "server_ping_2.png") .. "," ..
"5=" .. core.formspec_escape(defaulttexturedir .. "server_ping_1.png")
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -77,7 +82,7 @@ function order_favorite_list(list)
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function render_favorite(spec, is_favorite) function render_serverlist_row(spec, is_favorite)
local text = "" local text = ""
if spec.name then if spec.name then
text = text .. core.formspec_escape(spec.name:trim()) text = text .. core.formspec_escape(spec.name:trim())
@ -97,6 +102,21 @@ function render_favorite(spec, is_favorite)
details = "0," details = "0,"
end end
if spec.ping then
local ping = spec.ping * 1000
if ping <= 50 then
details = details .. "2,"
elseif ping <= 100 then
details = details .. "3,"
elseif ping <= 250 then
details = details .. "4,"
else
details = details .. "5,"
end
else
details = details .. "0,"
end
if spec.clients and spec.clients_max then if spec.clients and spec.clients_max then
local clients_color = '' local clients_color = ''
local clients_percent = 100 * spec.clients / spec.clients_max local clients_percent = 100 * spec.clients / spec.clients_max
@ -144,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()
@ -186,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
@ -230,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 .. ";"
@ -308,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

@ -24,7 +24,6 @@ local function modname_valid(name)
end end
local function get_formspec(data) local function get_formspec(data)
local mod = data.list:get_list()[data.selected_mod] local mod = data.list:get_list()[data.selected_mod]
local retval = local retval =
@ -32,18 +31,6 @@ local function get_formspec(data)
"label[0.5,0;" .. fgettext("World:") .. "]" .. "label[0.5,0;" .. fgettext("World:") .. "]" ..
"label[1.75,0;" .. data.worldspec.name .. "]" "label[1.75,0;" .. data.worldspec.name .. "]"
if data.hide_gamemods then
retval = retval .. "checkbox[1,6;cb_hide_gamemods;" .. fgettext("Hide Game") .. ";true]"
else
retval = retval .. "checkbox[1,6;cb_hide_gamemods;" .. fgettext("Hide Game") .. ";false]"
end
if data.hide_modpackcontents then
retval = retval .. "checkbox[6,6;cb_hide_mpcontent;" .. fgettext("Hide mp content") .. ";true]"
else
retval = retval .. "checkbox[6,6;cb_hide_mpcontent;" .. fgettext("Hide mp content") .. ";false]"
end
if mod == nil then if mod == nil then
mod = {name=""} mod = {name=""}
end end
@ -62,41 +49,45 @@ 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 ~= nil 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()
local all_enabled = true local all_enabled = true
for j = 1, #rawlist, 1 do for j = 1, #rawlist, 1 do
if rawlist[j].modpack == mod.name and if rawlist[j].modpack == mod.name and not rawlist[j].enabled then
rawlist[j].enabled ~= true then
all_enabled = false all_enabled = false
break break
end end
end end
if all_enabled == false then if all_enabled then
retval = retval .. "button[5.5,0.125;2.5,0.5;btn_mp_enable;" .. fgettext("Enable MP") .. "]" retval = retval .. "button[5.5,0.125;2.5,0.5;btn_mp_disable;" ..
fgettext("Disable MP") .. "]"
else else
retval = retval .. "button[5.5,0.125;2.5,0.5;btn_mp_disable;" .. fgettext("Disable MP") .. "]" retval = retval .. "button[5.5,0.125;2.5,0.5;btn_mp_enable;" ..
fgettext("Enable MP") .. "]"
end end
else else
if mod.enabled then if mod.enabled then
retval = retval .. "checkbox[5.5,-0.125;cb_mod_enable;" .. fgettext("enabled") .. ";true]" retval = retval .. "checkbox[5.5,-0.125;cb_mod_enable;" ..
fgettext("enabled") .. ";true]"
else else
retval = retval .. "checkbox[5.5,-0.125;cb_mod_enable;" .. fgettext("enabled") .. ";false]" retval = retval .. "checkbox[5.5,-0.125;cb_mod_enable;" ..
fgettext("enabled") .. ";false]"
end end
end end
end end
if enabled_all then if enabled_all then
retval = retval .. retval = retval ..
"button[8.75,0.125;2.5,0.5;btn_disable_all_mods;" .. fgettext("Disable all") .. "]" .. "button[8.75,0.125;2.5,0.5;btn_disable_all_mods;" .. fgettext("Disable all") .. "]"
"textlist[5.5,0.75;5.75,5.4;world_config_modlist;"
else else
retval = retval .. retval = retval ..
"button[8.75,0.125;2.5,0.5;btn_enable_all_mods;" .. fgettext("Enable all") .. "]" .. "button[8.75,0.125;2.5,0.5;btn_enable_all_mods;" .. fgettext("Enable all") .. "]"
"textlist[5.5,0.75;5.75,5.4;world_config_modlist;"
end end
retval = retval ..
"tablecolumns[color;tree;text]" ..
"table[5.5,0.75;5.75,6;world_config_modlist;"
retval = retval .. modmgr.render_modlist(data.list) retval = retval .. modmgr.render_modlist(data.list)
retval = retval .. ";" .. data.selected_mod .."]" retval = retval .. ";" .. data.selected_mod .."]"
@ -106,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
@ -129,11 +120,10 @@ end
local function handle_buttons(this, fields) local function handle_buttons(this, fields)
if fields["world_config_modlist"] ~= nil then if fields["world_config_modlist"] ~= nil then
local event = core.explode_textlist_event(fields["world_config_modlist"]) local event = core.explode_table_event(fields["world_config_modlist"])
this.data.selected_mod = event.index this.data.selected_mod = event.row
core.setting_set("world_config_selected_mod", event.index) 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)
@ -160,44 +150,7 @@ local function handle_buttons(this, fields)
return true return true
end end
if fields["cb_hide_gamemods"] ~= nil or
fields["cb_hide_mpcontent"] ~= nil then
local current = this.data.list:get_filtercriteria()
if current == nil then
current = {}
end
if fields["cb_hide_gamemods"] ~= nil then
if core.is_yes(fields["cb_hide_gamemods"]) then
current.hide_game = true
this.data.hide_gamemods = true
core.setting_set("world_config_hide_gamemods", "true")
else
current.hide_game = false
this.data.hide_gamemods = false
core.setting_set("world_config_hide_gamemods", "false")
end
end
if fields["cb_hide_mpcontent"] ~= nil then
if core.is_yes(fields["cb_hide_mpcontent"]) then
current.hide_modpackcontents = true
this.data.hide_modpackcontents = true
core.setting_set("world_config_hide_modpackcontents", "true")
else
current.hide_modpackcontents = false
this.data.hide_modpackcontents = false
core.setting_set("world_config_hide_modpackcontents", "false")
end
end
this.data.list:set_filtercriteria(current)
return true
end
if fields["btn_config_world_save"] then if fields["btn_config_world_save"] then
local filename = this.data.worldspec.path .. local filename = this.data.worldspec.path ..
DIR_DELIM .. "world.mt" DIR_DELIM .. "world.mt"
@ -209,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
@ -245,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
@ -257,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
@ -269,15 +224,12 @@ local function handle_buttons(this, fields)
end end
function create_configure_world_dlg(worldidx) function create_configure_world_dlg(worldidx)
local dlg = dialog_create("sp_config_world", local dlg = dialog_create("sp_config_world",
get_formspec, get_formspec,
handle_buttons, handle_buttons,
nil) nil)
dlg.data.hide_gamemods = core.setting_getbool("world_config_hide_gamemods") dlg.data.selected_mod = tonumber(core.settings:get("world_config_selected_mod"))
dlg.data.hide_modpackcontents = core.setting_getbool("world_config_hide_modpackcontents")
dlg.data.selected_mod = tonumber(core.setting_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
@ -304,7 +256,7 @@ function create_configure_world_dlg(worldidx)
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

@ -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

@ -344,11 +344,86 @@ local function parse_config_file(read_all, parse_mods)
return settings return settings
end end
local settings = parse_config_file(false, true) local function filter_settings(settings, searchstring)
if not searchstring or searchstring == "" then
return settings, -1
end
-- Setup the keyword list
local keywords = {}
for word in searchstring:lower():gmatch("%S+") do
table.insert(keywords, word)
end
local result = {}
local category_stack = {}
local current_level = 0
local best_setting = nil
for _, entry in pairs(settings) do
if entry.type == "category" then
-- Remove all settingless categories
while #category_stack > 0 and entry.level <= current_level do
table.remove(category_stack, #category_stack)
if #category_stack > 0 then
current_level = category_stack[#category_stack].level
else
current_level = 0
end
end
-- Push category onto stack
category_stack[#category_stack + 1] = entry
current_level = entry.level
else
-- See if setting matches keywords
local setting_score = 0
for k = 1, #keywords do
local keyword = keywords[k]
if string.find(entry.name:lower(), keyword, 1, true) then
setting_score = setting_score + 1
end
if entry.readable_name and
string.find(fgettext(entry.readable_name):lower(), keyword, 1, true) then
setting_score = setting_score + 1
end
if entry.comment and
string.find(fgettext_ne(entry.comment):lower(), keyword, 1, true) then
setting_score = setting_score + 1
end
end
-- Add setting to results if match
if setting_score > 0 then
-- Add parent categories
for _, category in pairs(category_stack) do
result[#result + 1] = category
end
category_stack = {}
-- Add setting
result[#result + 1] = entry
entry.score = setting_score
if not best_setting or
setting_score > result[best_setting].score then
best_setting = #result
end
end
end
end
return result, best_setting or -1
end
local full_settings = parse_config_file(false, true)
local search_string = ""
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
@ -464,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"])
@ -490,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"])
@ -500,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"]
@ -514,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
@ -544,14 +619,17 @@ end
local function create_settings_formspec(tabview, name, tabdata) local function create_settings_formspec(tabview, name, tabdata)
local formspec = "size[12,6.5;true]" .. local formspec = "size[12,6.5;true]" ..
"tablecolumns[color;tree;text;text]" .. "tablecolumns[color;tree;text,width=32;text]" ..
"tableoptions[background=#00000000;border=false]" .. "tableoptions[background=#00000000;border=false]" ..
"table[0,0;12,5.5;list_settings;" "field[0.3,0.1;10.2,1;search_string;;" .. core.formspec_escape(search_string) .. "]" ..
"field_close_on_enter[search_string;false]" ..
"button[10.2,-0.2;2,1;search;" .. fgettext("Search") .. "]" ..
"table[0,0.8;12,4.5;list_settings;"
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
@ -588,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
@ -600,10 +678,10 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
if core.explode_table_event(fields["list_settings"]).type == "DCL" then if core.explode_table_event(fields["list_settings"]).type == "DCL" then
-- Directly toggle booleans -- Directly toggle booleans
local setting = settings[selected_setting] local setting = settings[selected_setting]
if 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
@ -613,9 +691,39 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
end end
end end
if fields.search or fields.key_enter_field == "search_string" then
if search_string == fields.search_string then
if selected_setting > 0 then
-- Go to next result on enter press
local i = selected_setting + 1
local looped = false
while i > #settings or settings[i].type == "category" do
i = i + 1
if i > #settings then
-- Stop infinte looping
if looped then
return false
end
i = 1
looped = true
end
end
selected_setting = i
core.update_formspec(this:get_formspec())
return true
end
else
-- Search for setting
search_string = fields.search_string
settings, selected_setting = filter_settings(full_settings, search_string)
core.update_formspec(this:get_formspec())
end
return true
end
if fields["btn_edit"] or list_enter then if fields["btn_edit"] or list_enter then
local setting = settings[selected_setting] local setting = settings[selected_setting]
if setting.type ~= "category" then if setting and setting.type ~= "category" then
local edit_dialog = dialog_create("change_setting", create_change_setting_formspec, local edit_dialog = dialog_create("change_setting", create_change_setting_formspec,
handle_change_setting_buttons) handle_change_setting_buttons)
edit_dialog:set_parent(this) edit_dialog:set_parent(this)
@ -627,9 +735,9 @@ 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.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
@ -641,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
@ -661,10 +769,4 @@ end
-- Generate minetest.conf.example and settings_translation_file.cpp -- Generate minetest.conf.example and settings_translation_file.cpp
-- *** Please note *** --assert(loadfile(core.get_builtin_path()..DIR_DELIM.."mainmenu"..DIR_DELIM.."generate_from_settingtypes.lua"))(parse_config_file(true, false))
-- There is text in minetest.conf.example that will not be generated from
-- settingtypes.txt but must be preserved:
-- The documentation of mapgen noise parameter formats (title plus 16 lines)
-- Noise parameter 'mgv5_np_ground' in group format (13 lines)
--assert(loadfile(core.get_mainmenu_path()..DIR_DELIM.."generate_from_settingtypes.lua"))(parse_config_file(true, false))

@ -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

@ -16,9 +16,9 @@
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
mt_color_grey = "#AAAAAA" mt_color_grey = "#AAAAAA"
mt_color_blue = "#0000DD" mt_color_blue = "#6389FF"
mt_color_green = "#00DD00" mt_color_green = "#72FF63"
mt_color_dark_green = "#003300" mt_color_dark_green = "#25C191"
--for all other colors ask sfan5 to complete his work! --for all other colors ask sfan5 to complete his work!
@ -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,25 +118,24 @@ 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()
end end
-- Create main tabview -- Create main tabview
local tv_main = tabview_create("maintab", {x = 12, y = 5.2}, {x = 0, y = 0}) local tv_main = tabview_create("maintab", {x = 12, y = 5.4}, {x = 0, y = 0})
if PLATFORM == "Android" then if PLATFORM == "Android" then
tv_main:add(tabs.simple_main) tv_main:add(tabs.simple_main)
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()

@ -237,49 +237,37 @@ 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 = {}
for i, v in ipairs(list) do for i, v in ipairs(list) do
if retval ~= "" then
retval = retval ..","
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()
color = mt_color_dark_green
local all_enabled = true
for j = 1, #rawlist, 1 do for j = 1, #rawlist, 1 do
if rawlist[j].modpack == list[i].name and if rawlist[j].modpack == list[i].name and
rawlist[j].enabled ~= true then rawlist[j].enabled ~= true then
all_enabled = false -- Modpack not entirely enabled so showing as grey
color = mt_color_grey
break break
end end
end end
elseif v.is_game_content then
if all_enabled == false then
color = mt_color_grey
else
color = mt_color_dark_green
end
end
if v.typ == "game_mod" then
color = mt_color_blue color = mt_color_blue
else elseif v.enabled then
if v.enabled then
color = mt_color_green color = mt_color_green
end end
retval[#retval + 1] = color
if v.modpack ~= nil or v.typ == "game_mod" then
retval[#retval + 1] = "1"
else
retval[#retval + 1] = "0"
end
retval[#retval + 1] = core.formspec_escape(v.name)
end end
retval = retval .. color return table.concat(retval, ",")
if v.modpack ~= nil then
retval = retval .. " "
end
retval = retval .. v.name
end
return retval
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -425,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

@ -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

@ -19,61 +19,68 @@
local core_developers = { local core_developers = {
"Perttu Ahola (celeron55) <celeron55@gmail.com>", "Perttu Ahola (celeron55) <celeron55@gmail.com>",
"Ryan Kwolek (kwolekr) <kwolekr@minetest.net>",
"PilzAdam <pilzadam@minetest.net>",
"sfan5 <sfan5@live.de>", "sfan5 <sfan5@live.de>",
"kahrl <kahrl@gmx.net>",
"sapier",
"ShadowNinja <shadowninja@minetest.net>", "ShadowNinja <shadowninja@minetest.net>",
"Nathanaël Courant (Nore/Ekdohibs) <nore@mesecons.net>", "Nathanaël Courant (Nore/Ekdohibs) <nore@mesecons.net>",
"Loic Blot (nerzhul/nrz) <loic.blot@unix-experience.fr>", "Loic Blot (nerzhul/nrz) <loic.blot@unix-experience.fr>",
"Matt Gregory (paramat)", "paramat",
"est31 <MTest31@outlook.com>",
"Craig Robbins (Zeno) <craig.d.robbins@gmail.com>", "Craig Robbins (Zeno) <craig.d.robbins@gmail.com>",
"Auke Kok (sofar) <sofar@foo-projects.org>", "Auke Kok (sofar) <sofar@foo-projects.org>",
"Andrew Ward (rubenwardy) <rubenwardy@gmail.com>", "rubenwardy <rw@rubenwardy.com>",
"Krock/SmallJoker <mk939@ymail.com>",
} }
local active_contributors = { local active_contributors = {
"Duane Robertson <duane@duanerobertson.com>", "red-001 <red-001@outlook.ie> [CSM & Menu fixes]",
"SmallJoker <mk939@ymail.com>", "Dániel Juhász (juhdanad) <juhdanad@gmail.com> [Audiovisuals: lighting]",
"Lars Hofhansl <larsh@apache.org>", "numberZero [Audiovisuals: meshgen]",
"Jeija <jeija@mesecons.net>", "Lars Hofhansl <larsh@apache.org> [Occulusion culling, fixes]",
"Gregory Currie (gregorycu)", "Jean-Patrick G (kilbith) <jeanpatrick.guerrero@gmail.com> [Audiovisuals]",
"Sokomine <wegwerf@anarres.dyndns.org>", "Vincent Glize (Dumbeldor) <vincent.glize@live.fr> [CSM]",
"TeTpaAka", "bigfoot547 [CSM]",
"Jean-Patrick G (kilbith) <jeanpatrick.guerrero@gmail.com>", "Rogier <rogier777@gmail.com> [Fixes]",
"Diego Martínez (kaeza) <kaeza@users.sf.net>", "Wuzzy [Audiovisuals]",
"Dániel Juhász (juhdanad) <juhdanad@gmail.com>", "Shara/Ezhh [Settings]",
"Rogier <rogier777@gmail.com>",
} }
local previous_core_developers = { local previous_core_developers = {
"BlockMen", "BlockMen",
"Maciej Kasatkin (RealBadAngel) <maciej.kasatkin@o2.pl>", "Maciej Kasatkin (RealBadAngel) [RIP]",
"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>",
"est31 <MTest31@outlook.com>",
"kahrl <kahrl@gmx.net>",
"Ryan Kwolek (kwolekr) <kwolekr@minetest.net>",
"sapier",
} }
local previous_contributors = { local previous_contributors = {
"Vanessa Ezekowitz (VanessaE) <vanessaezekowitz@gmail.com>", "Gregory Currie (gregorycu) [optimisation]",
"Jurgen Doser (doserj) <jurgen.doser@gmail.com>", "Diego Martínez (kaeza) <kaeza@users.sf.net>",
"MirceaKitsune <mirceakitsune@gmail.com>", "T4im [Profiler]",
"dannydark <the_skeleton_of_a_child@yahoo.co.uk>", "TeTpaAka [Hand overriding, nametag colors]",
"0gb.us <0gb.us@0gb.us>", "HybridDog [Fixes]",
"Guiseppe Bilotta (Oblomov) <guiseppe.bilotta@gmail.com>", "Duane Robertson <duane@duanerobertson.com> [MGValleys]",
"Jonathan Neuschafer <j.neuschaefer@gmx.net>", "neoascetic [OS X Fixes]",
"Nils Dagsson Moskopp (erlehmann) <nils@dieweltistgarnichtso.net>", "TriBlade9 <triblade9@mail.com> [Audiovisuals]",
"Břetislav Štec (t0suj4/TBC_x)", "Jurgen Doser (doserj) <jurgen.doser@gmail.com> [Fixes]",
"Aaron Suen <warr1024@gmail.com>", "MirceaKitsune <mirceakitsune@gmail.com> [Audiovisuals]",
"Constantin Wenger (SpeedProg) <constantin.wenger@googlemail.com>", "Guiseppe Bilotta (Oblomov) <guiseppe.bilotta@gmail.com> [Fixes]",
"matttpt <matttpt@gmail.com>", "matttpt <matttpt@gmail.com> [Fixes]",
"JacobF <queatz@gmail.com>", "Nils Dagsson Moskopp (erlehmann) <nils@dieweltistgarnichtso.net> [Minetest Logo]",
"TriBlade9 <triblade9@mail.com>", "Jeija <jeija@mesecons.net> [HTTP, particles]",
"Zefram <zefram@fysh.org>",
} }
local function buildCreditList(source)
ret = {}
for i = 1, #source do
ret[i] = core.formspec_escape(source[i])
end
return table.concat(ret, ",,")
end
return { return {
name = "credits", name = "credits",
caption = fgettext("Credits"), caption = fgettext("Credits"),
@ -85,15 +92,15 @@ return {
"label[0.5,3.5;http://minetest.net]" .. "label[0.5,3.5;http://minetest.net]" ..
"tablecolumns[color;text]" .. "tablecolumns[color;text]" ..
"tableoptions[background=#00000000;highlight=#00000000;border=false]" .. "tableoptions[background=#00000000;highlight=#00000000;border=false]" ..
"table[3.5,-0.25;8.5,5.8;list_credits;" .. "table[3.5,-0.25;8.5,6.05;list_credits;" ..
"#FFFF00," .. fgettext("Core Developers") .. ",," .. "#FFFF00," .. fgettext("Core Developers") .. ",," ..
table.concat(core_developers, ",,") .. ",,," .. buildCreditList(core_developers) .. ",,," ..
"#FFFF00," .. fgettext("Active Contributors") .. ",," .. "#FFFF00," .. fgettext("Active Contributors") .. ",," ..
table.concat(active_contributors, ",,") .. ",,," .. buildCreditList(active_contributors) .. ",,," ..
"#FFFF00," .. fgettext("Previous Core Developers") ..",," .. "#FFFF00," .. fgettext("Previous Core Developers") ..",," ..
table.concat(previous_core_developers, ",,") .. ",,," .. buildCreditList(previous_core_developers) .. ",,," ..
"#FFFF00," .. fgettext("Previous Contributors") .. ",," .. "#FFFF00," .. fgettext("Previous Contributors") .. ",," ..
table.concat(previous_contributors, ",,") .. "," .. buildCreditList(previous_contributors) .. "," ..
";1]" ";1]"
end end
} }

@ -16,7 +16,7 @@
--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
@ -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
@ -57,7 +57,7 @@ local function singleplayer_refresh_gamebar()
local btnbar = buttonbar_create("game_button_bar", local btnbar = buttonbar_create("game_button_bar",
game_buttonbar_button_handler, game_buttonbar_button_handler,
{x=-0.3,y=5.65}, "horizontal", {x=12.4,y=1.15}) {x=-0.3,y=5.9}, "horizontal", {x=12.4,y=1.15})
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
@ -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,4.95;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,19 +173,56 @@ 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 core.settings:get_bool("enable_server") then
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.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
if selected ~= nil and gamedata.selected_world ~= 0 then if selected ~= nil and gamedata.selected_world ~= 0 then
gamedata.singleplayer = true gamedata.singleplayer = true
core.start() core.start()
@ -166,6 +232,7 @@ local function main_button_handler(this, fields, name, tabdata)
end end
return true return true
end end
end
if fields["world_create"] ~= nil then if fields["world_create"] ~= nil then
local create_world_dlg = create_create_world_dlg(true) local create_world_dlg = create_create_world_dlg(true)
@ -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

@ -28,7 +28,8 @@ local function get_formspec(tabview, name, tabdata)
local retval = local retval =
"label[0.05,-0.25;".. fgettext("Installed Mods:") .. "]" .. "label[0.05,-0.25;".. fgettext("Installed Mods:") .. "]" ..
"textlist[0,0.25;5.1,5;modlist;" .. "tablecolumns[color;tree;text]" ..
"table[0,0.25;5.1,5;modlist;" ..
modmgr.render_modlist(modmgr.global_mods) .. modmgr.render_modlist(modmgr.global_mods) ..
";" .. tabdata.selected_mod .. "]" ";" .. tabdata.selected_mod .. "]"
@ -74,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 = {}
@ -127,8 +128,8 @@ end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
local function handle_buttons(tabview, fields, tabname, tabdata) local function handle_buttons(tabview, fields, tabname, tabdata)
if fields["modlist"] ~= nil then if fields["modlist"] ~= nil then
local event = core.explode_textlist_event(fields["modlist"]) local event = core.explode_table_event(fields["modlist"])
tabdata.selected_mod = event.index tabdata.selected_mod = event.row
return true return true
end end

@ -20,28 +20,48 @@ local function get_formspec(tabview, name, tabdata)
-- Update the cached supported proto info, -- Update the cached supported proto info,
-- it may have changed after a change by the settings menu. -- it may have changed after a change by the settings menu.
common_update_cached_supp_proto() common_update_cached_supp_proto()
local fav_selected = menudata.favorites[tabdata.fav_selected] local fav_selected = nil
if menudata.search_result then
fav_selected = menudata.search_result[tabdata.fav_selected]
else
fav_selected = menudata.favorites[tabdata.fav_selected]
end
if not tabdata.search_for then
tabdata.search_for = ""
end
local retval = local retval =
"label[7.75,-0.15;" .. fgettext("Address / Port") .. "]" .. -- Search
"label[7.75,1.05;" .. fgettext("Name / Password") .. "]" .. "field[0.15,0.35;6.05,0.27;te_search;;"..core.formspec_escape(tabdata.search_for).."]"..
"field[8,0.75;3.3,0.5;te_address;;" .. "button[5.8,0.1;2,0.1;btn_mp_search;" .. fgettext("Search") .. "]" ..
core.formspec_escape(core.setting_get("address")) .. "]" ..
"field[11.15,0.75;1.4,0.5;te_port;;" .. -- Address / Port
core.formspec_escape(core.setting_get("remote_port")) .. "]" .. "label[7.75,-0.25;" .. fgettext("Address / Port") .. "]" ..
"button[10.1,4.9;2,0.5;btn_mp_connect;" .. fgettext("Connect") .. "]" .. "field[8,0.65;3.25,0.5;te_address;;" ..
"field[8,1.95;2.95,0.5;te_name;;" .. core.formspec_escape(core.settings:get("address")) .. "]" ..
core.formspec_escape(core.setting_get("name")) .. "]" .. "field[11.1,0.65;1.4,0.5;te_port;;" ..
"pwdfield[10.78,1.95;1.77,0.5;te_pwd;]" .. core.formspec_escape(core.settings:get("remote_port")) .. "]" ..
"box[7.73,2.35;4.3,2.28;#999999]"
-- Name / Password
"label[7.75,0.95;" .. fgettext("Name / Password") .. "]" ..
"field[8,1.85;2.9,0.5;te_name;;" ..
core.formspec_escape(core.settings:get("name")) .. "]" ..
"pwdfield[10.73,1.85;1.77,0.5;te_pwd;]" ..
-- Description Background
"box[7.73,2.25;4.25,2.6;#999999]"..
-- Connect
"button[10.1,5.15;2,0.5;btn_mp_connect;" .. fgettext("Connect") .. "]"
if tabdata.fav_selected and fav_selected then if tabdata.fav_selected and fav_selected then
if gamedata.fav then if gamedata.fav then
retval = retval .. "button[7.85,4.9;2.3,0.5;btn_delete_favorite;" .. retval = retval .. "button[7.75,5.15;2.3,0.5;btn_delete_favorite;" ..
fgettext("Del. Favorite") .. "]" fgettext("Del. Favorite") .. "]"
end end
if fav_selected.description then if fav_selected.description then
retval = retval .. "textarea[8.1,2.4;4.26,2.6;;" .. retval = retval .. "textarea[8.1,2.3;4.23,2.9;;" ..
core.formspec_escape((gamedata.serverdescription or ""), true) .. ";]" core.formspec_escape((gamedata.serverdescription or ""), true) .. ";]"
end end
end end
@ -49,6 +69,7 @@ local function get_formspec(tabview, name, tabdata)
--favourites --favourites
retval = retval .. "tablecolumns[" .. retval = retval .. "tablecolumns[" ..
image_column(fgettext("Favorite"), "favorite") .. ";" .. image_column(fgettext("Favorite"), "favorite") .. ";" ..
image_column(fgettext("Ping")) .. ",padding=0.25;" ..
"color,span=3;" .. "color,span=3;" ..
"text,align=right;" .. -- clients "text,align=right;" .. -- clients
"text,align=center,padding=0.25;" .. -- "/" "text,align=center,padding=0.25;" .. -- "/"
@ -58,9 +79,27 @@ local function get_formspec(tabview, name, tabdata)
image_column(fgettext("PvP enabled"), "pvp") .. ",padding=0.25;" .. image_column(fgettext("PvP enabled"), "pvp") .. ",padding=0.25;" ..
"color,span=1;" .. "color,span=1;" ..
"text,padding=1]" .. "text,padding=1]" ..
"table[-0.15,-0.1;7.75,5.5;favourites;" "table[-0.15,0.6;7.75,5.15;favourites;"
if #menudata.favorites > 0 then if menudata.search_result then
for i = 1, #menudata.search_result do
local favs = core.get_favorites("local")
local server = menudata.search_result[i]
for fav_id = 1, #favs do
if server.address == favs[fav_id].address and
server.port == favs[fav_id].port then
server.is_favorite = true
end
end
if i ~= 1 then
retval = retval .. ","
end
retval = retval .. render_serverlist_row(server, server.is_favorite)
end
elseif #menudata.favorites > 0 then
local favs = core.get_favorites("local") local favs = core.get_favorites("local")
if #favs > 0 then if #favs > 0 then
for i = 1, #favs do for i = 1, #favs do
@ -75,9 +114,9 @@ local function get_formspec(tabview, name, tabdata)
end end
end end
end end
retval = retval .. render_favorite(menudata.favorites[1], (#favs > 0)) retval = retval .. render_serverlist_row(menudata.favorites[1], (#favs > 0))
for i = 2, #menudata.favorites do for i = 2, #menudata.favorites do
retval = retval .. "," .. render_favorite(menudata.favorites[i], (i <= #favs)) retval = retval .. "," .. render_serverlist_row(menudata.favorites[i], (i <= #favs))
end end
end end
@ -92,17 +131,19 @@ end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
local function main_button_handler(tabview, fields, name, tabdata) local function main_button_handler(tabview, fields, name, tabdata)
local serverlist = menudata.search_result or menudata.favorites
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
local event = core.explode_table_event(fields.favourites) local event = core.explode_table_event(fields.favourites)
local fav = menudata.favorites[event.row] local fav = serverlist[event.row]
if event.type == "DCL" then if event.type == "DCL" then
if event.row <= #menudata.favorites then if event.row <= #serverlist then
if menudata.favorites_is_public and if menudata.favorites_is_public and
not is_server_protocol_compat_or_error( not is_server_protocol_compat_or_error(
fav.proto_min, fav.proto_max) then fav.proto_min, fav.proto_max) then
@ -122,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
@ -131,7 +172,7 @@ local function main_button_handler(tabview, fields, name, tabdata)
end end
if event.type == "CHG" then if event.type == "CHG" then
if event.row <= #menudata.favorites then if event.row <= #serverlist then
gamedata.fav = false gamedata.fav = false
local favs = core.get_favorites("local") local favs = core.get_favorites("local")
local address = fav.address local address = fav.address
@ -146,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
@ -157,7 +198,7 @@ local function main_button_handler(tabview, fields, name, tabdata)
if fields.key_up or fields.key_down then if fields.key_up or fields.key_down then
local fav_idx = core.get_table_index("favourites") local fav_idx = core.get_table_index("favourites")
local fav = menudata.favorites[fav_idx] local fav = serverlist[fav_idx]
if fav_idx then if fav_idx then
if fields.key_up and fav_idx > 1 then if fields.key_up and fav_idx > 1 then
@ -176,10 +217,10 @@ local function main_button_handler(tabview, fields, name, tabdata)
local address = fav.address local address = fav.address
local port = fav.port local port = fav.port
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
@ -194,21 +235,81 @@ 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.btn_mp_connect or fields.key_enter) and fields.te_address and fields.te_port then if fields.btn_mp_search or fields.key_enter_field == "te_search" then
tabdata.fav_selected = 1
local input = fields.te_search:lower()
tabdata.search_for = fields.te_search
if #menudata.favorites < 2 then
return true
end
menudata.search_result = {}
-- setup the keyword list
local keywords = {}
for word in input:gmatch("%S+") do
table.insert(keywords, word)
end
if #keywords == 0 then
menudata.search_result = nil
return true
end
-- Search the serverlist
local search_result = {}
for i = 1, #menudata.favorites do
local server = menudata.favorites[i]
local found = 0
for k = 1, #keywords do
local keyword = keywords[k]
if server.name then
local name = server.name:lower()
local _, count = name:gsub(keyword, keyword)
found = found + count * 4
end
if server.description then
local desc = server.description:lower()
local _, count = desc:gsub(keyword, keyword)
found = found + count * 2
end
end
if found > 0 then
local points = (#menudata.favorites - i) / 5 + found
server.points = points
table.insert(search_result, server)
end
end
if #search_result > 0 then
table.sort(search_result, function(a, b)
return a.points > b.points
end)
menudata.search_result = search_result
local first_server = search_result[1]
core.settings:set("address", first_server.address)
core.settings:set("remote_port", first_server.port)
end
return true
end
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
gamedata.port = fields.te_port gamedata.port = fields.te_port
gamedata.selected_world = 0 gamedata.selected_world = 0
local fav_idx = core.get_table_index("favourites") local fav_idx = core.get_table_index("favourites")
local fav = menudata.favorites[fav_idx] local fav = serverlist[fav_idx]
if fav_idx and fav_idx <= #menudata.favorites and if fav_idx and fav_idx <= #serverlist and
fav.address == fields.te_address and fav.address == fields.te_address and
fav.port == fields.te_port then fav.port == fields.te_port then
@ -225,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
@ -241,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

@ -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,4.95;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
}

@ -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 ..
@ -209,38 +213,38 @@ local function formspec(tabview, name, tabdata)
.. fgettext("Reset singleplayer world") .. "]" .. fgettext("Reset singleplayer world") .. "]"
else else
tab_string = tab_string .. tab_string = tab_string ..
"button[8,4.75;3.75,0.5;btn_change_keys;" "button[8,4.85;3.75,0.5;btn_change_keys;"
.. fgettext("Change keys") .. "]" .. fgettext("Change keys") .. "]"
end end
tab_string = tab_string .. tab_string = tab_string ..
"button[0,4.75;3.75,0.5;btn_advanced_settings;" "button[0,4.85;3.75,0.5;btn_advanced_settings;"
.. 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

@ -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;]"
@ -43,6 +43,7 @@ local function get_formspec(tabview, name, tabdata)
retval = retval .. "tablecolumns[" .. retval = retval .. "tablecolumns[" ..
image_column(fgettext("Favorite"), "favorite") .. ";" .. image_column(fgettext("Favorite"), "favorite") .. ";" ..
image_column(fgettext("Ping"), "") .. ",padding=0.25;" ..
"color,span=3;" .. "color,span=3;" ..
"text,align=right;" .. -- clients "text,align=right;" .. -- clients
"text,align=center,padding=0.25;" .. -- "/" "text,align=center,padding=0.25;" .. -- "/"
@ -70,9 +71,9 @@ local function get_formspec(tabview, name, tabdata)
end end
end end
end end
retval = retval .. render_favorite(menudata.favorites[1], (#favs > 0)) retval = retval .. render_serverlist_row(menudata.favorites[1], (#favs > 0))
for i = 2, #menudata.favorites do for i = 2, #menudata.favorites do
retval = retval .. "," .. render_favorite(menudata.favorites[i], (i <= #favs)) retval = retval .. "," .. render_serverlist_row(menudata.favorites[i], (i <= #favs))
end end
end end
@ -88,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") .. "]" ..
@ -127,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
@ -144,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
@ -185,8 +186,8 @@ 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

@ -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

@ -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()

@ -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

@ -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 {

@ -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

@ -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

@ -107,6 +107,12 @@ continuous_forward (Continuous forward) bool false
# Enable Joysticks # Enable Joysticks
enable_joysticks (Enable Joysticks) bool false enable_joysticks (Enable Joysticks) bool false
# The identifier of the joystick to use
joystick_id (Joystick ID) int 0
# The type of joystick
joystick_type (Joystick Type) enum auto auto,generic,xbox
# The time in seconds it takes between repeated events # The time in seconds it takes between repeated events
# when holding down a joystick button combination. # when holding down a joystick button combination.
repeat_joystick_button_time (Joystick button repetition interval) float 0.17 repeat_joystick_button_time (Joystick button repetition interval) float 0.17
@ -156,6 +162,10 @@ keymap_chat (Chat key) key KEY_KEY_T
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_cmd (Command key) key / keymap_cmd (Command key) key /
# Key for opening the chat window to type local commands.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_cmd_local (Command key) key .
# Key for opening the chat console. # Key for opening the chat console.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keyman_console (Console key) key KEY_F10 keyman_console (Console key) key KEY_F10
@ -176,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
@ -196,6 +226,10 @@ keymap_screenshot (Screenshot) key KEY_F12
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_drop (Drop item key) key KEY_KEY_Q keymap_drop (Drop item key) key KEY_KEY_Q
# Key to use view zoom when possible.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_zoom (View zoom key) key KEY_KEY_Z
# Key for toggling the display of the HUD. # Key for toggling the display of the HUD.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_toggle_hud (HUD toggle key) key KEY_F1 keymap_toggle_hud (HUD toggle key) key KEY_F1
@ -204,6 +238,10 @@ keymap_toggle_hud (HUD toggle key) key KEY_F1
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_toggle_chat (Chat toggle key) key KEY_F2 keymap_toggle_chat (Chat toggle key) key KEY_F2
# Key for toggling the display of the large chat console.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_console (Large chat console key) key KEY_F10
# Key for toggling the display of the fog. # Key for toggling the display of the fog.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_toggle_force_fog_off (Fog toggle key) key KEY_F3 keymap_toggle_force_fog_off (Fog toggle key) key KEY_F3
@ -264,12 +302,19 @@ show_entity_selectionbox (Show entity selection boxes) bool true
# when connecting to the server. # when connecting to the server.
enable_remote_media_server (Connect to external media server) bool true enable_remote_media_server (Connect to external media server) bool true
# Enable Lua modding support on client.
# This support is experimental and API can change.
enable_client_modding (Client modding) bool false
# URL to the server list displayed in the Multiplayer Tab. # URL to the server list displayed in the Multiplayer Tab.
serverlist_url (Serverlist URL) string servers.minetest.net 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]
@ -302,7 +347,10 @@ 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.
enable_particles (Digging particles) bool true
[***Filtering] [***Filtering]
@ -337,12 +385,20 @@ texture_min_size (Minimum texture size for filters) int 64
# when set to higher number than 0. # when set to higher number than 0.
fsaa (FSAA) enum 0 0,1,2,4,8,16 fsaa (FSAA) enum 0 0,1,2,4,8,16
# Undersampling is similar to using lower screen resolution, but it applies
# to the game world only, keeping the GUI intact.
# It should give significant performance boost at the cost of less detailed image.
undersampling (Undersampling) enum 0 0,2,3,4
[***Shaders] [***Shaders]
# Shaders allow advanced visual effects and may increase performance on some video cards. # Shaders allow advanced visual effects and may increase performance on some video cards.
# Thy only work with the OpenGL video backend. # This only works with the OpenGL video backend.
enable_shaders (Shaders) bool true enable_shaders (Shaders) bool true
# Path to shader directory. If no path is defined, default location will be used.
shader_path (Shader path) path
[****Tone Mapping] [****Tone Mapping]
# Enables filmic tone mapping # Enables filmic tone mapping
@ -377,7 +433,7 @@ enable_parallax_occlusion (Parallax occlusion) bool false
parallax_occlusion_mode (Parallax occlusion mode) int 1 0 1 parallax_occlusion_mode (Parallax occlusion mode) int 1 0 1
# Strength of parallax. # Strength of parallax.
3d_parallax_strength (Parallax occlusion strength) float 0.025 3d_paralax_strength (Parallax occlusion strength) float 0.025
# Number of parallax occlusion iterations. # Number of parallax occlusion iterations.
parallax_occlusion_iterations (Parallax occlusion iterations) int 4 parallax_occlusion_iterations (Parallax occlusion iterations) int 4
@ -426,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
@ -440,11 +499,11 @@ fov (Field of view) int 72 30 160
# Field of view while zooming in degrees. # Field of view while zooming in degrees.
# This requires the "zoom" privilege on the server. # This requires the "zoom" privilege on the server.
zoom_fov (Field of view for zoom) int 15 15 160 zoom_fov (Field of view for zoom) int 15 7 160
# Adjust the gamma encoding for the light tables. Lower numbers are brighter. # Adjust the gamma encoding for the light tables. Higher numbers are brighter.
# This setting is for the client only and is ignored by the server. # This setting is for the client only and is ignored by the server.
display_gamma (Gamma) float 1.8 1.0 3.0 display_gamma (Gamma) float 2.2 1.0 3.0
# Path to texture directory. All textures are first searched from here. # Path to texture directory. All textures are first searched from here.
texture_path (Texture path) path texture_path (Texture path) path
@ -459,13 +518,13 @@ 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
# Multiplier for view bobbing. # Enable view bobbing and amount of 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) float 1.0 view_bobbing_amount (View bobbing factor) float 1.0
# Multiplier for fall bobbing. # Multiplier for fall 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.
fall_bobbing_amount (Fall bobbing) float 0.0 fall_bobbing_amount (Fall bobbing factor) float 0.0
# 3D support. # 3D support.
# Currently supported: # Currently supported:
@ -477,6 +536,9 @@ fall_bobbing_amount (Fall bobbing) float 0.0
# - pageflip: quadbuffer based 3d. # - pageflip: quadbuffer based 3d.
3d_mode (3D mode) enum none none,anaglyph,interlaced,topbottom,sidebyside,pageflip 3d_mode (3D mode) enum none none,anaglyph,interlaced,topbottom,sidebyside,pageflip
# In-game chat console height, between 0.1 (10%) and 1.0 (100%).
console_height (Console height) float 1.0 0.1 1.0
# In-game chat console background color (R,G,B). # In-game chat console background color (R,G,B).
console_color (Console color) string (0,0,0) console_color (Console color) string (0,0,0)
@ -502,9 +564,21 @@ desynchronize_mapblock_texture_animation (Desynchronize block animation) bool tr
# Useful if there's something to be displayed right or left of hotbar. # Useful if there's something to be displayed right or left of hotbar.
hud_hotbar_max_width (Maximum hotbar width) float 1.0 hud_hotbar_max_width (Maximum hotbar width) float 1.0
# Modifies the size of the hudbar elements.
hud_scaling (HUD scale factor) float 1.0
# Enables caching of facedir rotated meshes. # Enables caching of facedir rotated meshes.
enable_mesh_cache (Mesh cache) bool false enable_mesh_cache (Mesh cache) bool false
# Delay between mesh updates on the client in ms. Increasing this will slow
# down the rate of mesh updates, thus reducing jitter on slower clients.
mesh_generation_interval (Mapblock mesh generation delay) int 0 0 50
# Size of the MapBlock cache of the mesh generator. Increasing this will
# increase the cache hit %, reducing the data being copied from the main
# thread, thus reducing jitter.
meshgen_block_cache_size (Mapblock mesh generator's MapBlock cache size MB) int 20 0 1000
# Enables minimap. # Enables minimap.
enable_minimap (Minimap) bool true enable_minimap (Minimap) bool true
@ -528,9 +602,16 @@ ambient_occlusion_gamma (Ambient occlusion gamma) float 2.2 0.25 4.0
# Enables animation of inventory items. # Enables animation of inventory items.
inventory_items_animations (Inventory items animations) bool false inventory_items_animations (Inventory items animations) bool false
# Android systems only: Tries to create inventory textures from meshes
# when no supported render was found.
inventory_image_hack (Inventory image hack) bool false
# Fraction of the visible distance at which fog starts to be rendered # Fraction of the visible distance at which fog starts to be rendered
fog_start (Fog Start) float 0.4 0.0 0.99 fog_start (Fog Start) float 0.4 0.0 0.99
# Makes all liquids opaque
opaque_water (Opaque liquids) bool false
[**Menus] [**Menus]
# Use a cloud animation for the main menu background. # Use a cloud animation for the main menu background.
@ -597,6 +678,10 @@ screenshot_quality (Screenshot quality) int 0 0 100
# Adjust dpi configuration to your screen (non X11/Android only) e.g. for 4k screens. # Adjust dpi configuration to your screen (non X11/Android only) e.g. for 4k screens.
screen_dpi (DPI) int 72 screen_dpi (DPI) int 72
# Windows systems only: Start Minetest with the command line window in the background.
# Contains the same information as the file debug.txt (default name).
enable_console (Enable console window) bool false
[*Sound] [*Sound]
enable_sound (Sound) bool true enable_sound (Sound) bool true
@ -703,9 +788,15 @@ map-dir (Map directory) path
# Setting it to -1 disables the feature. # Setting it to -1 disables the feature.
item_entity_ttl (Item entity TTL) int 900 item_entity_ttl (Item entity TTL) int 900
# If enabled, show the server status message on player connection.
show_statusline_on_connect (Status message on connection) bool true
# Enable players getting damage and dying. # Enable players getting damage and dying.
enable_damage (Damage) bool false enable_damage (Damage) bool false
# Enable creative mode for new created maps.
creative_mode (Creative) bool false
# A chosen map seed for a new map, leave empty for random. # A chosen map seed for a new map, leave empty for random.
# Will be overridden when creating a new world in the main menu. # Will be overridden when creating a new world in the main menu.
fixed_map_seed (Fixed map seed) string fixed_map_seed (Fixed map seed) string
@ -758,7 +849,7 @@ active_object_send_range_blocks (Active object send range) int 3
# How large area of blocks are subject to the active block stuff, stated in mapblocks (16 nodes). # How large area of blocks are subject to the active block stuff, stated in mapblocks (16 nodes).
# In active blocks objects are loaded and ABMs run. # In active blocks objects are loaded and ABMs run.
active_block_range (Active block range) int 2 active_block_range (Active block range) int 3
# From how far blocks are sent to clients, stated in mapblocks (16 nodes). # From how far blocks are sent to clients, stated in mapblocks (16 nodes).
max_block_send_distance (Max block send distance) int 10 max_block_send_distance (Max block send distance) int 10
@ -793,9 +884,8 @@ movement_acceleration_fast (Fast mode acceleration) float 10
movement_speed_walk (Walking speed) float 4 movement_speed_walk (Walking speed) float 4
movement_speed_crouch (Crouch speed) float 1.35 movement_speed_crouch (Crouch speed) float 1.35
movement_speed_fast (Fast mode speed) float 20 movement_speed_fast (Fast mode speed) float 20
movement_speed_climb (Climbing speed) float 2 movement_speed_climb (Climbing speed) float 3
movement_speed_jump (Jumping speed) float 6.5 movement_speed_jump (Jumping speed) float 6.5
movement_speed_descend (Descending speed) float 6
movement_liquid_fluidity (Liquid fluidity) float 1 movement_liquid_fluidity (Liquid fluidity) float 1
movement_liquid_fluidity_smooth (Liquid fluidity smoothing) float 0.5 movement_liquid_fluidity_smooth (Liquid fluidity smoothing) float 0.5
movement_liquid_sink (Liquid sink) float 10 movement_liquid_sink (Liquid sink) float 10
@ -834,7 +924,7 @@ active_block_mgmt_interval (Active Block Management interval) float 2.0
abm_interval (Active Block Modifier interval) float 1.0 abm_interval (Active Block Modifier interval) float 1.0
# Length of time between NodeTimer execution cycles # Length of time between NodeTimer execution cycles
nodetimer_interval (NodeTimer interval) float 1.0 nodetimer_interval (NodeTimer interval) float 0.2
# If enabled, invalid world data won't cause the server to shut down. # If enabled, invalid world data won't cause the server to shut down.
# Only enable this if you know what you are doing. # Only enable this if you know what you are doing.
@ -858,6 +948,12 @@ liquid_update (Liquid update tick) float 1.0
# Stated in mapblocks (16 nodes) # Stated in mapblocks (16 nodes)
block_send_optimize_distance (block send optimize distance) int 4 2 block_send_optimize_distance (block send optimize distance) int 4 2
# If enabled the server will perform map block occlusion culling based on
# on the eye position of the player. This can reduce the number of blocks
# sent to the client 50-80%. The client will not longer receive most invisible
# so that the utility of noclip mode is reduced.
server_side_occlusion_culling (Server side occlusion culling) bool true
[*Mapgen] [*Mapgen]
# Name of map generator to be used when creating a new world. # Name of map generator to be used when creating a new world.
@ -870,13 +966,10 @@ water_level (Water level) int 1
# From how far blocks are generated for clients, stated in mapblocks (16 nodes). # From how far blocks are generated for clients, stated in mapblocks (16 nodes).
max_block_generate_distance (Max block generate distance) int 6 max_block_generate_distance (Max block generate distance) int 6
# Where the map generator stops. # Limit of map generation, in nodes, in all 6 directions from (0, 0, 0).
# Please note: # Only mapchunks completely within the mapgen limit are generated.
# - Limited to 31000 (setting above has no effect) # Value is stored per-world.
# - The map generator works in groups of 80x80x80 nodes (5x5x5 MapBlocks). mapgen_limit (Map generation limit) int 31000 0 31000
# - Those groups have an offset of -32, -32 nodes from the origin.
# - Only groups which are within the map_generation_limit are generated
map_generation_limit (Map generation limit) int 31000 0 31000
# Global map generation attributes. # Global map generation attributes.
# In Mapgen v6 the 'decorations' flag controls all decorations except trees # In Mapgen v6 the 'decorations' flag controls all decorations except trees
@ -909,23 +1002,63 @@ emergequeue_limit_generate (Limit of emerge queues to generate) int 32
# at the cost of slightly buggy caves. # at the cost of slightly buggy caves.
num_emerge_threads (Number of emerge threads) int 1 num_emerge_threads (Number of emerge threads) int 1
# Noise parameters for biome API temperature, humidity and biome blend. [***Biome API temperature and humidity noise parameters]
mg_biome_np_heat (Mapgen biome heat noise parameters) noise_params 50, 50, (750, 750, 750), 5349, 3, 0.5, 2.0
mg_biome_np_heat_blend (Mapgen heat blend noise parameters) noise_params 0, 1.5, (8, 8, 8), 13, 2, 1.0, 2.0 # Temperature variation for biomes.
mg_biome_np_humidity (Mapgen biome humidity noise parameters) noise_params 50, 50, (750, 750, 750), 842, 3, 0.5, 2.0 mg_biome_np_heat (Heat noise) noise_params 50, 50, (1000, 1000, 1000), 5349, 3, 0.5, 2.0
mg_biome_np_humidity_blend (Mapgen biome humidity blend noise parameters) noise_params 0, 1.5, (8, 8, 8), 90003, 2, 1.0, 2.0
# Small-scale temperature variation for blending biomes on borders.
mg_biome_np_heat_blend (Heat blend noise) noise_params 0, 1.5, (8, 8, 8), 13, 2, 1.0, 2.0
# Humidity variation for biomes.
mg_biome_np_humidity (Humidity noise) noise_params 50, 50, (1000, 1000, 1000), 842, 3, 0.5, 2.0
# Small-scale humidity variation for blending biomes on borders.
mg_biome_np_humidity_blend (Humidity blend noise) noise_params 0, 1.5, (8, 8, 8), 90003, 2, 1.0, 2.0
[***Mapgen v5] [***Mapgen v5]
# Controls width of tunnels, a smaller value creates wider tunnels. # Map generation attributes specific to Mapgen v5.
mgv5_cave_width (Mapgen v5 cave width) float 0.125 # Flags that are not specified in the flag string are not modified from the default.
# Flags starting with 'no' are used to explicitly disable them.
mgv5_spflags (Mapgen v5 specific flags) flags caverns caverns,nocaverns
# Controls width of tunnels, a smaller value creates wider tunnels.
mgv5_cave_width (Cave width) float 0.125
# Y-level of cavern upper limit.
mgv5_cavern_limit (Cavern limit) int -256
# Y-distance over which caverns expand to full size.
mgv5_cavern_taper (Cavern taper) int 256
# Defines full size of caverns, smaller values create larger caverns.
mgv5_cavern_threshold (Cavern threshold) float 0.7
# Variation of biome filler depth.
mgv5_np_filler_depth (Filler depth noise) noise_params 0, 1, (150, 150, 150), 261, 4, 0.7, 2.0
# Variation of terrain vertical scale.
# When noise is < -0.55 terrain is near-flat.
mgv5_np_factor (Factor noise) noise_params 0, 1, (250, 250, 250), 920381, 3, 0.45, 2.0
# Y-level of average terrain surface.
mgv5_np_height (Height noise) noise_params 0, 10, (250, 250, 250), 84174, 4, 0.5, 2.0
# First of 2 3D noises that together define tunnels.
mgv5_np_cave1 (Cave1 noise) noise_params 0, 12, (50, 50, 50), 52534, 4, 0.5, 2.0
# Second of 2 3D noises that together define tunnels.
mgv5_np_cave2 (Cave2 noise) noise_params 0, 12, (50, 50, 50), 10325, 4, 0.5, 2.0
# 3D noise defining giant caverns.
mgv5_np_cavern (Cavern noise) noise_params 0, 1, (384, 128, 384), 723, 5, 0.63, 2.0
mgv5_np_filler_depth (Mapgen v5 filler depth noise parameters) noise_params 0, 1, (150, 150, 150), 261, 4, 0.7, 2.0
mgv5_np_factor (Mapgen v5 factor noise parameters) noise_params 0, 1, (250, 250, 250), 920381, 3, 0.45, 2.0
mgv5_np_height (Mapgen v5 height noise parameters) noise_params 0, 10, (250, 250, 250), 84174, 4, 0.5, 2.0
mgv5_np_cave1 (Mapgen v5 cave1 noise parameters) noise_params 0, 12, (50, 50, 50), 52534, 4, 0.5, 2.0
mgv5_np_cave2 (Mapgen v5 cave2 noise parameters) noise_params 0, 12, (50, 50, 50), 10325, 4, 0.5, 2.0
# TODO # TODO
# Noise parameters in group format, unsupported by advanced settings
# menu but settable in minetest.conf.
# See documentation of noise parameter formats in minetest.conf.example.
# 3D noise defining terrain.
#mgv5_np_ground = { #mgv5_np_ground = {
# offset = 0 # offset = 0
# scale = 40 # scale = 40
@ -940,27 +1073,52 @@ mgv5_np_cave2 (Mapgen v5 cave2 noise parameters) noise_params 0, 12, (50, 50, 50
[***Mapgen v6] [***Mapgen v6]
# Map generation attributes specific to Mapgen v6. # Map generation attributes specific to Mapgen v6.
# When snowbiomes are enabled jungles are automatically enabled, the 'jungles' flag is ignored. # The 'snowbiomes' flag enables the new 5 biome system.
# When the new biome system is enabled jungles are automatically enabled and
# the 'jungles' flag is ignored.
# Flags that are not specified in the flag string are not modified from the default. # Flags that are not specified in the flag string are not modified from the default.
# Flags starting with 'no' are used to explicitly disable them. # Flags starting with 'no' are used to explicitly disable them.
mgv6_spflags (Mapgen v6 flags) flags jungles,biomeblend,mudflow,snowbiomes,trees jungles,biomeblend,mudflow,snowbiomes,flat,trees,nojungles,nobiomeblend,nomudflow,nosnowbiomes,noflat,notrees mgv6_spflags (Mapgen v6 specific flags) flags jungles,biomeblend,mudflow,snowbiomes,trees jungles,biomeblend,mudflow,snowbiomes,flat,trees,nojungles,nobiomeblend,nomudflow,nosnowbiomes,noflat,notrees
# Controls size of deserts and beaches in Mapgen v6. # Deserts occur when np_biome exceeds this value.
# When snowbiomes are enabled 'mgv6_freq_desert' is ignored. # When the new biome system is enabled, this is ignored.
mgv6_freq_desert (Mapgen v6 desert frequency) float 0.45 mgv6_freq_desert (Desert noise threshold) float 0.45
mgv6_freq_beach (Mapgen v6 beach frequency) float 0.15
mgv6_np_terrain_base (Mapgen v6 terrain base noise parameters) noise_params -4, 20, (250, 250, 250), 82341, 5, 0.6, 2.0 # Sandy beaches occur when np_beach exceeds this value.
mgv6_np_terrain_higher (Mapgen v6 terrain altitude noise parameters) noise_params 20, 16, (500, 500, 500), 85039, 5, 0.6, 2.0 mgv6_freq_beach (Beach noise threshold) float 0.15
mgv6_np_steepness (Mapgen v6 steepness noise parameters) noise_params 0.85, 0.5, (125, 125, 125), -932, 5, 0.7, 2.0
mgv6_np_height_select (Mapgen v6 height select noise parameters) noise_params 0.5, 1, (250, 250, 250), 4213, 5, 0.69, 2.0 # Y-level of lower terrain and lakebeds.
mgv6_np_mud (Mapgen v6 mud noise parameters) noise_params 4, 2, (200, 200, 200), 91013, 3, 0.55, 2.0 mgv6_np_terrain_base (Terrain base noise) noise_params -4, 20, (250, 250, 250), 82341, 5, 0.6, 2.0
mgv6_np_beach (Mapgen v6 beach noise parameters) noise_params 0, 1, (250, 250, 250), 59420, 3, 0.50, 2.0
mgv6_np_biome (Mapgen v6 biome noise parameters) noise_params 0, 1, (500, 500, 500), 9130, 3, 0.50, 2.0 # Y-level of higher (cliff-top) terrain.
mgv6_np_cave (Mapgen v6 cave noise parameters) noise_params 6, 6, (250, 250, 250), 34329, 3, 0.50, 2.0 mgv6_np_terrain_higher (Terrain higher noise) noise_params 20, 16, (500, 500, 500), 85039, 5, 0.6, 2.0
mgv6_np_humidity (Mapgen v6 humidity noise parameters) noise_params 0.5, 0.5, (500, 500, 500), 72384, 3, 0.50, 2.0
mgv6_np_trees (Mapgen v6 trees noise parameters) noise_params 0, 1, (125, 125, 125), 2, 4, 0.66, 2.0 # Varies steepness of cliffs.
mgv6_np_apple_trees (Mapgen v6 apple trees noise parameters) noise_params 0, 1, (100, 100, 100), 342902, 3, 0.45, 2.0 mgv6_np_steepness (Steepness noise) noise_params 0.85, 0.5, (125, 125, 125), -932, 5, 0.7, 2.0
# Defines areas of 'terrain_higher' (cliff-top terrain).
mgv6_np_height_select (Height select noise) noise_params 0.5, 1, (250, 250, 250), 4213, 5, 0.69, 2.0
# Varies depth of biome surface nodes.
mgv6_np_mud (Mud noise) noise_params 4, 2, (200, 200, 200), 91013, 3, 0.55, 2.0
# Defines areas with sandy beaches.
mgv6_np_beach (Beach noise) noise_params 0, 1, (250, 250, 250), 59420, 3, 0.50, 2.0
# Temperature variation for biomes.
mgv6_np_biome (Biome noise) noise_params 0, 1, (500, 500, 500), 9130, 3, 0.50, 2.0
# Variation of number of caves.
mgv6_np_cave (Cave noise) noise_params 6, 6, (250, 250, 250), 34329, 3, 0.50, 2.0
# Humidity variation for biomes.
mgv6_np_humidity (Humidity noise) noise_params 0.5, 0.5, (500, 500, 500), 72384, 3, 0.50, 2.0
# Defines tree areas and tree density.
mgv6_np_trees (Trees noise) noise_params 0, 1, (125, 125, 125), 2, 4, 0.66, 2.0
# Defines areas where trees have apples.
mgv6_np_apple_trees (Apple trees noise) noise_params 0, 1, (100, 100, 100), 342902, 3, 0.45, 2.0
[***Mapgen v7] [***Mapgen v7]
@ -969,37 +1127,77 @@ mgv6_np_apple_trees (Mapgen v6 apple trees noise parameters) noise_params 0, 1,
# Floatlands are currently experimental and subject to change. # Floatlands are currently experimental and subject to change.
# Flags that are not specified in the flag string are not modified from the default. # Flags that are not specified in the flag string are not modified from the default.
# Flags starting with 'no' are used to explicitly disable them. # Flags starting with 'no' are used to explicitly disable them.
mgv7_spflags (Mapgen v7 flags) flags mountains,ridges mountains,ridges,floatlands,nomountains,noridges,nofloatlands mgv7_spflags (Mapgen v7 specific flags) flags mountains,ridges,nofloatlands,caverns mountains,ridges,floatlands,caverns,nomountains,noridges,nofloatlands,nocaverns
# Controls width of tunnels, a smaller value creates wider tunnels. # Controls width of tunnels, a smaller value creates wider tunnels.
mgv7_cave_width (Mapgen v7 cave width) float 0.09 mgv7_cave_width (Cave width) float 0.09
# Controls the density of floatland mountain terrain. # Controls the density of floatland mountain terrain.
# Is an offset added to the 'np_mountain' noise value. # Is an offset added to the 'np_mountain' noise value.
mgv7_float_mount_density (Mapgen v7 floatland mountain density) float 0.6 mgv7_float_mount_density (Floatland mountain density) float 0.6
# Typical maximum height, above and below midpoint, of floatland mountain terrain. # Typical maximum height, above and below midpoint, of floatland mountain terrain.
mgv7_float_mount_height (Mapgen v7 floatland mountain height) float 128.0 mgv7_float_mount_height (Floatland mountain height) float 128.0
# Y-level of floatland midpoint and lake surface. # Y-level of floatland midpoint and lake surface.
mgv7_floatland_level (Mapgen v7 floatland level) int 1280 mgv7_floatland_level (Floatland level) int 1280
# Y-level to which floatland shadows extend. # Y-level to which floatland shadows extend.
mgv7_shadow_limit (Mapgen v7 shadow limit) int 1024 mgv7_shadow_limit (Shadow limit) int 1024
mgv7_np_terrain_base (Mapgen v7 terrain base noise parameters) noise_params 4, 70, (600, 600, 600), 82341, 5, 0.6, 2.0 # Y-level of cavern upper limit.
mgv7_np_terrain_alt (Mapgen v7 terrain altitude noise parameters) noise_params 4, 25, (600, 600, 600), 5934, 5, 0.6, 2.0 mgv7_cavern_limit (Cavern limit) int -256
mgv7_np_terrain_persist (Mapgen v7 terrain persistation noise parameters) noise_params 0.6, 0.1, (2000, 2000, 2000), 539, 3, 0.6, 2.0
mgv7_np_height_select (Mapgen v7 height select noise parameters) noise_params -8, 16, (500, 500, 500), 4213, 6, 0.7, 2.0 # Y-distance over which caverns expand to full size.
mgv7_np_filler_depth (Mapgen v7 filler depth noise parameters) noise_params 0, 1.2, (150, 150, 150), 261, 3, 0.7, 2.0 mgv7_cavern_taper (Cavern taper) int 256
mgv7_np_mount_height (Mapgen v7 mount height noise parameters) noise_params 256, 112, (1000, 1000, 1000), 72449, 3, 0.6, 2.0
mgv7_np_ridge_uwater (Mapgen v7 river course noise parameters) noise_params 0, 1, (1000, 1000, 1000), 85039, 5, 0.6, 2.0 # Defines full size of caverns, smaller values create larger caverns.
mgv7_np_floatland_base (Mapgen v7 floatland base terrain noise parameters) noise_params -0.6, 1.5, (600, 600, 600), 114, 5, 0.6, 2.0 mgv7_cavern_threshold (Cavern threshold) float 0.7
mgv7_np_float_base_height (Mapgen v7 floatland base terrain height noise parameters) noise_params 48, 24, (300, 300, 300), 907, 4, 0.7, 2.0
mgv7_np_mountain (Mapgen v7 mountain noise parameters) noise_params -0.6, 1, (250, 350, 250), 5333, 5, 0.63, 2.0 # Y-level of higher (cliff-top) terrain.
mgv7_np_ridge (Mapgen v7 river channel wall noise parameters) noise_params 0, 1, (100, 100, 100), 6467, 4, 0.75, 2.0 mgv7_np_terrain_base (Terrain base noise) noise_params 4, 70, (600, 600, 600), 82341, 5, 0.6, 2.0
mgv7_np_cave1 (Mapgen v7 cave1 noise parameters) noise_params 0, 12, (61, 61, 61), 52534, 3, 0.5, 2.0
mgv7_np_cave2 (Mapgen v7 cave2 noise parameters) noise_params 0, 12, (67, 67, 67), 10325, 3, 0.5, 2.0 # Y-level of lower terrain and lakebeds.
mgv7_np_terrain_alt (Terrain alt noise) noise_params 4, 25, (600, 600, 600), 5934, 5, 0.6, 2.0
# Varies roughness of terrain.
# Defines the 'persistence' value for terrain_base and terrain_alt noises.
mgv7_np_terrain_persist (Terrain persistence noise) noise_params 0.6, 0.1, (2000, 2000, 2000), 539, 3, 0.6, 2.0
# Defines areas of higher (cliff-top) terrain and affects steepness of cliffs.
mgv7_np_height_select (Height select noise) noise_params -8, 16, (500, 500, 500), 4213, 6, 0.7, 2.0
# Variation of biome filler depth.
mgv7_np_filler_depth (Filler depth noise) noise_params 0, 1.2, (150, 150, 150), 261, 3, 0.7, 2.0
# Variation of maximum mountain height (in nodes).
mgv7_np_mount_height (Mountain height noise) noise_params 256, 112, (1000, 1000, 1000), 72449, 3, 0.6, 2.0
# Defines large-scale river channel structure.
mgv7_np_ridge_uwater (Ridge underwater noise) noise_params 0, 1, (1000, 1000, 1000), 85039, 5, 0.6, 2.0
# Defines areas of floatland smooth terrain.
# Smooth floatlands occur when noise > 0.
mgv7_np_floatland_base (Floatland base noise) noise_params -0.6, 1.5, (600, 600, 600), 114, 5, 0.6, 2.0
# Variation of hill height and lake depth on floatland smooth terrain.
mgv7_np_float_base_height (Floatland base height noise) noise_params 48, 24, (300, 300, 300), 907, 4, 0.7, 2.0
# 3D noise defining mountain structure and height.
# Also defines structure of floatland mountain terrain.
mgv7_np_mountain (Mountain noise) noise_params -0.6, 1, (250, 350, 250), 5333, 5, 0.63, 2.0
# 3D noise defining structure of river canyon walls.
mgv7_np_ridge (Ridge noise) noise_params 0, 1, (100, 100, 100), 6467, 4, 0.75, 2.0
# 3D noise defining giant caverns.
mgv7_np_cavern (Cavern noise) noise_params 0, 1, (384, 128, 384), 723, 5, 0.63, 2.0
# First of 2 3D noises that together define tunnels.
mgv7_np_cave1 (Cave1 noise) noise_params 0, 12, (61, 61, 61), 52534, 3, 0.5, 2.0
# Second of 2 3D noises that together define tunnels.
mgv7_np_cave2 (Cave2 noise) noise_params 0, 12, (67, 67, 67), 10325, 3, 0.5, 2.0
[***Mapgen flat] [***Mapgen flat]
@ -1007,46 +1205,49 @@ mgv7_np_cave2 (Mapgen v7 cave2 noise parameters) noise_params 0, 12, (67, 67, 67
# Occasional lakes and hills can be added to the flat world. # Occasional lakes and hills can be added to the flat world.
# Flags that are not specified in the flag string are not modified from the default. # Flags that are not specified in the flag string are not modified from the default.
# Flags starting with 'no' are used to explicitly disable them. # Flags starting with 'no' are used to explicitly disable them.
mgflat_spflags (Mapgen flat flags) flags lakes,hills,,nolakes,nohills mgflat_spflags (Mapgen flat specific flags) flags nolakes,nohills lakes,hills,nolakes,nohills
# Y of flat ground. # Y of flat ground.
mgflat_ground_level (Mapgen flat ground level) int 8 mgflat_ground_level (Ground level) int 8
# Y of upper limit of large pseudorandom caves. # Y of upper limit of large pseudorandom caves.
mgflat_large_cave_depth (Mapgen flat large cave depth) int -33 mgflat_large_cave_depth (Large cave depth) int -33
# Controls width of tunnels, a smaller value creates wider tunnels. # Controls width of tunnels, a smaller value creates wider tunnels.
mgflat_cave_width (Mapgen flat cave width) float 0.09 mgflat_cave_width (Cave width) float 0.09
# Terrain noise threshold for lakes. # Terrain noise threshold for lakes.
# Controls proportion of world area covered by lakes. # Controls proportion of world area covered by lakes.
# Adjust towards 0.0 for a larger proportion. # Adjust towards 0.0 for a larger proportion.
mgflat_lake_threshold (Mapgen flat lake threshold) float -0.45 mgflat_lake_threshold (Lake threshold) float -0.45
# Controls steepness/depth of lake depressions. # Controls steepness/depth of lake depressions.
mgflat_lake_steepness (Mapgen flat lake steepness) float 48.0 mgflat_lake_steepness (Lake steepness) float 48.0
# Terrain noise threshold for hills. # Terrain noise threshold for hills.
# Controls proportion of world area covered by hills. # Controls proportion of world area covered by hills.
# Adjust towards 0.0 for a larger proportion. # Adjust towards 0.0 for a larger proportion.
mgflat_hill_threshold (Mapgen flat hill threshold) float 0.45 mgflat_hill_threshold (Hill threshold) float 0.45
# Controls steepness/height of hills. # Controls steepness/height of hills.
mgflat_hill_steepness (Mapgen flat hill steepness) float 64.0 mgflat_hill_steepness (Hill steepness) float 64.0
# Determines terrain shape. # Defines location and terrain of optional hills and lakes.
# The 3 numbers in brackets control the scale of the mgflat_np_terrain (Terrain noise) noise_params 0, 1, (600, 600, 600), 7244, 5, 0.6, 2.0
# terrain, the 3 numbers should be identical.
mgflat_np_terrain (Mapgen flat terrain noise parameters) noise_params 0, 1, (600, 600, 600), 7244, 5, 0.6, 2.0
mgflat_np_filler_depth (Mapgen flat filler depth noise parameters) noise_params 0, 1.2, (150, 150, 150), 261, 3, 0.7, 2.0 # Variation of biome filler depth.
mgflat_np_cave1 (Mapgen flat cave1 noise parameters) noise_params 0, 12, (61, 61, 61), 52534, 3, 0.5, 2.0 mgflat_np_filler_depth (Filler depth noise) noise_params 0, 1.2, (150, 150, 150), 261, 3, 0.7, 2.0
mgflat_np_cave2 (Mapgen flat cave2 noise parameters) noise_params 0, 12, (67, 67, 67), 10325, 3, 0.5, 2.0
# First of 2 3D noises that together define tunnels.
mgflat_np_cave1 (Cave1 noise) noise_params 0, 12, (61, 61, 61), 52534, 3, 0.5, 2.0
# Second of 2 3D noises that together define tunnels.
mgflat_np_cave2 (Cave2 noise) noise_params 0, 12, (67, 67, 67), 10325, 3, 0.5, 2.0
[***Mapgen fractal] [***Mapgen fractal]
# Controls width of tunnels, a smaller value creates wider tunnels. # Controls width of tunnels, a smaller value creates wider tunnels.
mgfractal_cave_width (Mapgen fractal cave width) float 0.09 mgfractal_cave_width (Cave width) float 0.09
# Choice of 18 fractals from 9 formulas. # Choice of 18 fractals from 9 formulas.
# 1 = 4D "Roundy" mandelbrot set. # 1 = 4D "Roundy" mandelbrot set.
@ -1067,48 +1268,55 @@ mgfractal_cave_width (Mapgen fractal cave width) float 0.09
# 16 = 3D "Cosine Mandelbulb" julia set. # 16 = 3D "Cosine Mandelbulb" julia set.
# 17 = 4D "Mandelbulb" mandelbrot set. # 17 = 4D "Mandelbulb" mandelbrot set.
# 18 = 4D "Mandelbulb" julia set. # 18 = 4D "Mandelbulb" julia set.
mgfractal_fractal (Mapgen fractal fractal) int 1 1 18 mgfractal_fractal (Fractal type) int 1 1 18
# Iterations of the recursive function. # Iterations of the recursive function.
# Controls the amount of fine detail. # Controls the amount of fine detail.
mgfractal_iterations (Mapgen fractal iterations) int 11 mgfractal_iterations (Iterations) int 11
# Approximate (X,Y,Z) scale of fractal in nodes. # Approximate (X,Y,Z) scale of fractal in nodes.
mgfractal_scale (Mapgen fractal scale) v3f (4096.0, 1024.0, 4096.0) mgfractal_scale (Scale) v3f (4096.0, 1024.0, 4096.0)
# (X,Y,Z) offset of fractal from world centre in units of 'scale'. # (X,Y,Z) offset of fractal from world centre in units of 'scale'.
# Used to move a suitable spawn area of low land close to (0, 0). # Used to move a suitable spawn area of low land close to (0, 0).
# The default is suitable for mandelbrot sets, it needs to be edited for julia sets. # The default is suitable for mandelbrot sets, it needs to be edited for julia sets.
# Range roughly -2 to 2. Multiply by 'scale' for offset in nodes. # Range roughly -2 to 2. Multiply by 'scale' for offset in nodes.
mgfractal_offset (Mapgen fractal offset) v3f (1.79, 0.0, 0.0) mgfractal_offset (Offset) v3f (1.79, 0.0, 0.0)
# W co-ordinate of the generated 3D slice of a 4D fractal. # W co-ordinate of the generated 3D slice of a 4D fractal.
# Determines which 3D slice of the 4D shape is generated. # Determines which 3D slice of the 4D shape is generated.
# Has no effect on 3D fractals. # Has no effect on 3D fractals.
# Range roughly -2 to 2. # Range roughly -2 to 2.
mgfractal_slice_w (Mapgen fractal slice w) float 0.0 mgfractal_slice_w (Slice w) float 0.0
# Julia set only: X component of hypercomplex constant determining julia shape. # Julia set only: X component of hypercomplex constant determining julia shape.
# Range roughly -2 to 2. # Range roughly -2 to 2.
mgfractal_julia_x (Mapgen fractal julia x) float 0.33 mgfractal_julia_x (Julia x) float 0.33
# Julia set only: Y component of hypercomplex constant determining julia shape. # Julia set only: Y component of hypercomplex constant determining julia shape.
# Range roughly -2 to 2. # Range roughly -2 to 2.
mgfractal_julia_y (Mapgen fractal julia y) float 0.33 mgfractal_julia_y (Julia y) float 0.33
# Julia set only: Z component of hypercomplex constant determining julia shape. # Julia set only: Z component of hypercomplex constant determining julia shape.
# Range roughly -2 to 2. # Range roughly -2 to 2.
mgfractal_julia_z (Mapgen fractal julia z) float 0.33 mgfractal_julia_z (Julia z) float 0.33
# Julia set only: W component of hypercomplex constant determining julia shape. # Julia set only: W component of hypercomplex constant determining julia shape.
# Has no effect on 3D fractals. # Has no effect on 3D fractals.
# Range roughly -2 to 2. # Range roughly -2 to 2.
mgfractal_julia_w (Mapgen fractal julia w) float 0.33 mgfractal_julia_w (Julia w) float 0.33
mgfractal_np_seabed (Mapgen fractal seabed noise parameters) noise_params -14, 9, (600, 600, 600), 41900, 5, 0.6, 2.0 # Y-level of seabed.
mgfractal_np_filler_depth (Mapgen fractal filler depth noise parameters) noise_params 0, 1.2, (150, 150, 150), 261, 3, 0.7, 2.0 mgfractal_np_seabed (Seabed noise) noise_params -14, 9, (600, 600, 600), 41900, 5, 0.6, 2.0
mgfractal_np_cave1 (Mapgen fractal cave1 noise parameters) noise_params 0, 12, (61, 61, 61), 52534, 3, 0.5, 2.0
mgfractal_np_cave2 (Mapgen fractal cave2 noise parameters) noise_params 0, 12, (67, 67, 67), 10325, 3, 0.5, 2.0 # Variation of biome filler depth.
mgfractal_np_filler_depth (Filler depth noise) noise_params 0, 1.2, (150, 150, 150), 261, 3, 0.7, 2.0
# First of 2 3D noises that together define tunnels.
mgfractal_np_cave1 (Cave1 noise) noise_params 0, 12, (61, 61, 61), 52534, 3, 0.5, 2.0
# Second of 2 3D noises that together define tunnels.
mgfractal_np_cave2 (Cave2 noise) noise_params 0, 12, (67, 67, 67), 10325, 3, 0.5, 2.0
# Mapgen Valleys parameters # Mapgen Valleys parameters
[***Mapgen Valleys] [***Mapgen Valleys]
@ -1186,7 +1394,7 @@ mgvalleys_np_inter_valley_slope (Valley Slope) noise_params 0.5, 0.5, (128, 128,
[*Security] [*Security]
# Prevent mods from doing insecure things like running shell commands. # Prevent mods from doing insecure things like running shell commands.
secure.enable_security (Enable mod security) bool false secure.enable_security (Enable mod security) bool true
# Comma-separated list of trusted mods that are allowed to access insecure # Comma-separated list of trusted mods that are allowed to access insecure
# functions even when mod security is on (via request_insecure_environment()). # functions even when mod security is on (via request_insecure_environment()).
@ -1209,7 +1417,6 @@ profiler.load (Load the game profiler) bool false
profiler.default_report_format (Default report format) enum txt txt,csv,lua,json,json_pretty profiler.default_report_format (Default report format) enum txt txt,csv,lua,json,json_pretty
# The file path relative to your worldpath in which profiles will be saved to. # The file path relative to your worldpath in which profiles will be saved to.
#
profiler.report_path (Report path) string "" profiler.report_path (Report path) string ""
[***Instrumentation] [***Instrumentation]
@ -1260,7 +1467,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

@ -37,7 +37,7 @@ const float fogShadingParameter = 1 / ( 1 - fogStart);
vec3 uncharted2Tonemap(vec3 x) vec3 uncharted2Tonemap(vec3 x)
{ {
return ((x * (0.22 * x + 0.03) + 0.002) / (x * (0.22 * x + 0.3) + 0.06)) - 0.03334; return ((x * (0.22 * x + 0.03) + 0.002) / (x * (0.22 * x + 0.3) + 0.06)) - 0.03333;
} }
vec4 applyToneMapping(vec4 color) vec4 applyToneMapping(vec4 color)
@ -163,7 +163,8 @@ void main(void)
} }
#endif #endif
if (GENERATE_NORMALMAPS == 1 && normalTexturePresent == false) { #if GENERATE_NORMALMAPS == 1
if (normalTexturePresent == false) {
float tl = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y + SAMPLE_STEP)); 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 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 tr = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y + SAMPLE_STEP));
@ -177,7 +178,7 @@ void main(void)
bump = vec4(normalize(vec3 (dX, dY, NORMALMAPS_STRENGTH)), 1.0); bump = vec4(normalize(vec3 (dX, dY, NORMALMAPS_STRENGTH)), 1.0);
use_normalmap = true; use_normalmap = true;
} }
#endif
vec4 base = texture2D(baseTexture, uv).rgba; vec4 base = texture2D(baseTexture, uv).rgba;
#ifdef ENABLE_BUMPMAPPING #ifdef ENABLE_BUMPMAPPING
@ -200,7 +201,6 @@ void main(void)
col = applyToneMapping(col); col = applyToneMapping(col);
#endif #endif
if (fogDistance != 0.0) {
// Due to a bug in some (older ?) graphics stacks (possibly in the glsl compiler ?), // 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 // the fog will only be rendered correctly if the last operation before the
// clamp() is an addition. Else, the clamp() seems to be ignored. // clamp() is an addition. Else, the clamp() seems to be ignored.
@ -213,7 +213,6 @@ void main(void)
float clarity = clamp(fogShadingParameter float clarity = clamp(fogShadingParameter
- fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0); - fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0);
col = mix(skyBgColor, col, clarity); col = mix(skyBgColor, col, clarity);
}
col = vec4(col.rgb, base.a); col = vec4(col.rgb, base.a);
gl_FragColor = col; gl_FragColor = col;

@ -1,7 +1,8 @@
uniform mat4 mWorldViewProj; uniform mat4 mWorldViewProj;
uniform mat4 mWorld; uniform mat4 mWorld;
uniform float dayNightRatio; // Color of the light emitted by the sun.
uniform vec3 dayLight;
uniform vec3 eyePosition; uniform vec3 eyePosition;
uniform float animationTimer; uniform float animationTimer;
@ -14,6 +15,8 @@ varying vec3 tsEyeVec;
varying vec3 tsLightVec; varying vec3 tsLightVec;
varying float area_enable_parallax; varying float area_enable_parallax;
// 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 e = 2.718281828459;
const float BS = 10.0; const float BS = 10.0;
@ -119,31 +122,23 @@ float disp_z;
v.z = dot(eyeVec, normal); v.z = dot(eyeVec, normal);
tsEyeVec = normalize (v); tsEyeVec = normalize (v);
// 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; vec4 color;
float day = gl_Color.r; // The alpha gives the ratio of sunlight in the incoming light.
float night = gl_Color.g; float nightRatio = 1 - gl_Color.a;
float light_source = gl_Color.b; color.rgb = gl_Color.rgb * (gl_Color.a * dayLight.rgb +
nightRatio * artificialLight.rgb) * 2;
float rg = mix(night, day, dayNightRatio); color.a = 1;
rg += light_source * 2.5; // Make light sources brighter
float b = rg;
// Moonlight is blue
b += (day - night) / 13.0;
rg -= (day - night) / 23.0;
// Emphase blue a bit in darker places // Emphase blue a bit in darker places
// See C++ implementation in mapblock_mesh.cpp finalColorBlend() // See C++ implementation in mapblock_mesh.cpp finalColorBlend()
b += max(0.0, (1.0 - abs(b - 0.13) / 0.17) * 0.025); 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);
// Artificial light is yellow-ish
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
rg += max(0.0, (1.0 - abs(rg - 0.85) / 0.15) * 0.065);
color.r = rg;
color.g = rg;
color.b = b;
color.a = gl_Color.a;
gl_FrontColor = gl_BackColor = clamp(color, 0.0, 1.0); gl_FrontColor = gl_BackColor = clamp(color, 0.0, 1.0);
} }

@ -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 && 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;
}
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
if (fogDistance != 0.0) {
// 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;
}

@ -1,142 +0,0 @@
uniform mat4 mWorldViewProj;
uniform mat4 mWorld;
uniform float dayNightRatio;
uniform vec3 eyePosition;
uniform float animationTimer;
varying vec3 vPosition;
varying vec3 worldPosition;
varying vec3 eyeVec;
varying vec3 lightVec;
varying vec3 tsEyeVec;
varying vec3 tsLightVec;
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;
vec4 color;
float day = gl_Color.r;
float night = gl_Color.g;
float light_source = gl_Color.b;
float rg = mix(night, day, dayNightRatio);
rg += light_source * 2.5; // Make light sources brighter
float b = rg;
// Moonlight is blue
b += (day - night) / 13.0;
rg -= (day - night) / 23.0;
// Emphase blue a bit in darker places
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
b += max(0.0, (1.0 - abs(b - 0.13)/0.17) * 0.025);
// Artificial light is yellow-ish
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
rg += max(0.0, (1.0 - abs(rg - 0.85)/0.15) * 0.065);
color.r = rg;
color.g = rg;
color.b = b;
color.a = gl_Color.a;
gl_FrontColor = gl_BackColor = clamp(color,0.0,1.0);
}

@ -75,7 +75,8 @@ void main(void)
} }
#endif #endif
if (GENERATE_NORMALMAPS == 1 && normalTexturePresent == false) { #if GENERATE_NORMALMAPS == 1
if (normalTexturePresent == false) {
float tl = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y + SAMPLE_STEP)); 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 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 tr = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y + SAMPLE_STEP));
@ -89,6 +90,7 @@ void main(void)
bump = vec4(normalize(vec3 (dX, dY, NORMALMAPS_STRENGTH)), 1.0); bump = vec4(normalize(vec3 (dX, dY, NORMALMAPS_STRENGTH)), 1.0);
use_normalmap = true; use_normalmap = true;
} }
#endif
vec4 base = texture2D(baseTexture, uv).rgba; vec4 base = texture2D(baseTexture, uv).rgba;
@ -108,7 +110,6 @@ void main(void)
vec4 col = vec4(color.rgb, base.a); vec4 col = vec4(color.rgb, base.a);
col *= gl_Color; col *= gl_Color;
if (fogDistance != 0.0) {
// Due to a bug in some (older ?) graphics stacks (possibly in the glsl compiler ?), // 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 // the fog will only be rendered correctly if the last operation before the
// clamp() is an addition. Else, the clamp() seems to be ignored. // clamp() is an addition. Else, the clamp() seems to be ignored.
@ -121,6 +122,6 @@ void main(void)
float clarity = clamp(fogShadingParameter float clarity = clamp(fogShadingParameter
- fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0); - fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0);
col = mix(skyBgColor, col, clarity); col = mix(skyBgColor, col, clarity);
}
gl_FragColor = vec4(col.rgb, base.a); gl_FragColor = vec4(col.rgb, base.a);
} }

@ -1,7 +1,6 @@
uniform mat4 mWorldViewProj; uniform mat4 mWorldViewProj;
uniform mat4 mWorld; uniform mat4 mWorld;
uniform float dayNightRatio;
uniform vec3 eyePosition; uniform vec3 eyePosition;
uniform float animationTimer; uniform float animationTimer;

152
clientmods/preview/init.lua Normal file

@ -0,0 +1,152 @@
local modname = core.get_current_modname() or "??"
local modstorage = core.get_mod_storage()
-- This is an example function to ensure it's working properly, should be removed before merge
core.register_on_shutdown(function()
print("[PREVIEW] shutdown client")
end)
core.register_on_connect(function()
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)
-- This is an example function to ensure it's working properly, should be removed before merge
core.register_on_receiving_chat_messages(function(message)
print("[PREVIEW] Received message " .. message)
return false
end)
-- This is an example function to ensure it's working properly, should be removed before merge
core.register_on_sending_chat_messages(function(message)
print("[PREVIEW] Sending message " .. message)
return false
end)
-- This is an example function to ensure it's working properly, should be removed before merge
core.register_on_hp_modification(function(hp)
print("[PREVIEW] HP modified " .. hp)
end)
-- This is an example function to ensure it's working properly, should be removed before merge
core.register_on_damage_taken(function(hp)
print("[PREVIEW] Damage taken " .. hp)
end)
-- This is an example function to ensure it's working properly, should be removed before merge
core.register_globalstep(function(dtime)
-- print("[PREVIEW] globalstep " .. dtime)
end)
-- This is an example function to ensure it's working properly, should be removed before merge
core.register_chatcommand("dump", {
func = function(param)
return true, dump(_G)
end,
})
core.register_chatcommand("colorize_test", {
func = function(param)
return true, core.colorize("red", param)
end,
})
core.register_chatcommand("test_node", {
func = function(param)
core.display_chat_message(dump(core.get_node({x=0, y=0, z=0})))
core.display_chat_message(dump(core.get_node_or_nil({x=0, y=0, z=0})))
end,
})
local function preview_minimap()
local minimap = core.ui.minimap
if not minimap then
print("[PREVIEW] Minimap is disabled. Skipping.")
return
end
minimap:set_mode(4)
minimap:show()
minimap:set_pos({x=5, y=50, z=5})
minimap:set_shape(math.random(0, 1))
print("[PREVIEW] Minimap: mode => " .. dump(minimap:get_mode()) ..
" position => " .. dump(minimap:get_pos()) ..
" angle => " .. dump(minimap:get_angle()))
end
core.after(2, function()
print("[PREVIEW] loaded " .. modname .. " mod")
modstorage:set_string("current_mod", modname)
print(modstorage:get_string("current_mod"))
preview_minimap()
end)
core.after(5, function()
if core.ui.minimap then
core.ui.minimap:show()
end
print("[PREVIEW] Day count: " .. core.get_day_count() ..
" time of day " .. core.get_timeofday())
print("[PREVIEW] Node level: " .. core.get_node_level({x=0, y=20, z=0}) ..
" max level " .. core.get_node_max_level({x=0, y=20, z=0}))
print("[PREVIEW] Find node near: " .. dump(core.find_node_near({x=0, y=20, z=0}, 10,
{"group:tree", "default:dirt", "default:stone"})))
end)
core.register_on_dignode(function(pos, node)
print("The local player dug a node!")
print("pos:" .. dump(pos))
print("node:" .. dump(node))
return false
end)
core.register_on_punchnode(function(pos, node)
print("The local player punched a node!")
local itemstack = core.get_wielded_item()
--[[
-- getters
print(dump(itemstack:is_empty()))
print(dump(itemstack:get_name()))
print(dump(itemstack:get_count()))
print(dump(itemstack:get_wear()))
print(dump(itemstack:get_meta()))
print(dump(itemstack:get_metadata()
print(dump(itemstack:is_known()))
--print(dump(itemstack:get_definition()))
print(dump(itemstack:get_tool_capabilities()))
print(dump(itemstack:to_string()))
print(dump(itemstack:to_table()))
-- setters
print(dump(itemstack:set_name("default:dirt")))
print(dump(itemstack:set_count("95")))
print(dump(itemstack:set_wear(934)))
print(dump(itemstack:get_meta()))
print(dump(itemstack:get_metadata()))
--]]
print(dump(itemstack:to_table()))
print("pos:" .. dump(pos))
print("node:" .. dump(node))
return false
end)

@ -1,4 +1,3 @@
option(ENABLE_SYSTEM_GMP "Use GMP from system" TRUE) option(ENABLE_SYSTEM_GMP "Use GMP from system" TRUE)
mark_as_advanced(GMP_LIBRARY GMP_INCLUDE_DIR) mark_as_advanced(GMP_LIBRARY GMP_INCLUDE_DIR)
set(USE_SYSTEM_GMP FALSE) set(USE_SYSTEM_GMP FALSE)
@ -19,9 +18,9 @@ endif()
if(NOT USE_SYSTEM_GMP) if(NOT USE_SYSTEM_GMP)
message(STATUS "Using bundled mini-gmp library.") message(STATUS "Using bundled mini-gmp library.")
set(GMP_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/gmp) set(GMP_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib/gmp)
set(GMP_LIBRARY gmp) set(GMP_LIBRARY gmp)
add_subdirectory(gmp) add_subdirectory(lib/gmp)
endif() endif()
include(FindPackageHandleStandardArgs) include(FindPackageHandleStandardArgs)

@ -20,8 +20,7 @@ endif()
if(NOT JSONCPP_FOUND) if(NOT JSONCPP_FOUND)
message(STATUS "Using bundled JSONCPP library.") message(STATUS "Using bundled JSONCPP library.")
set(JSON_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/jsoncpp) set(JSON_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib/jsoncpp)
set(JSON_LIBRARY jsoncpp) set(JSON_LIBRARY jsoncpp)
add_subdirectory(jsoncpp/json) add_subdirectory(lib/jsoncpp)
endif() endif()

@ -0,0 +1,28 @@
# Look for Lua library to use
# This selects LuaJIT by default
option(ENABLE_LUAJIT "Enable LuaJIT support" TRUE)
set(USE_LUAJIT FALSE)
option(REQUIRE_LUAJIT "Require LuaJIT support" FALSE)
if(REQUIRE_LUAJIT)
set(ENABLE_LUAJIT TRUE)
endif()
if(ENABLE_LUAJIT)
find_package(LuaJIT)
if(LUAJIT_FOUND)
set(USE_LUAJIT TRUE)
message (STATUS "Using LuaJIT provided by system.")
elseif(REQUIRE_LUAJIT)
message(FATAL_ERROR "LuaJIT not found whereas REQUIRE_LUAJIT=\"TRUE\" is used.\n"
"To continue, either install LuaJIT or do not use REQUIRE_LUAJIT=\"TRUE\".")
endif()
else()
message (STATUS "LuaJIT detection disabled! (ENABLE_LUAJIT=0)")
endif()
if(NOT USE_LUAJIT)
message(STATUS "LuaJIT not found, using bundled Lua.")
set(LUA_LIBRARY lua)
set(LUA_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib/lua/src)
add_subdirectory(lib/lua)
endif()

1149
doc/client_lua_api.md Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,4 +1,4 @@
Minetest Lua Mainmenu API Reference 0.4.15 Minetest Lua Mainmenu API Reference 0.4.16
======================================== ========================================
Introduction Introduction

@ -76,6 +76,9 @@ by texture packs. All existing fallback textures can be found in the directory
* `player.png`: front texture of the 2D upright sprite player * `player.png`: front texture of the 2D upright sprite player
* `player_back.png`: back texture of the 2D upright sprite player * `player_back.png`: back texture of the 2D upright sprite player
* `progress_bar.png`: foreground texture of the loading screen's progress bar
* `progress_bar_bg.png`: background texture of the loading screen's progress bar
* `moon.png`: texture of the moon. Default texture is generated by Minetest * `moon.png`: texture of the moon. Default texture is generated by Minetest
* `moon_tonemap.png`: tonemap to be used when `moon.png` was found * `moon_tonemap.png`: tonemap to be used when `moon.png` was found
* `sun.png`: texture of the sun. Default texture is generated by Minetest * `sun.png`: texture of the sun. Default texture is generated by Minetest

@ -1,12 +1,13 @@
============================= =============================
Minetest World Format 22...25 Minetest World Format 22...27
============================= =============================
This applies to a world format carrying the block serialization version This applies to a world format carrying the block serialization version
22...25, used at least in 22...27, used at least in
- 0.4.dev-20120322 ... 0.4.dev-20120606 (22...23) - 0.4.dev-20120322 ... 0.4.dev-20120606 (22...23)
- 0.4.0 (23) - 0.4.0 (23)
- 24 was never released as stable and existed for ~2 days - 24 was never released as stable and existed for ~2 days
- 27 was added in 0.4.15-dev
The block serialization version does not fully specify every aspect of this The block serialization version does not fully specify every aspect of this
format; if compliance with this format is to be checked, it needs to be format; if compliance with this format is to be checked, it needs to be
@ -262,15 +263,36 @@ u8 flags
- 0x02: day_night_differs: Whether the lighting of the block is different - 0x02: day_night_differs: Whether the lighting of the block is different
on day and night. Only blocks that have this bit set are updated when on day and night. Only blocks that have this bit set are updated when
day transforms to night. day transforms to night.
- 0x04: lighting_expired: If true, lighting is invalid and should be - 0x04: lighting_expired: Not used in version 27 and above. If true,
updated. If you can't calculate lighting in your generator properly, lighting is invalid and should be updated. If you can't calculate
you could try setting this 1 to everything and setting the uppermost lighting in your generator properly, you could try setting this 1 to
block in every sector as is_underground=0. I am quite sure it doesn't everything and setting the uppermost block in every sector as
work properly, though. is_underground=0. I am quite sure it doesn't work properly, though.
- 0x08: generated: True if the block has been generated. If false, block - 0x08: generated: True if the block has been generated. If false, block
is mostly filled with CONTENT_IGNORE and is likely to contain eg. parts is mostly filled with CONTENT_IGNORE and is likely to contain eg. parts
of trees of neighboring blocks. of trees of neighboring blocks.
u16 lighting_complete
- Added in version 27.
- This contains 12 flags, each of them corresponds to a direction.
- Indicates if the light is correct at the sides of a map block.
Lighting may not be correct if the light changed, but a neighbor
block was not loaded at that time.
If these flags are false, Minetest will automatically recompute light
when both this block and its required neighbor are loaded.
- The bit order is:
nothing, nothing, nothing, nothing,
night X-, night Y-, night Z-, night Z+, night Y+, night X+,
day X-, day Y-, day Z-, day Z+, day Y+, day X+.
Where 'day' is for the day light bank, 'night' is for the night
light bank.
The 'nothing' bits should be always set, as they will be used
to indicate if direct sunlight spreading is finished.
- Example: if the block at (0, 0, 0) has
lighting_complete = 0b1111111111111110,
then Minetest will correct lighting in the day light bank when
the block at (1, 0, 0) is also loaded.
u8 content_width u8 content_width
- Number of bytes in the content (param0) fields of nodes - Number of bytes in the content (param0) fields of nodes
if map format version <= 23: if map format version <= 23:

2
fonts/Arimo-LICENSE.txt Normal file

@ -0,0 +1,2 @@
Arimo - Apache License, version 2.0
Arimo-Regular.ttf: Digitized data copyright (c) 2010-2012 Google Corporation.

BIN
fonts/Arimo-Regular.ttf Normal file

Binary file not shown.

@ -0,0 +1,2 @@
Cousine - Apache License, version 2.0
Cousine-Regular.ttf: Digitized data copyright (c) 2010-2012 Google Corporation.

BIN
fonts/Cousine-Regular.ttf Normal file

Binary file not shown.

@ -0,0 +1,13 @@
Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

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