Merge pull request #1 from minetest/master

merge
master
Trent Patterson 2016-05-16 09:52:39 -04:00
commit 4acda4bbe3
325 changed files with 56601 additions and 20230 deletions

15
.gitignore vendored
View File

@ -73,15 +73,14 @@ locale/
*.a *.a
## Android build files ## Android build files
build/android/assets build/android/src/main/assets
build/android/bin build/android/build
build/android/Debug
build/android/deps build/android/deps
build/android/gen
build/android/jni/src
build/android/libs build/android/libs
build/android/jni/src
build/android/src/main/jniLibs
build/android/obj build/android/obj
build/android/path.cfg build/android/local.properties
build/android/and_env build/android/.gradle
build/android/AndroidManifest.xml
timestamp timestamp

View File

@ -2,10 +2,13 @@ language: cpp
compiler: compiler:
- gcc - gcc
- clang - clang
os:
- osx
- linux
env: env:
- PLATFORM=Win32 - PLATFORM=Win32
- PLATFORM=Win64 - PLATFORM=Win64
- PLATFORM=Linux - PLATFORM=Unix
before_install: ./util/travis/before_install.sh before_install: ./util/travis/before_install.sh
script: ./util/travis/script.sh script: ./util/travis/script.sh
sudo: required sudo: required
@ -18,3 +21,9 @@ matrix:
compiler: clang compiler: clang
- env: PLATFORM=Win64 - env: PLATFORM=Win64
compiler: clang compiler: clang
- env: PLATFORM=Win32
os: osx
- env: PLATFORM=Win64
os: osx
- compiler: gcc
os: osx

View File

@ -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 13) set(VERSION_PATCH 14)
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
@ -113,6 +113,9 @@ endif()
set(CUSTOM_DOCDIR "" CACHE STRING "Directory to install documentation into") set(CUSTOM_DOCDIR "" CACHE STRING "Directory to install documentation into")
if(NOT CUSTOM_DOCDIR STREQUAL "") if(NOT CUSTOM_DOCDIR STREQUAL "")
set(DOCDIR "${CUSTOM_DOCDIR}") set(DOCDIR "${CUSTOM_DOCDIR}")
if(NOT RUN_IN_PLACE)
set(EXAMPLE_CONF_DIR ${DOCDIR})
endif()
message(STATUS "Using DOCDIR=${DOCDIR}") message(STATUS "Using DOCDIR=${DOCDIR}")
endif() endif()
@ -149,16 +152,9 @@ 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}/games/minimal" DESTINATION "${SHAREDIR}/games") install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/games" DESTINATION "${SHAREDIR}" PATTERN ".git*" EXCLUDE)
set(MINETEST_GAME_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/games/minetest_game")
if(EXISTS ${MINETEST_GAME_SOURCE} AND IS_DIRECTORY ${MINETEST_GAME_SOURCE})
install(FILES ${MINETEST_GAME_SOURCE}/game.conf DESTINATION "${SHAREDIR}/games/minetest_game/")
install(FILES ${MINETEST_GAME_SOURCE}/README.txt DESTINATION "${SHAREDIR}/games/minetest_game/")
install(DIRECTORY ${MINETEST_GAME_SOURCE}/mods DESTINATION "${SHAREDIR}/games/minetest_game")
install(DIRECTORY ${MINETEST_GAME_SOURCE}/menu DESTINATION "${SHAREDIR}/games/minetest_game")
endif()
if(BUILD_CLIENT) if(BUILD_CLIENT)
#install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/sounds/base/pack" DESTINATION "${SHAREDIR}/sounds/base")
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/textures/base/pack" DESTINATION "${SHAREDIR}/textures/base") install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/textures/base/pack" DESTINATION "${SHAREDIR}/textures/base")
endif() endif()
if(RUN_IN_PLACE) if(RUN_IN_PLACE)

107
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,107 @@
# Contributing
Contributions are welcome! Here's how you can help:
- [Contributing code](#code)
- [Reporting issues](#issues)
- [Requesting features](#feature-requests)
- [Translating](#translations)
- [Donating](#donations)
## Code
If you are planning to start some significant coding, you would benefit from asking first on [our IRC channel](http://www.minetest.net/irc/) before starting.
1. [Fork](https://help.github.com/articles/fork-a-repo/) the repository and [clone](https://help.github.com/articles/cloning-a-repository/) your fork.
2. Start coding!
- Refer to the [Lua API](https://github.com/minetest/minetest/blob/master/doc/lua_api.txt), [Developer Wiki](http://dev.minetest.net/Main_Page) and other [documentation](https://github.com/minetest/minetest/tree/master/doc).
- Follow the [C/C++](http://dev.minetest.net/Code_style_guidelines) and [Lua](http://dev.minetest.net/Lua_code_style_guidelines) code style guidelines.
- Check your code works as expected and document any changes to the Lua API.
3. Commit & [push](https://help.github.com/articles/pushing-to-a-remote/) your changes to a new branch (not `master`, one change per branch)
- Commit messages should:
- Use the present tense
- Have a title which begins with a capital letter
- 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*
- 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.
- Open the [pull-request form](https://github.com/minetest/minetest/pull/new/master)
- Add a short description explaining briefly what you've done (or if it's a work-in-progress - what you need to do)
##### A pull-request is considered merge-able when:
1. It follows the [roadmap](https://forum.minetest.net/viewtopic.php?t=9177) in some way and fits the whole picture of the project.
2. It works.
3. It follows the code style for [C/C++](http://dev.minetest.net/Code_style_guidelines) or [Lua](http://dev.minetest.net/Lua_code_style_guidelines).
4. The code's interfaces are well designed, regardless of other aspects that might need more work in the future.
5. It uses protocols and formats which include the required compatibility.
## Issues
If you experience an issue, we would like to know the details - especially when a stable release is on the way.
1. Do a quick search on GitHub to check if the issue has already been reported.
2. Is it an issue with the Minetest *engine*? If not, report it [elsewhere](http://www.minetest.net/development/#reporting-issues).
3. [Open an issue](https://github.com/minetest/minetest/issues/new) and describe the issue you are having - you could include:
- Error logs (check the bottom of the `debug.txt` file)
- Screenshots
- Ways you have tried to solve the issue, and whether they worked or not
- Your Minetest version and the content (subgames, mods or texture packs) you have installed
- Your platform (e.g. Windows 10 or Ubuntu 15.04 x64)
After reporting you should aim to answer questions or clarifications as this helps pinpoint the cause of the issue (if you don't do this your issue may be closed after 1 month).
## Feature requests
Feature requests are welcome but take a moment to see if your idea follows the [roadmap](https://forum.minetest.net/viewtopic.php?t=9177) in some way and fits the whole picture of the project. You should provide a clear explanation with as much detail as possible.
## Translations
Translations of Minetest are performed using Weblate. You can access the project page with a list of current languages [here](https://hosted.weblate.org/projects/minetest/minetest/).
### Donations
If you'd like to monetarily support Minetest development, you can find donation methods on [our website](http://www.minetest.net/development/#donate).
# Maintaining
*This is a concise version of the [Rules & Guidelines](http://dev.minetest.net/Category:Rules_and_Guidelines) on the developer wiki.*
These notes are for those who have push access Minetest (core developers / maintainers).
- See the [project organisation](http://dev.minetest.net/Organisation) for the people involved.
## Reviewing pull requests
Pull requests should be reviewed and, if appropriate, checked if they achieve their intended purpose. You can show that you are in the process of, or will review the pull request by commenting *"Looks good"* or something similar.
**If the pull-request is not [merge-able](#a-pull-request-is-considered-merge-able-when):**
Submit a comment explaining to the author what they need to change to make the pull-request merge-able.
- If the author comments or makes changes to the pull-request, it can be reviewed again.
- If no response is made from the author within 1 month (when improvements are suggested or a question is asked), it can be closed.
**If the pull-request is [merge-able](#a-pull-request-is-considered-merge-able-when):**
Submit a :+1: (+1) or "Looks good" comment to show you believe the pull-request should be merged. "Looks good" comments often signify that the patch might require (more) testing.
- Two core developers must agree to the merge before it is carried out and both should +1 the pull request.
- Who intends to merge the pull-request should follow the commit rules:
- The title should follow the commit guidelines (title starts with a capital letter, present tense, descriptive).
- Don't modify history older than 10 minutes.
- Use rebase, not merge to get linear history:
- `curl https://github.com/minetest/minetest/pull/1.patch | git am`
## Reviewing issues and feature requests
- If an issue does not get a response from its author within 1 month (when requiring more details), it can be closed.
- When an issue is a duplicate, refer to the first ones and close the later ones.
- Tag issues with the appropriate [labels](https://github.com/minetest/minetest/labels) for devices, platforms etc.
## Releasing a new version
*Refer to [dev.minetest.net/Releasing_Minetest](http://dev.minetest.net/Releasing_Minetest)*

View File

@ -105,11 +105,17 @@ Compiling on GNU/Linux:
Install dependencies. Here's an example for Debian/Ubuntu: Install dependencies. Here's an example for Debian/Ubuntu:
$ sudo apt-get install build-essential libirrlicht-dev cmake libbz2-dev libpng12-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 $ sudo apt-get install build-essential libirrlicht-dev cmake libbz2-dev libpng12-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
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
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-core $ sudo apt-get install git-core
For Fedora users:
$ sudo dnf install git-core
Download source (this is the URL to the latest of source repository, which might not work at all times) using git: Download source (this is the URL to the latest of source repository, which might not work at all times) using git:
$ git clone --depth 1 https://github.com/minetest/minetest.git $ git clone --depth 1 https://github.com/minetest/minetest.git
$ cd minetest $ cd minetest
@ -376,8 +382,8 @@ Authors of media files
Everything not listed in here: Everything not listed in here:
Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com> Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
BlockMen: Paramat:
textures/base/pack/menuheader.png textures/base/pack/menu_header.png
erlehmann: erlehmann:
misc/minetest-icon-24x24.png misc/minetest-icon-24x24.png

View File

@ -1,35 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.minetest.minetest"
android:versionCode="###ANDROID_VERSION###"
android:versionName="###BASE_VERSION###.###ANDROID_VERSION###"
android:installLocation="auto">
<uses-sdk android:minSdkVersion="9"/>
<uses-feature android:glEsVersion="0x00010000" android:required="true"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
###DEBUG_BUILD###
<application android:icon="@drawable/irr_icon" android:label="Minetest" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" ###DEBUG_FLAG###>
<activity android:name=".MtNativeActivity"
android:label="Minetest"
android:launchMode="singleTask"
android:configChanges="orientation|keyboard|keyboardHidden|navigation"
android:screenOrientation="sensorLandscape"
android:clearTaskOnLaunch="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="android.app.lib_name" android:value="minetest" />
</activity>
<activity android:name=".MinetestTextEntry"
android:theme="@style/Theme.Transparent"
android:excludeFromRecents="true">
</activity>
<activity android:name=".MinetestAssetCopy"
android:theme="@style/Theme.Transparent"
android:excludeFromRecents="true">
</activity>
</application>
</manifest>

View File

@ -8,42 +8,21 @@ OS := $(shell uname)
# build for build platform # build for build platform
APP_PLATFORM = android-9 APP_PLATFORM = android-9
# paths used for timestaps, dependencys, tree config and libs ANDR_ROOT = $(shell pwd)
PATHCFGFILE = path.cfg PROJ_ROOT = $(shell realpath $(ANDR_ROOT)/../..)
APP_ROOT = $(ANDR_ROOT)/src/main
ROOT = $(shell pwd)
GAMES_TO_COPY = minetest_game GAMES_TO_COPY = minetest_game
MODS_TO_COPY = MODS_TO_COPY =
VERSION_MAJOR := $(shell cat $(ROOT)/../../CMakeLists.txt | \ VERSION_MAJOR := $(shell cat $(PROJ_ROOT)/CMakeLists.txt | \
grep ^set\(VERSION_MAJOR\ | sed 's/)/ /' | cut -f2 -d' ') grep ^set\(VERSION_MAJOR\ | sed 's/)/ /' | cut -f2 -d' ')
VERSION_MINOR := $(shell cat $(ROOT)/../../CMakeLists.txt | \ VERSION_MINOR := $(shell cat $(PROJ_ROOT)/CMakeLists.txt | \
grep ^set\(VERSION_MINOR\ | sed 's/)/ /' | cut -f2 -d' ') grep ^set\(VERSION_MINOR\ | sed 's/)/ /' | cut -f2 -d' ')
VERSION_PATCH := $(shell cat $(ROOT)/../../CMakeLists.txt | \ VERSION_PATCH := $(shell cat $(PROJ_ROOT)/CMakeLists.txt | \
grep ^set\(VERSION_PATCH\ | sed 's/)/ /' | cut -f2 -d' ') grep ^set\(VERSION_PATCH\ | sed 's/)/ /' | cut -f2 -d' ')
################################################################################
# Android Version code
# Increase for each build!
################################################################################
# Play Store actual version (16/03/15): 11
ANDROID_VERSION_CODE = 13
################################################################################
# toolchain config for arm old processors
################################################################################
#TARGET_HOST = arm-linux
#TARGET_ABI = armeabi
#TARGET_LIBDIR = armeabi
#TARGET_TOOLCHAIN = arm-linux-androideabi-
#TARGET_CFLAGS_ADDON = -mfloat-abi=softfp -mfpu=vfp
#TARGET_ARCH = arm
#CROSS_PREFIX = arm-linux-androideabi-
#COMPILER_VERSION = 4.8
#HAVE_LEVELDB = 1
################################################################################ ################################################################################
# toolchain config for arm new processors # toolchain config for arm new processors
################################################################################ ################################################################################
@ -51,11 +30,11 @@ TARGET_HOST = arm-linux
TARGET_ABI = armeabi-v7a TARGET_ABI = armeabi-v7a
TARGET_LIBDIR = armeabi-v7a TARGET_LIBDIR = armeabi-v7a
TARGET_TOOLCHAIN = arm-linux-androideabi- TARGET_TOOLCHAIN = arm-linux-androideabi-
TARGET_CFLAGS_ADDON = -mfloat-abi=softfp -mfpu=vfpv3 TARGET_CFLAGS_ADDON = -mfloat-abi=softfp -mfpu=vfpv3 -O3
TARGET_CXXFLAGS_ADDON = $(TARGET_CFLAGS_ADDON) 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.8 COMPILER_VERSION = 4.9
HAVE_LEVELDB = 1 HAVE_LEVELDB = 1
################################################################################ ################################################################################
@ -67,7 +46,7 @@ HAVE_LEVELDB = 1
#TARGET_TOOLCHAIN = mipsel-linux-android- #TARGET_TOOLCHAIN = mipsel-linux-android-
#TARGET_ARCH = mips32 #TARGET_ARCH = mips32
#CROSS_PREFIX = mipsel-linux-android- #CROSS_PREFIX = mipsel-linux-android-
#COMPILER_VERSION = 4.8 #COMPILER_VERSION = 4.9
#HAVE_LEVELDB = 0 #HAVE_LEVELDB = 0
################################################################################ ################################################################################
@ -79,76 +58,80 @@ HAVE_LEVELDB = 1
#TARGET_TOOLCHAIN = x86- #TARGET_TOOLCHAIN = x86-
#CROSS_PREFIX = i686-linux-android- #CROSS_PREFIX = i686-linux-android-
#TARGET_ARCH = x86 #TARGET_ARCH = x86
#COMPILER_VERSION = 4.8 #COMPILER_VERSION = 4.9
#HAVE_LEVELDB = 1 #HAVE_LEVELDB = 1
################################################################################ ################################################################################
ASSETS_TIMESTAMP = deps/assets_timestamp ASSETS_TIMESTAMP = deps/assets_timestamp
LEVELDB_DIR = $(ROOT)/deps/leveldb/ LEVELDB_DIR = $(ANDR_ROOT)/deps/leveldb/
LEVELDB_LIB = $(LEVELDB_DIR)libleveldb.a LEVELDB_LIB = $(LEVELDB_DIR)libleveldb.a
LEVELDB_TIMESTAMP = $(LEVELDB_DIR)/timestamp LEVELDB_TIMESTAMP = $(LEVELDB_DIR)/timestamp
LEVELDB_TIMESTAMP_INT = $(ROOT)/deps/leveldb_timestamp LEVELDB_TIMESTAMP_INT = $(ANDR_ROOT)/deps/leveldb_timestamp
LEVELDB_URL_GIT = https://github.com/google/leveldb LEVELDB_URL_GIT = https://github.com/google/leveldb
LEVELDB_COMMIT = 2d0320a458d0e6a20fff46d5f80b18bfdcce7018
OPENAL_DIR = $(ROOT)/deps/openal-soft/ OPENAL_DIR = $(ANDR_ROOT)/deps/openal-soft/
OPENAL_LIB = $(OPENAL_DIR)libs/$(TARGET_ABI)/libopenal.so OPENAL_LIB = $(OPENAL_DIR)libs/$(TARGET_ABI)/libopenal.so
OPENAL_TIMESTAMP = $(OPENAL_DIR)/timestamp OPENAL_TIMESTAMP = $(OPENAL_DIR)/timestamp
OPENAL_TIMESTAMP_INT = $(ROOT)/deps/openal_timestamp OPENAL_TIMESTAMP_INT = $(ANDR_ROOT)/deps/openal_timestamp
OPENAL_URL_GIT = https://github.com/apportable/openal-soft OPENAL_URL_GIT = https://github.com/apportable/openal-soft
OGG_DIR = $(ROOT)/deps/libvorbis-libogg-android/ OGG_DIR = $(ANDR_ROOT)/deps/libvorbis-libogg-android/
OGG_LIB = $(OGG_DIR)libs/$(TARGET_ABI)/libogg.so OGG_LIB = $(OGG_DIR)libs/$(TARGET_ABI)/libogg.so
VORBIS_LIB = $(OGG_DIR)libs/$(TARGET_ABI)/libogg.so VORBIS_LIB = $(OGG_DIR)libs/$(TARGET_ABI)/libogg.so
OGG_TIMESTAMP = $(OGG_DIR)timestamp OGG_TIMESTAMP = $(OGG_DIR)timestamp
OGG_TIMESTAMP_INT = $(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_DIR = $(ROOT)/deps/irrlicht/ IRRLICHT_REVISION = 5122
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 = $(ROOT)/deps/irrlicht_timestamp IRRLICHT_TIMESTAMP_INT = $(ANDR_ROOT)/deps/irrlicht_timestamp
IRRLICHT_URL_SVN = http://svn.code.sf.net/p/irrlicht/code/branches/ogl-es/ IRRLICHT_URL_SVN = https://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@$(IRRLICHT_REVISION)
OPENSSL_VERSION = 1.0.1l OPENSSL_VERSION = 1.0.2h
OPENSSL_BASEDIR = openssl-$(OPENSSL_VERSION) OPENSSL_BASEDIR = openssl-$(OPENSSL_VERSION)
OPENSSL_DIR = $(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
OPENSSL_TIMESTAMP = $(OPENSSL_DIR)timestamp OPENSSL_TIMESTAMP = $(OPENSSL_DIR)timestamp
OPENSSL_TIMESTAMP_INT = $(ROOT)/deps/openssl_timestamp OPENSSL_TIMESTAMP_INT = $(ANDR_ROOT)/deps/openssl_timestamp
OPENSSL_URL = http://www.openssl.org/source/openssl-$(OPENSSL_VERSION).tar.gz OPENSSL_URL = https://www.openssl.org/source/openssl-$(OPENSSL_VERSION).tar.gz
CURL_VERSION = 7.41.0 CURL_VERSION = 7.48.0
CURL_DIR = $(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
CURL_TIMESTAMP_INT = $(ROOT)/deps/curl_timestamp CURL_TIMESTAMP_INT = $(ANDR_ROOT)/deps/curl_timestamp
CURL_URL_HTTP = http://curl.haxx.se/download/curl-${CURL_VERSION}.tar.bz2 CURL_URL_HTTP = https://curl.haxx.se/download/curl-${CURL_VERSION}.tar.bz2
GMP_VERSION = 6.0.0 GMP_VERSION = 6.1.0
GMP_DIR = $(ROOT)/deps/gmp-$(GMP_VERSION) GMP_DIR = $(ANDR_ROOT)/deps/gmp-$(GMP_VERSION)
GMP_LIB = $(GMP_DIR)/usr/lib/libgmp.so GMP_LIB = $(GMP_DIR)/usr/lib/libgmp.so
GMP_TIMESTAMP = $(GMP_DIR)/timestamp GMP_TIMESTAMP = $(GMP_DIR)/timestamp
GMP_TIMESTAMP_INT = $(ROOT)/deps/gmp_timestamp GMP_TIMESTAMP_INT = $(ANDR_ROOT)/deps/gmp_timestamp
GMP_URL_HTTP = https://gmplib.org/download/gmp/gmp-$(GMP_VERSION).tar.bz2 GMP_URL_HTTP = https://gmplib.org/download/gmp/gmp-$(GMP_VERSION).tar.bz2
FREETYPE_DIR = $(ROOT)/deps/freetype2-android/ FREETYPE_DIR = $(ANDR_ROOT)/deps/freetype2-android/
FREETYPE_LIB = $(FREETYPE_DIR)/Android/obj/local/$(TARGET_ABI)/libfreetype2-static.a FREETYPE_LIB = $(FREETYPE_DIR)/Android/obj/local/$(TARGET_ABI)/libfreetype2-static.a
FREETYPE_TIMESTAMP = $(FREETYPE_DIR)timestamp FREETYPE_TIMESTAMP = $(FREETYPE_DIR)timestamp
FREETYPE_TIMESTAMP_INT = $(ROOT)/deps/freetype_timestamp FREETYPE_TIMESTAMP_INT = $(ANDR_ROOT)/deps/freetype_timestamp
FREETYPE_URL_GIT = https://github.com/cdave1/freetype2-android FREETYPE_URL_GIT = https://github.com/cdave1/freetype2-android
ICONV_VERSION = 1.14 ICONV_VERSION = 1.14
ICONV_DIR = $(ROOT)/deps/libiconv/ ICONV_DIR = $(ANDR_ROOT)/deps/libiconv/
ICONV_LIB = $(ICONV_DIR)/lib/.libs/libiconv.so ICONV_LIB = $(ICONV_DIR)/lib/.libs/libiconv.so
ICONV_TIMESTAMP = $(ICONV_DIR)timestamp ICONV_TIMESTAMP = $(ICONV_DIR)timestamp
ICONV_TIMESTAMP_INT = $(ROOT)/deps/iconv_timestamp ICONV_TIMESTAMP_INT = $(ANDR_ROOT)/deps/iconv_timestamp
ICONV_URL_HTTP = http://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-3080704 SQLITE3_FOLDER = sqlite-amalgamation-3120200
SQLITE3_URL = http://www.sqlite.org/2014/$(SQLITE3_FOLDER).zip SQLITE3_URL = https://www.sqlite.org/2016/$(SQLITE3_FOLDER).zip
-include $(PATHCFGFILE) ANDROID_SDK = $(shell grep '^sdk\.dir' local.properties | sed 's/^.*=[[:space:]]*//')
ANDROID_NDK = $(shell grep '^ndk\.dir' local.properties | sed 's/^.*=[[:space:]]*//')
NDK_MODULE_PATH = $(ANDROID_NDK)/toolchains
#use interim target variable to switch leveldb on or off #use interim target variable to switch leveldb on or off
ifeq ($(HAVE_LEVELDB),1) ifeq ($(HAVE_LEVELDB),1)
@ -162,54 +145,50 @@ endif
freetype_download clean_freetype freetype \ freetype_download clean_freetype freetype \
apk clean_apk \ apk clean_apk \
clean_all clean prep_srcdir \ clean_all clean prep_srcdir \
install_debug install envpaths all \ install_debug install_release envpaths all \
manifest clean_manifest\
$(ASSETS_TIMESTAMP) $(LEVELDB_TIMESTAMP) \ $(ASSETS_TIMESTAMP) $(LEVELDB_TIMESTAMP) \
$(OPENAL_TIMESTAMP) $(OGG_TIMESTAMP) \ $(OPENAL_TIMESTAMP) $(OGG_TIMESTAMP) \
$(IRRLICHT_TIMESTAMP) $(CURL_TIMESTAMP) \ $(IRRLICHT_TIMESTAMP) $(CURL_TIMESTAMP) \
$(OPENSSL_TIMESTAMP) curl_binary \ $(OPENSSL_TIMESTAMP) \
$(ROOT)/jni/src/android_version.h \ $(ANDR_ROOT)/jni/src/android_version.h \
$(ROOT)/jni/src/android_version_githash.h $(ANDR_ROOT)/jni/src/android_version_githash.h
debug : $(PATHCFGFILE) debug : local.properties
export NDEBUG=; \ export NDEBUG=; \
export BUILD_TYPE=debug; \ export BUILD_TYPE=debug; \
$(MAKE) apk $(MAKE) apk
all : debug release all : debug release
release : $(PATHCFGFILE) release : local.properties
@export NDEBUG=1; \ @export NDEBUG=1; \
export BUILD_TYPE=release; \ export BUILD_TYPE=release; \
$(MAKE) apk $(MAKE) apk
reconfig: delconfig reconfig: delconfig
@$(MAKE) $(PATHCFGFILE) @$(MAKE) local.properties
delconfig : delconfig:
$(RM) ${PATHCFGFILE} $(RM) local.properties
$(PATHCFGFILE) : local.properties:
@echo "Please specify path of ANDROID NDK"; \ @echo "Please specify path of ANDROID NDK"; \
echo "e.g. /home/user/android-ndk-r9c/"; \ echo "e.g. $$HOME/Android/ndk-r11c/"; \
read ANDROID_NDK ; \ read ANDROID_NDK ; \
if [ ! -d $$ANDROID_NDK ] ; then \ if [ ! -d $$ANDROID_NDK ] ; then \
echo "$$ANDROID_NDK is not a valid folder"; \ echo "$$ANDROID_NDK is not a valid folder"; \
exit 1; \ exit 1; \
fi; \ fi; \
echo "ANDROID_NDK = $$ANDROID_NDK" > ${PATHCFGFILE}; \ echo "ndk.dir = $$ANDROID_NDK" > local.properties; \
echo "NDK_MODULE_PATH = $$ANDROID_NDK/toolchains" >> ${PATHCFGFILE}; \
echo "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";\
echo "+ Note: NDK_MODULE_PATH is set to $$ANDROID_NDK/toolchains"; \
echo "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";\
echo "Please specify path of ANDROID SDK"; \ echo "Please specify path of ANDROID SDK"; \
echo "e.g. /home/user/adt-bundle-linux-x86_64-20131030/sdk/"; \ echo "e.g. $$HOME/Android/sdk/"; \
read SDKFLDR ; \ read SDKFLDR ; \
if [ ! -d $$SDKFLDR ] ; then \ if [ ! -d $$SDKFLDR ] ; then \
echo "$$SDKFLDR is not a valid folder"; \ echo "$$SDKFLDR is not a valid folder"; \
exit 1; \ exit 1; \
fi; \ fi; \
echo "SDKFOLDER = $$SDKFLDR" >> ${PATHCFGFILE}; echo "sdk.dir = $$SDKFLDR" >> local.properties;
$(OPENAL_TIMESTAMP) : openal_download $(OPENAL_TIMESTAMP) : openal_download
@LAST_MODIF=$$(find ${OPENAL_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ @LAST_MODIF=$$(find ${OPENAL_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
@ -220,15 +199,15 @@ $(OPENAL_TIMESTAMP) : openal_download
openal_download : openal_download :
@if [ ! -d ${OPENAL_DIR} ] ; then \ @if [ ! -d ${OPENAL_DIR} ] ; then \
echo "openal sources missing, downloading..."; \ echo "openal sources missing, downloading..."; \
mkdir -p ${ROOT}/deps; \ mkdir -p ${ANDR_ROOT}/deps; \
cd ${ROOT}/deps ; \ cd ${ANDR_ROOT}/deps ; \
git clone ${OPENAL_URL_GIT} || exit 1; \ git clone ${OPENAL_URL_GIT} || exit 1; \
fi fi
openal : $(OPENAL_LIB) openal : $(OPENAL_LIB)
$(OPENAL_LIB): $(OPENAL_TIMESTAMP) $(OPENAL_LIB): $(OPENAL_TIMESTAMP)
@REFRESH=0; \ + @REFRESH=0; \
if [ ! -e ${OPENAL_TIMESTAMP_INT} ] ; then \ if [ ! -e ${OPENAL_TIMESTAMP_INT} ] ; then \
REFRESH=1; \ REFRESH=1; \
fi; \ fi; \
@ -236,12 +215,12 @@ $(OPENAL_LIB): $(OPENAL_TIMESTAMP)
REFRESH=1; \ REFRESH=1; \
fi; \ fi; \
if [ $$REFRESH -ne 0 ] ; then \ if [ $$REFRESH -ne 0 ] ; then \
export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \
echo "changed timestamp for openal detected building..."; \ echo "changed timestamp for openal detected building..."; \
cd ${OPENAL_DIR}; \ cd ${OPENAL_DIR}; \
ndk-build NDEBUG=${NDEBUG} NDK_MODULE_PATH=${NDK_MODULE_PATH} \ ${ANDROID_NDK}/ndk-build NDEBUG=${NDEBUG} \
APP_ABI=${TARGET_ABI} TARGET_ARCH_ABI=${TARGET_ABI} \ NDK_MODULE_PATH=${NDK_MODULE_PATH} APP_ABI=${TARGET_ABI} \
APP_PLATFORM=${APP_PLATFORM} TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \ TARGET_ARCH_ABI=${TARGET_ABI} APP_PLATFORM=${APP_PLATFORM} \
TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \
TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \ TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \
TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" || exit 1; \ TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" || exit 1; \
touch ${OPENAL_TIMESTAMP}; \ touch ${OPENAL_TIMESTAMP}; \
@ -262,18 +241,18 @@ $(OGG_TIMESTAMP) : ogg_download
ogg_download : ogg_download :
@if [ ! -d ${OGG_DIR} ] ; then \ @if [ ! -d ${OGG_DIR} ] ; then \
echo "ogg sources missing, downloading..."; \ echo "ogg sources missing, downloading..."; \
mkdir -p ${ROOT}/deps; \ mkdir -p ${ANDR_ROOT}/deps; \
cd ${ROOT}/deps ; \ cd ${ANDR_ROOT}/deps ; \
git clone ${OGG_URL_GIT}|| exit 1; \ git clone ${OGG_URL_GIT}|| exit 1; \
cd libvorbis-libogg-android ; \ cd libvorbis-libogg-android ; \
patch -p1 < ../../libvorbis-libogg-fpu.patch || exit 1; \ patch -p1 < ${ANDR_ROOT}/patches/libvorbis-libogg-fpu.patch || exit 1; \
sed -i 's-:-?-' jni/Application.mk; \ sed -i 's-:-?-' jni/Application.mk; \
fi fi
ogg : $(OGG_LIB) ogg : $(OGG_LIB)
$(OGG_LIB): $(OGG_TIMESTAMP) $(OGG_LIB): $(OGG_TIMESTAMP)
@REFRESH=0; \ + @REFRESH=0; \
if [ ! -e ${OGG_TIMESTAMP_INT} ] ; then \ if [ ! -e ${OGG_TIMESTAMP_INT} ] ; then \
echo "${OGG_TIMESTAMP_INT} doesn't exist"; \ echo "${OGG_TIMESTAMP_INT} doesn't exist"; \
REFRESH=1; \ REFRESH=1; \
@ -282,10 +261,10 @@ $(OGG_LIB): $(OGG_TIMESTAMP)
REFRESH=1; \ REFRESH=1; \
fi; \ fi; \
if [ $$REFRESH -ne 0 ] ; then \ if [ $$REFRESH -ne 0 ] ; then \
export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \
echo "changed timestamp for ogg detected building..."; \ echo "changed timestamp for ogg detected building..."; \
cd ${OGG_DIR}; \ cd ${OGG_DIR}; \
ndk-build NDEBUG=${NDEBUG} NDK_MODULE_PATH=${NDK_MODULE_PATH} \ ${ANDROID_NDK}/ndk-build NDEBUG=${NDEBUG} \
NDK_MODULE_PATH=${NDK_MODULE_PATH} \
APP_ABI=${TARGET_ABI} APP_PLATFORM=${APP_PLATFORM} \ APP_ABI=${TARGET_ABI} APP_PLATFORM=${APP_PLATFORM} \
TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \ TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \
TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \ TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \
@ -308,17 +287,17 @@ $(OPENSSL_TIMESTAMP) : openssl_download
openssl_download : openssl_download :
@if [ ! -d ${OPENSSL_DIR} ] ; then \ @if [ ! -d ${OPENSSL_DIR} ] ; then \
echo "openssl sources missing, downloading..."; \ echo "openssl sources missing, downloading..."; \
mkdir -p ${ROOT}/deps; \ mkdir -p ${ANDR_ROOT}/deps; \
cd ${ROOT}/deps ; \ cd ${ANDR_ROOT}/deps ; \
wget ${OPENSSL_URL} || exit 1; \ wget ${OPENSSL_URL} || exit 1; \
tar -xzf ${OPENSSL_BASEDIR}.tar.gz; \ tar -xzf ${OPENSSL_BASEDIR}.tar.gz; \
cd ${OPENSSL_BASEDIR}; \ cd ${OPENSSL_BASEDIR}; \
patch -p1 < ../../openssl_arch.patch; \ patch -p1 < ${ANDR_ROOT}/patches/openssl_arch.patch; \
fi fi
openssl : $(OPENSSL_LIB) openssl : $(OPENSSL_LIB)
$(OPENSSL_LIB): $(OPENSSL_TIMESTAMP) $(OPENSSL_LIB): $(OPENSSL_TIMESTAMP) $(GMP_LIB)
@REFRESH=0; \ @REFRESH=0; \
if [ ! -e ${OPENSSL_TIMESTAMP_INT} ] ; then \ if [ ! -e ${OPENSSL_TIMESTAMP_INT} ] ; then \
echo "${OPENSSL_TIMESTAMP_INT} doesn't exist"; \ echo "${OPENSSL_TIMESTAMP_INT} doesn't exist"; \
@ -336,7 +315,8 @@ $(OPENSSL_LIB): $(OPENSSL_TIMESTAMP)
--toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \ --toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \
--install-dir=$${TOOLCHAIN}; \ --install-dir=$${TOOLCHAIN}; \
export PATH="$${TOOLCHAIN}/bin:$${PATH}"; \ export PATH="$${TOOLCHAIN}/bin:$${PATH}"; \
CC=${CROSS_PREFIX}gcc ./Configure android-${TARGET_ARCH} no-idea no-seed -no-sha0 -DL_ENDIAN;\ CC=${CROSS_PREFIX}gcc ./Configure enable-gmp -DL_ENDIAN -I${GMP_DIR} -L${GMP_DIR}/usr/lib android-${TARGET_ARCH};\
CC=${CROSS_PREFIX}gcc ANDROID_DEV=/tmp/ndk-${TARGET_HOST} make depend; \
CC=${CROSS_PREFIX}gcc ANDROID_DEV=/tmp/ndk-${TARGET_HOST} make build_libs; \ CC=${CROSS_PREFIX}gcc ANDROID_DEV=/tmp/ndk-${TARGET_HOST} make build_libs; \
touch ${OPENSSL_TIMESTAMP}; \ touch ${OPENSSL_TIMESTAMP}; \
touch ${OPENSSL_TIMESTAMP_INT}; \ touch ${OPENSSL_TIMESTAMP_INT}; \
@ -347,8 +327,8 @@ $(OPENSSL_LIB): $(OPENSSL_TIMESTAMP)
clean_openssl : clean_openssl :
$(RM) -rf ${OPENSSL_DIR}; \ $(RM) -rf ${OPENSSL_DIR}; \
$(RM) -rf $(ROOT)/deps/${OPENSSL_BASEDIR}.tar.gz; \ $(RM) -rf $(ANDR_ROOT)/deps/${OPENSSL_BASEDIR}.tar.gz; \
$(RM) -rf $(ROOT)/deps/openssl $(RM) -rf $(ANDR_ROOT)/deps/openssl
$(LEVELDB_TIMESTAMP) : leveldb_download $(LEVELDB_TIMESTAMP) : leveldb_download
@LAST_MODIF=$$(find ${LEVELDB_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ @LAST_MODIF=$$(find ${LEVELDB_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
@ -359,9 +339,11 @@ $(LEVELDB_TIMESTAMP) : leveldb_download
leveldb_download : leveldb_download :
@if [ ! -d ${LEVELDB_DIR} ] ; then \ @if [ ! -d ${LEVELDB_DIR} ] ; then \
echo "leveldb sources missing, downloading..."; \ echo "leveldb sources missing, downloading..."; \
mkdir -p ${ROOT}/deps; \ mkdir -p ${ANDR_ROOT}/deps; \
cd ${ROOT}/deps ; \ cd ${ANDR_ROOT}/deps ; \
git clone ${LEVELDB_URL_GIT} || exit 1; \ git clone ${LEVELDB_URL_GIT} || exit 1; \
cd ${LEVELDB_DIR} || exit 1; \
git checkout ${LEVELDB_COMMIT} || exit 1; \
fi fi
leveldb : $(LEVELDB_LIB) leveldb : $(LEVELDB_LIB)
@ -375,7 +357,6 @@ $(LEVELDB_LIB): $(LEVELDB_TIMESTAMP)
REFRESH=1; \ REFRESH=1; \
fi; \ fi; \
if [ $$REFRESH -ne 0 ] ; then \ if [ $$REFRESH -ne 0 ] ; then \
export PATH=$${PATH}:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \
echo "changed timestamp for leveldb detected building..."; \ echo "changed timestamp for leveldb detected building..."; \
cd deps/leveldb; \ cd deps/leveldb; \
export CROSS_PREFIX=${CROSS_PREFIX}; \ export CROSS_PREFIX=${CROSS_PREFIX}; \
@ -387,10 +368,10 @@ $(LEVELDB_LIB): $(LEVELDB_TIMESTAMP)
export CC=${CROSS_PREFIX}gcc; \ export CC=${CROSS_PREFIX}gcc; \
export CXX=${CROSS_PREFIX}g++; \ export CXX=${CROSS_PREFIX}g++; \
export CFLAGS="$${CFLAGS} ${TARGET_CFLAGS_ADDON}"; \ export CFLAGS="$${CFLAGS} ${TARGET_CFLAGS_ADDON}"; \
export CPPFLAGS="$${CPPFLAGS} ${TARGET_CFLAGS_ADDON}"; \ export CPPFLAGS="$${CPPFLAGS} ${TARGET_CXXFLAGS_ADDON}"; \
export LDFLAGS="$${LDFLAGS} ${TARGET_LDFLAGS_ADDON}"; \ export LDFLAGS="$${LDFLAGS} ${TARGET_LDFLAGS_ADDON}"; \
export TARGET_OS=OS_ANDROID_CROSSCOMPILE; \ export TARGET_OS=OS_ANDROID_CROSSCOMPILE; \
$(MAKE) -s || exit 1; \ $(MAKE) || exit 1; \
touch ${LEVELDB_TIMESTAMP}; \ touch ${LEVELDB_TIMESTAMP}; \
touch ${LEVELDB_TIMESTAMP_INT}; \ touch ${LEVELDB_TIMESTAMP_INT}; \
$(RM) -rf $${TOOLCHAIN}; \ $(RM) -rf $${TOOLCHAIN}; \
@ -410,7 +391,7 @@ $(FREETYPE_TIMESTAMP) : freetype_download
freetype_download : freetype_download :
@if [ ! -d ${FREETYPE_DIR} ] ; then \ @if [ ! -d ${FREETYPE_DIR} ] ; then \
echo "freetype sources missing, downloading..."; \ echo "freetype sources missing, downloading..."; \
mkdir -p ${ROOT}/deps; \ mkdir -p ${ANDR_ROOT}/deps; \
cd deps; \ cd deps; \
git clone ${FREETYPE_URL_GIT} || exit 1; \ git clone ${FREETYPE_URL_GIT} || exit 1; \
fi fi
@ -418,7 +399,7 @@ freetype_download :
freetype : $(FREETYPE_LIB) freetype : $(FREETYPE_LIB)
$(FREETYPE_LIB) : $(FREETYPE_TIMESTAMP) $(FREETYPE_LIB) : $(FREETYPE_TIMESTAMP)
@REFRESH=0; \ + @REFRESH=0; \
if [ ! -e ${FREETYPE_TIMESTAMP_INT} ] ; then \ if [ ! -e ${FREETYPE_TIMESTAMP_INT} ] ; then \
REFRESH=1; \ REFRESH=1; \
fi; \ fi; \
@ -430,10 +411,10 @@ $(FREETYPE_LIB) : $(FREETYPE_TIMESTAMP)
fi; \ fi; \
if [ $$REFRESH -ne 0 ] ; then \ if [ $$REFRESH -ne 0 ] ; then \
mkdir -p ${FREETYPE_DIR}; \ mkdir -p ${FREETYPE_DIR}; \
export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \
echo "changed timestamp for freetype detected building..."; \ echo "changed timestamp for freetype detected building..."; \
cd ${FREETYPE_DIR}/Android/jni; \ cd ${FREETYPE_DIR}/Android/jni; \
ndk-build NDEBUG=${NDEBUG} NDK_MODULE_PATH=${NDK_MODULE_PATH} \ ${ANDROID_NDK}/ndk-build NDEBUG=${NDEBUG} \
NDK_MODULE_PATH=${NDK_MODULE_PATH} \
APP_PLATFORM=${APP_PLATFORM} APP_ABI=${TARGET_ABI} \ APP_PLATFORM=${APP_PLATFORM} APP_ABI=${TARGET_ABI} \
TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \ TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \
TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \ TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \
@ -456,15 +437,15 @@ $(ICONV_TIMESTAMP) : iconv_download
iconv_download : iconv_download :
@if [ ! -d ${ICONV_DIR} ] ; then \ @if [ ! -d ${ICONV_DIR} ] ; then \
echo "iconv sources missing, downloading..."; \ echo "iconv sources missing, downloading..."; \
mkdir -p ${ROOT}/deps; \ mkdir -p ${ANDR_ROOT}/deps; \
cd ${ROOT}/deps; \ cd ${ANDR_ROOT}/deps; \
wget ${ICONV_URL_HTTP} || exit 1; \ wget ${ICONV_URL_HTTP} || exit 1; \
tar -xzf libiconv-${ICONV_VERSION}.tar.gz || exit 1; \ tar -xzf libiconv-${ICONV_VERSION}.tar.gz || exit 1; \
rm libiconv-${ICONV_VERSION}.tar.gz; \ rm libiconv-${ICONV_VERSION}.tar.gz; \
ln -s libiconv-${ICONV_VERSION} libiconv; \ ln -s libiconv-${ICONV_VERSION} libiconv; \
cd ${ICONV_DIR}; \ cd ${ICONV_DIR}; \
patch -p1 < ${ROOT}/libiconv_android.patch; \ patch -p1 < ${ANDR_ROOT}/patches/libiconv_android.patch; \
patch -p1 < ${ROOT}/libiconv_stdio.patch; \ patch -p1 < ${ANDR_ROOT}/patches/libiconv_stdio.patch; \
fi fi
iconv : $(ICONV_LIB) iconv : $(ICONV_LIB)
@ -482,7 +463,6 @@ $(ICONV_LIB) : $(ICONV_TIMESTAMP)
fi; \ fi; \
if [ $$REFRESH -ne 0 ] ; then \ if [ $$REFRESH -ne 0 ] ; then \
mkdir -p ${ICONV_DIR}; \ mkdir -p ${ICONV_DIR}; \
export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \
echo "changed timestamp for iconv detected building..."; \ echo "changed timestamp for iconv detected building..."; \
cd ${ICONV_DIR}; \ cd ${ICONV_DIR}; \
\ \
@ -516,13 +496,13 @@ clean_iconv :
irrlicht_download : irrlicht_download :
@if [ ! -d "deps/irrlicht" ] ; then \ @if [ ! -d "deps/irrlicht" ] ; then \
echo "irrlicht sources missing, downloading..."; \ echo "irrlicht sources missing, downloading..."; \
mkdir -p ${ROOT}/deps; \ mkdir -p ${ANDR_ROOT}/deps; \
cd deps; \ cd deps; \
svn co ${IRRLICHT_URL_SVN} irrlicht || exit 1; \ svn co ${IRRLICHT_URL_SVN} irrlicht || exit 1; \
cd irrlicht; \ cd irrlicht; \
patch -p1 < ../../irrlicht-touchcount.patch || exit 1; \ patch -p1 < ${ANDR_ROOT}/patches/irrlicht-touchcount.patch || exit 1; \
patch -p1 < ../../irrlicht-back_button.patch || exit 1; \ patch -p1 < ${ANDR_ROOT}/patches/irrlicht-back_button.patch || exit 1; \
patch -p1 < ../../irrlicht-texturehack.patch || exit 1; \ patch -p1 < ${ANDR_ROOT}/patches/irrlicht-texturehack.patch || exit 1; \
fi fi
$(IRRLICHT_TIMESTAMP) : irrlicht_download $(IRRLICHT_TIMESTAMP) : irrlicht_download
@ -534,7 +514,7 @@ $(IRRLICHT_TIMESTAMP) : irrlicht_download
irrlicht : $(IRRLICHT_LIB) irrlicht : $(IRRLICHT_LIB)
$(IRRLICHT_LIB): $(IRRLICHT_TIMESTAMP) $(FREETYPE_LIB) $(IRRLICHT_LIB): $(IRRLICHT_TIMESTAMP) $(FREETYPE_LIB)
@REFRESH=0; \ + @REFRESH=0; \
if [ ! -e ${IRRLICHT_TIMESTAMP_INT} ] ; then \ if [ ! -e ${IRRLICHT_TIMESTAMP_INT} ] ; then \
REFRESH=1; \ REFRESH=1; \
fi; \ fi; \
@ -546,10 +526,10 @@ $(IRRLICHT_LIB): $(IRRLICHT_TIMESTAMP) $(FREETYPE_LIB)
fi; \ fi; \
if [ $$REFRESH -ne 0 ] ; then \ if [ $$REFRESH -ne 0 ] ; then \
mkdir -p ${IRRLICHT_DIR}; \ mkdir -p ${IRRLICHT_DIR}; \
export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \
echo "changed timestamp for irrlicht detected building..."; \ echo "changed timestamp for irrlicht detected building..."; \
cd deps/irrlicht/source/Irrlicht/Android; \ cd deps/irrlicht/source/Irrlicht/Android; \
ndk-build NDEBUG=${NDEBUG} NDK_MODULE_PATH=${NDK_MODULE_PATH} \ ${ANDROID_NDK}/ndk-build NDEBUG=${NDEBUG} \
NDK_MODULE_PATH=${NDK_MODULE_PATH} \
APP_ABI=${TARGET_ABI} APP_PLATFORM=${APP_PLATFORM} \ APP_ABI=${TARGET_ABI} APP_PLATFORM=${APP_PLATFORM} \
TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \ TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \
TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \ TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \
@ -572,7 +552,7 @@ $(CURL_TIMESTAMP) : curl_download
curl_download : curl_download :
@if [ ! -d "deps/curl-${CURL_VERSION}" ] ; then \ @if [ ! -d "deps/curl-${CURL_VERSION}" ] ; then \
echo "curl sources missing, downloading..."; \ echo "curl sources missing, downloading..."; \
mkdir -p ${ROOT}/deps; \ mkdir -p ${ANDR_ROOT}/deps; \
cd deps; \ cd deps; \
wget ${CURL_URL_HTTP} || exit 1; \ wget ${CURL_URL_HTTP} || exit 1; \
tar -xjf curl-${CURL_VERSION}.tar.bz2 || exit 1; \ tar -xjf curl-${CURL_VERSION}.tar.bz2 || exit 1; \
@ -595,7 +575,6 @@ $(CURL_LIB): $(CURL_TIMESTAMP) $(OPENSSL_LIB)
fi; \ fi; \
if [ $$REFRESH -ne 0 ] ; then \ if [ $$REFRESH -ne 0 ] ; then \
mkdir -p ${CURL_DIR}; \ mkdir -p ${CURL_DIR}; \
export PATH="$${PATH}:${SDKFOLDER}/platform-tools:${ANDROID_NDK}"; \
echo "changed timestamp for curl detected building..."; \ echo "changed timestamp for curl detected building..."; \
cd deps/curl-${CURL_VERSION}; \ cd deps/curl-${CURL_VERSION}; \
export CROSS_PREFIX=${CROSS_PREFIX}; \ export CROSS_PREFIX=${CROSS_PREFIX}; \
@ -607,8 +586,7 @@ $(CURL_LIB): $(CURL_TIMESTAMP) $(OPENSSL_LIB)
export CC=${CROSS_PREFIX}gcc; \ export CC=${CROSS_PREFIX}gcc; \
export CXX=${CROSS_PREFIX}g++; \ export CXX=${CROSS_PREFIX}g++; \
export TARGET_OS=OS_ANDROID_CROSSCOMPILE; \ export TARGET_OS=OS_ANDROID_CROSSCOMPILE; \
export CPPFLAGS="$${CPPFLAGS} -I${OPENSSL_DIR}/include \ export CPPFLAGS="$${CPPFLAGS} -I${OPENSSL_DIR}/include ${TARGET_CFLAGS_ADDON}"; \
-L${OPENSSL_DIR} ${TARGET_CFLAGS_ADDON}"; \
export CFLAGS="$${CFLAGS} ${TARGET_CFLAGS_ADDON}"; \ export CFLAGS="$${CFLAGS} ${TARGET_CFLAGS_ADDON}"; \
export LDFLAGS="$${LDFLAGS} -L${OPENSSL_DIR} ${TARGET_LDFLAGS_ADDON}"; \ export LDFLAGS="$${LDFLAGS} -L${OPENSSL_DIR} ${TARGET_LDFLAGS_ADDON}"; \
./configure --host=${TARGET_HOST} --disable-shared --enable-static --with-ssl; \ ./configure --host=${TARGET_HOST} --disable-shared --enable-static --with-ssl; \
@ -624,18 +602,6 @@ clean_curl :
$(RM) -rf deps/curl-${CURL_VERSION} \ $(RM) -rf deps/curl-${CURL_VERSION} \
$(RM) -f deps/curl $(RM) -f deps/curl
curl_binary:
@if [ ! -d "deps/curl-${CURL_VERSION_BINARY}" ] ; then \
echo "curl binary missing, downloading..."; \
mkdir -p ${ROOT}/deps; \
cd deps; \
wget http://curl.haxx.se/gknw.net/7.34.0/dist-android/curl-7.34.0-rtmp-ssh2-ssl-zlib-static-bin-android.tar.gz || exit 1;\
tar -xzf curl-7.34.0-rtmp-ssh2-ssl-zlib-static-bin-android.tar.gz || exit 1;\
mv curl-7.34.0-rtmp-ssh2-ssl-zlib-static-bin-android curl-${CURL_VERSION_BINARY};\
rm curl-7.34.0-rtmp-ssh2-ssl-zlib-static-bin-android.tar.gz; \
fi
$(GMP_TIMESTAMP) : gmp_download $(GMP_TIMESTAMP) : gmp_download
@LAST_MODIF=$$(find ${GMP_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ @LAST_MODIF=$$(find ${GMP_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
@ -645,7 +611,7 @@ $(GMP_TIMESTAMP) : gmp_download
gmp_download : gmp_download :
@if [ ! -d "${GMP_DIR}" ] ; then \ @if [ ! -d "${GMP_DIR}" ] ; then \
echo "gmp sources missing, downloading..."; \ echo "gmp sources missing, downloading..."; \
mkdir -p ${ROOT}/deps; \ mkdir -p ${ANDR_ROOT}/deps; \
cd deps; \ cd deps; \
wget ${GMP_URL_HTTP} || exit 1; \ wget ${GMP_URL_HTTP} || exit 1; \
tar -xjf gmp-${GMP_VERSION}.tar.bz2 || exit 1; \ tar -xjf gmp-${GMP_VERSION}.tar.bz2 || exit 1; \
@ -668,7 +634,6 @@ $(GMP_LIB): $(GMP_TIMESTAMP)
fi; \ fi; \
if [ $$REFRESH -ne 0 ] ; then \ if [ $$REFRESH -ne 0 ] ; then \
mkdir -p ${GMP_DIR}; \ mkdir -p ${GMP_DIR}; \
export PATH="$${PATH}:${SDKFOLDER}/platform-tools:${ANDROID_NDK}"; \
echo "changed timestamp for gmp detected building..."; \ echo "changed timestamp for gmp detected building..."; \
cd deps/gmp-${GMP_VERSION}; \ cd deps/gmp-${GMP_VERSION}; \
export CROSS_PREFIX=${CROSS_PREFIX}; \ export CROSS_PREFIX=${CROSS_PREFIX}; \
@ -707,11 +672,11 @@ clean_sqlite3:
$(RM) -f sqlite $(RM) -f sqlite
$(ASSETS_TIMESTAMP) : $(IRRLICHT_LIB) $(ASSETS_TIMESTAMP) : $(IRRLICHT_LIB)
@mkdir -p ${ROOT}/deps; \ @mkdir -p ${ANDR_ROOT}/deps; \
for DIRNAME in {builtin,client,doc,fonts,games,mods,po,textures}; do \ for DIRNAME in {builtin,client,doc,fonts,games,mods,po,textures}; do \
LAST_MODIF=$$(find ${ROOT}/../../${DIRNAME} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ LAST_MODIF=$$(find ${PROJ_ROOT}/${DIRNAME} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
if [ $$(basename $$LAST_MODIF) != "timestamp" ]; then \ if [ $$(basename $$LAST_MODIF) != "timestamp" ]; then \
touch ${ROOT}/../../${DIRNAME}/timestamp; \ touch ${PROJ_ROOT}/${DIRNAME}/timestamp; \
touch ${ASSETS_TIMESTAMP}; \ touch ${ASSETS_TIMESTAMP}; \
echo ${DIRNAME} changed $$LAST_MODIF; \ echo ${DIRNAME} changed $$LAST_MODIF; \
fi; \ fi; \
@ -721,11 +686,11 @@ $(ASSETS_TIMESTAMP) : $(IRRLICHT_LIB)
touch ${IRRLICHT_DIR}/media/timestamp; \ touch ${IRRLICHT_DIR}/media/timestamp; \
touch ${ASSETS_TIMESTAMP}; \ touch ${ASSETS_TIMESTAMP}; \
fi; \ fi; \
if [ ${ROOT}/../../minetest.conf.example -nt ${ASSETS_TIMESTAMP} ] ; then \ if [ ${PROJ_ROOT}/minetest.conf.example -nt ${ASSETS_TIMESTAMP} ] ; then \
echo "conf changed"; \ echo "conf changed"; \
touch ${ASSETS_TIMESTAMP}; \ touch ${ASSETS_TIMESTAMP}; \
fi; \ fi; \
if [ ${ROOT}/../../README.txt -nt ${ASSETS_TIMESTAMP} ] ; then \ if [ ${PROJ_ROOT}/README.txt -nt ${ASSETS_TIMESTAMP} ] ; then \
touch ${ASSETS_TIMESTAMP}; \ touch ${ASSETS_TIMESTAMP}; \
fi; \ fi; \
if [ ! -e $(ASSETS_TIMESTAMP) ] ; then \ if [ ! -e $(ASSETS_TIMESTAMP) ] ; then \
@ -740,32 +705,34 @@ assets : $(ASSETS_TIMESTAMP)
if [ ${ASSETS_TIMESTAMP} -nt ${ASSETS_TIMESTAMP}.old ] ; then \ if [ ${ASSETS_TIMESTAMP} -nt ${ASSETS_TIMESTAMP}.old ] ; then \
REFRESH=1; \ REFRESH=1; \
fi; \ fi; \
if [ ! -d ${ROOT}/assets ] ; then \ if [ ! -d ${APP_ROOT}/assets ] ; then \
REFRESH=1; \ REFRESH=1; \
fi; \ fi; \
if [ $$REFRESH -ne 0 ] ; then \ if [ $$REFRESH -ne 0 ] ; then \
echo "assets changed, refreshing..."; \ echo "assets changed, refreshing..."; \
$(MAKE) clean_assets; \ $(MAKE) clean_assets; \
mkdir -p ${ROOT}/assets/Minetest; \ mkdir -p ${APP_ROOT}/assets/Minetest; \
cp ${ROOT}/../../minetest.conf.example ${ROOT}/assets/Minetest; \ cp ${PROJ_ROOT}/minetest.conf.example ${APP_ROOT}/assets/Minetest; \
cp ${ROOT}/../../README.txt ${ROOT}/assets/Minetest; \ cp ${PROJ_ROOT}/README.txt ${APP_ROOT}/assets/Minetest; \
cp -r ${ROOT}/../../builtin ${ROOT}/assets/Minetest; \ cp -r ${PROJ_ROOT}/builtin ${APP_ROOT}/assets/Minetest; \
cp -r ${ROOT}/../../client ${ROOT}/assets/Minetest; \ mkdir -p ${APP_ROOT}/assets/Minetest/client; \
cp -r ${ROOT}/../../doc ${ROOT}/assets/Minetest; \ cp -r ${PROJ_ROOT}/client/shaders ${APP_ROOT}/assets/Minetest/client; \
cp -r ${ROOT}/../../fonts ${ROOT}/assets/Minetest; \ cp ${PROJ_ROOT}/doc/lgpl-2.1.txt ${APP_ROOT}/assets/Minetest/LICENSE.txt; \
mkdir ${ROOT}/assets/Minetest/games; \ mkdir -p ${APP_ROOT}/assets/Minetest/fonts; \
cp -r ${PROJ_ROOT}/fonts/*.ttf ${APP_ROOT}/assets/Minetest/fonts/; \
mkdir -p ${APP_ROOT}/assets/Minetest/games; \
for game in ${GAMES_TO_COPY}; do \ for game in ${GAMES_TO_COPY}; do \
cp -r ${ROOT}/../../games/$$game ${ROOT}/assets/Minetest/games/; \ cp -r ${PROJ_ROOT}/games/$$game ${APP_ROOT}/assets/Minetest/games/; \
done; \ done; \
mkdir ${ROOT}/assets/Minetest/mods; \ mkdir -p ${APP_ROOT}/assets/Minetest/mods; \
for mod in ${MODS_TO_COPY}; do \ for mod in ${MODS_TO_COPY}; do \
cp -r ${ROOT}/../../mods/$$mod ${ROOT}/assets/Minetest/mods/; \ cp -r ${PROJ_ROOT}/mods/$$mod ${APP_ROOT}/assets/Minetest/mods/; \
done; \ done; \
cp -r ${ROOT}/../../po ${ROOT}/assets/Minetest; \ cp -r ${PROJ_ROOT}/po ${APP_ROOT}/assets/Minetest; \
cp -r ${ROOT}/../../textures ${ROOT}/assets/Minetest; \ cp -r ${PROJ_ROOT}/textures ${APP_ROOT}/assets/Minetest; \
mkdir -p ${ROOT}/assets/Minetest/media; \ mkdir -p ${APP_ROOT}/assets/Minetest/media; \
cp -r ${IRRLICHT_DIR}/media/Shaders ${ROOT}/assets/Minetest/media; \ cp -r ${IRRLICHT_DIR}/media/Shaders ${APP_ROOT}/assets/Minetest/media; \
cd ${ROOT}/assets || exit 1; \ cd ${APP_ROOT}/assets || exit 1; \
find . -name "timestamp" -exec rm {} \; ; \ find . -name "timestamp" -exec rm {} \; ; \
find . -name "*.blend" -exec rm {} \; ; \ find . -name "*.blend" -exec rm {} \; ; \
find . -name "*~" -exec rm {} \; ; \ find . -name "*~" -exec rm {} \; ; \
@ -773,8 +740,8 @@ assets : $(ASSETS_TIMESTAMP)
find . -type d -path "*.svn" -exec rm -rf {} \; ; \ find . -type d -path "*.svn" -exec rm -rf {} \; ; \
find . -type f -path "*.gitignore" -exec rm -rf {} \; ; \ find . -type f -path "*.gitignore" -exec rm -rf {} \; ; \
ls -R | grep ":$$" | sed -e 's/:$$//' -e 's/\.//' -e 's/^\///' > "index.txt"; \ ls -R | grep ":$$" | sed -e 's/:$$//' -e 's/\.//' -e 's/^\///' > "index.txt"; \
find Minetest >"filelist.txt"; \ find -L Minetest > filelist.txt; \
cp ${ROOT}/${ASSETS_TIMESTAMP} ${ROOT}/${ASSETS_TIMESTAMP}.old; \ cp ${ANDR_ROOT}/${ASSETS_TIMESTAMP} ${ANDR_ROOT}/${ASSETS_TIMESTAMP}.old; \
else \ else \
echo "nothing to be done for assets"; \ echo "nothing to be done for assets"; \
fi fi
@ -782,56 +749,50 @@ assets : $(ASSETS_TIMESTAMP)
clean_assets : clean_assets :
@$(RM) -r assets @$(RM) -r assets
apk: $(PATHCFGFILE) assets $(ICONV_LIB) $(IRRLICHT_LIB) $(CURL_LIB) $(GMP_LIB) $(LEVELDB_TARGET) \ apk: local.properties assets $(ICONV_LIB) $(IRRLICHT_LIB) $(CURL_LIB) $(GMP_LIB) $(LEVELDB_TARGET) \
$(OPENAL_LIB) $(OGG_LIB) prep_srcdir $(ROOT)/jni/src/android_version.h \ $(OPENAL_LIB) $(OGG_LIB) prep_srcdir $(ANDR_ROOT)/jni/src/android_version.h \
$(ROOT)/jni/src/android_version_githash.h sqlite3_download $(ANDR_ROOT)/jni/src/android_version_githash.h sqlite3_download
@export NDEBUG=$$NDEBUG; $(MAKE) manifest; \ + @${ANDROID_NDK}/ndk-build NDK_MODULE_PATH=${NDK_MODULE_PATH} \
export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \
export ANDROID_HOME=${SDKFOLDER}; \
mkdir -p ${ROOT}/src; \
ndk-build NDK_MODULE_PATH=${NDK_MODULE_PATH} \
GPROF=${GPROF} APP_ABI=${TARGET_ABI} HAVE_LEVELDB=${HAVE_LEVELDB} \ GPROF=${GPROF} APP_ABI=${TARGET_ABI} HAVE_LEVELDB=${HAVE_LEVELDB} \
APP_PLATFORM=${APP_PLATFORM} \ APP_PLATFORM=${APP_PLATFORM} \
TARGET_LIBDIR=${TARGET_LIBDIR} \ TARGET_LIBDIR=${TARGET_LIBDIR} \
TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \ TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \
TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \ TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \
TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" && \ TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" || exit 1; \
ant $$BUILD_TYPE && \ if [ ! -e ${APP_ROOT}/jniLibs ]; then \
echo "++ Success!" && \ ln -s ${ANDR_ROOT}/libs ${APP_ROOT}/jniLibs || exit 1; \
echo "APK: bin/Minetest-$$BUILD_TYPE.apk" && \ fi; \
echo "You can install it with \`adb install -r bin/Minetest-$$BUILD_TYPE.apk\`" export VERSION_STR="${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}" && \
export BUILD_TYPE_C=$$(echo "$${BUILD_TYPE}" | sed 's/./\U&/') && \
gradle assemble$$BUILD_TYPE_C && \
echo "APK stored at: build/outputs/apk/Minetest-$$BUILD_TYPE.apk" && \
echo "You can install it with \`make install_$$BUILD_TYPE\`"
# These Intentionally doesn't depend on their respective build steps,
# because it takes a while to verify that everything's up-to-date.
install_debug:
${ANDROID_SDK}/platform-tools/adb install -r build/outputs/apk/Minetest-debug.apk
install_release:
${ANDROID_SDK}/platform-tools/adb install -r build/outputs/apk/Minetest-release.apk
prep_srcdir : prep_srcdir :
@if [ ! -e ${ROOT}/jni/src ]; then \ @if [ ! -e ${ANDR_ROOT}/jni/src ]; then \
ln -s ${ROOT}/../../src ${ROOT}/jni/src; \ ln -s ${PROJ_ROOT}/src ${ANDR_ROOT}/jni/src; \
fi fi
clean_apk : manifest clean_apk :
@export PATH=$$PATH:${SDKFOLDER}platform-tools:${ANDROID_NDK}; \ gradle clean
export ANDROID_HOME=${SDKFOLDER}; \
ant clean
install_debug :
@export PATH=$$PATH:${SDKFOLDER}platform-tools:${ANDROID_NDK}; \
adb install -r ${ROOT}/bin/Minetest-debug.apk
install :
@export PATH=$$PATH:${SDKFOLDER}platform-tools:${ANDROID_NDK}; \
adb install -r ${ROOT}/bin/Minetest-release.apk
envpaths :
@echo "export PATH=$$PATH:${SDKFOLDER}platform-tools:${ANDROID_NDK}" > and_env;\
echo "export ANDROID_HOME=${SDKFOLDER}" >> and_env;
clean_all : clean_all :
@$(MAKE) clean_apk; \ @$(MAKE) clean_apk; \
$(MAKE) clean_assets clean_iconv clean_irrlicht clean_leveldb clean_curl clean_openssl \ $(MAKE) clean_assets clean_iconv clean_irrlicht clean_leveldb clean_curl \
clean_openal clean_ogg clean_gmp clean_manifest; \ clean_openssl clean_openal clean_ogg clean_gmp; \
sleep 1; \ sleep 1; \
$(RM) -r gen libs obj deps bin Debug and_env $(RM) -r gen libs obj deps bin Debug and_env
$(ROOT)/jni/src/android_version_githash.h : prep_srcdir $(ANDR_ROOT)/jni/src/android_version_githash.h : prep_srcdir
@export VERSION_FILE=${ROOT}/jni/src/android_version_githash.h; \ @export VERSION_FILE=${ANDR_ROOT}/jni/src/android_version_githash.h; \
export VERSION_FILE_NEW=$${VERSION_FILE}.new; \ export VERSION_FILE_NEW=$${VERSION_FILE}.new; \
{ \ { \
echo "#ifndef ANDROID_MT_VERSION_GITHASH_H"; \ echo "#ifndef ANDROID_MT_VERSION_GITHASH_H"; \
@ -849,8 +810,8 @@ $(ROOT)/jni/src/android_version_githash.h : prep_srcdir
fi fi
$(ROOT)/jni/src/android_version.h : prep_srcdir $(ANDR_ROOT)/jni/src/android_version.h : prep_srcdir
@export VERSION_FILE=${ROOT}/jni/src/android_version.h; \ @export VERSION_FILE=${ANDR_ROOT}/jni/src/android_version.h; \
export VERSION_FILE_NEW=$${VERSION_FILE}.new; \ export VERSION_FILE_NEW=$${VERSION_FILE}.new; \
{ \ { \
echo "#ifndef ANDROID_MT_VERSION_H"; \ echo "#ifndef ANDROID_MT_VERSION_H"; \
@ -858,8 +819,8 @@ $(ROOT)/jni/src/android_version.h : prep_srcdir
echo "#define VERSION_MAJOR ${VERSION_MAJOR}"; \ echo "#define VERSION_MAJOR ${VERSION_MAJOR}"; \
echo "#define VERSION_MINOR ${VERSION_MINOR}"; \ echo "#define VERSION_MINOR ${VERSION_MINOR}"; \
echo "#define VERSION_PATCH ${VERSION_PATCH}"; \ echo "#define VERSION_PATCH ${VERSION_PATCH}"; \
echo "#define VERSION_STRING STR(VERSION_MAJOR)\".\"STR(VERSION_MINOR)\ echo "#define VERSION_STRING STR(VERSION_MAJOR) \".\" STR(VERSION_MINOR) \
\".\"STR(VERSION_PATCH)"; \ \".\" STR(VERSION_PATCH)"; \
echo "#endif"; \ echo "#endif"; \
} > $${VERSION_FILE_NEW}; \ } > $${VERSION_FILE_NEW}; \
if ! cmp -s $${VERSION_FILE} $${VERSION_FILE_NEW}; then \ if ! cmp -s $${VERSION_FILE} $${VERSION_FILE_NEW}; then \
@ -869,22 +830,5 @@ $(ROOT)/jni/src/android_version.h : prep_srcdir
rm "$${VERSION_FILE_NEW}"; \ rm "$${VERSION_FILE_NEW}"; \
fi fi
manifest :
@BASE_VERSION="${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}"; \
if [ "${NDEBUG}x" != "x" ] ; then \
DBG=''; \
DBG_FLAG="android:debuggable=\"false\""; \
else \
DBG="<uses-permission android:name=\"android.permission.SET_DEBUG_APP\" />"; \
DBG_FLAG="android:debuggable=\"true\""; \
fi; \
cat ${ROOT}/AndroidManifest.xml.template | \
sed "s/###ANDROID_VERSION###/${ANDROID_VERSION_CODE}/g" | \
sed "s/###BASE_VERSION###/$$BASE_VERSION/g" | \
sed -e "s@###DEBUG_BUILD###@$$DBG@g" | \
sed -e "s@###DEBUG_FLAG###@$$DBG_FLAG@g" >${ROOT}/AndroidManifest.xml
clean_manifest :
rm -rf ${ROOT}/AndroidManifest.xml
clean : clean_apk clean_assets clean : clean_apk clean_assets

View File

@ -0,0 +1,49 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:1.5.0"
}
}
apply plugin: "com.android.application"
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
defaultConfig {
versionCode 14
versionName "${System.env.VERSION_STR}.${versionCode}"
minSdkVersion 9
targetSdkVersion 9
applicationId "net.minetest.minetest"
manifestPlaceholders = [ package: "net.minetest.minetest", project: project.name ]
}
lintOptions {
disable "OldTargetApi", "GoogleAppIndexingWarning"
}
Properties props = new Properties()
props.load(new FileInputStream(file("local.properties")))
if (props.getProperty("keystore") != null) {
signingConfigs {
release {
storeFile file(props["keystore"])
storePassword props["keystore.password"]
keyAlias props["key"]
keyPassword props["key.password"]
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
}

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="Minetest" default="help">
<property file="local.properties" />
<property file="ant.properties" />
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<loadproperties srcFile="project.properties" />
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<import file="custom_rules.xml" optional="true" />
<import file="${sdk.dir}/tools/ant/build.xml" />
</project>

View File

@ -80,7 +80,7 @@ LOCAL_CFLAGS := -D_IRR_ANDROID_PLATFORM_ \
ifndef NDEBUG ifndef NDEBUG
LOCAL_CFLAGS += -g -D_DEBUG -O0 -fno-omit-frame-pointer LOCAL_CFLAGS += -g -D_DEBUG -O0 -fno-omit-frame-pointer
else else
LOCAL_CFLAGS += -fexpensive-optimizations -O3 LOCAL_CFLAGS += -O3
endif endif
ifdef GPROF ifdef GPROF
@ -96,7 +96,7 @@ LOCAL_CFLAGS += -fno-stack-protector
endif endif
LOCAL_C_INCLUDES := \ LOCAL_C_INCLUDES := \
jni/src jni/src/sqlite \ jni/src \
jni/src/script \ jni/src/script \
jni/src/lua/src \ jni/src/lua/src \
jni/src/json \ jni/src/json \
@ -112,7 +112,6 @@ LOCAL_C_INCLUDES := \
deps/sqlite/ deps/sqlite/
LOCAL_SRC_FILES := \ LOCAL_SRC_FILES := \
jni/src/areastore.cpp \
jni/src/ban.cpp \ jni/src/ban.cpp \
jni/src/camera.cpp \ jni/src/camera.cpp \
jni/src/cavegen.cpp \ jni/src/cavegen.cpp \
@ -173,11 +172,13 @@ LOCAL_SRC_FILES := \
jni/src/mapblock.cpp \ jni/src/mapblock.cpp \
jni/src/mapblock_mesh.cpp \ jni/src/mapblock_mesh.cpp \
jni/src/mapgen.cpp \ jni/src/mapgen.cpp \
jni/src/mapgen_flat.cpp \
jni/src/mapgen_fractal.cpp \ jni/src/mapgen_fractal.cpp \
jni/src/mapgen_singlenode.cpp \ jni/src/mapgen_singlenode.cpp \
jni/src/mapgen_v5.cpp \ jni/src/mapgen_v5.cpp \
jni/src/mapgen_v6.cpp \ jni/src/mapgen_v6.cpp \
jni/src/mapgen_v7.cpp \ jni/src/mapgen_v7.cpp \
jni/src/mapgen_valleys.cpp \
jni/src/mapnode.cpp \ jni/src/mapnode.cpp \
jni/src/mapsector.cpp \ jni/src/mapsector.cpp \
jni/src/mesh.cpp \ jni/src/mesh.cpp \
@ -219,6 +220,7 @@ LOCAL_SRC_FILES := \
jni/src/version.cpp \ jni/src/version.cpp \
jni/src/voxel.cpp \ jni/src/voxel.cpp \
jni/src/voxelalgorithms.cpp \ jni/src/voxelalgorithms.cpp \
jni/src/util/areastore.cpp \
jni/src/util/auth.cpp \ jni/src/util/auth.cpp \
jni/src/util/base64.cpp \ jni/src/util/base64.cpp \
jni/src/util/directiontables.cpp \ jni/src/util/directiontables.cpp \
@ -301,16 +303,16 @@ 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_http.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_game.cpp \
jni/src/script/scripting_mainmenu.cpp jni/src/script/scripting_mainmenu.cpp
#freetype2 support #freetype2 support
LOCAL_SRC_FILES += \ LOCAL_SRC_FILES += jni/src/cguittfont/xCGUITTFont.cpp
jni/src/cguittfont/xCGUITTFont.cpp
# lua # Lua
LOCAL_SRC_FILES += \ LOCAL_SRC_FILES += \
jni/src/lua/src/lapi.c \ jni/src/lua/src/lapi.c \
jni/src/lua/src/lauxlib.c \ jni/src/lua/src/lauxlib.c \
@ -348,6 +350,7 @@ LOCAL_SRC_FILES += deps/sqlite/sqlite3.c
# Threading # Threading
LOCAL_SRC_FILES += \ LOCAL_SRC_FILES += \
jni/src/threading/event.cpp \
jni/src/threading/mutex.cpp \ jni/src/threading/mutex.cpp \
jni/src/threading/semaphore.cpp \ jni/src/threading/semaphore.cpp \
jni/src/threading/thread.cpp jni/src/threading/thread.cpp
@ -370,3 +373,4 @@ 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)

View File

@ -1,4 +1,4 @@
# NDK_TOOLCHAIN_VERSION := clang3.3 # NDK_TOOLCHAIN_VERSION := clang3.8
APP_PLATFORM := android-9 APP_PLATFORM := android-9
APP_MODULES := minetest APP_MODULES := minetest
@ -6,3 +6,4 @@ APP_STL := gnustl_static
APP_CPPFLAGS += -fexceptions APP_CPPFLAGS += -fexceptions
APP_GNUSTL_FORCE_CPP_FEATURES := rtti APP_GNUSTL_FORCE_CPP_FEATURES := rtti

View File

@ -1,14 +1,15 @@
--- irrlicht/source/Irrlicht/Android/CIrrDeviceAndroid.cpp 2014-06-03 20:56:21.289559503 +0200 --- irrlicht/source/Irrlicht/Android/CIrrDeviceAndroid.cpp.orig 2015-08-29 15:43:09.000000000 +0300
+++ irrlicht/source/Irrlicht/Android/CIrrDeviceAndroid.cpp.orig 2014-06-03 20:57:39.281556749 +0200 +++ irrlicht/source/Irrlicht/Android/CIrrDeviceAndroid.cpp 2016-05-13 21:36:22.880388505 +0300
@@ -423,6 +423,7 @@ @@ -486,7 +486,7 @@
event.KeyInput.Char = 0;
} }
device->postEventFromUser(event); - device->postEventFromUser(event);
+ status = 1; + status = device->postEventFromUser(event);
} }
break; break;
default: default:
@@ -479,7 +480,7 @@ @@ -543,7 +543,7 @@
KeyMap[1] = KEY_LBUTTON; // AKEYCODE_SOFT_LEFT KeyMap[1] = KEY_LBUTTON; // AKEYCODE_SOFT_LEFT
KeyMap[2] = KEY_RBUTTON; // AKEYCODE_SOFT_RIGHT KeyMap[2] = KEY_RBUTTON; // AKEYCODE_SOFT_RIGHT
KeyMap[3] = KEY_HOME; // AKEYCODE_HOME KeyMap[3] = KEY_HOME; // AKEYCODE_HOME

View File

@ -1,11 +1,13 @@
--- openssl-1.0.1j/Configure.orig 2014-10-15 14:53:39.000000000 +0200 --- openssl-1.0.2e.orig/Configure 2015-12-03 15:04:23.000000000 +0100
+++ openssl-1.0.1j/Configure 2015-01-03 22:41:43.505749921 +0100 +++ openssl-1.0.2e/Configure 2015-12-14 21:01:40.351265968 +0100
@@ -407,6 +407,8 @@ @@ -464,8 +464,10 @@
# Android: linux-* but without pointers to headers and libs.
"android","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", "android","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
"android-x86","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", "android-x86","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
"android-armv7","gcc:-march=armv7-a -mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"android-arm","gcc:-march=armv4 -mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +"android-arm","gcc:-march=armv4 -mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"android-mips32","gcc:-march=mips32 -mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", "android-armv7","gcc:-march=armv7-a -mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
"android-mips","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+"android-mips32","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
#### *BSD [do see comment about ${BSDthreads} above!] #### *BSD [do see comment about ${BSDthreads} above!]
"BSD-generic32","gcc:-DTERMIOS -O3 -fomit-frame-pointer -Wall::${BSDthreads}:::BN_LLONG RC2_CHAR RC4_INDEX DES_INT DES_UNROLL:${no_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", "BSD-generic32","gcc:-O3 -fomit-frame-pointer -Wall::${BSDthreads}:::BN_LLONG RC2_CHAR RC4_INDEX DES_INT DES_UNROLL:${no_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",

View File

@ -1 +0,0 @@
target=android-10

View File

@ -0,0 +1,2 @@
rootProject.name = "Minetest"

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.SET_DEBUG_APP" />
</manifest>

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.minetest.minetest"
android:installLocation="auto">
<uses-feature android:glEsVersion="0x00010000" android:required="true"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application android:icon="@drawable/irr_icon"
android:label="${project}"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:allowBackup="true">
<activity android:name=".MtNativeActivity"
android:label="${project}"
android:launchMode="singleTask"
android:configChanges="orientation|keyboard|keyboardHidden|navigation"
android:screenOrientation="sensorLandscape"
android:clearTaskOnLaunch="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="android.app.lib_name" android:value="minetest" />
</activity>
<activity android:name=".MinetestTextEntry"
android:theme="@style/Theme.Transparent"
android:excludeFromRecents="true">
</activity>
<activity android:name=".MinetestAssetCopy"
android:theme="@style/Theme.Transparent"
android:excludeFromRecents="true">
</activity>
</application>
</manifest>

View File

@ -254,55 +254,15 @@ public class MinetestAssetCopy extends Activity
boolean shortened = false; boolean shortened = false;
String todisplay = m_tocopy.get(progress[0]); String todisplay = m_tocopy.get(progress[0]);
m_ProgressBar.setProgress(progress[0]); m_ProgressBar.setProgress(progress[0]);
// make sure our text doesn't exceed our layout width
Rect bounds = new Rect();
Paint textPaint = m_Filename.getPaint();
textPaint.getTextBounds(todisplay, 0, todisplay.length(), bounds);
while (bounds.width() > getResources().getDisplayMetrics().widthPixels * 0.7) {
if (todisplay.length() < 2) {
break;
}
todisplay = todisplay.substring(1);
textPaint.getTextBounds(todisplay, 0, todisplay.length(), bounds);
shortened = true;
}
if (! shortened) {
m_Filename.setText(todisplay); m_Filename.setText(todisplay);
} }
else {
m_Filename.setText(".." + todisplay);
}
}
else else
{ {
boolean shortened = false; boolean shortened = false;
String todisplay = m_Foldername; String todisplay = m_Foldername;
String full_text = "scanning " + todisplay + " ..."; String full_text = "scanning " + todisplay + " ...";
// make sure our text doesn't exceed our layout width
Rect bounds = new Rect();
Paint textPaint = m_Filename.getPaint();
textPaint.getTextBounds(full_text, 0, full_text.length(), bounds);
while (bounds.width() > getResources().getDisplayMetrics().widthPixels * 0.7) {
if (todisplay.length() < 2) {
break;
}
todisplay = todisplay.substring(1);
full_text = "scanning " + todisplay + " ...";
textPaint.getTextBounds(full_text, 0, full_text.length(), bounds);
shortened = true;
}
if (! shortened) {
m_Filename.setText(full_text); m_Filename.setText(full_text);
} }
else {
m_Filename.setText("scanning .." + todisplay + " ...");
}
}
} }
/** /**

View File

@ -20,6 +20,10 @@ public class MtNativeActivity extends NativeActivity {
super.onDestroy(); super.onDestroy();
} }
@Override
public void onBackPressed() {
}
public void copyAssets() { public void copyAssets() {
Intent intent = new Intent(this, MinetestAssetCopy.class); Intent intent = new Intent(this, MinetestAssetCopy.class);

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

@ -13,10 +13,12 @@
<TextView <TextView
android:id="@+id/textView1" android:id="@+id/textView1"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:ellipsize="middle"
android:singleLine="true"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:text="preparing media ..." android:text="@string/preparing_media"
android:textAppearance="?android:attr/textAppearanceSmall" /> android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout> </LinearLayout>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="preparing_media">Preparing media...</string>
</resources>

View File

@ -189,7 +189,7 @@ function filterlist.process(self)
for k,v in pairs(self.m_raw_list) do for k,v in pairs(self.m_raw_list) do
if self.m_filtercriteria == nil or if self.m_filtercriteria == nil or
self.m_filter_fct(v,self.m_filtercriteria) then self.m_filter_fct(v,self.m_filtercriteria) then
table.insert(self.m_processed_list,v) self.m_processed_list[#self.m_processed_list + 1] = v
end end
end end

View File

@ -2,7 +2,6 @@
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Localize functions to avoid table lookups (better performance). -- Localize functions to avoid table lookups (better performance).
local table_insert = table.insert
local string_sub, string_find = string.sub, string.find local string_sub, string_find = string.sub, string.find
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -94,13 +93,13 @@ function dump2(o, name, dumped)
-- the form _G["table: 0xFFFFFFF"] -- the form _G["table: 0xFFFFFFF"]
keyStr = string.format("_G[%q]", tostring(k)) keyStr = string.format("_G[%q]", tostring(k))
-- Dump key table -- Dump key table
table_insert(t, dump2(k, keyStr, dumped)) t[#t + 1] = dump2(k, keyStr, dumped)
end end
else else
keyStr = basic_dump(k) keyStr = basic_dump(k)
end end
local vname = string.format("%s[%s]", name, keyStr) local vname = string.format("%s[%s]", name, keyStr)
table_insert(t, dump2(v, vname, dumped)) t[#t + 1] = dump2(v, vname, dumped)
end end
return string.format("%s = {}\n%s", name, table.concat(t)) return string.format("%s = {}\n%s", name, table.concat(t))
end end
@ -135,7 +134,7 @@ function dump(o, indent, nested, level)
local t = {} local t = {}
local dumped_indexes = {} local dumped_indexes = {}
for i, v in ipairs(o) do for i, v in ipairs(o) do
table_insert(t, dump(v, indent, nested, level + 1)) t[#t + 1] = dump(v, indent, nested, level + 1)
dumped_indexes[i] = true dumped_indexes[i] = true
end end
for k, v in pairs(o) do for k, v in pairs(o) do
@ -144,7 +143,7 @@ function dump(o, indent, nested, level)
k = "["..dump(k, indent, nested, level + 1).."]" k = "["..dump(k, indent, nested, level + 1).."]"
end end
v = dump(v, indent, nested, level + 1) v = dump(v, indent, nested, level + 1)
table_insert(t, k.." = "..v) t[#t + 1] = k.." = "..v
end end
end end
nested[o] = nil nested[o] = nil
@ -177,7 +176,7 @@ function string.split(str, delim, include_empty, max_splits, sep_is_pattern)
local s = string_sub(str, pos, np - 1) local s = string_sub(str, pos, np - 1)
if include_empty or (s ~= "") then if include_empty or (s ~= "") then
max_splits = max_splits - 1 max_splits = max_splits - 1
table_insert(items, s) items[#items + 1] = s
end end
pos = npe + 1 pos = npe + 1
until (max_splits == 0) or (pos > (len + 1)) until (max_splits == 0) or (pos > (len + 1))
@ -186,8 +185,8 @@ end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function table.indexof(list, val) function table.indexof(list, val)
for i = 1, #list do for i, v in ipairs(list) do
if list[i] == val then if v == val then
return i return i
end end
end end
@ -324,7 +323,7 @@ function core.splittext(text,charlimit)
local last_line = "" local last_line = ""
while start ~= nil do while start ~= nil do
if string.len(last_line) + (stop-start) > charlimit then if string.len(last_line) + (stop-start) > charlimit then
table_insert(retval, last_line) retval[#retval + 1] = last_line
last_line = "" last_line = ""
end end
@ -335,7 +334,7 @@ function core.splittext(text,charlimit)
last_line = last_line .. string_sub(text, current_idx, stop - 1) last_line = last_line .. string_sub(text, current_idx, stop - 1)
if gotnewline then if gotnewline then
table_insert(retval, last_line) retval[#retval + 1] = last_line
last_line = "" last_line = ""
gotnewline = false gotnewline = false
end end
@ -353,11 +352,11 @@ function core.splittext(text,charlimit)
--add last part of text --add last part of text
if string.len(last_line) + (string.len(text) - current_idx) > charlimit then if string.len(last_line) + (string.len(text) - current_idx) > charlimit then
table_insert(retval, last_line) retval[#retval + 1] = last_line
table_insert(retval, string_sub(text, current_idx)) retval[#retval + 1] = string_sub(text, current_idx)
else else
last_line = last_line .. " " .. string_sub(text, current_idx) last_line = last_line .. " " .. string_sub(text, current_idx)
table_insert(retval, last_line) retval[#retval + 1] = last_line
end end
return retval return retval
@ -430,14 +429,14 @@ if INIT == "game" then
if iswall then if iswall then
core.set_node(pos, {name = wield_name, core.set_node(pos, {name = wield_name,
param2 = dirs1[fdir+1]}) param2 = dirs1[fdir + 1]})
elseif isceiling then elseif isceiling then
if orient_flags.force_facedir then if orient_flags.force_facedir then
core.set_node(pos, {name = wield_name, core.set_node(pos, {name = wield_name,
param2 = 20}) param2 = 20})
else else
core.set_node(pos, {name = wield_name, core.set_node(pos, {name = wield_name,
param2 = dirs2[fdir+1]}) param2 = dirs2[fdir + 1]})
end end
else -- place right side up else -- place right side up
if orient_flags.force_facedir then if orient_flags.force_facedir then

View File

@ -104,7 +104,7 @@ function core.serialize(x)
local i = local_index local i = local_index
local_index = local_index + 1 local_index = local_index + 1
var = "_["..i.."]" var = "_["..i.."]"
table.insert(local_defs, var.." = "..val) local_defs[#local_defs + 1] = var.." = "..val
dumped[x] = var dumped[x] = var
return var return var
end end
@ -135,16 +135,15 @@ function core.serialize(x)
local np = nest_points[x] local np = nest_points[x]
for i, v in ipairs(x) do for i, v in ipairs(x) do
if not np or not np[i] then if not np or not np[i] then
table.insert(vals, dump_or_ref_val(v)) vals[#vals + 1] = dump_or_ref_val(v)
end end
idx_dumped[i] = true idx_dumped[i] = true
end end
for k, v in pairs(x) do for k, v in pairs(x) do
if (not np or not np[k]) and if (not np or not np[k]) and
not idx_dumped[k] then not idx_dumped[k] then
table.insert(vals, vals[#vals + 1] = "["..dump_or_ref_val(k).."] = "
"["..dump_or_ref_val(k).."] = " ..dump_or_ref_val(v)
..dump_or_ref_val(v))
end end
end end
return "{"..table.concat(vals, ", ").."}" return "{"..table.concat(vals, ", ").."}"
@ -156,9 +155,9 @@ function core.serialize(x)
local function dump_nest_points() local function dump_nest_points()
for parent, vals in pairs(nest_points) do for parent, vals in pairs(nest_points) do
for k, v in pairs(vals) do for k, v in pairs(vals) do
table.insert(local_defs, dump_or_ref_val(parent) local_defs[#local_defs + 1] = dump_or_ref_val(parent)
.."["..dump_or_ref_val(k).."] = " .."["..dump_or_ref_val(k).."] = "
..dump_or_ref_val(v)) ..dump_or_ref_val(v)
end end
end end
end end

View File

@ -145,7 +145,12 @@ local buttonbar_metatable = {
if image == nil then image = "" end if image == nil then image = "" end
if tooltip == nil then tooltip = "" end if tooltip == nil then tooltip = "" end
table.insert(self.buttons,{ name=name, caption=caption, image=image, tooltip=tooltip}) self.buttons[#self.buttons + 1] = {
name = name,
caption = caption,
image = image,
tooltip = tooltip
}
if self.orientation == "horizontal" then if self.orientation == "horizontal" then
if ( (self.btn_size * #self.buttons) + (self.btn_size * 0.05 *2) if ( (self.btn_size * #self.buttons) + (self.btn_size * 0.05 *2)
> self.size.x ) then > self.size.x ) then

View File

@ -46,7 +46,7 @@ local function add_tab(self,tab)
tabdata = {}, tabdata = {},
} }
table.insert(self.tablist,newtab) self.tablist[#self.tablist + 1] = newtab
if self.last_tab_index == #self.tablist then if self.last_tab_index == #self.tablist then
self.current_tab = tab.name self.current_tab = tab.name

View File

@ -20,7 +20,7 @@ function core.privs_to_string(privs, delim)
local list = {} local list = {}
for priv, bool in pairs(privs) do for priv, bool in pairs(privs) do
if bool then if bool then
table.insert(list, priv) list[#list + 1] = priv
end end
end end
return table.concat(list, delim) return table.concat(list, delim)

View File

@ -84,6 +84,18 @@ core.register_chatcommand("me", {
end, end,
}) })
core.register_chatcommand("admin", {
description = "Show the name of the server owner",
func = function(name)
local admin = minetest.setting_get("name")
if admin then
return true, "The administrator of this server is "..admin.."."
else
return false, "There's no administrator named in the config file."
end
end,
})
core.register_chatcommand("help", { core.register_chatcommand("help", {
privs = {}, privs = {},
params = "[all/privs/<cmd>]", params = "[all/privs/<cmd>]",
@ -104,7 +116,7 @@ core.register_chatcommand("help", {
local cmds = {} local cmds = {}
for cmd, def in pairs(core.chatcommands) do for cmd, def in pairs(core.chatcommands) do
if core.check_player_privs(name, def.privs) then if core.check_player_privs(name, def.privs) then
table.insert(cmds, cmd) cmds[#cmds + 1] = cmd
end end
end end
table.sort(cmds) table.sort(cmds)
@ -115,7 +127,7 @@ core.register_chatcommand("help", {
local cmds = {} local cmds = {}
for cmd, def in pairs(core.chatcommands) do for cmd, def in pairs(core.chatcommands) do
if core.check_player_privs(name, def.privs) then if core.check_player_privs(name, def.privs) then
table.insert(cmds, format_help_line(cmd, def)) cmds[#cmds + 1] = format_help_line(cmd, def)
end end
end end
table.sort(cmds) table.sort(cmds)
@ -123,7 +135,7 @@ core.register_chatcommand("help", {
elseif param == "privs" then elseif param == "privs" then
local privs = {} local privs = {}
for priv, def in pairs(core.registered_privileges) do for priv, def in pairs(core.registered_privileges) do
table.insert(privs, priv .. ": " .. def.description) privs[#privs + 1] = priv .. ": " .. def.description
end end
table.sort(privs) table.sort(privs)
return true, "Available privileges:\n"..table.concat(privs, "\n") return true, "Available privileges:\n"..table.concat(privs, "\n")
@ -169,8 +181,10 @@ core.register_chatcommand("grant", {
end end
local privs = core.get_player_privs(grantname) local privs = core.get_player_privs(grantname)
local privs_unknown = "" local privs_unknown = ""
local basic_privs =
core.string_to_privs(core.setting_get("basic_privs") or "interact,shout")
for priv, _ in pairs(grantprivs) do for priv, _ in pairs(grantprivs) do
if priv ~= "interact" and priv ~= "shout" 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
return false, "Your privileges are insufficient." return false, "Your privileges are insufficient."
end end
@ -211,8 +225,10 @@ core.register_chatcommand("revoke", {
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 =
core.string_to_privs(core.setting_get("basic_privs") or "interact,shout")
for priv, _ in pairs(revoke_privs) do for priv, _ in pairs(revoke_privs) do
if priv ~= "interact" and priv ~= "shout" 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
return false, "Your privileges are insufficient." return false, "Your privileges are insufficient."
end end
@ -336,11 +352,17 @@ core.register_chatcommand("teleport", {
p.x = tonumber(p.x) p.x = tonumber(p.x)
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
local lm = tonumber(minetest.setting_get("map_generation_limit") or 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
return false, "Cannot teleport out of map bounds!"
end
teleportee = core.get_player_by_name(name) teleportee = core.get_player_by_name(name)
if teleportee and p.x and p.y and p.z then if teleportee then
teleportee:setpos(p) teleportee:setpos(p)
return true, "Teleporting to "..core.pos_to_string(p) return true, "Teleporting to "..core.pos_to_string(p)
end end
end
local teleportee = nil local teleportee = nil
local p = nil local p = nil
@ -773,6 +795,13 @@ core.register_chatcommand("time", {
end, end,
}) })
core.register_chatcommand("days", {
description = "Display day count",
func = function(name, param)
return true, "Current day is " .. core.get_day_count()
end
})
core.register_chatcommand("shutdown", { core.register_chatcommand("shutdown", {
description = "shutdown server", description = "shutdown server",
privs = {server=true}, privs = {server=true},
@ -836,14 +865,25 @@ core.register_chatcommand("kick", {
}) })
core.register_chatcommand("clearobjects", { core.register_chatcommand("clearobjects", {
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)
core.log("action", name .. " clears all objects.") local options = {}
if param == "" or param == "full" then
options.mode = "full"
elseif param == "quick" then
options.mode = "quick"
else
return false, "Invalid usage, see /help clearobjects."
end
core.log("action", name .. " clears all objects ("
.. options.mode .. " mode).")
core.chat_send_all("Clearing all objects. This may take long." core.chat_send_all("Clearing all objects. This may take long."
.. " You may experience a timeout. (by " .. " You may experience a timeout. (by "
.. name .. ")") .. name .. ")")
core.clear_objects() core.clear_objects(options)
core.log("action", "Object clearing done.") core.log("action", "Object clearing done.")
core.chat_send_all("*** Cleared all objects.") core.chat_send_all("*** Cleared all objects.")
end, end,

View File

@ -6,42 +6,49 @@
core.register_entity(":__builtin:falling_node", { core.register_entity(":__builtin:falling_node", {
initial_properties = { initial_properties = {
physical = true,
collide_with_objects = false,
collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
visual = "wielditem", visual = "wielditem",
visual_size = {x = 0.667, y = 0.667},
textures = {}, textures = {},
visual_size = {x=0.667, y=0.667}, physical = true,
is_visible = false,
collide_with_objects = false,
collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
}, },
node = {}, node = {},
set_node = function(self, node) set_node = function(self, node)
self.node = node self.node = node
local prop = { self.object:set_properties({
is_visible = true, is_visible = true,
textures = {node.name}, textures = {node.name},
} })
self.object:set_properties(prop)
end, end,
get_staticdata = function(self) get_staticdata = function(self)
return self.node.name return core.serialize(self.node)
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})
if staticdata then
self:set_node({name=staticdata}) local node = core.deserialize(staticdata)
if node then
self:set_node(node)
elseif staticdata ~= "" then
self:set_node({name = staticdata})
end end
end, end,
on_step = function(self, dtime) on_step = function(self, dtime)
-- Set gravity -- Set gravity
self.object:setacceleration({x=0, y=-10, z=0}) local acceleration = self.object:getacceleration()
if not vector.equals(acceleration, {x = 0, y = -10, z = 0}) then
self.object:setacceleration({x = 0, y = -10, z = 0})
end
-- Turn to actual sand when collides to ground or just move -- Turn to actual sand when collides to ground or just move
local pos = self.object:getpos() local pos = self.object:getpos()
local bcp = {x=pos.x, y=pos.y-0.7, z=pos.z} -- Position of bottom center point local bcp = {x = pos.x, y = pos.y - 0.7, z = pos.z} -- Position of bottom center point
local bcn = core.get_node(bcp) local bcn = core.get_node(bcp)
local bcd = core.registered_nodes[bcn.name] local bcd = core.registered_nodes[bcn.name]
-- Note: walkable is in the node definition, not in item groups -- Note: walkable is in the node definition, not in item groups
@ -52,7 +59,7 @@ core.register_entity(":__builtin:falling_node", {
if bcd and bcd.leveled and if bcd and bcd.leveled and
bcn.name == self.node.name then bcn.name == self.node.name then
local addlevel = self.node.level local addlevel = self.node.level
if addlevel == nil or addlevel <= 0 then if not addlevel or addlevel <= 0 then
addlevel = bcd.leveled addlevel = bcd.leveled
end end
if core.add_node_level(bcp, addlevel) == 0 then if core.add_node_level(bcp, addlevel) == 0 then
@ -65,7 +72,7 @@ core.register_entity(":__builtin:falling_node", {
core.remove_node(bcp) core.remove_node(bcp)
return return
end end
local np = {x=bcp.x, y=bcp.y+1, z=bcp.z} local np = {x = bcp.x, y = bcp.y + 1, z = bcp.z}
-- Check what's here -- Check what's here
local n2 = core.get_node(np) local n2 = core.get_node(np)
-- If it's not air or liquid, remove node and replace it with -- If it's not air or liquid, remove node and replace it with
@ -76,25 +83,25 @@ core.register_entity(":__builtin:falling_node", {
if core.registered_nodes[n2.name].buildable_to == false then if core.registered_nodes[n2.name].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, "")
local _, dropped_item
for _, dropped_item in ipairs(drops) do for _, dropped_item in ipairs(drops) do
core.add_item(np, dropped_item) core.add_item(np, dropped_item)
end end
end end
-- Run script hook -- Run script hook
local _, callback
for _, callback in ipairs(core.registered_on_dignodes) do for _, callback in ipairs(core.registered_on_dignodes) do
callback(np, n2, nil) callback(np, n2)
end end
end end
-- Create node and remove entity -- Create node and remove entity
if core.registered_nodes[self.node.name] then
core.add_node(np, self.node) core.add_node(np, self.node)
end
self.object:remove() self.object:remove()
nodeupdate(np) nodeupdate(np)
return return
end end
local vel = self.object:getvelocity() local vel = self.object:getvelocity()
if vector.equals(vel, {x=0,y=0,z=0}) then if vector.equals(vel, {x = 0, y = 0, z = 0}) then
local npos = self.object:getpos() local npos = self.object:getpos()
self.object:setpos(vector.round(npos)) self.object:setpos(vector.round(npos))
end end
@ -109,7 +116,7 @@ end
function drop_attached_node(p) 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)
for _,item in ipairs(core.get_node_drops(nn, "")) do for _, item in ipairs(core.get_node_drops(nn, "")) do
local pos = { local pos = {
x = p.x + math.random()/2 - 0.25, x = p.x + math.random()/2 - 0.25,
y = p.y + math.random()/2 - 0.25, y = p.y + math.random()/2 - 0.25,
@ -121,25 +128,13 @@ end
function check_attached_node(p, n) function 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" then
if n.param2 == 0 then d = core.wallmounted_to_dir(n.param2)
d.y = 1
elseif n.param2 == 1 then
d.y = -1
elseif n.param2 == 2 then
d.x = 1
elseif n.param2 == 3 then
d.x = -1
elseif n.param2 == 4 then
d.z = 1
elseif n.param2 == 5 then
d.z = -1
end
else else
d.y = -1 d.y = -1
end end
local p2 = {x=p.x+d.x, y=p.y+d.y, z=p.z+d.z} local p2 = vector.add(p, d)
local nn = core.get_node(p2).name local nn = core.get_node(p2).name
local def2 = core.registered_nodes[nn] local def2 = core.registered_nodes[nn]
if def2 and not def2.walkable then if def2 and not def2.walkable then
@ -152,10 +147,10 @@ end
-- Some common functions -- Some common functions
-- --
function nodeupdate_single(p, delay) function nodeupdate_single(p)
local n = core.get_node(p) local n = core.get_node(p)
if core.get_item_group(n.name, "falling_node") ~= 0 then if core.get_item_group(n.name, "falling_node") ~= 0 then
local p_bottom = {x=p.x, y=p.y-1, z=p.z} local p_bottom = {x = p.x, y = p.y - 1, z = p.z}
local n_bottom = core.get_node(p_bottom) local n_bottom = core.get_node(p_bottom)
-- Note: walkable is in the node definition, not in item groups -- Note: walkable is in the node definition, not in item groups
if core.registered_nodes[n_bottom.name] and if core.registered_nodes[n_bottom.name] and
@ -165,36 +160,87 @@ function nodeupdate_single(p, delay)
core.get_node_level(p_bottom) < core.get_node_max_level(p_bottom))) and core.get_node_level(p_bottom) < core.get_node_max_level(p_bottom))) and
(not core.registered_nodes[n_bottom.name].walkable or (not core.registered_nodes[n_bottom.name].walkable or
core.registered_nodes[n_bottom.name].buildable_to) then core.registered_nodes[n_bottom.name].buildable_to) then
if delay then
core.after(0.1, nodeupdate_single, {x=p.x, y=p.y, z=p.z}, false)
else
n.level = core.get_node_level(p) n.level = core.get_node_level(p)
core.remove_node(p) core.remove_node(p)
spawn_falling_node(p, n) spawn_falling_node(p, n)
nodeupdate(p) return true
end
end end
end end
if core.get_item_group(n.name, "attached_node") ~= 0 then if core.get_item_group(n.name, "attached_node") ~= 0 then
if not check_attached_node(p, n) then if not check_attached_node(p, n) then
drop_attached_node(p) drop_attached_node(p)
nodeupdate(p) return true
end end
end end
return false
end end
function nodeupdate(p, delay) -- This table is specifically ordered.
-- Round p to prevent falling entities to get stuck -- We don't walk diagonals, only our direct neighbors, and self.
p.x = math.floor(p.x+0.5) -- Down first as likely case, but always before self. The same with sides.
p.y = math.floor(p.y+0.5) -- Up must come last, so that things above self will also fall all at once.
p.z = math.floor(p.z+0.5) local nodeupdate_neighbors = {
{x = -1, y = -1, z = 0},
{x = 1, y = -1, z = 0},
{x = 0, y = -1, z = -1},
{x = 0, y = -1, z = 1},
{x = 0, y = -1, z = 0},
{x = -1, y = 0, z = 0},
{x = 1, y = 0, z = 0},
{x = 0, y = 0, z = 1},
{x = 0, y = 0, z = -1},
{x = 0, y = 0, z = 0},
{x = 0, y = 1, z = 0},
}
for x = -1,1 do function nodeupdate(p)
for y = -1,1 do -- Round p to prevent falling entities to get stuck.
for z = -1,1 do p = vector.round(p)
nodeupdate_single({x=p.x+x, y=p.y+y, z=p.z+z}, delay or not (x==0 and y==0 and z==0))
-- We make a stack, and manually maintain size for performance.
-- Stored in the stack, we will maintain tables with pos, and
-- last neighbor visited. This way, when we get back to each
-- node, we know which directions we have already walked, and
-- which direction is the next to walk.
local s = {}
local n = 0
-- The neighbor order we will visit from our table.
local v = 1
while true do
-- Push current pos onto the stack.
n = n + 1
s[n] = {p = p, v = v}
-- Select next node from neighbor list.
p = vector.add(p, nodeupdate_neighbors[v])
-- Now we check out the node. If it is in need of an update,
-- it will let us know in the return value (true = updated).
if not nodeupdate_single(p) then
-- If we don't need to "recurse" (walk) to it then pop
-- our previous pos off the stack and continue from there,
-- with the v value we were at when we last were at that
-- node
repeat
local pop = s[n]
p = pop.p
v = pop.v
s[n] = nil
n = n - 1
-- If there's nothing left on the stack, and no
-- more sides to walk to, we're done and can exit
if n == 0 and v == 11 then
return
end end
until v < 11
-- The next round walk the next neighbor in list.
v = v + 1
else
-- If we did need to walk the neighbor, then
-- start walking it from the walk order start (1),
-- and not the order we just pushed up the stack.
v = 1
end end
end end
end end

View File

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

View File

@ -27,19 +27,11 @@ function core.get_pointed_thing_position(pointed_thing, above)
if above then if above then
-- The position where a node would be placed -- The position where a node would be placed
return pointed_thing.above return pointed_thing.above
else end
-- The position where a node would be dug -- The position where a node would be dug
return pointed_thing.under return pointed_thing.under
end
elseif pointed_thing.type == "object" then elseif pointed_thing.type == "object" then
obj = pointed_thing.ref return pointed_thing.ref and pointed_thing.ref:getpos()
if obj ~= nil then
return obj:getpos()
else
return nil
end
else
return nil
end end
end end
@ -96,25 +88,26 @@ function core.dir_to_facedir(dir, is6d)
end end
end end
function core.facedir_to_dir(facedir) -- Table of possible dirs
--a table of possible dirs local facedir_to_dir = {
return ({{x=0, y=0, z=1}, {x= 0, y=0, z= 1},
{x=1, y=0, z=0}, {x= 1, y=0, z= 0},
{x=0, y=0, z=-1}, {x= 0, y=0, z=-1},
{x=-1, y=0, z=0}, {x=-1, y=0, z= 0},
{x=0, y=-1, z=0}, {x= 0, y=-1, z= 0},
{x=0, y=1, z=0}}) {x= 0, y=1, z= 0},
}
--indexed into by a table of correlating facedirs -- Mapping from facedir value to index in facedir_to_dir.
[({[0]=1, 2, 3, 4, local facedir_to_dir_map = {
[0]=1, 2, 3, 4,
5, 2, 6, 4, 5, 2, 6, 4,
6, 2, 5, 4, 6, 2, 5, 4,
1, 5, 3, 6, 1, 5, 3, 6,
1, 6, 3, 5, 1, 6, 3, 5,
1, 4, 3, 2}) 1, 4, 3, 2,
}
--indexed into by the facedir in question function core.facedir_to_dir(facedir)
[facedir]] return facedir_to_dir[facedir_to_dir_map[facedir]]
end end
function core.dir_to_wallmounted(dir) function core.dir_to_wallmounted(dir)
@ -139,17 +132,17 @@ function core.dir_to_wallmounted(dir)
end end
end end
function core.wallmounted_to_dir(wallmounted) -- table of dirs in wallmounted order
-- table of dirs in wallmounted order local wallmounted_to_dir = {
return ({[0] = {x = 0, y = 1, z = 0}, [0] = {x = 0, y = 1, z = 0},
{x = 0, y = -1, z = 0}, {x = 0, y = -1, z = 0},
{x = 1, y = 0, z = 0}, {x = 1, y = 0, z = 0},
{x = -1, y = 0, z = 0}, {x = -1, y = 0, z = 0},
{x = 0, y = 0, z = 1}, {x = 0, y = 0, z = 1},
{x = 0, y = 0, z = -1}}) {x = 0, y = 0, z = -1},
}
--indexed into by the wallmounted in question function core.wallmounted_to_dir(wallmounted)
[wallmounted] return wallmounted_to_dir[wallmounted]
end end
function core.get_node_drops(nodename, toolname) function core.get_node_drops(nodename, toolname)
@ -240,7 +233,8 @@ 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()) then if core.is_protected(place_to, placer:get_player_name()) and
not minetest.check_player_privs(placer, "protection_bypass") then
core.log("action", placer:get_player_name() core.log("action", placer:get_player_name()
.. " tried to place " .. def.name .. " tried to place " .. def.name
.. " at protected position " .. " at protected position "
@ -347,8 +341,12 @@ function core.item_place(itemstack, placer, pointed_thing, param2)
return itemstack return itemstack
end end
function core.item_secondary_use(itemstack, placer)
return itemstack
end
function core.item_drop(itemstack, dropper, pos) function core.item_drop(itemstack, dropper, pos)
if dropper.is_player then if dropper and dropper:is_player() then
local v = dropper:get_look_dir() local v = dropper:get_look_dir()
local p = {x=pos.x, y=pos.y+1.2, z=pos.z} local p = {x=pos.x, y=pos.y+1.2, z=pos.z}
local cs = itemstack:get_count() local cs = itemstack:get_count()
@ -362,6 +360,7 @@ function core.item_drop(itemstack, dropper, pos)
v.y = v.y*2 + 2 v.y = v.y*2 + 2
v.z = v.z*2 v.z = v.z*2
obj:setvelocity(v) obj:setvelocity(v)
obj:get_luaentity().dropped_by = dropper:get_player_name()
return itemstack return itemstack
end end
@ -446,7 +445,8 @@ function core.node_dig(pos, node, digger)
return return
end end
if core.is_protected(pos, digger:get_player_name()) then if core.is_protected(pos, digger:get_player_name()) and
not minetest.check_player_privs(digger, "protection_bypass") then
core.log("action", digger:get_player_name() core.log("action", digger:get_player_name()
.. " tried to dig " .. node.name .. " tried to dig " .. node.name
.. " at protected position " .. " at protected position "
@ -577,6 +577,7 @@ core.nodedef_default = {
diggable = true, diggable = true,
climbable = false, climbable = false,
buildable_to = false, buildable_to = false,
floodable = false,
liquidtype = "none", liquidtype = "none",
liquid_alternative_flowing = "", liquid_alternative_flowing = "",
liquid_alternative_source = "", liquid_alternative_source = "",
@ -604,6 +605,7 @@ core.craftitemdef_default = {
-- Interaction callbacks -- Interaction callbacks
on_place = redef_wrapper(core, 'item_place'), -- core.item_place on_place = redef_wrapper(core, 'item_place'), -- core.item_place
on_drop = redef_wrapper(core, 'item_drop'), -- core.item_drop on_drop = redef_wrapper(core, 'item_drop'), -- core.item_drop
on_secondary_use = redef_wrapper(core, 'item_secondary_use'),
on_use = nil, on_use = nil,
} }
@ -621,6 +623,7 @@ core.tooldef_default = {
-- Interaction callbacks -- Interaction callbacks
on_place = redef_wrapper(core, 'item_place'), -- core.item_place on_place = redef_wrapper(core, 'item_place'), -- core.item_place
on_secondary_use = redef_wrapper(core, 'item_secondary_use'),
on_drop = redef_wrapper(core, 'item_drop'), -- core.item_drop on_drop = redef_wrapper(core, 'item_drop'), -- core.item_drop
on_use = nil, on_use = nil,
} }
@ -639,6 +642,7 @@ core.noneitemdef_default = { -- This is used for the hand and unknown items
-- Interaction callbacks -- Interaction callbacks
on_place = redef_wrapper(core, 'item_place'), on_place = redef_wrapper(core, 'item_place'),
on_secondary_use = redef_wrapper(core, 'item_secondary_use'),
on_drop = nil, on_drop = nil,
on_use = nil, on_use = nil,
} }

View File

@ -31,6 +31,7 @@ core.register_entity(":__builtin:item", {
spritediv = {x = 1, y = 1}, spritediv = {x = 1, y = 1},
initial_sprite_basepos = {x = 0, y = 0}, initial_sprite_basepos = {x = 0, y = 0},
is_visible = false, is_visible = false,
infotext = "",
}, },
itemstring = '', itemstring = '',
@ -50,6 +51,7 @@ core.register_entity(":__builtin:item", {
local c = s local c = s
local itemtable = stack:to_table() local itemtable = stack:to_table()
local itemname = nil local itemname = nil
local description = ""
if itemtable then if itemtable then
itemname = stack:to_table().name itemname = stack:to_table().name
end end
@ -58,6 +60,7 @@ core.register_entity(":__builtin:item", {
if core.registered_items[itemname] then if core.registered_items[itemname] then
item_texture = core.registered_items[itemname].inventory_image item_texture = core.registered_items[itemname].inventory_image
item_type = core.registered_items[itemname].type item_type = core.registered_items[itemname].type
description = core.registered_items[itemname].description
end end
local prop = { local prop = {
is_visible = true, is_visible = true,
@ -66,6 +69,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,
infotext = description,
} }
self.object:set_properties(prop) self.object:set_properties(prop)
end, end,
@ -74,7 +78,8 @@ core.register_entity(":__builtin:item", {
return core.serialize({ return core.serialize({
itemstring = self.itemstring, itemstring = self.itemstring,
always_collect = self.always_collect, always_collect = self.always_collect,
age = self.age age = self.age,
dropped_by = self.dropped_by
}) })
end, end,
@ -89,6 +94,7 @@ core.register_entity(":__builtin:item", {
else else
self.age = dtime_s self.age = dtime_s
end end
self.dropped_by = data.dropped_by
end end
else else
self.itemstring = staticdata self.itemstring = staticdata

View File

@ -4,73 +4,47 @@
-- Misc. API functions -- Misc. API functions
-- --
local timers = {} local jobs = {}
local mintime local time = 0.0
local function update_timers(delay) local last = core.get_us_time() / 1000000
mintime = false
local sub = 0
for index = 1, #timers do
index = index - sub
local timer = timers[index]
timer.time = timer.time - delay
if timer.time <= 0 then
core.set_last_run_mod(timer.mod_origin)
timer.func(unpack(timer.args or {}))
table.remove(timers, index)
sub = sub + 1
elseif mintime then
mintime = math.min(mintime, timer.time)
else
mintime = timer.time
end
end
end
local timers_to_add
local function add_timers()
for _, timer in ipairs(timers_to_add) do
table.insert(timers, timer)
end
timers_to_add = false
end
local delay = 0
core.register_globalstep(function(dtime) core.register_globalstep(function(dtime)
if not mintime then local new = core.get_us_time() / 1000000
-- abort if no timers are running 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 return
end end
if timers_to_add then
add_timers() -- 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
delay = delay + dtime
if delay < mintime then
return
end end
update_timers(delay)
delay = 0
end) end)
function core.after(time, func, ...) function core.after(after, func, ...)
assert(tonumber(time) and type(func) == "function", assert(tonumber(time) and type(func) == "function",
"Invalid core.after invocation") "Invalid core.after invocation")
if not mintime then jobs[#jobs + 1] = {
mintime = time
timers_to_add = {{
time = time+delay,
func = func, func = func,
args = {...}, expire = time + after,
mod_origin = core.get_last_run_mod(), arg = {...},
}} mod_origin = core.get_last_run_mod()
return
end
mintime = math.min(mintime, time)
timers_to_add = timers_to_add or {}
timers_to_add[#timers_to_add+1] = {
time = time+delay,
func = func,
args = {...},
mod_origin = core.get_last_run_mod(),
} }
end end
@ -89,14 +63,14 @@ function core.check_player_privs(player_or_name, ...)
-- We were provided with a table like { privA = true, privB = true }. -- We were provided with a table like { privA = true, privB = true }.
for priv, value in pairs(requested_privs[1]) do for priv, value in pairs(requested_privs[1]) do
if value and not player_privs[priv] then if value and not player_privs[priv] then
table.insert(missing_privileges, priv) missing_privileges[#missing_privileges + 1] = priv
end end
end end
else else
-- Only a list, we can process it directly. -- Only a list, we can process it directly.
for key, priv in pairs(requested_privs) do for key, priv in pairs(requested_privs) do
if not player_privs[priv] then if not player_privs[priv] then
table.insert(missing_privileges, priv) missing_privileges[#missing_privileges + 1] = priv
end end
end end
end end
@ -122,7 +96,7 @@ function core.get_connected_players()
local temp_table = {} local temp_table = {}
for index, value in pairs(player_list) do for index, value in pairs(player_list) do
if value:is_player_connected() then if value:is_player_connected() then
table.insert(temp_table, value) temp_table[#temp_table + 1] = value
end end
end end
return temp_table return temp_table
@ -204,3 +178,22 @@ function core.raillike_group(name)
end end
return id return id
end end
-- HTTP callback interface
function core.http_add_fetch(httpenv)
httpenv.fetch = function(req, callback)
local handle = httpenv.fetch_async(req)
local function update_http_status()
local res = httpenv.fetch_async_get(handle)
if res.completed then
callback(res)
else
core.after(0, update_http_status)
end
end
core.after(0, update_http_status)
end
return httpenv
end

View File

@ -32,6 +32,7 @@ core.register_privilege("settime", "Can use /time")
core.register_privilege("privs", "Can modify privileges") core.register_privilege("privs", "Can modify privileges")
core.register_privilege("basic_privs", "Can modify 'shout' and 'interact' privileges") core.register_privilege("basic_privs", "Can modify 'shout' and 'interact' privileges")
core.register_privilege("server", "Can do server maintenance stuff") core.register_privilege("server", "Can do server maintenance stuff")
core.register_privilege("protection_bypass", "Can bypass node protection in the world")
core.register_privilege("shout", "Can speak in chat") core.register_privilege("shout", "Can speak in chat")
core.register_privilege("ban", "Can ban and unban players") core.register_privilege("ban", "Can ban and unban players")
core.register_privilege("kick", "Can kick players") core.register_privilege("kick", "Can kick players")

View File

@ -11,10 +11,11 @@ local register_alias_raw = core.register_alias_raw
core.register_alias_raw = nil core.register_alias_raw = nil
-- --
-- Item / entity / ABM registration functions -- Item / entity / ABM / LBM registration functions
-- --
core.registered_abms = {} core.registered_abms = {}
core.registered_lbms = {}
core.registered_entities = {} core.registered_entities = {}
core.registered_items = {} core.registered_items = {}
core.registered_nodes = {} core.registered_nodes = {}
@ -51,27 +52,38 @@ local forbidden_item_names = {
local function check_modname_prefix(name) local function check_modname_prefix(name)
if name:sub(1,1) == ":" then if name:sub(1,1) == ":" then
-- Escape the modname prefix enforcement mechanism -- If the name starts with a colon, we can skip the modname prefix
-- mechanism.
return name:sub(2) return name:sub(2)
else else
-- Modname prefix enforcement -- Enforce that the name starts with the correct mod name.
local expected_prefix = core.get_current_modname() .. ":" local expected_prefix = core.get_current_modname() .. ":"
if name:sub(1, #expected_prefix) ~= expected_prefix then if name:sub(1, #expected_prefix) ~= expected_prefix then
error("Name " .. name .. " does not follow naming conventions: " .. error("Name " .. name .. " does not follow naming conventions: " ..
"\"modname:\" or \":\" prefix required") "\"" .. expected_prefix .. "\" or \":\" prefix required")
end end
-- Enforce that the name only contains letters, numbers and underscores.
local subname = name:sub(#expected_prefix+1) local subname = name:sub(#expected_prefix+1)
if subname:find("[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]") then if subname:find("[^%w_]") then
error("Name " .. name .. " does not follow naming conventions: " .. error("Name " .. name .. " does not follow naming conventions: " ..
"contains unallowed characters") "contains unallowed characters")
end end
return name return name
end end
end end
function core.register_abm(spec) function core.register_abm(spec)
-- Add to core.registered_abms -- Add to core.registered_abms
core.registered_abms[#core.registered_abms+1] = spec core.registered_abms[#core.registered_abms + 1] = spec
spec.mod_origin = core.get_current_modname() or "??"
end
function core.register_lbm(spec)
-- Add to core.registered_lbms
check_modname_prefix(spec.name)
core.registered_lbms[#core.registered_lbms + 1] = spec
spec.mod_origin = core.get_current_modname() or "??" spec.mod_origin = core.get_current_modname() or "??"
end end
@ -268,6 +280,7 @@ core.register_item(":unknown", {
description = "Unknown Item", description = "Unknown Item",
inventory_image = "unknown_item.png", inventory_image = "unknown_item.png",
on_place = core.item_place, on_place = core.item_place,
on_secondary_use = core.item_secondary_use,
on_drop = core.item_drop, on_drop = core.item_drop,
groups = {not_in_creative_inventory=1}, groups = {not_in_creative_inventory=1},
diggable = true, diggable = true,
@ -284,6 +297,7 @@ core.register_node(":air", {
pointable = false, pointable = false,
diggable = false, diggable = false,
buildable_to = true, buildable_to = true,
floodable = true,
air_equivalent = true, air_equivalent = true,
drop = "", drop = "",
groups = {not_in_creative_inventory=1}, groups = {not_in_creative_inventory=1},
@ -385,7 +399,7 @@ end
local function make_registration() local function make_registration()
local t = {} local t = {}
local registerfunc = function(func) local registerfunc = function(func)
table.insert(t, func) t[#t + 1] = func
core.callback_origins[func] = { core.callback_origins[func] = {
mod = core.get_current_modname() or "??", mod = core.get_current_modname() or "??",
name = debug.getinfo(1, "n").name or "??" name = debug.getinfo(1, "n").name or "??"
@ -461,9 +475,9 @@ end
function core.register_on_player_hpchange(func, modifier) function core.register_on_player_hpchange(func, modifier)
if modifier then if modifier then
table.insert(core.registered_on_player_hpchanges.modifiers, func) core.registered_on_player_hpchanges.modifiers[#core.registered_on_player_hpchanges.modifiers + 1] = func
else else
table.insert(core.registered_on_player_hpchanges.loggers, func) core.registered_on_player_hpchanges.loggers[#core.registered_on_player_hpchanges.loggers + 1] = func
end end
core.callback_origins[func] = { core.callback_origins[func] = {
mod = core.get_current_modname() or "??", mod = core.get_current_modname() or "??",

View File

@ -3,31 +3,23 @@
local function warn_invalid_static_spawnpoint() local function warn_invalid_static_spawnpoint()
if core.setting_get("static_spawnpoint") and if core.setting_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.setting_get("static_spawnpoint").."\"")
end end
end end
warn_invalid_static_spawnpoint() warn_invalid_static_spawnpoint()
local function put_player_in_spawn(obj) local function put_player_in_spawn(player_obj)
warn_invalid_static_spawnpoint()
local static_spawnpoint = core.setting_get_pos("static_spawnpoint") local static_spawnpoint = core.setting_get_pos("static_spawnpoint")
if not static_spawnpoint then if not static_spawnpoint then
return false return false
end end
core.log('action', "Moving "..obj:get_player_name().. core.log("action", "Moving " .. player_obj:get_player_name() ..
" to static spawnpoint at ".. " to static spawnpoint at " .. core.pos_to_string(static_spawnpoint))
core.pos_to_string(static_spawnpoint)) player_obj:setpos(static_spawnpoint)
obj:setpos(static_spawnpoint)
return true return true
end end
core.register_on_newplayer(function(obj) core.register_on_newplayer(put_player_in_spawn)
put_player_in_spawn(obj) core.register_on_respawnplayer(put_player_in_spawn)
end)
core.register_on_respawnplayer(function(obj)
return put_player_in_spawn(obj)
end)

View File

@ -12,7 +12,11 @@ if core.print then
-- Override native print and use -- Override native print and use
-- terminal if that's turned on -- terminal if that's turned on
function print(...) function print(...)
core_print(table.concat({...}, "\t")) local n, t = select("#", ...), {...}
for i = 1, n do
t[i] = tostring(t[i])
end
core_print(table.concat(t, "\t"))
end end
core.print = nil -- don't pollute our namespace core.print = nil -- don't pollute our namespace
end end
@ -21,26 +25,26 @@ os.setlocale("C", "numeric")
minetest = core 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 commonpath = scriptdir.."common"..DIR_DELIM local commonpath = scriptdir .. "common" .. DIR_DELIM
local asyncpath = scriptdir.."async"..DIR_DELIM local asyncpath = scriptdir .. "async" .. DIR_DELIM
dofile(commonpath.."strict.lua") dofile(commonpath .. "strict.lua")
dofile(commonpath.."serialize.lua") dofile(commonpath .. "serialize.lua")
dofile(commonpath.."misc_helpers.lua") 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 mainmenuscript = core.setting_get("main_menu_script")
if mainmenuscript ~= nil and mainmenuscript ~= "" then if mainmenuscript ~= nil and mainmenuscript ~= "" then
dofile(mainmenuscript) dofile(mainmenuscript)
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")
else else
error(("Unrecognized builtin initialization type %s!"):format(tostring(INIT))) error(("Unrecognized builtin initialization type %s!"):format(tostring(INIT)))
end end

View File

@ -22,40 +22,37 @@ menudata = {}
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Local cached values -- Local cached values
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
local min_supp_proto = core.get_min_supp_proto() local min_supp_proto, max_supp_proto
local max_supp_proto = core.get_max_supp_proto()
function common_update_cached_supp_proto()
min_supp_proto = core.get_min_supp_proto()
max_supp_proto = core.get_max_supp_proto()
end
common_update_cached_supp_proto()
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Menu helper functions -- Menu helper functions
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
local function render_client_count(n) local function render_client_count(n)
if n > 99 then if n > 99 then return '99+'
return '99+' elseif n >= 0 then return tostring(n)
elseif n >= 0 then else return '?' end
return tostring(n)
else
return '?'
end
end end
local function configure_selected_world_params(idx) local function configure_selected_world_params(idx)
local worldconfig = modmgr.get_worldconfig( local worldconfig = modmgr.get_worldconfig(menudata.worldlist:get_list()[idx].path)
menudata.worldlist:get_list()[idx].path) if worldconfig.creative_mode then
if worldconfig.creative_mode ~= nil then
core.setting_set("creative_mode", worldconfig.creative_mode) core.setting_set("creative_mode", worldconfig.creative_mode)
end end
if worldconfig.enable_damage ~= nil then if worldconfig.enable_damage then
core.setting_set("enable_damage", worldconfig.enable_damage) core.setting_set("enable_damage", worldconfig.enable_damage)
end end
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function image_column(tooltip, flagname) function image_column(tooltip, flagname)
return "image," .. return "image,tooltip=" .. core.formspec_escape(tooltip) .. "," ..
"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 .. "server_flags_" .. flagname .. ".png")
end end
@ -64,76 +61,60 @@ end
function order_favorite_list(list) function order_favorite_list(list)
local res = {} local res = {}
--orders the favorite list after support --orders the favorite list after support
for i=1,#list,1 do for i = 1, #list do
local fav = list[i] local fav = list[i]
if is_server_protocol_compat(fav.proto_min, fav.proto_max) then if is_server_protocol_compat(fav.proto_min, fav.proto_max) then
table.insert(res, fav) res[#res + 1] = fav
end end
end end
for i=1,#list,1 do for i = 1, #list do
local fav = list[i] local fav = list[i]
if not is_server_protocol_compat(fav.proto_min, fav.proto_max) then if not is_server_protocol_compat(fav.proto_min, fav.proto_max) then
table.insert(res, fav) res[#res + 1] = fav
end end
end end
return res return res
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function render_favorite(spec,render_details) function render_favorite(spec, is_favorite)
local text = "" local text = ""
if spec.name then
if spec.name ~= nil then
text = text .. core.formspec_escape(spec.name:trim()) text = text .. core.formspec_escape(spec.name:trim())
elseif spec.address then
-- if spec.description ~= nil and
-- core.formspec_escape(spec.description):trim() ~= "" then
-- text = text .. " (" .. core.formspec_escape(spec.description) .. ")"
-- end
else
if spec.address ~= nil then
text = text .. spec.address:trim() text = text .. spec.address:trim()
if spec.port then
if spec.port ~= nil then
text = text .. ":" .. spec.port text = text .. ":" .. spec.port
end end
end end
end
if not render_details then
return text
end
local details = "" local details = ""
local grey_out = not is_server_protocol_compat(spec.proto_max, spec.proto_min) local grey_out = not is_server_protocol_compat(spec.proto_min, spec.proto_max)
if spec.clients ~= nil and spec.clients_max ~= nil then if is_favorite then
details = "1,"
else
details = "0,"
end
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
-- Choose a color depending on how many clients are connected -- Choose a color depending on how many clients are connected
-- (relatively to clients_max) -- (relatively to clients_max)
if spec.clients == 0 then if grey_out then clients_color = '#aaaaaa'
clients_color = '' -- 0 players: default/white elseif spec.clients == 0 then clients_color = '' -- 0 players: default/white
elseif spec.clients == spec.clients_max then elseif clients_percent <= 60 then clients_color = '#a1e587' -- 0-60%: green
clients_color = '#dd5b5b' -- full server: red (darker) elseif clients_percent <= 90 then clients_color = '#ffdc97' -- 60-90%: yellow
elseif clients_percent <= 60 then elseif clients_percent == 100 then clients_color = '#dd5b5b' -- full server: red (darker)
clients_color = '#a1e587' -- 0-60%: green else clients_color = '#ffba97' -- 90-100%: orange
elseif clients_percent <= 90 then
clients_color = '#ffdc97' -- 60-90%: yellow
else
clients_color = '#ffba97' -- 90-100%: orange
end end
if grey_out then details = details .. clients_color .. ',' ..
clients_color = '#aaaaaa' render_client_count(spec.clients) .. ',/,' ..
end
details = details ..
clients_color .. ',' ..
render_client_count(spec.clients) .. ',' ..
'/,' ..
render_client_count(spec.clients_max) .. ',' render_client_count(spec.clients_max) .. ','
elseif grey_out then elseif grey_out then
details = details .. '#aaaaaa,?,/,?,' details = details .. '#aaaaaa,?,/,?,'
else else
@ -184,14 +165,10 @@ end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function menu_render_worldlist() function menu_render_worldlist()
local retval = "" local retval = ""
local current_worldlist = menudata.worldlist:get_list() local current_worldlist = menudata.worldlist:get_list()
for i,v in ipairs(current_worldlist) do for i, v in ipairs(current_worldlist) do
if retval ~= "" then if retval ~= "" then retval = retval .. "," end
retval = retval ..","
end
retval = retval .. core.formspec_escape(v.name) .. retval = retval .. core.formspec_escape(v.name) ..
" \\[" .. core.formspec_escape(v.gameid) .. "\\]" " \\[" .. core.formspec_escape(v.gameid) .. "\\]"
end end
@ -200,40 +177,24 @@ function menu_render_worldlist()
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function menu_handle_key_up_down(fields,textlist,settingname) function menu_handle_key_up_down(fields, textlist, settingname)
if fields["key_up"] then local oldidx, newidx = core.get_textlist_index(textlist), 1
local oldidx = core.get_textlist_index(textlist) if fields.key_up or fields.key_down then
if fields.key_up and oldidx and oldidx > 1 then
if oldidx ~= nil and oldidx > 1 then newidx = oldidx - 1
local newidx = oldidx -1 elseif fields.key_down and oldidx and
core.setting_set(settingname, oldidx < menudata.worldlist:size() then
menudata.worldlist:get_raw_index(newidx)) newidx = oldidx + 1
configure_selected_world_params(newidx)
end end
core.setting_set(settingname, menudata.worldlist:get_raw_index(newidx))
configure_selected_world_params(newidx)
return true return true
end end
if fields["key_down"] then
local oldidx = core.get_textlist_index(textlist)
if oldidx ~= nil and oldidx < menudata.worldlist:size() then
local newidx = oldidx + 1
core.setting_set(settingname,
menudata.worldlist:get_raw_index(newidx))
configure_selected_world_params(newidx)
end
return true
end
return false return false
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function asyncOnlineFavourites() function asyncOnlineFavourites()
if not menudata.public_known then if not menudata.public_known then
menudata.public_known = {{ menudata.public_known = {{
name = fgettext("Loading..."), name = fgettext("Loading..."),
@ -241,43 +202,45 @@ function asyncOnlineFavourites()
}} }}
end end
menudata.favorites = menudata.public_known menudata.favorites = menudata.public_known
menudata.favorites_is_public = true
if not menudata.public_downloading then
menudata.public_downloading = true
else
return
end
core.handle_async( core.handle_async(
function(param) function(param)
return core.get_favorites("online") return core.get_favorites("online")
end, end,
nil, nil,
function(result) function(result)
if core.setting_getbool("public_serverlist") then menudata.public_downloading = nil
local favs = order_favorite_list(result) local favs = order_favorite_list(result)
if favs[1] then if favs[1] then
menudata.public_known = favs menudata.public_known = favs
menudata.favorites = menudata.public_known menudata.favorites = menudata.public_known
menudata.favorites_is_public = true
end end
core.event_handler("Refresh") core.event_handler("Refresh")
end end
end
) )
end 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.splittext(text, textlen)
local retval = "textlist[" .. xpos .. "," .. ypos .. ";" .. width ..
"," .. height .. ";" .. tl_name .. ";"
local retval = "textlist[" .. xpos .. "," .. ypos .. ";" for i = 1, #textlines do
.. width .. "," .. height .. ";" textlines[i] = textlines[i]:gsub("\r", "")
.. tl_name .. ";"
for i=1, #textlines, 1 do
textlines[i] = textlines[i]:gsub("\r","")
retval = retval .. core.formspec_escape(textlines[i]) .. "," retval = retval .. core.formspec_escape(textlines[i]) .. ","
end end
retval = retval .. ";0;" retval = retval .. ";0;"
if transparency then retval = retval .. "true" end
if transparency then
retval = retval .. "true"
end
retval = retval .. "]" retval = retval .. "]"
return retval return retval
@ -285,19 +248,21 @@ end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function is_server_protocol_compat(server_proto_min, server_proto_max) function is_server_protocol_compat(server_proto_min, server_proto_max)
return not ((min_supp_proto > (server_proto_max or 24)) or (max_supp_proto < (server_proto_min or 13))) return min_supp_proto <= (server_proto_max or 24) and max_supp_proto >= (server_proto_min or 13)
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function is_server_protocol_compat_or_error(server_proto_min, server_proto_max) function is_server_protocol_compat_or_error(server_proto_min, server_proto_max)
if not is_server_protocol_compat(server_proto_min, server_proto_max) then if not is_server_protocol_compat(server_proto_min, server_proto_max) then
local server_prot_ver_info local server_prot_ver_info, client_prot_ver_info
local client_prot_ver_info local s_p_min = server_proto_min or 13
if server_proto_min ~= server_proto_max then local s_p_max = server_proto_max or 24
if s_p_min ~= s_p_max then
server_prot_ver_info = fgettext_ne("Server supports protocol versions between $1 and $2. ", server_prot_ver_info = fgettext_ne("Server supports protocol versions between $1 and $2. ",
server_proto_min or 13, server_proto_max or 24) s_p_min, s_p_max)
else else
server_prot_ver_info = fgettext_ne("Server enforces protocol version $1. ", server_prot_ver_info = fgettext_ne("Server enforces protocol version $1. ",
server_proto_min or 13) s_p_min)
end end
if min_supp_proto ~= max_supp_proto then if min_supp_proto ~= max_supp_proto then
client_prot_ver_info= fgettext_ne("We support protocol versions between version $1 and $2.", client_prot_ver_info= fgettext_ne("We support protocol versions between version $1 and $2.",
@ -320,7 +285,7 @@ function menu_worldmt(selected, setting, value)
local filename = world.path .. DIR_DELIM .. "world.mt" local filename = world.path .. DIR_DELIM .. "world.mt"
local world_conf = Settings(filename) local world_conf = Settings(filename)
if value ~= nil then if value then
if not world_conf:write() then if not world_conf:write() then
core.log("error", "Failed to write world config file") core.log("error", "Failed to write world config file")
end end
@ -338,7 +303,7 @@ function menu_worldmt_legacy(selected)
local modes_names = {"creative_mode", "enable_damage", "server_announce"} local modes_names = {"creative_mode", "enable_damage", "server_announce"}
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 ~= nil then if mode_val then
core.setting_set(mode_name, mode_val) core.setting_set(mode_name, mode_val)
else else
menu_worldmt(selected, mode_name, core.setting_get(mode_name)) menu_worldmt(selected, mode_name, core.setting_get(mode_name))

View File

@ -25,20 +25,20 @@ 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 =
"size[11,6.5,true]" .. "size[11.5,7.5,true]" ..
"label[0.5,-0.25;" .. fgettext("World:") .. "]" .. "label[0.5,0;" .. fgettext("World:") .. "]" ..
"label[1.75,-0.25;" .. data.worldspec.name .. "]" "label[1.75,0;" .. data.worldspec.name .. "]"
if data.hide_gamemods then if data.hide_gamemods then
retval = retval .. "checkbox[0,5.75;cb_hide_gamemods;" .. fgettext("Hide Game") .. ";true]" retval = retval .. "checkbox[1,6;cb_hide_gamemods;" .. fgettext("Hide Game") .. ";true]"
else else
retval = retval .. "checkbox[0,5.75;cb_hide_gamemods;" .. fgettext("Hide Game") .. ";false]" retval = retval .. "checkbox[1,6;cb_hide_gamemods;" .. fgettext("Hide Game") .. ";false]"
end end
if data.hide_modpackcontents then if data.hide_modpackcontents then
retval = retval .. "checkbox[2,5.75;cb_hide_mpcontent;" .. fgettext("Hide mp content") .. ";true]" retval = retval .. "checkbox[6,6;cb_hide_mpcontent;" .. fgettext("Hide mp content") .. ";true]"
else else
retval = retval .. "checkbox[2,5.75;cb_hide_mpcontent;" .. fgettext("Hide mp content") .. ";false]" retval = retval .. "checkbox[6,6;cb_hide_mpcontent;" .. fgettext("Hide mp content") .. ";false]"
end end
if mod == nil then if mod == nil then
@ -46,13 +46,13 @@ local function get_formspec(data)
end end
retval = retval .. retval = retval ..
"label[0,0.45;" .. fgettext("Mod:") .. "]" .. "label[0,0.7;" .. fgettext("Mod:") .. "]" ..
"label[0.75,0.45;" .. mod.name .. "]" .. "label[0.75,0.7;" .. mod.name .. "]" ..
"label[0,1;" .. fgettext("Depends:") .. "]" .. "label[0,1.25;" .. fgettext("Depends:") .. "]" ..
"textlist[0,1.5;5,4.25;world_config_depends;" .. "textlist[0,1.75;5,4.25;world_config_depends;" ..
modmgr.get_dependencies(mod.path) .. ";0]" .. modmgr.get_dependencies(mod.path) .. ";0]" ..
"button[9.25,6.35;2,0.5;btn_config_world_save;" .. fgettext("Save") .. "]" .. "button[3.25,7;2.5,0.5;btn_config_world_save;" .. fgettext("Save") .. "]" ..
"button[7.4,6.35;2,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 ~= nil and mod.name ~= "" and mod.typ ~= "game_mod" then
if mod.is_modpack then if mod.is_modpack then
@ -68,22 +68,22 @@ local function get_formspec(data)
end end
if all_enabled == false then if all_enabled == false then
retval = retval .. "button[5.5,-0.125;2,0.5;btn_mp_enable;" .. fgettext("Enable MP") .. "]" retval = retval .. "button[5.5,0.125;2.5,0.5;btn_mp_enable;" .. fgettext("Enable MP") .. "]"
else else
retval = retval .. "button[5.5,-0.125;2,0.5;btn_mp_disable;" .. fgettext("Disable MP") .. "]" retval = retval .. "button[5.5,0.125;2.5,0.5;btn_mp_disable;" .. fgettext("Disable MP") .. "]"
end end
else else
if mod.enabled then if mod.enabled then
retval = retval .. "checkbox[5.5,-0.375;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.375;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
retval = retval .. retval = retval ..
"button[8.5,-0.125;2.5,0.5;btn_all_mods;" .. fgettext("Enable all") .. "]" .. "button[8.75,0.125;2.5,0.5;btn_all_mods;" .. fgettext("Enable all") .. "]" ..
"textlist[5.5,0.5;5.5,5.75;world_config_modlist;" "textlist[5.5,0.75;5.75,5.25;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 .."]"

View File

@ -46,7 +46,7 @@ local function create_world_formspec(dialogdata)
current_seed = core.formspec_escape(current_seed) current_seed = core.formspec_escape(current_seed)
local retval = local retval =
"size[12,6,true]" .. "size[11.5,6.5,true]" ..
"label[2,0;" .. fgettext("World name") .. "]".. "label[2,0;" .. fgettext("World name") .. "]"..
"field[4.5,0.4;6,0.5;te_world_name;;]" .. "field[4.5,0.4;6,0.5;te_world_name;;]" ..
@ -60,8 +60,8 @@ local function create_world_formspec(dialogdata)
"textlist[4.2,3;5.8,2.3;games;" .. gamemgr.gamelist() .. "textlist[4.2,3;5.8,2.3;games;" .. gamemgr.gamelist() ..
";" .. gameidx .. ";true]" .. ";" .. gameidx .. ";true]" ..
"button[5,5.5;2.6,0.5;world_create_confirm;" .. fgettext("Create") .. "]" .. "button[3.25,6;2.5,0.5;world_create_confirm;" .. fgettext("Create") .. "]" ..
"button[7.5,5.5;2.8,0.5;world_create_cancel;" .. fgettext("Cancel") .. "]" "button[5.75,6;2.5,0.5;world_create_cancel;" .. fgettext("Cancel") .. "]"
if #gamemgr.games == 0 then if #gamemgr.games == 0 then
retval = retval .. "box[2,4;8,1;#ff8800]label[2.25,4;" .. retval = retval .. "box[2,4;8,1;#ff8800]label[2.25,4;" ..

View File

@ -22,10 +22,11 @@ local function delete_mod_formspec(dialogdata)
dialogdata.mod = modmgr.global_mods:get_list()[dialogdata.selected] dialogdata.mod = modmgr.global_mods:get_list()[dialogdata.selected]
local retval = local retval =
"size[12.4,5,true]" .. "size[11.5,4.5,true]" ..
"field[1.75,1;10,3;;" .. fgettext("Are you sure you want to delete \"$1\"?", dialogdata.mod.name) .. ";]".. "label[2,2;" ..
"button[4,4.2;1,0.5;dlg_delete_mod_confirm;" .. fgettext("Yes") .. "]" .. fgettext("Are you sure you want to delete \"$1\"?", dialogdata.mod.name) .. "]"..
"button[6.5,4.2;3,0.5;dlg_delete_mod_cancel;" .. fgettext("No of course not!") .. "]" "button[3.25,3.5;2.5,0.5;dlg_delete_mod_confirm;" .. fgettext("Delete") .. "]" ..
"button[5.75,3.5;2.5,0.5;dlg_delete_mod_cancel;" .. fgettext("Cancel") .. "]"
return retval return retval
end end

View File

@ -19,11 +19,11 @@
local function delete_world_formspec(dialogdata) local function delete_world_formspec(dialogdata)
local retval = local retval =
"size[12,6,true]" .. "size[11.5,4.5,true]" ..
"label[2,2;" .. "label[2,2;" ..
fgettext("Delete World \"$1\"?", dialogdata.delete_name) .. "]".. fgettext("Delete World \"$1\"?", dialogdata.delete_name) .. "]" ..
"button[3.5,4.2;2.6,0.5;world_delete_confirm;" .. fgettext("Yes").. "]" .. "button[3.25,3.5;2.5,0.5;world_delete_confirm;" .. fgettext("Delete") .. "]" ..
"button[6,4.2;2.8,0.5;world_delete_cancel;" .. fgettext("No") .. "]" "button[5.75,3.5;2.5,0.5;world_delete_cancel;" .. fgettext("Cancel") .. "]"
return retval return retval
end end

View File

@ -22,14 +22,12 @@ local function rename_modpack_formspec(dialogdata)
dialogdata.mod = modmgr.global_mods:get_list()[dialogdata.selected] dialogdata.mod = modmgr.global_mods:get_list()[dialogdata.selected]
local retval = local retval =
"size[12.4,5,true]" .. "size[11.5,4.5,true]" ..
"label[1.75,1;".. fgettext("Rename Modpack:") .. "]".. "field[2.5,2;7,0.5;te_modpack_name;".. fgettext("Rename Modpack:") .. ";" ..
"field[4.5,1.4;6,0.5;te_modpack_name;;" .. dialogdata.mod.name .. "]" ..
dialogdata.mod.name .. "button[3.25,3.5;2.5,0.5;dlg_rename_modpack_confirm;"..
"]" ..
"button[5,4.2;2.6,0.5;dlg_rename_modpack_confirm;"..
fgettext("Accept") .. "]" .. fgettext("Accept") .. "]" ..
"button[7.5,4.2;2.8,0.5;dlg_rename_modpack_cancel;".. "button[5.75,3.5;2.5,0.5;dlg_rename_modpack_cancel;"..
fgettext("Cancel") .. "]" fgettext("Cancel") .. "]"
return retval return retval

View File

@ -0,0 +1,760 @@
--Minetest
--Copyright (C) 2015 PilzAdam
--
--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 FILENAME = "settingtypes.txt"
local CHAR_CLASSES = {
SPACE = "[%s]",
VARIABLE = "[%w_%-%.]",
INTEGER = "[+-]?[%d]",
FLOAT = "[+-]?[%d%.]",
FLAGS = "[%w_%-%.,]",
}
-- returns error message, or nil
local function parse_setting_line(settings, line, read_all, base_level, allow_secure)
-- comment
local comment = line:match("^#" .. CHAR_CLASSES.SPACE .. "*(.*)$")
if comment then
if settings.current_comment == "" then
settings.current_comment = comment
else
settings.current_comment = settings.current_comment .. "\n" .. comment
end
return
end
-- clear current_comment so only comments directly above a setting are bound to it
-- but keep a local reference to it for variables in the current line
local current_comment = settings.current_comment
settings.current_comment = ""
-- empty lines
if line:match("^" .. CHAR_CLASSES.SPACE .. "*$") then
return
end
-- category
local stars, category = line:match("^%[([%*]*)([^%]]+)%]$")
if category then
table.insert(settings, {
name = category,
level = stars:len() + base_level,
type = "category",
})
return
end
-- settings
local first_part, name, readable_name, setting_type = line:match("^"
-- this first capture group matches the whole first part,
-- so we can later strip it from the rest of the line
.. "("
.. "([" .. CHAR_CLASSES.VARIABLE .. "+)" -- variable name
.. CHAR_CLASSES.SPACE .. "*"
.. "%(([^%)]*)%)" -- readable name
.. CHAR_CLASSES.SPACE .. "*"
.. "(" .. CHAR_CLASSES.VARIABLE .. "+)" -- type
.. CHAR_CLASSES.SPACE .. "*"
.. ")")
if not first_part then
return "Invalid line"
end
if name:match("secure%.[.]*") and not allow_secure then
return "Tried to add \"secure.\" setting"
end
if readable_name == "" then
readable_name = nil
end
local remaining_line = line:sub(first_part:len() + 1)
if setting_type == "int" then
local default, min, max = remaining_line:match("^"
-- first int is required, the last 2 are optional
.. "(" .. CHAR_CLASSES.INTEGER .. "+)" .. CHAR_CLASSES.SPACE .. "*"
.. "(" .. CHAR_CLASSES.INTEGER .. "*)" .. CHAR_CLASSES.SPACE .. "*"
.. "(" .. CHAR_CLASSES.INTEGER .. "*)"
.. "$")
if not default or not tonumber(default) then
return "Invalid integer setting"
end
min = tonumber(min)
max = tonumber(max)
table.insert(settings, {
name = name,
readable_name = readable_name,
type = "int",
default = default,
min = min,
max = max,
comment = current_comment,
})
return
end
if setting_type == "string" or setting_type == "noise_params"
or setting_type == "key" or setting_type == "v3f" then
local default = remaining_line:match("^(.*)$")
if not default then
return "Invalid string setting"
end
if setting_type == "key" and not read_all then
-- ignore key type if read_all is false
return
end
table.insert(settings, {
name = name,
readable_name = readable_name,
type = setting_type,
default = default,
comment = current_comment,
})
return
end
if setting_type == "bool" then
if remaining_line ~= "false" and remaining_line ~= "true" then
return "Invalid boolean setting"
end
table.insert(settings, {
name = name,
readable_name = readable_name,
type = "bool",
default = remaining_line,
comment = current_comment,
})
return
end
if setting_type == "float" then
local default, min, max = remaining_line:match("^"
-- first float is required, the last 2 are optional
.. "(" .. CHAR_CLASSES.FLOAT .. "+)" .. CHAR_CLASSES.SPACE .. "*"
.. "(" .. CHAR_CLASSES.FLOAT .. "*)" .. CHAR_CLASSES.SPACE .. "*"
.. "(" .. CHAR_CLASSES.FLOAT .. "*)"
.."$")
if not default or not tonumber(default) then
return "Invalid float setting"
end
min = tonumber(min)
max = tonumber(max)
table.insert(settings, {
name = name,
readable_name = readable_name,
type = "float",
default = default,
min = min,
max = max,
comment = current_comment,
})
return
end
if setting_type == "enum" then
local default, values = remaining_line:match("^"
-- first value (default) may be empty (i.e. is optional)
.. "(" .. CHAR_CLASSES.VARIABLE .. "*)" .. CHAR_CLASSES.SPACE .. "*"
.. "(" .. CHAR_CLASSES.FLAGS .. "+)"
.. "$")
if not default or values == "" then
return "Invalid enum setting"
end
table.insert(settings, {
name = name,
readable_name = readable_name,
type = "enum",
default = default,
values = values:split(",", true),
comment = current_comment,
})
return
end
if setting_type == "path" then
local default = remaining_line:match("^(.*)$")
if not default then
return "Invalid path setting"
end
table.insert(settings, {
name = name,
readable_name = readable_name,
type = "path",
default = default,
comment = current_comment,
})
return
end
if setting_type == "flags" then
local default, possible = remaining_line:match("^"
-- first value (default) may be empty (i.e. is optional)
-- this is implemented by making the last value optional, and
-- swapping them around if it turns out empty.
.. "(" .. CHAR_CLASSES.FLAGS .. "+)" .. CHAR_CLASSES.SPACE .. "*"
.. "(" .. CHAR_CLASSES.FLAGS .. "*)"
.. "$")
if not default or not possible then
return "Invalid flags setting"
end
if possible == "" then
possible = default
default = ""
end
table.insert(settings, {
name = name,
readable_name = readable_name,
type = "flags",
default = default,
possible = possible,
comment = current_comment,
})
return
end
return "Invalid setting type \"" .. setting_type .. "\""
end
local function parse_single_file(file, filepath, read_all, result, base_level, allow_secure)
-- store this helper variable in the table so it's easier to pass to parse_setting_line()
result.current_comment = ""
local line = file:read("*line")
while line do
local error_msg = parse_setting_line(result, line, read_all, base_level, allow_secure)
if error_msg then
core.log("error", error_msg .. " in " .. filepath .. " \"" .. line .. "\"")
end
line = file:read("*line")
end
result.current_comment = nil
end
-- read_all: whether to ignore certain setting types for GUI or not
-- parse_mods: whether to parse settingtypes.txt in mods and games
local function parse_config_file(read_all, parse_mods)
local builtin_path = core.get_builtin_path() .. DIR_DELIM .. FILENAME
local file = io.open(builtin_path, "r")
local settings = {}
if not file then
core.log("error", "Can't load " .. FILENAME)
return settings
end
parse_single_file(file, builtin_path, read_all, settings, 0, true)
file:close()
if parse_mods then
-- Parse games
local games_category_initialized = false
local index = 1
local game = gamemgr.get_game(index)
while game do
local path = game.path .. DIR_DELIM .. FILENAME
local file = io.open(path, "r")
if file then
if not games_category_initialized then
local translation = fgettext_ne("Games"), -- not used, but needed for xgettext
table.insert(settings, {
name = "Games",
level = 0,
type = "category",
})
games_category_initialized = true
end
table.insert(settings, {
name = game.name,
level = 1,
type = "category",
})
parse_single_file(file, path, read_all, settings, 2, false)
file:close()
end
index = index + 1
game = gamemgr.get_game(index)
end
-- Parse mods
local mods_category_initialized = false
local mods = {}
get_mods(core.get_modpath(), mods)
for _, mod in ipairs(mods) do
local path = mod.path .. DIR_DELIM .. FILENAME
local file = io.open(path, "r")
if file then
if not mods_category_initialized then
local translation = fgettext_ne("Mods"), -- not used, but needed for xgettext
table.insert(settings, {
name = "Mods",
level = 0,
type = "category",
})
mods_category_initialized = true
end
table.insert(settings, {
name = mod.name,
level = 1,
type = "category",
})
parse_single_file(file, path, read_all, settings, 2, false)
file:close()
end
end
end
return settings
end
local settings = parse_config_file(false, true)
local selected_setting = 1
local function get_current_value(setting)
local value = core.setting_get(setting.name)
if value == nil then
value = setting.default
end
return value
end
local function create_change_setting_formspec(dialogdata)
local setting = settings[selected_setting]
local formspec = "size[10,5.2,true]" ..
"button[5,4.5;2,1;btn_done;" .. fgettext("Save") .. "]" ..
"button[3,4.5;2,1;btn_cancel;" .. fgettext("Cancel") .. "]" ..
"tablecolumns[color;text]" ..
"tableoptions[background=#00000000;highlight=#00000000;border=false]" ..
"table[0,0;10,3;info;"
if setting.readable_name then
formspec = formspec .. "#FFFF00," .. fgettext(setting.readable_name)
.. " (" .. core.formspec_escape(setting.name) .. "),"
else
formspec = formspec .. "#FFFF00," .. core.formspec_escape(setting.name) .. ","
end
formspec = formspec .. ",,"
local comment_text = ""
if setting.comment == "" then
comment_text = fgettext_ne("(No description of setting given)")
else
comment_text = fgettext_ne(setting.comment)
end
for _, comment_line in ipairs(comment_text:split("\n", true)) do
formspec = formspec .. "," .. core.formspec_escape(comment_line) .. ","
end
if setting.type == "flags" then
formspec = formspec .. ",,"
.. "," .. fgettext("Please enter a comma seperated list of flags.") .. ","
.. "," .. fgettext("Possible values are: ")
.. core.formspec_escape(setting.possible:gsub(",", ", ")) .. ","
elseif setting.type == "noise_params" then
formspec = formspec .. ",,"
.. "," .. fgettext("Format: <offset>, <scale>, (<spreadX>, <spreadY>, <spreadZ>), <seed>, <octaves>, <persistence>") .. ","
.. "," .. fgettext("Optionally the lacunarity can be appended with a leading comma.") .. ","
elseif setting.type == "v3f" then
formspec = formspec .. ",,"
.. "," .. fgettext_ne("Format is 3 numbers separated by commas and inside brackets.") .. ","
end
formspec = formspec:sub(1, -2) -- remove trailing comma
formspec = formspec .. ";1]"
if setting.type == "bool" then
local selected_index
if core.is_yes(get_current_value(setting)) then
selected_index = 2
else
selected_index = 1
end
formspec = formspec .. "dropdown[0.5,3.5;3,1;dd_setting_value;"
.. fgettext("Disabled") .. "," .. fgettext("Enabled") .. ";"
.. selected_index .. "]"
elseif setting.type == "enum" then
local selected_index = 0
formspec = formspec .. "dropdown[0.5,3.5;3,1;dd_setting_value;"
for index, value in ipairs(setting.values) do
-- translating value is not possible, since it's the value
-- that we set the setting to
formspec = formspec .. core.formspec_escape(value) .. ","
if get_current_value(setting) == value then
selected_index = index
end
end
if #setting.values > 0 then
formspec = formspec:sub(1, -2) -- remove trailing comma
end
formspec = formspec .. ";" .. selected_index .. "]"
elseif setting.type == "path" then
local current_value = dialogdata.selected_path
if not current_value then
current_value = get_current_value(setting)
end
formspec = formspec .. "field[0.5,4;7.5,1;te_setting_value;;"
.. core.formspec_escape(current_value) .. "]"
.. "button[8,3.75;2,1;btn_browser_path;" .. fgettext("Browse") .. "]"
else
-- TODO: fancy input for float, int, flags, noise_params, v3f
local width = 10
local text = get_current_value(setting)
if dialogdata.error_message then
formspec = formspec .. "tablecolumns[color;text]" ..
"tableoptions[background=#00000000;highlight=#00000000;border=false]" ..
"table[5,3.9;5,0.6;error_message;#FF0000,"
.. core.formspec_escape(dialogdata.error_message) .. ";0]"
width = 5
if dialogdata.entered_text then
text = dialogdata.entered_text
end
end
formspec = formspec .. "field[0.5,4;" .. width .. ",1;te_setting_value;;"
.. core.formspec_escape(text) .. "]"
end
return formspec
end
local function handle_change_setting_buttons(this, fields)
if fields["btn_done"] or fields["key_enter"] then
local setting = settings[selected_setting]
if setting.type == "bool" then
local new_value = fields["dd_setting_value"]
-- Note: new_value is the actual (translated) value shown in the dropdown
core.setting_setbool(setting.name, new_value == fgettext("Enabled"))
elseif setting.type == "enum" then
local new_value = fields["dd_setting_value"]
core.setting_set(setting.name, new_value)
elseif setting.type == "int" then
local new_value = tonumber(fields["te_setting_value"])
if not new_value or math.floor(new_value) ~= new_value then
this.data.error_message = fgettext_ne("Please enter a valid integer.")
this.data.entered_text = fields["te_setting_value"]
core.update_formspec(this:get_formspec())
return true
end
if setting.min and new_value < setting.min then
this.data.error_message = fgettext_ne("The value must be greater than $1.", setting.min)
this.data.entered_text = fields["te_setting_value"]
core.update_formspec(this:get_formspec())
return true
end
if setting.max and new_value > setting.max then
this.data.error_message = fgettext_ne("The value must be lower than $1.", setting.max)
this.data.entered_text = fields["te_setting_value"]
core.update_formspec(this:get_formspec())
return true
end
core.setting_set(setting.name, new_value)
elseif setting.type == "float" then
local new_value = tonumber(fields["te_setting_value"])
if not new_value then
this.data.error_message = fgettext_ne("Please enter a valid number.")
this.data.entered_text = fields["te_setting_value"]
core.update_formspec(this:get_formspec())
return true
end
core.setting_set(setting.name, new_value)
elseif setting.type == "flags" then
local new_value = fields["te_setting_value"]
for _,value in ipairs(new_value:split(",", true)) do
value = value:trim()
local possible = "," .. setting.possible .. ","
if not possible:find("," .. value .. ",", 0, true) then
this.data.error_message = fgettext_ne("\"$1\" is not a valid flag.", value)
this.data.entered_text = fields["te_setting_value"]
core.update_formspec(this:get_formspec())
return true
end
end
core.setting_set(setting.name, new_value)
else
local new_value = fields["te_setting_value"]
core.setting_set(setting.name, new_value)
end
core.setting_save()
this:delete()
return true
end
if fields["btn_cancel"] then
this:delete()
return true
end
if fields["btn_browser_path"] then
core.show_file_open_dialog("dlg_browse_path", fgettext_ne("Select path"))
end
if fields["dlg_browse_path_accepted"] then
this.data.selected_path = fields["dlg_browse_path_accepted"]
core.update_formspec(this:get_formspec())
end
return false
end
local function create_settings_formspec(tabview, name, tabdata)
local formspec = "size[12,6.5;true]" ..
"tablecolumns[color;tree;text;text]" ..
"tableoptions[background=#00000000;border=false]" ..
"table[0,0;12,5.5;list_settings;"
local current_level = 0
for _, entry in ipairs(settings) do
local name
if not core.setting_getbool("main_menu_technical_settings") and entry.readable_name then
name = fgettext_ne(entry.readable_name)
else
name = entry.name
end
if entry.type == "category" then
current_level = entry.level
formspec = formspec .. "#FFFF00," .. current_level .. "," .. fgettext(name) .. ",,"
elseif entry.type == "bool" then
local value = get_current_value(entry)
if core.is_yes(value) then
value = fgettext("Enabled")
else
value = fgettext("Disabled")
end
formspec = formspec .. "," .. (current_level + 1) .. "," .. core.formspec_escape(name) .. ","
.. value .. ","
elseif entry.type == "key" then
-- ignore key settings, since we have a special dialog for them
else
formspec = formspec .. "," .. (current_level + 1) .. "," .. core.formspec_escape(name) .. ","
.. core.formspec_escape(get_current_value(entry)) .. ","
end
end
if #settings > 0 then
formspec = formspec:sub(1, -2) -- remove trailing comma
end
formspec = formspec .. ";" .. selected_setting .. "]" ..
"button[0,6;4,1;btn_back;".. fgettext("< Back to Settings page") .. "]" ..
"button[10,6;2,1;btn_edit;" .. fgettext("Edit") .. "]" ..
"button[7,6;3,1;btn_restore;" .. fgettext("Restore Default") .. "]" ..
"checkbox[0,5.3;cb_tech_settings;" .. fgettext("Show technical names") .. ";"
.. dump(core.setting_getbool("main_menu_technical_settings")) .. "]"
return formspec
end
local function handle_settings_buttons(this, fields, tabname, tabdata)
local list_enter = false
if fields["list_settings"] then
selected_setting = core.get_table_index("list_settings")
if core.explode_table_event(fields["list_settings"]).type == "DCL" then
-- Directly toggle booleans
local setting = settings[selected_setting]
if setting.type == "bool" then
local current_value = get_current_value(setting)
core.setting_setbool(setting.name, not core.is_yes(current_value))
core.setting_save()
return true
else
list_enter = true
end
else
return true
end
end
if fields["btn_edit"] or list_enter then
local setting = settings[selected_setting]
if setting.type ~= "category" then
local edit_dialog = dialog_create("change_setting", create_change_setting_formspec,
handle_change_setting_buttons)
edit_dialog:set_parent(this)
this:hide()
edit_dialog:show()
end
return true
end
if fields["btn_restore"] then
local setting = settings[selected_setting]
if setting.type ~= "category" then
core.setting_set(setting.name, setting.default)
core.setting_save()
core.update_formspec(this:get_formspec())
end
return true
end
if fields["btn_back"] then
this:delete()
return true
end
if fields["cb_tech_settings"] then
core.setting_set("main_menu_technical_settings", fields["cb_tech_settings"])
core.setting_save()
core.update_formspec(this:get_formspec())
return true
end
return false
end
function create_adv_settings_dlg()
local dlg = dialog_create("settings_advanced",
create_settings_formspec,
handle_settings_buttons,
nil)
return dlg
end
local function create_minetest_conf_example()
local result = "# This file contains a list of all available settings and their default value for minetest.conf\n" ..
"\n" ..
"# By default, all the settings are commented and not functional.\n" ..
"# Uncomment settings by removing the preceding #.\n" ..
"\n" ..
"# minetest.conf is read by default from:\n" ..
"# ../minetest.conf\n" ..
"# ../../minetest.conf\n" ..
"# Any other path can be chosen by passing the path as a parameter\n" ..
"# to the program, eg. \"minetest.exe --config ../minetest.conf.example\".\n" ..
"\n" ..
"# Further documentation:\n" ..
"# http://wiki.minetest.net/\n" ..
"\n"
local settings = parse_config_file(true, false)
for _, entry in ipairs(settings) do
if entry.type == "category" then
if entry.level == 0 then
result = result .. "#\n# " .. entry.name .. "\n#\n\n"
else
for i = 1, entry.level do
result = result .. "#"
end
result = result .. "# " .. entry.name .. "\n\n"
end
else
if entry.comment ~= "" then
for _, comment_line in ipairs(entry.comment:split("\n", true)) do
result = result .."# " .. comment_line .. "\n"
end
end
result = result .. "# type: " .. entry.type
if entry.min then
result = result .. " min: " .. entry.min
end
if entry.max then
result = result .. " max: " .. entry.max
end
if entry.values then
result = result .. " values: " .. table.concat(entry.values, ", ")
end
if entry.possible then
result = result .. " possible values: " .. entry.possible:gsub(",", ", ")
end
result = result .. "\n"
local append = ""
if entry.default ~= "" then
append = " " .. entry.default
end
result = result .. "# " .. entry.name .. " =" .. append .. "\n\n"
end
end
return result
end
local function create_translation_file()
local result = "// This file is automatically generated\n" ..
"// It conatins a bunch of fake gettext calls, to tell xgettext about the strings in config files\n" ..
"// To update it, refer to the bottom of builtin/mainmenu/tab_settings.lua\n\n" ..
"fake_function() {\n"
local settings = parse_config_file(true, false)
for _, entry in ipairs(settings) do
if entry.type == "category" then
local name_escaped = entry.name:gsub("\"", "\\\"")
result = result .. "\tgettext(\"" .. name_escaped .. "\");\n"
else
if entry.readable_name then
local readable_name_escaped = entry.readable_name:gsub("\"", "\\\"")
result = result .. "\tgettext(\"" .. readable_name_escaped .. "\");\n"
end
if entry.comment ~= "" then
local comment_escaped = entry.comment:gsub("\n", "\\n")
comment_escaped = comment_escaped:gsub("\"", "\\\"")
result = result .. "\tgettext(\"" .. comment_escaped .. "\");\n"
end
end
end
result = result .. "}\n"
return result
end
if false then
local file = io.open("minetest.conf.example", "w")
if file then
file:write(create_minetest_conf_example())
file:close()
end
end
if false then
local file = io.open("src/settings_translation_file.cpp", "w")
if file then
file:write(create_translation_file())
file:close()
end
end

View File

@ -37,22 +37,29 @@ dofile(menupath .. DIR_DELIM .. "common.lua")
dofile(menupath .. DIR_DELIM .. "gamemgr.lua") dofile(menupath .. DIR_DELIM .. "gamemgr.lua")
dofile(menupath .. DIR_DELIM .. "modmgr.lua") dofile(menupath .. DIR_DELIM .. "modmgr.lua")
dofile(menupath .. DIR_DELIM .. "store.lua") dofile(menupath .. DIR_DELIM .. "store.lua")
dofile(menupath .. DIR_DELIM .. "textures.lua")
dofile(menupath .. DIR_DELIM .. "dlg_config_world.lua") dofile(menupath .. DIR_DELIM .. "dlg_config_world.lua")
dofile(menupath .. DIR_DELIM .. "tab_credits.lua") dofile(menupath .. DIR_DELIM .. "dlg_settings_advanced.lua")
dofile(menupath .. DIR_DELIM .. "tab_mods.lua")
dofile(menupath .. DIR_DELIM .. "tab_settings.lua")
if PLATFORM ~= "Android" then if PLATFORM ~= "Android" then
dofile(menupath .. DIR_DELIM .. "dlg_create_world.lua") dofile(menupath .. DIR_DELIM .. "dlg_create_world.lua")
dofile(menupath .. DIR_DELIM .. "dlg_delete_mod.lua") dofile(menupath .. DIR_DELIM .. "dlg_delete_mod.lua")
dofile(menupath .. DIR_DELIM .. "dlg_delete_world.lua") dofile(menupath .. DIR_DELIM .. "dlg_delete_world.lua")
dofile(menupath .. DIR_DELIM .. "dlg_rename_modpack.lua") dofile(menupath .. DIR_DELIM .. "dlg_rename_modpack.lua")
dofile(menupath .. DIR_DELIM .. "tab_multiplayer.lua") end
dofile(menupath .. DIR_DELIM .. "tab_server.lua")
dofile(menupath .. DIR_DELIM .. "tab_singleplayer.lua") local tabs = {}
dofile(menupath .. DIR_DELIM .. "tab_texturepacks.lua")
dofile(menupath .. DIR_DELIM .. "textures.lua") tabs.settings = dofile(menupath .. DIR_DELIM .. "tab_settings.lua")
tabs.mods = dofile(menupath .. DIR_DELIM .. "tab_mods.lua")
tabs.credits = dofile(menupath .. DIR_DELIM .. "tab_credits.lua")
if PLATFORM == "Android" then
tabs.simple_main = dofile(menupath .. DIR_DELIM .. "tab_simple_main.lua")
else else
dofile(menupath .. DIR_DELIM .. "tab_simple_main.lua") tabs.singleplayer = dofile(menupath .. DIR_DELIM .. "tab_singleplayer.lua")
tabs.multiplayer = dofile(menupath .. DIR_DELIM .. "tab_multiplayer.lua")
tabs.server = dofile(menupath .. DIR_DELIM .. "tab_server.lua")
tabs.texturepacks = dofile(menupath .. DIR_DELIM .. "tab_texturepacks.lua")
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -68,8 +75,34 @@ local function init_globals()
-- Init gamedata -- Init gamedata
gamedata.worldindex = 0 gamedata.worldindex = 0
if PLATFORM == "Android" then
local world_list = core.get_worlds()
local world_index
if PLATFORM ~= "Android" then local found_singleplayerworld = false
for i, world in ipairs(world_list) do
if world.name == "singleplayerworld" then
found_singleplayerworld = true
world_index = i
break
end
end
if not found_singleplayerworld then
core.create_world("singleplayerworld", 1)
world_list = core.get_worlds()
for i, world in ipairs(world_list) do
if world.name == "singleplayerworld" then
world_index = i
break
end
end
end
gamedata.worldindex = world_index
else
menudata.worldlist = filterlist.create( menudata.worldlist = filterlist.create(
core.get_worlds, core.get_worlds,
compare_worlds, compare_worlds,
@ -88,61 +121,34 @@ local function init_globals()
if not core.setting_get("menu_last_game") then if not core.setting_get("menu_last_game") then
local default_game = core.setting_get("default_game") or "minetest" local default_game = core.setting_get("default_game") or "minetest"
core.setting_set("menu_last_game", default_game ) core.setting_set("menu_last_game", default_game)
end end
mm_texture.init() mm_texture.init()
else
local world_list = core.get_worlds()
local found_singleplayerworld = false
for i,world in pairs(world_list) do
if world.name == "singleplayerworld" then
found_singleplayerworld = true
gamedata.worldindex = i
break
end
end
if not found_singleplayerworld then
core.create_world("singleplayerworld", 1)
local world_list = core.get_worlds()
for i,world in pairs(world_list) do
if world.name == "singleplayerworld" then
gamedata.worldindex = i
break
end
end
end
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.2}, {x = 0, y = 0})
if PLATFORM ~= "Android" then
tv_main:set_autosave_tab(true) if PLATFORM == "Android" then
end tv_main:add(tabs.simple_main)
if PLATFORM ~= "Android" then tv_main:add(tabs.settings)
tv_main:add(tab_singleplayer)
tv_main:add(tab_multiplayer)
tv_main:add(tab_server)
else else
tv_main:add(tab_simple_main) tv_main:set_autosave_tab(true)
tv_main:add(tabs.singleplayer)
tv_main:add(tabs.multiplayer)
tv_main:add(tabs.server)
tv_main:add(tabs.settings)
tv_main:add(tabs.texturepacks)
end end
tv_main:add(tab_settings)
if PLATFORM ~= "Android" then tv_main:add(tabs.mods)
tv_main:add(tab_texturepacks) tv_main:add(tabs.credits)
end
tv_main:add(tab_mods)
tv_main:add(tab_credits)
tv_main:set_global_event_handler(main_event_handler) tv_main:set_global_event_handler(main_event_handler)
tv_main:set_fixed_size(false) tv_main:set_fixed_size(false)
if not (PLATFORM == "Android") then if PLATFORM ~= "Android" then
tv_main:set_tab(core.setting_get("maintab_LAST")) tv_main:set_tab(core.setting_get("maintab_LAST"))
end end
ui.set_default("maintab") ui.set_default("maintab")
@ -150,9 +156,9 @@ local function init_globals()
-- Create modstore ui -- Create modstore ui
if PLATFORM == "Android" then if PLATFORM == "Android" then
modstore.init({x=12, y=6}, 3, 2) modstore.init({x = 12, y = 6}, 3, 2)
else else
modstore.init({x=12, y=8}, 4, 3) modstore.init({x = 12, y = 8}, 4, 3)
end end
ui.update() ui.update()

View File

@ -1,4 +1,4 @@
-- helper file to be able to debug the simple menu on PC -- helper file to be able to debug the simple menu on PC
-- without messing around with actual menu code! -- without messing around with actual menu code!
PLATFORM="Android" PLATFORM = "Android"
dofile("builtin/mainmenu/init.lua") dofile("builtin/mainmenu/init.lua")

View File

@ -19,29 +19,29 @@
function get_mods(path,retval,modpack) function get_mods(path,retval,modpack)
local mods = core.get_dir_list(path, true) local mods = core.get_dir_list(path, true)
for i=1, #mods, 1 do for _, name in ipairs(mods) do
if mods[i]:sub(1,1) ~= "." then if name:sub(1, 1) ~= "." then
local prefix = path .. DIR_DELIM .. name .. DIR_DELIM
local toadd = {} local toadd = {}
local modpackfile = nil retval[#retval + 1] = toadd
toadd.name = mods[i] local mod_conf = Settings(prefix .. "mod.conf"):to_table()
toadd.path = path .. DIR_DELIM .. mods[i] .. DIR_DELIM if mod_conf.name then
if modpack ~= nil and name = mod_conf.name
modpack ~= "" then
toadd.modpack = modpack
else
local filename = path .. DIR_DELIM .. mods[i] .. DIR_DELIM .. "modpack.txt"
local error = nil
modpackfile,error = io.open(filename,"r")
end end
if modpackfile ~= nil then toadd.name = name
toadd.path = prefix
if modpack ~= nil and modpack ~= "" then
toadd.modpack = modpack
else
local modpackfile = io.open(prefix .. "modpack.txt")
if modpackfile then
modpackfile:close() modpackfile:close()
toadd.is_modpack = true toadd.is_modpack = true
table.insert(retval,toadd) get_mods(prefix, retval, name)
get_mods(path .. DIR_DELIM .. mods[i],retval,mods[i]) end
else
table.insert(retval,toadd)
end end
end end
end end
@ -412,7 +412,7 @@ function modmgr.preparemodlist(data)
for i=1,#global_mods,1 do for i=1,#global_mods,1 do
global_mods[i].typ = "global_mod" global_mods[i].typ = "global_mod"
table.insert(retval,global_mods[i]) retval[#retval + 1] = global_mods[i]
end end
--read game mods --read game mods
@ -421,7 +421,7 @@ function modmgr.preparemodlist(data)
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"
table.insert(retval,game_mods[i]) retval[#retval + 1] = game_mods[i]
end end
if data.worldpath == nil then if data.worldpath == nil then

View File

@ -17,64 +17,84 @@
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
tab_credits = { local core_developers = {
"Perttu Ahola (celeron55) <celeron55@gmail.com>",
"Ryan Kwolek (kwolekr) <kwolekr@minetest.net>",
"PilzAdam <pilzadam@minetest.net>",
"sfan5 <sfan5@live.de>",
"kahrl <kahrl@gmx.net>",
"sapier",
"ShadowNinja <shadowninja@minetest.net>",
"Nathanaël Courant (Nore/Ekdohibs) <nore@mesecons.net>",
"Loic Blot (nerzhul/nrz) <loic.blot@unix-experience.fr>",
"Matt Gregory (paramat)",
"est31 <MTest31@outlook.com>",
"Craig Robbins (Zeno)",
}
local active_contributors = {
"Auke Kok (sofar) <sofar@foo-projects.org>",
"Duane Robertson <duane@duanerobertson.com>",
"SmallJoker <mk939@ymail.com>",
"Andrew Ward (rubenwardy) <rubenwardy@gmail.com>",
"Jeija <jeija@mesecons.net>",
"Gregory Currie (gregorycu)",
"Sokomine <wegwerf@anarres.dyndns.org>",
"TeTpaAka",
"Jean-Patrick G (kilbith) <jeanpatrick.guerrero@gmail.com>",
"Diego Martínez (kaeza) <kaeza@users.sf.net>",
}
local previous_core_developers = {
"BlockMen",
"Maciej Kasatkin (RealBadAngel) <maciej.kasatkin@o2.pl>",
"Lisa Milne (darkrose) <lisa@ltmnet.com>",
"proller",
"Ilya Zhuravlev (xyz) <xyz@minetest.net>",
}
local previous_contributors = {
"Vanessa Ezekowitz (VanessaE) <vanessaezekowitz@gmail.com>",
"Jurgen Doser (doserj) <jurgen.doser@gmail.com>",
"MirceaKitsune <mirceakitsune@gmail.com>",
"dannydark <the_skeleton_of_a_child@yahoo.co.uk>",
"0gb.us <0gb.us@0gb.us>",
"Guiseppe Bilotta (Oblomov) <guiseppe.bilotta@gmail.com>",
"Jonathan Neuschafer <j.neuschaefer@gmx.net>",
"Nils Dagsson Moskopp (erlehmann) <nils@dieweltistgarnichtso.net>",
"Břetislav Štec (t0suj4/TBC_x)",
"Aaron Suen <warr1024@gmail.com>",
"Constantin Wenger (SpeedProg) <constantin.wenger@googlemail.com>",
"matttpt <matttpt@gmail.com>",
"JacobF <queatz@gmail.com>",
"TriBlade9 <triblade9@mail.com>",
"Zefram <zefram@fysh.org>",
}
return {
name = "credits", name = "credits",
caption = fgettext("Credits"), caption = fgettext("Credits"),
cbf_formspec = function (tabview, name, tabdata) cbf_formspec = function(tabview, name, tabdata)
local logofile = defaulttexturedir .. "logo.png" local logofile = defaulttexturedir .. "logo.png"
return "label[0.5,3.2;Minetest " .. core.get_version() .. "]" .. return "image[0.5,1;" .. core.formspec_escape(logofile) .. "]" ..
"label[0.5,3.2;Minetest " .. core.get_version() .. "]" ..
"label[0.5,3.5;http://minetest.net]" .. "label[0.5,3.5;http://minetest.net]" ..
"image[0.5,1;" .. core.formspec_escape(logofile) .. "]" ..
"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,5.8;list_credits;" ..
"#FFFF00," .. fgettext("Core Developers") .."," .. "#FFFF00," .. "Dedication of the current release" .. ",," ..
",Perttu Ahola (celeron55) <celeron55@gmail.com>,".. "The 0.4.14 release is dedicated to the memory of" .. ",," ..
",Ryan Kwolek (kwolekr) <kwolekr@minetest.net>,".. "Minetest developer Maciej Kasatkin (RealBadAngel)" .. ",," ..
",PilzAdam <pilzadam@minetest.net>," .. "who died on March 24 2016." .. ",," ..
",sfan5 <sfan5@live.de>,".. "Our thoughts are with his family and friends." .. ",,," ..
",kahrl <kahrl@gmx.net>,".. "#FFFF00," .. fgettext("Core Developers") .. ",," ..
",sapier,".. table.concat(core_developers, ",,") .. ",,," ..
",ShadowNinja <shadowninja@minetest.net>,".. "#FFFF00," .. fgettext("Active Contributors") .. ",," ..
",Nathanael Courant (Nore/Ekdohibs) <nore@mesecons.net>,".. table.concat(active_contributors, ",,") .. ",,," ..
",BlockMen,".. "#FFFF00," .. fgettext("Previous Core Developers") ..",," ..
",Craig Robbins (Zeno),".. table.concat(previous_core_developers, ",,") .. ",,," ..
",Loic Blot (nerzhul/nrz) <loic.blot@unix-experience.fr>,".. "#FFFF00," .. fgettext("Previous Contributors") .. ",," ..
",Mat Gregory (paramat),".. table.concat(previous_contributors, ",,") .. "," ..
",est31 <MTest31@outlook.com>," ..
",,"..
"#FFFF00," .. fgettext("Active Contributors") .. "," ..
",SmallJoker <mk939@ymail.com>," ..
",Andrew Ward (rubenwardy) <rubenwardy@gmail.com>," ..
",Aaron Suen <warr1024@gmail.com>," ..
",Sokomine <wegwerf@anarres.dyndns.org>," ..
",Břetislav Štec (t0suj4/TBC_x)," ..
",TeTpaAka," ..
",Jean-Patrick G (kilbith) <jeanpatrick.guerrero@gmail.com>," ..
",Diego Martinez (kaeza) <kaeza@users.sf.net>," ..
",," ..
"#FFFF00," .. fgettext("Previous Core Developers") .."," ..
",Maciej Kasatkin (RealBadAngel) <maciej.kasatkin@o2.pl>,"..
",Lisa Milne (darkrose) <lisa@ltmnet.com>," ..
",proller," ..
",Ilya Zhuravlev (xyz) <xyz@minetest.net>," ..
",," ..
"#FFFF00," .. fgettext("Previous Contributors") .. "," ..
",Vanessa Ezekowitz (VanessaE) <vanessaezekowitz@gmail.com>,"..
",Jurgen Doser (doserj) <jurgen.doser@gmail.com>,"..
",Gregory Currie (gregorycu)," ..
",Jeija <jeija@mesecons.net>,"..
",MirceaKitsune <mirceakitsune@gmail.com>,"..
",dannydark <the_skeleton_of_a_child@yahoo.co.uk>,"..
",0gb.us <0gb.us@0gb.us>,"..
",Guiseppe Bilotta (Oblomov) <guiseppe.bilotta@gmail.com>,"..
",Jonathan Neuschafer <j.neuschaefer@gmx.net>,"..
",Nils Dagsson Moskopp (erlehmann) <nils@dieweltistgarnichtso.net>,"..
",Constantin Wenger (SpeedProg) <constantin.wenger@googlemail.com>,"..
",matttpt <matttpt@gmail.com>,"..
",JacobF <queatz@gmail.com>,"..
",TriBlade9 <triblade9@mail.com>,"..
",Zefram <zefram@fysh.org>,"..
";1]" ";1]"
end end
} }

View File

@ -28,7 +28,7 @@ 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,4.35;modlist;" .. "textlist[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 .. "]"
@ -78,7 +78,7 @@ local function get_formspec(tabview, name, tabdata)
descriptionfile:close() descriptionfile:close()
else else
descriptionlines = {} descriptionlines = {}
table.insert(descriptionlines,fgettext("No mod description available")) descriptionlines[#descriptionlines + 1] = fgettext("No mod description available")
end end
retval = retval .. retval = retval ..
@ -163,7 +163,7 @@ local function handle_buttons(tabview, fields, tabname, tabdata)
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
tab_mods = { return {
name = "mods", name = "mods",
caption = fgettext("Mods"), caption = fgettext("Mods"),
cbf_formspec = get_formspec, cbf_formspec = get_formspec,

View File

@ -17,44 +17,38 @@
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
local function get_formspec(tabview, name, tabdata) local function get_formspec(tabview, name, tabdata)
local render_details = core.is_yes(core.setting_getbool("public_serverlist")) -- Update the cached supported proto info,
-- it may have changed after a change by the settings menu.
common_update_cached_supp_proto()
local fav_selected = menudata.favorites[tabdata.fav_selected]
local retval = local retval =
"label[7.75,-0.15;" .. fgettext("Address / Port :") .. "]" .. "label[7.75,-0.15;" .. fgettext("Address / Port") .. "]" ..
"label[7.75,1.05;" .. fgettext("Name / Password :") .. "]" .. "label[7.75,1.05;" .. fgettext("Name / Password") .. "]" ..
"field[8,0.75;3.4,0.5;te_address;;" .. "field[8,0.75;3.3,0.5;te_address;;" ..
core.formspec_escape(core.setting_get("address")) .. "]" .. core.formspec_escape(core.setting_get("address")) .. "]" ..
"field[11.25,0.75;1.3,0.5;te_port;;" .. "field[11.15,0.75;1.4,0.5;te_port;;" ..
core.formspec_escape(core.setting_get("remote_port")) .. "]" .. core.formspec_escape(core.setting_get("remote_port")) .. "]" ..
"checkbox[0,4.85;cb_public_serverlist;" .. fgettext("Public Serverlist") .. ";" .. "button[10.1,4.9;2,0.5;btn_mp_connect;" .. fgettext("Connect") .. "]" ..
dump(core.setting_getbool("public_serverlist")) .. "]"
if not core.setting_getbool("public_serverlist") then
retval = retval ..
"button[8,4.9;2,0.5;btn_delete_favorite;" .. fgettext("Delete") .. "]"
end
retval = retval ..
"button[10,4.9;2,0.5;btn_mp_connect;" .. fgettext("Connect") .. "]" ..
"field[8,1.95;2.95,0.5;te_name;;" .. "field[8,1.95;2.95,0.5;te_name;;" ..
core.formspec_escape(core.setting_get("name")) .. "]" .. core.formspec_escape(core.setting_get("name")) .. "]" ..
"pwdfield[10.78,1.95;1.77,0.5;te_pwd;]" .. "pwdfield[10.78,1.95;1.77,0.5;te_pwd;]" ..
"box[7.73,2.35;4.3,2.28;#999999]" .. "box[7.73,2.35;4.3,2.28;#999999]"
"textarea[8.1,2.4;4.26,2.6;;"
if tabdata.fav_selected ~= nil and if tabdata.fav_selected and fav_selected then
menudata.favorites[tabdata.fav_selected] ~= nil and if gamedata.fav then
menudata.favorites[tabdata.fav_selected].description ~= nil then retval = retval .. "button[7.85,4.9;2.3,0.5;btn_delete_favorite;" ..
retval = retval .. fgettext("Del. Favorite") .. "]"
core.formspec_escape(menudata.favorites[tabdata.fav_selected].description,true) end
if fav_selected.description then
retval = retval .. "textarea[8.1,2.4;4.26,2.6;;" ..
core.formspec_escape((gamedata.serverdescription or ""), true) .. ";]"
end
end end
retval = retval ..
";]"
--favourites --favourites
if render_details then
retval = retval .. "tablecolumns[" .. retval = retval .. "tablecolumns[" ..
image_column(fgettext("Favorite"), "favorite") .. ";" ..
"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;" .. -- "/"
@ -63,22 +57,31 @@ local function get_formspec(tabview, name, tabdata)
image_column(fgettext("Damage enabled"), "damage") .. ",padding=0.25;" .. image_column(fgettext("Damage enabled"), "damage") .. ",padding=0.25;" ..
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]" -- name "text,padding=1]" ..
else "table[-0.15,-0.1;7.75,5.5;favourites;"
retval = retval .. "tablecolumns[text]"
end
retval = retval ..
"table[-0.15,-0.1;7.75,5;favourites;"
if #menudata.favorites > 0 then if #menudata.favorites > 0 then
retval = retval .. render_favorite(menudata.favorites[1],render_details) local favs = core.get_favorites("local")
if #favs > 0 then
for i=2,#menudata.favorites,1 do for i = 1, #favs do
retval = retval .. "," .. render_favorite(menudata.favorites[i],render_details) for j = 1, #menudata.favorites do
if menudata.favorites[j].address == favs[i].address and
menudata.favorites[j].port == favs[i].port then
table.insert(menudata.favorites, i, table.remove(menudata.favorites, j))
end
end
if favs[i].address ~= menudata.favorites[i].address then
table.insert(menudata.favorites, i, favs[i])
end
end
end
retval = retval .. render_favorite(menudata.favorites[1], (#favs > 0))
for i = 2, #menudata.favorites do
retval = retval .. "," .. render_favorite(menudata.favorites[i], (i <= #favs))
end end
end end
if tabdata.fav_selected ~= nil then if tabdata.fav_selected then
retval = retval .. ";" .. tabdata.fav_selected .. "]" retval = retval .. ";" .. tabdata.fav_selected .. "]"
else else
retval = retval .. ";0]" retval = retval .. ";0]"
@ -89,36 +92,38 @@ end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
local function main_button_handler(tabview, fields, name, tabdata) local function main_button_handler(tabview, fields, name, tabdata)
if fields["te_name"] ~= nil then if fields.te_name then
gamedata.playername = fields["te_name"] gamedata.playername = fields.te_name
core.setting_set("name", fields["te_name"]) core.setting_set("name", fields.te_name)
end end
if fields["favourites"] ~= nil 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]
if event.type == "DCL" then if event.type == "DCL" then
if event.row <= #menudata.favorites then if event.row <= #menudata.favorites then
if not is_server_protocol_compat_or_error(menudata.favorites[event.row].proto_min, if menudata.favorites_is_public and
menudata.favorites[event.row].proto_max) then not is_server_protocol_compat_or_error(
fav.proto_min, fav.proto_max) then
return true return true
end end
gamedata.address = menudata.favorites[event.row].address
gamedata.port = menudata.favorites[event.row].port gamedata.address = fav.address
gamedata.playername = fields["te_name"] gamedata.port = fav.port
if fields["te_pwd"] ~= nil then gamedata.playername = fields.te_name
gamedata.password = fields["te_pwd"]
end
gamedata.selected_world = 0 gamedata.selected_world = 0
if menudata.favorites ~= nil then if fields.te_pwd then
gamedata.servername = menudata.favorites[event.row].name gamedata.password = fields.te_pwd
gamedata.serverdescription = menudata.favorites[event.row].description
end end
if gamedata.address ~= nil and gamedata.servername = fav.name
gamedata.port ~= nil then gamedata.serverdescription = fav.description
core.setting_set("address",gamedata.address)
core.setting_set("remote_port",gamedata.port) if gamedata.address and gamedata.port then
core.setting_set("address", gamedata.address)
core.setting_set("remote_port", gamedata.port)
core.start() core.start()
end end
end end
@ -127,101 +132,92 @@ local function main_button_handler(tabview, fields, name, tabdata)
if event.type == "CHG" then if event.type == "CHG" then
if event.row <= #menudata.favorites then if event.row <= #menudata.favorites then
local address = menudata.favorites[event.row].address gamedata.fav = false
local port = menudata.favorites[event.row].port local favs = core.get_favorites("local")
local address = fav.address
local port = fav.port
gamedata.serverdescription = fav.description
if address ~= nil and for i = 1, #favs do
port ~= nil then if fav.address == favs[i].address and
core.setting_set("address",address) fav.port == favs[i].port then
core.setting_set("remote_port",port) gamedata.fav = true
end
end end
if address and port then
core.setting_set("address", address)
core.setting_set("remote_port", port)
end
tabdata.fav_selected = event.row tabdata.fav_selected = event.row
end end
return true return true
end end
end end
if fields["key_up"] ~= nil or if fields.key_up or fields.key_down then
fields["key_down"] ~= nil then
local fav_idx = core.get_table_index("favourites") local fav_idx = core.get_table_index("favourites")
local fav = menudata.favorites[fav_idx]
if fav_idx ~= nil then if fav_idx then
if fields["key_up"] ~= nil and fav_idx > 1 then if fields.key_up and fav_idx > 1 then
fav_idx = fav_idx -1 fav_idx = fav_idx - 1
else if fields["key_down"] and fav_idx < #menudata.favorites then elseif fields.key_down and fav_idx < #menudata.favorites then
fav_idx = fav_idx +1 fav_idx = fav_idx + 1
end end end
else else
fav_idx = 1 fav_idx = 1
end end
if menudata.favorites == nil or if not menudata.favorites or not fav then
menudata.favorites[fav_idx] == nil then
tabdata.fav_selected = 0 tabdata.fav_selected = 0
return true return true
end end
local address = menudata.favorites[fav_idx].address local address = fav.address
local port = menudata.favorites[fav_idx].port local port = fav.port
if address ~= nil and if address and port then
port ~= nil then core.setting_set("address", address)
core.setting_set("address",address) core.setting_set("remote_port", port)
core.setting_set("remote_port",port)
end end
tabdata.fav_selected = fav_idx tabdata.fav_selected = fav_idx
return true return true
end end
if fields["cb_public_serverlist"] ~= nil then if fields.btn_delete_favorite then
core.setting_set("public_serverlist", fields["cb_public_serverlist"])
if core.setting_getbool("public_serverlist") then
asyncOnlineFavourites()
else
menudata.favorites = core.get_favorites("local")
end
tabdata.fav_selected = nil
return true
end
if fields["btn_delete_favorite"] ~= nil then
local current_favourite = core.get_table_index("favourites") local current_favourite = core.get_table_index("favourites")
if current_favourite == nil then return end if not current_favourite then return end
core.delete_favorite(current_favourite) core.delete_favorite(current_favourite)
menudata.favorites = order_favorite_list(core.get_favorites()) asyncOnlineFavourites()
tabdata.fav_selected = nil tabdata.fav_selected = nil
core.setting_set("address","") core.setting_set("address", "")
core.setting_set("remote_port","30000") core.setting_set("remote_port", "30000")
return true return true
end end
if (fields["btn_mp_connect"] ~= nil or if (fields.btn_mp_connect or fields.key_enter) and fields.te_address and fields.te_port then
fields["key_enter"] ~= nil) and fields["te_address"] ~= nil and gamedata.playername = fields.te_name
fields["te_port"] ~= nil then gamedata.password = fields.te_pwd
gamedata.address = fields.te_address
gamedata.playername = fields["te_name"] gamedata.port = fields.te_port
gamedata.password = fields["te_pwd"] gamedata.selected_world = 0
gamedata.address = fields["te_address"]
gamedata.port = fields["te_port"]
local fav_idx = core.get_table_index("favourites") local fav_idx = core.get_table_index("favourites")
local fav = menudata.favorites[fav_idx]
if fav_idx ~= nil and fav_idx <= #menudata.favorites and if fav_idx and fav_idx <= #menudata.favorites and
menudata.favorites[fav_idx].address == fields["te_address"] and fav.address == fields.te_address and
menudata.favorites[fav_idx].port == fields["te_port"] then fav.port == fields.te_port then
gamedata.servername = menudata.favorites[fav_idx].name gamedata.servername = fav.name
gamedata.serverdescription = menudata.favorites[fav_idx].description gamedata.serverdescription = fav.description
if not is_server_protocol_compat_or_error(menudata.favorites[fav_idx].proto_min, if menudata.favorites_is_public and
menudata.favorites[fav_idx].proto_max)then not is_server_protocol_compat_or_error(
fav.proto_min, fav.proto_max) then
return true return true
end end
else else
@ -229,10 +225,8 @@ local function main_button_handler(tabview, fields, name, tabdata)
gamedata.serverdescription = "" gamedata.serverdescription = ""
end end
gamedata.selected_world = 0 core.setting_set("address", fields.te_address)
core.setting_set("remote_port", fields.te_port)
core.setting_set("address", fields["te_address"])
core.setting_set("remote_port",fields["te_port"])
core.start() core.start()
return true return true
@ -240,22 +234,16 @@ local function main_button_handler(tabview, fields, name, tabdata)
return false return false
end end
local function on_change(type,old_tab,new_tab) local function on_change(type, old_tab, new_tab)
if type == "LEAVE" then if type == "LEAVE" then return end
return
end
if core.setting_getbool("public_serverlist") then
asyncOnlineFavourites() asyncOnlineFavourites()
else
menudata.favorites = core.get_favorites("local")
end
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
tab_multiplayer = { return {
name = "multiplayer", name = "multiplayer",
caption = fgettext("Client"), caption = fgettext("Client"),
cbf_formspec = get_formspec, cbf_formspec = get_formspec,
cbf_button_handler = main_button_handler, cbf_button_handler = main_button_handler,
on_change = on_change on_change = on_change
} }

View File

@ -186,10 +186,10 @@ local function main_button_handler(this, fields, name, tabdata)
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
tab_server = { return {
name = "server", name = "server",
caption = fgettext("Server"), caption = fgettext("Server"),
cbf_formspec = get_formspec, cbf_formspec = get_formspec,
cbf_button_handler = main_button_handler, cbf_button_handler = main_button_handler,
on_change = nil on_change = nil
} }

File diff suppressed because it is too large Load Diff

View File

@ -17,27 +17,32 @@
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
local function get_formspec(tabview, name, tabdata) local function get_formspec(tabview, name, tabdata)
local retval = "" -- Update the cached supported proto info,
-- it may have changed after a change by the settings menu.
common_update_cached_supp_proto()
local fav_selected = menudata.favorites[tabdata.fav_selected]
local render_details = dump(core.setting_getbool("public_serverlist")) local retval =
"label[9.5,0;".. fgettext("Name / Password") .. "]" ..
retval = retval .. "field[0.25,3.35;5.5,0.5;te_address;;" ..
"label[8,0.5;".. fgettext("Name/Password") .. "]" ..
"field[0.25,3.25;5.5,0.5;te_address;;" ..
core.formspec_escape(core.setting_get("address")) .."]" .. core.formspec_escape(core.setting_get("address")) .."]" ..
"field[5.75,3.25;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.setting_get("remote_port")) .."]" ..
"checkbox[8,-0.25;cb_public_serverlist;".. fgettext("Public Serverlist") .. ";" .. "button[10,2.6;2,1.5;btn_mp_connect;".. fgettext("Connect") .. "]" ..
render_details .. "]" "field[9.8,1;2.6,0.5;te_name;;" ..
retval = retval ..
"button[8,2.5;4,1.5;btn_mp_connect;".. fgettext("Connect") .. "]" ..
"field[8.75,1.5;3.5,0.5;te_name;;" ..
core.formspec_escape(core.setting_get("name")) .."]" .. core.formspec_escape(core.setting_get("name")) .."]" ..
"pwdfield[8.75,2.3;3.5,0.5;te_pwd;]" "pwdfield[9.8,2;2.6,0.5;te_pwd;]"
if tabdata.fav_selected and fav_selected then
if gamedata.fav then
retval = retval .. "button[7.7,2.6;2.3,1.5;btn_delete_favorite;" ..
fgettext("Del. Favorite") .. "]"
end
end
if render_details then
retval = retval .. "tablecolumns[" .. retval = retval .. "tablecolumns[" ..
image_column(fgettext("Favorite"), "favorite") .. ";" ..
"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;" .. -- "/"
@ -46,30 +51,39 @@ local function get_formspec(tabview, name, tabdata)
image_column(fgettext("Damage enabled"), "damage") .. ",padding=0.25;" .. image_column(fgettext("Damage enabled"), "damage") .. ",padding=0.25;" ..
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]" -- name "text,padding=1]" .. -- name
else "table[-0.05,0;9.2,2.75;favourites;"
retval = retval .. "tablecolumns[text]"
end
retval = retval ..
"table[-0.05,0;7.55,2.75;favourites;"
if #menudata.favorites > 0 then if #menudata.favorites > 0 then
retval = retval .. render_favorite(menudata.favorites[1],render_details) local favs = core.get_favorites("local")
if #favs > 0 then
for i=2,#menudata.favorites,1 do for i = 1, #favs do
retval = retval .. "," .. render_favorite(menudata.favorites[i],render_details) for j = 1, #menudata.favorites do
if menudata.favorites[j].address == favs[i].address and
menudata.favorites[j].port == favs[i].port then
table.insert(menudata.favorites, i,
table.remove(menudata.favorites, j))
end
end
if favs[i].address ~= menudata.favorites[i].address then
table.insert(menudata.favorites, i, favs[i])
end
end
end
retval = retval .. render_favorite(menudata.favorites[1], (#favs > 0))
for i = 2, #menudata.favorites do
retval = retval .. "," .. render_favorite(menudata.favorites[i], (i <= #favs))
end end
end end
if tabdata.fav_selected ~= nil then if tabdata.fav_selected then
retval = retval .. ";" .. tabdata.fav_selected .. "]" retval = retval .. ";" .. tabdata.fav_selected .. "]"
else else
retval = retval .. ";0]" retval = retval .. ";0]"
end end
-- separator -- separator
retval = retval .. retval = retval .. "box[-0.28,3.75;12.4,0.1;#FFFFFF]"
"box[-0.28,3.75;12.4,0.1;#FFFFFF]"
-- checkboxes -- checkboxes
retval = retval .. retval = retval ..
@ -87,74 +101,81 @@ end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
local function main_button_handler(tabview, fields, name, tabdata) local function main_button_handler(tabview, fields, name, tabdata)
if fields.btn_start_singleplayer then
if fields["btn_start_singleplayer"] then
gamedata.selected_world = gamedata.worldindex gamedata.selected_world = gamedata.worldindex
gamedata.singleplayer = true gamedata.singleplayer = true
core.start() core.start()
return true return true
end end
if fields["favourites"] ~= nil then if fields.favourites then
local event = core.explode_table_event(fields["favourites"]) local event = core.explode_table_event(fields.favourites)
if event.type == "CHG" then if event.type == "CHG" then
if event.row <= #menudata.favorites then if event.row <= #menudata.favorites then
local address = menudata.favorites[event.row].address gamedata.fav = false
local port = menudata.favorites[event.row].port local favs = core.get_favorites("local")
local fav = menudata.favorites[event.row]
local address = fav.address
local port = fav.port
gamedata.serverdescription = fav.description
if address ~= nil and for i = 1, #favs do
port ~= nil then if fav.address == favs[i].address and
core.setting_set("address",address) fav.port == favs[i].port then
core.setting_set("remote_port",port) gamedata.fav = true
end
end end
if address and port then
core.setting_set("address", address)
core.setting_set("remote_port", port)
end
tabdata.fav_selected = event.row tabdata.fav_selected = event.row
end end
end
return true return true
end end
end
if fields["cb_public_serverlist"] ~= nil then if fields.btn_delete_favorite then
core.setting_set("public_serverlist", fields["cb_public_serverlist"]) local current_favourite = core.get_table_index("favourites")
if not current_favourite then return end
if core.setting_getbool("public_serverlist") then core.delete_favorite(current_favourite)
asyncOnlineFavourites() asyncOnlineFavourites()
else tabdata.fav_selected = nil
menudata.favorites = core.get_favorites("local")
end core.setting_set("address", "")
core.setting_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.setting_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.setting_set("enable_damage", fields.cb_damage)
return true return true
end end
if fields["btn_mp_connect"] ~= nil or if fields.btn_mp_connect or fields.key_enter then
fields["key_enter"] ~= nil then gamedata.playername = fields.te_name
gamedata.password = fields.te_pwd
gamedata.playername = fields["te_name"] gamedata.address = fields.te_address
gamedata.password = fields["te_pwd"] gamedata.port = fields.te_port
gamedata.address = fields["te_address"]
gamedata.port = fields["te_port"]
local fav_idx = core.get_textlist_index("favourites") local fav_idx = core.get_textlist_index("favourites")
if fav_idx ~= nil and fav_idx <= #menudata.favorites and if fav_idx and fav_idx <= #menudata.favorites and
menudata.favorites[fav_idx].address == fields["te_address"] and menudata.favorites[fav_idx].address == fields.te_address and
menudata.favorites[fav_idx].port == fields["te_port"] then menudata.favorites[fav_idx].port == fields.te_port then
local fav = menudata.favorites[fav_idx]
gamedata.servername = fav.name
gamedata.serverdescription = fav.description
gamedata.servername = menudata.favorites[fav_idx].name if menudata.favorites_is_public and
gamedata.serverdescription = menudata.favorites[fav_idx].description not is_server_protocol_compat_or_error(
fav.proto_min, fav.proto_max) then
if not is_server_protocol_compat_or_error(menudata.favorites[fav_idx].proto_min,
menudata.favorites[fav_idx].proto_max) then
return true return true
end end
else else
@ -164,17 +185,16 @@ 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.setting_set("address", fields.te_address)
core.setting_set("remote_port",fields["te_port"]) core.setting_set("remote_port", fields.te_port)
core.start() core.start()
return true return true
end end
if fields["btn_config_sp_world"] ~= nil then if fields.btn_config_sp_world then
local configdialog = create_configure_world_dlg(1) local configdialog = create_configure_world_dlg(1)
if configdialog then
if (configdialog ~= nil) then
configdialog:set_parent(tabview) configdialog:set_parent(tabview)
tabview:hide() tabview:hide()
configdialog:show() configdialog:show()
@ -185,21 +205,15 @@ end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
local function on_activate(type,old_tab,new_tab) local function on_activate(type,old_tab,new_tab)
if type == "LEAVE" then if type == "LEAVE" then return end
return
end
if core.setting_getbool("public_serverlist") then
asyncOnlineFavourites() asyncOnlineFavourites()
else
menudata.favorites = core.get_favorites("local")
end
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
tab_simple_main = { return {
name = "main", name = "main",
caption = fgettext("Main"), caption = fgettext("Main"),
cbf_formspec = get_formspec, cbf_formspec = get_formspec,
cbf_button_handler = main_button_handler, cbf_button_handler = main_button_handler,
on_change = on_activate on_change = on_activate
} }

View File

@ -241,10 +241,10 @@ local function on_change(type, old_tab, new_tab)
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
tab_singleplayer = { return {
name = "singleplayer", name = "singleplayer",
caption = fgettext("Singleplayer"), caption = fgettext("Singleplayer"),
cbf_formspec = get_formspec, cbf_formspec = get_formspec,
cbf_button_handler = main_button_handler, cbf_button_handler = main_button_handler,
on_change = on_change on_change = on_change
} }

View File

@ -17,12 +17,17 @@
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
local function filter_texture_pack_list(list) local function filter_texture_pack_list(list)
local retval = {fgettext("None")} local retval = {}
for _, item in ipairs(list) do for _, item in ipairs(list) do
if item ~= "base" then if item ~= "base" then
table.insert(retval, item) retval[#retval + 1] = item
end end
end end
table.sort(retval)
table.insert(retval, 1, fgettext("None"))
return retval return retval
end end
@ -31,9 +36,9 @@ local function render_texture_pack_list(list)
local retval = "" local retval = ""
for i, v in ipairs(list) do for i, v in ipairs(list) do
if v:sub(1,1) ~= "." then if v:sub(1, 1) ~= "." then
if retval ~= "" then if retval ~= "" then
retval = retval .."," retval = retval .. ","
end end
retval = retval .. core.formspec_escape(v) retval = retval .. core.formspec_escape(v)
@ -46,14 +51,14 @@ end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
local function get_formspec(tabview, name, tabdata) 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.setting_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.setting_get("mainmenu_last_selected_TP"))
if index == nil then index = 1 end if not index then index = 1 end
if current_texture_path == "" then if current_texture_path == "" then
retval = retval .. retval = retval ..
@ -62,15 +67,16 @@ local function get_formspec(tabview, name, tabdata)
return retval return retval
end end
local infofile = current_texture_path ..DIR_DELIM.."description.txt" local infofile = current_texture_path .. DIR_DELIM .. "description.txt"
-- This adds backwards compatibility for old texture pack description files named -- This adds backwards compatibility for old texture pack description files named
-- "info.txt", and should be removed once all such texture packs have been updated -- "info.txt", and should be removed once all such texture packs have been updated
if not file_exists(infofile) then if not file_exists(infofile) then
infofile = current_texture_path ..DIR_DELIM.."info.txt" infofile = current_texture_path .. DIR_DELIM .. "info.txt"
if file_exists(infofile) then if file_exists(infofile) then
core.log("info.txt is depreciated. description.txt should be used instead."); core.log("info.txt is depreciated. description.txt should be used instead.")
end end
end end
local infotext = "" local infotext = ""
local f = io.open(infofile, "r") local f = io.open(infofile, "r")
if not f then if not f then
@ -80,8 +86,8 @@ local function get_formspec(tabview, name, tabdata)
f:close() f:close()
end end
local screenfile = current_texture_path..DIR_DELIM.."screenshot.png" local screenfile = current_texture_path .. DIR_DELIM .. "screenshot.png"
local no_screenshot = nil local no_screenshot
if not file_exists(screenfile) then if not file_exists(screenfile) then
screenfile = nil screenfile = nil
no_screenshot = defaulttexturedir .. "no_screenshot.png" no_screenshot = defaulttexturedir .. "no_screenshot.png"
@ -90,24 +96,24 @@ local function get_formspec(tabview, name, tabdata)
return retval .. return retval ..
render_texture_pack_list(list) .. render_texture_pack_list(list) ..
";" .. index .. "]" .. ";" .. index .. "]" ..
"image[0.25,0.25;4.0,3.7;"..core.formspec_escape(screenfile or no_screenshot).."]".. "image[0.25,0.25;4.0,3.7;" .. core.formspec_escape(screenfile or no_screenshot) .. "]" ..
"textarea[0.6,3.25;3.7,1.5;;"..core.formspec_escape(infotext or "")..";]" "textarea[0.6,3.5;3.7,1.5;;" .. core.formspec_escape(infotext or "") .. ";]"
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
local function main_button_handler(tabview, fields, name, tabdata) local function main_button_handler(tabview, fields, name, tabdata)
if fields["TPs"] ~= nil then if fields["TPs"] then
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", core.setting_set("mainmenu_last_selected_TP", index)
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 ~= nil and #list >= current_index then if current_index and #list >= current_index then
local new_path = core.get_texturepath()..DIR_DELIM..list[current_index] local new_path = core.get_texturepath() .. DIR_DELIM .. list[current_index]
if list[current_index] == fgettext("None") then new_path = "" end if list[current_index] == fgettext("None") then
new_path = ""
end
core.setting_set("texture_path", new_path) core.setting_set("texture_path", new_path)
end end
end end
@ -117,10 +123,10 @@ local function main_button_handler(tabview, fields, name, tabdata)
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
tab_texturepacks = { return {
name = "texturepacks", name = "texturepacks",
caption = fgettext("Texturepacks"), caption = fgettext("Texturepacks"),
cbf_formspec = get_formspec, cbf_formspec = get_formspec,
cbf_button_handler = main_button_handler, cbf_button_handler = main_button_handler,
on_change = nil on_change = nil
} }

View File

@ -179,7 +179,7 @@ function mm_texture.set_dirt_bg()
end end
end end
--use base pack -- Use universal fallback texture in textures/base/pack
local minimalpath = defaulttexturedir .. "dirt_bg.png" local minimalpath = defaulttexturedir .. "menu_bg.png"
core.set_background("background", minimalpath, true, 128) core.set_background("background", minimalpath, true, 128)
end end

View File

@ -209,11 +209,11 @@ keymap_toggle_profiler (Profiler toggle key) key KEY_F6
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_camera_mode (Toggle camera mode key) key KEY_F7 keymap_camera_mode (Toggle camera mode key) key KEY_F7
# Key for increasing the viewing range. Modifies the minimum viewing range. # Key for increasing the viewing range.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_increase_viewing_range_min (View range increase key) key + keymap_increase_viewing_range_min (View range increase key) key +
# Key for decreasing the viewing range. Modifies the minimum viewing range. # Key for decreasing the viewing range.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_decrease_viewing_range_min (View range decrease key) key - keymap_decrease_viewing_range_min (View range decrease key) key -
@ -232,9 +232,18 @@ address (Server address) string
# Note that the port field in the main menu overrides this setting. # Note that the port field in the main menu overrides this setting.
remote_port (Remote port) int 30000 1 65535 remote_port (Remote port) int 30000 1 65535
# Whether to support older servers before protocol version 25.
# Enable if you want to connect to 0.4.12 servers and before.
# Servers starting with 0.4.13 will work, 0.4.12-dev servers may work.
# Disabling this option will protect your password better.
send_pre_v25_init (Support older servers) bool true
# Save the map received by the client on disk. # Save the map received by the client on disk.
enable_local_map_saving (Saving map received from server) bool false enable_local_map_saving (Saving map received from server) bool false
# Show entity selection boxes
show_entity_selectionbox (Show entity selection boxes) bool true
# Enable usage of remote media server (if provided by server). # Enable usage of remote media server (if provided by server).
# Remote servers offer a significantly faster way to download media (e.g. textures) # Remote servers offer a significantly faster way to download media (e.g. textures)
# when connecting to the server. # when connecting to the server.
@ -252,14 +261,12 @@ serverlist_file (Serverlist file) string favoriteservers.txt
[***Basic] [***Basic]
# Enable VBO
enable_vbo (VBO) bool true
# Whether to fog out the end of the visible area. # Whether to fog out the end of the visible area.
enable_fog (Fog) bool true enable_fog (Fog) bool true
# Enable a bit lower water surface, so it doesn't "fill" the node completely.
# Note that this is not quite optimized and that smooth lighting on the
# water surface doesn't work with this.
new_style_water (New style water) bool false
# Leaves style: # Leaves style:
# - Fancy: all faces visible # - Fancy: all faces visible
# - Simple: only outer faces, if defined special_tiles are used # - Simple: only outer faces, if defined special_tiles are used
@ -279,6 +286,9 @@ enable_clouds (Clouds) bool true
# Use 3D cloud look instead of flat. # Use 3D cloud look instead of flat.
enable_3d_clouds (3D clouds) bool true enable_3d_clouds (3D clouds) bool true
# Method used to highlight selected object.
node_highlighting (Node highlighting) enum box box,halo
[***Filtering] [***Filtering]
# Use mip mapping to scale textures. May slightly increase performance. # Use mip mapping to scale textures. May slightly increase performance.
@ -308,11 +318,6 @@ texture_clean_transparent (Clean transparent textures) bool false
# enabled. # enabled.
texture_min_size (Minimum texture size for filters) int 64 texture_min_size (Minimum texture size for filters) int 64
# Pre-generate all item visuals used in the inventory.
# This increases startup time, but runs smoother in-game.
# The generated textures can easily exceed your VRAM, causing artifacts in the inventory.
preload_item_visuals (Preload inventory textures) bool false
# Experimental option, might cause visible spaces between blocks # Experimental option, might cause visible spaces between blocks
# 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
@ -323,6 +328,11 @@ fsaa (FSAA) enum 0 0,1,2,4,8,16
# Thy only work with the OpenGL video backend. # Thy only work with the OpenGL video backend.
enable_shaders (Shaders) bool true enable_shaders (Shaders) bool true
[****Tone Mapping]
# Enables filmic tone mapping
tone_mapping (Filmic tone mapping) bool false
[****Bumpmapping] [****Bumpmapping]
# Enables bumpmapping for textures. Normalmaps need to be supplied by the texture pack # Enables bumpmapping for textures. Normalmaps need to be supplied by the texture pack
@ -385,10 +395,6 @@ enable_waving_plants (Waving plants) bool false
[***Advanced] [***Advanced]
# Minimum wanted FPS.
# The amount of rendered stuff is dynamically set according to this. and viewing range min and max.
wanted_fps (Wanted FPS) int 30
# If FPS would go higher than this, limit it by sleeping # If FPS would go higher than this, limit it by sleeping
# to not waste CPU power for no benefit. # to not waste CPU power for no benefit.
fps_max (Maximum FPS) int 60 fps_max (Maximum FPS) int 60
@ -396,18 +402,14 @@ fps_max (Maximum FPS) int 60
# Maximum FPS when game is paused. # Maximum FPS when game is paused.
pause_fps_max (FPS in pause menu) int 20 pause_fps_max (FPS in pause menu) int 20
# The allowed adjustment range for the automatic rendering range adjustment. # View distance in nodes.
# Set this to be equal to viewing range minimum to disable the auto-adjustment algorithm. # Min = 20
viewing_range_nodes_max (Viewing range maximum) int 160 viewing_range (Viewing range) int 100
# The allowed adjustment range for the automatic rendering range adjustment. # Width component of the initial window size.
# Set this to be equal to viewing range minimum to disable the auto-adjustment algorithm.
viewing_range_nodes_min (Viewing range minimum) int 35
# Vertical initial window size.
screenW (Screen width) int 800 screenW (Screen width) int 800
# Horizontal initial window size. # Height component of the initial window size.
screenH (Screen height) int 600 screenH (Screen height) int 600
# Fullscreen mode. # Fullscreen mode.
@ -454,7 +456,8 @@ fall_bobbing_amount (Fall bobbing) float 0.0
# - interlaced: odd/even line based polarisation screen support. # - interlaced: odd/even line based polarisation screen support.
# - topbottom: split screen top/bottom. # - topbottom: split screen top/bottom.
# - sidebyside: split screen side by side. # - sidebyside: split screen side by side.
3d_mode (3D mode) enum none none,anaglyph,interlaced,topbottom,sidebyside # - pageflip: quadbuffer based 3d.
3d_mode (3D mode) enum none none,anaglyph,interlaced,topbottom,sidebyside,pageflip
# 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)
@ -481,9 +484,6 @@ 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
# Enable selection highlighting for nodes (disables selectionbox).
enable_node_highlighting (Node highlighting) bool false
# 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
@ -507,6 +507,9 @@ directional_colored_fog (Colored fog) bool true
# set to the nearest valid value. # set to the nearest valid value.
ambient_occlusion_gamma (Ambient occlusion gamma) float 2.2 0.25 4.0 ambient_occlusion_gamma (Ambient occlusion gamma) float 2.2 0.25 4.0
# Enables animation of inventory items.
inventory_items_animations (Inventory items animations) bool false
[**Menus] [**Menus]
# Use a cloud animation for the main menu background. # Use a cloud animation for the main menu background.
@ -560,6 +563,14 @@ fallback_font_shadow_alpha (Fallback font shadow alpha) int 128 0 255
# Path to save screenshots at. # Path to save screenshots at.
screenshot_path (Screenshot folder) path screenshot_path (Screenshot folder) path
# Format of screenshots.
screenshot_format (Screenshot format) enum png png,jpg,bmp,pcx,ppm,tga
# Screenshot quality. Only used for JPEG format.
# 1 means worst quality; 100 means best quality.
# Use 0 for default quality.
screenshot_quality (Screenshot quality) int 0 0 100
[**Advanced] [**Advanced]
# 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.
@ -680,6 +691,9 @@ default_password (Default password) string
# See /privs in game for a full list on your server and mod configuration. # See /privs in game for a full list on your server and mod configuration.
default_privs (Default privileges) string interact, shout default_privs (Default privileges) string interact, shout
# Privileges that players with basic_privs can grant
basic_privs (Basic Privileges) string interact, shout
# Whether players are shown to clients without any range limit. # Whether players are shown to clients without any range limit.
# Deprecated, use the setting player_transfer_distance instead. # Deprecated, use the setting player_transfer_distance instead.
unlimited_player_transfer_distance (Unlimited player transfer distance) bool true unlimited_player_transfer_distance (Unlimited player transfer distance) bool true
@ -693,12 +707,6 @@ enable_pvp (Player versus Player) bool true
# If this is set, players will always (re)spawn at the given position. # If this is set, players will always (re)spawn at the given position.
static_spawnpoint (Static spawnpoint) string static_spawnpoint (Static spawnpoint) string
# Maximum distance above water level for player spawn.
# Larger values result in spawn points closer to (x = 0, z = 0).
# Smaller values may result in a suitable spawn point not being found,
# resulting in a spawn at (0, 0, 0) possibly buried underground.
vertical_spawn_range (Vertical spawn range) int 16
# If enabled, new players cannot join with an empty password. # If enabled, new players cannot join with an empty password.
disallow_empty_password (Disallow empty passwords) bool false disallow_empty_password (Disallow empty passwords) bool false
@ -793,6 +801,15 @@ sqlite_synchronous (Synchronous SQLite) enum 2 0,1,2
# Length of a server tick and the interval at which objects are generally updated over network. # Length of a server tick and the interval at which objects are generally updated over network.
dedicated_server_step (Dedicated server step) float 0.1 dedicated_server_step (Dedicated server step) float 0.1
# Time in between active block management cycles
active_block_mgmt_interval (Active Block Management interval) float 2.0
# Length of time between ABM execution cycles
abm_interval (Active Block Modifier interval) float 1.0
# Length of time between NodeTimer execution cycles
nodetimer_interval (NodeTimer interval) float 1.0
# 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.
ignore_world_load_errors (Ignore world errors) bool false ignore_world_load_errors (Ignore world errors) bool false
@ -812,7 +829,7 @@ liquid_update (Liquid update tick) float 1.0
# Name of map generator to be used when creating a new world. # Name of map generator to be used when creating a new world.
# Creating a world in the main menu will override this. # Creating a world in the main menu will override this.
mg_name (Mapgen name) enum v6 v5,v6,v7,fractal,singlenode mg_name (Mapgen name) enum v6 v5,v6,v7,flat,valleys,fractal,singlenode
# Water surface level of the world. # Water surface level of the world.
water_level (Water level) int 1 water_level (Water level) int 1
@ -829,10 +846,11 @@ max_block_generate_distance (Max block generate distance) int 6
map_generation_limit (Map generation limit) int 31000 0 31000 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
# and junglegrass, in all other mapgens this flag controls all decorations.
# 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.
# 'trees' and 'flat' flags only have effect in mgv6. mg_flags (Mapgen flags) flags caves,dungeons,light,decorations caves,dungeons,light,decorations,nocaves,nodungeons,nolight,nodecorations
mg_flags (Mapgen flags) flags trees,caves,dungeons,light trees,caves,dungeons,light,flat,notrees,nocaves,nodungeons,nolight,noflat
[**Advanced] [**Advanced]
@ -866,6 +884,9 @@ mg_biome_np_humidity_blend (Mapgen biome humidity blend noise parameters) noise_
[***Mapgen v5] [***Mapgen v5]
# Controls width of tunnels, a smaller value creates wider tunnels.
mgv5_cave_width (Mapgen v5 cave width) float 0.125
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_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_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_height (Mapgen v5 height noise parameters) noise_params 0, 10, (250, 250, 250), 84174, 4, 0.5, 2.0
@ -886,10 +907,10 @@ 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 enabled and the jungles flag is ignored. # When snowbiomes are enabled jungles are automatically enabled, 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 jungles,biomeblend,mudflow,snowbiomes,nojungles,nobiomeblend,nomudflow,nosnowbiomes mgv6_spflags (Mapgen v6 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. # Controls size of deserts and beaches in Mapgen v6.
# When snowbiomes are enabled 'mgv6_freq_desert' is ignored. # When snowbiomes are enabled 'mgv6_freq_desert' is ignored.
@ -911,15 +932,18 @@ mgv6_np_apple_trees (Mapgen v6 apple trees noise parameters) noise_params 0, 1,
[***Mapgen v7] [***Mapgen v7]
# Map generation attributes specific to Mapgen v7. # Map generation attributes specific to Mapgen v7.
# 'ridges' are the rivers. # The 'ridges' flag controls the rivers.
# 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,nomountains,noridges mgv7_spflags (Mapgen v7 flags) flags mountains,ridges mountains,ridges,nomountains,noridges
# Controls width of tunnels, a smaller value creates wider tunnels.
mgv7_cave_width (Mapgen v7 cave width) float 0.3
mgv7_np_terrain_base (Mapgen v7 terrain base noise parameters) noise_params 4, 70, (600, 600, 600), 82341, 5, 0.6, 2.0 mgv7_np_terrain_base (Mapgen v7 terrain base noise parameters) noise_params 4, 70, (600, 600, 600), 82341, 5, 0.6, 2.0
mgv7_np_terrain_alt (Mapgen v7 terrain altitude noise parameters) noise_params 4, 25, (600, 600, 600), 5934, 5, 0.6, 2.0 mgv7_np_terrain_alt (Mapgen v7 terrain altitude noise parameters) noise_params 4, 25, (600, 600, 600), 5934, 5, 0.6, 2.0
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_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 -12, 24, (500, 500, 500), 4213, 6, 0.7, 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
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_np_filler_depth (Mapgen v7 filler depth noise parameters) noise_params 0, 1.2, (150, 150, 150), 261, 3, 0.7, 2.0
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_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 ridge water noise parameters) noise_params 0, 1, (1000, 1000, 1000), 85039, 5, 0.6, 2.0 mgv7_np_ridge_uwater (Mapgen v7 ridge water noise parameters) noise_params 0, 1, (1000, 1000, 1000), 85039, 5, 0.6, 2.0
@ -928,65 +952,107 @@ mgv7_np_ridge (Mapgen v7 ridge noise parameters) noise_params 0, 1, (100, 100, 1
mgv7_np_cave1 (Mapgen v7 cave1 noise parameters) noise_params 0, 12, (100, 100, 100), 52534, 4, 0.5, 2.0 mgv7_np_cave1 (Mapgen v7 cave1 noise parameters) noise_params 0, 12, (100, 100, 100), 52534, 4, 0.5, 2.0
mgv7_np_cave2 (Mapgen v7 cave2 noise parameters) noise_params 0, 12, (100, 100, 100), 10325, 4, 0.5, 2.0 mgv7_np_cave2 (Mapgen v7 cave2 noise parameters) noise_params 0, 12, (100, 100, 100), 10325, 4, 0.5, 2.0
[***Mapgen flat]
# Map generation attributes specific to Mapgen flat.
# 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 starting with 'no' are used to explicitly disable them.
mgflat_spflags (Mapgen flat flags) flags lakes,hills,,nolakes,nohills
# Y of flat ground.
mgflat_ground_level (Mapgen flat ground level) int 8
# Y of upper limit of large pseudorandom caves.
mgflat_large_cave_depth (Mapgen flat large cave depth) int -33
# Controls width of tunnels, a smaller value creates wider tunnels.
mgflat_cave_width (Mapgen flat cave width) float 0.3
# Terrain noise threshold for lakes.
# Controls proportion of world area covered by lakes.
# Adjust towards 0.0 for a larger proportion.
mgflat_lake_threshold (Mapgen flat lake threshold) float -0.45
# Controls steepness/depth of lake depressions.
mgflat_lake_steepness (Mapgen flat lake steepness) float 48.0
# Terrain noise threshold for hills.
# Controls proportion of world area covered by hills.
# Adjust towards 0.0 for a larger proportion.
mgflat_hill_threshold (Mapgen flat hill threshold) float 0.45
# Controls steepness/height of hills.
mgflat_hill_steepness (Mapgen flat hill steepness) float 64.0
# Determines terrain shape.
# The 3 numbers in brackets control the scale of the
# 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
mgflat_np_cave1 (Mapgen flat cave1 noise parameters) noise_params 0, 12, (128, 128, 128), 52534, 4, 0.5, 2.0
mgflat_np_cave2 (Mapgen flat cave2 noise parameters) noise_params 0, 12, (128, 128, 128), 10325, 4, 0.5, 2.0
[***Mapgen fractal] [***Mapgen fractal]
# Map generation attributes specific to Mapgen fractal. # Controls width of tunnels, a smaller value creates wider tunnels.
# 'julia' selects a julia set to be generated instead of a mandelbrot set. mgfractal_cave_width (Mapgen fractal cave width) float 0.3
# 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.
mgfractal_spflags (Mapgen fractal flags) flags nojulia julia,nojulia
# Mandelbrot set: Iterations of the recursive function. # Choice of 18 fractals from 9 formulas.
# Controls scale of finest detail. # 1 = 4D "Roundy" mandelbrot set.
mgfractal_m_iterations (Mapgen fractal mandelbrot iterations) int 9 # 2 = 4D "Roundy" julia set.
# 3 = 4D "Squarry" mandelbrot set.
# 4 = 4D "Squarry" julia set.
# 5 = 4D "Mandy Cousin" mandelbrot set.
# 6 = 4D "Mandy Cousin" julia set.
# 7 = 4D "Variation" mandelbrot set.
# 8 = 4D "Variation" julia set.
# 9 = 3D "Mandelbrot/Mandelbar" mandelbrot set.
# 10 = 3D "Mandelbrot/Mandelbar" julia set.
# 11 = 3D "Christmas Tree" mandelbrot set.
# 12 = 3D "Christmas Tree" julia set.
# 13 = 3D "Mandelbulb" mandelbrot set.
# 14 = 3D "Mandelbulb" julia set.
# 15 = 3D "Cosine Mandelbulb" mandelbrot set.
# 16 = 3D "Cosine Mandelbulb" julia set.
# 17 = 4D "Mandelbulb" mandelbrot set.
# 18 = 4D "Mandelbulb" julia set.
mgfractal_fractal (Mapgen fractal fractal) int 1 1 18
# Mandelbrot set: Approximate (X,Y,Z) scales in nodes. # Iterations of the recursive function.
# Format is 3 numbers separated by commas and inside brackets. # Controls the amount of fine detail.
mgfractal_m_scale (Mapgen fractal mandelbrot scale) string (1024.0, 256.0, 1024.0) mgfractal_iterations (Mapgen fractal iterations) int 11
# Type 'string' is currently used for a v3f.
# Mandelbrot set: (X,Y,Z) offsets from world centre. # Approximate (X,Y,Z) scale of fractal in nodes.
# Format is 3 numbers separated by commas and inside brackets. mgfractal_scale (Mapgen fractal scale) v3f (4096.0, 1024.0, 4096.0)
# Range roughly -2 to 2, multiply by m_scale for offsets in nodes.
mgfractal_m_offset (Mapgen fractal mandelbrot offset) string (1.75, 0.0, 0.0)
# Type 'string' is currently used for a v3f.
# Mandelbrot set: W co-ordinate of the generated 3D slice of the 4D shape. # (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).
# 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.
mgfractal_offset (Mapgen fractal offset) v3f (1.79, 0.0, 0.0)
# W co-ordinate of the generated 3D slice of a 4D fractal.
# Determines which 3D slice of the 4D shape is generated.
# Has no effect on 3D fractals.
# Range roughly -2 to 2. # Range roughly -2 to 2.
mgfractal_m_slice_w (Mapgen fractal mandelbrot slice w) float 0.0 mgfractal_slice_w (Mapgen fractal slice w) float 0.0
# Julia set: Iterations of the recursive function. # Julia set only: X component of hypercomplex constant determining julia shape.
# Controls scale of finest detail.
mgfractal_j_iterations (Mapgen fractal julia iterations) int 9
# Julia set: Approximate (X,Y,Z) scales in nodes.
# Format is 3 numbers separated by commas and inside brackets.
mgfractal_j_scale (Mapgen fractal julia scale) string (2048.0, 512.0, 2048.0)
# Type 'string' is currently used for a v3f.
# Julia set: (X,Y,Z) offsets from world centre.
# Format is 3 numbers separated by commas and inside brackets.
# Range roughly -2 to 2, multiply by j_scale for offsets in nodes.
mgfractal_j_offset (Mapgen fractal julia offset) string (0.0, 1.0, 0.0)
# Type 'string' is currently used for a v3f.
# Julia set: W co-ordinate of the generated 3D slice of the 4D shape.
# Range roughly -2 to 2.
mgfractal_j_slice_w (Mapgen fractal julia slice w) float 0.0
# Julia set: X value determining the 4D shape.
# Range roughly -2 to 2. # Range roughly -2 to 2.
mgfractal_julia_x (Mapgen fractal julia x) float 0.33 mgfractal_julia_x (Mapgen fractal julia x) float 0.33
# Julia set: Y value determining the 4D 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 (Mapgen fractal julia y) float 0.33
# Julia set: Z value determining the 4D 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 (Mapgen fractal julia z) float 0.33
# Julia set: W value determining the 4D shape. # Julia set only: W component of hypercomplex constant determining julia shape.
# 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 (Mapgen fractal julia w) float 0.33
@ -995,6 +1061,79 @@ mgfractal_np_filler_depth (Mapgen fractal filler depth noise parameters) noise_p
mgfractal_np_cave1 (Mapgen fractal cave1 noise parameters) noise_params 0, 12, (128, 128, 128), 52534, 4, 0.5, 2.0 mgfractal_np_cave1 (Mapgen fractal cave1 noise parameters) noise_params 0, 12, (128, 128, 128), 52534, 4, 0.5, 2.0
mgfractal_np_cave2 (Mapgen fractal cave2 noise parameters) noise_params 0, 12, (128, 128, 128), 10325, 4, 0.5, 2.0 mgfractal_np_cave2 (Mapgen fractal cave2 noise parameters) noise_params 0, 12, (128, 128, 128), 10325, 4, 0.5, 2.0
# Mapgen Valleys parameters
[***Mapgen Valleys]
# General parameters
[****General]
# Map generation attributes specific to Mapgen Valleys.
# 'altitude_chill' makes higher elevations colder, which may cause biome issues.
# 'humid_rivers' modifies the humidity around rivers and in areas where water would tend to pool,
# it may interfere with delicately adjusted biomes.
# 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.
mg_valleys_spflags (Valleys C Flags) flags altitude_chill,humid_rivers altitude_chill,noaltitude_chill,humid_rivers,nohumid_rivers
# The altitude at which temperature drops by 20C
mgvalleys_altitude_chill (Altitude Chill) int 90
# Depth below which you'll find large caves.
mgvalleys_large_cave_depth (Large cave depth) int -33
# Creates unpredictable lava features in caves.
# These can make mining difficult. Zero disables them. (0-10)
mgvalleys_lava_features (Lava Features) int 0
# Depth below which you'll find massive caves.
mgvalleys_massive_cave_depth (Massive cave depth) int -256
# How deep to make rivers
mgvalleys_river_depth (River Depth) int 4
# How wide to make rivers
mgvalleys_river_size (River Size) int 5
# Creates unpredictable water features in caves.
# These can make mining difficult. Zero disables them. (0-10)
mgvalleys_water_features (Water Features) int 0
# Controls width of tunnels, a smaller value creates wider tunnels.
mgvalleys_cave_width (Cave width) float 0.3
# Noise parameters
[****Noises]
# Caves and tunnels form at the intersection of the two noises
mgvalleys_np_cave1 (Cave noise #1) noise_params 0, 12, (100, 100, 100), 52534, 4, 0.5, 2.0
# Caves and tunnels form at the intersection of the two noises
mgvalleys_np_cave2 (Cave noise #2) noise_params 0, 12, (100, 100, 100), 10325, 4, 0.5, 2.0
# The depth of dirt or other filler
mgvalleys_np_filler_depth (Filler Depth) noise_params 0, 1.2, (256, 256, 256), 1605, 3, 0.5, 2.0
# Massive caves form here.
mgvalleys_np_massive_caves (Massive cave noise) noise_params 0, 1, (768, 256, 768), 59033, 6, 0.63, 2.0
# River noise -- rivers occur close to zero
mgvalleys_np_rivers (River Noise) noise_params 0, 1, (256, 256, 256), -6050, 5, 0.6, 2.0
# Base terrain height
mgvalleys_np_terrain_height (Terrain Height) noise_params -10, 50, (1024, 1024, 1024), 5202, 6, 0.4, 2.0
# Raises terrain to make valleys around the rivers
mgvalleys_np_valley_depth (Valley Depth) noise_params 5, 4, (512, 512, 512), -1914, 1, 1.0, 2.0
# Slope and fill work together to modify the heights
mgvalleys_np_inter_valley_fill (Valley Fill) noise_params 0, 1, (256, 512, 256), 1993, 6, 0.8, 2.0
# Amplifies the valleys
mgvalleys_np_valley_profile (Valley Profile) noise_params 0.6, 0.5, (512, 512, 512), 777, 1, 1.0, 2.0
# Slope and fill work together to modify the heights
mgvalleys_np_inter_valley_slope (Valley Slope) noise_params 0.5, 0.5, (128, 128, 128), 746, 1, 1.0, 2.0
[*Security] [*Security]
# Prevent mods from doing insecure things like running shell commands. # Prevent mods from doing insecure things like running shell commands.
@ -1004,6 +1143,10 @@ secure.enable_security (Enable mod security) bool false
# functions even when mod security is on (via request_insecure_environment()). # functions even when mod security is on (via request_insecure_environment()).
secure.trusted_mods (Trusted mods) string secure.trusted_mods (Trusted mods) string
# Comma-seperated list of mods that are allowed to access HTTP APIs, which
# allow them to upload and download data to/from the internet.
secure.http_mods (HTTP Mods) string
[Client and Server] [Client and Server]
# Name of the player. # Name of the player.

View File

@ -0,0 +1,4 @@
void main(void)
{
gl_FragColor = gl_Color;
}

View File

@ -0,0 +1,9 @@
uniform mat4 mWorldViewProj;
void main(void)
{
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = mWorldViewProj * gl_Vertex;
gl_FrontColor = gl_BackColor = gl_Color;
}

View File

@ -20,6 +20,38 @@ bool normalTexturePresent = false;
const float e = 2.718281828459; const float e = 2.718281828459;
const float BS = 10.0; const float BS = 10.0;
#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() void get_texture_flags()
{ {
vec4 flags = texture2D(textureFlags, vec2(0.0, 0.0)); vec4 flags = texture2D(textureFlags, vec2(0.0, 0.0));
@ -47,15 +79,29 @@ vec4 get_normal_map(vec2 uv)
float find_intersection(vec2 dp, vec2 ds) float find_intersection(vec2 dp, vec2 ds)
{ {
const float depth_step = 1.0 / 24.0;
float depth = 1.0; float depth = 1.0;
for (int i = 0 ; i < 24 ; i++) { float best_depth = 0.0;
float size = 0.0625;
for (int i = 0; i < 15; i++) {
depth -= size;
float h = texture2D(normalTexture, dp + ds * depth).a; float h = texture2D(normalTexture, dp + ds * depth).a;
if (h >= depth) if (depth <= h) {
best_depth = depth;
break; break;
depth -= depth_step;
} }
return depth; }
depth = best_depth;
for (int i = 0; i < 4; i++) {
size *= 0.5;
float h = texture2D(normalTexture,dp + ds * depth).a;
if (depth <= h) {
best_depth = depth;
depth += size;
} else {
depth -= size;
}
}
return best_depth;
} }
float find_intersectionRGB(vec2 dp, vec2 ds) float find_intersectionRGB(vec2 dp, vec2 ds)
@ -146,22 +192,26 @@ void main(void)
color = base.rgb; color = base.rgb;
#endif #endif
#if MATERIAL_TYPE == TILE_MATERIAL_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_LIQUID_OPAQUE vec4 col = vec4(color.rgb * gl_Color.rgb, 1.0);
#if MATERIAL_TYPE == TILE_MATERIAL_LIQUID_TRANSPARENT
float alpha = gl_Color.a; float alpha = gl_Color.a;
vec4 col = vec4(color.rgb, alpha);
col *= gl_Color;
if (fogDistance != 0.0) { if (fogDistance != 0.0) {
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0)); float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
alpha = mix(alpha, 0.0, d); alpha = mix(alpha, 0.0, d);
} }
gl_FragColor = vec4(col.rgb, alpha); col = vec4(col.rgb, alpha);
#else #else
vec4 col = vec4(color.rgb, base.a);
col *= gl_Color;
if (fogDistance != 0.0) { if (fogDistance != 0.0) {
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0)); float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
col = mix(col, skyBgColor, d); col = mix(col, skyBgColor, d);
} }
gl_FragColor = vec4(col.rgb, base.a); col = vec4(col.rgb, base.a);
#endif
#ifdef ENABLE_TONE_MAPPING
gl_FragColor = applyToneMapping(col);
#else
gl_FragColor = col;
#endif #endif
} }

View File

@ -15,7 +15,6 @@ varying vec3 lightVec;
varying vec3 tsEyeVec; varying vec3 tsEyeVec;
varying vec3 tsLightVec; varying vec3 tsLightVec;
varying float area_enable_parallax; varying float area_enable_parallax;
varying float disp;
const float e = 2.718281828459; const float e = 2.718281828459;
const float BS = 10.0; const float BS = 10.0;
@ -55,12 +54,16 @@ void main(void)
#endif #endif
float disp_x;
float disp_z;
#if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES && ENABLE_WAVING_LEAVES) || (MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS && ENABLE_WAVING_PLANTS) #if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES && ENABLE_WAVING_LEAVES) || (MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS && ENABLE_WAVING_PLANTS)
vec4 pos2 = mWorld * gl_Vertex; vec4 pos2 = mWorld * gl_Vertex;
float tOffset = (pos2.x + pos2.y) * 0.001 + pos2.z * 0.002; float tOffset = (pos2.x + pos2.y) * 0.001 + pos2.z * 0.002;
disp = (smoothTriangleWave(animationTimer * 31.0 + tOffset) + disp_x = (smoothTriangleWave(animationTimer * 23.0 + tOffset) +
smoothTriangleWave(animationTimer * 11.0 + tOffset)) * 0.4;
disp_z = (smoothTriangleWave(animationTimer * 31.0 + tOffset) +
smoothTriangleWave(animationTimer * 29.0 + tOffset) + smoothTriangleWave(animationTimer * 29.0 + tOffset) +
smoothTriangleWave(animationTimer * 13.0 + tOffset)) - 0.9; smoothTriangleWave(animationTimer * 13.0 + tOffset)) * 0.5;
#endif #endif
@ -72,14 +75,15 @@ void main(void)
gl_Position = mWorldViewProj * pos; gl_Position = mWorldViewProj * pos;
#elif MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES && ENABLE_WAVING_LEAVES #elif MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES && ENABLE_WAVING_LEAVES
vec4 pos = gl_Vertex; vec4 pos = gl_Vertex;
pos.x += disp * 0.1; pos.x += disp_x;
pos.y += disp * 0.1; pos.y += disp_z * 0.1;
pos.z += disp; pos.z += disp_z;
gl_Position = mWorldViewProj * pos; gl_Position = mWorldViewProj * pos;
#elif MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS && ENABLE_WAVING_PLANTS #elif MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS && ENABLE_WAVING_PLANTS
vec4 pos = gl_Vertex; vec4 pos = gl_Vertex;
if (gl_TexCoord[0].y < 0.05) { if (gl_TexCoord[0].y < 0.05) {
pos.z += disp; pos.x += disp_x;
pos.z += disp_z;
} }
gl_Position = mWorldViewProj * pos; gl_Position = mWorldViewProj * pos;
#else #else
@ -91,7 +95,7 @@ void main(void)
worldPosition = (mWorld * gl_Vertex).xyz; worldPosition = (mWorld * gl_Vertex).xyz;
// Don't generate heightmaps when too far from the eye // Don't generate heightmaps when too far from the eye
float dist = distance (vec3(0.0, 0.0 ,0.0), vPosition); float dist = distance (vec3(0.0, 0.0, 0.0), vPosition);
if (dist > 150.0) { if (dist > 150.0) {
area_enable_parallax = 0.0; area_enable_parallax = 0.0;
} }
@ -132,16 +136,16 @@ void main(void)
// 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); b += max(0.0, (1.0 - abs(b - 0.13) / 0.17) * 0.025);
// Artificial light is yellow-ish // Artificial light is yellow-ish
// See C++ implementation in mapblock_mesh.cpp finalColorBlend() // See C++ implementation in mapblock_mesh.cpp finalColorBlend()
rg += max(0.0, (1.0 - abs(rg - 0.85)/0.15) * 0.065); rg += max(0.0, (1.0 - abs(rg - 0.85) / 0.15) * 0.065);
color.r = rg; color.r = rg;
color.g = rg; color.g = rg;
color.b = b; color.b = b;
color.a = gl_Color.a; 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);
} }

View File

@ -0,0 +1,9 @@
uniform sampler2D baseTexture;
void main(void)
{
vec2 uv = gl_TexCoord[0].st;
vec4 color = texture2D(baseTexture, uv);
color.rgb *= gl_Color.rgb;
gl_FragColor = color;
}

View File

@ -0,0 +1,9 @@
uniform mat4 mWorldViewProj;
void main(void)
{
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = mWorldViewProj * gl_Vertex;
gl_FrontColor = gl_BackColor = gl_Color;
}

View File

@ -22,6 +22,38 @@ bool texSeamless = false;
const float e = 2.718281828459; const float e = 2.718281828459;
const float BS = 10.0; const float BS = 10.0;
#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() void get_texture_flags()
{ {
vec4 flags = texture2D(textureFlags, vec2(0.0, 0.0)); vec4 flags = texture2D(textureFlags, vec2(0.0, 0.0));
@ -116,22 +148,26 @@ vec4 base = texture2D(baseTexture, uv).rgba;
color = base.rgb; color = base.rgb;
#endif #endif
vec4 col = vec4(color.rgb * gl_Color.rgb, 1.0);
#if MATERIAL_TYPE == TILE_MATERIAL_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_LIQUID_OPAQUE #if MATERIAL_TYPE == TILE_MATERIAL_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_LIQUID_OPAQUE
float alpha = gl_Color.a; float alpha = gl_Color.a;
vec4 col = vec4(color.rgb, alpha); if (fogDistance != 0.0) {
col *= gl_Color;
if(fogDistance != 0.0){
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0)); float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
alpha = mix(alpha, 0.0, d); alpha = mix(alpha, 0.0, d);
} }
gl_FragColor = vec4(col.rgb, alpha); col = vec4(col.rgb, alpha);
#else #else
vec4 col = vec4(color.rgb, base.a); if (fogDistance != 0.0) {
col *= gl_Color;
if(fogDistance != 0.0){
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0)); float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
col = mix(col, skyBgColor, d); col = mix(col, skyBgColor, d);
} }
gl_FragColor = vec4(col.rgb, base.a); col = vec4(col.rgb, base.a);
#endif
#ifdef ENABLE_TONE_MAPPING
gl_FragColor = applyToneMapping(col);
#else
gl_FragColor = col;
#endif #endif
} }

View File

@ -1,25 +0,0 @@
option(ENABLE_LUAJIT "Enable LuaJIT support" TRUE)
mark_as_advanced(LUA_LIBRARY LUA_INCLUDE_DIR)
set(USE_LUAJIT FALSE)
if(ENABLE_LUAJIT)
find_library(LUA_LIBRARY luajit
NAMES luajit-5.1)
find_path(LUA_INCLUDE_DIR luajit.h
NAMES luajit.h
PATH_SUFFIXES luajit-2.0)
if(LUA_LIBRARY AND LUA_INCLUDE_DIR)
set(USE_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 "${PROJECT_SOURCE_DIR}/lua/src")
add_subdirectory(lua)
endif()

View File

@ -0,0 +1,50 @@
# Locate LuaJIT library
# This module defines
# LUAJIT_FOUND, if false, do not try to link to Lua
# LUA_INCLUDE_DIR, where to find lua.h
# LUA_VERSION_STRING, the version of Lua found (since CMake 2.8.8)
#
# This module is similar to FindLua51.cmake except that it finds LuaJit instead.
FIND_PATH(LUA_INCLUDE_DIR luajit.h
HINTS
$ENV{LUA_DIR}
PATH_SUFFIXES include/luajit-2.0 include/luajit-5_1-2.0 include
PATHS
~/Library/Frameworks
/Library/Frameworks
/sw # Fink
/opt/local # DarwinPorts
/opt/csw # Blastwave
/opt
)
FIND_LIBRARY(LUA_LIBRARY
NAMES luajit-5.1
HINTS
$ENV{LUA_DIR}
PATH_SUFFIXES lib64 lib
PATHS
~/Library/Frameworks
/Library/Frameworks
/sw
/opt/local
/opt/csw
/opt
)
IF(LUA_INCLUDE_DIR AND EXISTS "${LUA_INCLUDE_DIR}/luajit.h")
FILE(STRINGS "${LUA_INCLUDE_DIR}/luajit.h" lua_version_str REGEX "^#define[ \t]+LUA_RELEASE[ \t]+\"LuaJIT .+\"")
STRING(REGEX REPLACE "^#define[ \t]+LUA_RELEASE[ \t]+\"LuaJIT ([^\"]+)\".*" "\\1" LUA_VERSION_STRING "${lua_version_str}")
UNSET(lua_version_str)
ENDIF()
INCLUDE(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set LUAJIT_FOUND to TRUE if
# all listed variables are TRUE
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LuaJit
REQUIRED_VARS LUA_LIBRARY LUA_INCLUDE_DIR
VERSION_VAR LUA_VERSION_STRING)
MARK_AS_ADVANCED(LUA_INCLUDE_DIR LUA_LIBRARY LUA_MATH_LIBRARY)

View File

@ -115,7 +115,7 @@ if(CURSES_USE_NCURSESW)
get_filename_component(_cursesParentDir "${_cursesLibDir}" PATH) get_filename_component(_cursesParentDir "${_cursesLibDir}" PATH)
find_path(CURSES_INCLUDE_PATH find_path(CURSES_INCLUDE_PATH
NAMES ncursesw/ncurses.h ncursesw/curses.h NAMES ncursesw/ncurses.h ncursesw/curses.h ncurses.h curses.h
HINTS "${_cursesParentDir}/include" HINTS "${_cursesParentDir}/include"
) )
@ -147,6 +147,21 @@ if(CURSES_USE_NCURSESW)
set(CURSES_HAVE_NCURSESW_CURSES_H "CURSES_HAVE_NCURSESW_CURSES_H-NOTFOUND") set(CURSES_HAVE_NCURSESW_CURSES_H "CURSES_HAVE_NCURSESW_CURSES_H-NOTFOUND")
endif() endif()
endif() endif()
if(NOT DEFINED CURSES_HAVE_NCURSES_H)
if(EXISTS "${CURSES_INCLUDE_PATH}/ncurses.h")
set(CURSES_HAVE_NCURSES_H "${CURSES_INCLUDE_PATH}/ncurses.h")
else()
set(CURSES_HAVE_NCURSES_H "CURSES_HAVE_NCURSES_H-NOTFOUND")
endif()
endif()
if(NOT DEFINED CURSES_HAVE_CURSES_H)
if(EXISTS "${CURSES_INCLUDE_PATH}/curses.h")
set(CURSES_HAVE_CURSES_H "${CURSES_INCLUDE_PATH}/curses.h")
else()
set(CURSES_HAVE_CURSES_H "CURSES_HAVE_CURSES_H-NOTFOUND")
endif()
endif()
find_library(CURSES_FORM_LIBRARY form HINTS "${_cursesLibDir}" find_library(CURSES_FORM_LIBRARY form HINTS "${_cursesLibDir}"
DOC "Path to libform.so or .lib or .a") DOC "Path to libform.so or .lib or .a")

View File

@ -1,34 +1,53 @@
DOXYFILE_ENCODING = UTF-8 # Project properties
PROJECT_NAME = @PROJECT_NAME_CAPITALIZED@
PROJECT_NAME = "Minetest"
PROJECT_NUMBER = @VERSION_STRING@ PROJECT_NUMBER = @VERSION_STRING@
PROJECT_LOGO = @CMAKE_CURRENT_SOURCE_DIR@/misc/minetest.svg
STRIP_FROM_PATH = @CMAKE_CURRENT_SOURCE_DIR@/src # Parsing
JAVADOC_AUTOBRIEF = YES JAVADOC_AUTOBRIEF = YES
EXTRACT_ALL = YES EXTRACT_ALL = YES
EXTRACT_PRIVATE = YES EXTRACT_PRIVATE = YES
EXTRACT_STATIC = YES EXTRACT_STATIC = YES
SORT_MEMBERS_CTORS_1ST = YES SORT_MEMBERS_CTORS_1ST = YES
WARN_IF_UNDOCUMENTED = NO WARN_IF_UNDOCUMENTED = NO
BUILTIN_STL_SUPPORT = YES
PREDEFINED = "USE_SPATIAL=1" \
"USE_LEVELDB=1" \
"USE_REDIS=1" \
"USE_SOUND=1" \
"USE_CURL=1" \
"USE_FREETYPE=1" \
"USE_GETTEXT=1"
INPUT = @CMAKE_CURRENT_SOURCE_DIR@/src/ \ # Input
RECURSIVE = NO
STRIP_FROM_PATH = @CMAKE_CURRENT_SOURCE_DIR@/src
INPUT = @CMAKE_CURRENT_SOURCE_DIR@/doc/main_page.dox \
@CMAKE_CURRENT_SOURCE_DIR@/src/ \
@CMAKE_CURRENT_SOURCE_DIR@/src/client \ @CMAKE_CURRENT_SOURCE_DIR@/src/client \
@CMAKE_CURRENT_SOURCE_DIR@/src/network \ @CMAKE_CURRENT_SOURCE_DIR@/src/network \
@CMAKE_CURRENT_SOURCE_DIR@/src/util \ @CMAKE_CURRENT_SOURCE_DIR@/src/util \
@CMAKE_CURRENT_SOURCE_DIR@/src/script \ @CMAKE_CURRENT_SOURCE_DIR@/src/script \
@CMAKE_CURRENT_SOURCE_DIR@/src/script/common \ @CMAKE_CURRENT_SOURCE_DIR@/src/script/common \
@CMAKE_CURRENT_SOURCE_DIR@/src/script/cpp_api \ @CMAKE_CURRENT_SOURCE_DIR@/src/script/cpp_api \
@CMAKE_CURRENT_SOURCE_DIR@/src/script/lua_api @CMAKE_CURRENT_SOURCE_DIR@/src/script/lua_api \
RECURSIVE = NO @CMAKE_CURRENT_SOURCE_DIR@/src/threading
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
GENERATE_LATEX = NO
PAPER_TYPE = a4wide
# Dot graphs
HAVE_DOT = @DOXYGEN_DOT_FOUND@ HAVE_DOT = @DOXYGEN_DOT_FOUND@
CALL_GRAPH = YES CALL_GRAPH = YES
CALLER_GRAPH = YES CALLER_GRAPH = YES
MAX_DOT_GRAPH_DEPTH = 3 MAX_DOT_GRAPH_DEPTH = 3
DOT_MULTI_TARGETS = YES DOT_MULTI_TARGETS = YES
DOT_IMAGE_FORMAT = svg
# Output
GENERATE_LATEX = NO
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
SEARCHENGINE = YES
DISABLE_INDEX = YES
GENERATE_TREEVIEW = YES
HTML_DYNAMIC_SECTIONS = YES
HTML_TIMESTAMP = YES

View File

@ -1,4 +1,4 @@
Minetest Lua Modding API Reference 0.4.13 Minetest Lua Modding API Reference 0.4.14
========================================= =========================================
* More information at <http://www.minetest.net/> * More information at <http://www.minetest.net/>
* Developer Wiki: <http://dev.minetest.net/> * Developer Wiki: <http://dev.minetest.net/>
@ -243,6 +243,7 @@ Example:
default_dirt.png^default_grass_side.png default_dirt.png^default_grass_side.png
`default_grass_side.png` is overlayed over `default_dirt.png`. `default_grass_side.png` is overlayed over `default_dirt.png`.
The texture with the lower resolution will be automatically upscaled to the higher resolution texture.
### Texture grouping ### Texture grouping
Textures can be grouped together by enclosing them in `(` and `)`. Textures can be grouped together by enclosing them in `(` and `)`.
@ -264,20 +265,27 @@ Example:
default_cobble.png^[crack:10:1 default_cobble.png^[crack:10:1
#### `[combine:<w>x<h>:<x1>,<y1>=<file1>:<x2>,<y2>=<file2>` #### `[combine:<w>x<h>:<x1>,<y1>=<file1>:<x2>,<y2>=<file2>:...`
* `<w>` = width * `<w>` = width
* `<h>` = height * `<h>` = height
* `<x1>`/`<x2>` = x positions * `<x>` = x position
* `<y1>`/`<y1>` = y positions * `<y>` = y position
* `<file1>`/`<file2>` = textures to combine * `<file>` = texture to combine
Create a texture of size `<w>` times `<h>` and blit `<file1>` to (`<x1>`,`<y1>`) Creates a texture of size `<w>` times `<h>` and blits the listed files to their
and blit `<file2>` to (`<x2>`,`<y2>`). specified coordinates.
Example: Example:
[combine:16x32:0,0=default_cobble.png:0,16=default_wood.png [combine:16x32:0,0=default_cobble.png:0,16=default_wood.png
#### `[resize:<w>x<h>`
Resizes the texture to the given dimensions.
Example:
default_sandstone.png^[resize:16x16
#### `[brighten` #### `[brighten`
Brightens the texture. Brightens the texture.
@ -357,8 +365,13 @@ The mask is applied using binary AND.
#### `[colorize:<color>:<ratio>` #### `[colorize:<color>:<ratio>`
Colorize the textures with the given color. Colorize the textures with the given color.
`<color>` is specified as a `ColorString`. `<color>` is specified as a `ColorString`.
`<ratio>` is an int ranging from 0 to 255, and specifies how much of the `<ratio>` is an int ranging from 0 to 255 or the word "`alpha`". If
color to apply. If ommitted, the alpha will be used. it is an int, then it specifies how far to interpolate between the
colors where 0 is only the texture color and 255 is only `<color>`. If
omitted, the alpha of `<color>` will be used as the ratio. If it is
the word "`alpha`", then each texture pixel will contain the RGB of
`<color>` and the alpha of `<color>` multiplied by the alpha of the
texture pixel.
Sounds Sounds
------ ------
@ -541,9 +554,9 @@ node definition:
^ The rotation of the node is stored in param2. Furnaces and chests are ^ The rotation of the node is stored in param2. Furnaces and chests are
rotated this way. Can be made by using minetest.dir_to_facedir(). rotated this way. Can be made by using minetest.dir_to_facedir().
Values range 0 - 23 Values range 0 - 23
facedir modulo 4 = axisdir facedir / 4 = axis direction:
0 = y+ 1 = z+ 2 = z- 3 = x+ 4 = x- 5 = y- 0 = y+ 1 = z+ 2 = z- 3 = x+ 4 = x- 5 = y-
facedir's two less significant bits are rotation around the axis facedir modulo 4 = rotation around that axis
paramtype2 == "leveled" paramtype2 == "leveled"
paramtype2 == "degrotate" paramtype2 == "degrotate"
^ The rotation of this node is stored in param2. Plants are rotated this way. ^ The rotation of this node is stored in param2. Plants are rotated this way.
@ -617,6 +630,18 @@ A nodebox is defined as any of:
wall_bottom = box, wall_bottom = box,
wall_side = box wall_side = box
} }
{
-- A node that has optional boxes depending on neighbouring nodes'
-- presence and type. See also `connects_to`.
type = "connected",
fixed = box OR {box1, box2, ...}
connect_top = box OR {box1, box2, ...}
connect_bottom = box OR {box1, box2, ...}
connect_front = box OR {box1, box2, ...}
connect_left = box OR {box1, box2, ...}
connect_back = box OR {box1, box2, ...}
connect_right = box OR {box1, box2, ...}
}
A `box` is defined as: A `box` is defined as:
@ -763,7 +788,7 @@ Creates veins of ore varying in density by according to the intersection of two
instances of 3d perlin noise with diffferent seeds, both described by instances of 3d perlin noise with diffferent seeds, both described by
`noise_params`. `random_factor` varies the influence random chance has on `noise_params`. `random_factor` varies the influence random chance has on
placement of an ore inside the vein, which is `1` by default. Note that placement of an ore inside the vein, which is `1` by default. Note that
modifying this parameter may require adjusting `noise_threshhold`. modifying this parameter may require adjusting `noise_threshold`.
The parameters `clust_scarcity`, `clust_num_ores`, and `clust_size` are ignored The parameters `clust_scarcity`, `clust_num_ores`, and `clust_size` are ignored
by this ore type. This ore type is difficult to control since it is sensitive by this ore type. This ore type is difficult to control since it is sensitive
to small changes. The following is a decent set of parameters to work from: to small changes. The following is a decent set of parameters to work from:
@ -777,7 +802,7 @@ to small changes. The following is a decent set of parameters to work from:
persist = 0.5, persist = 0.5,
flags = "eased", flags = "eased",
}, },
noise_threshhold = 1.6 noise_threshold = 1.6
WARNING: Use this ore type *very* sparingly since it is ~200x more WARNING: Use this ore type *very* sparingly since it is ~200x more
computationally expensive than any other ore. computationally expensive than any other ore.
@ -928,6 +953,7 @@ Displays a horizontal bar made up of half-images.
* `number`: Number of items in the inventory to be displayed. * `number`: Number of items in the inventory to be displayed.
* `item`: Position of item that is selected. * `item`: Position of item that is selected.
* `direction` * `direction`
* `offset`: offset in pixels from position.
### `waypoint` ### `waypoint`
Displays distance to selected world position. Displays distance to selected world position.
@ -1305,10 +1331,12 @@ mentioned in "Nodes". However, it is possible to insert extra data into a
node. It is called "node metadata"; See "`NodeMetaRef`". node. It is called "node metadata"; See "`NodeMetaRef`".
Metadata contains two things: Metadata contains two things:
* A key-value store * A key-value store
* An inventory * An inventory
Some of the values in the key-value store are handled specially: Some of the values in the key-value store are handled specially:
* `formspec`: Defines a right-click inventory menu. See "Formspec". * `formspec`: Defines a right-click inventory menu. See "Formspec".
* `infotext`: Text shown on the screen when the node is pointed at * `infotext`: Text shown on the screen when the node is pointed at
@ -1614,7 +1642,7 @@ examples.
* types: `text`, `image`, `color`, `indent`, `tree` * types: `text`, `image`, `color`, `indent`, `tree`
* `text`: show cell contents as text * `text`: show cell contents as text
* `image`: cell contents are an image index, use column options to define images * `image`: cell contents are an image index, use column options to define images
* `colo`: cell contents are a ColorString and define color of following cell * `color`: cell contents are a ColorString and define color of following cell
* `indent`: cell contents are a number and define indentation of following cell * `indent`: cell contents are a number and define indentation of following cell
* `tree`: same as indent, but user can open and close subtrees (treeview-like) * `tree`: same as indent, but user can open and close subtrees (treeview-like)
* column options: * column options:
@ -1674,16 +1702,15 @@ or string form, a ColorString (defined above):
`colorspec = "green"` `colorspec = "green"`
Spatial Vectors Spatial Vectors
-------------- ---------------
* `vector.new(a[, b, c])`: returns a vector:
* `vector.new([x[, y, z]])`: returns a vector. * A copy of `a` if `a` is a vector.
* `x` is a table or the `x` position. * `{x = a, y = b, z = c}`, if all `a, b, c` are defined
* `vector.direction(p1, p2)`: returns a vector * `vector.direction(p1, p2)`: returns a vector
* `vector.distance(p1, p2)`: returns a number * `vector.distance(p1, p2)`: returns a number
* `vector.length(v)`: returns a number * `vector.length(v)`: returns a number
* `vector.normalize(v)`: returns a vector * `vector.normalize(v)`: returns a vector
* `vector.round(v)`: returns a vector * `vector.round(v)`: returns a vector, each dimension rounded to floor
* `vector.apply(v, func)`: returns a vector * `vector.apply(v, func)`: returns a vector
* `vector.equals(v1, v2)`: returns a boolean * `vector.equals(v1, v2)`: returns a boolean
@ -1695,7 +1722,7 @@ For the following functions `x` can be either a vector or a number:
* `vector.divide(v, x)`: returns a scaled vector or Schur quotient * `vector.divide(v, x)`: returns a scaled vector or Schur quotient
Helper functions Helper functions
----------------- ----------------
* `dump2(obj, name="_", dumped={})` * `dump2(obj, name="_", dumped={})`
* Return object serialized as a string, handles reference loops * Return object serialized as a string, handles reference loops
* `dump(obj, dumped={})` * `dump(obj, dumped={})`
@ -1713,8 +1740,9 @@ Helper functions
* e.g. `string:split("a,b", ",") == {"a","b"}` * e.g. `string:split("a,b", ",") == {"a","b"}`
* `string:trim()` * `string:trim()`
* e.g. `string.trim("\n \t\tfoo bar\t ") == "foo bar"` * e.g. `string.trim("\n \t\tfoo bar\t ") == "foo bar"`
* `minetest.pos_to_string({x=X,y=Y,z=Z})`: returns `"(X,Y,Z)"` * `minetest.pos_to_string({x=X,y=Y,z=Z}, decimal_places))`: returns `"(X,Y,Z)"`
* Convert position to a printable string * Convert position to a printable string
Optional: 'decimal_places' will round the x, y and z of the pos to the given decimal place.
* `minetest.string_to_pos(string)`: returns a position * `minetest.string_to_pos(string)`: returns a position
* Same but in reverse. Returns `nil` if the string can't be parsed to a position. * Same but in reverse. Returns `nil` if the string can't be parsed to a position.
* `minetest.string_to_area("(X1, Y1, Z1) (X2, Y2, Z2)")`: returns two positions * `minetest.string_to_area("(X1, Y1, Z1) (X2, Y2, Z2)")`: returns two positions
@ -1724,7 +1752,7 @@ Helper functions
* `minetest.is_yes(arg)` * `minetest.is_yes(arg)`
* returns whether `arg` can be interpreted as yes * returns whether `arg` can be interpreted as yes
* `minetest.get_us_time()` * `minetest.get_us_time()`
* returns time with microsecond precision * returns time with microsecond precision. May not return wall time.
* `table.copy(table)`: returns a table * `table.copy(table)`: returns a table
* returns a deep copy of `table` * returns a deep copy of `table`
@ -1790,6 +1818,7 @@ Call these functions only at load time!
* `minetest.register_entity(name, prototype table)` * `minetest.register_entity(name, prototype table)`
* `minetest.register_abm(abm definition)` * `minetest.register_abm(abm definition)`
* `minetest.register_lbm(lbm definition)`
* `minetest.register_node(name, node definition)` * `minetest.register_node(name, node definition)`
* `minetest.register_tool(name, item definition)` * `minetest.register_tool(name, item definition)`
* `minetest.register_craftitem(name, item definition)` * `minetest.register_craftitem(name, item definition)`
@ -1850,6 +1879,7 @@ Call these functions only at load time!
* `modifier`: when true, the function should return the actual hp_change. * `modifier`: when true, the function should return the actual hp_change.
Note: modifiers only get a temporary hp_change that can be modified by later modifiers. Note: modifiers only get a temporary hp_change that can be modified by later modifiers.
modifiers can return true as a second argument to stop the execution of further functions. modifiers can return true as a second argument to stop the execution of further functions.
Non-modifiers receive the final hp change calculated by the modifiers.
* `minetest.register_on_respawnplayer(func(ObjectRef))` * `minetest.register_on_respawnplayer(func(ObjectRef))`
* Called when player is to be respawned * Called when player is to be respawned
* Called _before_ repositioning of player occurs * Called _before_ repositioning of player occurs
@ -1901,6 +1931,7 @@ Call these functions only at load time!
* `minetest.register_privilege(name, definition)` * `minetest.register_privilege(name, definition)`
* `definition`: `"description text"` * `definition`: `"description text"`
* `definition`: `{ description = "description text", give_to_singleplayer = boolean, -- default: true }` * `definition`: `{ description = "description text", give_to_singleplayer = boolean, -- default: true }`
* To allow players with basic_privs to grant, see basic_privs minetest.conf setting.
* `minetest.register_authentication_handler(handler)` * `minetest.register_authentication_handler(handler)`
* See `minetest.builtin_auth_handler` in `builtin.lua` for reference * See `minetest.builtin_auth_handler` in `builtin.lua` for reference
@ -1921,7 +1952,11 @@ Call these functions only at load time!
* Should be called by the authentication handler if privileges changes. * Should be called by the authentication handler if privileges changes.
* To report everybody, set `name=nil`. * To report everybody, set `name=nil`.
* `minetest.get_password_hash(name, raw_password)` * `minetest.get_password_hash(name, raw_password)`
* Convert a name-password pair to a password hash that Minetest can use * Convert a name-password pair to a password hash that Minetest can use.
* The returned value alone is not a good basis for password checks based
* on comparing the password hash in the database with the password hash
* from the function, with an externally provided password, as the hash
* in the db might use the new SRP verifier format.
* `minetest.string_to_privs(str)`: returns `{priv1=true,...}` * `minetest.string_to_privs(str)`: returns `{priv1=true,...}`
* `minetest.privs_to_string(privs)`: returns `"priv1,priv2,..."` * `minetest.privs_to_string(privs)`: returns `"priv1,priv2,..."`
* Convert between two privilege representations * Convert between two privilege representations
@ -1952,9 +1987,11 @@ and `minetest.auth_reload` call the authetification handler.
* `minetest.remove_node(pos)` * `minetest.remove_node(pos)`
* Equivalent to `set_node(pos, "air")` * Equivalent to `set_node(pos, "air")`
* `minetest.get_node(pos)` * `minetest.get_node(pos)`
* Returns `{name="ignore", ...}` for unloaded area * Returns the node at the given position as table in the format
`{name="node_name", param1=0, param2=0}`, returns `{name="ignore", param1=0, param2=0}`
for unloaded areas.
* `minetest.get_node_or_nil(pos)` * `minetest.get_node_or_nil(pos)`
* Returns `nil` for unloaded area * Same as `get_node` but returns `nil` for unloaded areas.
* `minetest.get_node_light(pos, timeofday)` * `minetest.get_node_light(pos, timeofday)`
* Gets the light value at the given position. Note that the light value * Gets the light value at the given position. Note that the light value
"inside" the node at the given position is returned, so you usually want "inside" the node at the given position is returned, so you usually want
@ -1988,6 +2025,8 @@ and `minetest.auth_reload` call the authetification handler.
* `val` is between `0` and `1`; `0` for midnight, `0.5` for midday * `val` is between `0` and `1`; `0` for midnight, `0.5` for midday
* `minetest.get_timeofday()` * `minetest.get_timeofday()`
* `minetest.get_gametime()`: returns the time, in seconds, since the world was created * `minetest.get_gametime()`: returns the time, in seconds, since the world was created
* `minetest.get_day_count()`: returns number days elapsed since world was created,
* accounting for time changes.
* `minetest.find_node_near(pos, radius, nodenames)`: returns pos or `nil` * `minetest.find_node_near(pos, radius, nodenames)`: returns pos or `nil`
* `radius`: using a maximum metric * `radius`: using a maximum metric
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"` * `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
@ -2037,8 +2076,12 @@ and `minetest.auth_reload` call the authetification handler.
* `minetest.generate_decorations(vm, pos1, pos2)` * `minetest.generate_decorations(vm, pos1, pos2)`
* Generate all registered decorations within the VoxelManip `vm` and in the area from `pos1` to `pos2`. * Generate all registered decorations within the VoxelManip `vm` and in the area from `pos1` to `pos2`.
* `pos1` and `pos2` are optional and default to mapchunk minp and maxp. * `pos1` and `pos2` are optional and default to mapchunk minp and maxp.
* `minetest.clear_objects()` * `minetest.clear_objects([options])`
* clear all objects in the environments * Clear all objects in the environment
* Takes an optional table as an argument with the field `mode`.
* mode = `"full"`: Load and go through every mapblock, clearing objects (default).
* mode = `"quick"`: Clear objects immediately in loaded mapblocks;
clear objects in unloaded mapblocks only when the mapblocks are next activated.
* `minetest.emerge_area(pos1, pos2, [callback], [param])` * `minetest.emerge_area(pos1, pos2, [callback], [param])`
* Queue all blocks in the area from `pos1` to `pos2`, inclusive, to be asynchronously * Queue all blocks in the area from `pos1` to `pos2`, inclusive, to be asynchronously
* fetched from memory, loaded from disk, or if inexistent, generates them. * fetched from memory, loaded from disk, or if inexistent, generates them.
@ -2071,7 +2114,9 @@ and `minetest.auth_reload` call the authetification handler.
* `max_drop`: maximum height difference to consider droppable * `max_drop`: maximum height difference to consider droppable
* `algorithm`: One of `"A*_noprefetch"` (default), `"A*"`, `"Dijkstra"` * `algorithm`: One of `"A*_noprefetch"` (default), `"A*"`, `"Dijkstra"`
* `minetest.spawn_tree (pos, {treedef})` * `minetest.spawn_tree (pos, {treedef})`
* spawns L-System tree at given `pos` with definition in `treedef` table * spawns L-system tree at given `pos` with definition in `treedef` table
* Warning: L-system generation currently creates lighting bugs in the form of mapblock-sized shadows.
Often these bugs appear as subtle shadows in water.
* `minetest.transforming_liquid_add(pos)` * `minetest.transforming_liquid_add(pos)`
* add node to liquid update queue * add node to liquid update queue
* `minetest.get_node_max_level(pos)` * `minetest.get_node_max_level(pos)`
@ -2140,6 +2185,8 @@ and `minetest.auth_reload` call the authetification handler.
* Convert a facedir back into a vector aimed directly out the "back" of a node * Convert a facedir back into a vector aimed directly out the "back" of a node
* `minetest.dir_to_wallmounted(dir)` * `minetest.dir_to_wallmounted(dir)`
* Convert a vector to a wallmounted value, used for `paramtype2="wallmounted"` * Convert a vector to a wallmounted value, used for `paramtype2="wallmounted"`
* `minetest.wallmounted_to_dir(wallmounted)`
* Convert a wallmounted value back into a vector aimed directly out the "back" of a node
* `minetest.get_node_drops(nodename, toolname)` * `minetest.get_node_drops(nodename, toolname)`
* Returns list of item names. * Returns list of item names.
* **Note**: This will be removed or modified in a future version. * **Note**: This will be removed or modified in a future version.
@ -2233,7 +2280,7 @@ These functions return the leftover itemstack.
### Timing ### Timing
* `minetest.after(time, func, ...)` * `minetest.after(time, func, ...)`
* Call the function `func` after `time` seconds * Call the function `func` after `time` seconds, may be fractional
* Optional: Variable number of arguments that are passed to `func` * Optional: Variable number of arguments that are passed to `func`
### Server ### Server
@ -2315,6 +2362,26 @@ These functions return the leftover itemstack.
* If `lua_num_indent_spaces` is a nonzero number and `format` is "lua", the Lua code generated * If `lua_num_indent_spaces` is a nonzero number and `format` is "lua", the Lua code generated
* will use that number of spaces as indentation instead of a tab character. * will use that number of spaces as indentation instead of a tab character.
### HTTP Requests:
* `minetest.request_http_api()`:
* returns `HTTPApiTable` containing http functions if the calling mod has been granted
access by being listed in the `secure.http_mods` or `secure.trusted_mods` setting,
otherwise returns `nil`.
* The returned table contains the functions `fetch`, `fetch_async` and `fetch_async_get`
described below.
* Only works at init time and must be called from the mod's main scope (not from a function).
* Function only exists if minetest server was built with cURL support.
* **DO NOT ALLOW ANY OTHER MODS TO ACCESS THE RETURNED TABLE, STORE IT IN
A LOCAL VARIABLE!**
* `HTTPApiTable.fetch(HTTPRequest req, callback)`
* Performs given request asynchronously and calls callback upon completion
* callback: `function(HTTPRequestResult res)`
* Use this HTTP function if you are unsure, the others are for advanced use.
* `HTTPApiTable.fetch_async(HTTPRequest req)`: returns handle
* Performs given request asynchronously and returns handle for `minetest.http_fetch_async_get`
* `HTTPApiTable.fetch_async_get(handle)`: returns HTTPRequestResult
* Return response data for given asynchronous HTTP request
### Misc. ### Misc.
* `minetest.get_connected_players()`: returns list of `ObjectRefs` * `minetest.get_connected_players()`: returns list of `ObjectRefs`
* `minetest.hash_node_position({x=,y=,z=})`: returns an 48-bit integer * `minetest.hash_node_position({x=,y=,z=})`: returns an 48-bit integer
@ -2422,7 +2489,7 @@ These functions return the leftover itemstack.
* `minetest.request_insecure_environment()`: returns an environment containing * `minetest.request_insecure_environment()`: returns an environment containing
insecure functions if the calling mod has been listed as trusted in the insecure functions if the calling mod has been listed as trusted in the
`secure.trusted_mods` setting or security is disabled, otherwise returns `nil`. `secure.trusted_mods` setting or security is disabled, otherwise returns `nil`.
* Only works at init time. * Only works at init time and must be called from the mod's main scope (not from a function).
* **DO NOT ALLOW ANY OTHER MODS TO ACCESS THE RETURNED ENVIRONMENT, STORE IT IN * **DO NOT ALLOW ANY OTHER MODS TO ACCESS THE RETURNED ENVIRONMENT, STORE IT IN
A LOCAL VARIABLE!** A LOCAL VARIABLE!**
@ -2453,6 +2520,8 @@ These functions return the leftover itemstack.
* Map of Lua entities, indexed by active object id * Map of Lua entities, indexed by active object id
* `minetest.registered_ores` * `minetest.registered_ores`
* List of registered ore definitions. * List of registered ore definitions.
* `minetest.registered_biomes`
* List of registered biome definitions.
* `minetest.registered_decorations` * `minetest.registered_decorations`
* List of registered decoration definitions. * List of registered decoration definitions.
@ -2538,6 +2607,19 @@ This is basically a reference to a C++ `ServerActiveObject`
* `set_properties(object property table)` * `set_properties(object property table)`
* `get_properties()`: returns object property table * `get_properties()`: returns object property table
* `is_player()`: returns true for players, false otherwise * `is_player()`: returns true for players, false otherwise
* `get_nametag_attributes()`
* returns a table with the attributes of the nametag of an object
* {
color = {a=0..255, r=0..255, g=0..255, b=0..255},
text = "",
}
* `set_nametag_attributes(attributes)`
* sets the attributes of the nametag of an object
* `attributes`:
{
color = ColorSpec,
text = "My Nametag",
}
##### LuaEntitySAO-only (no-op for other objects) ##### LuaEntitySAO-only (no-op for other objects)
* `setvelocity({x=num, y=num, z=num})` * `setvelocity({x=num, y=num, z=num})`
@ -2617,8 +2699,6 @@ This is basically a reference to a C++ `ServerActiveObject`
* `"regular"`: Uses 0 textures, `bgcolor` ignored * `"regular"`: Uses 0 textures, `bgcolor` ignored
* `"skybox"`: Uses 6 textures, `bgcolor` used * `"skybox"`: Uses 6 textures, `bgcolor` used
* `"plain"`: Uses 0 textures, `bgcolor` used * `"plain"`: Uses 0 textures, `bgcolor` used
* **Note**: currently does not work directly in `on_joinplayer`; use
`minetest.after(0)` in there.
* `get_sky()`: returns bgcolor, type and a table with the textures * `get_sky()`: returns bgcolor, type and a table with the textures
* `override_day_night_ratio(ratio or nil)` * `override_day_night_ratio(ratio or nil)`
* `0`...`1`: Overrides day-night ratio, controlling sunlight to a specific amount * `0`...`1`: Overrides day-night ratio, controlling sunlight to a specific amount
@ -2638,17 +2718,6 @@ This is basically a reference to a C++ `ServerActiveObject`
* in first person view * in first person view
* in third person view (max. values `{x=-10/10,y=-10,15,z=-5/5}`) * in third person view (max. values `{x=-10/10,y=-10,15,z=-5/5}`)
* `get_eye_offset()`: returns offset_first and offset_third * `get_eye_offset()`: returns offset_first and offset_third
* `get_nametag_attributes()`
* returns a table with the attributes of the nametag of the player
* {
color = {a=0..255, r=0..255, g=0..255, b=0..255},
}
* `set_nametag_attributes(attributes)`
* sets the attributes of the nametag of the player
* `attributes`:
{
color = ColorSpec,
}
### `InvRef` ### `InvRef`
An `InvRef` is a reference to an inventory. An `InvRef` is a reference to an inventory.
@ -2689,8 +2758,7 @@ If you chose the parameter-less constructor, a fast implementation will be autom
* `get_area(id, include_borders, include_data)`: returns the area with the id `id`. (optional) Boolean values `include_borders` and `include_data` control what's copied. * `get_area(id, include_borders, include_data)`: returns the area with the id `id`. (optional) Boolean values `include_borders` and `include_data` control what's copied.
* `get_areas_for_pos(pos, include_borders, include_data)`: returns all areas that contain the position `pos`. (optional) Boolean values `include_borders` and `include_data` control what's copied. * `get_areas_for_pos(pos, include_borders, include_data)`: returns all areas that contain the position `pos`. (optional) Boolean values `include_borders` and `include_data` control what's copied.
* `get_areas_in_area(edge1, edge2, accept_overlap, include_borders, include_data)`: returns all areas that contain all nodes inside the area specified by `edge1` and `edge2` (inclusive). If `accept_overlap` is true, also areas are returned that have nodes in common with the specified area. (optional) Boolean values `include_borders` and `include_data` control what's copied. * `get_areas_in_area(edge1, edge2, accept_overlap, include_borders, include_data)`: returns all areas that contain all nodes inside the area specified by `edge1` and `edge2` (inclusive). If `accept_overlap` is true, also areas are returned that have nodes in common with the specified area. (optional) Boolean values `include_borders` and `include_data` control what's copied.
* `insert_area(edge1, edge2, data)`: inserts an area into the store. Returns the id if successful, nil otherwise. The (inclusive) positions `edge1` and `edge2` describe the area, `data` * `insert_area(edge1, edge2, data, [id])`: inserts an area into the store. Returns the new area's ID, or nil if the insertion failed. The (inclusive) positions `edge1` and `edge2` describe the area. `data` is a string stored with the area. If passed, `id` will be used as the internal area ID, it must be a unique number between 0 and 2^32-2. If you use the `id` parameter you must always use it, or insertions are likely to fail due to conflicts.
is a string stored with the area.
* `reserve(count)`: reserves resources for at most `count` many contained areas. Only needed for efficiency, and only some implementations profit. * `reserve(count)`: reserves resources for at most `count` many contained areas. Only needed for efficiency, and only some implementations profit.
* `remove_area(id)`: removes the area with the given id from the store, returns success. * `remove_area(id)`: removes the area with the given id from the store, returns success.
* `set_cache_params(params)`: sets params for the included prefiltering cache. Calling invalidates the cache, so that its elements have to be newly generated. * `set_cache_params(params)`: sets params for the included prefiltering cache. Calling invalidates the cache, so that its elements have to be newly generated.
@ -2700,6 +2768,10 @@ is a string stored with the area.
block_radius = number, -- the radius (in nodes) of the areas the cache generates prefiltered lists for, minimum 16, default 64 block_radius = number, -- the radius (in nodes) of the areas the cache generates prefiltered lists for, minimum 16, default 64
limit = number, -- the cache's size, minimum 20, default 1000 limit = number, -- the cache's size, minimum 20, default 1000
} }
* `to_string()`: Experimental. Returns area store serialized as a (binary) string.
* `to_file(filename)`: Experimental. Like `to_string()`, but writes the data to a file.
* `from_string(str)`: Experimental. Deserializes string and loads it into the AreaStore. Returns success and, optionally, an error message.
* `from_file(filename)`: Experimental. Like `from_string()`, but reads the data from a file.
### `ItemStack` ### `ItemStack`
An `ItemStack` is a stack of items. An `ItemStack` is a stack of items.
@ -2765,6 +2837,15 @@ It can be created via `PcgRandom(seed)` or `PcgRandom(seed, sequence)`.
* This is only a rough approximation of a normal distribution with mean=(max-min)/2 and variance=1 * This is only a rough approximation of a normal distribution with mean=(max-min)/2 and variance=1
* Increasing num_trials improves accuracy of the approximation * Increasing num_trials improves accuracy of the approximation
### `SecureRandom`
Interface for the operating system's crypto-secure PRNG.
It can be created via `SecureRandom()`. The constructor returns nil if a secure random device cannot be
be found on the system.
#### Methods
* `next_bytes([count])`: return next `count` (default 1, capped at 2048) many random bytes, as a string.
### `PerlinNoise` ### `PerlinNoise`
A perlin noise generator. A perlin noise generator.
It can be created via `PerlinNoise(seed, octaves, persistence, scale)` It can be created via `PerlinNoise(seed, octaves, persistence, scale)`
@ -2925,6 +3006,7 @@ core.CONTENT_IGNORE (ID for "ignore" nodes)
Inside of `on_generated()` callbacks, it is possible to retrieve the same VoxelManip object used by the Inside of `on_generated()` callbacks, it is possible to retrieve the same VoxelManip object used by the
core's Map Generator (commonly abbreviated Mapgen). Most of the rules previously described still apply core's Map Generator (commonly abbreviated Mapgen). Most of the rules previously described still apply
but with a few differences: but with a few differences:
* The Mapgen VoxelManip object is retrieved using: `minetest.get_mapgen_object("voxelmanip")` * The Mapgen VoxelManip object is retrieved using: `minetest.get_mapgen_object("voxelmanip")`
* This VoxelManip object already has the region of map just generated loaded into it; it's not necessary * This VoxelManip object already has the region of map just generated loaded into it; it's not necessary
to call `VoxelManip:read_from_map()` before using a Mapgen VoxelManip. to call `VoxelManip:read_from_map()` before using a Mapgen VoxelManip.
@ -2983,7 +3065,7 @@ will place the schematic inside of the VoxelManip.
* `update_map()`: Update map after writing chunk back to map. * `update_map()`: Update map after writing chunk back to map.
* To be used only by `VoxelManip` objects created by the mod itself; * To be used only by `VoxelManip` objects created by the mod itself;
not a `VoxelManip` that was retrieved from `minetest.get_mapgen_object` not a `VoxelManip` that was retrieved from `minetest.get_mapgen_object`
* `set_lighting(light, p1, p2)`: Set the lighting within the `VoxelManip` to a uniform value * `set_lighting(light, [p1, p2])`: Set the lighting within the `VoxelManip` to a uniform value
* `light` is a table, `{day=<0...15>, night=<0...15>}` * `light` is a table, `{day=<0...15>, night=<0...15>}`
* To be used only by a `VoxelManip` object from `minetest.get_mapgen_object` * To be used only by a `VoxelManip` object from `minetest.get_mapgen_object`
* (`p1`, `p2`) is the area in which lighting is set; * (`p1`, `p2`) is the area in which lighting is set;
@ -2997,10 +3079,12 @@ will place the schematic inside of the VoxelManip.
* expects lighting data in the same format that `get_light_data()` returns * expects lighting data in the same format that `get_light_data()` returns
* `get_param2_data()`: Gets the raw `param2` data read into the `VoxelManip` object * `get_param2_data()`: Gets the raw `param2` data read into the `VoxelManip` object
* `set_param2_data(param2_data)`: Sets the `param2` contents of each node in the `VoxelManip` * `set_param2_data(param2_data)`: Sets the `param2` contents of each node in the `VoxelManip`
* `calc_lighting(p1, p2)`: Calculate lighting within the `VoxelManip` * `calc_lighting([p1, p2], [propagate_shadow])`: Calculate lighting within the `VoxelManip`
* To be used only by a `VoxelManip` object from `minetest.get_mapgen_object` * To be used only by a `VoxelManip` object from `minetest.get_mapgen_object`
* (`p1`, `p2`) is the area in which lighting is set; defaults to the whole area * (`p1`, `p2`) is the area in which lighting is set; defaults to the whole area
if left out if left out or nil
* `propagate_shadow` is an optional boolean deciding whether shadows in a generated
mapchunk above are propagated down into the mapchunk; defaults to `true` if left out
* `update_liquids()`: Update liquid flow * `update_liquids()`: Update liquid flow
* `was_modified()`: Returns `true` or `false` if the data in the voxel manipulator * `was_modified()`: Returns `true` or `false` if the data in the voxel manipulator
had been modified since the last read from map, due to a call to had been modified since the last read from map, due to a call to
@ -3121,6 +3205,9 @@ Registered entities
L-system trees L-system trees
-------------- --------------
**Warning**
L-system generation currently creates lighting bugs in the form of mapblock-sized shadows.
Often these bugs appear as subtle shadows in water.
### Tree definition ### Tree definition
@ -3213,7 +3300,12 @@ Definition tables
stepheight = 0, stepheight = 0,
automatic_face_movement_dir = 0.0, automatic_face_movement_dir = 0.0,
-- ^ automatically set yaw to movement direction; offset in degrees; false to disable -- ^ automatically set yaw to movement direction; offset in degrees; false to disable
automatic_face_movement_max_rotation_per_sec = -1,
-- ^ limit automatic rotation to this value in degrees per second. values < 0 no limit
backface_culling = true, -- false to disable backface_culling for model backface_culling = true, -- false to disable backface_culling for model
nametag = "", -- by default empty, for players their name is shown if empty
nametag_color = <color>, -- sets color of nametag as ColorSpec
infotext = "", -- by default empty, text to be shown when pointed at object
} }
### Entity definition (`register_entity`) ### Entity definition (`register_entity`)
@ -3251,6 +3343,21 @@ Definition tables
action = func(pos, node, active_object_count, active_object_count_wider), action = func(pos, node, active_object_count, active_object_count_wider),
} }
### LBM (LoadingBlockModifier) definition (`register_lbm`)
{
name = "modname:replace_legacy_door",
nodenames = {"default:lava_source"},
-- ^ List of node names to trigger the LBM on.
-- Also non-registered nodes will work.
-- Groups (as of group:groupname) will work as well.
run_at_every_load = false,
-- ^ Whether to run the LBM's action every time a block gets loaded,
-- and not just for blocks that were saved last time before LBMs were
-- introduced to the world.
action = func(pos, node),
}
### Item definition (`register_node`, `register_craftitem`, `register_tool`) ### Item definition (`register_node`, `register_craftitem`, `register_tool`)
{ {
@ -3294,6 +3401,11 @@ Definition tables
--[[ --[[
^ Shall place item and return the leftover itemstack ^ Shall place item and return the leftover itemstack
^ default: minetest.item_place ]] ^ default: minetest.item_place ]]
on_secondary_use = func(itemstack, user, pointed_thing),
--[[
^ Same as on_place but called when pointing at nothing.
^ pointed_thing : always { type = "nothing" }
]]
on_drop = func(itemstack, dropper, pos), on_drop = func(itemstack, dropper, pos),
--[[ --[[
^ Shall drop item and return the leftover itemstack ^ Shall drop item and return the leftover itemstack
@ -3325,7 +3437,7 @@ Definition tables
* `{name="image.png", animation={Tile Animation definition}}` * `{name="image.png", animation={Tile Animation definition}}`
* `{name="image.png", backface_culling=bool, tileable_vertical=bool, * `{name="image.png", backface_culling=bool, tileable_vertical=bool,
tileable_horizontal=bool}` tileable_horizontal=bool}`
* backface culling only supported in special tiles. * backface culling enabled by default for most nodes
* tileable flags are info for shaders, how they should treat texture * tileable flags are info for shaders, how they should treat texture
when displacement mapping is used when displacement mapping is used
Directions are from the point of view of the tile texture, Directions are from the point of view of the tile texture,
@ -3367,6 +3479,7 @@ Definition tables
diggable = true, -- If false, can never be dug diggable = true, -- If false, can never be dug
climbable = false, -- If true, can be climbed on (ladder) climbable = false, -- If true, can be climbed on (ladder)
buildable_to = false, -- If true, placed nodes can replace this node buildable_to = false, -- If true, placed nodes can replace this node
floodable = false, -- If true, liquids flow into and replace this node
liquidtype = "none", -- "none"/"source"/"flowing" liquidtype = "none", -- "none"/"source"/"flowing"
liquid_alternative_flowing = "", -- Flowing version of source liquid liquid_alternative_flowing = "", -- Flowing version of source liquid
liquid_alternative_source = "", -- Source version of flowing liquid liquid_alternative_source = "", -- Source version of flowing liquid
@ -3380,6 +3493,12 @@ Definition tables
light_source = 0, -- Amount of light emitted by node light_source = 0, -- Amount of light emitted by node
damage_per_second = 0, -- If player is inside node, this damage is caused damage_per_second = 0, -- If player is inside node, this damage is caused
node_box = {type="regular"}, -- See "Node boxes" node_box = {type="regular"}, -- See "Node boxes"
connects_to = nodenames, --[[
* Used for nodebox nodes with the type == "connected"
* Specifies to what neighboring nodes connections will be drawn
* e.g. `{"group:fence", "default:wood"}` or `"default:stone"` ]]
connect_sides = { "top", "bottom", "front", "left", "back", "right" }, --[[
^ Tells connected nodebox nodes to connect only to these sides of this node. ]]
mesh = "model", mesh = "model",
selection_box = {type="regular"}, -- See "Node boxes" --[[ selection_box = {type="regular"}, -- See "Node boxes" --[[
^ If drawtype "nodebox" is used and selection_box is nil, then node_box is used. ]] ^ If drawtype "nodebox" is used and selection_box is nil, then node_box is used. ]]
@ -3554,7 +3673,7 @@ Definition tables
y_max = 64, y_max = 64,
flags = "", flags = "",
-- ^ Attributes for this ore generation -- ^ Attributes for this ore generation
noise_threshhold = 0.5, noise_threshold = 0.5,
-- ^ If noise is above this threshold, ore is placed. Not needed for a uniform distribution -- ^ If noise is above this threshold, ore is placed. Not needed for a uniform distribution
noise_params = {offset=0, scale=1, spread={x=100, y=100, z=100}, seed=23, octaves=3, persist=0.70} noise_params = {offset=0, scale=1, spread={x=100, y=100, z=100}, seed=23, octaves=3, persist=0.70}
-- ^ NoiseParams structure describing the perlin noise used for ore distribution. -- ^ NoiseParams structure describing the perlin noise used for ore distribution.
@ -3569,6 +3688,51 @@ Definition tables
-- ^ Can be a list of (or a single) biome names, IDs, or definitions. -- ^ Can be a list of (or a single) biome names, IDs, or definitions.
} }
### Biome definition (`register_biome`)
{
name = "tundra",
node_dust = "default:snow",
-- ^ Node dropped onto upper surface after all else is generated.
node_top = "default:dirt_with_snow",
depth_top = 1,
-- ^ Node forming surface layer of biome and thickness of this layer.
node_filler = "default:permafrost",
depth_filler = 3,
-- ^ Node forming lower layer of biome and thickness of this layer.
node_stone = "default:bluestone",
-- ^ Node that replaces all stone nodes between roughly y_min and y_max.
node_water_top = "default:ice",
depth_water_top = 10,
-- ^ Node forming a surface layer in seawater with the defined thickness.
node_water = "",
-- ^ Node that replaces all seawater nodes not in the defined surface layer.
node_river_water = "default:ice",
-- ^ Node that replaces river water in mapgens that use default:river_water.
y_min = 1,
y_max = 31000,
-- ^ Lower and upper limits for biome.
-- ^ Because biome is not recalculated for every node in a node column
-- ^ some biome materials can exceed their limits, especially stone.
-- ^ For each node column in a mapchunk, biome is only recalculated at column
-- ^ top and at each of these surfaces:
-- ^ Ground below air, water below air, ground below water.
-- ^ The selected biome then stays in effect for all nodes below until
-- ^ column base or the next biome recalculation.
heat_point = 0,
humidity_point = 50,
-- ^ Characteristic average temperature and humidity for the biome.
-- ^ These values create 'biome points' on a voronoi diagram that has heat
-- ^ and humidity as axes. The resulting voronoi cells determine which
-- ^ heat/humidity points belong to which biome, and therefore determine
-- ^ the area and location of each biome in the world.
-- ^ The biome points need to be carefully and evenly spaced on the voronoi
-- ^ diagram to result in roughly equal size biomes.
-- ^ Heat and humidity have average values of 50, vary mostly between
-- ^ 0 and 100 but also often exceed these values.
-- ^ Heat is not in degrees celcius, both values are abstract.
}
### Decoration definition (`register_decoration`) ### Decoration definition (`register_decoration`)
{ {
@ -3593,11 +3757,12 @@ Definition tables
-- ^ Minimum and maximum `y` positions these decorations can be generated at. -- ^ Minimum and maximum `y` positions these decorations can be generated at.
-- ^ This parameter refers to the `y` position of the decoration base, so -- ^ This parameter refers to the `y` position of the decoration base, so
-- the actual maximum height would be `height_max + size.Y`. -- the actual maximum height would be `height_max + size.Y`.
flags = "liquid_surface", flags = "liquid_surface, force_placement",
-- ^ Flags for all decoration types. -- ^ Flags for all decoration types.
-- ^ "liquid_surface": Instead of placement on the highest solid surface -- ^ "liquid_surface": Instead of placement on the highest solid surface
-- ^ in a mapchunk column, placement is on the highest liquid surface. -- ^ in a mapchunk column, placement is on the highest liquid surface.
-- ^ Placement is disabled if solid nodes are found above the liquid surface. -- ^ Placement is disabled if solid nodes are found above the liquid surface.
-- ^ "force_placement": Nodes other than "air" and "ignore" are replaced by the decoration.
----- Simple-type parameters ----- Simple-type parameters
decoration = "default:grass", decoration = "default:grass",
@ -3641,7 +3806,7 @@ Definition tables
}, },
-- ^ See 'Schematic specifier' for details. -- ^ See 'Schematic specifier' for details.
replacements = {["oldname"] = "convert_to", ...}, replacements = {["oldname"] = "convert_to", ...},
flags = "place_center_x, place_center_y, place_center_z, force_placement", flags = "place_center_x, place_center_y, place_center_z",
-- ^ Flags for schematic decorations. See 'Schematic attributes'. -- ^ Flags for schematic decorations. See 'Schematic attributes'.
rotation = "90" -- rotate schematic 90 degrees on placement rotation = "90" -- rotate schematic 90 degrees on placement
-- ^ Rotation can be "0", "90", "180", "270", or "random". -- ^ Rotation can be "0", "90", "180", "270", or "random".
@ -3752,3 +3917,37 @@ Definition tables
playername = "singleplayer" playername = "singleplayer"
-- ^ Playername is optional, if specified spawns particle only on the player's client -- ^ Playername is optional, if specified spawns particle only on the player's client
} }
### `HTTPRequest` definition (`http_fetch`, `http_fetch_async`)
{
url = "http://example.org",
timeout = 10,
-- ^ Timeout for connection in seconds. Default is 3 seconds.
post_data = "Raw POST request data string" OR { field1 = "data1", field2 = "data2" },
-- ^ Optional, if specified a POST request with post_data is performed.
-- ^ Accepts both a string and a table. If a table is specified, encodes table
-- ^ as x-www-form-urlencoded key-value pairs.
-- ^ If post_data ist not specified, a GET request is performed instead.
user_agent = "ExampleUserAgent",
-- ^ Optional, if specified replaces the default minetest user agent with given string
extra_headers = { "Accept-Language: en-us", "Accept-Charset: utf-8" },
-- ^ Optional, if specified adds additional headers to the HTTP request. You must make sure
-- ^ that the header strings follow HTTP specification ("Key: Value").
multipart = boolean
-- ^ Optional, if true performs a multipart HTTP request. Default is false.
}
### `HTTPRequestResult` definition (`http_fetch` callback, `http_fetch_async_get`)
{
completed = true,
-- ^ If true, the request has finished (either succeeded, failed or timed out)
succeeded = true,
-- ^ If true, the request was succesful
timeout = false,
-- ^ If true, the request timed out
code = 200,
-- ^ HTTP status code
data = "response"
}

8
doc/main_page.dox Normal file
View File

@ -0,0 +1,8 @@
/** @mainpage The Minetest engine internal documentation
Welcome to the Minetest engine Doxygen documentation site!\n
This page documents the internal structure of the Minetest engine's C++ code.\n
Use the tree view at the left to navigate.
*/

View File

@ -1,4 +1,4 @@
Minetest Lua Mainmenu API Reference 0.4.13 Minetest Lua Mainmenu API Reference 0.4.14
======================================== ========================================
Introduction Introduction

View File

@ -36,7 +36,7 @@ minetest.register_ore({
clust_size = 7, clust_size = 7,
y_min = -15, y_min = -15,
y_max = 0, y_max = 0,
noise_threshhold = 0, noise_threshold = 0,
noise_params = { noise_params = {
offset=0.35, offset=0.35,
scale=0.2, scale=0.2,

View File

@ -214,12 +214,12 @@
# type: key # type: key
# keymap_camera_mode = KEY_F7 # keymap_camera_mode = KEY_F7
# Key for increasing the viewing range. Modifies the minimum viewing range. # Key for increasing the viewing range.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
# type: key # type: key
# keymap_increase_viewing_range_min = + # keymap_increase_viewing_range_min = +
# Key for decreasing the viewing range. Modifies the minimum viewing range. # Key for decreasing the viewing range.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
# type: key # type: key
# keymap_decrease_viewing_range_min = - # keymap_decrease_viewing_range_min = -
@ -242,10 +242,21 @@
# type: int min: 1 max: 65535 # type: int min: 1 max: 65535
# remote_port = 30000 # remote_port = 30000
# Whether to support older servers before protocol version 25.
# Enable if you want to connect to 0.4.12 servers and before.
# Servers starting with 0.4.13 will work, 0.4.12-dev servers may work.
# Disabling this option will protect your password better.
# type: bool
# send_pre_v25_init = true
# Save the map received by the client on disk. # Save the map received by the client on disk.
# type: bool # type: bool
# enable_local_map_saving = false # enable_local_map_saving = false
# Show entity selection boxes
# type: bool
# show_entity_selectionbox = true
# Enable usage of remote media server (if provided by server). # Enable usage of remote media server (if provided by server).
# Remote servers offer a significantly faster way to download media (e.g. textures) # Remote servers offer a significantly faster way to download media (e.g. textures)
# when connecting to the server. # when connecting to the server.
@ -266,16 +277,14 @@
#### Basic #### Basic
# Enable VBO
# type: bool
# enable_vbo = true
# Whether to fog out the end of the visible area. # Whether to fog out the end of the visible area.
# type: bool # type: bool
# enable_fog = true # enable_fog = true
# Enable a bit lower water surface, so it doesn't "fill" the node completely.
# Note that this is not quite optimized and that smooth lighting on the
# water surface doesn't work with this.
# type: bool
# new_style_water = false
# Leaves style: # Leaves style:
# - Fancy: all faces visible # - Fancy: all faces visible
# - Simple: only outer faces, if defined special_tiles are used # - Simple: only outer faces, if defined special_tiles are used
@ -300,6 +309,10 @@
# type: bool # type: bool
# enable_3d_clouds = true # enable_3d_clouds = true
# Method used to highlight selected object.
# type: enum values: box, halo
# node_highlighting = box
#### Filtering #### Filtering
# Use mip mapping to scale textures. May slightly increase performance. # Use mip mapping to scale textures. May slightly increase performance.
@ -335,12 +348,6 @@
# type: int # type: int
# texture_min_size = 64 # texture_min_size = 64
# Pre-generate all item visuals used in the inventory.
# This increases startup time, but runs smoother in-game.
# The generated textures can easily exceed your VRAM, causing artifacts in the inventory.
# type: bool
# preload_item_visuals = false
# Experimental option, might cause visible spaces between blocks # Experimental option, might cause visible spaces between blocks
# when set to higher number than 0. # when set to higher number than 0.
# type: enum values: 0, 1, 2, 4, 8, 16 # type: enum values: 0, 1, 2, 4, 8, 16
@ -353,6 +360,12 @@
# type: bool # type: bool
# enable_shaders = true # enable_shaders = true
##### Tone Mapping
# Enables filmic tone mapping
# type: bool
# tone_mapping = false
##### Bumpmapping ##### Bumpmapping
# Enables bumpmapping for textures. Normalmaps need to be supplied by the texture pack # Enables bumpmapping for textures. Normalmaps need to be supplied by the texture pack
@ -431,11 +444,6 @@
#### Advanced #### Advanced
# Minimum wanted FPS.
# The amount of rendered stuff is dynamically set according to this. and viewing range min and max.
# type: int
# wanted_fps = 30
# If FPS would go higher than this, limit it by sleeping # If FPS would go higher than this, limit it by sleeping
# to not waste CPU power for no benefit. # to not waste CPU power for no benefit.
# type: int # type: int
@ -445,21 +453,16 @@
# type: int # type: int
# pause_fps_max = 20 # pause_fps_max = 20
# The allowed adjustment range for the automatic rendering range adjustment. # View distance in nodes.
# Set this to be equal to viewing range minimum to disable the auto-adjustment algorithm. # Min = 20
# type: int # type: int
# viewing_range_nodes_max = 160 # viewing_range = 100
# The allowed adjustment range for the automatic rendering range adjustment. # Width component of the initial window size.
# Set this to be equal to viewing range minimum to disable the auto-adjustment algorithm.
# type: int
# viewing_range_nodes_min = 35
# Vertical initial window size.
# type: int # type: int
# screenW = 800 # screenW = 800
# Horizontal initial window size. # Height component of the initial window size.
# type: int # type: int
# screenH = 600 # screenH = 600
@ -518,7 +521,8 @@
# - interlaced: odd/even line based polarisation screen support. # - interlaced: odd/even line based polarisation screen support.
# - topbottom: split screen top/bottom. # - topbottom: split screen top/bottom.
# - sidebyside: split screen side by side. # - sidebyside: split screen side by side.
# type: enum values: none, anaglyph, interlaced, topbottom, sidebyside # - pageflip: quadbuffer based 3d.
# type: enum values: none, anaglyph, interlaced, topbottom, sidebyside, pageflip
# 3d_mode = none # 3d_mode = none
# In-game chat console background color (R,G,B). # In-game chat console background color (R,G,B).
@ -554,10 +558,6 @@
# type: float # type: float
# hud_hotbar_max_width = 1.0 # hud_hotbar_max_width = 1.0
# Enable selection highlighting for nodes (disables selectionbox).
# type: bool
# enable_node_highlighting = false
# Enables caching of facedir rotated meshes. # Enables caching of facedir rotated meshes.
# type: bool # type: bool
# enable_mesh_cache = false # enable_mesh_cache = false
@ -587,6 +587,10 @@
# type: float min: 0.25 max: 4 # type: float min: 0.25 max: 4
# ambient_occlusion_gamma = 2.2 # ambient_occlusion_gamma = 2.2
# Enables animation of inventory items.
# type: bool
# inventory_items_animations = false
### Menus ### Menus
# Use a cloud animation for the main menu background. # Use a cloud animation for the main menu background.
@ -660,6 +664,16 @@
# type: path # type: path
# screenshot_path = # screenshot_path =
# Format of screenshots.
# type: enum values: png, jpg, bmp, pcx, ppm, tga
# screenshot_format = png
# Screenshot quality. Only used for JPEG format.
# 1 means worst quality; 100 means best quality.
# Use 0 for default quality.
# type: int min: 0 max: 100
# screenshot_quality = 0
### Advanced ### Advanced
# 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.
@ -812,6 +826,10 @@
# type: string # type: string
# default_privs = interact, shout # default_privs = interact, shout
# Privileges that players with basic_privs can grant
# type: string
# basic_privs = interact, shout
# Whether players are shown to clients without any range limit. # Whether players are shown to clients without any range limit.
# Deprecated, use the setting player_transfer_distance instead. # Deprecated, use the setting player_transfer_distance instead.
# type: bool # type: bool
@ -829,13 +847,6 @@
# type: string # type: string
# static_spawnpoint = # static_spawnpoint =
# Maximum distance above water level for player spawn.
# Larger values result in spawn points closer to (x = 0, z = 0).
# Smaller values may result in a suitable spawn point not being found,
# resulting in a spawn at (0, 0, 0) possibly buried underground.
# type: int
# vertical_spawn_range = 16
# If enabled, new players cannot join with an empty password. # If enabled, new players cannot join with an empty password.
# type: bool # type: bool
# disallow_empty_password = false # disallow_empty_password = false
@ -977,6 +988,18 @@
# type: float # type: float
# dedicated_server_step = 0.1 # dedicated_server_step = 0.1
# Time in between active block management cycles
# type: float
# active_block_mgmt_interval = 2.0
# Length of time between ABM execution cycles
# type: float
# abm_interval = 1.0
# Length of time between NodeTimer execution cycles
# type: float
# nodetimer_interval = 1.0
# 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.
# type: bool # type: bool
@ -1000,7 +1023,7 @@
# Name of map generator to be used when creating a new world. # Name of map generator to be used when creating a new world.
# Creating a world in the main menu will override this. # Creating a world in the main menu will override this.
# type: enum values: v5, v6, v7, fractal, singlenode # type: enum values: v5, v6, v7, flat, valleys, fractal, singlenode
# mg_name = v6 # mg_name = v6
# Water surface level of the world. # Water surface level of the world.
@ -1021,11 +1044,12 @@
# map_generation_limit = 31000 # map_generation_limit = 31000
# Global map generation attributes. # Global map generation attributes.
# In Mapgen v6 the 'decorations' flag controls all decorations except trees
# and junglegrass, in all other mapgens this flag controls all decorations.
# 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.
# 'trees' and 'flat' flags only have effect in mgv6. # type: flags possible values: caves, dungeons, light, decorations, nocaves, nodungeons, nolight, nodecorations
# type: flags possible values: trees, caves, dungeons, light, flat, notrees, nocaves, nodungeons, nolight, noflat # mg_flags = caves,dungeons,light,decorations
# mg_flags = trees,caves,dungeons,light
### Advanced ### Advanced
@ -1072,6 +1096,10 @@
#### Mapgen v5 #### Mapgen v5
# Controls width of tunnels, a smaller value creates wider tunnels.
# type: float
# mgv5_cave_width = 0.125
# type: noise_params # type: noise_params
# mgv5_np_filler_depth = 0, 1, (150, 150, 150), 261, 4, 0.7, 2.0 # mgv5_np_filler_depth = 0, 1, (150, 150, 150), 261, 4, 0.7, 2.0
@ -1090,13 +1118,13 @@
#### Mapgen v6 #### Mapgen v6
# Map generation attributes specific to Mapgen v6. # Map generation attributes specific to Mapgen v6.
# When snowbiomes are enabled jungles are enabled and the jungles flag is ignored. # When snowbiomes are enabled jungles are automatically enabled, 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.
# type: flags possible values: jungles, biomeblend, mudflow, snowbiomes, nojungles, nobiomeblend, nomudflow, nosnowbiomes # type: flags possible values: jungles, biomeblend, mudflow, snowbiomes, flat, trees, nojungles, nobiomeblend, nomudflow, nosnowbiomes, noflat, notrees
# mgv6_spflags = jungles,biomeblend,mudflow,snowbiomes # mgv6_spflags = jungles,biomeblend,mudflow,snowbiomes,trees
# Controls size of deserts and beaches in Mapgen V6. # Controls size of deserts and beaches in Mapgen v6.
# When snowbiomes are enabled 'mgv6_freq_desert' is ignored. # When snowbiomes are enabled 'mgv6_freq_desert' is ignored.
# type: float # type: float
# mgv6_freq_desert = 0.45 # mgv6_freq_desert = 0.45
@ -1140,12 +1168,16 @@
#### Mapgen v7 #### Mapgen v7
# Map generation attributes specific to Mapgen v7. # Map generation attributes specific to Mapgen v7.
# 'ridges' are the rivers. # The 'ridges' flag controls the rivers.
# 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.
# type: flags possible values: mountains, ridges, nomountains, noridges # type: flags possible values: mountains, ridges, nomountains, noridges
# mgv7_spflags = mountains,ridges # mgv7_spflags = mountains,ridges
# Controls width of tunnels, a smaller value creates wider tunnels.
# type: float
# mgv7_cave_width = 0.3
# type: noise_params # type: noise_params
# mgv7_np_terrain_base = 4, 70, (600, 600, 600), 82341, 5, 0.6, 2.0 # mgv7_np_terrain_base = 4, 70, (600, 600, 600), 82341, 5, 0.6, 2.0
@ -1156,7 +1188,7 @@
# mgv7_np_terrain_persist = 0.6, 0.1, (2000, 2000, 2000), 539, 3, 0.6, 2.0 # mgv7_np_terrain_persist = 0.6, 0.1, (2000, 2000, 2000), 539, 3, 0.6, 2.0
# type: noise_params # type: noise_params
# mgv7_np_height_select = -12, 24, (500, 500, 500), 4213, 6, 0.7, 2.0 # mgv7_np_height_select = -8, 16, (500, 500, 500), 4213, 6, 0.7, 2.0
# type: noise_params # type: noise_params
# mgv7_np_filler_depth = 0, 1.2, (150, 150, 150), 261, 3, 0.7, 2.0 # mgv7_np_filler_depth = 0, 1.2, (150, 150, 150), 261, 3, 0.7, 2.0
@ -1179,59 +1211,132 @@
# type: noise_params # type: noise_params
# mgv7_np_cave2 = 0, 12, (100, 100, 100), 10325, 4, 0.5, 2.0 # mgv7_np_cave2 = 0, 12, (100, 100, 100), 10325, 4, 0.5, 2.0
#### Mapgen flat
# Map generation attributes specific to Mapgen flat.
# 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 starting with 'no' are used to explicitly disable them.
# type: flags possible values: lakes, hills, , nolakes, nohills
# mgflat_spflags =
# Y of flat ground.
# type: int
# mgflat_ground_level = 8
# Y of upper limit of large pseudorandom caves.
# type: int
# mgflat_large_cave_depth = -33
# Controls width of tunnels, a smaller value creates wider tunnels.
# type: float
# mgflat_cave_width = 0.3
# Terrain noise threshold for lakes.
# Controls proportion of world area covered by lakes.
# Adjust towards 0.0 for a larger proportion.
# type: float
# mgflat_lake_threshold = -0.45
# Controls steepness/depth of lake depressions.
# type: float
# mgflat_lake_steepness = 48.0
# Terrain noise threshold for hills.
# Controls proportion of world area covered by hills.
# Adjust towards 0.0 for a larger proportion.
# type: float
# mgflat_hill_threshold = 0.45
# Controls steepness/height of hills.
# type: float
# mgflat_hill_steepness = 64.0
# Determines terrain shape.
# The 3 numbers in brackets control the scale of the
# terrain, the 3 numbers should be identical.
# type: noise_params
# mgflat_np_terrain = 0, 1, (600, 600, 600), 7244, 5, 0.6, 2.0
# type: noise_params
# mgflat_np_filler_depth = 0, 1.2, (150, 150, 150), 261, 3, 0.7, 2.0
# type: noise_params
# mgflat_np_cave1 = 0, 12, (128, 128, 128), 52534, 4, 0.5, 2.0
# type: noise_params
# mgflat_np_cave2 = 0, 12, (128, 128, 128), 10325, 4, 0.5, 2.0
#### Mapgen fractal #### Mapgen fractal
# Map generation attributes specific to Mapgen fractal. # Controls width of tunnels, a smaller value creates wider tunnels.
# 'julia' selects a julia set to be generated instead of a mandelbrot set. # type: float
# Flags that are not specified in the flag string are not modified from the default. # mgfractal_cave_width = 0.3
# Flags starting with "no" are used to explicitly disable them.
# type: flags possible values: julia, nojulia
# mgfractal_spflags = nojulia
# Mandelbrot set: Iterations of the recursive function. # Choice of 18 fractals from 9 formulas.
# Controls scale of finest detail. # 1 = 4D "Roundy" mandelbrot set.
# 2 = 4D "Roundy" julia set.
# 3 = 4D "Squarry" mandelbrot set.
# 4 = 4D "Squarry" julia set.
# 5 = 4D "Mandy Cousin" mandelbrot set.
# 6 = 4D "Mandy Cousin" julia set.
# 7 = 4D "Variation" mandelbrot set.
# 8 = 4D "Variation" julia set.
# 9 = 3D "Mandelbrot/Mandelbar" mandelbrot set.
# 10 = 3D "Mandelbrot/Mandelbar" julia set.
# 11 = 3D "Christmas Tree" mandelbrot set.
# 12 = 3D "Christmas Tree" julia set.
# 13 = 3D "Mandelbulb" mandelbrot set.
# 14 = 3D "Mandelbulb" julia set.
# 15 = 3D "Cosine Mandelbulb" mandelbrot set.
# 16 = 3D "Cosine Mandelbulb" julia set.
# 17 = 4D "Mandelbulb" mandelbrot set.
# 18 = 4D "Mandelbulb" julia set.
# type: int min: 1 max: 18
# mgfractal_fractal = 1
# Iterations of the recursive function.
# Controls the amount of fine detail.
# type: int # type: int
# mgfractal_m_iterations = 9 # mgfractal_iterations = 11
# Mandelbrot set: Approximate (X,Y,Z) scales in nodes. # Approximate (X,Y,Z) scale of fractal in nodes.
# type: v3f # type: v3f
# mgfractal_m_scale = (1024.0, 256.0, 1024.0) # mgfractal_scale = (4096.0, 1024.0, 4096.0)
# Mandelbrot set: (X,Y,Z) offsets from world centre. # (X,Y,Z) offset of fractal from world centre in units of 'scale'.
# Range roughly -2 to 2, multiply by m_scale for offsets in nodes. # 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.
# Range roughly -2 to 2. Multiply by 'scale' for offset in nodes.
# type: v3f # type: v3f
# mgfractal_m_offset = (1.75, 0.0, 0.0) # mgfractal_offset = (1.79, 0.0, 0.0)
# Mandelbrot set: W co-ordinate of the generated 3D slice of the 4D shape. # W co-ordinate of the generated 3D slice of a 4D fractal.
# Determines which 3D slice of the 4D shape is generated.
# Has no effect on 3D fractals.
# Range roughly -2 to 2. # Range roughly -2 to 2.
# type: float # type: float
# mgfractal_m_slice_w = 0.0 # mgfractal_slice_w = 0.0
# Julia set: Iterations of the recursive function. # Julia set only: X component of hypercomplex constant determining julia shape.
# Controls scale of finest detail.
# type: int
# mgfractal_j_iterations = 9
# Julia set: Approximate (X,Y,Z) scales in nodes.
# type: v3f
# mgfractal_j_scale = (2048.0, 512.0, 2048.0)
# Julia set: (X,Y,Z) offsets from world centre.
# Range roughly -2 to 2, multiply by j_scale for offsets in nodes.
# type: v3f
# mgfractal_j_offset = (0.0, 1.0, 0.0)
# Julia set: W co-ordinate of the generated 3D slice of the 4D shape.
# Range roughly -2 to 2.
# type: float
# mgfractal_j_slice_w = 0.0
# Julia set: The following 4 values determine the 4D shape.
# Range roughly -2 to 2. # Range roughly -2 to 2.
# type: float # type: float
# mgfractal_julia_x = 0.33 # mgfractal_julia_x = 0.33
# Julia set only: Y component of hypercomplex constant determining julia shape.
# Range roughly -2 to 2.
# type: float
# mgfractal_julia_y = 0.33 # mgfractal_julia_y = 0.33
# Julia set only: Z component of hypercomplex constant determining julia shape.
# Range roughly -2 to 2.
# type: float
# mgfractal_julia_z = 0.33 # mgfractal_julia_z = 0.33
# Julia set only: W component of hypercomplex constant determining julia shape.
# Has no effect on 3D fractals.
# Range roughly -2 to 2.
# type: float
# mgfractal_julia_w = 0.33 # mgfractal_julia_w = 0.33
# type: noise_params # type: noise_params
@ -1246,6 +1351,95 @@
# type: noise_params # type: noise_params
# mgfractal_np_cave2 = 0, 12, (128, 128, 128), 10325, 4, 0.5, 2.0 # mgfractal_np_cave2 = 0, 12, (128, 128, 128), 10325, 4, 0.5, 2.0
#### Mapgen Valleys
##### General
# Map generation attributes specific to Mapgen Valleys.
# 'altitude_chill' makes higher elevations colder, which may cause biome issues.
# 'humid_rivers' modifies the humidity around rivers and in areas where water would tend to pool,
# it may interfere with delicately adjusted biomes.
# 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.
# type: flags possible values: altitude_chill, noaltitude_chill, humid_rivers, nohumid_rivers
# mg_valleys_spflags = altitude_chill,humid_rivers
# The altitude at which temperature drops by 20C
# type: int
# mgvalleys_altitude_chill = 90
# Depth below which you'll find large caves.
# type: int
# mgvalleys_large_cave_depth = -33
# Creates unpredictable lava features in caves.
# These can make mining difficult. Zero disables them. (0-10)
# type: int
# mgvalleys_lava_features = 0
# Depth below which you'll find massive caves.
# type: int
# mgvalleys_massive_cave_depth = -256
# How deep to make rivers
# type: int
# mgvalleys_river_depth = 4
# How wide to make rivers
# type: int
# mgvalleys_river_size = 5
# Creates unpredictable water features in caves.
# These can make mining difficult. Zero disables them. (0-10)
# type: int
# mgvalleys_water_features = 0
# Controls width of tunnels, a smaller value creates wider tunnels.
# type: float
# mgvalleys_cave_width = 0.3
##### Noises
# Caves and tunnels form at the intersection of the two noises
# type: noise_params
# mgvalleys_np_cave1 = 0, 12, (100, 100, 100), 52534, 4, 0.5, 2.0
# Caves and tunnels form at the intersection of the two noises
# type: noise_params
# mgvalleys_np_cave2 = 0, 12, (100, 100, 100), 10325, 4, 0.5, 2.0
# The depth of dirt or other filler
# type: noise_params
# mgvalleys_np_filler_depth = 0, 1.2, (256, 256, 256), 1605, 3, 0.5, 2.0
# Massive caves form here.
# type: noise_params
# mgvalleys_np_massive_caves = 0, 1, (768, 256, 768), 59033, 6, 0.63, 2.0
# River noise -- rivers occur close to zero
# type: noise_params
# mgvalleys_np_rivers = 0, 1, (256, 256, 256), -6050, 5, 0.6, 2.0
# Base terrain height
# type: noise_params
# mgvalleys_np_terrain_height = -10, 50, (1024, 1024, 1024), 5202, 6, 0.4, 2.0
# Raises terrain to make valleys around the rivers
# type: noise_params
# mgvalleys_np_valley_depth = 5, 4, (512, 512, 512), -1914, 1, 1.0, 2.0
# Slope and fill work together to modify the heights
# type: noise_params
# mgvalleys_np_inter_valley_fill = 0, 1, (256, 512, 256), 1993, 6, 0.8, 2.0
# Amplifies the valleys
# type: noise_params
# mgvalleys_np_valley_profile = 0.6, 0.5, (512, 512, 512), 777, 1, 1.0, 2.0
# Slope and fill work together to modify the heights
# type: noise_params
# mgvalleys_np_inter_valley_slope = 0.5, 0.5, (128, 128, 128), 746, 1, 1.0, 2.0
## Security ## Security
# Prevent mods from doing insecure things like running shell commands. # Prevent mods from doing insecure things like running shell commands.
@ -1257,6 +1451,11 @@
# type: string # type: string
# secure.trusted_mods = # secure.trusted_mods =
# Comma-seperated list of mods that are allowed to access HTTP APIs, which
# allow them to upload and download data to/from the internet.
# type: string
# secure.http_mods =
# #
# Client and Server # Client and Server
# #

View File

@ -28,8 +28,9 @@
</ul> </ul>
</description> </description>
<screenshots> <screenshots>
<screenshot type="default" width="1440" height="851">http://minetest.net/_media/screen2.png</screenshot> <screenshot type="default" width="1920" height="1080">http://www.minetest.net/media/gallery/1.jpg</screenshot>
<screenshot width="1440" height="851">http://minetest.net/_media/screenshot_4032289578.png</screenshot> <screenshot width="1920" height="1080">http://www.minetest.net/media/gallery/3.jpg</screenshot>
<screenshot width="1920" height="1080">http://www.minetest.net/media/gallery/5.jpg</screenshot>
</screenshots> </screenshots>
<url type="homepage">http://minetest.net</url> <url type="homepage">http://minetest.net</url>
<updatecontact>sfan5@live.de</updatecontact> <updatecontact>sfan5@live.de</updatecontact>

File diff suppressed because it is too large Load Diff

4214
po/ca/minetest.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

4047
po/he/minetest.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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