Sync all Minetest commits
master
Maksim Gamarnik 2015-11-10 13:49:24 +02:00
parent 84cc7510ab
commit 9012ac8f22
394 changed files with 113621 additions and 30202 deletions

94
.gitignore vendored
View File

@ -1,26 +1,48 @@
## Generic ignorable patterns and files
## Editors and Development environments
*~
.*.swp
.*-swp
*bak*
tags
*.vim
*.swp
*.bak*
*.orig
*.rej
# Vim
*.vim
# Kate
.*.kate-swp
.swp.*
# KDevelop4
.kdev4/
*.kdev4
# Eclipse (CDT and LDT)
.project
.cproject
.settings/
.buildpath
.metadata
# GNU Global
tags
!tags/
gtags.files
## Files related to MultiCraft development cycle
/*.patch
# GNU Patch reject file
*.rej
## Non-static MultiCraft directories
## Non-static MultiCraft directories or symlinks to these
/bin/
/games/*
!/games/MultiCraft_game/
/cache/
/cache
/textures/*
!/textures/base/
/sounds/
/screenshots
/sounds
/mods/*
/worlds/
!/mods/minetest/
/mods/minetest/*
!/mods/minetest/mods_here.txt
/worlds
/world/
## Configuration/log files
minetest.conf
@ -33,51 +55,24 @@ doc/html/
doc/doxygen_*
## Build files
CMakeFiles/*
src/CMakeFiles/*
src/Makefile
src/android_version.h
src/cmake_config.h
src/cmake_config_githash.h
src/cmake_install.cmake
src/script/CMakeFiles/*
src/script/common/CMakeFiles/*
src/script/cpp_api/CMakeFiles/*
src/script/lua_api/CMakeFiles/*
src/util/CMakeFiles/*
src/unittest/CMakeFiles/*
src/jthread/CMakeFiles/*
src/jthread/Makefile
src/jthread/cmake_config.h
src/jthread/cmake_install.cmake
src/jthread/libjthread.a
src/json/libjson.a
src/lua/build/
src/lua/CMakeFiles/
src/cguittfont/CMakeFiles/
src/cguittfont/libcguittfont.a
src/cguittfont/cmake_install.cmake
src/cguittfont/Makefile
src/gmp/CMakeFiles/
src/gmp/libgmp.a
src/json/CMakeFiles/
src/json/libjsoncpp.a
src/sqlite/CMakeFiles/*
src/sqlite/libsqlite3.a
src/client/CMakeFiles/
src/network/CMakeFiles/
CMakeFiles
Makefile
!build/android/Makefile
cmake_install.cmake
CMakeCache.txt
CPackConfig.cmake
CPackSourceConfig.cmake
Makefile
cmake_install.cmake
src/android_version.h
src/android_version_githash.h
src/cmake_config.h
src/cmake_config_githash.h
src/lua/build/
locale/
.directory
.kdev4/
*.cbp
*.kdev4
*.layout
*.o
*.a
## Android build files
build/android/assets
@ -90,5 +85,6 @@ build/android/jni/src
##build/android/libs
build/android/obj
build/android/path.cfg
build/android/and_env
build/android/AndroidManifest.xml
timestamp
timestamp

View File

@ -8,6 +8,7 @@ env:
- PLATFORM=Linux
before_install: ./util/travis/before_install.sh
script: ./util/travis/script.sh
sudo: required
notifications:
email: false
matrix:

View File

@ -54,7 +54,7 @@ endif()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
# This is done here so that relative search paths are more reasnable
# This is done here so that relative search paths are more reasonable
find_package(Irrlicht)
@ -171,14 +171,14 @@ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/fonts" DESTINATION "${SHAREDIR}")
install(FILES "README.txt" DESTINATION "${DOCDIR}")
install(FILES "doc/lua_api.txt" DESTINATION "${DOCDIR}")
install(FILES "doc/menu_lua_api.txt" DESTINATION "${DOCDIR}")
install(FILES "doc/mapformat.txt" DESTINATION "${DOCDIR}")
install(FILES "doc/world_format.txt" DESTINATION "${DOCDIR}")
install(FILES "multicraft.conf.example" DESTINATION "${EXAMPLE_CONF_DIR}")
if(UNIX AND NOT APPLE)
install(FILES "doc/minetest.6" "doc/minetestserver.6" DESTINATION "${MANDIR}/man6")
install(FILES "misc/minetest.desktop" DESTINATION "${XDG_APPS_DIR}")
install(FILES "misc/minetest.appdata.xml" DESTINATION "${APPDATADIR}")
install(FILES "misc/minetest-icon.svg" DESTINATION "${ICONDIR}/hicolor/scalable/apps")
install(FILES "misc/minetest.svg" DESTINATION "${ICONDIR}/hicolor/scalable/apps")
endif()
if(APPLE)

View File

@ -1,16 +0,0 @@
There are two mods within MultiCraft licensed under CC BY-NC-SA 4.0 (https://creativecommons.org/licenses/by-nc-sa/4.0/): "adbs" and "4hunger".
Those mods are the intellectual property of 4aiman (4aiman@inbox.ru) and by no means are free (as in freedom) or open-source software.
To fully understand your rights consult the license (the link is given above).
While the CC BY-NC-SA 4.0 license forbids any kind of commercial usage by default, 4aiman holds the right to give his permission to neglect that restriction.
Thus being said, 4aiman had explicitly granted the right to commercially use "adbs" and "4hunger" mods to Maksim Gamarnik (a.k.a. MoNTE48, MoNTE48@mail.ua) on the following terms:
- Maksim Gamarnik can use current version of "adbs" and "4hunger" mods for commercial purposes in any Minetest or Freeminer related projects - both existing and those which are yet to come;
- The exception mentioned above also applies to any organization with Maksim Gamarnik as it's leader/head.
- The exception mentioned above cease to apply in case any changes to any part of "adbs" or "4hunger" are to be made by any other person than 4aiman;
- The exception mentioned above does not apply to Maksim Gamarnik's or his organization's (organisations') customers.
- Maksim Gamarnik holds no right to grant anyone else the right to use any part of "adbs" or "4hunger" mods commercially.
All questions concerning 4aiman's rights and protection of those should be directed to 4aiman via e-mail message in the first place.
4aiman has explicitly mentioned that he does not want anyone to "protect" his rights until he will express that intention by himself.
Thus, any person or organization convinced in the fact of the 4aiman's rights infringement should consult with him in the first place.
Note, that in the case 4aiman won't be properly notified and won't express his willingness (due to any reason) to cooperate with anyone who wants to protect 4aiman's rights, the actions of that "4aiman's rights defender" may well be interpreted as a slander against Maksim Gamarnik and/or 4aiman himself.

View File

@ -1,16 +0,0 @@
В состав MultiCraft входят два мода, распространяемых под лицензией CC BY-NC-SA 4.0 (https://creativecommons.org/licenses/by-nc-sa/4.0/): "adbs" и "4hunger".
Эти моды являются интеллектуальной собственностью 4aiman (4aiman@inbox.ru) и никоим образом не являются свободным или открытым программным обеспечением.
Ознакомьтесь с лицензией для того чтобы ознакомится со своими правами (ссылка дана выше).
Несмотря на то, что лицензия CC BY-NC-SA 4.0 запрещает любой вид коммерческого использования по-умолчанию, 4aiman имеет право давать разрешение на пренебрежение этим ограничением.
Таким образом, 4aiman неоднозначно и чётко предоставил право коммерческого использования модов "adbs" и "4hunger" Максиму Гамарнику (Maksim Gamarnik, также известный как MoNTE48, MoNTE48@mail.ua) на следующих условиях:
- Maksim Gamarnik может использовать текущие версии модов "adbs" и "4hunger" в коммерческих целях в любом проекте, связанном с Minetest или Freeminer - как существующих, так и тех, что, возможно, будут созданы;
- Исключительное право действует также и для любой организации, лидером/главой которой является Maksim Gamarnik.
- Исключение теряет силу в случае внесения в код "adbs" или "4hunger" изменений кем-либо помимо самого 4aiman;
- Исключение не распространяется на клиентов Maksim Gamarnik или его организации (организаций).
- Maksim Gamarnik не в праве передавать разрешения на коммерческое использование модов "adbs" или "4hunger" третьей стороне.
По всем вопросам касательно прав 4aiman и их защиты в первую очередь необходимо обращаться посредством электронной почты лично к 4aiman.
4aiman неоднозначно и чётко заявил, что не хочет, чтобы кто-либо "защищал" его права до тех пор, пока он сам не выразит такого намерения.
Таким образом, любой человек или организация, убежденный(ая) в факте ущемления прав 4aiman, обязана в первую очередь связаться с ним.
Заметьте, что в случае если 4aiman не будет как следует уведомлен и не выразит своего желания (какими бы не были причины) сотрудничать с кем бы то ни было, желающим защищать права 4aiman, действия такого "защитника" вполне могут быть рассмотрены как случай клеветы против Maksim Gamarnik и/или самого 4aiman.

View File

@ -1,10 +0,0 @@
According to the line #9 of the "License notice on adbs and 4hunger mods (ENG).txt" the permission to use adbs & 4hunger commercially should have ceased to apply.
However, Maksim Gamarnik and 4aiman made an agreement which prolongues that permision on certain special terms.
As long as those terms are being carried out the permission to use commertially is granted.
That pemission will be given again upon fullfilling the terms of agreement between Maksim Gamarnik and 4aiman.
Согласно строке №9 файла "License notice on adbs and 4hunger mods (RUS).txt", разрешение на коммерческое использование модов adbs и 4hunger должно было потерять силу.
Тем не менее, Maksim Gamarnik и 4aiman пришли к соглашению, которое продлевает данное разрешение до тех пор, пока соблюдаются особые конкретные условия.
Пока эти оговоренные условия соблюдаются, разрешение на коммерческое использование сохраняет свою силу.
Разрешение будет выдано снова, как только условия соглашения между Maksim Gamarnik и 4aiman будут выполнены окончательно.

View File

@ -13,10 +13,18 @@ PATHCFGFILE = path.cfg
ROOT = $(shell pwd)
GAMES_TO_COPY = MultiCraft_game
# this string will be written to Files.zip in ver.txt
VER_TEXT = 1.0.2
GAMES_TO_COPY =
MODS_TO_COPY =
VERSION_MAJOR := $(shell cat $(ROOT)/../../CMakeLists.txt | \
grep ^set\(VERSION_MAJOR\ | sed 's/)/ /' | cut -f2 -d' ')
VERSION_MINOR := $(shell cat $(ROOT)/../../CMakeLists.txt | \
grep ^set\(VERSION_MINOR\ | sed 's/)/ /' | cut -f2 -d' ')
VERSION_PATCH := $(shell cat $(ROOT)/../../CMakeLists.txt | \
grep ^set\(VERSION_PATCH\ | sed 's/)/ /' | cut -f2 -d' ')
################################################################################
# Android Version code
@ -29,17 +37,15 @@ ANDROID_VERSION_CODE = 1
# toolchain config for ARMv7 processors
################################################################################
TARGET_HOST = arm-linux
TARGET_ABI = armeabi-v7a-hard
TARGET_ABI = armeabi-v7a
TARGET_LIBDIR = armeabi-v7a
TARGET_TOOLCHAIN = arm-linux-androideabi-
TARGET_CFLAGS_ADDON = -mfpu=vfpv3-d16 -D_NDK_MATH_NO_SOFTFP=1 \
-mfloat-abi=hard -march=armv7-a
TARGET_CFLAGS_ADDON = -mfloat-abi=softfp -mfpu=vfpv3
TARGET_CXXFLAGS_ADDON = $(TARGET_CFLAGS_ADDON)
TARGET_LDFLAGS_ADDON = -Wl,--no-warn-mismatch -lm_hard
TARGET_ARCH = armv7
CROSS_PREFIX = arm-linux-androideabi-
COMPILER_VERSION = 4.9
HAVE_LEVELDB = 1
HAVE_LEVELDB = 0
################################################################################
# toolchain config for x86 processors
@ -61,7 +67,7 @@ LEVELDB_DIR = $(ROOT)/deps/leveldb/
LEVELDB_LIB = $(LEVELDB_DIR)libleveldb.a
LEVELDB_TIMESTAMP = $(LEVELDB_DIR)/timestamp
LEVELDB_TIMESTAMP_INT = $(ROOT)/deps/leveldb_timestamp
LEVELDB_URL_GIT = https://code.google.com/p/leveldb/
LEVELDB_URL_GIT = https://github.com/google/leveldb
OPENAL_DIR = $(ROOT)/deps/openal-soft/
OPENAL_LIB = $(OPENAL_DIR)libs/$(TARGET_ABI)/libopenal.so
@ -90,7 +96,7 @@ OPENSSL_TIMESTAMP = $(OPENSSL_DIR)timestamp
OPENSSL_TIMESTAMP_INT = $(ROOT)/deps/openssl_timestamp
OPENSSL_URL = http://www.openssl.org/source/openssl-$(OPENSSL_VERSION).tar.gz
CURL_VERSION = 7.44.0
CURL_VERSION = 7.45.0
CURL_DIR = $(ROOT)/deps/curl-$(CURL_VERSION)
CURL_LIB = $(CURL_DIR)/lib/.libs/libcurl.a
CURL_TIMESTAMP = $(CURL_DIR)/timestamp
@ -110,7 +116,14 @@ FREETYPE_TIMESTAMP = $(FREETYPE_DIR)timestamp
FREETYPE_TIMESTAMP_INT = $(ROOT)/deps/freetype_timestamp
FREETYPE_URL_GIT = https://github.com/cdave1/freetype2-android
SQLITE3_FOLDER = sqlite-amalgamation-3081101
ICONV_VERSION = 1.14
ICONV_DIR = $(ROOT)/deps/libiconv/
ICONV_LIB = $(ICONV_DIR)/lib/.libs/libiconv.so
ICONV_TIMESTAMP = $(ICONV_DIR)timestamp
ICONV_TIMESTAMP_INT = $(ROOT)/deps/iconv_timestamp
ICONV_URL_HTTP = http://ftp.gnu.org/pub/gnu/libiconv/libiconv-$(ICONV_VERSION).tar.gz
SQLITE3_FOLDER = sqlite-amalgamation-3090100
SQLITE3_URL = http://www.sqlite.org/2015/$(SQLITE3_FOLDER).zip
-include $(PATHCFGFILE)
@ -133,7 +146,8 @@ endif
$(OPENAL_TIMESTAMP) $(OGG_TIMESTAMP) \
$(IRRLICHT_TIMESTAMP) $(CURL_TIMESTAMP) \
$(OPENSSL_TIMESTAMP) curl_binary \
$(ROOT)/jni/src/android_version.h
$(ROOT)/jni/src/android_version.h \
$(ROOT)/jni/src/android_version_githash.h
debug : $(PATHCFGFILE)
export NDEBUG=; \
@ -204,8 +218,8 @@ $(OPENAL_LIB): $(OPENAL_TIMESTAMP)
echo "changed timestamp for openal detected building..."; \
cd ${OPENAL_DIR}; \
ndk-build NDEBUG=${NDEBUG} NDK_MODULE_PATH=${NDK_MODULE_PATH} \
APP_ABI=${TARGET_ABI} APP_PLATFORM=${APP_PLATFORM} \
TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \
APP_ABI=${TARGET_ABI} TARGET_ARCH_ABI=${TARGET_ABI} \
APP_PLATFORM=${APP_PLATFORM} TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \
TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \
TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" || exit 1; \
touch ${OPENAL_TIMESTAMP}; \
@ -231,6 +245,7 @@ ogg_download :
git clone ${OGG_URL_GIT}|| exit 1; \
cd libvorbis-libogg-android ; \
patch -p1 < ../../libvorbis-libogg-fpu.patch || exit 1; \
sed -i 's-:-?-' jni/Application.mk; \
fi
ogg : $(OGG_LIB)
@ -378,12 +393,6 @@ freetype_download :
git clone ${FREETYPE_URL_GIT} || exit 1; \
fi
$(IRRLICHT_TIMESTAMP) : irrlicht_download
@LAST_MODIF=$$(find ${IRRLICHT_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
touch ${IRRLICHT_TIMESTAMP}; \
fi
freetype : $(FREETYPE_LIB)
$(FREETYPE_LIB) : $(FREETYPE_TIMESTAMP)
@ -416,6 +425,67 @@ $(FREETYPE_LIB) : $(FREETYPE_TIMESTAMP)
clean_freetype :
$(RM) -rf ${FREETYPE_DIR}
$(ICONV_TIMESTAMP) : iconv_download
@LAST_MODIF=$$(find ${ICONV_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
touch ${ICONV_TIMESTAMP}; \
fi
iconv_download :
@if [ ! -d ${ICONV_DIR} ] ; then \
echo "iconv sources missing, downloading..."; \
mkdir -p ${ROOT}/deps; \
cd ${ROOT}/deps; \
wget ${ICONV_URL_HTTP} || exit 1; \
tar -xzf libiconv-${ICONV_VERSION}.tar.gz || exit 1; \
rm libiconv-${ICONV_VERSION}.tar.gz; \
ln -s libiconv-${ICONV_VERSION} libiconv; \
cd ${ICONV_DIR}; \
patch -p1 < ${ROOT}/libiconv_android.patch; \
patch -p1 < ${ROOT}/libiconv_stdio.patch; \
fi
iconv : $(ICONV_LIB)
$(ICONV_LIB) : $(ICONV_TIMESTAMP)
@REFRESH=0; \
if [ ! -e ${ICONV_TIMESTAMP_INT} ] ; then \
REFRESH=1; \
fi; \
if [ ! -e ${ICONV_LIB} ] ; then \
REFRESH=1; \
fi; \
if [ ${ICONV_TIMESTAMP} -nt ${ICONV_TIMESTAMP_INT} ] ; then \
REFRESH=1; \
fi; \
if [ $$REFRESH -ne 0 ] ; then \
mkdir -p ${ICONV_DIR}; \
export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \
echo "changed timestamp for iconv detected building..."; \
cd ${ICONV_DIR}; \
\
export TOOLCHAIN=/tmp/ndk-${TARGET_HOST}-iconv; \
${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \
--toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \
--install-dir=$${TOOLCHAIN}; \
export PATH="$${TOOLCHAIN}/bin:$${PATH}"; \
export CC=${CROSS_PREFIX}gcc; \
export CXX=${CROSS_PREFIX}g++; \
export TARGET_OS=OS_ANDROID_CROSSCOMPILE; \
./configure --host=${TARGET_HOST} || exit 1; \
sed -i 's/LIBICONV_VERSION_INFO) /LIBICONV_VERSION_INFO) -avoid-version /g' lib/Makefile; \
grep "iconv_LDFLAGS" src/Makefile; \
$(MAKE) -s || exit 1; \
touch ${ICONV_TIMESTAMP}; \
touch ${ICONV_TIMESTAMP_INT}; \
rm -rf ${TOOLCHAIN}; \
else \
echo "nothing to be done for iconv"; \
fi
clean_iconv :
$(RM) -rf ${ICONV_DIR}
#Note: Texturehack patch is required for gpu's not supporting color format
# correctly. Known bad GPU:
# -geforce on emulator
@ -433,6 +503,12 @@ irrlicht_download :
patch -p1 < ../../irrlicht-texturehack.patch || exit 1; \
fi
$(IRRLICHT_TIMESTAMP) : irrlicht_download
@LAST_MODIF=$$(find ${IRRLICHT_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
touch ${IRRLICHT_TIMESTAMP}; \
fi
irrlicht : $(IRRLICHT_LIB)
$(IRRLICHT_LIB): $(IRRLICHT_TIMESTAMP) $(FREETYPE_LIB)
@ -529,7 +605,7 @@ clean_curl :
curl_binary:
@if [ ! -d "deps/curl-${CURL_VERSION_BINARY}" ] ; then \
echo "curl sources missing, downloading..."; \
echo "curl binary missing, downloading..."; \
mkdir -p ${ROOT}/deps; \
cd deps; \
wget http://curl.haxx.se/gknw.net/${CURL_VERSION}/dist-android/curl-${CURL_VERSION}-rtmp-ssh2-ssl-zlib-static-bin-android.tar.gz || exit 1;\
@ -557,6 +633,61 @@ gmp_download :
gmp : $(GMP_LIB)
$(GMP_LIB): $(GMP_TIMESTAMP)
@REFRESH=0; \
if [ ! -e ${GMP_TIMESTAMP_INT} ] ; then \
REFRESH=1; \
fi; \
if [ ! -e ${GMP_LIB} ] ; then \
REFRESH=1; \
fi; \
if [ ${GMP_TIMESTAMP} -nt ${GMP_TIMESTAMP_INT} ] ; then \
REFRESH=1; \
fi; \
if [ $$REFRESH -ne 0 ] ; then \
mkdir -p ${GMP_DIR}; \
export PATH="$${PATH}:${SDKFOLDER}/platform-tools:${ANDROID_NDK}"; \
echo "changed timestamp for gmp detected building..."; \
cd deps/gmp-${GMP_VERSION}; \
export CROSS_PREFIX=${CROSS_PREFIX}; \
export TOOLCHAIN=/tmp/ndk-${TARGET_HOST}-gmp; \
${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \
--toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \
--install-dir=$${TOOLCHAIN}; \
export PATH="$${TOOLCHAIN}/bin:$${PATH}"; \
export CC=${CROSS_PREFIX}gcc; \
export CXX=${CROSS_PREFIX}g++; \
export LIBGMP_LDFLAGS="-avoid-version"; \
export LIBGMPXX_LDFLAGS="-avoid-version"; \
./configure --disable-static --host=${TARGET_HOST} --prefix=/usr; \
$(MAKE) install DESTDIR=/${GMP_DIR} || exit 1; \
touch ${GMP_TIMESTAMP}; \
touch ${GMP_TIMESTAMP_INT}; \
$(RM) -rf $${TOOLCHAIN}; \
else \
echo "nothing to be done for gmp"; \
fi
$(GMP_TIMESTAMP) : gmp_download
@LAST_MODIF=$$(find ${GMP_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
touch ${GMP_TIMESTAMP}; \
fi
gmp_download :
@if [ ! -d "${GMP_DIR}" ] ; then \
echo "gmp sources missing, downloading..."; \
mkdir -p ${ROOT}/deps; \
cd deps; \
wget ${GMP_URL_HTTP} || exit 1; \
tar -xjf gmp-${GMP_VERSION}a.tar.bz2 || exit 1; \
rm gmp-${GMP_VERSION}a.tar.bz2; \
ln -s gmp-${GMP_VERSION} gmp; \
fi
gmp : $(GMP_LIB)
$(GMP_LIB): $(GMP_TIMESTAMP)
@REFRESH=0; \
if [ ! -e ${GMP_TIMESTAMP_INT} ] ; then \
@ -610,42 +741,14 @@ clean_sqlite3:
$(ASSETS_TIMESTAMP) : $(IRRLICHT_LIB)
@mkdir -p ${ROOT}/deps; \
LAST_MODIF=$$(find ${ROOT}/../../builtin -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
touch ${ROOT}/../../builtin/timestamp; \
touch ${ASSETS_TIMESTAMP}; \
echo builtin changed $$LAST_MODIF; \
fi; \
LAST_MODIF=$$(find ${ROOT}/../../client -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
touch ${ROOT}/../../client/timestamp; \
touch ${ASSETS_TIMESTAMP}; \
fi; \
LAST_MODIF=$$(find ${ROOT}/../../doc -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
touch ${ROOT}/../../doc/timestamp; \
touch ${ASSETS_TIMESTAMP}; \
fi; \
LAST_MODIF=$$(find ${ROOT}/../../fonts -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
touch ${ROOT}/../../fonts/timestamp; \
touch ${ASSETS_TIMESTAMP}; \
fi; \
LAST_MODIF=$$(find ${ROOT}/../../games -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
touch ${ROOT}/../../games/timestamp; \
touch ${ASSETS_TIMESTAMP}; \
fi; \ \
LAST_MODIF=$$(find ${ROOT}/../../po -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
touch ${ROOT}/../../po/timestamp; \
touch ${ASSETS_TIMESTAMP}; \
fi; \
LAST_MODIF=$$(find ${ROOT}/../../textures -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
touch ${ROOT}/../../textures/timestamp; \
touch ${ASSETS_TIMESTAMP}; \
fi; \
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" "); \
if [ $$(basename $$LAST_MODIF) != "timestamp" ]; then \
touch ${ROOT}/../../${DIRNAME}/timestamp; \
touch ${ASSETS_TIMESTAMP}; \
echo ${DIRNAME} changed $$LAST_MODIF; \
fi; \
done; \
LAST_MODIF=$$(find ${IRRLICHT_DIR}/media -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
touch ${IRRLICHT_DIR}/media/timestamp; \
@ -676,25 +779,25 @@ assets : $(ASSETS_TIMESTAMP)
if [ $$REFRESH -ne 0 ] ; then \
echo "assets changed, refreshing..."; \
$(MAKE) clean_assets; \
mkdir -p ${ROOT}/assets/MultiCraft; \
echo ${VER_TEXT} > ${ROOT}/assets/MultiCraft/ver.txt; \
cp ${ROOT}/../../multicraft.conf.example ${ROOT}/assets/MultiCraft; \
cp ${ROOT}/../../README.md ${ROOT}/assets/MultiCraft; \
cp -r ${ROOT}/../../builtin ${ROOT}/assets/MultiCraft; \
cp -r ${ROOT}/../../client ${ROOT}/assets/MultiCraft; \
#cp -r ${ROOT}/../../doc ${ROOT}/assets/MultiCraft; \
cp -r ${ROOT}/../../fonts ${ROOT}/assets/MultiCraft; \
mkdir ${ROOT}/assets/MultiCraft/games; \
for game in ${GAMES_TO_COPY}; \
do \
cp -r ${ROOT}/../../games/$$game ${ROOT}/assets/MultiCraft/games/; \
mkdir -p ${ROOT}/assets/Minetest; \
cp ${ROOT}/../../minetest.conf.example ${ROOT}/assets/Minetest; \
cp ${ROOT}/../../README.txt ${ROOT}/assets/Minetest; \
cp -r ${ROOT}/../../builtin ${ROOT}/assets/Minetest; \
cp -r ${ROOT}/../../client ${ROOT}/assets/Minetest; \
cp -r ${ROOT}/../../doc ${ROOT}/assets/Minetest; \
cp -r ${ROOT}/../../fonts ${ROOT}/assets/Minetest; \
mkdir ${ROOT}/assets/Minetest/games; \
for game in ${GAMES_TO_COPY}; do \
cp -r ${ROOT}/../../games/$$game ${ROOT}/assets/Minetest/games/; \
done; \
cp -r ${ROOT}/../../po ${ROOT}/assets/MultiCraft; \
cp -r ${ROOT}/../../textures ${ROOT}/assets/MultiCraft; \
mkdir -p ${ROOT}/assets/MultiCraft/media; \
cp -r ${IRRLICHT_DIR}/media/Shaders ${ROOT}/assets/MultiCraft/media; \
echo "excluding PO files"; \
rm -r ${ROOT}/assets/MultiCraft/po; \
mkdir ${ROOT}/assets/Minetest/mods; \
for mod in ${MODS_TO_COPY}; do \
cp -r ${ROOT}/../../mods/$$mod ${ROOT}/assets/Minetest/mods/; \
done; \
cp -r ${ROOT}/../../po ${ROOT}/assets/Minetest; \
cp -r ${ROOT}/../../textures ${ROOT}/assets/Minetest; \
mkdir -p ${ROOT}/assets/Minetest/media; \
cp -r ${IRRLICHT_DIR}/media/Shaders ${ROOT}/assets/Minetest/media; \
cd ${ROOT}/assets || exit 1; \
find . -name "timestamp" -exec rm {} \; ; \
find . -name "*.blend" -exec rm {} \; ; \
@ -719,9 +822,9 @@ assets : $(ASSETS_TIMESTAMP)
clean_assets :
@$(RM) -r assets
apk: $(PATHCFGFILE) assets $(IRRLICHT_LIB) $(CURL_LIB) $(GMP_LIB) $(LEVELDB_TARGET) \
apk: $(PATHCFGFILE) assets $(ICONV_LIB) $(IRRLICHT_LIB) $(CURL_LIB) $(GMP_LIB) $(LEVELDB_TARGET) \
$(OPENAL_LIB) $(OGG_LIB) prep_srcdir $(ROOT)/jni/src/android_version.h \
sqlite3_download
$(ROOT)/jni/src/android_version_githash.h sqlite3_download
@export NDEBUG=$$NDEBUG; $(MAKE) manifest; \
export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \
export ANDROID_HOME=${SDKFOLDER}; \
@ -735,19 +838,20 @@ apk: $(PATHCFGFILE) assets $(IRRLICHT_LIB) $(CURL_LIB) $(GMP_LIB) $(LEVELDB_TARG
TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" && \
ant $$BUILD_TYPE && \
echo "++ Success!" && \
echo "APK: bin/MultiCraft-$$BUILD_TYPE.apk" && \
echo "APK: bin/MultiCraft-$$BUILD_TYPE.apk" && \
echo "You can install it with \`adb install -r bin/MultiCraft-$$BUILD_TYPE.apk\`"
prep_srcdir :
@rm ${ROOT}/jni/src; \
ln -s ${ROOT}/../../src ${ROOT}/jni/src
@if [ ! -e ${ROOT}/jni/src ]; then \
ln -s ${ROOT}/../../src ${ROOT}/jni/src; \
fi
clean_apk : manifest
@export PATH=$$PATH:${SDKFOLDER}platform-tools:${ANDROID_NDK}; \
export ANDROID_HOME=${SDKFOLDER}; \
ant clean
install_debug :
install_debug :
@export PATH=$$PATH:${SDKFOLDER}platform-tools:${ANDROID_NDK}; \
adb install -r ${ROOT}/bin/MultiCraft-debug.apk
@ -761,43 +865,52 @@ envpaths :
clean_all :
@$(MAKE) clean_apk; \
$(MAKE) clean_assets clean_irrlicht clean_leveldb clean_curl clean_openssl \
$(MAKE) clean_assets clean_iconv clean_irrlicht clean_leveldb clean_curl clean_openssl \
clean_openal clean_ogg clean_gmp clean_manifest; \
sleep 1; \
$(RM) -r gen libs obj deps bin Debug and_env
$(ROOT)/jni/src/android_version.h :
@echo "#ifndef ANDROID_MT_VERSION_H" \
>${ROOT}/jni/src/android_version.h; \
echo "#define ANDROID_MT_VERSION_H" \
>> ${ROOT}/jni/src/android_version.h; \
echo "#define VERSION_MAJOR $$(cat ${ROOT}/../../CMakeLists.txt | \
grep ^set\(VERSION_MAJOR\ | sed 's/)/ /' | awk '{print $$2;}')" \
>> ${ROOT}/jni/src/android_version.h; \
echo "#define VERSION_MINOR $$(cat ${ROOT}/../../CMakeLists.txt | \
grep ^set\(VERSION_MINOR\ | sed 's/)/ /' | awk '{print $$2;}')" \
>> ${ROOT}/jni/src/android_version.h; \
echo "#define VERSION_PATCH $$(cat ${ROOT}/../../CMakeLists.txt | \
grep ^set\(VERSION_PATCH\ | sed 's/)/ /' | awk '{print $$2;}')" \
>> ${ROOT}/jni/src/android_version.h; \
$(ROOT)/jni/src/android_version_githash.h : prep_srcdir
@export VERSION_FILE=${ROOT}/jni/src/android_version_githash.h; \
export VERSION_FILE_NEW=$${VERSION_FILE}.new; \
{ \
echo "#ifndef ANDROID_MT_VERSION_GITHASH_H"; \
echo "#define ANDROID_MT_VERSION_GITHASH_H"; \
export GITHASH=$$(git rev-parse --short=8 HEAD); \
export GITTAG=$$(git describe --abbrev=0 --tags); \
echo "#define VERSION_GITHASH \"1.0.1\"" \
>> ${ROOT}/jni/src/android_version.h; \
export VERSION_STR="${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}"; \
echo "#define VERSION_GITHASH \"$$VERSION_STR-$$GITHASH-Android\""; \
echo "#endif"; \
} > "$${VERSION_FILE_NEW}"; \
if ! cmp -s $${VERSION_FILE} $${VERSION_FILE_NEW}; then \
echo "android_version_githash.h changed, updating..."; \
mv "$${VERSION_FILE_NEW}" "$${VERSION_FILE}"; \
else \
rm "$${VERSION_FILE_NEW}"; \
fi
$(ROOT)/jni/src/android_version.h : prep_srcdir
@export VERSION_FILE=${ROOT}/jni/src/android_version.h; \
export VERSION_FILE_NEW=$${VERSION_FILE}.new; \
{ \
echo "#ifndef ANDROID_MT_VERSION_H"; \
echo "#define ANDROID_MT_VERSION_H"; \
echo "#define VERSION_MAJOR ${VERSION_MAJOR}"; \
echo "#define VERSION_MINOR ${VERSION_MINOR}"; \
echo "#define VERSION_PATCH ${VERSION_PATCH}"; \
echo "#define VERSION_STRING STR(VERSION_MAJOR)\".\"STR(VERSION_MINOR)\
\".\"STR(VERSION_PATCH)" \
>> ${ROOT}/jni/src/android_version.h; \
echo "#endif" \
>> ${ROOT}/jni/src/android_version.h;
\".\"STR(VERSION_PATCH)"; \
echo "#endif"; \
} > $${VERSION_FILE_NEW}; \
if ! cmp -s $${VERSION_FILE} $${VERSION_FILE_NEW}; then \
echo "android_version.h changed, updating..."; \
mv "$${VERSION_FILE_NEW}" "$${VERSION_FILE}"; \
else \
rm "$${VERSION_FILE_NEW}"; \
fi
manifest :
@VERS_MAJOR=$$(cat ${ROOT}/../../CMakeLists.txt | \
grep ^set\(VERSION_MAJOR\ | sed 's/)/ /' | awk '{print $$2;}'); \
VERS_MINOR=$$(cat ${ROOT}/../../CMakeLists.txt | \
grep ^set\(VERSION_MINOR\ | sed 's/)/ /' | awk '{print $$2;}'); \
VERS_PATCH=$$(cat ${ROOT}/../../CMakeLists.txt | \
grep ^set\(VERSION_PATCH\ | sed 's/)/ /' | awk '{print $$2;}'); \
BASE_VERSION="$$VERS_MAJOR.$$VERS_MINOR.$$VERS_PATCH"; \
@BASE_VERSION="${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}"; \
if [ "${NDEBUG}x" != "x" ] ; then \
DBG=''; \
DBG_FLAG="android:debuggable=\"false\""; \
@ -806,8 +919,8 @@ manifest :
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 "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

View File

@ -24,6 +24,11 @@ LOCAL_MODULE := freetype
LOCAL_SRC_FILES := deps/freetype2-android/Android/obj/local/$(TARGET_ARCH_ABI)/libfreetype2-static.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := iconv
LOCAL_SRC_FILES := deps/libiconv/lib/.libs/libiconv.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := openal
LOCAL_SRC_FILES := deps/openal-soft/libs/$(TARGET_LIBDIR)/libopenal.so
@ -97,6 +102,7 @@ LOCAL_C_INCLUDES := \
jni/src/json \
jni/src/cguittfont \
deps/irrlicht/include \
deps/libiconv/include \
deps/freetype2-android/include \
deps/curl/include \
deps/openal-soft/jni/OpenAL/include \
@ -106,6 +112,7 @@ LOCAL_C_INCLUDES := \
deps/sqlite/
LOCAL_SRC_FILES := \
jni/src/areastore.cpp \
jni/src/ban.cpp \
jni/src/camera.cpp \
jni/src/cavegen.cpp \
@ -153,6 +160,7 @@ LOCAL_SRC_FILES := \
jni/src/httpfetch.cpp \
jni/src/hud.cpp \
jni/src/imagefilters.cpp \
jni/src/intlGUIEditBox.cpp \
jni/src/inventory.cpp \
jni/src/inventorymanager.cpp \
jni/src/itemdef.cpp \
@ -165,6 +173,7 @@ LOCAL_SRC_FILES := \
jni/src/mapblock.cpp \
jni/src/mapblock_mesh.cpp \
jni/src/mapgen.cpp \
jni/src/mapgen_fractal.cpp \
jni/src/mapgen_singlenode.cpp \
jni/src/mapgen_v5.cpp \
jni/src/mapgen_v6.cpp \
@ -176,6 +185,7 @@ LOCAL_SRC_FILES := \
jni/src/mg_decoration.cpp \
jni/src/mg_ore.cpp \
jni/src/mg_schematic.cpp \
jni/src/minimap.cpp \
jni/src/mods.cpp \
jni/src/nameidmapping.cpp \
jni/src/nodedef.cpp \
@ -275,6 +285,7 @@ LOCAL_SRC_FILES += \
jni/src/script/cpp_api/s_player.cpp \
jni/src/script/cpp_api/s_security.cpp \
jni/src/script/cpp_api/s_server.cpp \
jni/src/script/lua_api/l_areastore.cpp \
jni/src/script/lua_api/l_base.cpp \
jni/src/script/lua_api/l_craft.cpp \
jni/src/script/lua_api/l_env.cpp \
@ -332,20 +343,19 @@ LOCAL_SRC_FILES += \
jni/src/lua/src/lzio.c \
jni/src/lua/src/print.c
# sqlite
# SQLite3
LOCAL_SRC_FILES += deps/sqlite/sqlite3.c
# jthread
LOCAL_SRC_FILES += \
jni/src/jthread/pthread/jevent.cpp \
jni/src/jthread/pthread/jmutex.cpp \
jni/src/jthread/pthread/jsemaphore.cpp \
jni/src/jthread/pthread/jthread.cpp
# Threading
LOCAL_SRC_FILES += \
jni/src/threading/mutex.cpp \
jni/src/threading/semaphore.cpp \
jni/src/threading/thread.cpp
# json
# JSONCPP
LOCAL_SRC_FILES += jni/src/json/jsoncpp.cpp
LOCAL_SHARED_LIBRARIES := openal ogg vorbis gmp
LOCAL_SHARED_LIBRARIES := iconv openal ogg vorbis gmp
LOCAL_STATIC_LIBRARIES := Irrlicht freetype curl ssl crypto android_native_app_glue $(PROFILER_LIBS)
ifeq ($(HAVE_LEVELDB), 1)

View File

@ -0,0 +1,39 @@
--- a/libcharset/lib/localcharset.c 2015-06-10 11:55:25.933870724 +0200
+++ b/libcharset/lib/localcharset.c 2015-06-10 11:55:39.578063493 +0200
@@ -47,7 +47,7 @@
#if !defined WIN32_NATIVE
# include <unistd.h>
-# if HAVE_LANGINFO_CODESET
+# if HAVE_LANGINFO_CODESET && !(defined __ANDROID__)
# include <langinfo.h>
# else
# if 0 /* see comment below */
@@ -124,7 +124,7 @@ get_charset_aliases (void)
cp = charset_aliases;
if (cp == NULL)
{
-#if !(defined DARWIN7 || defined VMS || defined WIN32_NATIVE || defined __CYGWIN__)
+#if !(defined DARWIN7 || defined VMS || defined WIN32_NATIVE || defined __CYGWIN__ || defined __ANDROID__)
const char *dir;
const char *base = "charset.alias";
char *file_name;
@@ -338,6 +338,9 @@ get_charset_aliases (void)
"CP54936" "\0" "GB18030" "\0"
"CP65001" "\0" "UTF-8" "\0";
# endif
+# if defined __ANDROID__
+ cp = "*" "\0" "UTF-8" "\0";
+# endif
#endif
charset_aliases = cp;
@@ -361,7 +364,7 @@ locale_charset (void)
const char *codeset;
const char *aliases;
-#if !(defined WIN32_NATIVE || defined OS2)
+#if !(defined WIN32_NATIVE || defined OS2 || defined __ANDROID__)
# if HAVE_LANGINFO_CODESET

View File

@ -0,0 +1,13 @@
--- a/srclib/stdio.in.h 2011-08-07 15:42:06.000000000 +0200
+++ b/srclib/stdio.in.h 2015-06-10 09:27:58.129056262 +0200
@@ -695,8 +696,9 @@ _GL_CXXALIASWARN (gets);
/* It is very rare that the developer ever has full control of stdin,
so any use of gets warrants an unconditional warning. Assume it is
always declared, since it is required by C89. */
-_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");
+/*_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");*/
+#define gets(a) fgets( a, sizeof(*(a)), stdin)
#endif
#if @GNULIB_OBSTACK_PRINTF@ || @GNULIB_OBSTACK_PRINTF_POSIX@

Binary file not shown.

View File

@ -48,6 +48,8 @@ public class MCNativeActivity extends NativeActivity {
public static native void putMessageBoxResult(String text);
/* ugly code to workaround putMessageBoxResult not beeing found */
public int getDialogState() {
return m_MessagReturnCode;
}
@ -69,6 +71,21 @@ public class MCNativeActivity extends NativeActivity {
return getResources().getDisplayMetrics().heightPixels;
}
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
if (requestCode == 101) {
if (resultCode == RESULT_OK) {
String text = data.getStringExtra("text");
m_MessagReturnCode = 0;
m_MessageReturnValue = text;
}
else {
m_MessagReturnCode = 1;
}
}
}
static {
System.loadLibrary("openal");
System.loadLibrary("ogg");
@ -76,10 +93,13 @@ public class MCNativeActivity extends NativeActivity {
System.loadLibrary("ssl");
System.loadLibrary("crypto");
System.loadLibrary("gmp");
System.loadLibrary("iconv");
// We don't have to load libminetest.so ourselves,
// but if we do, we get nicer logcat errors when
// loading fails.
System.loadLibrary("minetest");
}
}
private int m_MessagReturnCode;
private String m_MessageReturnValue;
}

View File

@ -3,7 +3,7 @@
--
--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
--the Free Software Foundation; either version 3.0 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,

View File

@ -1,5 +1,10 @@
-- Minetest: builtin/misc_helpers.lua
--------------------------------------------------------------------------------
-- Localize functions to avoid table lookups (better performance).
local table_insert = table.insert
local string_sub, string_find = string.sub, string.find
--------------------------------------------------------------------------------
function basic_dump(o)
local tp = type(o)
@ -89,13 +94,13 @@ function dump2(o, name, dumped)
-- the form _G["table: 0xFFFFFFF"]
keyStr = string.format("_G[%q]", tostring(k))
-- Dump key table
table.insert(t, dump2(k, keyStr, dumped))
table_insert(t, dump2(k, keyStr, dumped))
end
else
keyStr = basic_dump(k)
end
local vname = string.format("%s[%s]", name, keyStr)
table.insert(t, dump2(v, vname, dumped))
table_insert(t, dump2(v, vname, dumped))
end
return string.format("%s = {}\n%s", name, table.concat(t))
end
@ -130,7 +135,7 @@ function dump(o, indent, nested, level)
local t = {}
local dumped_indexes = {}
for i, v in ipairs(o) do
table.insert(t, dump(v, indent, nested, level + 1))
table_insert(t, dump(v, indent, nested, level + 1))
dumped_indexes[i] = true
end
for k, v in pairs(o) do
@ -139,7 +144,7 @@ function dump(o, indent, nested, level)
k = "["..dump(k, indent, nested, level + 1).."]"
end
v = dump(v, indent, nested, level + 1)
table.insert(t, k.." = "..v)
table_insert(t, k.." = "..v)
end
end
nested[o] = nil
@ -155,9 +160,6 @@ function dump(o, indent, nested, level)
end
--------------------------------------------------------------------------------
-- Localize functions to avoid table lookups (better performance).
local table_insert = table.insert
local str_sub, str_find = string.sub, string.find
function string.split(str, delim, include_empty, max_splits, sep_is_pattern)
delim = delim or ","
max_splits = max_splits or -1
@ -166,13 +168,13 @@ function string.split(str, delim, include_empty, max_splits, sep_is_pattern)
local plain = not sep_is_pattern
max_splits = max_splits + 1
repeat
local np, npe = str_find(str, delim, pos, plain)
local np, npe = string_find(str, delim, pos, plain)
np, npe = (np or (len+1)), (npe or (len+1))
if (not np) or (max_splits == 1) then
np = len + 1
npe = np
end
local s = str_sub(str, pos, np - 1)
local s = string_sub(str, pos, np - 1)
if include_empty or (s ~= "") then
max_splits = max_splits - 1
table_insert(items, s)
@ -182,10 +184,23 @@ function string.split(str, delim, include_empty, max_splits, sep_is_pattern)
return items
end
--------------------------------------------------------------------------------
function table.indexof(list, val)
for i = 1, #list do
if list[i] == val then
return i
end
end
return -1
end
assert(table.indexof({"foo", "bar"}, "foo") == 1)
assert(table.indexof({"foo", "bar"}, "baz") == -1)
--------------------------------------------------------------------------------
function file_exists(filename)
local f = io.open(filename, "r")
if f==nil then
if f == nil then
return false
else
f:close()
@ -298,8 +313,8 @@ function core.splittext(text,charlimit)
local current_idx = 1
local start,stop = string.find(text," ",current_idx)
local nl_start,nl_stop = string.find(text,"\n",current_idx)
local start,stop = string_find(text, " ", current_idx)
local nl_start,nl_stop = string_find(text, "\n", current_idx)
local gotnewline = false
if nl_start ~= nil and (start == nil or nl_start < start) then
start = nl_start
@ -309,7 +324,7 @@ function core.splittext(text,charlimit)
local last_line = ""
while start ~= nil do
if string.len(last_line) + (stop-start) > charlimit then
table.insert(retval,last_line)
table_insert(retval, last_line)
last_line = ""
end
@ -317,17 +332,17 @@ function core.splittext(text,charlimit)
last_line = last_line .. " "
end
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
table.insert(retval,last_line)
table_insert(retval, last_line)
last_line = ""
gotnewline = false
end
current_idx = stop+1
start,stop = string.find(text," ",current_idx)
nl_start,nl_stop = string.find(text,"\n",current_idx)
start,stop = string_find(text, " ", current_idx)
nl_start,nl_stop = string_find(text, "\n", current_idx)
if nl_start ~= nil and (start == nil or nl_start < start) then
start = nl_start
@ -338,11 +353,11 @@ function core.splittext(text,charlimit)
--add last part of text
if string.len(last_line) + (string.len(text) - current_idx) > charlimit then
table.insert(retval,last_line)
table.insert(retval,string.sub(text,current_idx))
table_insert(retval, last_line)
table_insert(retval, string_sub(text, current_idx))
else
last_line = last_line .. " " .. string.sub(text,current_idx)
table.insert(retval,last_line)
last_line = last_line .. " " .. string_sub(text, current_idx)
table_insert(retval, last_line)
end
return retval
@ -539,6 +554,36 @@ assert(core.string_to_pos("10.0, 5, -2").x == 10)
assert(core.string_to_pos("( 10.0, 5, -2)").z == -2)
assert(core.string_to_pos("asd, 5, -2)") == nil)
--------------------------------------------------------------------------------
function core.string_to_area(value)
local p1, p2 = unpack(value:split(") ("))
if p1 == nil or p2 == nil then
return nil
end
p1 = core.string_to_pos(p1 .. ")")
p2 = core.string_to_pos("(" .. p2)
if p1 == nil or p2 == nil then
return nil
end
return p1, p2
end
local function test_string_to_area()
local p1, p2 = core.string_to_area("(10.0, 5, -2) ( 30.2, 4, -12.53)")
assert(p1.x == 10.0 and p1.y == 5 and p1.z == -2)
assert(p2.x == 30.2 and p2.y == 4 and p2.z == -12.53)
p1, p2 = core.string_to_area("(10.0, 5, -2 30.2, 4, -12.53")
assert(p1 == nil and p2 == nil)
p1, p2 = core.string_to_area("(10.0, 5,) -2 fgdf2, 4, -12.53")
assert(p1 == nil and p2 == nil)
end
test_string_to_area()
--------------------------------------------------------------------------------
function table.copy(t, seen)
local n = {}

View File

@ -9,11 +9,6 @@ function core.global_exists(name)
end
local function warn(message)
print(os.date("%H:%M:%S: WARNING: ")..message)
end
local meta = {}
local declared = {}
-- Key is source file, line, and variable name; seperated by NULs
@ -27,7 +22,7 @@ function meta:__newindex(name, value)
info.currentline, name)
if not warned[warn_key] and info.what ~= "main" and
info.what ~= "C" then
warn(("Assignment to undeclared "..
core.log("warning", ("Assignment to undeclared "..
"global %q inside a function at %s.")
:format(name, desc))
warned[warn_key] = true
@ -35,9 +30,8 @@ function meta:__newindex(name, value)
declared[name] = true
end
-- Ignore mod namespaces
if WARN_INIT and (not core.get_current_modname or
name ~= core.get_current_modname()) then
warn(("Global variable %q created at %s.")
if WARN_INIT and name ~= core.get_current_modname() then
core.log("warning", ("Global variable %q created at %s.")
:format(name, desc))
end
rawset(self, name, value)
@ -48,7 +42,7 @@ function meta:__index(name)
local info = debug.getinfo(2, "Sl")
local warn_key = ("%s\0%d\0%s"):format(info.source, info.currentline, name)
if not declared[name] and not warned[warn_key] and info.what ~= "C" then
warn(("Undeclared global variable %q accessed at %s:%s")
core.log("warning", ("Undeclared global variable %q accessed at %s:%s")
:format(name, info.short_src, info.currentline))
warned[warn_key] = true
end

View File

@ -1,18 +1,18 @@
--Minetest
--Copyright (C) 2014 sapier
--
--self program is free software; you can redistribute it and/or modify
--This program is free software; you can redistribute it and/or modify
--it under the terms of the GNU Lesser General Public License as published by
--the Free Software Foundation; either version 2.1 of the License, or
--the Free Software Foundation; either version 3.0 of the License, or
--(at your option) any later version.
--
--self program is distributed in the hope that it will be useful,
--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 self program; if not, write to the Free Software Foundation, Inc.,
--with this program; if not, write to the Free Software Foundation, Inc.,
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
@ -24,11 +24,11 @@ local function buttonbar_formspec(self)
local formspec = string.format("box[%f,%f;%f,%f;%s]",
self.pos.x,self.pos.y ,self.size.x,self.size.y,self.bgcolor)
for i=self.startbutton,#self.buttons,1 do
local btn_name = self.buttons[i].name
local btn_pos = {}
if self.orientation == "horizontal" then
btn_pos.x = self.pos.x + --base pos
(i - self.startbutton) * self.btn_size + --button offset
@ -36,7 +36,7 @@ local function buttonbar_formspec(self)
else
btn_pos.x = self.pos.x + (self.btn_size * 0.05)
end
if self.orientation == "vertical" then
btn_pos.y = self.pos.y + --base pos
(i - self.startbutton) * self.btn_size + --button offset
@ -44,18 +44,18 @@ local function buttonbar_formspec(self)
else
btn_pos.y = self.pos.y + (self.btn_size * 0.05)
end
if (self.orientation == "vertical" and
(btn_pos.y + self.btn_size <= self.pos.y + self.size.y)) or
(self.orientation == "horizontal" and
(btn_pos.x + self.btn_size <= self.pos.x + self.size.x)) then
local borders="true"
if self.buttons[i].image ~= nil then
borders="false"
end
formspec = formspec ..
string.format("image_button[%f,%f;%f,%f;%s;%s;%s;true;%s]tooltip[%s;%s]",
btn_pos.x, btn_pos.y, self.btn_size, self.btn_size,
@ -75,7 +75,7 @@ local function buttonbar_formspec(self)
btn_dec_pos.y = self.pos.y + (self.btn_size * 0.05)
local btn_inc_pos = {}
local btn_size = {}
if self.orientation == "horizontal" then
btn_size.x = 0.5
btn_size.y = self.btn_size
@ -87,25 +87,25 @@ local function buttonbar_formspec(self)
btn_inc_pos.x = self.pos.x + (self.btn_size * 0.05)
btn_inc_pos.y = self.pos.y + self.size.y - 0.5
end
local text_dec = "<"
local text_inc = ">"
if self.orientation == "vertical" then
text_dec = "^"
text_inc = "v"
end
formspec = formspec ..
string.format("image_button[%f,%f;%f,%f;;btnbar_dec_%s;%s;true;true]",
btn_dec_pos.x, btn_dec_pos.y, btn_size.x, btn_size.y,
self.name, text_dec)
formspec = formspec ..
string.format("image_button[%f,%f;%f,%f;;btnbar_inc_%s;%s;true;true]",
btn_inc_pos.x, btn_inc_pos.y, btn_size.x, btn_size.y,
self.name, text_inc)
end
return formspec
end
@ -113,16 +113,16 @@ local function buttonbar_buttonhandler(self, fields)
if fields["btnbar_inc_" .. self.name] ~= nil and
self.startbutton < #self.buttons then
self.startbutton = self.startbutton + 1
return true
end
if fields["btnbar_dec_" .. self.name] ~= nil and self.startbutton > 1 then
self.startbutton = self.startbutton - 1
return true
end
for i=1,#self.buttons,1 do
if fields[self.buttons[i].name] ~= nil then
return self.userbuttonhandler(fields)
@ -134,35 +134,35 @@ local buttonbar_metatable = {
handle_buttons = buttonbar_buttonhandler,
handle_events = function(self, event) end,
get_formspec = buttonbar_formspec,
hide = function(self) self.hidden = true end,
show = function(self) self.hidden = false end,
delete = function(self) ui.delete(self) end,
add_button = function(self, name, caption, image, tooltip)
if caption == nil then caption = "" end
if image == nil then image = "" end
if tooltip == nil then tooltip = "" end
table.insert(self.buttons,{ name=name, caption=caption, image=image, tooltip=tooltip})
if self.orientation == "horizontal" then
if ( (self.btn_size * #self.buttons) + (self.btn_size * 0.05 *2)
> self.size.x ) then
self.btn_initial_offset = self.btn_size * 0.05 + 0.5
self.have_move_buttons = true
end
else
if ((self.btn_size * #self.buttons) + (self.btn_size * 0.05 *2)
> self.size.y ) then
self.btn_initial_offset = self.btn_size * 0.05 + 0.5
self.have_move_buttons = true
end
end
end,
set_bgparams = function(self, bgcolor)
if (type(bgcolor) == "string") then
self.bgcolor = bgcolor
@ -189,20 +189,20 @@ function buttonbar_create(name, cbf_buttonhandler, pos, orientation, size)
self.startbutton = 1
self.have_move_buttons = false
self.hidden = false
if self.orientation == "horizontal" then
self.btn_size = self.size.y
else
self.btn_size = self.size.x
end
if (self.btn_initial_offset == nil) then
self.btn_initial_offset = self.btn_size * 0.05
end
self.userbuttonhandler = cbf_buttonhandler
self.buttons = {}
setmetatable(self,buttonbar_metatable)
ui.add(self)

View File

@ -1,18 +1,18 @@
--Minetest
--Copyright (C) 2014 sapier
--
--self program is free software; you can redistribute it and/or modify
--This program is free software; you can redistribute it and/or modify
--it under the terms of the GNU Lesser General Public License as published by
--the Free Software Foundation; either version 2.1 of the License, or
--the Free Software Foundation; either version 3.0 of the License, or
--(at your option) any later version.
--
--self program is distributed in the hope that it will be useful,
--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 self program; if not, write to the Free Software Foundation, Inc.,
--with this program; if not, write to the Free Software Foundation, Inc.,
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
local function dialog_event_handler(self,event)
@ -61,7 +61,7 @@ function dialog_create(name,get_formspec,buttonhandler,eventhandler)
self.formspec = get_formspec
self.buttonhandler = buttonhandler
self.user_eventhandler = eventhandler
setmetatable(self,dialog_metatable)
ui.add(self)

View File

@ -1,18 +1,18 @@
--Minetest
--Copyright (C) 2014 sapier
--
--self program is free software; you can redistribute it and/or modify
--This program is free software; you can redistribute it and/or modify
--it under the terms of the GNU Lesser General Public License as published by
--the Free Software Foundation; either version 2.1 of the License, or
--the Free Software Foundation; either version 3.0 of the License, or
--(at your option) any later version.
--
--self program is distributed in the hope that it will be useful,
--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 self program; if not, write to the Free Software Foundation, Inc.,
--with this program; if not, write to the Free Software Foundation, Inc.,
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
@ -61,7 +61,7 @@ local function get_formspec(self)
local formspec = ""
if not self.hidden and (self.parent == nil or not self.parent.hidden) then
if self.parent == nil then
local tsize = self.tablist[self.last_tab_index].tabsize or
{width=self.width, height=self.height}
@ -87,11 +87,11 @@ local function handle_buttons(self,fields)
if self.hidden then
return false
end
if self:handle_tab_buttons(fields) then
return true
end
if self.glb_btn_handler ~= nil and
self.glb_btn_handler(self,fields) then
return true
@ -112,16 +112,16 @@ end
--------------------------------------------------------------------------------
local function handle_events(self,event)
if self.hidden then
return false
end
if self.glb_evt_handler ~= nil and
self.glb_evt_handler(self,event) then
return true
end
if self.tablist[self.last_tab_index].evt_handler ~= nil then
return
self.tablist[self.last_tab_index].evt_handler(
@ -131,7 +131,7 @@ local function handle_events(self,event)
self.tablist[self.last_tab_index].tabdata
)
end
return false
end
@ -160,16 +160,16 @@ local function switch_to_tab(self, index)
self.tablist[self.last_tab_index].on_change("LEAVE",
self.current_tab, self.tablist[index].name)
end
--update tabview data
self.last_tab_index = index
local old_tab = self.current_tab
self.current_tab = self.tablist[index].name
if (self.autosave_tab) then
core.setting_set(self.name .. "_LAST",self.current_tab)
end
-- call for tab to enter
if self.tablist[index].on_change ~= nil then
self.tablist[index].on_change("ENTER",
@ -197,14 +197,14 @@ local function set_tab_by_name(self, name)
return true
end
end
return false
end
--------------------------------------------------------------------------------
local function hide_tabview(self)
self.hidden=true
--call on_change as we're not gonna show self tab any longer
if self.tablist[self.last_tab_index].on_change ~= nil then
self.tablist[self.last_tab_index].on_change("LEAVE",
@ -215,7 +215,7 @@ end
--------------------------------------------------------------------------------
local function show_tabview(self)
self.hidden=false
-- call for tab to enter
if self.tablist[self.last_tab_index].on_change ~= nil then
self.tablist[self.last_tab_index].on_change("ENTER",
@ -265,7 +265,7 @@ function tabview_create(name, size, tabheaderpos)
self.current_tab = nil
self.last_tab_index = 1
self.tablist = {}
self.autosave_tab = false
ui.add(self)

View File

@ -1,18 +1,18 @@
--Minetest
--Copyright (C) 2014 sapier
--
--self program is free software; you can redistribute it and/or modify
--This program is free software; you can redistribute it and/or modify
--it under the terms of the GNU Lesser General Public License as published by
--the Free Software Foundation; either version 2.1 of the License, or
--the Free Software Foundation; either version 3.0 of the License, or
--(at your option) any later version.
--
--self program is distributed in the hope that it will be useful,
--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 self program; if not, write to the Free Software Foundation, Inc.,
--with this program; if not, write to the Free Software Foundation, Inc.,
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ui = {}
@ -23,7 +23,7 @@ ui.default = nil
function ui.add(child)
--TODO check child
ui.childlist[child.name] = child
return child.name
end
@ -33,7 +33,7 @@ function ui.delete(child)
if ui.childlist[child.name] == nil then
return false
end
ui.childlist[child.name] = nil
return true
end
@ -54,17 +54,52 @@ end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local function wordwrap_quickhack(str)
local res = ""
local ar = str:split("\n")
for i = 1, #ar do
local text = ar[i]
-- Hack to add word wrapping.
-- TODO: Add engine support for wrapping in formspecs
while #text > 80 do
if res ~= "" then
res = res .. ","
end
res = res .. core.formspec_escape(string.sub(text, 1, 79))
text = string.sub(text, 80, #text)
end
if res ~= "" then
res = res .. ","
end
res = res .. core.formspec_escape(text)
end
return res
end
--------------------------------------------------------------------------------
function ui.update()
local formspec = ""
-- handle errors
if gamedata ~= nil and gamedata.errormessage ~= nil then
formspec = "size[12,3.2]" ..
"textarea[1,1;10,2;;ERROR: " ..
core.formspec_escape(gamedata.errormessage) ..
";]"..
"button[4.5,2.5;3,0.5;btn_error_confirm;" .. fgettext("Ok") .. "]"
if gamedata ~= nil and gamedata.reconnect_requested then
formspec = wordwrap_quickhack(gamedata.errormessage or "")
formspec = "size[12,5]" ..
"label[0.5,0;" .. fgettext("The server has requested a reconnect:") ..
"]textlist[0.2,0.8;11.5,3.5;;" .. formspec ..
"]button[6,4.6;3,0.5;btn_reconnect_no;" .. fgettext("Main menu") .. "]" ..
"button[3,4.6;3,0.5;btn_reconnect_yes;" .. fgettext("Reconnect") .. "]"
elseif gamedata ~= nil and gamedata.errormessage ~= nil then
formspec = wordwrap_quickhack(gamedata.errormessage)
local error_title
if string.find(gamedata.errormessage, "ModError") then
error_title = fgettext("An error occured in a Lua script, such as a mod:")
else
error_title = fgettext("An error occured:")
end
formspec = "size[12,5]" ..
"label[0.5,0;" .. error_title ..
"]textlist[0.2,0.8;11.5,3.5;;" .. formspec ..
"]button[4.5,4.6;3,0.5;btn_error_confirm;" .. fgettext("Ok") .. "]"
else
local active_toplevel_ui_elements = 0
for key,value in pairs(ui.childlist) do
@ -77,7 +112,7 @@ function ui.update()
end
end
end
-- no need to show addons if there ain't a toplevel element
if (active_toplevel_ui_elements > 0) then
for key,value in pairs(ui.childlist) do
@ -92,11 +127,13 @@ function ui.update()
end
if (active_toplevel_ui_elements > 1) then
print("WARNING: ui manager detected more then one active ui element, self most likely isn't intended")
core.log("warning", "more than one active ui "..
"element, self most likely isn't intended")
end
if (active_toplevel_ui_elements == 0) then
print("WARNING: not a single toplevel ui element active switching to default")
core.log("warning", "no toplevel ui element "..
"active; switching to default")
ui.childlist[ui.default]:show()
formspec = ui.childlist[ui.default]:get_formspec()
end
@ -106,13 +143,6 @@ end
--------------------------------------------------------------------------------
function ui.handle_buttons(fields)
if fields["btn_error_confirm"] then
gamedata.errormessage = nil
update_menu()
return
end
for key,value in pairs(ui.childlist) do
local retval = value:handle_buttons(fields)
@ -127,7 +157,7 @@ end
--------------------------------------------------------------------------------
function ui.handle_events(event)
for key,value in pairs(ui.childlist) do
if value.handle_events ~= nil then
@ -146,8 +176,15 @@ end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
core.button_handler = function(fields)
if fields["btn_error_confirm"] then
if fields["btn_reconnect_yes"] then
gamedata.reconnect_requested = false
gamedata.errormessage = nil
gamedata.do_reconnect = true
core.start()
return
elseif fields["btn_reconnect_no"] or fields["btn_error_confirm"] then
gamedata.errormessage = nil
gamedata.reconnect_requested = false
ui.update()
return
end

View File

@ -171,6 +171,7 @@ function core.register_authentication_handler(handler)
end
core.registered_auth_handler = handler
core.registered_auth_handler_modname = core.get_current_modname()
handler.mod_origin = core.registered_auth_handler_modname
end
function core.get_auth_handler()

View File

@ -10,6 +10,7 @@ function core.register_chatcommand(cmd, def)
def.params = def.params or ""
def.description = def.description or ""
def.privs = def.privs or {}
def.mod_origin = core.get_current_modname() or "??"
core.chatcommands[cmd] = def
end
@ -37,6 +38,7 @@ core.register_on_chat_message(function(name, message)
end
local has_privs, missing_privs = core.check_player_privs(name, cmd_def.privs)
if has_privs then
core.set_last_run_mod(cmd_def.mod_origin)
local success, message = cmd_def.func(name, param)
if message then
core.chat_send_player(name, message)
@ -49,6 +51,27 @@ core.register_on_chat_message(function(name, message)
return true -- Handled chat message
end)
-- Parses a "range" string in the format of "here (number)" or
-- "(x1, y1, z1) (x2, y2, z2)", returning two position vectors
local function parse_range_str(player_name, str)
local p1, p2
local args = str:split(" ")
if args[1] == "here" then
p1, p2 = core.get_player_radius_area(player_name, tonumber(args[2]))
if p1 == nil then
return false, "Unable to get player " .. player_name .. " position"
end
else
p1, p2 = core.string_to_area(str)
if p1 == nil then
return false, "Incorrect area format. Expected: (x1,y1,z1) (x2,y2,z2)"
end
end
return p1, p2
end
--
-- Chat commands
--
@ -189,7 +212,7 @@ core.register_chatcommand("revoke", {
local revoke_privs = core.string_to_privs(revoke_priv_str)
local privs = core.get_player_privs(revoke_name)
for priv, _ in pairs(revoke_privs) do
if priv ~= "interact" and priv ~= "shout" and priv ~= "interact_extra" and
if priv ~= "interact" and priv ~= "shout" and
not core.check_player_privs(name, {privs=true}) then
return false, "Your privileges are insufficient."
end
@ -413,40 +436,31 @@ core.register_chatcommand("set", {
end,
})
core.register_chatcommand("emergeblocks", {
params = "(here [radius]) | (<pos1> <pos2>)",
description = "starts loading (or generating, if inexistent) map blocks "
.. "contained in area pos1 to pos2",
privs = {server=true},
func = function(name, param)
local p1, p2 = parse_range_str(name, param)
if p1 == false then
return false, p2
end
core.emerge_area(p1, p2)
return true, "Started emerge of area ranging from " ..
core.pos_to_string(p1, 1) .. " to " .. core.pos_to_string(p2, 1)
end,
})
core.register_chatcommand("deleteblocks", {
params = "(here [radius]) | (<pos1> <pos2>)",
description = "delete map blocks contained in area pos1 to pos2",
privs = {server=true},
func = function(name, param)
local p1 = {}
local p2 = {}
local args = param:split(" ")
if args[1] == "here" then
local player = core.get_player_by_name(name)
if player == nil then
core.log("error", "player is nil")
return false, "Unable to get current position; player is nil"
end
p1 = player:getpos()
p2 = p1
if #args >= 2 then
local radius = tonumber(args[2]) or 0
p1 = vector.add(p1, radius)
p2 = vector.subtract(p2, radius)
end
else
local pos1, pos2 = unpack(param:split(") ("))
if pos1 == nil or pos2 == nil then
return false, "Incorrect area format. Expected: (x1,y1,z1) (x2,y2,z2)"
end
p1 = core.string_to_pos(pos1 .. ")")
p2 = core.string_to_pos("(" .. pos2)
if p1 == nil or p2 == nil then
return false, "Incorrect area format. Expected: (x1,y1,z1) (x2,y2,z2)"
end
local p1, p2 = parse_range_str(name, param)
if p1 == false then
return false, p2
end
if core.delete_area(p1, p2) then
@ -530,22 +544,29 @@ core.register_chatcommand("giveme", {
})
core.register_chatcommand("spawnentity", {
params = "<EntityName>",
description = "Spawn entity at your position",
params = "<EntityName> [<X>,<Y>,<Z>]",
description = "Spawn entity at given (or your) position",
privs = {give=true, interact=true},
func = function(name, param)
local entityname = string.match(param, "(.+)$")
local entityname, p = string.match(param, "^([^ ]+) *(.*)$")
if not entityname then
return false, "EntityName required"
end
core.log("action", ("/spawnentity invoked, entityname=%q")
:format(entityname))
core.log("action", ("%s invokes /spawnentity, entityname=%q")
:format(name, entityname))
local player = core.get_player_by_name(name)
if player == nil then
core.log("error", "Unable to spawn entity, player is nil")
return false, "Unable to spawn entity, player is nil"
end
local p = player:getpos()
if p == "" then
p = player:getpos()
else
p = core.string_to_pos(p)
if p == nil then
return false, "Invalid parameters ('" .. param .. "')"
end
end
p.y = p.y + 1
core.add_entity(p, entityname)
return true, ("%q spawned."):format(entityname)
@ -689,7 +710,7 @@ core.register_chatcommand("time", {
local hour = (current_time - minutes) / 60
return true, ("Current time is %d:%02d"):format(hour, minutes)
end
local player_privs = minetest.get_player_privs(name)
local player_privs = core.get_player_privs(name)
if not player_privs.settime then
return false, "You don't have permission to run this command " ..
"(missing privilege: settime)."
@ -713,7 +734,7 @@ core.register_chatcommand("time", {
return false, "Invalid minute (must be between 0 and 59 inclusive)."
end
core.set_timeofday((hour * 60 + minute) / 1440)
core.log("action", name .. " sets time to " .. hour .. ":" .. minute)
core.log("action", ("%s sets time to %d:%02d"):format(name, hour, minute))
return true, "Time of day changed."
end,
})

View File

@ -3,9 +3,8 @@
--
-- Default material types
--
function digprop_err()
core.log("info", debug.traceback())
core.log("info", "WARNING: The core.digprop_* functions are obsolete and need to be replaced by item groups.")
local function digprop_err()
core.log("deprecated", "The core.digprop_* functions are obsolete and need to be replaced by item groups.")
end
core.digprop_constanttime = digprop_err
@ -16,12 +15,12 @@ core.digprop_woodlike = digprop_err
core.digprop_leaveslike = digprop_err
core.digprop_glasslike = digprop_err
core.node_metadata_inventory_move_allow_all = function()
core.log("info", "WARNING: core.node_metadata_inventory_move_allow_all is obsolete and does nothing.")
function core.node_metadata_inventory_move_allow_all()
core.log("deprecated", "core.node_metadata_inventory_move_allow_all is obsolete and does nothing.")
end
core.add_to_creative_inventory = function(itemstring)
core.log('info', "WARNING: core.add_to_creative_inventory: This function is deprecated and does nothing.")
function core.add_to_creative_inventory(itemstring)
core.log("deprecated", "core.add_to_creative_inventory: This function is deprecated and does nothing.")
end
--
@ -32,7 +31,7 @@ local envref_deprecation_message_printed = false
setmetatable(core.env, {
__index = function(table, key)
if not envref_deprecation_message_printed then
core.log("info", "WARNING: core.env:[...] is deprecated and should be replaced with core.[...]")
core.log("deprecated", "core.env:[...] is deprecated and should be replaced with core.[...]")
envref_deprecation_message_printed = true
end
local func = core[key]
@ -50,4 +49,3 @@ setmetatable(core.env, {
function core.rollback_get_last_node_actor(pos, range, seconds)
return core.rollback_get_node_actions(pos, range, seconds, 1)[1]
end

View File

@ -13,6 +13,7 @@ function core.create_detached_inventory(name, callbacks)
stuff.on_put = callbacks.on_put
stuff.on_take = callbacks.on_take
end
stuff.mod_origin = core.get_current_modname() or "??"
core.detached_inventories[name] = stuff
return core.create_detached_inventory_raw(name)
end

View File

@ -18,18 +18,6 @@ core.register_entity(":__builtin:falling_node", {
set_node = function(self, node)
self.node = node
local stack = ItemStack(node.name)
local itemtable = stack:to_table()
local itemname = nil
if itemtable then
itemname = stack:to_table().name
end
local item_texture = nil
local item_type = ""
if core.registered_items[itemname] then
item_texture = core.registered_items[itemname].inventory_image
item_type = core.registered_items[itemname].type
end
local prop = {
is_visible = true,
textures = {node.name},
@ -43,7 +31,9 @@ core.register_entity(":__builtin:falling_node", {
on_activate = function(self, staticdata)
self.object:set_armor_groups({immortal=1})
self:set_node({name=staticdata})
if staticdata then
self:set_node({name=staticdata})
end
end,
on_step = function(self, dtime)

View File

@ -12,9 +12,9 @@ core.features = {
function core.has_feature(arg)
if type(arg) == "table" then
missing_features = {}
result = true
for ft, _ in pairs(arg) do
local missing_features = {}
local result = true
for ftr in pairs(arg) do
if not core.features[ftr] then
missing_features[ftr] = true
result = false

View File

@ -1,5 +1,5 @@
local scriptpath = minetest.get_builtin_path()..DIR_DELIM
local scriptpath = core.get_builtin_path()..DIR_DELIM
local commonpath = scriptpath.."common"..DIR_DELIM
local gamepath = scriptpath.."game"..DIR_DELIM

View File

@ -139,6 +139,19 @@ function core.dir_to_wallmounted(dir)
end
end
function core.wallmounted_to_dir(wallmounted)
-- table of dirs in wallmounted order
return ({[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 = 0, y = 0, z = 1},
{x = 0, y = 0, z = -1}})
--indexed into by the wallmounted in question
[wallmounted]
end
function core.get_node_drops(nodename, toolname)
local drop = ItemStack({name=nodename}):get_definition().drop
if drop == nil then
@ -349,12 +362,16 @@ function core.item_drop(itemstack, dropper, pos)
v.y = v.y*2 + 2
v.z = v.z*2
obj:setvelocity(v)
return itemstack
end
else
core.add_item(pos, itemstack)
if core.add_item(pos, itemstack) then
return itemstack
end
end
return itemstack
-- If we reach this, adding the object to the
-- environment failed
end
function core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing)
@ -479,6 +496,15 @@ function core.node_dig(pos, node, digger)
-- Run script hook
local _, callback
for _, callback in ipairs(core.registered_on_dignodes) do
local origin = core.callback_origins[callback]
if origin then
core.set_last_run_mod(origin.mod)
--print("Running " .. tostring(callback) ..
-- " (a " .. origin.name .. " callback in " .. origin.mod .. ")")
else
--print("No data associated with callback")
end
-- Copy pos and node because callback can modify them
local pos_copy = {x=pos.x, y=pos.y, z=pos.z}
local node_copy = {name=node.name, param1=node.param1, param2=node.param2}

View File

@ -4,11 +4,14 @@ function core.spawn_item(pos, item)
-- Take item in any format
local stack = ItemStack(item)
local obj = core.add_entity(pos, "__builtin:item")
obj:get_luaentity():set_item(stack:to_string())
-- Don't use obj if it couldn't be added to the map.
if obj then
obj:get_luaentity():set_item(stack:to_string())
end
return obj
end
-- If item_entity_ttl is not set, enity will have default life time
-- If item_entity_ttl is not set, enity will have default life time
-- Setting it to -1 disables the feature
local time_to_live = tonumber(core.setting_get("item_entity_ttl"))
@ -81,7 +84,7 @@ core.register_entity(":__builtin:item", {
if data and type(data) == "table" then
self.itemstring = data.itemstring
self.always_collect = data.always_collect
if data.age then
if data.age then
self.age = data.age + dtime_s
else
self.age = dtime_s
@ -197,9 +200,10 @@ core.register_entity(":__builtin:item", {
end,
on_punch = function(self, hitter)
if self.itemstring ~= '' then
local left = hitter:get_inventory():add_item("main", self.itemstring)
if not left:is_empty() then
local inv = hitter:get_inventory()
if inv and self.itemstring ~= '' then
local left = inv:add_item("main", self.itemstring)
if left and not left:is_empty() then
self.itemstring = left:to_string()
return
end

View File

@ -4,45 +4,107 @@
-- Misc. API functions
--
core.timers_to_add = {}
core.timers = {}
core.register_globalstep(function(dtime)
for _, timer in ipairs(core.timers_to_add) do
table.insert(core.timers, timer)
end
core.timers_to_add = {}
local index = 1
while index <= #core.timers do
local timer = core.timers[index]
timer.time = timer.time - dtime
local timers = {}
local mintime
local function update_timers(delay)
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(core.timers,index)
table.remove(timers, index)
sub = sub + 1
elseif mintime then
mintime = math.min(mintime, timer.time)
else
index = index + 1
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)
if not mintime then
-- abort if no timers are running
return
end
if timers_to_add then
add_timers()
end
delay = delay + dtime
if delay < mintime then
return
end
update_timers(delay)
delay = 0
end)
function core.after(time, func, ...)
assert(tonumber(time) and type(func) == "function",
"Invalid core.after invocation")
table.insert(core.timers_to_add, {time=time, func=func, args={...}})
if not mintime then
mintime = time
timers_to_add = {{
time = time+delay,
func = func,
args = {...},
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
function core.check_player_privs(name, privs)
function core.check_player_privs(player_or_name, ...)
local name = player_or_name
-- Check if we have been provided with a Player object.
if type(name) ~= "string" then
name = name:get_player_name()
end
local requested_privs = {...}
local player_privs = core.get_player_privs(name)
local missing_privileges = {}
for priv, val in pairs(privs) do
if val then
if type(requested_privs[1]) == "table" then
-- We were provided with a table like { privA = true, privB = true }.
for priv, value in pairs(requested_privs[1]) do
if value and not player_privs[priv] then
table.insert(missing_privileges, priv)
end
end
else
-- Only a list, we can process it directly.
for key, priv in pairs(requested_privs) do
if not player_privs[priv] then
table.insert(missing_privileges, priv)
end
end
end
if #missing_privileges > 0 then
return false, missing_privileges
end
return true, ""
end
@ -66,6 +128,25 @@ function core.get_connected_players()
return temp_table
end
-- Returns two position vectors representing a box of `radius` in each
-- direction centered around the player corresponding to `player_name`
function core.get_player_radius_area(player_name, radius)
local player = core.get_player_by_name(player_name)
if player == nil then
return nil
end
local p1 = player:getpos()
local p2 = p1
if radius then
p1 = vector.subtract(p1, radius)
p2 = vector.add(p2, radius)
end
return p1, p2
end
function core.hash_node_position(pos)
return (pos.z+32768)*65536*65536 + (pos.y+32768)*65536 + pos.x+32768
end

View File

@ -72,6 +72,7 @@ end
function core.register_abm(spec)
-- Add to core.registered_abms
core.registered_abms[#core.registered_abms+1] = spec
spec.mod_origin = core.get_current_modname() or "??"
end
function core.register_entity(name, prototype)
@ -86,6 +87,7 @@ function core.register_entity(name, prototype)
-- Add to core.registered_entities
core.registered_entities[name] = prototype
prototype.mod_origin = core.get_current_modname() or "??"
end
function core.register_item(name, itemdef)
@ -147,6 +149,8 @@ function core.register_item(name, itemdef)
end
-- END Legacy stuff
itemdef.mod_origin = core.get_current_modname() or "??"
-- Disable all further modifications
getmetatable(itemdef).__newindex = {}
@ -217,7 +221,7 @@ function core.register_alias(name, convert_to)
error("Unable to register alias: Name is forbidden: " .. name)
end
if core.registered_items[name] ~= nil then
core.log("WARNING: Not registering alias, item with same name" ..
core.log("warning", "Not registering alias, item with same name" ..
" is already defined: " .. name .. " -> " .. convert_to)
else
--core.log("Registering alias: " .. name .. " -> " .. convert_to)
@ -326,6 +330,8 @@ function core.override_item(name, redefinition)
end
core.callback_origins = {}
function core.run_callbacks(callbacks, mode, ...)
assert(type(callbacks) == "table")
local cb_len = #callbacks
@ -338,6 +344,14 @@ function core.run_callbacks(callbacks, mode, ...)
end
local ret = nil
for i = 1, cb_len do
local origin = core.callback_origins[callbacks[i]]
if origin then
core.set_last_run_mod(origin.mod)
--print("Running " .. tostring(callbacks[i]) ..
-- " (a " .. origin.name .. " callback in " .. origin.mod .. ")")
else
--print("No data associated with callback")
end
local cb_ret = callbacks[i](...)
if mode == 0 and i == 1 then
@ -370,13 +384,29 @@ end
local function make_registration()
local t = {}
local registerfunc = function(func) table.insert(t, func) end
local registerfunc = function(func)
table.insert(t, func)
core.callback_origins[func] = {
mod = core.get_current_modname() or "??",
name = debug.getinfo(1, "n").name or "??"
}
--local origin = core.callback_origins[func]
--print(origin.name .. ": " .. origin.mod .. " registering cbk " .. tostring(func))
end
return t, registerfunc
end
local function make_registration_reverse()
local t = {}
local registerfunc = function(func) table.insert(t, 1, func) end
local registerfunc = function(func)
table.insert(t, 1, func)
core.callback_origins[func] = {
mod = core.get_current_modname() or "??",
name = debug.getinfo(1, "n").name or "??"
}
--local origin = core.callback_origins[func]
--print(origin.name .. ": " .. origin.mod .. " registering cbk " .. tostring(func))
end
return t, registerfunc
end
@ -407,6 +437,40 @@ local function make_registration_wrap(reg_fn_name, clear_fn_name)
return list
end
core.registered_on_player_hpchanges = { modifiers = { }, loggers = { } }
function core.registered_on_player_hpchange(player, hp_change)
local last = false
for i = #core.registered_on_player_hpchanges.modifiers, 1, -1 do
local func = core.registered_on_player_hpchanges.modifiers[i]
hp_change, last = func(player, hp_change)
if type(hp_change) ~= "number" then
local debuginfo = debug.getinfo(func)
error("The register_on_hp_changes function has to return a number at " ..
debuginfo.short_src .. " line " .. debuginfo.linedefined)
end
if last then
break
end
end
for i, func in ipairs(core.registered_on_player_hpchanges.loggers) do
func(player, hp_change)
end
return hp_change
end
function core.register_on_player_hpchange(func, modifier)
if modifier then
table.insert(core.registered_on_player_hpchanges.modifiers, func)
else
table.insert(core.registered_on_player_hpchanges.loggers, func)
end
core.callback_origins[func] = {
mod = core.get_current_modname() or "??",
name = debug.getinfo(1, "n").name or "??"
}
end
core.registered_biomes = make_registration_wrap("register_biome", "clear_registered_biomes")
core.registered_ores = make_registration_wrap("register_ore", "clear_registered_ores")
core.registered_decorations = make_registration_wrap("register_decoration", "clear_registered_decorations")

View File

@ -6,7 +6,7 @@
--
-- Initialize some very basic things
print = core.debug
function core.debug(...) core.log(table.concat({...}, "\t")) end
math.randomseed(os.time())
os.setlocale("C", "numeric")
minetest = core

View File

@ -3,7 +3,7 @@
--
--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
--the Free Software Foundation; either version 3.0 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,
@ -224,17 +224,23 @@ function menu_handle_key_up_down(fields,textlist,settingname)
configure_selected_world_params(newidx)
end
return true
end
return false
end
--------------------------------------------------------------------------------
function asyncOnlineFavourites()
menudata.favorites = {}
if not menudata.public_known then
menudata.public_known = {{
name = fgettext("Loading..."),
description = fgettext_ne("Try reenabling public serverlist and check your internet connection.")
}}
end
menudata.favorites = menudata.public_known
core.handle_async(
function(param)
return core.get_favorites("online")
@ -242,51 +248,100 @@ function asyncOnlineFavourites()
nil,
function(result)
if core.setting_getbool("public_serverlist") then
menudata.favorites = order_favorite_list(result)
local favs = order_favorite_list(result)
if favs[1] then
menudata.public_known = favs
menudata.favorites = menudata.public_known
end
core.event_handler("Refresh")
end
end
)
)
end
--------------------------------------------------------------------------------
function text2textlist(xpos,ypos,width,height,tl_name,textlen,text,transparency)
local textlines = core.splittext(text,textlen)
local retval = "textlist[" .. xpos .. "," .. ypos .. ";"
.. width .. "," .. height .. ";"
.. tl_name .. ";"
for i=1, #textlines, 1 do
textlines[i] = textlines[i]:gsub("\r","")
retval = retval .. core.formspec_escape(textlines[i]) .. ","
end
retval = retval .. ";0;"
if transparency then
retval = retval .. "true"
end
retval = retval .. "]"
return retval
end
--------------------------------------------------------------------------------
function is_server_protocol_compat(proto_min, proto_max)
return not ((min_supp_proto > (proto_max or 24)) or (max_supp_proto < (proto_min or 13)))
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)))
end
--------------------------------------------------------------------------------
function is_server_protocol_compat_or_error(proto_min, proto_max)
if not is_server_protocol_compat(proto_min, proto_max) then
gamedata.errormessage = fgettext_ne("Protocol version mismatch, server " ..
((proto_min ~= proto_max) and "supports protocols between $1 and $2" or "enforces protocol version $1") ..
", we " ..
((min_supp_proto ~= max_supp_proto) and "support protocols between version $3 and $4." or "only support protocol version $3"),
proto_min or 13, proto_max or 24, min_supp_proto, max_supp_proto)
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
local server_prot_ver_info
local client_prot_ver_info
if server_proto_min ~= server_proto_max then
server_prot_ver_info = fgettext_ne("Server supports protocol versions between $1 and $2. ",
server_proto_min or 13, server_proto_max or 24)
else
server_prot_ver_info = fgettext_ne("Server enforces protocol version $1. ",
server_proto_min or 13)
end
if min_supp_proto ~= max_supp_proto then
client_prot_ver_info= fgettext_ne("We support protocol versions between version $1 and $2.",
min_supp_proto, max_supp_proto)
else
client_prot_ver_info = fgettext_ne("We only support protocol version $1.", min_supp_proto)
end
gamedata.errormessage = fgettext_ne("Protocol version mismatch. ")
.. server_prot_ver_info
.. client_prot_ver_info
return false
end
return true
end
--------------------------------------------------------------------------------
function menu_worldmt(selected, setting, value)
local world = menudata.worldlist:get_list()[selected]
if world then
local filename = world.path .. DIR_DELIM .. "world.mt"
local world_conf = Settings(filename)
if value ~= nil then
if not world_conf:write() then
core.log("error", "Failed to write world config file")
end
world_conf:set(setting, value)
world_conf:write()
else
return world_conf:get(setting)
end
else
return nil
end
end
function menu_worldmt_legacy(selected)
local modes_names = {"creative_mode", "enable_damage", "server_announce"}
for _, mode_name in pairs(modes_names) do
local mode_val = menu_worldmt(selected, mode_name)
if mode_val ~= nil then
core.setting_set(mode_name, mode_val)
else
menu_worldmt(selected, mode_name, core.setting_get(mode_name))
end
end
end

View File

@ -3,7 +3,7 @@
--
--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
--the Free Software Foundation; either version 3.0 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,

View File

@ -3,7 +3,7 @@
--
--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
--the Free Software Foundation; either version 3.0 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,

View File

@ -3,7 +3,7 @@
--
--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
--the Free Software Foundation; either version 3.0 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,

View File

@ -3,7 +3,7 @@
--
--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
--the Free Software Foundation; either version 3.0 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,

View File

@ -3,7 +3,7 @@
--
--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
--the Free Software Foundation; either version 3.0 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,

View File

@ -3,7 +3,7 @@
--
--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
--the Free Software Foundation; either version 3.0 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,

View File

@ -3,7 +3,7 @@
--
--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
--the Free Software Foundation; either version 3.0 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,

View File

@ -3,7 +3,7 @@
--
--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
--the Free Software Foundation; either version 3.0 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,

View File

@ -3,7 +3,7 @@
--
--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
--the Free Software Foundation; either version 3.0 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,

View File

@ -3,7 +3,7 @@
--
--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
--the Free Software Foundation; either version 3.0 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,
@ -25,46 +25,56 @@ tab_credits = {
return "label[0.5,3.2;Minetest " .. core.get_version() .. "]" ..
"label[0.5,3.5;http://minetest.net]" ..
"image[0.5,1;" .. core.formspec_escape(logofile) .. "]" ..
"textlist[3.5,-0.25;8.5,5.8;list_credits;" ..
"#FFFF00" .. fgettext("Core Developers") .."," ..
"Perttu Ahola (celeron55) <celeron55@gmail.com>,"..
"Ryan Kwolek (kwolekr) <kwolekr@minetest.net>,"..
"PilzAdam <pilzadam@minetest.net>," ..
"Lisa Milne (darkrose) <lisa@ltmnet.com>,"..
"Maciej Kasatkin (RealBadAngel) <mk@realbadangel.pl>,"..
"sfan5 <sfan5@live.de>,"..
"kahrl <kahrl@gmx.net>,"..
"sapier,"..
"ShadowNinja <shadowninja@minetest.net>,"..
"Nathanael Courant (Nore/Novatux) <nore@mesecons.net>,"..
"BlockMen,"..
"Craig Robbins (Zeno),"..
"Loic Blot (nerzhul/nrz),"..
"paramat,"..
","..
"#FFFF00" .. fgettext("Active Contributors") .. "," ..
"SmallJoker <mk939@ymail.com>," ..
"est31 <MTest31@outlook.com>," ..
"gregorycu,"..
"Andrew Ward (rubenwardy) <rubenwardy@gmail.com>," ..
"TriBlade9 <triblade9@mail.com>,"..
"Zefram <zefram@fysh.org>,"..
"," ..
"#FFFF00" .. fgettext("Previous Contributors") .. "," ..
"Vanessa Ezekowitz (VanessaE) <vanessaezekowitz@gmail.com>,"..
"Jurgen Doser (doserj) <jurgen.doser@gmail.com>,"..
"Jeija <jeija@mesecons.net>,"..
"MirceaKitsune <mirceakitsune@gmail.com>,"..
"dannydark <the_skeleton_of_a_child@yahoo.co.uk>,"..
"0gb.us <0gb.us@0gb.us>,"..
"proller <proler@gmail.com>,"..
"Ilya Zhuravlev (xyz) <xyz@minetest.net>,"..
"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>,"..
";0;true]"
"tablecolumns[color;text]" ..
"tableoptions[background=#00000000;highlight=#00000000;border=false]" ..
"table[3.5,-0.25;8.5,5.8;list_credits;" ..
"#FFFF00," .. fgettext("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>,"..
",Nathanael Courant (Nore/Ekdohibs) <nore@mesecons.net>,"..
",BlockMen,"..
",Craig Robbins (Zeno),"..
",Loic Blot (nerzhul/nrz) <loic.blot@unix-experience.fr>,"..
",Mat Gregory (paramat),"..
",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]"
end
}

View File

@ -3,7 +3,7 @@
--
--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
--the Free Software Foundation; either version 3.0 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,
@ -36,7 +36,10 @@ local function get_formspec(tabview, name, tabdata)
-- "label[0.8,4.2;" .. fgettext("Add mod:") .. "]" ..
-- TODO Disabled due to upcoming release 0.4.8 and irrlicht messing up localization
-- "button[0.75,4.85;1.8,0.5;btn_mod_mgr_install_local;".. fgettext("Local install") .. "]" ..
"button[0,4.85;5.25,0.5;btn_modstore;".. fgettext("Online mod repository") .. "]"
-- TODO Disabled due to service being offline, and not likely to come online again, in this form
-- "button[0,4.85;5.25,0.5;btn_modstore;".. fgettext("Online mod repository") .. "]"
""
local selected_mod = nil

View File

@ -3,7 +3,7 @@
--
--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
--the Free Software Foundation; either version 3.0 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,

View File

@ -3,7 +3,7 @@
--
--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
--the Free Software Foundation; either version 3.0 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,
@ -67,32 +67,9 @@ local function main_button_handler(this, fields, name, tabdata)
if fields["srv_worlds"] ~= nil then
local event = core.explode_textlist_event(fields["srv_worlds"])
local selected = core.get_textlist_index("srv_worlds")
if selected ~= nil then
local filename = menudata.worldlist:get_list()[selected].path
local worldconfig = modmgr.get_worldconfig(filename)
filename = filename .. DIR_DELIM .. "world.mt"
if worldconfig.creative_mode ~= nil then
core.setting_set("creative_mode", worldconfig.creative_mode)
else
local worldfile = Settings(filename)
worldfile:set("creative_mode", core.setting_get("creative_mode"))
if not worldfile:write() then
core.log("error", "Failed to write world config file")
end
end
if worldconfig.enable_damage ~= nil then
core.setting_set("enable_damage", worldconfig.enable_damage)
else
local worldfile = Settings(filename)
worldfile:set("enable_damage", core.setting_get("enable_damage"))
if not worldfile:write() then
core.log("error", "Failed to write world config file")
end
end
end
menu_worldmt_legacy(selected)
if event.type == "DCL" then
world_doubleclick = true
@ -111,33 +88,24 @@ local function main_button_handler(this, fields, name, tabdata)
if fields["cb_creative_mode"] then
core.setting_set("creative_mode", fields["cb_creative_mode"])
local selected = core.get_textlist_index("srv_worlds")
local filename = menudata.worldlist:get_list()[selected].path ..
DIR_DELIM .. "world.mt"
menu_worldmt(selected, "creative_mode", fields["cb_creative_mode"])
local worldfile = Settings(filename)
worldfile:set("creative_mode", fields["cb_creative_mode"])
if not worldfile:write() then
core.log("error", "Failed to write world config file")
end
return true
end
if fields["cb_enable_damage"] then
core.setting_set("enable_damage", fields["cb_enable_damage"])
local selected = core.get_textlist_index("srv_worlds")
local filename = menudata.worldlist:get_list()[selected].path ..
DIR_DELIM .. "world.mt"
menu_worldmt(selected, "enable_damage", fields["cb_enable_damage"])
local worldfile = Settings(filename)
worldfile:set("enable_damage", fields["cb_enable_damage"])
if not worldfile:write() then
core.log("error", "Failed to write world config file")
end
return true
end
if fields["cb_server_announce"] then
core.setting_set("server_announce", fields["cb_server_announce"])
local selected = core.get_textlist_index("srv_worlds")
menu_worldmt(selected, "server_announce", fields["cb_server_announce"])
return true
end
@ -145,12 +113,12 @@ local function main_button_handler(this, fields, name, tabdata)
world_doubleclick or
fields["key_enter"] then
local selected = core.get_textlist_index("srv_worlds")
if selected ~= nil then
gamedata.selected_world = menudata.worldlist:get_raw_index(selected)
if selected ~= nil and gamedata.selected_world ~= 0 then
gamedata.playername = fields["te_playername"]
gamedata.password = fields["te_passwd"]
gamedata.port = fields["te_serverport"]
gamedata.address = ""
gamedata.selected_world = menudata.worldlist:get_raw_index(selected)
core.setting_set("port",gamedata.port)
if fields["te_serveraddr"] ~= nil then
@ -159,12 +127,17 @@ local function main_button_handler(this, fields, name, tabdata)
--update last game
local world = menudata.worldlist:get_raw_element(gamedata.selected_world)
if world then
local game, index = gamemgr.find_by_gameid(world.gameid)
core.setting_set("menu_last_game", game.id)
end
local game,index = gamemgr.find_by_gameid(world.gameid)
core.setting_set("menu_last_game",game.id)
core.start()
return true
else
gamedata.errormessage =
fgettext("No world created or selected!")
end
return true
end
if fields["world_create"] ~= nil then

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
--
--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
--the Free Software Foundation; either version 3.0 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,

View File

@ -3,7 +3,7 @@
--
--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
--the Free Software Foundation; either version 3.0 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,
@ -23,9 +23,9 @@ local function current_game()
end
local function singleplayer_refresh_gamebar()
local old_bar = ui.find_by_name("game_button_bar")
if old_bar ~= nil then
old_bar:delete()
end
@ -38,6 +38,17 @@ local function singleplayer_refresh_gamebar()
core.set_topleft_text(gamemgr.games[j].name)
core.setting_set("menu_last_game",gamemgr.games[j].id)
menudata.worldlist:set_filtercriteria(gamemgr.games[j].id)
local index = filterlist.get_current_index(menudata.worldlist,
tonumber(core.setting_get("mainmenu_last_selected_world")))
if not index or index < 1 then
local selected = core.get_textlist_index("sp_worlds")
if selected ~= nil and selected < #menudata.worldlist:get_list() then
index = selected
else
index = #menudata.worldlist:get_list()
end
end
menu_worldmt_legacy(index)
return true
end
end
@ -76,7 +87,7 @@ end
local function get_formspec(tabview, name, tabdata)
local retval = ""
local index = filterlist.get_current_index(menudata.worldlist,
tonumber(core.setting_get("mainmenu_last_selected_world"))
)
@ -105,32 +116,9 @@ local function main_button_handler(this, fields, name, tabdata)
if fields["sp_worlds"] ~= nil then
local event = core.explode_textlist_event(fields["sp_worlds"])
local selected = core.get_textlist_index("sp_worlds")
if selected ~= nil then
local filename = menudata.worldlist:get_list()[selected].path
local worldconfig = modmgr.get_worldconfig(filename)
filename = filename .. DIR_DELIM .. "world.mt"
if worldconfig.creative_mode ~= nil then
core.setting_set("creative_mode", worldconfig.creative_mode)
else
local worldfile = Settings(filename)
worldfile:set("creative_mode", core.setting_get("creative_mode"))
if not worldfile:write() then
core.log("error", "Failed to write world config file")
end
end
if worldconfig.enable_damage ~= nil then
core.setting_set("enable_damage", worldconfig.enable_damage)
else
local worldfile = Settings(filename)
worldfile:set("enable_damage", core.setting_get("enable_damage"))
if not worldfile:write() then
core.log("error", "Failed to write world config file")
end
end
end
menu_worldmt_legacy(selected)
if event.type == "DCL" then
world_doubleclick = true
@ -150,28 +138,16 @@ local function main_button_handler(this, fields, name, tabdata)
if fields["cb_creative_mode"] then
core.setting_set("creative_mode", fields["cb_creative_mode"])
local selected = core.get_textlist_index("sp_worlds")
local filename = menudata.worldlist:get_list()[selected].path ..
DIR_DELIM .. "world.mt"
menu_worldmt(selected, "creative_mode", fields["cb_creative_mode"])
local worldfile = Settings(filename)
worldfile:set("creative_mode", fields["cb_creative_mode"])
if not worldfile:write() then
core.log("error", "Failed to write world config file")
end
return true
end
if fields["cb_enable_damage"] then
core.setting_set("enable_damage", fields["cb_enable_damage"])
local selected = core.get_textlist_index("sp_worlds")
local filename = menudata.worldlist:get_list()[selected].path ..
DIR_DELIM .. "world.mt"
menu_worldmt(selected, "enable_damage", fields["cb_enable_damage"])
local worldfile = Settings(filename)
worldfile:set("enable_damage", fields["cb_enable_damage"])
if not worldfile:write() then
core.log("error", "Failed to write world config file")
end
return true
end
@ -179,12 +155,14 @@ local function main_button_handler(this, fields, name, tabdata)
world_doubleclick or
fields["key_enter"] then
local selected = core.get_textlist_index("sp_worlds")
gamedata.selected_world = menudata.worldlist:get_raw_index(selected)
if selected ~= nil then
gamedata.selected_world = menudata.worldlist:get_raw_index(selected)
gamedata.singleplayer = true
if selected ~= nil and gamedata.selected_world ~= 0 then
gamedata.singleplayer = true
core.start()
else
gamedata.errormessage =
fgettext("No world created or selected!")
end
return true
end

View File

@ -3,7 +3,7 @@
--
--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
--the Free Software Foundation; either version 3.0 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,
@ -17,7 +17,7 @@
--------------------------------------------------------------------------------
local function filter_texture_pack_list(list)
local retval = {"None"}
local retval = {fgettext("None")}
for _, item in ipairs(list) do
if item ~= "base" then
table.insert(retval, item)
@ -45,7 +45,7 @@ end
--------------------------------------------------------------------------------
local function get_formspec(tabview, name, tabdata)
local retval = "label[4,-0.25;".. fgettext("Select texture pack:") .. "]"..
"textlist[4,0.25;7.5,5.0;TPs;"
@ -62,10 +62,18 @@ local function get_formspec(tabview, name, tabdata)
return retval
end
local infofile = current_texture_path ..DIR_DELIM.."info.txt"
local infofile = current_texture_path ..DIR_DELIM.."description.txt"
-- 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
if not file_exists(infofile) then
infofile = current_texture_path ..DIR_DELIM.."info.txt"
if file_exists(infofile) then
core.log("info.txt is depreciated. description.txt should be used instead.");
end
end
local infotext = ""
local f = io.open(infofile, "r")
if f==nil then
if not f then
infotext = fgettext("No information available")
else
infotext = f:read("*all")
@ -98,7 +106,7 @@ local function main_button_handler(tabview, fields, name, tabdata)
local current_index = core.get_textlist_index("TPs")
if current_index ~= nil and #list >= current_index then
local new_path = core.get_texturepath()..DIR_DELIM..list[current_index]
if list[current_index] == "None" then new_path = "" end
if list[current_index] == fgettext("None") then new_path = "" end
core.setting_set("texture_path", new_path)
end

View File

@ -3,7 +3,7 @@
--
--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
--the Free Software Foundation; either version 3.0 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,
@ -129,7 +129,7 @@ function mm_texture.set_generic(identifier)
end
--------------------------------------------------------------------------------
function mm_texture.set_game(identifier,gamedetails)
function mm_texture.set_game(identifier, gamedetails)
if gamedetails == nil then
return false
@ -137,15 +137,34 @@ function mm_texture.set_game(identifier,gamedetails)
if mm_texture.texturepack ~= nil then
local path = mm_texture.texturepack .. DIR_DELIM ..
gamedetails.id .. "_menu_" .. identifier .. ".png"
if core.set_background(identifier,path) then
gamedetails.id .. "_menu_" .. identifier .. ".png"
if core.set_background(identifier, path) then
return true
end
end
local path = gamedetails.path .. DIR_DELIM .."menu" ..
DIR_DELIM .. identifier .. ".png"
if core.set_background(identifier,path) then
-- Find out how many randomized textures the subgame provides
local n = 0
local filename
local menu_files = core.get_dir_list(gamedetails.path .. DIR_DELIM .. "menu", false)
for i = 1, #menu_files do
filename = identifier .. "." .. i .. ".png"
if table.indexof(menu_files, filename) == -1 then
n = i - 1
break
end
end
-- Select random texture, 0 means standard texture
n = math.random(0, n)
if n == 0 then
filename = identifier .. ".png"
else
filename = identifier .. "." .. n .. ".png"
end
local path = gamedetails.path .. DIR_DELIM .. "menu" ..
DIR_DELIM .. filename
if core.set_background(identifier, path) then
return true
end

993
builtin/settingtypes.txt Normal file
View File

@ -0,0 +1,993 @@
# This file contains all settings displayed in the settings menu.
#
# General format:
# name (Readable name) type type_args
#
# Note that the parts are seperated by exactly one space
#
# `type` can be:
# - int
# - string
# - bool
# - float
# - enum
# - path
# - key (will be ignored in GUI, since a special key change dialog exists)
# - flags
# - noise_params
#
# `type_args` can be:
# * int:
# - default
# - default min max
# * string:
# - default (if default is not specified then "" is set)
# * bool:
# - default
# * float:
# - default
# - default min max
# * enum:
# - default value1,value2,...
# * path:
# - default (if default is not specified then "" is set)
# * key:
# - default
# * flags:
# Flags are always separated by comma without spaces.
# - default possible_flags
# * noise_params:
# TODO: these are currently treated like strings
#
# Comments directly above a setting are bound to this setting.
# All other comments are ignored.
#
# Comments and (Readable name) are handled by gettext.
# Comments should be complete sentences that describe the setting and possibly
# give the user additional useful insight.
# Sections are marked by a single line in the format: [Section Name]
# Sub-section are marked by adding * in front of the section name: [*Sub-section]
# Sub-sub-sections have two * etc.
# There shouldn't be too much settings per category; settings that shouldn't be
# modified by the "average user" should be in (sub-)categories called "Advanced".
[Client]
[*Controls]
# If enabled, you can place blocks at the position (feet + eye level) where you stand.
# This is helpful when working with nodeboxes in small areas.
enable_build_where_you_stand (Build inside player) bool false
# Player is able to fly without being affected by gravity.
# This requires the "fly" privilege on the server.
free_move (Flying) bool false
# Fast movement (via use key).
# This requires the "fast" privilege on the server.
fast_move (Fast movement) bool false
# If enabled together with fly mode, player is able to fly through solid nodes.
# This requires the "noclip" privilege on the server.
noclip (Noclip) bool false
# Smooths camera when moving and looking around.
# Useful for recording videos.
cinematic (Cinematic mode) bool false
# Smooths rotation of camera. 0 to disable.
camera_smoothing (Camera smoothing) float 0.0 0.0 0.99
# Smooths rotation of camera in cinematic mode. 0 to disable.
cinematic_camera_smoothing (Camera smoothing in cinematic mode) float 0.7 0.0 0.99
# Invert vertical mouse movement.
invert_mouse (Invert mouse) bool false
# Mouse sensitivity multiplier.
mouse_sensitivity (Mouse sensitivity) float 0.2
# If enabled, "use" key instead of "sneak" key is used for climbing down and descending.
aux1_descends (Key use for climbing/descending) bool false
# Double-tapping the jump key toggles fly mode.
doubletap_jump (Double tap jump for fly) bool false
# If disabled "use" key is used to fly fast if both fly and fast mode are enabled.
always_fly_fast (Always fly and fast) bool true
# The time in seconds it takes between repeated right clicks when holding the right mouse button.
repeat_rightclick_time (Rightclick repetition interval) float 0.25
# Enable random user input (only used for testing).
random_input (Random input) bool false
# Continuous forward movement (only used for testing).
continuous_forward (Continuous forward) bool false
# Key for moving the player forward.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_forward (Forward key) key KEY_KEY_W
# Key for moving the player backward.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_backward (Backward key) key KEY_KEY_S
# Key for moving the player left.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_left (Left key) key KEY_KEY_A
# Key for moving the player right.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_right (Right key) key KEY_KEY_D
# Key for jumping.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_jump (Jump key) key KEY_SPACE
# Key for sneaking.
# Also used for climbing down and descending in water if aux1_descends is disabled.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_sneak (Sneak key) key KEY_LSHIFT
# Key for opening the inventory.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_inventory (Inventory key) key KEY_KEY_I
# Key for moving fast in fast mode.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_special1 (Use key) key KEY_KEY_E
# Key for opening the chat window.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_chat (Chat key) key KEY_KEY_T
# Key for opening the chat window to type commands.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_cmd (Command key) key /
# Key for opening the chat console.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keyman_console (Console key) key KEY_F10
# Key for toggling unlimited view range.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_rangeselect (Range select key) key KEY_KEY_R
# Key for toggling flying.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_freemove (Fly key) key KEY_KEY_K
# Key for toggling fast mode.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_fastmove (Fast key) key KEY_KEY_J
# Key for toggling noclip mode.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_noclip (Noclip key) key KEY_KEY_H
# Key for toggling cinematic mode.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_cinematic (Cinematic mode key) key KEY_F8
# Key for toggling display of minimap.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_minimap (Minimap key) key KEY_F9
# Key for taking screenshots.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_screenshot (Screenshot) key KEY_F12
# Key for dropping the currently selected item.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_drop (Drop item key) key KEY_KEY_Q
# Key for toggling the display of the HUD.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_toggle_hud (HUD toggle key) key KEY_F1
# Key for toggling the display of the chat.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_toggle_chat (Chat toggle key) key KEY_F2
# Key for toggling the display of the fog.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_toggle_force_fog_off (Fog toggle key) key KEY_F3
# Key for toggling the camrea update. Only used for development
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_toggle_update_camera (Camera update toggle key) key
# Key for toggling the display of debug info.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_toggle_debug (Debug info toggle key) key KEY_F5
# Key for toggling the display of the profiler. Used for development.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_toggle_profiler (Profiler toggle key) key KEY_F6
# Key for switching between first- and third-person camera.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_camera_mode (Toggle camera mode key) key KEY_F7
# Key for increasing the viewing range. Modifies the minimum viewing range.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_increase_viewing_range_min (View range increase key) key +
# Key for decreasing the viewing range. Modifies the minimum viewing range.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_decrease_viewing_range_min (View range decrease key) key -
# Key for printing debug stacks. Used for development.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_print_debug_stacks (Print stacks) key KEY_KEY_P
[*Network]
# Address to connect to.
# Leave this blank to start a local server.
# Note that the address field in the main menu overrides this setting.
address (Server address) string
# Port to connect to (UDP).
# Note that the port field in the main menu overrides this setting.
remote_port (Remote port) int 30000 1 65535
# Save the map received by the client on disk.
enable_local_map_saving (Saving map received from server) bool false
# Enable usage of remote media server (if provided by server).
# Remote servers offer a significantly faster way to download media (e.g. textures)
# when connecting to the server.
enable_remote_media_server (Connect to external media server) bool true
# URL to the server list displayed in the Multiplayer Tab.
serverlist_url (Serverlist URL) string servers.minetest.net
# File in client/serverlist/ that contains your favorite servers displayed in the Multiplayer Tab.
serverlist_file (Serverlist file) string favoriteservers.txt
[*Graphics]
[**In-Game]
[***Basic]
# Whether to fog out the end of the visible area.
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:
# - Fancy: all faces visible
# - Simple: only outer faces, if defined special_tiles are used
# - Opaque: disable transparency
leaves_style (Leaves style) enum fancy fancy,simple,opaque
# Connects glass if supported by node.
connected_glass (Connect glass) bool false
# Enable smooth lighting with simple ambient occlusion.
# Disable for speed or for different looks.
smooth_lighting (Smooth lighting) bool true
# Clouds are a client side effect.
enable_clouds (Clouds) bool true
# Use 3D cloud look instead of flat.
enable_3d_clouds (3D clouds) bool true
[***Filtering]
# Use mip mapping to scale textures. May slightly increase performance.
mip_map (Mipmapping) bool false
# Use anisotropic filtering when viewing at textures from an angle.
anisotropic_filter (Anisotropic filtering) bool false
# Use bilinear filtering when scaling textures.
bilinear_filter (Bilinear filtering) bool false
# Use trilinear filtering when scaling textures.
trilinear_filter (Trilinear filtering) bool false
# Filtered textures can blend RGB values with fully-transparent neighbors,
# which PNG optimizers usually discard, sometimes resulting in a dark or
# light edge to transparent textures. Apply this filter to clean that up
# at texture load time.
texture_clean_transparent (Clean transparent textures) bool false
# When using bilinear/trilinear/anisotropic filters, low-resolution textures
# can be blurred, so automatically upscale them with nearest-neighbor
# interpolation to preserve crisp pixels. This sets the minimum texture size
# for the upscaled textures; higher values look sharper, but require more
# memory. Powers of 2 are recommended. Setting this higher than 1 may not
# have a visible effect unless bilinear/trilinear/anisotropic filtering is
# enabled.
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
# when set to higher number than 0.
fsaa (FSAA) enum 0 0,1,2,4,8,16
[***Shaders]
# Shaders allow advanced visul effects and may increase performance on some video cards.
# Thy only work with the OpenGL video backend.
enable_shaders (Shaders) bool true
[****Bumpmapping]
# Enables bumpmapping for textures. Normalmaps need to be supplied by the texture pack
# or need to be auto-generated.
# Requires shaders to be enabled.
enable_bumpmapping (Bumpmapping) bool false
# Enables on the fly normalmap generation (Emboss effect).
# Requires bumpmapping to be enabled.
generate_normalmaps (Generate normalmaps) bool false
# Strength of generated normalmaps.
normalmaps_strength (Normalmaps strength) float 0.6
# Defines sampling step of texture.
# A higher value results in smoother normal maps.
normalmaps_smooth (Normalmaps sampling) int 0 0 2
[****Parallax Occlusion]
# Enables parallax occlusion mapping.
# Requires shaders to be enabled.
enable_parallax_occlusion (Parallax occlusion) bool false
# 0 = parallax occlusion with slope information (faster).
# 1 = relief mapping (slower, more accurate).
parallax_occlusion_mode (Parallax occlusion mode) int 1 0 1
# Strength of parallax.
3d_parallax_strength (Parallax occlusion strength) float 0.025
# Number of parallax occlusion iterations.
parallax_occlusion_iterations (Parallax occlusion iterations) int 4
# Overall scale of parallax occlusion effect.
parallax_occlusion_scale (Parallax occlusion Scale) float 0.08
# Overall bias of parallax occlusion effect, usually scale/2.
parallax_occlusion_bias (Parallax occlusion bias) float 0.04
[****Waving Nodes]
# Set to true enables waving water.
# Requires shaders to be enabled.
enable_waving_water (Waving water) bool false
water_wave_height (Waving water height) float 1.0
water_wave_length (Waving water length) float 20.0
water_wave_speed (Waving water speed) float 5.0
# Set to true enables waving leaves.
# Requires shaders to be enabled.
enable_waving_leaves (Waving leaves) bool false
# Set to true enables waving plants.
# Requires shaders to be enabled.
enable_waving_plants (Waving plants) bool false
[***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
# to not waste CPU power for no benefit.
fps_max (Maximum FPS) int 60
# Maximum FPS when game is paused.
pause_fps_max (FPS in pause menu) int 20
# The allowed adjustment range for the automatic rendering range adjustment.
# Set this to be equal to viewing range minimum to disable the auto-adjustment algorithm.
viewing_range_nodes_max (Viewing range maximum) int 160
# The allowed adjustment range for the automatic rendering range adjustment.
# 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
# Horizontal initial window size.
screenH (Screen height) int 600
# Fullscreen mode.
fullscreen (Full screen) bool false
# Bits per pixel (aka color depth) in fullscreen mode.
fullscreen_bpp (Full screen BPP) int 24
# Vertical screen synchronization.
vsync (V-Sync) bool false
# Field of view in degrees.
fov (Field of view) int 72 30 160
# Adjust the gamma encoding for the light tables. Lower numbers are brighter.
# This setting is for the client only and is ignored by the server.
display_gamma (Gamma) float 1.8 1.0 3.0
# Path to texture directory. All textures are first searched from here.
texture_path (Texture path) path
# The rendering back-end for Irrlicht.
video_driver (Video driver) enum opengl null,software,burningsvideo,direct3d8,direct3d9,opengl
# Height on which clouds are appearing.
cloud_height (Cloud height) int 120
# Radius of cloud area stated in number of 64 node cloud squares.
# Values larger than 26 will start to produce sharp cutoffs at cloud area corners.
cloud_radius (Cloud radius) int 12
# Multiplier for view bobbing.
# For example: 0 for no view bobbing; 1.0 for normal; 2.0 for double.
view_bobbing_amount (View bobbing) float 1.0
# Multiplier for fall bobbing.
# For example: 0 for no view bobbing; 1.0 for normal; 2.0 for double.
fall_bobbing_amount (Fall bobbing) float 0.0
# 3D support.
# Currently supported:
# - none: no 3d output.
# - anaglyph: cyan/magenta color 3d.
# - interlaced: odd/even line based polarisation screen support.
# - topbottom: split screen top/bottom.
# - sidebyside: split screen side by side.
3d_mode (3D mode) enum none none,anaglyph,interlaced,topbottom,sidebyside
# In-game chat console background color (R,G,B).
console_color (Console color) string (0,0,0)
# In-game chat console background alpha (opaqueness, between 0 and 255).
console_alpha (Console alpha) int 200 0 255
# Selection box border color (R,G,B).
selectionbox_color (Selection box color) string (0,0,0)
# Width of the selectionbox's lines around nodes.
selectionbox_width (Selection box width) int 2 1 5
# Crosshair color (R,G,B).
crosshair_color (Crosshair color) string (255,255,255)
# Crosshair alpha (opaqueness, between 0 and 255).
crosshair_alpha (Crosshair alpha) int 255 0 255
# Whether node texture animations should be desynchronized per mapblock.
desynchronize_mapblock_texture_animation (Desynchronize block animation) bool true
# Maximum proportion of current window to be used for hotbar.
# Useful if there's something to be displayed right or left of hotbar.
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.
enable_mesh_cache (Mesh cache) bool false
# Enables minimap.
enable_minimap (Minimap) bool true
# Shape of the minimap. Enabled = round, disabled = square.
minimap_shape_round (Round minimap) bool true
# True = 256
# False = 128
# Useable to make minimap smoother on slower machines.
minimap_double_scan_height (Minimap scan height) bool true
# Make fog and sky colors depend on daytime (dawn/sunset) and view direction.
directional_colored_fog (Colored fog) bool true
# The strength (darkness) of node ambient-occlusion shading.
# Lower is darker, Higher is lighter. The valid range of values for this
# setting is 0.25 to 4.0 inclusive. If the value is out of range it will be
# set to the nearest valid value.
ambient_occlusion_gamma (Ambient occlusion gamma) float 2.2 0.25 4.0
[**Menus]
# Use a cloud animation for the main menu background.
menu_clouds (Clouds in menu) bool true
# Scale gui by a user specified value.
# Use a nearest-neighbor-anti-alias filter to scale the GUI.
# This will smooth over some of the rough edges, and blend
# pixels when scaling down, at the cost of blurring some
# edge pixels when images are scaled by non-integer sizes.
gui_scaling (GUI scaling) float 1.0
# When gui_scaling_filter is true, all GUI images need to be
# filtered in software, but some images are generated directly
# to hardware (e.g. render-to-texture for nodes in inventory).
gui_scaling_filter (GUI scaling filter) bool false
# When gui_scaling_filter_txr2img is true, copy those images
# from hardware to software for scaling. When false, fall back
# to the old scaling method, for video drivers that don't
# propery support downloading textures back from hardware.
gui_scaling_filter_txr2img (GUI scaling filter txr2img) bool true
# Delay showing tooltips, stated in milliseconds.
tooltip_show_delay (Tooltip delay) int 400
# Whether freetype fonts are used, requires freetype support to be compiled in.
freetype (Freetype fonts) bool true
# Path to TrueTypeFont or bitmap.
font_path (Font path) path fonts/liberationsans.ttf
font_size (Font size) int 15
# Font shadow offset, if 0 then shadow will not be drawn.
font_shadow (Font shadow) int 1
# Font shadow alpha (opaqueness, between 0 and 255).
font_shadow_alpha (Font shadow alpha) int 128 0 255
mono_font_path (Monospace font path) path fonts/liberationmono.ttf
mono_font_size (Monospace font size) int 15
# This font will be used for certain languages.
fallback_font_path (Fallback font) path fonts/DroidSansFallbackFull.ttf
fallback_font_size (Fallback font size) int 15
fallback_font_shadow (Fallback font shadow) int 1
fallback_font_shadow_alpha (Fallback font shadow alpha) int 128 0 255
# Path to save screenshots at.
screenshot_path (Screenshot folder) path
[**Advanced]
# Adjust dpi configuration to your screen (non X11/Android only) e.g. for 4k screens.
screen_dpi (DPI) int 72
[*Sound]
enable_sound (Sound) bool true
sound_volume (Volume) float 0.7 0.0 1.0
[*Advanced]
# Timeout for client to remove unused map data from memory.
client_unload_unused_data_timeout (Mapblock unload timeout) int 600
# Maximum number of mapblocks for client to be kept in memory.
# Set to -1 for unlimited amount.
client_mapblock_limit (Mapblock limit) int 5000
# Whether to show the client debug info (has the same effect as hitting F5).
show_debug (Show debug info) bool false
[Server / Singleplayer]
# Name of the server, to be displayed when players join and in the serverlist.
server_name (Server name) string Minetest server
# Description of server, to be displayed when players join and in the serverlist.
server_description (Server description) string mine here
# Domain name of server, to be displayed in the serverlist.
server_address (Server address) string game.minetest.net
# Homepage of server, to be displayed in the serverlist.
server_url (Server URL) string http://minetest.net
# Automaticaly report to the serverlist.
server_announce (Announce server) bool false
# Announce to this serverlist.
# If you want to announce your ipv6 address, use serverlist_url = v6.servers.minetest.net.
serverlist_url (Serverlist URL) string servers.minetest.net
[*Network]
# Network port to listen (UDP).
# This value will be overridden when starting from the main menu.
port (Server port) int 30000
# The network interface that the server listens on.
bind_address (Bind address) string
# Enable to disallow old clients from connecting.
# Older clients are compatible in the sense that they will not crash when connecting
# to new servers, but they may not support all new features that you are expecting.
strict_protocol_version_checking (Strict protocol checking) bool false
# Specifies URL from which client fetches media instead of using UDP.
# $filename should be accessible from $remote_media$filename via cURL
# (obviously, remote_media should end with a slash).
# Files that are not present will be fetched the usual way.
remote_media (Remote media) string
# Enable/disable running an IPv6 server. An IPv6 server may be restricted
# to IPv6 clients, depending on system configuration.
# Ignored if bind_address is set.
ipv6_server (IPv6 server) bool false
[**Advanced]
# How many blocks are flying in the wire simultaneously per client.
max_simultaneous_block_sends_per_client (Maximum simultaneously blocks send per client) int 10
# How many blocks are flying in the wire simultaneously for the whole server.
max_simultaneous_block_sends_server_total (Maximum simultaneously bocks send total) int 40
# To reduce lag, block transfers are slowed down when a player is building something.
# This determines how long they are slowed down after placing or removing a node.
full_block_send_enable_min_time_from_building () float 2.0
# Maximum number of packets sent per send step, if you have a slow connection
# try reducing it, but don't reduce it to a number below double of targeted
# client number.
max_packets_per_iteration (Max. packets per iteration) int 1024
[*Game]
# Default game when creating a new world.
# This will be overridden when creating a world from the main menu.
default_game (Default game) string minetest
# Message of the day displayed to players connecting.
motd (Message of the day) string
# Maximum number of players that can connect simultaneously.
max_users (Maximum users) int 15
# World directory (everything in the world is stored here).
# Not needed if starting from the main menu.
map-dir (Map directory) path
# Time in seconds for item entity (dropped items) to live.
# Setting it to -1 disables the feature.
item_entity_ttl (Item entity TTL) int 900
# Enable players getting damage and dying.
enable_damage (Damage) bool false
# A chosen map seed for a new map, leave empty for random.
# Will be overridden when creating a new world in the main menu.
fixed_map_seed (Fixed map seed) string
# New users need to input this password.
default_password (Default password) string
# The privileges that new users automatically get.
# See /privs in game for a full list on your server and mod configuration.
default_privs (Default privileges) string interact, shout
# Whether players are shown to clients without any range limit.
# Deprecated, use the setting player_transfer_distance instead.
unlimited_player_transfer_distance (Unlimited player transfer distance) bool true
# Defines the maximal player transfer distance in blocks (0 = unlimited).
player_transfer_distance (Player transfer distance) int 0
# Whether to allow players to damage and kill each other.
enable_pvp (Player versus Player) bool true
# If this is set, players will always (re)spawn at the given position.
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.
disallow_empty_password (Disallow empty passwords) bool false
# If enabled, disable cheat prevention in multiplayer.
disable_anticheat (Disable anticheat) bool false
# If enabled, actions are recorded for rollback.
# This option is only read when server starts.
enable_rollback_recording (Rollback recording) bool false
# A message to be displayed to all clients when the server shuts down.
kick_msg_shutdown (Shutdown message) string Server shutting down.
# A message to be displayed to all clients when the server crashes.
kick_msg_crash (Crash message) string This server has experienced an internal error. You will now be disconnected.
# Whether to ask clients to reconnect after a (Lua) crash.
# Set this to true if your server is set up to restart automatically.
ask_reconnect_on_crash (Ask to reconnect after crash) bool false
# From how far clients know about objects, stated in mapblocks (16 nodes).
active_object_send_range_blocks (Active object send range) int 3
# How large area of blocks are subject to the active block stuff, stated in mapblocks (16 nodes).
# In active blocks objects are loaded and ABMs run.
active_block_range (Active block range) int 2
# From how far blocks are sent to clients, stated in mapblocks (16 nodes).
max_block_send_distance (Max block send distance) int 10
# Maximum number of forceloaded mapblocks.
max_forceloaded_blocks (Maximum forceloaded blocks) int 16
# Interval of sending time of day to clients.
time_send_interval (Time send interval) int 5
# Controls length of day/night cycle.
# Examples: 72 = 20min, 360 = 4min, 1 = 24hour, 0 = day/night/whatever stays unchanged.
time_speed (Time speed) int 72
# Interval of saving important changes in the world, stated in seconds.
server_map_save_interval (Map save interval) float 5.3
[**Physics]
movement_acceleration_default (Default acceleration) float 3
movement_acceleration_air (Acceleration in air) float 2
movement_acceleration_fast (Fast mode acceleration) float 10
movement_speed_walk (Walking speed) float 4
movement_speed_crouch (Crouch speed) float 1.35
movement_speed_fast (Fast mode speed) float 20
movement_speed_climb (Climbing speed) float 2
movement_speed_jump (Jumping speed) float 6.5
movement_speed_descend (Descending speed) float 6
movement_liquid_fluidity (Liquid fluidity) float 1
movement_liquid_fluidity_smooth (Liquid fluidity smoothing) float 0.5
movement_liquid_sink (Liquid sink) float 10
movement_gravity (Gravity) float 9.81
[**Advanced]
# Handling for deprecated lua api calls:
# - legacy: (try to) mimic old behaviour (default for release).
# - log: mimic and log backtrace of deprecated call (default for debug).
# - error: abort on usage of deprecated call (suggested for mod developers).
deprecated_lua_api_handling (Deprecated Lua API handling) enum legacy legacy,log,error
# Useful for mod developers.
mod_profiling (Mod profiling) bool false
# Detailed mod profile data. Useful for mod developers.
detailed_profiling (Detailed mod profiling) bool false
# Profiler data print interval. 0 = disable. Useful for developers.
profiler_print_interval (Profiling print interval) int 0
# Number of extra blocks that can be loaded by /clearobjects at once.
# This is a trade-off between sqlite transaction overhead and
# memory consumption (4096=100MB, as a rule of thumb).
max_clearobjects_extra_loaded_blocks (Max. clearobjects extra blocks) int 4096
# How much the server will wait before unloading unused mapblocks.
# Higher value is smoother, but will use more RAM.
server_unload_unused_data_timeout (Unload unused server data) int 29
# Maximum number of statically stored objects in a block.
max_objects_per_block (Maxmimum objects per block) int 49
# See http://www.sqlite.org/pragma.html#pragma_synchronous
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.
dedicated_server_step (Dedicated server step) float 0.1
# If enabled, invalid world data won't cause the server to shut down.
# Only enable this if you know what you are doing.
ignore_world_load_errors (Ignore world errors) bool false
# Max liquids processed per step.
liquid_loop_max (Liquid loop max) int 100000
# The time (in seconds) that the liquids queue may grow beyond processing
# capacity until an attempt is made to decrease its size by dumping old queue
# items. A value of 0 disables the functionality.
liquid_queue_purge_time (Liquid queue purge time) int 0
# Liquid update interval in seconds.
liquid_update (Liquid update tick) float 1.0
[*Mapgen]
# Name of map generator to be used when creating a new world.
# Creating a world in the main menu will override this.
mg_name (Mapgen name) enum v6 v5,v6,v7,singlenode
# Water surface level of the world.
water_level (Water level) int 1
# From how far blocks are generated for clients, stated in mapblocks (16 nodes).
max_block_generate_distance (Max block generate distance) int 6
# Where the map generator stops.
# Please note:
# - Limited to 31000 (setting above has no effect)
# - The map generator works in groups of 80x80x80 nodes (5x5x5 MapBlocks).
# - Those groups have an offset of -32, -32 nodes from the origin.
# - Only groups which are within the map_generation_limit are generated
map_generation_limit (Map generation limit) int 31000 0 31000
# Global map generation attributes.
# 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.
# 'trees' and 'flat' flags only have effect in mgv6.
mg_flags (Mapgen flags) flags trees,caves,dungeons,light trees,caves,dungeons,light,flat,notrees,nocaves,nodungeons,nolight,noflat
[**Advanced]
# Size of chunks to be generated at once by mapgen, stated in mapblocks (16 nodes).
chunksize (Chunk size) int 5
# Dump the mapgen debug infos.
enable_mapgen_debug_info (Mapgen debug) bool false
# Maximum number of blocks that can be queued for loading.
emergequeue_limit_total (Absolute limit of emerge queues) int 256
# Maximum number of blocks to be queued that are to be loaded from file.
# Set to blank for an appropriate amount to be chosen automatically.
emergequeue_limit_diskonly (Limit of emerge queues on disk) int 32
# Maximum number of blocks to be queued that are to be generated.
# Set to blank for an appropriate amount to be chosen automatically.
emergequeue_limit_generate (Limit of emerge queues to generate) int 32
# Number of emerge threads to use. Make this field blank, or increase this number
# to use multiple threads. On multiprocessor systems, this will improve mapgen speed greatly
# at the cost of slightly buggy caves.
num_emerge_threads (Number of emerge threads) int 1
# Noise parameters for biome API temperature, humidity and biome blend.
mg_biome_np_heat (Mapgen biome heat noise parameters) noise_params 50, 50, (750, 750, 750), 5349, 3, 0.5, 2.0
mg_biome_np_heat_blend (Mapgen heat blend noise parameters) noise_params 0, 1.5, (8, 8, 8), 13, 2, 1.0, 2.0
mg_biome_np_humidity (Mapgen biome humidity noise parameters) noise_params 50, 50, (750, 750, 750), 842, 3, 0.5, 2.0
mg_biome_np_humidity_blend (Mapgen biome humidity blend noise parameters) noise_params 0, 1.5, (8, 8, 8), 90003, 2, 1.0, 2.0
[***Mapgen v5]
mgv5_np_filler_depth (Mapgen v5 filler depth noise parameters) noise_params 0, 1, (150, 150, 150), 261, 4, 0.7, 2.0
mgv5_np_factor (Mapgen v5 factor noise parameters) noise_params 0, 1, (250, 250, 250), 920381, 3, 0.45, 2.0
mgv5_np_height (Mapgen v5 height noise parameters) noise_params 0, 10, (250, 250, 250), 84174, 4, 0.5, 2.0
mgv5_np_cave1 (Mapgen v5 cave1 noise parameters) noise_params 0, 12, (50, 50, 50), 52534, 4, 0.5, 2.0
mgv5_np_cave2 (Mapgen v5 cave2 noise parameters) noise_params 0, 12, (50, 50, 50), 10325, 4, 0.5, 2.0
# TODO
#mgv5_np_ground = {
# offset = 0
# scale = 40
# spread = (80, 80, 80)
# seed = 983240
# octaves = 4
# persistence = 0.55
# lacunarity = 2.0
# flags = "eased"
#}
[***Mapgen v6]
# Map generation attributes specific to Mapgen V6.
# When snowbiomes are enabled jungles are enabled and the jungles flag is ignored.
# 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.
mgv6_spflags (Mapgen v6 flags) flags jungles,biomeblend,mudflow,snowbiomes jungles,biomeblend,mudflow,snowbiomes,nojungles,nobiomeblend,nomudflow,nosnowbiomes
# Controls size of deserts and beaches in Mapgen V6.
# When snowbiomes are enabled 'mgv6_freq_desert' is ignored.
mgv6_freq_desert (Mapgen v6 desert frequency) float 0.45
mgv6_freq_beach (Mapgen v6 beach frequency) float 0.15
mgv6_np_terrain_base (Mapgen v6 terrain base noise parameters) noise_params -4, 20, (250, 250, 250), 82341, 5, 0.6, 2.0
mgv6_np_terrain_higher (Mapgen v6 terrain altitude noise parameters) noise_params 20, 16, (500, 500, 500), 85039, 5, 0.6, 2.0
mgv6_np_steepness (Mapgen v6 steepness noise parameters) noise_params 0.85, 0.5, (125, 125, 125), -932, 5, 0.7, 2.0
mgv6_np_height_select (Mapgen v6 height select noise parameters) noise_params 0.5, 1, (250, 250, 250), 4213, 5, 0.69, 2.0
mgv6_np_mud (Mapgen v6 mud noise parameters) noise_params 4, 2, (200, 200, 200), 91013, 3, 0.55, 2.0
mgv6_np_beach (Mapgen v6 beach noise parameters) noise_params 0, 1, (250, 250, 250), 59420, 3, 0.50, 2.0
mgv6_np_biome (Mapgen v6 biome noise parameters) noise_params 0, 1, (500, 500, 500), 9130, 3, 0.50, 2.0
mgv6_np_cave (Mapgen v6 cave noise parameters) noise_params 6, 6, (250, 250, 250), 34329, 3, 0.50, 2.0
mgv6_np_humidity (Mapgen v6 humidity noise parameters) noise_params 0.5, 0.5, (500, 500, 500), 72384, 3, 0.50, 2.0
mgv6_np_trees (Mapgen v6 trees noise parameters) noise_params 0, 1, (125, 125, 125), 2, 4, 0.66, 2.0
mgv6_np_apple_trees (Mapgen v6 apple trees noise parameters) noise_params 0, 1, (100, 100, 100), 342902, 3, 0.45, 2.0
[***Mapgen v7]
# Map generation attributes specific to Mapgen V7.
# 'ridges' are the rivers.
# 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.
mgv7_spflags (Mapgen v7 flags) flags mountains,ridges mountains,ridges,nomountains,noridges
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_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_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_ridge_uwater (Mapgen v7 ridge water noise parameters) noise_params 0, 1, (1000, 1000, 1000), 85039, 5, 0.6, 2.0
mgv7_np_mountain (Mapgen v7 mountain noise parameters) noise_params -0.6, 1, (250, 350, 250), 5333, 5, 0.63, 2.0
mgv7_np_ridge (Mapgen v7 ridge noise parameters) noise_params 0, 1, (100, 100, 100), 6467, 4, 0.75, 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
[*Security]
# Prevent mods from doing insecure things like running shell commands.
secure.enable_security (Enable mod security) bool false
# Comma-separated list of trusted mods that are allowed to access insecure
# functions even when mod security is on (via request_insecure_environment()).
secure.trusted_mods (Trusted mods) string
[Client and Server]
# Name of the player.
# When running a server, clients connecting with this name are admins.
# When starting from the main menu, this is overridden.
name (Player name) string
# Set the language. Leave empty to use the system language.
# A restart is required after changing this.
language (Language) enum ,be,cs,da,de,eo,es,et,fr,hu,id,it,ja,jbo,ko,ky,lt,nb,nl,pl,pt,pt_BR,ro,ru,tr,uk,zh_CN,zh_TW
# Level of logging to be written to debug.txt:
# - <nothing> (no logging)
# - none (messages with no level)
# - error
# - warning
# - action
# - info
# - verbose
debug_log_level (Debug log level) enum action ,warning,action,info,verbose
# IPv6 support.
enable_ipv6 (IPv6) bool true
[*Advanced]
# Default timeout for cURL, stated in milliseconds.
# Only has an effect if compiled with cURL.
curl_timeout (cURL timeout) int 5000
# Limits number of parallel HTTP requests. Affects:
# - Media fetch if server uses remote_media setting.
# - Serverlist download and server announcement.
# - Downloads performed by main menu (e.g. mod manager).
# Only has an effect if compiled with cURL.
curl_parallel_limit (cURL parallel limit) int 8
# Maximum time in ms a file download (e.g. a mod download) may take.
curl_file_download_timeout (cURL file download timeout) int 300000
# Makes DirectX work with LuaJIT. Disable if it causes troubles.
high_precision_fpu (High-precision FPU) bool true
# Replaces the default main menu with a custom one.
main_menu_script (Main menu script) string
main_menu_game_mgr (Main menu game manager) int 0
main_menu_mod_mgr (Main menu mod manager) int 1
modstore_download_url (Modstore download URL) string https://forum.minetest.net/media/
modstore_listmods_url (Modstore mods list URL) string https://forum.minetest.net/mmdb/mods/
modstore_details_url (Modstore details URL) string https://forum.minetest.net/mmdb/mod/*/

View File

@ -0,0 +1,32 @@
uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform vec3 yawVec;
void main (void)
{
vec2 uv = gl_TexCoord[0].st;
//texture sampling rate
const float step = 1.0 / 256.0;
float tl = texture2D(normalTexture, vec2(uv.x - step, uv.y + step)).r;
float t = texture2D(normalTexture, vec2(uv.x - step, uv.y - step)).r;
float tr = texture2D(normalTexture, vec2(uv.x + step, uv.y + step)).r;
float r = texture2D(normalTexture, vec2(uv.x + step, uv.y)).r;
float br = texture2D(normalTexture, vec2(uv.x + step, uv.y - step)).r;
float b = texture2D(normalTexture, vec2(uv.x, uv.y - step)).r;
float bl = texture2D(normalTexture, vec2(uv.x - step, uv.y - step)).r;
float l = texture2D(normalTexture, vec2(uv.x - step, uv.y)).r;
float dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl);
float dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr);
vec4 bump = vec4 (normalize(vec3 (dX, dY, 0.1)),1.0);
float height = 2.0 * texture2D(normalTexture, vec2(uv.x, uv.y)).r - 1.0;
vec4 base = texture2D(baseTexture, uv).rgba;
vec3 L = normalize(vec3(0.0, 0.75, 1.0));
float specular = pow(clamp(dot(reflect(L, bump.xyz), yawVec), 0.0, 1.0), 1.0);
float diffuse = dot(yawVec, bump.xyz);
vec3 color = (1.1 * diffuse + 0.05 * height + 0.5 * specular) * base.rgb;
vec4 col = vec4(color.rgb, base.a);
col *= gl_Color;
gl_FragColor = vec4(col.rgb, base.a);
}

View File

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

View File

@ -1,6 +1,6 @@
uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D useNormalmap;
uniform sampler2D textureFlags;
uniform vec4 skyBgColor;
uniform float fogDistance;
@ -8,91 +8,137 @@ uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 worldPosition;
varying float area_enable_parallax;
varying vec3 eyeVec;
varying vec3 tsEyeVec;
varying vec3 lightVec;
varying vec3 tsLightVec;
bool normalTexturePresent = false;
bool normalTexturePresent = false;
const float e = 2.718281828459;
const float BS = 10.0;
float intensity (vec3 color){
void get_texture_flags()
{
vec4 flags = texture2D(textureFlags, vec2(0.0, 0.0));
if (flags.r > 0.5) {
normalTexturePresent = true;
}
}
float intensity(vec3 color)
{
return (color.r + color.g + color.b) / 3.0;
}
float get_rgb_height (vec2 uv){
return intensity(texture2D(baseTexture,uv).rgb);
float get_rgb_height(vec2 uv)
{
return intensity(texture2D(baseTexture, uv).rgb);
}
vec4 get_normal_map(vec2 uv){
vec4 get_normal_map(vec2 uv)
{
vec4 bump = texture2D(normalTexture, uv).rgba;
bump.xyz = normalize(bump.xyz * 2.0 -1.0);
bump.y = -bump.y;
bump.xyz = normalize(bump.xyz * 2.0 - 1.0);
return bump;
}
void main (void)
float find_intersection(vec2 dp, vec2 ds)
{
const float depth_step = 1.0 / 24.0;
float depth = 1.0;
for (int i = 0 ; i < 24 ; i++) {
float h = texture2D(normalTexture, dp + ds * depth).a;
if (h >= depth)
break;
depth -= depth_step;
}
return depth;
}
float find_intersectionRGB(vec2 dp, vec2 ds)
{
const float depth_step = 1.0 / 24.0;
float depth = 1.0;
for (int i = 0 ; i < 24 ; i++) {
float h = get_rgb_height(dp + ds * depth);
if (h >= depth)
break;
depth -= depth_step;
}
return depth;
}
void main(void)
{
vec3 color;
vec4 bump;
vec2 uv = gl_TexCoord[0].st;
bool use_normalmap = false;
#ifdef USE_NORMALMAPS
if (texture2D(useNormalmap,vec2(1.0,1.0)).r > 0.0){
normalTexturePresent = true;
}
#endif
get_texture_flags();
#ifdef ENABLE_PARALLAX_OCCLUSION
if (normalTexturePresent){
vec3 tsEye = normalize(tsEyeVec);
float height = PARALLAX_OCCLUSION_SCALE * texture2D(normalTexture, uv).a - PARALLAX_OCCLUSION_BIAS;
uv = uv + texture2D(normalTexture, uv).z * height * vec2(tsEye.x,-tsEye.y);
vec2 eyeRay = vec2 (tsEyeVec.x, -tsEyeVec.y);
const float scale = PARALLAX_OCCLUSION_SCALE / PARALLAX_OCCLUSION_ITERATIONS;
const float bias = PARALLAX_OCCLUSION_BIAS / PARALLAX_OCCLUSION_ITERATIONS;
#if PARALLAX_OCCLUSION_MODE == 0
// Parallax occlusion with slope information
if (normalTexturePresent && area_enable_parallax > 0.0) {
for (int i = 0; i < PARALLAX_OCCLUSION_ITERATIONS; i++) {
vec4 normal = texture2D(normalTexture, uv.xy);
float h = normal.a * scale - bias;
uv += h * normal.z * eyeRay;
}
#endif
#if PARALLAX_OCCLUSION_MODE == 1
// Relief mapping
if (normalTexturePresent && area_enable_parallax > 0.0) {
vec2 ds = eyeRay * PARALLAX_OCCLUSION_SCALE;
float dist = find_intersection(uv, ds);
uv += dist * ds;
#endif
} else if (GENERATE_NORMALMAPS == 1 && area_enable_parallax > 0.0) {
vec2 ds = eyeRay * PARALLAX_OCCLUSION_SCALE;
float dist = find_intersectionRGB(uv, ds);
uv += dist * ds;
}
#endif
#ifdef USE_NORMALMAPS
if (normalTexturePresent){
#if USE_NORMALMAPS == 1
if (normalTexturePresent) {
bump = get_normal_map(uv);
use_normalmap = true;
}
#endif
#ifdef GENERATE_NORMALMAPS
if (use_normalmap == false){
float tl = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y+SAMPLE_STEP));
float t = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y-SAMPLE_STEP));
float tr = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y+SAMPLE_STEP));
float r = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y));
float br = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y-SAMPLE_STEP));
float b = get_rgb_height (vec2(uv.x,uv.y-SAMPLE_STEP));
float bl = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y-SAMPLE_STEP));
float l = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y));
float dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl);
float dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr);
bump = vec4 (normalize(vec3 (dX, -dY, NORMALMAPS_STRENGTH)),1.0);
use_normalmap = true;
}
#endif
vec4 base = texture2D(baseTexture, uv).rgba;
if (GENERATE_NORMALMAPS == 1 && normalTexturePresent == false) {
float tl = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y + SAMPLE_STEP));
float t = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y - SAMPLE_STEP));
float tr = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y + SAMPLE_STEP));
float r = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y));
float br = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y - SAMPLE_STEP));
float b = get_rgb_height(vec2(uv.x, uv.y - SAMPLE_STEP));
float bl = get_rgb_height(vec2(uv.x -SAMPLE_STEP, uv.y - SAMPLE_STEP));
float l = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y));
float dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl);
float dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr);
bump = vec4(normalize(vec3 (dX, dY, NORMALMAPS_STRENGTH)), 1.0);
use_normalmap = true;
}
vec4 base = texture2D(baseTexture, uv).rgba;
#ifdef ENABLE_BUMPMAPPING
if (use_normalmap){
if (use_normalmap) {
vec3 L = normalize(lightVec);
vec3 E = normalize(eyeVec);
float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0),0.5);
float diffuse = dot(E,bump.xyz);
/* Mathematic optimization
* Original: color = 0.05*base.rgb + diffuse*base.rgb + 0.2*specular*base.rgb;
* This optimization save 2 multiplications (orig: 4 multiplications + 3 additions
* end: 2 multiplications + 3 additions)
*/
color = (0.05 + diffuse + 0.2 * specular) * base.rgb;
float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0), 1.0);
float diffuse = dot(-E,bump.xyz);
color = (diffuse + 0.1 * specular) * base.rgb;
} else {
color = base.rgb;
}
@ -104,7 +150,7 @@ vec4 base = texture2D(baseTexture, uv).rgba;
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));
alpha = mix(alpha, 0.0, d);
}
@ -112,7 +158,7 @@ vec4 base = texture2D(baseTexture, uv).rgba;
#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));
col = mix(col, skyBgColor, d);
}

View File

@ -14,105 +14,108 @@ varying vec3 eyeVec;
varying vec3 lightVec;
varying vec3 tsEyeVec;
varying vec3 tsLightVec;
varying float area_enable_parallax;
varying float disp;
const float e = 2.718281828459;
const float BS = 10.0;
float smoothCurve( float x ) {
return x * x *( 3.0 - 2.0 * x );
float smoothCurve(float x)
{
return x * x * (3.0 - 2.0 * x);
}
float triangleWave( float x ) {
return abs( fract( x + 0.5 ) * 2.0 - 1.0 );
float triangleWave(float x)
{
return abs(fract(x + 0.5) * 2.0 - 1.0);
}
float smoothTriangleWave( float x ) {
return smoothCurve( triangleWave( x ) ) * 2.0 - 1.0;
float smoothTriangleWave(float x)
{
return smoothCurve(triangleWave(x)) * 2.0 - 1.0;
}
void main(void)
{
gl_TexCoord[0] = gl_MultiTexCoord0;
#if (MATERIAL_TYPE == TILE_MATERIAL_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_LIQUID_OPAQUE) && ENABLE_WAVING_WATER
//TODO: make offset depending on view angle and parallax uv displacement
//thats for textures that doesnt align vertically, like dirt with grass
//gl_TexCoord[0].y += 0.008;
//Allow parallax/relief mapping only for certain kind of nodes
//Variable is also used to control area of the effect
#if (DRAW_TYPE == NDT_NORMAL || DRAW_TYPE == NDT_LIQUID || DRAW_TYPE == NDT_FLOWINGLIQUID)
area_enable_parallax = 1.0;
#else
area_enable_parallax = 0.0;
#endif
#if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES && ENABLE_WAVING_LEAVES) || (MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS && ENABLE_WAVING_PLANTS)
vec4 pos2 = mWorld * gl_Vertex;
float tOffset = (pos2.x + pos2.y) * 0.001 + pos2.z * 0.002;
disp = (smoothTriangleWave(animationTimer * 31.0 + tOffset) +
smoothTriangleWave(animationTimer * 29.0 + tOffset) +
smoothTriangleWave(animationTimer * 13.0 + tOffset)) - 0.9;
#endif
#if (MATERIAL_TYPE == TILE_MATERIAL_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_LIQUID_OPAQUE) && ENABLE_WAVING_WATER
vec4 pos = gl_Vertex;
pos.y -= 2.0;
float posYbuf = (pos.z / WATER_WAVE_LENGTH + animationTimer * WATER_WAVE_SPEED * WATER_WAVE_LENGTH);
pos.y -= sin(posYbuf) * WATER_WAVE_HEIGHT + sin(posYbuf / 7.0) * WATER_WAVE_HEIGHT;
gl_Position = mWorldViewProj * pos;
#elif MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES && ENABLE_WAVING_LEAVES
vec4 pos = gl_Vertex;
vec4 pos2 = mWorld * gl_Vertex;
/*
* Mathematic optimization: pos2.x * A + pos2.z * A (2 multiplications + 1 addition)
* replaced with: (pos2.x + pos2.z) * A (1 addition + 1 multiplication)
* And bufferize calcul to a float
*/
float pos2XpZ = pos2.x + pos2.z;
pos.x += (smoothTriangleWave(animationTimer*10.0 + pos2XpZ * 0.01) * 2.0 - 1.0) * 0.4;
pos.y += (smoothTriangleWave(animationTimer*15.0 + pos2XpZ * -0.01) * 2.0 - 1.0) * 0.2;
pos.z += (smoothTriangleWave(animationTimer*10.0 + pos2XpZ * -0.01) * 2.0 - 1.0) * 0.4;
pos.x += disp * 0.1;
pos.y += disp * 0.1;
pos.z += disp;
gl_Position = mWorldViewProj * pos;
#elif MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS && ENABLE_WAVING_PLANTS
vec4 pos = gl_Vertex;
vec4 pos2 = mWorld * gl_Vertex;
if (gl_TexCoord[0].y < 0.05) {
/*
* Mathematic optimization: pos2.x * A + pos2.z * A (2 multiplications + 1 addition)
* replaced with: (pos2.x + pos2.z) * A (1 addition + 1 multiplication)
* And bufferize calcul to a float
*/
float pos2XpZ = pos2.x + pos2.z;
pos.x += (smoothTriangleWave(animationTimer * 20.0 + pos2XpZ * 0.1) * 2.0 - 1.0) * 0.8;
pos.y -= (smoothTriangleWave(animationTimer * 10.0 + pos2XpZ * -0.5) * 2.0 - 1.0) * 0.4;
pos.z += disp;
}
gl_Position = mWorldViewProj * pos;
#else
gl_Position = mWorldViewProj * gl_Vertex;
#endif
vPosition = gl_Position.xyz;
worldPosition = (mWorld * gl_Vertex).xyz;
// Don't generate heightmaps when too far from the eye
float dist = distance (vec3(0.0, 0.0 ,0.0), vPosition);
if (dist > 150.0) {
area_enable_parallax = 0.0;
}
vec3 sunPosition = vec3 (0.0, eyePosition.y * BS + 900.0, 0.0);
vec3 normal, tangent, binormal;
normal = normalize(gl_NormalMatrix * gl_Normal);
if (gl_Normal.x > 0.5) {
// 1.0, 0.0, 0.0
tangent = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, -1.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
} else if (gl_Normal.x < -0.5) {
// -1.0, 0.0, 0.0
tangent = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
} else if (gl_Normal.y > 0.5) {
// 0.0, 1.0, 0.0
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
} else if (gl_Normal.y < -0.5) {
// 0.0, -1.0, 0.0
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, 0.0, 1.0));
} else if (gl_Normal.z > 0.5) {
// 0.0, 0.0, 1.0
tangent = normalize(gl_NormalMatrix * vec3( 1.0, 0.0, 0.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
} else if (gl_Normal.z < -0.5) {
// 0.0, 0.0, -1.0
tangent = normalize(gl_NormalMatrix * vec3(-1.0, 0.0, 0.0));
binormal = normalize(gl_NormalMatrix * vec3( 0.0, -1.0, 0.0));
}
mat3 tbnMatrix = mat3( tangent.x, binormal.x, normal.x,
tangent.y, binormal.y, normal.y,
tangent.z, binormal.z, normal.z);
tangent = normalize(gl_NormalMatrix * gl_MultiTexCoord1.xyz);
binormal = normalize(gl_NormalMatrix * gl_MultiTexCoord2.xyz);
vec3 v;
lightVec = sunPosition - worldPosition;
tsLightVec = lightVec * tbnMatrix;
eyeVec = (gl_ModelViewMatrix * gl_Vertex).xyz;
tsEyeVec = eyeVec * tbnMatrix;
v.x = dot(lightVec, tangent);
v.y = dot(lightVec, binormal);
v.z = dot(lightVec, normal);
tsLightVec = normalize (v);
eyeVec = -(gl_ModelViewMatrix * gl_Vertex).xyz;
v.x = dot(eyeVec, tangent);
v.y = dot(eyeVec, binormal);
v.z = dot(eyeVec, normal);
tsEyeVec = normalize (v);
vec4 color;
float day = gl_Color.r;

View File

@ -1,6 +1,6 @@
uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D useNormalmap;
uniform sampler2D textureFlags;
uniform vec4 skyBgColor;
uniform float fogDistance;
@ -14,41 +14,59 @@ varying vec3 tsEyeVec;
varying vec3 lightVec;
varying vec3 tsLightVec;
bool normalTexturePresent = false;
bool normalTexturePresent = false;
bool texTileableHorizontal = false;
bool texTileableVertical = false;
bool texSeamless = false;
const float e = 2.718281828459;
const float BS = 10.0;
float intensity (vec3 color){
void get_texture_flags()
{
vec4 flags = texture2D(textureFlags, vec2(0.0, 0.0));
if (flags.r > 0.5) {
normalTexturePresent = true;
}
if (flags.g > 0.5) {
texTileableHorizontal = true;
}
if (flags.b > 0.5) {
texTileableVertical = true;
}
if (texTileableHorizontal && texTileableVertical) {
texSeamless = true;
}
}
float intensity(vec3 color)
{
return (color.r + color.g + color.b) / 3.0;
}
float get_rgb_height (vec2 uv){
float get_rgb_height(vec2 uv)
{
return intensity(texture2D(baseTexture,uv).rgb);
}
vec4 get_normal_map(vec2 uv){
vec4 get_normal_map(vec2 uv)
{
vec4 bump = texture2D(normalTexture, uv).rgba;
bump.xyz = normalize(bump.xyz * 2.0 -1.0);
bump.y = -bump.y;
return bump;
}
void main (void)
void main(void)
{
vec3 color;
vec4 bump;
vec2 uv = gl_TexCoord[0].st;
bool use_normalmap = false;
#ifdef USE_NORMALMAPS
if (texture2D(useNormalmap,vec2(1.0,1.0)).r > 0.0){
normalTexturePresent = true;
}
#endif
get_texture_flags();
#ifdef ENABLE_PARALLAX_OCCLUSION
if (normalTexturePresent){
if (normalTexturePresent) {
vec3 tsEye = normalize(tsEyeVec);
float height = PARALLAX_OCCLUSION_SCALE * texture2D(normalTexture, uv).a - PARALLAX_OCCLUSION_BIAS;
uv = uv + texture2D(normalTexture, uv).z * height * vec2(tsEye.x,-tsEye.y);
@ -56,14 +74,13 @@ void main (void)
#endif
#ifdef USE_NORMALMAPS
if (normalTexturePresent){
if (normalTexturePresent) {
bump = get_normal_map(uv);
use_normalmap = true;
}
#endif
#ifdef GENERATE_NORMALMAPS
if (use_normalmap == false){
if (GENERATE_NORMALMAPS == 1 && use_normalmap == false) {
float tl = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y+SAMPLE_STEP));
float t = get_rgb_height (vec2(uv.x-SAMPLE_STEP,uv.y-SAMPLE_STEP));
float tr = get_rgb_height (vec2(uv.x+SAMPLE_STEP,uv.y+SAMPLE_STEP));
@ -77,16 +94,15 @@ void main (void)
bump = vec4 (normalize(vec3 (dX, -dY, NORMALMAPS_STRENGTH)),1.0);
use_normalmap = true;
}
#endif
vec4 base = texture2D(baseTexture, uv).rgba;
#ifdef ENABLE_BUMPMAPPING
if (use_normalmap){
if (use_normalmap) {
vec3 L = normalize(lightVec);
vec3 E = normalize(eyeVec);
float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0),0.5);
float diffuse = dot(E,bump.xyz);
float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0),0.5);
float diffuse = dot(E,bump.xyz);
/* Mathematic optimization
* Original: color = 0.05*base.rgb + diffuse*base.rgb + 0.2*specular*base.rgb;
* This optimization save 2 multiplications (orig: 4 multiplications + 3 additions

View File

@ -18,20 +18,23 @@ varying vec3 tsLightVec;
const float e = 2.718281828459;
const float BS = 10.0;
float smoothCurve( float x ) {
return x * x *( 3.0 - 2.0 * x );
float smoothCurve(float x)
{
return x * x * (3.0 - 2.0 * x);
}
float triangleWave( float x ) {
return abs( fract( x + 0.5 ) * 2.0 - 1.0 );
float triangleWave(float x)
{
return abs(fract( x + 0.5 ) * 2.0 - 1.0);
}
float smoothTriangleWave( float x ) {
return smoothCurve( triangleWave( x ) ) * 2.0 - 1.0;
float smoothTriangleWave(float x)
{
return smoothCurve(triangleWave( x )) * 2.0 - 1.0;
}
void main(void)
{
gl_TexCoord[0] = gl_MultiTexCoord0;
#if (MATERIAL_TYPE == TILE_MATERIAL_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_LIQUID_OPAQUE) && ENABLE_WAVING_WATER
vec4 pos = gl_Vertex;
pos.y -= 2.0;

View File

@ -0,0 +1,114 @@
uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D textureFlags;
uniform vec4 skyBgColor;
uniform float fogDistance;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 worldPosition;
varying vec3 eyeVec;
varying vec3 lightVec;
bool normalTexturePresent = false;
bool texTileableHorizontal = false;
bool texTileableVertical = false;
bool texSeamless = false;
const float e = 2.718281828459;
const float BS = 10.0;
void get_texture_flags()
{
vec4 flags = texture2D(textureFlags, vec2(0.0, 0.0));
if (flags.r > 0.5) {
normalTexturePresent = true;
}
if (flags.g > 0.5) {
texTileableHorizontal = true;
}
if (flags.b > 0.5) {
texTileableVertical = true;
}
if (texTileableHorizontal && texTileableVertical) {
texSeamless = true;
}
}
float intensity(vec3 color)
{
return (color.r + color.g + color.b) / 3.0;
}
float get_rgb_height(vec2 uv)
{
if (texSeamless) {
return intensity(texture2D(baseTexture, uv).rgb);
} else {
return intensity(texture2D(baseTexture, clamp(uv, 0.0, 0.999)).rgb);
}
}
vec4 get_normal_map(vec2 uv)
{
vec4 bump = texture2D(normalTexture, uv).rgba;
bump.xyz = normalize(bump.xyz * 2.0 - 1.0);
return bump;
}
void main(void)
{
vec3 color;
vec4 bump;
vec2 uv = gl_TexCoord[0].st;
bool use_normalmap = false;
get_texture_flags();
#if USE_NORMALMAPS == 1
if (normalTexturePresent) {
bump = get_normal_map(uv);
use_normalmap = true;
}
#endif
if (GENERATE_NORMALMAPS == 1 && normalTexturePresent == false) {
float tl = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y + SAMPLE_STEP));
float t = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y - SAMPLE_STEP));
float tr = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y + SAMPLE_STEP));
float r = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y));
float br = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y - SAMPLE_STEP));
float b = get_rgb_height(vec2(uv.x, uv.y - SAMPLE_STEP));
float bl = get_rgb_height(vec2(uv.x -SAMPLE_STEP, uv.y - SAMPLE_STEP));
float l = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y));
float dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl);
float dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr);
bump = vec4(normalize(vec3 (dX, dY, NORMALMAPS_STRENGTH)), 1.0);
use_normalmap = true;
}
vec4 base = texture2D(baseTexture, uv).rgba;
#ifdef ENABLE_BUMPMAPPING
if (use_normalmap) {
vec3 L = normalize(lightVec);
vec3 E = normalize(eyeVec);
float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0), 1.0);
float diffuse = dot(-E,bump.xyz);
color = (diffuse + 0.1 * specular) * base.rgb;
} else {
color = base.rgb;
}
#else
color = base.rgb;
#endif
vec4 col = vec4(color.rgb, base.a);
col *= gl_Color;
if (fogDistance != 0.0) {
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
col = mix(col, skyBgColor, d);
}
gl_FragColor = vec4(col.rgb, base.a);
}

View File

@ -0,0 +1,35 @@
uniform mat4 mWorldViewProj;
uniform mat4 mInvWorld;
uniform mat4 mTransWorld;
uniform mat4 mWorld;
uniform float dayNightRatio;
uniform vec3 eyePosition;
uniform float animationTimer;
varying vec3 vPosition;
varying vec3 worldPosition;
varying vec3 eyeVec;
varying vec3 lightVec;
varying vec3 tsEyeVec;
varying vec3 tsLightVec;
const float e = 2.718281828459;
const float BS = 10.0;
void main(void)
{
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = mWorldViewProj * gl_Vertex;
vPosition = gl_Position.xyz;
worldPosition = (mWorld * gl_Vertex).xyz;
vec3 sunPosition = vec3 (0.0, eyePosition.y * BS + 900.0, 0.0);
lightVec = sunPosition - worldPosition;
eyeVec = -(gl_ModelViewMatrix * gl_Vertex).xyz;
gl_FrontColor = gl_BackColor = gl_Color;
}

View File

@ -8,7 +8,7 @@ option(ENABLE_SYSTEM_JSONCPP "Enable using a system-wide JSONCPP. May cause seg
if(ENABLE_SYSTEM_JSONCPP)
find_library(JSON_LIBRARY NAMES jsoncpp)
find_path(JSON_INCLUDE_DIR json/features.h)
find_path(JSON_INCLUDE_DIR json/features.h PATH_SUFFIXES jsoncpp)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(JSONCPP DEFAULT_MSG JSON_LIBRARY JSON_INCLUDE_DIR)

View File

@ -12,6 +12,8 @@ SORT_MEMBERS_CTORS_1ST = YES
WARN_IF_UNDOCUMENTED = NO
INPUT = @CMAKE_CURRENT_SOURCE_DIR@/src/ \
@CMAKE_CURRENT_SOURCE_DIR@/src/client \
@CMAKE_CURRENT_SOURCE_DIR@/src/network \
@CMAKE_CURRENT_SOURCE_DIR@/src/util \
@CMAKE_CURRENT_SOURCE_DIR@/src/script \
@CMAKE_CURRENT_SOURCE_DIR@/src/script/common \

View File

@ -74,7 +74,7 @@ Compiling on GNU/Linux:
-----------------------
Install dependencies. Here's an example for Debian/Ubuntu:
$ sudo apt-get install build-essential libirrlicht-dev cmake libbz2-dev libpng12-dev libjpeg8-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-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
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.
@ -125,8 +125,10 @@ ENABLE_GETTEXT - Build with Gettext; Allows using translations
ENABLE_GLES - Search for Open GLES headers & libraries and use them
ENABLE_LEVELDB - Build with LevelDB; Enables use of LevelDB map backend (faster than SQLite3)
ENABLE_REDIS - Build with libhiredis; Enables use of Redis map backend
ENABLE_SPATIAL - Build with LibSpatial; Speeds up AreaStores
ENABLE_SOUND - Build with OpenAL, libogg & libvorbis; in-game Sounds
ENABLE_LUAJIT - Build with LuaJIT (much faster than non-JIT Lua)
ENABLE_SYSTEM_GMP - Use GMP from system (much faster than bundled mini-gmp)
RUN_IN_PLACE - Create a portable install (worlds, settings etc. in current directory)
USE_GPROF - Enable profiling using GProf
VERSION_EXTRA - Text to append to version (e.g. VERSION_EXTRA=foobar -> MultiCraft 0.1-foobar)
@ -149,14 +151,16 @@ GETTEXT_ICONV_DLL - Only when building with Gettext on Windows; pa
GETTEXT_INCLUDE_DIR - Only when building with Gettext; directory that contains iconv.h
GETTEXT_LIBRARY - Only when building with Gettext on Windows; path to libintl.dll.a
GETTEXT_MSGFMT - Only when building with Gettext; path to msgfmt/msgfmt.exe
IRRLICHT_DLL - path to Irrlicht.dll
IRRLICHT_INCLUDE_DIR - directory that contains IrrCompileConfig.h
IRRLICHT_LIBRARY - path to libIrrlicht.a/libIrrlicht.so/libIrrlicht.dll.a
IRRLICHT_DLL - Only on Windows; path to Irrlicht.dll
IRRLICHT_INCLUDE_DIR - Directory that contains IrrCompileConfig.h
IRRLICHT_LIBRARY - Path to libIrrlicht.a/libIrrlicht.so/libIrrlicht.dll.a/Irrlicht.lib
LEVELDB_INCLUDE_DIR - Only when building with LevelDB; directory that contains db.h
LEVELDB_LIBRARY - Only when building with LevelDB; path to libleveldb.a/libleveldb.so/libleveldb.dll.a
LEVELDB_DLL - Only when building with LevelDB on Windows; path to libleveldb.dll
REDIS_INCLUDE_DIR - Only when building with Redis support; directory that contains hiredis.h
REDIS_LIBRARY - Only when building with Redis support; path to libhiredis.a/libhiredis.so
REDIS_INCLUDE_DIR - Only when building with Redis; directory that contains hiredis.h
REDIS_LIBRARY - Only when building with Redis; path to libhiredis.a/libhiredis.so
SPATIAL_INCLUDE_DIR - Only when building with LibSpatial; directory that contains spatialindex/SpatialIndex.h
SPATIAL_LIBRARY - Only when building with LibSpatial; path to libspatialindex_c.so/spatialindex-32.lib
LUA_INCLUDE_DIR - Only if you want to use LuaJIT; directory where luajit.h is located
LUA_LIBRARY - Only if you want to use LuaJIT; path to libluajit.a/libluajit.so
MINGWM10_DLL - Only if compiling with MinGW; path to mingwm10.dll
@ -168,8 +172,8 @@ OPENAL_INCLUDE_DIR - Only if building with sound; directory where a
OPENAL_LIBRARY - Only if building with sound; path to libopenal.a/libopenal.so/OpenAL32.lib
OPENGLES2_INCLUDE_DIR - Only if building with GLES; directory that contains gl2.h
OPENGLES2_LIBRARY - Only if building with GLES; path to libGLESv2.a/libGLESv2.so
SQLITE3_INCLUDE_DIR - Only if you want to use SQLite from your OS; directory that contains sqlite3.h
SQLITE3_LIBRARY - Only if you want to use the SQLite from your OS; path to libsqlite3.a/libsqlite3.so
SQLITE3_INCLUDE_DIR - Directory that contains sqlite3.h
SQLITE3_LIBRARY - Path to libsqlite3.a/libsqlite3.so/sqlite3.lib
VORBISFILE_DLL - Only if building with sound on Windows; path to libvorbisfile-3.dll
VORBISFILE_LIBRARY - Only if building with sound; path to libvorbisfile.a/libvorbisfile.so/libvorbisfile.dll.a
VORBIS_DLL - Only if building with sound on Windows; path to libvorbis-0.dll
@ -178,8 +182,8 @@ VORBIS_LIBRARY - Only if building with sound; path to libvorbis
XXF86VM_LIBRARY - Only on Linux; path to libXXf86vm.a/libXXf86vm.so
ZLIB_DLL - Only on Windows; path to zlib1.dll
ZLIBWAPI_DLL - Only on Windows; path to zlibwapi.dll
ZLIB_INCLUDE_DIR - directory where zlib.h is located
ZLIB_LIBRARY - path to libz.a/libz.so/zlibwapi.lib
ZLIB_INCLUDE_DIR - Directory that contains zlib.h
ZLIB_LIBRARY - Path to libz.a/libz.so/zlibwapi.lib
Compiling on Windows:
---------------------
@ -314,4 +318,165 @@ exit /b 0
:fail
popd
echo Failed.
exit /b 1
exit /b 1
License of Minetest textures and sounds
---------------------------------------
This applies to textures and sounds contained in the main Minetest
distribution.
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
http://creativecommons.org/licenses/by-sa/3.0/
Authors of media files
-----------------------
Everything not listed in here:
Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
BlockMen:
textures/base/pack/menuheader.png
erlehmann:
misc/minetest-icon-24x24.png
misc/minetest-icon.ico
misc/minetest.svg
textures/base/pack/logo.png
License of Minetest source code
-------------------------------
Minetest
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
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 3.0 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.
Irrlicht
---------------
This program uses the Irrlicht Engine. http://irrlicht.sourceforge.net/
The Irrlicht Engine License
Copyright © 2002-2005 Nikolaus Gebhardt
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute
it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you
must not claim that you wrote the original software. If you use
this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
JThread
---------------
This program uses the JThread library. License for JThread follows:
Copyright (c) 2000-2006 Jori Liesenborgs (jori.liesenborgs@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
Lua
---------------
Lua is licensed under the terms of the MIT license reproduced below.
This means that Lua is free software and can be used for both academic
and commercial purposes at absolutely no cost.
For details and rationale, see http://www.lua.org/license.html .
Copyright (C) 1994-2008 Lua.org, PUC-Rio.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Fonts
---------------
DejaVu Sans Mono:
Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below)
Bitstream Vera Fonts Copyright:
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
a trademark of Bitstream, Inc.
Arev Fonts Copyright:
Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.
Liberation Fonts Copyright:
Copyright (c) 2007 Red Hat, Inc. All rights reserved. LIBERATION is a trademark of Red Hat, Inc.
DroidSansFallback:
Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,4 +1,4 @@
Minetest Lua Modding API Reference 0.4.12
Minetest Lua Modding API Reference 0.4.13
=========================================
* More information at <http://www.minetest.net/>
* Developer Wiki: <http://dev.minetest.net/>
@ -64,6 +64,17 @@ e.g.
The game directory can contain the file minetest.conf, which will be used
to set default settings when running the particular game.
It can also contain a settingtypes.txt in the same format as the one in builtin.
This settingtypes.txt will be parsed by the menu and the settings will be displayed in the "Games" category in the settings tab.
### Menu images
Games can provide custom main menu images. They are put inside a `menu` directory inside the game directory.
The images are named `$identifier.png`, where `$identifier` is one of `overlay,background,footer,header`.
If you want to specify multiple images for one identifier, add additional images named like `$identifier.$n.png`, with an ascending number $n starting with 1,
and a random image will be chosen from the provided ones.
Mod load path
-------------
@ -116,6 +127,7 @@ Mod directory structure
| |-- depends.txt
| |-- screenshot.png
| |-- description.txt
| |-- settingtypes.txt
| |-- init.lua
| |-- models
| |-- textures
@ -146,6 +158,10 @@ A screenshot shown in modmanager within mainmenu.
### `description.txt`
A File containing description to be shown within mainmenu.
### `settingtypes.txt`
A file in the same format as the one in builtin. It will be parsed by the
settings menu and the settings will be displayed in the "Mods" category.
### `init.lua`
The main Lua script. Running this script should register everything it
wants to register. Subsequent execution depends on minetest calling the
@ -384,13 +400,13 @@ Examples of sound parameter tables:
{
pos = {x=1,y=2,z=3},
gain = 1.0, -- default
max_hear_distance = 32, -- default
max_hear_distance = 32, -- default, uses an euclidean metric
}
-- Play connected to an object, looped
{
object = <an ObjectRef>,
gain = 1.0, -- default
max_hear_distance = 32, -- default
max_hear_distance = 32, -- default, uses an euclidean metric
loop = true, -- only sounds connected to objects can be looped
}
@ -529,6 +545,10 @@ node definition:
0 = y+ 1 = z+ 2 = z- 3 = x+ 4 = x- 5 = y-
facedir's two less significant bits are rotation around the axis
paramtype2 == "leveled"
paramtype2 == "degrotate"
^ The rotation of this node is stored in param2. Plants are rotated this way.
Values range 0 - 179. The value stored in param2 is multiplied by two to
get the actual rotation of the node.
collision_box = {
type = "fixed",
fixed = {
@ -705,24 +725,40 @@ a non-equal distribution of ore.
### `sheet`
Creates a sheet of ore in a blob shape according to the 2D perlin noise
described by `noise_params`. The relative height of the sheet can be
controlled by the same perlin noise as well, by specifying a non-zero
`scale` parameter in `noise_params`.
described by `noise_params` and `noise_threshold`. This is essentially an
improved version of the so-called "stratus" ore seen in some unofficial mods.
**IMPORTANT**: The noise is not transformed by `offset` or `scale` when comparing
against the noise threshold, but scale is used to determine relative height.
The height of the blob is randomly scattered, with a maximum height of `clust_size`.
This sheet consists of vertical columns of uniform randomly distributed height,
varying between the inclusive range `column_height_min` and `column_height_max`.
If `column_height_min` is not specified, this parameter defaults to 1.
If `column_height_max` is not specified, this parameter defaults to `clust_size`
for reverse compatibility. New code should prefer `column_height_max`.
`clust_scarcity` and `clust_num_ores` are ignored.
The `column_midpoint_factor` parameter controls the position of the column at which
ore eminates from. If 1, columns grow upward. If 0, columns grow downward. If 0.5,
columns grow equally starting from each direction. `column_midpoint_factor` is a
decimal number ranging in value from 0 to 1. If this parameter is not specified,
the default is 0.5.
The ore parameters `clust_scarcity` and `clust_num_ores` are ignored for this ore type.
### `puff`
Creates a sheet of ore in a cloud-like puff shape.
As with the `sheet` ore type, the size and shape of puffs are described by
`noise_params` and `noise_threshold` and are placed at random vertical positions
within the currently generated chunk.
The vertical top and bottom displacement of each puff are determined by the noise
parameters `np_puff_top` and `np_puff_bottom`, respectively.
This is essentially an improved version of the so-called "stratus" ore seen in
some unofficial mods.
### `blob`
Creates a deformed sphere of ore according to 3d perlin noise described by
`noise_params`. The maximum size of the blob is `clust_size`, and
`clust_scarcity` has the same meaning as with the `scatter` type.
### `vein
### `vein`
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
`noise_params`. `random_factor` varies the influence random chance has on
@ -757,19 +793,28 @@ Also produce this same ore between the height range of `-y_max` and `-y_min`.
Useful for having ore in sky realms without having to duplicate ore entries.
### `puff_cliffs`
If set, puff ore generation will not taper down large differences in displacement
when approaching the edge of a puff. This flag has no effect for ore types other
than `puff`.
### `puff_additive_composition`
By default, when noise described by `np_puff_top` or `np_puff_bottom` results in a
negative displacement, the sub-column at that point is not generated. With this
attribute set, puff ore generation will instead generate the absolute difference in
noise displacement values. This flag has no effect for ore types other than `puff`.
Decoration types
----------------
The varying types of decorations that can be placed.
The default value is `simple`, and is currently the only type supported.
### `simple`
Creates a 1 times `H` times 1 column of a specified node (or a random node from
a list, if a decoration list is specified). Can specify a certain node it must
spawn next to, such as water or lava, for example. Can also generate a
decoration of random height between a specified lower and upper bound.
This type of decoration is intended for placement of grass, flowers, cacti,
papyri, and so on.
papyri, waterlilies and so on.
### `schematic`
Copies a box of `MapNodes` from a specified schematic file (or raw description).
@ -808,8 +853,8 @@ Schematic attributes
--------------------
See section "Flag Specifier Format".
Currently supported flags: `place_center_x`, `place_center_y`,
`place_center_z`, `force_placement`.
Currently supported flags: `place_center_x`, `place_center_y`, `place_center_z`,
`force_placement`.
* `place_center_x`: Placement of this decoration is centered along the X axis.
* `place_center_y`: Placement of this decoration is centered along the Y axis.
@ -1340,6 +1385,17 @@ examples.
#### `list[<inventory location>;<list name>;<X>,<Y>;<W>,<H>;<starting item index>]`
* Show an inventory list
#### `listring[<inventory location>;<list name>]`
* Allows to create a ring of inventory lists
* Shift-clicking on items in one element of the ring
* will send them to the next inventory list inside the ring
* The first occurrence of an element inside the ring will
* determine the inventory where items will be sent to
#### `listring[]`
* Shorthand for doing `listring[<inventory location>;<list name>]`
* for the last two inventory lists added by list[...]
#### `listcolors[<slot_bg_normal>;<slot_bg_hover>]`
* Sets background color of slots as `ColorString`
* Sets background color of slots on mouse hovering
@ -1617,7 +1673,7 @@ numerical form, the raw integer value of an ARGB8 quad:
or string form, a ColorString (defined above):
`colorspec = "green"`
Vector helpers
Spatial Vectors
--------------
* `vector.new([x[, y, z]])`: returns a vector.
@ -1635,8 +1691,8 @@ For the following functions `x` can be either a vector or a number:
* `vector.add(v, x)`: returns a vector
* `vector.subtract(v, x)`: returns a vector
* `vector.multiply(v, x)`: returns a vector
* `vector.divide(v, x)`: returns a vector
* `vector.multiply(v, x)`: returns a scaled vector or Schur product
* `vector.divide(v, x)`: returns a scaled vector or Schur quotient
Helper functions
-----------------
@ -1661,6 +1717,8 @@ Helper functions
* Convert position to a printable string
* `minetest.string_to_pos(string)`: returns a position
* Same but in reverse. Returns `nil` if the string can't be parsed to a position.
* `minetest.string_to_area("(X1, Y1, Z1) (X2, Y2, Z2)")`: returns two positions
* Converts a string representing an area box into two positions
* `minetest.formspec_escape(string)`: returns a string
* escapes the characters "[", "]", "\", "," and ";", which can not be used in formspecs
* `minetest.is_yes(arg)`
@ -1700,7 +1758,7 @@ Helper functions
max_jitter = 0.5, -- maximum packet time jitter
avg_jitter = 0.03, -- average packet time jitter
connection_uptime = 200, -- seconds since client connected
-- following information is available on debug build only!!!
-- DO NOT USE IN MODS
--ser_vers = 26, -- serialization version used by client
@ -1721,11 +1779,11 @@ Helper functions
* false: return only file names.
### Logging
* `minetest.debug(line)`
* Always printed to `stderr` and logfile (`print()` is redirected here)
* `minetest.log(line)`
* `minetest.log(loglevel, line)`
* `loglevel` is one of `"error"`, `"action"`, `"info"`, `"verbose"`
* `minetest.debug(...)`
* Equivalent to `minetest.log(table.concat({...}, "\t"))`
* `minetest.log([level,] text)`
* `level` is one of `"none"`, `"error"`, `"warning"`, `"action"`,
`"info"`, or `"verbose"`. Default is `"none"`.
### Registration functions
Call these functions only at load time!
@ -1785,6 +1843,13 @@ Call these functions only at load time!
the puncher to the punched.
* `damage` - number that represents the damage calculated by the engine
* should return `true` to prevent the default damage mechanism
* `minetest.register_on_player_hpchange(func(player, hp_change), modifier)`
* Called when the player gets damaged or healed
* `player`: ObjectRef of the player
* `hp_change`: the amount of change. Negative when it is damage.
* `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.
modifiers can return true as a second argument to stop the execution of further functions.
* `minetest.register_on_respawnplayer(func(ObjectRef))`
* Called when player is to be respawned
* Called _before_ repositioning of player occurs
@ -1806,6 +1871,7 @@ Call these functions only at load time!
* `dug_too_fast`
* `minetest.register_on_chat_message(func(name, message))`
* Called always when a player says something
* Return `true` to mark the message as handled, which means that it will not be sent to other players
* `minetest.register_on_player_receive_fields(func(player, formname, fields))`
* Called when a button is pressed in player's inventory form
* Newest functions are called first
@ -1863,8 +1929,11 @@ Call these functions only at load time!
* `minetest.set_player_privs(name, {priv1=true,...})`
* `minetest.get_player_privs(name) -> {priv1=true,...}`
* `minetest.auth_reload()`
* `minetest.check_player_privs(name, {priv1=true,...})`: returns `bool, missing_privs`
* A quickhand for checking privileges
* `minetest.check_player_privs(player_or_name, ...)`: returns `bool, missing_privs`
* A quickhand for checking privileges.
* `player_or_name`: Either a Player object or the name of a player.
* `...` is either a list of strings, e.g. `"priva", "privb"` or
a table, e.g. `{ priva = true, privb = true }`.
* `minetest.get_player_ip(name)`: returns an IP address string
`minetest.set_player_password`, `minetest_set_player_privs`, `minetest_get_player_privs`
@ -1886,9 +1955,13 @@ and `minetest.auth_reload` call the authetification handler.
* Returns `{name="ignore", ...}` for unloaded area
* `minetest.get_node_or_nil(pos)`
* Returns `nil` for unloaded area
* `minetest.get_node_light(pos, timeofday)` returns a number between `0` and `15` or `nil`
* `minetest.get_node_light(pos, timeofday)`
* 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
to get the light value of a neighbor.
* `pos`: The position where to measure the light.
* `timeofday`: `nil` for current time, `0` for night, `0.5` for day
* Returns a number between `0` and `15` or `nil`
* `minetest.place_node(pos, node)`
* Place node with the same effects that a player would cause
* `minetest.dig_node(pos)`
@ -1910,13 +1983,16 @@ and `minetest.auth_reload` call the authetification handler.
* Returns `ObjectRef`, or `nil` if failed
* `minetest.get_player_by_name(name)`: Get an `ObjectRef` to a player
* `minetest.get_objects_inside_radius(pos, radius)`
* `radius`: using an euclidean metric
* `minetest.set_timeofday(val)`
* `val` is between `0` and `1`; `0` for midnight, `0.5` for midday
* `minetest.get_timeofday()`
* `minetest.get_gametime()`: returns the time, in seconds, since the world was created
* `minetest.find_node_near(pos, radius, nodenames)`: returns pos or `nil`
* `radius`: using a maximum metric
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
* `minetest.find_nodes_in_area(minp, maxp, nodenames)`: returns a list of positions
* returns as second value a table with the count of the individual nodes found
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
* `minetest.find_nodes_in_area_under_air(minp, maxp, nodenames)`: returns a list of positions
* returned positions are nodes with a node air above
@ -1935,6 +2011,9 @@ and `minetest.auth_reload` call the authetification handler.
* `get_gen_notify()`: returns a flagstring and a table with the deco_ids
* `minetest.get_mapgen_object(objectname)`
* Return requested mapgen object if available (see "Mapgen objects")
* `minetest.get_biome_id(biome_name)`
* Returns the biome id, as used in the biomemap Mapgen object, for a
given biome_name string.
* `minetest.get_mapgen_params()` Returns mapgen parameters, a table containing
`mgname`, `seed`, `chunksize`, `water_level`, and `flags`.
* `minetest.set_mapgen_params(MapgenParams)`
@ -1960,6 +2039,9 @@ and `minetest.auth_reload` call the authetification handler.
* `pos1` and `pos2` are optional and default to mapchunk minp and maxp.
* `minetest.clear_objects()`
* clear all objects in the environments
* `minetest.emerge_area(pos1, pos2)`
* queues all mapblocks in the area from pos1 to pos2, inclusive, for emerge
* i.e. asynchronously loads blocks from disk, or if inexistent, generates them
* `minetest.delete_area(pos1, pos2)`
* delete all mapblocks in the area from pos1 to pos2, inclusive
* `minetest.line_of_sight(pos1, pos2, stepsize)`: returns `boolean, pos`
@ -1974,7 +2056,7 @@ and `minetest.auth_reload` call the authetification handler.
* returns a table of 3D points representing a path from `pos1` to `pos2` or `nil`
* `pos1`: start position
* `pos2`: end position
* `searchdistance`: number of blocks to search in each direction
* `searchdistance`: number of blocks to search in each direction using a maximum metric
* `max_jump`: maximum height difference to consider walkable
* `max_drop`: maximum height difference to consider droppable
* `algorithm`: One of `"A*_noprefetch"` (default), `"A*"`, `"Dijkstra"`
@ -2058,6 +2140,8 @@ and `minetest.auth_reload` call the authetification handler.
`{ stack1, stack2, stack3, stack4, stack 5, stack 6, stack 7, stack 8, stack 9 }`
* `output.item` = `ItemStack`, if unsuccessful: empty `ItemStack`
* `output.time` = a number, if unsuccessful: `0`
* `output.replacements` = list of `ItemStack`s that couldn't be placed in
`decremented_input.items`
* `decremented_input` = like `input`
* `minetest.get_craft_recipe(output)`: returns input
* returns last registered recipe for output item (node)
@ -2143,7 +2227,8 @@ These functions return the leftover itemstack.
* Optional: Variable number of arguments that are passed to `func`
### Server
* `minetest.request_shutdown()`: request for server shutdown
* `minetest.request_shutdown([message],[reconnect])`: request for server shutdown. Will display `message` to clients,
and `reconnect` == true displays a reconnect button.
* `minetest.get_server_status()`: returns server status string
### Bans
@ -2160,7 +2245,7 @@ These functions return the leftover itemstack.
* `minetest.add_particlespawner(particlespawner definition)`
* Add a `ParticleSpawner`, an object that spawns an amount of particles over `time` seconds
* Returns an `id`
* Returns an `id`, and -1 if adding didn't succeed
* `Deprecated: minetest.add_particlespawner(amount, time,
minpos, maxpos,
minvel, maxvel,
@ -2268,6 +2353,9 @@ These functions return the leftover itemstack.
* currently supported.
* `...` indicates method-specific arguments. Currently, no methods use this.
* `minetest.is_protected(pos, name)`: returns boolean
* Returns true, if player `name` shouldn't be abled to dig at `pos` or do other
actions, defineable by mods, due to some mod-defined ownership-like concept.
Returns false or nil, if the player is allowed to do such actions.
* This function should be overridden by protection mods and should be used to
check if a player can interact at a position.
* This function should call the old version of itself if the position is not
@ -2368,7 +2456,7 @@ Can be gotten via `minetest.get_meta(pos)`.
* `from_table(nil or {})`
* See "Node Metadata"
### `NoteTimerRef`
### `NodeTimerRef`
Node Timers: a high resolution persistent per-node timer.
Can be gotten via `minetest.get_node_timer(pos)`.
@ -2415,8 +2503,8 @@ This is basically a reference to a C++ `ServerActiveObject`
* `set_wielded_item(item)`: replaces the wielded item, returns `true` if successful
* `set_armor_groups({group1=rating, group2=rating, ...})`
* `get_armor_groups()`: returns a table with the armor group ratings
* `set_animation({x=1,y=1}, frame_speed=15, frame_blend=0)`
* `get_animation()`: returns range, frame_speed and frame_blend
* `set_animation({x=1,y=1}, frame_speed=15, frame_blend=0, frame_loop=true)`
* `get_animation()`: returns range, frame_speed, frame_blend and frame_loop
* `set_attach(parent, bone, position, rotation)`
* `bone`: string
* `position`: `{x=num, y=num, z=num}` (relative)
@ -2449,6 +2537,7 @@ This is basically a reference to a C++ `ServerActiveObject`
##### Player-only (no-op for other objects)
* `get_player_name()`: returns `""` if is not a player
* `get_player_velocity()`: returns `nil` if is not a player otherwise a table {x, y, z} representing the player's instantaneous velocity in nodes/s
* `get_look_dir()`: get camera direction as a unit vector
* `get_look_pitch()`: pitch in radians
* `get_look_yaw()`: yaw in radians (wraps around pretty randomly as of now)
@ -2483,11 +2572,13 @@ This is basically a reference to a C++ `ServerActiveObject`
* element `stat` values: `position`, `name`, `scale`, `text`, `number`, `item`, `dir`
* `hud_get(id)`: gets the HUD element definition structure of the specified ID
* `hud_set_flags(flags)`: sets specified HUD flags to `true`/`false`
* `flags`: (is visible) `hotbar`, `healthbar`, `crosshair`, `wielditem`
* `flags`: (is visible) `hotbar`, `healthbar`, `crosshair`, `wielditem`, `minimap`
* pass a table containing a `true`/`false` value of each flag to be set or unset
* if a flag equals `nil`, the flag is not modified
* note that setting `minimap` modifies the client's permission to view the minimap -
* the client may locally elect to not view the minimap
* `hud_get_flags()`: returns a table containing status of hud flags
* returns `{ hotbar=true, healthbar=true, crosshair=true, wielditem=true, breathbar=true }`
* returns `{ hotbar=true, healthbar=true, crosshair=true, wielditem=true, breathbar=true, minimap=true }`
* `hud_set_hotbar_itemcount(count)`: sets number of items in builtin hotbar
* `count`: number of items, must be between `1` and `23`
* `hud_get_hotbar_itemcount`: returns number of visible items
@ -2569,6 +2660,28 @@ An `InvRef` is a reference to an inventory.
* `get_location()`: returns a location compatible to `minetest.get_inventory(location)`
* returns `{type="undefined"}` in case location is not known
### `AreaStore`
A fast access data structure to store areas, and find areas near a given position or area.
Every area has a `data` string attribute to store additional information.
You can create an empty `AreaStore` by calling `AreaStore()`, or `AreaStore(type_name)`.
If you chose the parameter-less constructor, a fast implementation will be automatically chosen for you.
#### Methods
* `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_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`
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.
* `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.
* `params`:
{
enabled = boolean, -- whether to enable, default true
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
}
### `ItemStack`
An `ItemStack` is a stack of items.
@ -2932,6 +3045,7 @@ Definition tables
stepheight = 0,
automatic_face_movement_dir = 0.0,
-- ^ automatically set yaw to movement direction; offset in degrees; false to disable
backface_culling = true, -- false to disable backface_culling for model
}
### Entity definition (`register_entity`)
@ -2958,10 +3072,14 @@ Definition tables
{
-- In the following two fields, also group:groupname will work.
nodenames = {"default:lava_source"},
neighbors = {"default:water_source", "default:water_flowing"}, -- (any of these)
-- ^ If left out or empty, any neighbor will do
interval = 1.0, -- (operation interval)
chance = 1, -- (chance of trigger is 1.0/this)
neighbors = {"default:water_source", "default:water_flowing"}, -- Any of these --[[
^ If left out or empty, any neighbor will do ]]
interval = 1.0, -- Operation interval in seconds
chance = 1, -- Chance of trigger per-node per-interval is 1.0 / this
catch_up = true, -- If true, catch-up behaviour is enabled --[[
^ The chance value is temporarily reduced when returning to
an area to simulate time lost by the area being unattended.
^ Note chance value can often be reduced to 1 ]]
action = func(pos, node, active_object_count, active_object_count_wider),
}
@ -3037,8 +3155,13 @@ Definition tables
### Tile definition
* `"image.png"`
* `{name="image.png", animation={Tile Animation definition}}`
* `{name="image.png", backface_culling=bool}`
* backface culling only supported in special tiles
* `{name="image.png", backface_culling=bool, tileable_vertical=bool,
tileable_horizontal=bool}`
* backface culling only supported in special tiles.
* tileable flags are info for shaders, how they should treat texture
when displacement mapping is used
Directions are from the point of view of the tile texture,
not the node it's on
* deprecated, yet still supported field names:
* `image` (name)
@ -3113,14 +3236,17 @@ Definition tables
},
on_construct = func(pos), --[[
^ Node constructor; always called after adding node
^ Node constructor; called after adding node
^ Can set up metadata and stuff like that
^ Not called for bulk node placement (i.e. schematics and VoxelManip)
^ default: nil ]]
on_destruct = func(pos), --[[
^ Node destructor; always called before removing node
^ Node destructor; called before removing node
^ Not called for bulk node placement (i.e. schematics and VoxelManip)
^ default: nil ]]
after_destruct = func(pos, oldnode), --[[
^ Node destructor; always called after removing node
^ Node destructor; called after removing node
^ Not called for bulk node placement (i.e. schematics and VoxelManip)
^ default: nil ]]
after_place_node = func(pos, placer, itemstack, pointed_thing) --[[
@ -3298,6 +3424,11 @@ Definition tables
-- ^ Minimum and maximum `y` positions these decorations can be generated at.
-- ^ This parameter refers to the `y` position of the decoration base, so
-- the actual maximum height would be `height_max + size.Y`.
flags = "liquid_surface",
-- ^ Flags for all decoration types.
-- ^ "liquid_surface": Instead of placement on the highest solid surface
-- ^ in a mapchunk column, placement is on the highest liquid surface.
-- ^ Placement is disabled if solid nodes are found above the liquid surface.
----- Simple-type parameters
decoration = "default:grass",
@ -3310,7 +3441,9 @@ Definition tables
-- ^ Number of nodes the decoration can be at maximum.
-- ^ If absent, the parameter 'height' is used as a constant.
spawn_by = "default:water",
-- ^ Node that the decoration only spawns next to, in a 1-node square radius.
-- ^ Node that the decoration only spawns next to.
-- ^ The neighbours checked are the 8 nodes horizontally surrounding the lowest node of the
-- ^ decoration, and the 8 nodes horizontally surrounding the ground node below the decoration.
num_spawn_by = 1,
-- ^ Number of spawn_by nodes that must be surrounding the decoration position to occur.
-- ^ If absent or -1, decorations occur next to any nodes.

View File

@ -1,4 +1,4 @@
Minetest Lua Mainmenu API Reference 0.4.12
Minetest Lua Mainmenu API Reference 0.4.13
========================================
Introduction
@ -141,8 +141,8 @@ core.get_game(index)
addon_mods_paths = {[1] = <path>,},
}
core.get_games() -> table of all games in upper format (possible in async calls)
core.get_mapgen_names() -> table of all map generator algorithms registered in
the core (possible in async calls)
core.get_mapgen_names([include_hidden=false]) -> table of map generator algorithms
registered in the core (possible in async calls)
Favorites:
core.get_favorites(location) -> list of favorites (possible in async calls)
@ -191,6 +191,8 @@ core.create_world(worldname, gameid)
core.delete_world(index)
Helpers:
core.get_us_time()
^ returns time with microsecond precision
core.gettext(string) -> string
^ look up the translation of a string in the gettext message catalog
fgettext_ne(string, ...)

View File

@ -41,13 +41,23 @@ auth.txt
---------
Contains authentication data, player per line.
<name>:<password hash>:<privilege1,...>
Format of password hash is <name><password> SHA1'd, in the base64 encoding.
Legacy format (until 0.4.12) of password hash is <name><password> SHA1'd,
in the base64 encoding.
Format (since 0.4.13) of password hash is #1#<salt>#<verifier>, with the
parts inside <> encoded in the base64 encoding.
<verifier> is an RFC 2945 compatible SRP verifier,
of the given salt, password, and the player's name lowercased,
using the 2048-bit group specified in RFC 5054 and the SHA-256 hash function.
Example lines:
- Player "celeron55", no password, privileges "interact" and "shout":
celeron55::interact,shout
- Player "Foo", password "bar", privilege "shout":
- Player "Foo", password "bar", privilege "shout", with a legacy password hash:
foo:iEPX+SQWIR3p67lj/0zigSWTKHg:shout
- Player "Foo", password "bar", privilege "shout", with a 0.4.13 pw hash:
foo:#1#hPpy4O3IAn1hsNK00A6wNw#Kpu6rj7McsrPCt4euTb5RA5ltF7wdcWGoYMcRngwDi11cZhPuuR9i5Bo7o6A877TgcEwoc//HNrj9EjR/CGjdyTFmNhiermZOADvd8eu32FYK1kf7RMC0rXWxCenYuOQCG4WF9mMGiyTPxC63VAjAMuc1nCZzmy6D9zt0SIKxOmteI75pAEAIee2hx4OkSXRIiU4Zrxo1Xf7QFxkMY4x77vgaPcvfmuzom0y/fU1EdSnZeopGPvzMpFx80ODFx1P34R52nmVl0W8h4GNo0k8ZiWtRCdrJxs8xIg7z5P1h3Th/BJ0lwexpdK8sQZWng8xaO5ElthNuhO8UQx1l6FgEA:shout
- Player "bar", no password, no privileges:
bar::
@ -204,14 +214,14 @@ algorithm, defined here in Python:
def getBlockAsInteger(p):
return int64(p[2]*16777216 + p[1]*4096 + p[0])
def int64(u):
while u >= 2**63:
u -= 2**64
while u <= -2**63:
u += 2**64
return u
It can be converted the other way by using this code:
def getIntegerAsBlock(i):
@ -221,7 +231,7 @@ It can be converted the other way by using this code:
i = int((i - y) / 4096)
z = unsignedToSigned(i % 4096, 2048)
return x,y,z
def unsignedToSigned(i, max_positive):
if i < max_positive:
return i
@ -241,7 +251,7 @@ NOTE: Zlib data is in such a format that Python's zlib at least can
directly decompress.
u8 version
- map format version number, this one is version 22
- map format version number, see serialisation.h for the latest number
u8 flags
- Flag bitmasks:
@ -287,13 +297,26 @@ if content_width == 2:
zlib-compressed node metadata list
- content:
if map format version <= 22:
u16 version (=1)
u16 count of metadata
foreach count:
u16 position (p.Z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + p.Y*MAP_BLOCKSIZE + p.X)
u16 type_id
u16 content_size
u8[content_size] (content of metadata)
u8[content_size] content of metadata. Format depends on type_id, see below.
if map format version >= 23:
u8 version (=1) -- Note the type is u8, while for map format version <= 22 it's u16
u16 count of metadata
foreach count:
u16 position (p.Z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + p.Y*MAP_BLOCKSIZE + p.X)
u32 num_vars
foreach num_vars:
u16 key_len
u8[key_len] key
u32 val_len
u8[val_len] value
serialized inventory
- Node timers
if map format version == 23:
@ -308,6 +331,8 @@ if map format version == 24: (NOTE: Not released as stable)
u16 timer position (z*16*16 + y*16 + x)
s32 timeout*1000
s32 elapsed*1000
if map format version >= 25:
-- Nothing right here, node timers are serialized later
u8 static object version:
- Always 0
@ -367,8 +392,9 @@ The name-id-mapping
--------------------
The mapping maps node content ids to node names.
Node metadata format
---------------------
Node metadata format for map format versions <= 22
---------------------------------------------------
The node metadata are serialized depending on the type_id field.
1: Generic metadata
serialized inventory

View File

@ -5,6 +5,7 @@ Comment=Multiplayer infinite-world block sandbox
Comment[de]=Mehrspieler-Sandkastenspiel mit unendlichen Blockwelten
Comment[es]=Juego sandbox multijugador con mundos infinitos
Comment[fr]=Jeu multijoueurs de type bac à sable avec des mondes infinis
Comment[ja]=マルチプレイに対応した、無限の世界のブロック型サンドボックスゲームです
Comment[ru]=Игра-песочница с безграничным миром, состоящим из блоков
Comment[tr]=Tek-Çok oyuncuyla küplerden sonsuz dünyalar inşa et
Exec=MultiCraft
@ -13,5 +14,4 @@ Terminal=false
Type=Application
Categories=Game;
StartupNotify=false
Keywords=sandbox;world;mining;crafting;blocks;nodes;multiplayer;roleplaying;
Keywords=sandbox;world;mining;crafting;blocks;nodes;multiplayer;roleplaying;

183
misc/minetest.svg Normal file
View File

@ -0,0 +1,183 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="48px"
height="48px"
id="svg2856"
version="1.1"
inkscape:version="0.47 r22583"
sodipodi:docname="minetest.svg"
inkscape:export-filename="/home/erlehmann/pics/icons/minetest/minetest-icon-24x24.png"
inkscape:export-xdpi="45"
inkscape:export-ydpi="45">
<defs
id="defs2858">
<filter
inkscape:collect="always"
id="filter3864">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.20490381"
id="feGaussianBlur3866" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="12.083333"
inkscape:cx="24"
inkscape:cy="24"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1233"
inkscape:window-height="755"
inkscape:window-x="0"
inkscape:window-y="25"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid2866"
empspacing="2"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true"
spacingx="0.5px"
spacingy="10px"
color="#ff0000"
opacity="0.1254902"
empcolor="#ff0000"
empopacity="0.25098039"
dotted="false" />
<inkscape:grid
type="axonomgrid"
id="grid2870"
units="px"
empspacing="1"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true"
spacingy="1px"
originx="0px" />
</sodipodi:namedview>
<metadata
id="metadata2861">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<path
style="fill:#e9b96e;fill-opacity:1;stroke:#573a0d;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
d="M 6.1513775e-7,16 3.2110204e-7,28 21.035899,40.145082 l 21,-12.414519 0,-11.461126 L 20.78461,4 6.1513775e-7,16 z"
id="path3047"
transform="translate(3.4641013,6)"
sodipodi:nodetypes="ccccccc" />
<path
style="fill:#2e3436;fill-opacity:1;stroke:#2e3436;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
d="m 8.5,30.907477 -2,-1.1547 0,6 L 17.320508,42 l 0,-2 -1.732051,-1 0,-2 L 13.5,35.794229 l 0,-4 -5,-2.886752 0,2 z"
id="path3831"
sodipodi:nodetypes="ccccccccccc" />
<path
style="opacity:1;fill:#555753;fill-opacity:1;stroke:#2e3436;stroke-linejoin:miter"
d="m 6.9282032,36 3.4641018,-2 3.464101,2 1.643594,0.948929 0,2 2,1.154701 0,2 L 6.9282032,36 z"
id="path3870"
sodipodi:nodetypes="cccccccc" />
<path
style="fill:#fce94f;fill-opacity:1;stroke:#625802;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
d="M 25.980762,19 31.5,22.186533 l 0,2 L 38.09375,28 41.5625,26 45.5,23.730563 l 0,2.538874 0,-4 L 32.908965,15 25.980762,19 z"
id="path3851"
sodipodi:nodetypes="cccccccccc" />
<path
style="fill:#e9b96e;fill-opacity:1;stroke:#573a0d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.50000000000000000"
d="m 24.839746,18.341234 8.660254,-5 0,2 -8.660254,5 0,-2 z"
id="path5684"
sodipodi:nodetypes="ccccc" />
<path
style="fill:#73d216;fill-opacity:1;stroke:#325b09;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
d="M 25.980762,5 3.4641016,18 17.5,26.10363 31.5,18.186533 24.839746,14.341234 33.5,9.341234 25.980762,5 z"
id="path3821"
sodipodi:nodetypes="ccccccc"
transform="translate(0,4)" />
<path
style="fill:#729fcf;fill-opacity:1;stroke:#19314b;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
d="m 17.5,28.10363 0,2 1.552559,0.89637 0,2 5.447441,3.145082 12,-7.071797 0,-2.14657 2,-1.1547 0,-1.54403 -7,-4.041452 -14,7.917097 z"
id="path3825"
sodipodi:nodetypes="ccccccccccc"
transform="translate(0,4)" />
<g
id="g5691"
style="stroke-linejoin:miter">
<path
sodipodi:nodetypes="ccccc"
id="path3862"
d="m 13.856406,20 6.928204,4 -6.928204,4 -6.9282028,-4 6.9282028,-4 z"
style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;filter:url(#filter3864);opacity:0.25000000000000000" />
<g
id="g3858"
style="stroke-linejoin:miter">
<path
style="fill:#c17d11;fill-opacity:1;stroke:#8f5902;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
d="m 15.588457,21 1.732051,1 1.732051,-1 0,-6 -1.732051,-1 -1.732051,1 0,6 z"
id="path3833"
sodipodi:nodetypes="ccccccc"
transform="translate(-3.4641015,2)" />
<path
style="fill:#4e9a06;fill-opacity:1;stroke:#316004;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
d="M 9.9641015,13.752777 17.320508,18 l 6.643593,-3.835681 0,-8.3286385 L 17.320508,2 9.9641015,6.2472233 l 0,7.5055537 z"
id="path3837"
transform="translate(-3.4641015,2)"
sodipodi:nodetypes="ccccccc" />
</g>
</g>
<g
id="g5686"
transform="translate(-4.2591582e-7,2)"
style="stroke-linejoin:miter">
<path
transform="translate(24.248712,-2)"
style="opacity:0.25000000000000000;fill:#2e3436;fill-opacity:1;stroke:none;filter:url(#filter3864);stroke-linejoin:miter"
d="m 13.856406,20 5.196153,3 -5.196153,3 -5.196152,-3 5.196152,-3 z"
id="path3868"
sodipodi:nodetypes="ccccc" />
<path
style="fill:#4e9a06;fill-opacity:1;stroke:#316004;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
d="M 15.71539,21.073285 17.320508,22 l 1.394882,-0.805336 0,-8.389328 L 17.320508,12 l -1.605118,1.073285 0,8 z"
id="path3853"
sodipodi:nodetypes="ccccccc"
transform="translate(20.78461,0)" />
</g>
<path
style="fill:none;fill-opacity:1;stroke:#ef2929;stroke-width:0.50000000000000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:0.50000000000000000, 0.50000000000000000;stroke-dashoffset:0.25000000000000000"
d="M 12.124356,33 11.25833,32.5"
id="path3872"
sodipodi:nodetypes="cc" />
<path
style="fill:#888a85;stroke:#2e3436;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.50000000000000000"
d="m 45.5,26.730563 -4,2.309401 0,1 -2,1.1547 0,2 -2,1.154701 0,4 8,-4.618802 0,-7 z"
id="path3874"
sodipodi:nodetypes="ccccccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.1 KiB

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

3587
po/eo/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

3478
po/jbo/minetest.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3578
po/zh_TW/minetest.po Normal file

File diff suppressed because it is too large Load Diff

View File

@ -27,6 +27,12 @@ set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
mark_as_advanced(EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH)
if(NOT (BUILD_CLIENT OR BUILD_SERVER))
message(WARNING "Neither BUILD_CLIENT nor BUILD_SERVER is set! Setting BUILD_SERVER=true")
set(BUILD_SERVER TRUE)
endif()
option(ENABLE_CURL "Enable cURL support for fetching media" TRUE)
set(USE_CURL FALSE)
@ -40,6 +46,15 @@ else()
mark_as_advanced(CLEAR CURL_LIBRARY CURL_INCLUDE_DIR)
endif()
if(NOT USE_CURL)
if(BUILD_CLIENT)
message(WARNING "cURL is required to load the server list")
endif()
if(BUILD_SERVER)
message(WARNING "cURL is required to announce to the server list")
endif()
endif()
option(ENABLE_GETTEXT "Use GetText for internationalization" FALSE)
set(USE_GETTEXT FALSE)
@ -180,6 +195,21 @@ endif(ENABLE_REDIS)
find_package(SQLite3 REQUIRED)
find_package(Json REQUIRED)
OPTION(ENABLE_SPATIAL "Enable SpatialIndex AreaStore backend" TRUE)
set(USE_SPATIAL FALSE)
if(ENABLE_SPATIAL)
find_library(SPATIAL_LIBRARY spatialindex)
find_path(SPATIAL_INCLUDE_DIR spatialindex/SpatialIndex.h)
if(SPATIAL_LIBRARY AND SPATIAL_INCLUDE_DIR)
set(USE_SPATIAL TRUE)
message(STATUS "SpatialIndex AreaStore backend enabled.")
include_directories(${SPATIAL_INCLUDE_DIR})
else(SPATIAL_LIBRARY AND SPATIAL_INCLUDE_DIR)
message(STATUS "SpatialIndex not found!")
endif(SPATIAL_LIBRARY AND SPATIAL_INCLUDE_DIR)
endif(ENABLE_SPATIAL)
if(NOT MSVC)
set(USE_GPROF FALSE CACHE BOOL "Use -pg flag for g++")
@ -249,11 +279,18 @@ else()
else()
set(PLATFORM_LIBS -lrt ${PLATFORM_LIBS})
endif(APPLE)
#set(CLIENT_PLATFORM_LIBS -lXxf86vm)
# This way Xxf86vm is found on OpenBSD too
find_library(XXF86VM_LIBRARY Xxf86vm)
mark_as_advanced(XXF86VM_LIBRARY)
set(CLIENT_PLATFORM_LIBS ${CLIENT_PLATFORM_LIBS} ${XXF86VM_LIBRARY})
# Prefer local iconv if installed
find_library(ICONV_LIBRARY iconv)
mark_as_advanced(ICONV_LIBRARY)
if (ICONV_LIBRARY)
set(PLATFORM_LIBS ${PLATFORM_LIBS} ${ICONV_LIBRARY})
endif()
endif()
check_include_files(endian.h HAVE_ENDIAN_H)
@ -275,13 +312,14 @@ add_custom_target(GenerateVersion
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
add_subdirectory(jthread)
add_subdirectory(threading)
add_subdirectory(network)
add_subdirectory(script)
add_subdirectory(unittest)
add_subdirectory(util)
set(common_SRCS
areastore.cpp
ban.cpp
cavegen.cpp
clientiface.cpp
@ -314,6 +352,7 @@ set(common_SRCS
map.cpp
mapblock.cpp
mapgen.cpp
mapgen_fractal.cpp
mapgen_singlenode.cpp
mapgen_v5.cpp
mapgen_v6.cpp
@ -417,11 +456,13 @@ set(client_SRCS
guiVolumeChange.cpp
hud.cpp
imagefilters.cpp
intlGUIEditBox.cpp
keycode.cpp
localplayer.cpp
main.cpp
mapblock_mesh.cpp
mesh.cpp
minimap.cpp
particles.cpp
shader.cpp
sky.cpp
@ -523,6 +564,9 @@ if(BUILD_CLIENT)
if (USE_REDIS)
target_link_libraries(${PROJECT_NAME} ${REDIS_LIBRARY})
endif()
if (USE_SPATIAL)
target_link_libraries(${PROJECT_NAME} ${SPATIAL_LIBRARY})
endif()
endif(BUILD_CLIENT)
@ -547,6 +591,9 @@ if(BUILD_SERVER)
if (USE_REDIS)
target_link_libraries(${PROJECT_NAME}server ${REDIS_LIBRARY})
endif()
if (USE_SPATIAL)
target_link_libraries(${PROJECT_NAME}server ${SPATIAL_LIBRARY})
endif()
if(USE_CURL)
target_link_libraries(
${PROJECT_NAME}server

343
src/areastore.cpp Normal file
View File

@ -0,0 +1,343 @@
/*
Minetest
Copyright (C) 2015 est31 <mtest31@outlook.com>
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 3.0 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.
*/
#include "areastore.h"
#include "util/serialize.h"
#include "util/container.h"
#if USE_SPATIAL
#include <spatialindex/SpatialIndex.h>
#include <spatialindex/RTree.h>
#include <spatialindex/Point.h>
#endif
#define AST_SMALLER_EQ_AS(p, q) (((p).X <= (q).X) && ((p).Y <= (q).Y) && ((p).Z <= (q).Z))
#define AST_OVERLAPS_IN_DIMENSION(amine, amaxe, b, d) \
(!(((amine).d > (b)->maxedge.d) || ((amaxe).d < (b)->minedge.d)))
#define AST_CONTAINS_PT(a, p) (AST_SMALLER_EQ_AS((a)->minedge, (p)) && \
AST_SMALLER_EQ_AS((p), (a)->maxedge))
#define AST_CONTAINS_AREA(amine, amaxe, b) \
(AST_SMALLER_EQ_AS((amine), (b)->minedge) \
&& AST_SMALLER_EQ_AS((b)->maxedge, (amaxe)))
#define AST_AREAS_OVERLAP(amine, amaxe, b) \
(AST_OVERLAPS_IN_DIMENSION((amine), (amaxe), (b), X) && \
AST_OVERLAPS_IN_DIMENSION((amine), (amaxe), (b), Y) && \
AST_OVERLAPS_IN_DIMENSION((amine), (amaxe), (b), Z))
u16 AreaStore::size() const
{
return areas_map.size();
}
u32 AreaStore::getFreeId(v3s16 minedge, v3s16 maxedge)
{
int keep_on = 100;
while (keep_on--) {
m_highest_id++;
// Handle overflows, we dont want to return 0
if (m_highest_id == AREA_ID_INVALID)
m_highest_id++;
if (areas_map.find(m_highest_id) == areas_map.end())
return m_highest_id;
}
// search failed
return AREA_ID_INVALID;
}
const Area *AreaStore::getArea(u32 id) const
{
const Area *res = NULL;
std::map<u32, Area>::const_iterator itr = areas_map.find(id);
if (itr != areas_map.end()) {
res = &itr->second;
}
return res;
}
#if 0
Currently, serialisation is commented out. This is because of multiple reasons:
1. Why do we store the areastore into a file, why not into the database?
2. We don't use libspatial's serialisation, but we should, or perhaps not, because
it would remove the ability to switch. Perhaps write migration routines?
3. Various things need fixing, e.g. the size is serialized as
c++ implementation defined size_t
bool AreaStore::deserialize(std::istream &is)
{
u8 ver = readU8(is);
if (ver != 1)
return false;
u16 count_areas = readU16(is);
for (u16 i = 0; i < count_areas; i++) {
// deserialize an area
Area a;
a.id = readU32(is);
a.minedge = readV3S16(is);
a.maxedge = readV3S16(is);
a.datalen = readU16(is);
a.data = new char[a.datalen];
is.read((char *) a.data, a.datalen);
insertArea(a);
}
return true;
}
static bool serialize_area(void *ostr, Area *a)
{
std::ostream &os = *((std::ostream *) ostr);
writeU32(os, a->id);
writeV3S16(os, a->minedge);
writeV3S16(os, a->maxedge);
writeU16(os, a->datalen);
os.write(a->data, a->datalen);
return false;
}
void AreaStore::serialize(std::ostream &os) const
{
// write initial data
writeU8(os, 1); // serialisation version
writeU16(os, areas_map.size()); //DANGER: not platform independent
forEach(&serialize_area, &os);
}
#endif
void AreaStore::invalidateCache()
{
if (cache_enabled) {
m_res_cache.invalidate();
}
}
void AreaStore::setCacheParams(bool enabled, u8 block_radius, size_t limit)
{
cache_enabled = enabled;
m_cacheblock_radius = MYMAX(block_radius, 16);
m_res_cache.setLimit(MYMAX(limit, 20));
invalidateCache();
}
void AreaStore::cacheMiss(void *data, const v3s16 &mpos, std::vector<Area *> *dest)
{
AreaStore *as = (AreaStore *)data;
u8 r = as->m_cacheblock_radius;
// get the points at the edges of the mapblock
v3s16 minedge(mpos.X * r, mpos.Y * r, mpos.Z * r);
v3s16 maxedge(
minedge.X + r - 1,
minedge.Y + r - 1,
minedge.Z + r - 1);
as->getAreasInArea(dest, minedge, maxedge, true);
/* infostream << "Cache miss with " << dest->size() << " areas, between ("
<< minedge.X << ", " << minedge.Y << ", " << minedge.Z
<< ") and ("
<< maxedge.X << ", " << maxedge.Y << ", " << maxedge.Z
<< ")" << std::endl; // */
}
void AreaStore::getAreasForPos(std::vector<Area *> *result, v3s16 pos)
{
if (cache_enabled) {
v3s16 mblock = getContainerPos(pos, m_cacheblock_radius);
const std::vector<Area *> *pre_list = m_res_cache.lookupCache(mblock);
size_t s_p_l = pre_list->size();
for (size_t i = 0; i < s_p_l; i++) {
Area *b = (*pre_list)[i];
if (AST_CONTAINS_PT(b, pos)) {
result->push_back(b);
}
}
} else {
return getAreasForPosImpl(result, pos);
}
}
////
// VectorAreaStore
////
void VectorAreaStore::insertArea(const Area &a)
{
areas_map[a.id] = a;
m_areas.push_back(&(areas_map[a.id]));
invalidateCache();
}
void VectorAreaStore::reserve(size_t count)
{
m_areas.reserve(count);
}
bool VectorAreaStore::removeArea(u32 id)
{
std::map<u32, Area>::iterator itr = areas_map.find(id);
if (itr != areas_map.end()) {
size_t msiz = m_areas.size();
for (size_t i = 0; i < msiz; i++) {
Area * b = m_areas[i];
if (b->id == id) {
areas_map.erase(itr);
m_areas.erase(m_areas.begin() + i);
invalidateCache();
return true;
}
}
// we should never get here, it means we did find it in map,
// but not in the vector
}
return false;
}
void VectorAreaStore::getAreasForPosImpl(std::vector<Area *> *result, v3s16 pos)
{
size_t msiz = m_areas.size();
for (size_t i = 0; i < msiz; i++) {
Area *b = m_areas[i];
if (AST_CONTAINS_PT(b, pos)) {
result->push_back(b);
}
}
}
void VectorAreaStore::getAreasInArea(std::vector<Area *> *result,
v3s16 minedge, v3s16 maxedge, bool accept_overlap)
{
size_t msiz = m_areas.size();
for (size_t i = 0; i < msiz; i++) {
Area * b = m_areas[i];
if (accept_overlap ? AST_AREAS_OVERLAP(minedge, maxedge, b) :
AST_CONTAINS_AREA(minedge, maxedge, b)) {
result->push_back(b);
}
}
}
#if 0
bool VectorAreaStore::forEach(bool (*callback)(void *args, Area *a), void *args) const
{
size_t msiz = m_areas.size();
for (size_t i = 0; i < msiz; i++) {
if (callback(args, m_areas[i])) {
return true;
}
}
return false;
}
#endif
#if USE_SPATIAL
static inline SpatialIndex::Region get_spatial_region(const v3s16 minedge,
const v3s16 maxedge)
{
const double p_low[] = {(double)minedge.X,
(double)minedge.Y, (double)minedge.Z};
const double p_high[] = {(double)maxedge.X, (double)maxedge.Y,
(double)maxedge.Z};
return SpatialIndex::Region(p_low, p_high, 3);
}
static inline SpatialIndex::Point get_spatial_point(const v3s16 pos)
{
const double p[] = {(double)pos.X, (double)pos.Y, (double)pos.Z};
return SpatialIndex::Point(p, 3);
}
void SpatialAreaStore::insertArea(const Area &a)
{
areas_map[a.id] = a;
m_tree->insertData(0, NULL, get_spatial_region(a.minedge, a.maxedge), a.id);
invalidateCache();
}
bool SpatialAreaStore::removeArea(u32 id)
{
std::map<u32, Area>::iterator itr = areas_map.find(id);
if (itr != areas_map.end()) {
Area *a = &itr->second;
bool result = m_tree->deleteData(get_spatial_region(a->minedge,
a->maxedge), id);
invalidateCache();
return result;
} else {
return false;
}
}
void SpatialAreaStore::getAreasForPosImpl(std::vector<Area *> *result, v3s16 pos)
{
VectorResultVisitor visitor(result, this);
m_tree->pointLocationQuery(get_spatial_point(pos), visitor);
}
void SpatialAreaStore::getAreasInArea(std::vector<Area *> *result,
v3s16 minedge, v3s16 maxedge, bool accept_overlap)
{
VectorResultVisitor visitor(result, this);
if (accept_overlap) {
m_tree->intersectsWithQuery(get_spatial_region(minedge, maxedge),
visitor);
} else {
m_tree->containsWhatQuery(get_spatial_region(minedge, maxedge), visitor);
}
}
#if 0
bool SpatialAreaStore::forEach(bool (*callback)(void *args, Area *a), void *args) const
{
// TODO ?? (this is only needed for serialisation, but libspatial has its own serialisation)
return false;
}
#endif
SpatialAreaStore::~SpatialAreaStore()
{
delete m_tree;
}
SpatialAreaStore::SpatialAreaStore()
{
m_storagemanager =
SpatialIndex::StorageManager::createNewMemoryStorageManager();
SpatialIndex::id_type id;
m_tree = SpatialIndex::RTree::createNewRTree(
*m_storagemanager,
.7, // Fill factor
100, // Index capacity
100, // Leaf capacity
3, // dimension :)
SpatialIndex::RTree::RV_RSTAR,
id);
}
#endif

196
src/areastore.h Normal file
View File

@ -0,0 +1,196 @@
/*
Minetest
Copyright (C) 2015 est31 <mtest31@outlook.com>
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 3.0 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.
*/
#ifndef AREASTORE_H_
#define AREASTORE_H_
#include "irr_v3d.h"
#include "noise.h" // for PcgRandom
#include <map>
#include <list>
#include <vector>
#include <istream>
#include "util/container.h"
#include "util/numeric.h"
#ifndef ANDROID
#include "cmake_config.h"
#endif
#if USE_SPATIAL
#include <spatialindex/SpatialIndex.h>
#include "util/serialize.h"
#endif
#define AST_EXTREMIFY(min, max, pa, pb) \
(min).X = MYMIN((pa).X, (pb).X); \
(min).Y = MYMIN((pa).Y, (pb).Y); \
(min).Z = MYMIN((pa).Z, (pb).Z); \
(max).X = MYMAX((pa).X, (pb).X); \
(max).Y = MYMAX((pa).Y, (pb).Y); \
(max).Z = MYMAX((pa).Z, (pb).Z);
#define AREA_ID_INVALID 0
struct Area {
Area(const v3s16 &minedge, const v3s16 &maxedge)
{
this->minedge = minedge;
this->maxedge = maxedge;
}
Area() {}
void extremifyEdges()
{
v3s16 nminedge;
v3s16 nmaxedge;
AST_EXTREMIFY(nminedge, nmaxedge, minedge, maxedge)
maxedge = nmaxedge;
minedge = nminedge;
}
u32 id;
v3s16 minedge;
v3s16 maxedge;
std::string data;
};
std::vector<std::string> get_areastore_typenames();
class AreaStore {
protected:
// TODO change to unordered_map when we can
std::map<u32, Area> areas_map;
void invalidateCache();
virtual void getAreasForPosImpl(std::vector<Area *> *result, v3s16 pos) = 0;
bool cache_enabled; // don't write to this from subclasses, only read.
public:
virtual void insertArea(const Area &a) = 0;
virtual void reserve(size_t count) {};
virtual bool removeArea(u32 id) = 0;
void getAreasForPos(std::vector<Area *> *result, v3s16 pos);
virtual void getAreasInArea(std::vector<Area *> *result,
v3s16 minedge, v3s16 maxedge, bool accept_overlap) = 0;
#if 0
// calls a passed function for every stored area, until the
// callback returns true. If that happens, it returns true,
// if the search is exhausted, it returns false
virtual bool forEach(bool (*callback)(void *args, Area *a), void *args) const = 0;
#endif
virtual ~AreaStore()
{}
AreaStore() :
cache_enabled(true),
m_cacheblock_radius(64),
m_res_cache(1000, &cacheMiss, this),
m_highest_id(0)
{
}
void setCacheParams(bool enabled, u8 block_radius, size_t limit);
u32 getFreeId(v3s16 minedge, v3s16 maxedge);
const Area *getArea(u32 id) const;
u16 size() const;
#if 0
bool deserialize(std::istream &is);
void serialize(std::ostream &is) const;
#endif
private:
static void cacheMiss(void *data, const v3s16 &mpos, std::vector<Area *> *dest);
u8 m_cacheblock_radius; // if you modify this, call invalidateCache()
LRUCache<v3s16, std::vector<Area *> > m_res_cache;
u32 m_highest_id;
};
class VectorAreaStore : public AreaStore {
protected:
virtual void getAreasForPosImpl(std::vector<Area *> *result, v3s16 pos);
public:
virtual void insertArea(const Area &a);
virtual void reserve(size_t count);
virtual bool removeArea(u32 id);
virtual void getAreasInArea(std::vector<Area *> *result,
v3s16 minedge, v3s16 maxedge, bool accept_overlap);
// virtual bool forEach(bool (*callback)(void *args, Area *a), void *args) const;
private:
std::vector<Area *> m_areas;
};
#if USE_SPATIAL
class SpatialAreaStore : public AreaStore {
protected:
virtual void getAreasForPosImpl(std::vector<Area *> *result, v3s16 pos);
public:
SpatialAreaStore();
virtual void insertArea(const Area &a);
virtual bool removeArea(u32 id);
virtual void getAreasInArea(std::vector<Area *> *result,
v3s16 minedge, v3s16 maxedge, bool accept_overlap);
// virtual bool forEach(bool (*callback)(void *args, Area *a), void *args) const;
virtual ~SpatialAreaStore();
private:
SpatialIndex::ISpatialIndex *m_tree;
SpatialIndex::IStorageManager *m_storagemanager;
class VectorResultVisitor : public SpatialIndex::IVisitor {
private:
SpatialAreaStore *m_store;
std::vector<Area *> *m_result;
public:
VectorResultVisitor(std::vector<Area *> *result, SpatialAreaStore *store)
{
m_store = store;
m_result = result;
}
virtual void visitNode(const SpatialIndex::INode &in)
{
}
virtual void visitData(const SpatialIndex::IData &in)
{
u32 id = in.getIdentifier();
std::map<u32, Area>::iterator itr = m_store->areas_map.find(id);
assert(itr != m_store->areas_map.end());
m_result->push_back(&itr->second);
}
virtual void visitData(std::vector<const SpatialIndex::IData *> &v)
{
for (size_t i = 0; i < v.size(); i++)
visitData(*(v[i]));
}
~VectorResultVisitor() {}
};
};
#endif
#endif /* AREASTORE_H_ */

View File

@ -19,7 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "ban.h"
#include <fstream>
#include "jthread/jmutexautolock.h"
#include "threading/mutex_auto_lock.h"
#include <sstream>
#include <set>
#include "strfnd.h"
@ -36,7 +36,7 @@ BanManager::BanManager(const std::string &banfilepath):
}
catch(SerializationError &e)
{
infostream<<"WARNING: BanManager: creating "
warningstream<<"BanManager: creating "
<<m_banfilepath<<std::endl;
}
}
@ -48,7 +48,7 @@ BanManager::~BanManager()
void BanManager::load()
{
JMutexAutoLock lock(m_mutex);
MutexAutoLock lock(m_mutex);
infostream<<"BanManager: loading from "<<m_banfilepath<<std::endl;
std::ifstream is(m_banfilepath.c_str(), std::ios::binary);
if(is.good() == false)
@ -73,7 +73,7 @@ void BanManager::load()
void BanManager::save()
{
JMutexAutoLock lock(m_mutex);
MutexAutoLock lock(m_mutex);
infostream << "BanManager: saving to " << m_banfilepath << std::endl;
std::ostringstream ss(std::ios_base::binary);
@ -90,13 +90,13 @@ void BanManager::save()
bool BanManager::isIpBanned(const std::string &ip)
{
JMutexAutoLock lock(m_mutex);
MutexAutoLock lock(m_mutex);
return m_ips.find(ip) != m_ips.end();
}
std::string BanManager::getBanDescription(const std::string &ip_or_name)
{
JMutexAutoLock lock(m_mutex);
MutexAutoLock lock(m_mutex);
std::string s = "";
for (StringMap::iterator it = m_ips.begin(); it != m_ips.end(); ++it) {
if (it->first == ip_or_name || it->second == ip_or_name
@ -110,7 +110,7 @@ std::string BanManager::getBanDescription(const std::string &ip_or_name)
std::string BanManager::getBanName(const std::string &ip)
{
JMutexAutoLock lock(m_mutex);
MutexAutoLock lock(m_mutex);
StringMap::iterator it = m_ips.find(ip);
if (it == m_ips.end())
return "";
@ -119,14 +119,14 @@ std::string BanManager::getBanName(const std::string &ip)
void BanManager::add(const std::string &ip, const std::string &name)
{
JMutexAutoLock lock(m_mutex);
MutexAutoLock lock(m_mutex);
m_ips[ip] = name;
m_modified = true;
}
void BanManager::remove(const std::string &ip_or_name)
{
JMutexAutoLock lock(m_mutex);
MutexAutoLock lock(m_mutex);
for (StringMap::iterator it = m_ips.begin(); it != m_ips.end();) {
if ((it->first == ip_or_name) || (it->second == ip_or_name)) {
m_ips.erase(it++);
@ -140,7 +140,7 @@ void BanManager::remove(const std::string &ip_or_name)
bool BanManager::isModified()
{
JMutexAutoLock lock(m_mutex);
MutexAutoLock lock(m_mutex);
return m_modified;
}

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