forked from Mirrorlandia_minetest/minetest
Compare commits
187 Commits
master
...
stable-0.4
Author | SHA1 | Date | |
---|---|---|---|
|
426b5d3149 | ||
|
dda844be16 | ||
|
899dcbf1ee | ||
|
957c59a678 | ||
|
3d15a6774d | ||
|
3c24f941e0 | ||
|
9d64805ec1 | ||
|
ce4497224f | ||
|
a873a3f4f8 | ||
|
86e29ae586 | ||
|
dd5f03731a | ||
|
5e7faf3f50 | ||
|
8427ae529a | ||
|
2e85254e91 | ||
|
971dea7efd | ||
|
85ce23b165 | ||
|
e66d5e500c | ||
|
ea86ecf015 | ||
|
4a48cd57e8 | ||
|
289c8dfde5 | ||
|
9dfe9be1f3 | ||
|
f5c9c760e3 | ||
|
6dc7177a5d | ||
|
24a2fd4dc4 | ||
|
2515207606 | ||
|
119aa5c919 | ||
|
fb4bfc60de | ||
|
9bbe99b4f8 | ||
|
0ef9c53a8c | ||
|
b5350e27ad | ||
|
ecbb9310de | ||
|
aac35a6e7c | ||
|
04fe8cc0a2 | ||
|
24abdf45b9 | ||
|
263400b3d8 | ||
|
695d02e6bd | ||
|
e2815d27f1 | ||
|
ebfdb21624 | ||
|
0088fa6db4 | ||
|
e660b05523 | ||
|
14d20f5827 | ||
|
0414322d23 | ||
|
a6cfe73cb0 | ||
|
1d06a8ef6c | ||
|
875972ffa6 | ||
|
396daf1be1 | ||
|
fe41725e50 | ||
|
5624cf750f | ||
|
1d7fbd035d | ||
|
a6b9acb7af | ||
|
c40f535df8 | ||
|
79fde0dd52 | ||
|
8aaf526730 | ||
|
c683e050d4 | ||
|
c2e39b9363 | ||
|
f8cc92c190 | ||
|
858c41b842 | ||
|
2a4fbbbff8 | ||
|
6d346a817b | ||
|
529f00a240 | ||
|
7725030067 | ||
|
bb28afcfc3 | ||
|
880a25c921 | ||
|
0268c9d7c9 | ||
|
f72490950a | ||
|
9d3fa874be | ||
|
842eccee19 | ||
|
127b1fa6f8 | ||
|
6b5e2618fb | ||
|
b2099d4277 | ||
|
df0a8574dc | ||
|
6698067256 | ||
|
bb219e1059 | ||
|
b3167d4e57 | ||
|
8a849e893a | ||
|
f9738c1909 | ||
|
6f80e302fd | ||
|
48ebbf0fc6 | ||
|
7d9dbbbf3c | ||
|
7cc1a36b3c | ||
|
3f1094475f | ||
|
f72ac42ca0 | ||
|
8fba3c93d5 | ||
|
a90c314c80 | ||
|
222fab3d20 | ||
|
1cf32b22be | ||
|
6f803b9c89 | ||
|
0fe3e7574d | ||
|
b816c63196 | ||
|
313ca53b36 | ||
|
a65a46b889 | ||
|
0cfe3a810a | ||
|
6808a3d144 | ||
|
4d9bf75d3a | ||
|
416c4535c7 | ||
|
73baeb82ef | ||
|
7b8288d605 | ||
|
2f969196b8 | ||
|
0041bcc73e | ||
|
cc48c95ca7 | ||
|
0129c9a9dd | ||
|
9dc1f2d638 | ||
|
d215198fe8 | ||
|
c56c3d8d6f | ||
|
0034abb560 | ||
|
200e9cc4a2 | ||
|
6b0fb94d60 | ||
|
017815161b | ||
|
ab72100a2c | ||
|
9927076b47 | ||
|
bd8d6f8f2f | ||
|
3a9d500396 | ||
|
01b9da870b | ||
|
e8286e8894 | ||
|
b8f473be21 | ||
|
b1fae4c7be | ||
|
c2a0333901 | ||
|
5b2461c713 | ||
|
e9087d1be7 | ||
|
bb4ef52954 | ||
|
888b99e1b6 | ||
|
2c450ed93f | ||
|
d9c7af109a | ||
|
12562be393 | ||
|
151c19a6be | ||
|
9d40d89d27 | ||
|
037b01eac7 | ||
|
c789c532bb | ||
|
b3ffe675c3 | ||
|
90a9e4e69f | ||
|
e5311a4d56 | ||
|
4be7d8b43a | ||
|
070ab6654a | ||
|
ebf9dda2e6 | ||
|
c352ff71e8 | ||
|
26d0753d87 | ||
|
46ff2e2cef | ||
|
a08a93bc9c | ||
|
6e0557e20c | ||
|
0c91c65a11 | ||
|
849fe19f8c | ||
|
cfa6216694 | ||
|
322e5aaf92 | ||
|
03bc584f57 | ||
|
5f796f7a04 | ||
|
7aa52fe4e1 | ||
|
0664b5f772 | ||
|
14b039f0b4 | ||
|
c399f5a541 | ||
|
f736226c1a | ||
|
e665e75e77 | ||
|
cba783f7fa | ||
|
87b9451820 | ||
|
41b7823057 | ||
|
7968f1ddaa | ||
|
caecdb681c | ||
|
81d56b9491 | ||
|
8077612dcb | ||
|
07fddf1f6c | ||
|
315b00d150 | ||
|
0c0248a19c | ||
|
0429ec4cfd | ||
|
a740a48f62 | ||
|
b12f569fc6 | ||
|
7993a403f2 | ||
|
b0df67d9c0 | ||
|
45ff8569d7 | ||
|
82bfa2ee7b | ||
|
9ef2e5000f | ||
|
678546308e | ||
|
6f688c50ee | ||
|
bb603ff18e | ||
|
4208fdfd22 | ||
|
4875213168 | ||
|
f92540e8ad | ||
|
ec0bf899ed | ||
|
2b635a892c | ||
|
7f6fc148bd | ||
|
878e9f7594 | ||
|
c7249f5983 | ||
|
7f07858209 | ||
|
9e9688fc61 | ||
|
93e5ab367a | ||
|
60fa5807b9 | ||
|
9dbca41385 | ||
|
61588a43dd | ||
|
e62927ed71 |
3
.gitignore
vendored
3
.gitignore
vendored
@ -77,6 +77,7 @@ src/cmake_config_githash.h
|
|||||||
src/lua/build/
|
src/lua/build/
|
||||||
locale/
|
locale/
|
||||||
.directory
|
.directory
|
||||||
|
.gradle/
|
||||||
*.cbp
|
*.cbp
|
||||||
*.layout
|
*.layout
|
||||||
*.o
|
*.o
|
||||||
@ -84,6 +85,8 @@ locale/
|
|||||||
*.ninja
|
*.ninja
|
||||||
.ninja*
|
.ninja*
|
||||||
*.gch
|
*.gch
|
||||||
|
*.iml
|
||||||
|
test_config.h
|
||||||
cmake-build-debug/
|
cmake-build-debug/
|
||||||
cmake-build-release/
|
cmake-build-release/
|
||||||
|
|
||||||
|
@ -13,13 +13,14 @@ set(PROJECT_NAME_CAPITALIZED "Minetest")
|
|||||||
# Also remember to set PROTOCOL_VERSION in network/networkprotocol.h when releasing
|
# Also remember to set PROTOCOL_VERSION in network/networkprotocol.h when releasing
|
||||||
set(VERSION_MAJOR 0)
|
set(VERSION_MAJOR 0)
|
||||||
set(VERSION_MINOR 4)
|
set(VERSION_MINOR 4)
|
||||||
set(VERSION_PATCH 16)
|
set(VERSION_PATCH 17)
|
||||||
|
set(VERSION_TWEAK 1)
|
||||||
set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string")
|
set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string")
|
||||||
|
|
||||||
# Change to false for releases
|
# Change to false for releases
|
||||||
set(DEVELOPMENT_BUILD FALSE)
|
set(DEVELOPMENT_BUILD FALSE)
|
||||||
|
|
||||||
set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
|
set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}.${VERSION_TWEAK}")
|
||||||
if(VERSION_EXTRA)
|
if(VERSION_EXTRA)
|
||||||
set(VERSION_STRING ${VERSION_STRING}-${VERSION_EXTRA})
|
set(VERSION_STRING ${VERSION_STRING}-${VERSION_EXTRA})
|
||||||
elseif(DEVELOPMENT_BUILD)
|
elseif(DEVELOPMENT_BUILD)
|
||||||
|
@ -6,7 +6,8 @@ OS := $(shell uname)
|
|||||||
# GPROF = 1
|
# GPROF = 1
|
||||||
|
|
||||||
# build for build platform
|
# build for build platform
|
||||||
APP_PLATFORM = android-9
|
API = 14
|
||||||
|
APP_PLATFORM = android-$(API)
|
||||||
|
|
||||||
ANDR_ROOT = $(shell pwd)
|
ANDR_ROOT = $(shell pwd)
|
||||||
PROJ_ROOT = $(shell realpath $(ANDR_ROOT)/../..)
|
PROJ_ROOT = $(shell realpath $(ANDR_ROOT)/../..)
|
||||||
@ -30,7 +31,7 @@ TARGET_HOST = arm-linux
|
|||||||
TARGET_ABI = armeabi-v7a
|
TARGET_ABI = armeabi-v7a
|
||||||
TARGET_LIBDIR = armeabi-v7a
|
TARGET_LIBDIR = armeabi-v7a
|
||||||
TARGET_TOOLCHAIN = arm-linux-androideabi-
|
TARGET_TOOLCHAIN = arm-linux-androideabi-
|
||||||
TARGET_CFLAGS_ADDON = -mfloat-abi=softfp -mfpu=vfpv3 -O3
|
TARGET_CFLAGS_ADDON = -mfloat-abi=softfp -mfpu=vfpv3 -O3 -D__ANDROID_API__=$(API)
|
||||||
TARGET_CXXFLAGS_ADDON = $(TARGET_CFLAGS_ADDON)
|
TARGET_CXXFLAGS_ADDON = $(TARGET_CFLAGS_ADDON)
|
||||||
TARGET_ARCH = armv7
|
TARGET_ARCH = armv7
|
||||||
CROSS_PREFIX = arm-linux-androideabi-
|
CROSS_PREFIX = arm-linux-androideabi-
|
||||||
@ -82,7 +83,7 @@ OGG_LIB = $(OGG_DIR)libs/$(TARGET_ABI)/libogg.so
|
|||||||
VORBIS_LIB = $(OGG_DIR)libs/$(TARGET_ABI)/libogg.so
|
VORBIS_LIB = $(OGG_DIR)libs/$(TARGET_ABI)/libogg.so
|
||||||
OGG_TIMESTAMP = $(OGG_DIR)timestamp
|
OGG_TIMESTAMP = $(OGG_DIR)timestamp
|
||||||
OGG_TIMESTAMP_INT = $(ANDR_ROOT)/deps/ogg_timestamp
|
OGG_TIMESTAMP_INT = $(ANDR_ROOT)/deps/ogg_timestamp
|
||||||
OGG_URL_GIT = https://github.com/vincentjames501/libvorbis-libogg-android
|
OGG_URL_GIT = https://gitlab.com/minetest/libvorbis-libogg-android
|
||||||
|
|
||||||
IRRLICHT_REVISION = 5145
|
IRRLICHT_REVISION = 5145
|
||||||
IRRLICHT_DIR = $(ANDR_ROOT)/deps/irrlicht/
|
IRRLICHT_DIR = $(ANDR_ROOT)/deps/irrlicht/
|
||||||
@ -99,20 +100,13 @@ OPENSSL_TIMESTAMP = $(OPENSSL_DIR)timestamp
|
|||||||
OPENSSL_TIMESTAMP_INT = $(ANDR_ROOT)/deps/openssl_timestamp
|
OPENSSL_TIMESTAMP_INT = $(ANDR_ROOT)/deps/openssl_timestamp
|
||||||
OPENSSL_URL = https://www.openssl.org/source/openssl-$(OPENSSL_VERSION).tar.gz
|
OPENSSL_URL = https://www.openssl.org/source/openssl-$(OPENSSL_VERSION).tar.gz
|
||||||
|
|
||||||
CURL_VERSION = 7.54.0
|
CURL_VERSION = 7.60.0
|
||||||
CURL_DIR = $(ANDR_ROOT)/deps/curl-$(CURL_VERSION)
|
CURL_DIR = $(ANDR_ROOT)/deps/curl-$(CURL_VERSION)
|
||||||
CURL_LIB = $(CURL_DIR)/lib/.libs/libcurl.a
|
CURL_LIB = $(CURL_DIR)/lib/.libs/libcurl.a
|
||||||
CURL_TIMESTAMP = $(CURL_DIR)/timestamp
|
CURL_TIMESTAMP = $(CURL_DIR)/timestamp
|
||||||
CURL_TIMESTAMP_INT = $(ANDR_ROOT)/deps/curl_timestamp
|
CURL_TIMESTAMP_INT = $(ANDR_ROOT)/deps/curl_timestamp
|
||||||
CURL_URL_HTTP = https://curl.haxx.se/download/curl-${CURL_VERSION}.tar.bz2
|
CURL_URL_HTTP = https://curl.haxx.se/download/curl-${CURL_VERSION}.tar.bz2
|
||||||
|
|
||||||
GMP_VERSION = 6.1.2
|
|
||||||
GMP_DIR = $(ANDR_ROOT)/deps/gmp-$(GMP_VERSION)
|
|
||||||
GMP_LIB = $(GMP_DIR)/usr/lib/libgmp.so
|
|
||||||
GMP_TIMESTAMP = $(GMP_DIR)/timestamp
|
|
||||||
GMP_TIMESTAMP_INT = $(ANDR_ROOT)/deps/gmp_timestamp
|
|
||||||
GMP_URL_HTTP = https://gmplib.org/download/gmp/gmp-$(GMP_VERSION).tar.bz2
|
|
||||||
|
|
||||||
FREETYPE_DIR = $(ANDR_ROOT)/deps/freetype2-android/
|
FREETYPE_DIR = $(ANDR_ROOT)/deps/freetype2-android/
|
||||||
FREETYPE_LIB = $(FREETYPE_DIR)/Android/obj/local/$(TARGET_ABI)/libfreetype2-static.a
|
FREETYPE_LIB = $(FREETYPE_DIR)/Android/obj/local/$(TARGET_ABI)/libfreetype2-static.a
|
||||||
FREETYPE_TIMESTAMP = $(FREETYPE_DIR)timestamp
|
FREETYPE_TIMESTAMP = $(FREETYPE_DIR)timestamp
|
||||||
@ -126,12 +120,11 @@ ICONV_TIMESTAMP = $(ICONV_DIR)timestamp
|
|||||||
ICONV_TIMESTAMP_INT = $(ANDR_ROOT)/deps/iconv_timestamp
|
ICONV_TIMESTAMP_INT = $(ANDR_ROOT)/deps/iconv_timestamp
|
||||||
ICONV_URL_HTTP = https://ftp.gnu.org/pub/gnu/libiconv/libiconv-$(ICONV_VERSION).tar.gz
|
ICONV_URL_HTTP = https://ftp.gnu.org/pub/gnu/libiconv/libiconv-$(ICONV_VERSION).tar.gz
|
||||||
|
|
||||||
SQLITE3_FOLDER = sqlite-amalgamation-3180000
|
SQLITE3_FOLDER = sqlite-amalgamation-3240000
|
||||||
SQLITE3_URL = https://www.sqlite.org/2017/$(SQLITE3_FOLDER).zip
|
SQLITE3_URL = https://www.sqlite.org/2018/$(SQLITE3_FOLDER).zip
|
||||||
|
|
||||||
ANDROID_SDK = $(shell grep '^sdk\.dir' local.properties | sed 's/^.*=[[:space:]]*//')
|
ANDROID_SDK = $(shell grep '^sdk\.dir' local.properties | sed 's/^.*=[[:space:]]*//')
|
||||||
ANDROID_NDK = $(shell grep '^ndk\.dir' local.properties | sed 's/^.*=[[:space:]]*//')
|
ANDROID_NDK = $(shell grep '^ndk\.dir' local.properties | sed 's/^.*=[[:space:]]*//')
|
||||||
NDK_MODULE_PATH = $(ANDROID_NDK)/toolchains
|
|
||||||
|
|
||||||
#use interim target variable to switch leveldb on or off
|
#use interim target variable to switch leveldb on or off
|
||||||
ifeq ($(HAVE_LEVELDB),1)
|
ifeq ($(HAVE_LEVELDB),1)
|
||||||
@ -217,14 +210,10 @@ $(OPENAL_LIB): $(OPENAL_TIMESTAMP)
|
|||||||
if [ $$REFRESH -ne 0 ] ; then \
|
if [ $$REFRESH -ne 0 ] ; then \
|
||||||
echo "changed timestamp for openal detected building..."; \
|
echo "changed timestamp for openal detected building..."; \
|
||||||
cd ${OPENAL_DIR}; \
|
cd ${OPENAL_DIR}; \
|
||||||
|
export APP_PLATFORM=${APP_PLATFORM}; \
|
||||||
|
export TARGET_ABI=${TARGET_ABI}; \
|
||||||
${ANDROID_NDK}/ndk-build NDEBUG=${NDEBUG} \
|
${ANDROID_NDK}/ndk-build NDEBUG=${NDEBUG} \
|
||||||
NDK_MODULE_PATH=${NDK_MODULE_PATH} APP_ABI=${TARGET_ABI} \
|
NDK_APPLICATION_MK=${ANDR_ROOT}/jni/Deps.mk || exit 1; \
|
||||||
TARGET_ARCH_ABI=${TARGET_ABI} APP_PLATFORM=${APP_PLATFORM} \
|
|
||||||
PRIVATE_CC=${NDK_MODULE_PATH}/${TARGET_TOOLCHAIN}${COMPILER_VERSION}/prebuilt/linux-x86_64/bin/${TARGET_TOOLCHAIN}gcc \
|
|
||||||
PRIVATE_CXX=${NDK_MODULE_PATH}/${TARGET_TOOLCHAIN}${COMPILER_VERSION}/prebuilt/linux-x86_64/bin/${TARGET_TOOLCHAIN}g++ \
|
|
||||||
TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \
|
|
||||||
TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \
|
|
||||||
TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" || exit 1; \
|
|
||||||
touch ${OPENAL_TIMESTAMP}; \
|
touch ${OPENAL_TIMESTAMP}; \
|
||||||
touch ${OPENAL_TIMESTAMP_INT}; \
|
touch ${OPENAL_TIMESTAMP_INT}; \
|
||||||
else \
|
else \
|
||||||
@ -248,7 +237,6 @@ ogg_download :
|
|||||||
git clone ${OGG_URL_GIT}|| exit 1; \
|
git clone ${OGG_URL_GIT}|| exit 1; \
|
||||||
cd libvorbis-libogg-android ; \
|
cd libvorbis-libogg-android ; \
|
||||||
patch -p1 < ${ANDR_ROOT}/patches/libvorbis-libogg-fpu.patch || exit 1; \
|
patch -p1 < ${ANDR_ROOT}/patches/libvorbis-libogg-fpu.patch || exit 1; \
|
||||||
sed -i 's-:-?-' jni/Application.mk; \
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ogg : $(OGG_LIB)
|
ogg : $(OGG_LIB)
|
||||||
@ -265,14 +253,12 @@ $(OGG_LIB): $(OGG_TIMESTAMP)
|
|||||||
if [ $$REFRESH -ne 0 ] ; then \
|
if [ $$REFRESH -ne 0 ] ; then \
|
||||||
echo "changed timestamp for ogg detected building..."; \
|
echo "changed timestamp for ogg detected building..."; \
|
||||||
cd ${OGG_DIR}; \
|
cd ${OGG_DIR}; \
|
||||||
${ANDROID_NDK}/ndk-build NDEBUG=${NDEBUG} \
|
export APP_PLATFORM=${APP_PLATFORM}; \
|
||||||
NDK_MODULE_PATH=${NDK_MODULE_PATH} \
|
export TARGET_ABI=${TARGET_ABI}; \
|
||||||
APP_ABI=${TARGET_ABI} APP_PLATFORM=${APP_PLATFORM} \
|
${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \
|
||||||
PRIVATE_CC=${NDK_MODULE_PATH}/${TARGET_TOOLCHAIN}${COMPILER_VERSION}/prebuilt/linux-x86_64/bin/${TARGET_TOOLCHAIN}gcc \
|
--toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \
|
||||||
PRIVATE_CXX=${NDK_MODULE_PATH}/${TARGET_TOOLCHAIN}${COMPILER_VERSION}/prebuilt/linux-x86_64/bin/${TARGET_TOOLCHAIN}g++ \
|
--platform=${APP_PLATFORM} \
|
||||||
TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \
|
--install-dir=$${TOOLCHAIN}; \
|
||||||
TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \
|
|
||||||
TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" || exit 1; \
|
|
||||||
touch ${OGG_TIMESTAMP}; \
|
touch ${OGG_TIMESTAMP}; \
|
||||||
touch ${OGG_TIMESTAMP_INT}; \
|
touch ${OGG_TIMESTAMP_INT}; \
|
||||||
else \
|
else \
|
||||||
@ -301,7 +287,7 @@ openssl_download :
|
|||||||
|
|
||||||
openssl : $(OPENSSL_LIB)
|
openssl : $(OPENSSL_LIB)
|
||||||
|
|
||||||
$(OPENSSL_LIB): $(OPENSSL_TIMESTAMP) $(GMP_LIB)
|
$(OPENSSL_LIB): $(OPENSSL_TIMESTAMP)
|
||||||
@REFRESH=0; \
|
@REFRESH=0; \
|
||||||
if [ ! -e ${OPENSSL_TIMESTAMP_INT} ] ; then \
|
if [ ! -e ${OPENSSL_TIMESTAMP_INT} ] ; then \
|
||||||
echo "${OPENSSL_TIMESTAMP_INT} doesn't exist"; \
|
echo "${OPENSSL_TIMESTAMP_INT} doesn't exist"; \
|
||||||
@ -317,10 +303,10 @@ $(OPENSSL_LIB): $(OPENSSL_TIMESTAMP) $(GMP_LIB)
|
|||||||
export TOOLCHAIN=/tmp/ndk-${TARGET_HOST}-openssl; \
|
export TOOLCHAIN=/tmp/ndk-${TARGET_HOST}-openssl; \
|
||||||
${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \
|
${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \
|
||||||
--toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \
|
--toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \
|
||||||
--platform=android-9 \
|
--platform=${APP_PLATFORM} \
|
||||||
--install-dir=$${TOOLCHAIN}; \
|
--install-dir=$${TOOLCHAIN}; \
|
||||||
export PATH="$${TOOLCHAIN}/bin:$${PATH}"; \
|
export PATH="$${TOOLCHAIN}/bin:$${PATH}"; \
|
||||||
CC=${CROSS_PREFIX}gcc ./Configure enable-gmp -DL_ENDIAN -I${GMP_DIR} -L${GMP_DIR}/usr/lib android-${TARGET_ARCH};\
|
CC=${CROSS_PREFIX}gcc ./Configure -DL_ENDIAN android-${TARGET_ARCH};\
|
||||||
CC=${CROSS_PREFIX}gcc ANDROID_DEV=/tmp/ndk-${TARGET_HOST} make depend; \
|
CC=${CROSS_PREFIX}gcc ANDROID_DEV=/tmp/ndk-${TARGET_HOST} make depend; \
|
||||||
CC=${CROSS_PREFIX}gcc ANDROID_DEV=/tmp/ndk-${TARGET_HOST} make build_libs; \
|
CC=${CROSS_PREFIX}gcc ANDROID_DEV=/tmp/ndk-${TARGET_HOST} make build_libs; \
|
||||||
touch ${OPENSSL_TIMESTAMP}; \
|
touch ${OPENSSL_TIMESTAMP}; \
|
||||||
@ -368,7 +354,7 @@ $(LEVELDB_LIB): $(LEVELDB_TIMESTAMP)
|
|||||||
export TOOLCHAIN=/tmp/ndk-${TARGET_HOST}-leveldb; \
|
export TOOLCHAIN=/tmp/ndk-${TARGET_HOST}-leveldb; \
|
||||||
${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \
|
${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \
|
||||||
--toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \
|
--toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \
|
||||||
--platform=android-9 \
|
--platform=${APP_PLATFORM} \
|
||||||
--install-dir=$${TOOLCHAIN}; \
|
--install-dir=$${TOOLCHAIN}; \
|
||||||
export PATH="$${TOOLCHAIN}/bin:$${PATH}"; \
|
export PATH="$${TOOLCHAIN}/bin:$${PATH}"; \
|
||||||
export CC=${CROSS_PREFIX}gcc; \
|
export CC=${CROSS_PREFIX}gcc; \
|
||||||
@ -420,14 +406,10 @@ $(FREETYPE_LIB) : $(FREETYPE_TIMESTAMP)
|
|||||||
mkdir -p ${FREETYPE_DIR}; \
|
mkdir -p ${FREETYPE_DIR}; \
|
||||||
echo "changed timestamp for freetype detected building..."; \
|
echo "changed timestamp for freetype detected building..."; \
|
||||||
cd ${FREETYPE_DIR}/Android/jni; \
|
cd ${FREETYPE_DIR}/Android/jni; \
|
||||||
|
export APP_PLATFORM=${APP_PLATFORM}; \
|
||||||
|
export TARGET_ABI=${TARGET_ABI}; \
|
||||||
${ANDROID_NDK}/ndk-build NDEBUG=${NDEBUG} \
|
${ANDROID_NDK}/ndk-build NDEBUG=${NDEBUG} \
|
||||||
NDK_MODULE_PATH=${NDK_MODULE_PATH} \
|
NDK_APPLICATION_MK=${ANDR_ROOT}/jni/Deps.mk || exit 1; \
|
||||||
APP_PLATFORM=${APP_PLATFORM} APP_ABI=${TARGET_ABI} \
|
|
||||||
PRIVATE_CC=${NDK_MODULE_PATH}/${TARGET_TOOLCHAIN}${COMPILER_VERSION}/prebuilt/linux-x86_64/bin/${TARGET_TOOLCHAIN}gcc \
|
|
||||||
PRIVATE_CXX=${NDK_MODULE_PATH}/${TARGET_TOOLCHAIN}${COMPILER_VERSION}/prebuilt/linux-x86_64/bin/${TARGET_TOOLCHAIN}g++ \
|
|
||||||
TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \
|
|
||||||
TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \
|
|
||||||
TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" || exit 1; \
|
|
||||||
touch ${FREETYPE_TIMESTAMP}; \
|
touch ${FREETYPE_TIMESTAMP}; \
|
||||||
touch ${FREETYPE_TIMESTAMP_INT}; \
|
touch ${FREETYPE_TIMESTAMP_INT}; \
|
||||||
else \
|
else \
|
||||||
@ -478,9 +460,10 @@ $(ICONV_LIB) : $(ICONV_TIMESTAMP)
|
|||||||
export TOOLCHAIN=/tmp/ndk-${TARGET_HOST}-iconv; \
|
export TOOLCHAIN=/tmp/ndk-${TARGET_HOST}-iconv; \
|
||||||
${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \
|
${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \
|
||||||
--toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \
|
--toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \
|
||||||
--platform=android-9 \
|
--platform=${APP_PLATFORM} \
|
||||||
--install-dir=$${TOOLCHAIN}; \
|
--install-dir=$${TOOLCHAIN}; \
|
||||||
export PATH="$${TOOLCHAIN}/bin:$${PATH}"; \
|
export PATH="$${TOOLCHAIN}/bin:$${PATH}"; \
|
||||||
|
export CFLAGS="$${CFLAGS} ${TARGET_CFLAGS_ADDON}"; \
|
||||||
export CC=${CROSS_PREFIX}gcc; \
|
export CC=${CROSS_PREFIX}gcc; \
|
||||||
export CXX=${CROSS_PREFIX}g++; \
|
export CXX=${CROSS_PREFIX}g++; \
|
||||||
export TARGET_OS=OS_ANDROID_CROSSCOMPILE; \
|
export TARGET_OS=OS_ANDROID_CROSSCOMPILE; \
|
||||||
@ -513,6 +496,7 @@ irrlicht_download :
|
|||||||
patch -p1 < ${ANDR_ROOT}/patches/irrlicht-touchcount.patch || exit 1; \
|
patch -p1 < ${ANDR_ROOT}/patches/irrlicht-touchcount.patch || exit 1; \
|
||||||
patch -p1 < ${ANDR_ROOT}/patches/irrlicht-back_button.patch || exit 1; \
|
patch -p1 < ${ANDR_ROOT}/patches/irrlicht-back_button.patch || exit 1; \
|
||||||
patch -p1 < ${ANDR_ROOT}/patches/irrlicht-texturehack.patch || exit 1; \
|
patch -p1 < ${ANDR_ROOT}/patches/irrlicht-texturehack.patch || exit 1; \
|
||||||
|
patch -p1 < ${ANDR_ROOT}/patches/irrlicht-native_activity.patch || exit 1; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
$(IRRLICHT_TIMESTAMP) : irrlicht_download
|
$(IRRLICHT_TIMESTAMP) : irrlicht_download
|
||||||
@ -538,14 +522,10 @@ $(IRRLICHT_LIB): $(IRRLICHT_TIMESTAMP) $(FREETYPE_LIB)
|
|||||||
mkdir -p ${IRRLICHT_DIR}; \
|
mkdir -p ${IRRLICHT_DIR}; \
|
||||||
echo "changed timestamp for irrlicht detected building..."; \
|
echo "changed timestamp for irrlicht detected building..."; \
|
||||||
cd deps/irrlicht/source/Irrlicht/Android; \
|
cd deps/irrlicht/source/Irrlicht/Android; \
|
||||||
|
export APP_PLATFORM=${APP_PLATFORM}; \
|
||||||
|
export TARGET_ABI=${TARGET_ABI}; \
|
||||||
${ANDROID_NDK}/ndk-build NDEBUG=${NDEBUG} \
|
${ANDROID_NDK}/ndk-build NDEBUG=${NDEBUG} \
|
||||||
NDK_MODULE_PATH=${NDK_MODULE_PATH} \
|
NDK_APPLICATION_MK=${ANDR_ROOT}/jni/Irrlicht.mk || exit 1; \
|
||||||
APP_ABI=${TARGET_ABI} APP_PLATFORM=${APP_PLATFORM} \
|
|
||||||
PRIVATE_CC=${NDK_MODULE_PATH}/${TARGET_TOOLCHAIN}${COMPILER_VERSION}/prebuilt/linux-x86_64/bin/${TARGET_TOOLCHAIN}gcc \
|
|
||||||
PRIVATE_CXX=${NDK_MODULE_PATH}/${TARGET_TOOLCHAIN}${COMPILER_VERSION}/prebuilt/linux-x86_64/bin/${TARGET_TOOLCHAIN}g++ \
|
|
||||||
TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \
|
|
||||||
TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \
|
|
||||||
TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" || exit 1; \
|
|
||||||
touch ${IRRLICHT_TIMESTAMP}; \
|
touch ${IRRLICHT_TIMESTAMP}; \
|
||||||
touch ${IRRLICHT_TIMESTAMP_INT}; \
|
touch ${IRRLICHT_TIMESTAMP_INT}; \
|
||||||
else \
|
else \
|
||||||
@ -593,7 +573,7 @@ $(CURL_LIB): $(CURL_TIMESTAMP) $(OPENSSL_LIB)
|
|||||||
export TOOLCHAIN=/tmp/ndk-${TARGET_HOST}-curl; \
|
export TOOLCHAIN=/tmp/ndk-${TARGET_HOST}-curl; \
|
||||||
${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \
|
${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \
|
||||||
--toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \
|
--toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \
|
||||||
--platform=android-9 \
|
--platform=${APP_PLATFORM} \
|
||||||
--install-dir=$${TOOLCHAIN}; \
|
--install-dir=$${TOOLCHAIN}; \
|
||||||
export PATH="$${TOOLCHAIN}/bin:$${PATH}"; \
|
export PATH="$${TOOLCHAIN}/bin:$${PATH}"; \
|
||||||
export CC=${CROSS_PREFIX}gcc; \
|
export CC=${CROSS_PREFIX}gcc; \
|
||||||
@ -615,64 +595,6 @@ clean_curl :
|
|||||||
$(RM) -rf deps/curl-${CURL_VERSION} \
|
$(RM) -rf deps/curl-${CURL_VERSION} \
|
||||||
$(RM) -f deps/curl
|
$(RM) -f deps/curl
|
||||||
|
|
||||||
$(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 ${ANDR_ROOT}/deps; \
|
|
||||||
cd deps; \
|
|
||||||
wget ${GMP_URL_HTTP} || exit 1; \
|
|
||||||
tar -xjf gmp-${GMP_VERSION}.tar.bz2 || exit 1; \
|
|
||||||
rm gmp-${GMP_VERSION}.tar.bz2; \
|
|
||||||
ln -s gmp-${GMP_VERSION} gmp; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
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}; \
|
|
||||||
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} \
|
|
||||||
--platform=android-9 \
|
|
||||||
--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
|
|
||||||
|
|
||||||
clean_gmp:
|
|
||||||
$(RM) -rf deps/gmp-${GMP_VERSION} \
|
|
||||||
$(RM) -f deps/gmp
|
|
||||||
|
|
||||||
sqlite3_download: deps/${SQLITE3_FOLDER}/sqlite3.c
|
sqlite3_download: deps/${SQLITE3_FOLDER}/sqlite3.c
|
||||||
|
|
||||||
deps/${SQLITE3_FOLDER}/sqlite3.c :
|
deps/${SQLITE3_FOLDER}/sqlite3.c :
|
||||||
@ -762,20 +684,16 @@ assets : $(ASSETS_TIMESTAMP)
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
clean_assets :
|
clean_assets :
|
||||||
@$(RM) -r assets
|
@$(RM) -r ${APP_ROOT}/assets
|
||||||
|
|
||||||
apk: local.properties assets $(ICONV_LIB) $(IRRLICHT_LIB) $(CURL_LIB) $(GMP_LIB) $(LEVELDB_TARGET) \
|
apk: local.properties assets $(ICONV_LIB) $(IRRLICHT_LIB) $(CURL_LIB) $(LEVELDB_TARGET) \
|
||||||
$(OPENAL_LIB) $(OGG_LIB) prep_srcdir $(ANDR_ROOT)/jni/src/android_version.h \
|
$(OPENAL_LIB) $(OGG_LIB) prep_srcdir $(ANDR_ROOT)/jni/src/android_version.h \
|
||||||
$(ANDR_ROOT)/jni/src/android_version_githash.h sqlite3_download
|
$(ANDR_ROOT)/jni/src/android_version_githash.h sqlite3_download
|
||||||
+ @${ANDROID_NDK}/ndk-build NDK_MODULE_PATH=${NDK_MODULE_PATH} \
|
+ @export TARGET_LIBDIR=${TARGET_LIBDIR}; \
|
||||||
GPROF=${GPROF} APP_ABI=${TARGET_ABI} HAVE_LEVELDB=${HAVE_LEVELDB} \
|
export HAVE_LEVELDB=${HAVE_LEVELDB}; \
|
||||||
APP_PLATFORM=${APP_PLATFORM} \
|
export APP_PLATFORM=${APP_PLATFORM}; \
|
||||||
PRIVATE_CC=${NDK_MODULE_PATH}/${TARGET_TOOLCHAIN}${COMPILER_VERSION}/prebuilt/linux-x86_64/bin/${TARGET_TOOLCHAIN}gcc \
|
export TARGET_ABI=${TARGET_ABI}; \
|
||||||
PRIVATE_CXX=${NDK_MODULE_PATH}/${TARGET_TOOLCHAIN}${COMPILER_VERSION}/prebuilt/linux-x86_64/bin/${TARGET_TOOLCHAIN}g++ \
|
${ANDROID_NDK}/ndk-build || exit 1; \
|
||||||
TARGET_LIBDIR=${TARGET_LIBDIR} \
|
|
||||||
TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \
|
|
||||||
TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \
|
|
||||||
TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" || exit 1; \
|
|
||||||
if [ ! -e ${APP_ROOT}/jniLibs ]; then \
|
if [ ! -e ${APP_ROOT}/jniLibs ]; then \
|
||||||
ln -s ${ANDR_ROOT}/libs ${APP_ROOT}/jniLibs || exit 1; \
|
ln -s ${ANDR_ROOT}/libs ${APP_ROOT}/jniLibs || exit 1; \
|
||||||
fi; \
|
fi; \
|
||||||
@ -807,7 +725,7 @@ clean_apk :
|
|||||||
clean_all :
|
clean_all :
|
||||||
@$(MAKE) clean_apk; \
|
@$(MAKE) clean_apk; \
|
||||||
$(MAKE) clean_assets clean_iconv clean_irrlicht clean_leveldb clean_curl \
|
$(MAKE) clean_assets clean_iconv clean_irrlicht clean_leveldb clean_curl \
|
||||||
clean_openssl clean_openal clean_ogg clean_gmp; \
|
clean_openssl clean_openal clean_ogg; \
|
||||||
sleep 1; \
|
sleep 1; \
|
||||||
$(RM) -r gen libs obj deps bin Debug and_env
|
$(RM) -r gen libs obj deps bin Debug and_env
|
||||||
|
|
||||||
|
@ -1,25 +1,46 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
maven { url 'https://maven.google.com' }
|
||||||
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath "com.android.tools.build:gradle:1.5.0"
|
classpath 'com.android.tools.build:gradle:3.1.3'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
repositories {
|
||||||
|
maven { url 'https://maven.google.com' }
|
||||||
|
jcenter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def curl_version = "7.60.0"
|
||||||
|
def gmp_version = "6.1.2"
|
||||||
|
def irrlicht_revision = "5150"
|
||||||
|
def openal_version = "1.18.2"
|
||||||
|
def openssl_version = "1.0.2n"
|
||||||
|
def sqlite3_version = "3260000"
|
||||||
|
|
||||||
apply plugin: "com.android.application"
|
apply plugin: "com.android.application"
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 25
|
compileSdkVersion 28
|
||||||
buildToolsVersion "25.0.3"
|
buildToolsVersion "28.0.3"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
versionCode 17
|
versionCode 22
|
||||||
versionName "${System.env.VERSION_STR}.${versionCode}"
|
versionName "${System.env.VERSION_STR}.${versionCode}"
|
||||||
minSdkVersion 9
|
minSdkVersion 14
|
||||||
targetSdkVersion 9
|
targetSdkVersion 28
|
||||||
applicationId "net.minetest.minetest"
|
applicationId "net.minetest.minetest"
|
||||||
manifestPlaceholders = [package: "net.minetest.minetest", project: project.name]
|
manifestPlaceholders = [package: "net.minetest.minetest", project: project.name]
|
||||||
|
ndk {
|
||||||
|
// Specifies the ABI configurations of your native
|
||||||
|
// libraries Gradle should build and package with your APK.
|
||||||
|
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64',
|
||||||
|
'arm64-v8a'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lintOptions {
|
lintOptions {
|
||||||
@ -46,3 +67,68 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task cleanAssets(type: Delete) {
|
||||||
|
delete 'src/main/assets'
|
||||||
|
}
|
||||||
|
|
||||||
|
task cleanIconv(type: Delete) {
|
||||||
|
delete 'deps/libiconv'
|
||||||
|
}
|
||||||
|
|
||||||
|
task cleanIrrlicht(type: Delete) {
|
||||||
|
delete 'deps/irrlicht'
|
||||||
|
}
|
||||||
|
|
||||||
|
task cleanLevelDB(type: Delete) {
|
||||||
|
delete 'deps/leveldb'
|
||||||
|
}
|
||||||
|
|
||||||
|
task cleanCURL(type: Delete) {
|
||||||
|
delete 'deps/curl'
|
||||||
|
delete 'deps/curl-' + curl_version
|
||||||
|
}
|
||||||
|
|
||||||
|
task cleanOpenSSL(type: Delete) {
|
||||||
|
delete 'deps/openssl'
|
||||||
|
delete 'deps/openssl-' + openssl_version
|
||||||
|
delete 'deps/openssl-' + openssl_version + '.tar.gz'
|
||||||
|
}
|
||||||
|
|
||||||
|
task cleanOpenAL(type: Delete) {
|
||||||
|
delete 'deps/openal-soft'
|
||||||
|
}
|
||||||
|
|
||||||
|
task cleanFreetype(type: Delete) {
|
||||||
|
delete 'deps/freetype2-android'
|
||||||
|
}
|
||||||
|
|
||||||
|
task cleanOgg(type: Delete) {
|
||||||
|
delete 'deps/libvorbis-libogg-android'
|
||||||
|
}
|
||||||
|
|
||||||
|
task cleanSQLite3(type: Delete) {
|
||||||
|
delete 'deps/sqlite-amalgamation-' + sqlite3_version
|
||||||
|
delete 'deps/sqlite-amalgamation-' + sqlite3_version + '.zip'
|
||||||
|
}
|
||||||
|
|
||||||
|
task cleanGMP(type: Delete) {
|
||||||
|
delete 'deps/gmp'
|
||||||
|
delete 'deps/gmp-' + gmp_version
|
||||||
|
}
|
||||||
|
|
||||||
|
task cleanAll(type: Delete, dependsOn: [clean, cleanAssets, cleanIconv,
|
||||||
|
cleanFreetype, cleanIrrlicht, cleanLevelDB, cleanSQLite3, cleanCURL,
|
||||||
|
cleanOpenSSL, cleanOpenAL, cleanOgg, cleanGMP]) {
|
||||||
|
delete 'deps'
|
||||||
|
delete 'gen'
|
||||||
|
delete 'libs'
|
||||||
|
delete 'obj'
|
||||||
|
delete 'bin'
|
||||||
|
delete 'Debug'
|
||||||
|
delete 'and_env'
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'com.android.support:support-v4:28.0.0'
|
||||||
|
}
|
||||||
|
BIN
build/android/gradle/wrapper/gradle-wrapper.jar
vendored
BIN
build/android/gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
@ -1,6 +1,6 @@
|
|||||||
#Sat Aug 27 20:10:09 CEST 2016
|
#Mon Oct 15 00:47:03 CEST 2018
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
|
||||||
|
74
build/android/gradlew
vendored
74
build/android/gradlew
vendored
@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
##
|
##
|
||||||
@ -6,12 +6,30 @@
|
|||||||
##
|
##
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
# Attempt to set APP_HOME
|
||||||
DEFAULT_JVM_OPTS=""
|
# Resolve links: $0 may be a link
|
||||||
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
APP_NAME="Gradle"
|
APP_NAME="Gradle"
|
||||||
APP_BASE_NAME=`basename "$0"`
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS=""
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD="maximum"
|
MAX_FD="maximum"
|
||||||
|
|
||||||
@ -30,6 +48,7 @@ die ( ) {
|
|||||||
cygwin=false
|
cygwin=false
|
||||||
msys=false
|
msys=false
|
||||||
darwin=false
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
case "`uname`" in
|
case "`uname`" in
|
||||||
CYGWIN* )
|
CYGWIN* )
|
||||||
cygwin=true
|
cygwin=true
|
||||||
@ -40,31 +59,11 @@ case "`uname`" in
|
|||||||
MINGW* )
|
MINGW* )
|
||||||
msys=true
|
msys=true
|
||||||
;;
|
;;
|
||||||
|
NONSTOP* )
|
||||||
|
nonstop=true
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# For Cygwin, ensure paths are in UNIX format before anything is touched.
|
|
||||||
if $cygwin ; then
|
|
||||||
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Attempt to set APP_HOME
|
|
||||||
# Resolve links: $0 may be a link
|
|
||||||
PRG="$0"
|
|
||||||
# Need this for relative symlinks.
|
|
||||||
while [ -h "$PRG" ] ; do
|
|
||||||
ls=`ls -ld "$PRG"`
|
|
||||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
|
||||||
if expr "$link" : '/.*' > /dev/null; then
|
|
||||||
PRG="$link"
|
|
||||||
else
|
|
||||||
PRG=`dirname "$PRG"`"/$link"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
SAVED="`pwd`"
|
|
||||||
cd "`dirname \"$PRG\"`/" >&-
|
|
||||||
APP_HOME="`pwd -P`"
|
|
||||||
cd "$SAVED" >&-
|
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
# Determine the Java command to use to start the JVM.
|
# Determine the Java command to use to start the JVM.
|
||||||
@ -90,7 +89,7 @@ location of your Java installation."
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||||
MAX_FD_LIMIT=`ulimit -H -n`
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
if [ $? -eq 0 ] ; then
|
if [ $? -eq 0 ] ; then
|
||||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
@ -114,6 +113,7 @@ fi
|
|||||||
if $cygwin ; then
|
if $cygwin ; then
|
||||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
# We build the pattern for arguments to be converted via cygpath
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
@ -154,11 +154,19 @@ if $cygwin ; then
|
|||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
# Escape application args
|
||||||
function splitJvmOpts() {
|
save () {
|
||||||
JVM_OPTS=("$@")
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
}
|
}
|
||||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
APP_ARGS=$(save "$@")
|
||||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
|
||||||
|
|
||||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
|
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||||
|
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
||||||
|
14
build/android/gradlew.bat
vendored
14
build/android/gradlew.bat
vendored
@ -8,14 +8,14 @@
|
|||||||
@rem Set local scope for the variables with windows NT shell
|
@rem Set local scope for the variables with windows NT shell
|
||||||
if "%OS%"=="Windows_NT" setlocal
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
|
||||||
set DEFAULT_JVM_OPTS=
|
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%" == "" set DIRNAME=.
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS=
|
||||||
|
|
||||||
@rem Find java.exe
|
@rem Find java.exe
|
||||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
@ -46,10 +46,9 @@ echo location of your Java installation.
|
|||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:init
|
:init
|
||||||
@rem Get command-line arguments, handling Windowz variants
|
@rem Get command-line arguments, handling Windows variants
|
||||||
|
|
||||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
|
||||||
|
|
||||||
:win9xME_args
|
:win9xME_args
|
||||||
@rem Slurp the command line arguments.
|
@rem Slurp the command line arguments.
|
||||||
@ -60,11 +59,6 @@ set _SKIP=2
|
|||||||
if "x%~1" == "x" goto execute
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
set CMD_LINE_ARGS=%*
|
set CMD_LINE_ARGS=%*
|
||||||
goto execute
|
|
||||||
|
|
||||||
:4NT_args
|
|
||||||
@rem Get arguments from the 4NT Shell from JP Software
|
|
||||||
set CMD_LINE_ARGS=%$
|
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
@ -44,11 +44,6 @@ LOCAL_MODULE := vorbis
|
|||||||
LOCAL_SRC_FILES := deps/libvorbis-libogg-android/libs/$(TARGET_LIBDIR)/libvorbis.so
|
LOCAL_SRC_FILES := deps/libvorbis-libogg-android/libs/$(TARGET_LIBDIR)/libvorbis.so
|
||||||
include $(PREBUILT_SHARED_LIBRARY)
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
LOCAL_MODULE := gmp
|
|
||||||
LOCAL_SRC_FILES := deps/gmp/usr/lib/libgmp.so
|
|
||||||
include $(PREBUILT_SHARED_LIBRARY)
|
|
||||||
|
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE := ssl
|
LOCAL_MODULE := ssl
|
||||||
LOCAL_SRC_FILES := deps/openssl/libssl.a
|
LOCAL_SRC_FILES := deps/openssl/libssl.a
|
||||||
@ -98,6 +93,7 @@ endif
|
|||||||
LOCAL_C_INCLUDES := \
|
LOCAL_C_INCLUDES := \
|
||||||
jni/src \
|
jni/src \
|
||||||
jni/src/script \
|
jni/src/script \
|
||||||
|
jni/lib/gmp \
|
||||||
jni/lib/lua/src \
|
jni/lib/lua/src \
|
||||||
jni/lib/jsoncpp \
|
jni/lib/jsoncpp \
|
||||||
jni/src/cguittfont \
|
jni/src/cguittfont \
|
||||||
@ -107,7 +103,6 @@ LOCAL_C_INCLUDES := \
|
|||||||
deps/curl/include \
|
deps/curl/include \
|
||||||
deps/openal-soft/jni/OpenAL/include \
|
deps/openal-soft/jni/OpenAL/include \
|
||||||
deps/libvorbis-libogg-android/jni/include \
|
deps/libvorbis-libogg-android/jni/include \
|
||||||
deps/gmp/usr/include \
|
|
||||||
deps/leveldb/include \
|
deps/leveldb/include \
|
||||||
deps/sqlite/
|
deps/sqlite/
|
||||||
|
|
||||||
@ -339,6 +334,9 @@ LOCAL_SRC_FILES += \
|
|||||||
#freetype2 support
|
#freetype2 support
|
||||||
LOCAL_SRC_FILES += jni/src/cguittfont/xCGUITTFont.cpp
|
LOCAL_SRC_FILES += jni/src/cguittfont/xCGUITTFont.cpp
|
||||||
|
|
||||||
|
# GMP
|
||||||
|
LOCAL_SRC_FILES += jni/lib/gmp/mini-gmp.c
|
||||||
|
|
||||||
# Lua
|
# Lua
|
||||||
LOCAL_SRC_FILES += \
|
LOCAL_SRC_FILES += \
|
||||||
jni/lib/lua/src/lapi.c \
|
jni/lib/lua/src/lapi.c \
|
||||||
@ -385,7 +383,7 @@ LOCAL_SRC_FILES += \
|
|||||||
# JSONCPP
|
# JSONCPP
|
||||||
LOCAL_SRC_FILES += jni/lib/jsoncpp/jsoncpp.cpp
|
LOCAL_SRC_FILES += jni/lib/jsoncpp/jsoncpp.cpp
|
||||||
|
|
||||||
LOCAL_SHARED_LIBRARIES := iconv openal ogg vorbis gmp
|
LOCAL_SHARED_LIBRARIES := iconv openal ogg vorbis
|
||||||
LOCAL_STATIC_LIBRARIES := Irrlicht freetype curl ssl crypto android_native_app_glue $(PROFILER_LIBS)
|
LOCAL_STATIC_LIBRARIES := Irrlicht freetype curl ssl crypto android_native_app_glue $(PROFILER_LIBS)
|
||||||
|
|
||||||
ifeq ($(HAVE_LEVELDB), 1)
|
ifeq ($(HAVE_LEVELDB), 1)
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
# NDK_TOOLCHAIN_VERSION := clang3.8
|
APP_PLATFORM := ${APP_PLATFORM}
|
||||||
|
APP_ABI := ${TARGET_ABI}
|
||||||
APP_PLATFORM := android-9
|
APP_STL := c++_shared
|
||||||
APP_MODULES := minetest
|
APP_MODULES := minetest
|
||||||
APP_STL := gnustl_static
|
|
||||||
|
|
||||||
APP_CPPFLAGS += -fexceptions
|
|
||||||
APP_GNUSTL_FORCE_CPP_FEATURES := rtti
|
|
||||||
|
|
||||||
|
APP_CPPFLAGS += -fexceptions -frtti
|
||||||
|
7
build/android/jni/Deps.mk
Normal file
7
build/android/jni/Deps.mk
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
APP_PLATFORM := ${APP_PLATFORM}
|
||||||
|
APP_ABI := ${TARGET_ABI}
|
||||||
|
APP_STL := c++_shared
|
||||||
|
APP_DEPRECATED_HEADERS := true
|
||||||
|
|
||||||
|
APP_CFLAGS += -mfloat-abi=softfp -mfpu=vfpv3 -O3
|
||||||
|
APP_CPPFLAGS += -fexceptions
|
8
build/android/jni/Irrlicht.mk
Normal file
8
build/android/jni/Irrlicht.mk
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
APP_PLATFORM := ${APP_PLATFORM}
|
||||||
|
APP_ABI := ${TARGET_ABI}
|
||||||
|
APP_STL := c++_static
|
||||||
|
APP_DEPRECATED_HEADERS := true
|
||||||
|
APP_MODULES := Irrlicht
|
||||||
|
|
||||||
|
APP_CFLAGS += -mfloat-abi=softfp -mfpu=vfpv3 -O3
|
||||||
|
APP_CPPFLAGS += -fexceptions
|
13
build/android/patches/irrlicht-native_activity.patch
Normal file
13
build/android/patches/irrlicht-native_activity.patch
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
--- irrlicht/source/Irrlicht/CEGLManager.cpp.orig 2018-06-10 16:58:11.357709173 +0200
|
||||||
|
+++ irrlicht/source/Irrlicht/CEGLManager.cpp 2018-06-10 16:58:25.100709843 +0200
|
||||||
|
@@ -9,6 +9,10 @@
|
||||||
|
#include "irrString.h"
|
||||||
|
#include "os.h"
|
||||||
|
|
||||||
|
+#if defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_)
|
||||||
|
+#include <android/native_activity.h>
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
namespace irr
|
||||||
|
{
|
||||||
|
namespace video
|
@ -1,2 +1 @@
|
|||||||
rootProject.name = "Minetest"
|
rootProject.name = "Minetest"
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.SET_DEBUG_APP" />
|
<uses-permission android:name="android.permission.SET_DEBUG_APP" />
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@ -2,33 +2,58 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="net.minetest.minetest"
|
package="net.minetest.minetest"
|
||||||
android:installLocation="auto">
|
android:installLocation="auto">
|
||||||
<uses-feature android:glEsVersion="0x00010000" android:required="true"/>
|
|
||||||
|
<uses-feature
|
||||||
|
android:glEsVersion="0x00010000"
|
||||||
|
android:required="true" />
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
<application android:icon="@drawable/irr_icon"
|
|
||||||
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="${project}"
|
android:label="${project}"
|
||||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
|
android:resizeableActivity="false">
|
||||||
android:allowBackup="true">
|
|
||||||
<activity android:name=".MtNativeActivity"
|
<meta-data
|
||||||
|
android:name="android.max_aspect"
|
||||||
|
android:value="2.1" />
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".MainActivity"
|
||||||
|
android:configChanges="orientation|keyboardHidden|navigation|screenSize"
|
||||||
android:label="${project}"
|
android:label="${project}"
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
android:configChanges="orientation|keyboard|keyboardHidden|navigation"
|
|
||||||
android:screenOrientation="sensorLandscape"
|
android:screenOrientation="sensorLandscape"
|
||||||
android:clearTaskOnLaunch="true">
|
android:theme="@style/AppTheme">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<meta-data android:name="android.app.lib_name" android:value="minetest" />
|
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".MinetestTextEntry"
|
<activity
|
||||||
android:theme="@style/Theme.Transparent"
|
android:name=".MtNativeActivity"
|
||||||
android:excludeFromRecents="true">
|
android:configChanges="orientation|keyboard|keyboardHidden|navigation|screenSize|smallestScreenSize"
|
||||||
</activity>
|
android:hardwareAccelerated="true"
|
||||||
<activity android:name=".MinetestAssetCopy"
|
android:launchMode="singleTask"
|
||||||
android:theme="@style/Theme.Transparent"
|
android:screenOrientation="sensorLandscape"
|
||||||
android:excludeFromRecents="true">
|
android:theme="@style/AppTheme">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
</intent-filter>
|
||||||
|
<meta-data
|
||||||
|
android:name="android.app.lib_name"
|
||||||
|
android:value="minetest" />
|
||||||
</activity>
|
</activity>
|
||||||
|
<activity
|
||||||
|
android:name=".MinetestTextEntry"
|
||||||
|
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||||
|
android:theme="@style/Theme.Dialog"
|
||||||
|
android:windowSoftInputMode="stateAlwaysHidden"/>
|
||||||
|
<activity
|
||||||
|
android:name=".MinetestAssetCopy"
|
||||||
|
android:screenOrientation="sensorLandscape"
|
||||||
|
android:theme="@style/AppTheme"/>
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@ -0,0 +1,79 @@
|
|||||||
|
package net.minetest.minetest;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.v4.app.ActivityCompat;
|
||||||
|
import android.support.v4.content.ContextCompat;;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class MainActivity extends Activity {
|
||||||
|
|
||||||
|
private final static int PERMISSIONS = 1;
|
||||||
|
private static final String[] REQUIRED_SDK_PERMISSIONS = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
checkPermission();
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void checkPermission() {
|
||||||
|
final List<String> missingPermissions = new ArrayList<String>();
|
||||||
|
// check required permission
|
||||||
|
for (final String permission : REQUIRED_SDK_PERMISSIONS) {
|
||||||
|
final int result = ContextCompat.checkSelfPermission(this, permission);
|
||||||
|
if (result != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
missingPermissions.add(permission);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!missingPermissions.isEmpty()) {
|
||||||
|
// request permission
|
||||||
|
final String[] permissions = missingPermissions
|
||||||
|
.toArray(new String[missingPermissions.size()]);
|
||||||
|
ActivityCompat.requestPermissions(this, permissions, PERMISSIONS);
|
||||||
|
} else {
|
||||||
|
final int[] grantResults = new int[REQUIRED_SDK_PERMISSIONS.length];
|
||||||
|
Arrays.fill(grantResults, PackageManager.PERMISSION_GRANTED);
|
||||||
|
onRequestPermissionsResult(PERMISSIONS, REQUIRED_SDK_PERMISSIONS,
|
||||||
|
grantResults);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[],
|
||||||
|
@NonNull int[] grantResults) {
|
||||||
|
switch (requestCode) {
|
||||||
|
case PERMISSIONS:
|
||||||
|
for (int index = 0; index < permissions.length; index++) {
|
||||||
|
if (grantResults[index] != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
// permission not granted - toast and exit
|
||||||
|
Toast.makeText(this, R.string.not_granted, Toast.LENGTH_LONG).show();
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// permission were granted - run
|
||||||
|
next();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void next() {
|
||||||
|
Intent intent = new Intent(this, MtNativeActivity.class);
|
||||||
|
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,17 @@
|
|||||||
package net.minetest.minetest;
|
package net.minetest.minetest;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.res.AssetFileDescriptor;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.Display;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
@ -7,36 +19,20 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.Vector;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.lang.Object;
|
import java.util.Vector;
|
||||||
|
|
||||||
import android.app.Activity;
|
public class MinetestAssetCopy extends Activity {
|
||||||
import android.content.res.AssetFileDescriptor;
|
ProgressBar m_ProgressBar;
|
||||||
|
TextView m_Filename;
|
||||||
|
copyAssetTask m_AssetCopy;
|
||||||
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Environment;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.Display;
|
|
||||||
import android.widget.ProgressBar;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.graphics.Rect;
|
|
||||||
import android.graphics.Paint;
|
|
||||||
import android.text.TextPaint;
|
|
||||||
|
|
||||||
public class MinetestAssetCopy extends Activity
|
|
||||||
{
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState)
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
{
|
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
setContentView(R.layout.assetcopy);
|
setContentView(R.layout.assetcopy);
|
||||||
|
m_ProgressBar = findViewById(R.id.progressBar1);
|
||||||
m_ProgressBar = (ProgressBar) findViewById(R.id.progressBar1);
|
m_Filename = findViewById(R.id.textView1);
|
||||||
m_Filename = (TextView) findViewById(R.id.textView1);
|
|
||||||
|
|
||||||
Display display = getWindowManager().getDefaultDisplay();
|
Display display = getWindowManager().getDefaultDisplay();
|
||||||
m_ProgressBar.getLayoutParams().width = (int) (display.getWidth() * 0.8);
|
m_ProgressBar.getLayoutParams().width = (int) (display.getWidth() * 0.8);
|
||||||
m_ProgressBar.invalidate();
|
m_ProgressBar.invalidate();
|
||||||
@ -46,51 +42,67 @@ public class MinetestAssetCopy extends Activity
|
|||||||
(MinetestAssetCopy) getLastNonConfigurationInstance();
|
(MinetestAssetCopy) getLastNonConfigurationInstance();
|
||||||
if (prevActivity != null) {
|
if (prevActivity != null) {
|
||||||
m_AssetCopy = prevActivity.m_AssetCopy;
|
m_AssetCopy = prevActivity.m_AssetCopy;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
m_AssetCopy = new copyAssetTask();
|
m_AssetCopy = new copyAssetTask();
|
||||||
m_AssetCopy.execute();
|
m_AssetCopy.execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
makeFullScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void makeFullScreen() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||||
|
this.getWindow().getDecorView().setSystemUiVisibility(
|
||||||
|
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onWindowFocusChanged(boolean hasFocus) {
|
||||||
|
super.onWindowFocusChanged(hasFocus);
|
||||||
|
if (hasFocus) {
|
||||||
|
makeFullScreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* preserve asset copy background task to prevent restart of copying */
|
/* preserve asset copy background task to prevent restart of copying */
|
||||||
/* this way of doing it is not recommended for latest android version */
|
/* this way of doing it is not recommended for latest android version */
|
||||||
/* but the recommended way isn't available on android 2.x */
|
/* but the recommended way isn't available on android 2.x */
|
||||||
public Object onRetainNonConfigurationInstance()
|
public Object onRetainNonConfigurationInstance() {
|
||||||
{
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProgressBar m_ProgressBar;
|
private class copyAssetTask extends AsyncTask<String, Integer, String> {
|
||||||
TextView m_Filename;
|
boolean m_copy_started = false;
|
||||||
|
String m_Foldername = "media";
|
||||||
|
Vector<String> m_foldernames;
|
||||||
|
Vector<String> m_filenames;
|
||||||
|
Vector<String> m_tocopy;
|
||||||
|
Vector<String> m_asset_size_unknown;
|
||||||
|
|
||||||
copyAssetTask m_AssetCopy;
|
private long getFullSize(String filename) {
|
||||||
|
|
||||||
private class copyAssetTask extends AsyncTask<String, Integer, String>
|
|
||||||
{
|
|
||||||
private long getFullSize(String filename)
|
|
||||||
{
|
|
||||||
long size = 0;
|
long size = 0;
|
||||||
try {
|
try {
|
||||||
InputStream src = getAssets().open(filename);
|
InputStream src = getAssets().open(filename);
|
||||||
byte[] buf = new byte[4096];
|
byte[] buf = new byte[4096];
|
||||||
|
|
||||||
int len = 0;
|
int len = 0;
|
||||||
while ((len = src.read(buf)) > 0)
|
while ((len = src.read(buf)) > 0) {
|
||||||
{
|
|
||||||
size += len;
|
size += len;
|
||||||
}
|
}
|
||||||
}
|
} catch (IOException e) {
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String doInBackground(String... files)
|
protected String doInBackground(String... files) {
|
||||||
{
|
|
||||||
m_foldernames = new Vector<String>();
|
m_foldernames = new Vector<String>();
|
||||||
m_filenames = new Vector<String>();
|
m_filenames = new Vector<String>();
|
||||||
m_tocopy = new Vector<String>();
|
m_tocopy = new Vector<String>();
|
||||||
@ -103,15 +115,12 @@ public class MinetestAssetCopy extends Activity
|
|||||||
// prepare temp folder
|
// prepare temp folder
|
||||||
File TempFolder = new File(baseDir + "Minetest/tmp/");
|
File TempFolder = new File(baseDir + "Minetest/tmp/");
|
||||||
|
|
||||||
if (!TempFolder.exists())
|
if (!TempFolder.exists()) {
|
||||||
{
|
|
||||||
TempFolder.mkdir();
|
TempFolder.mkdir();
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
File[] todel = TempFolder.listFiles();
|
File[] todel = TempFolder.listFiles();
|
||||||
|
|
||||||
for(int i=0; i < todel.length; i++)
|
for (int i = 0; i < todel.length; i++) {
|
||||||
{
|
|
||||||
Log.v("MinetestAssetCopy", "deleting: " + todel[i].getAbsolutePath());
|
Log.v("MinetestAssetCopy", "deleting: " + todel[i].getAbsolutePath());
|
||||||
todel[i].delete();
|
todel[i].delete();
|
||||||
}
|
}
|
||||||
@ -138,30 +147,25 @@ public class MinetestAssetCopy extends Activity
|
|||||||
m_copy_started = true;
|
m_copy_started = true;
|
||||||
m_ProgressBar.setMax(m_tocopy.size());
|
m_ProgressBar.setMax(m_tocopy.size());
|
||||||
|
|
||||||
for (int i = 0; i < m_tocopy.size(); i++)
|
for (int i = 0; i < m_tocopy.size(); i++) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
String filename = m_tocopy.get(i);
|
String filename = m_tocopy.get(i);
|
||||||
publishProgress(i);
|
publishProgress(i);
|
||||||
|
|
||||||
boolean asset_size_unknown = false;
|
boolean asset_size_unknown = false;
|
||||||
long filesize = -1;
|
long filesize = -1;
|
||||||
|
|
||||||
if (m_asset_size_unknown.contains(filename))
|
if (m_asset_size_unknown.contains(filename)) {
|
||||||
{
|
|
||||||
File testme = new File(baseDir + "/" + filename);
|
File testme = new File(baseDir + "/" + filename);
|
||||||
|
|
||||||
if(testme.exists())
|
if (testme.exists()) {
|
||||||
{
|
|
||||||
filesize = testme.length();
|
filesize = testme.length();
|
||||||
}
|
}
|
||||||
asset_size_unknown = true;
|
asset_size_unknown = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
InputStream src;
|
InputStream src;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
src = getAssets().open(filename);
|
src = getAssets().open(filename);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e("MinetestAssetCopy", "Copying file: " + filename + " FAILED (not in assets)");
|
Log.e("MinetestAssetCopy", "Copying file: " + filename + " FAILED (not in assets)");
|
||||||
@ -170,39 +174,33 @@ public class MinetestAssetCopy extends Activity
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Transfer bytes from in to out
|
// Transfer bytes from in to out
|
||||||
byte[] buf = new byte[1*1024];
|
byte[] buf = new byte[1024];
|
||||||
int len = src.read(buf, 0, 1024);
|
int len = src.read(buf, 0, 1024);
|
||||||
|
|
||||||
/* following handling is crazy but we need to deal with */
|
/* following handling is crazy but we need to deal with */
|
||||||
/* compressed assets.Flash chips limited livetime due to */
|
/* compressed assets.Flash chips limited livetime due to */
|
||||||
/* write operations, we can't allow large files to destroy */
|
/* write operations, we can't allow large files to destroy */
|
||||||
/* users flash. */
|
/* users flash. */
|
||||||
if (asset_size_unknown)
|
if (asset_size_unknown) {
|
||||||
{
|
if ((len > 0) && (len < buf.length) && (len == filesize)) {
|
||||||
if ( (len > 0) && (len < buf.length) && (len == filesize))
|
|
||||||
{
|
|
||||||
src.close();
|
src.close();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len == buf.length)
|
if (len == buf.length) {
|
||||||
{
|
|
||||||
src.close();
|
src.close();
|
||||||
long size = getFullSize(filename);
|
long size = getFullSize(filename);
|
||||||
if ( size == filesize)
|
if (size == filesize) {
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
src = getAssets().open(filename);
|
src = getAssets().open(filename);
|
||||||
len = src.read(buf, 0, 1024);
|
len = src.read(buf, 0, 1024);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (len > 0)
|
if (len > 0) {
|
||||||
{
|
|
||||||
int total_filesize = 0;
|
int total_filesize = 0;
|
||||||
OutputStream dst;
|
OutputStream dst;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
dst = new FileOutputStream(baseDir + "/" + filename);
|
dst = new FileOutputStream(baseDir + "/" + filename);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e("MinetestAssetCopy", "Copying file: " + baseDir +
|
Log.e("MinetestAssetCopy", "Copying file: " + baseDir +
|
||||||
@ -214,8 +212,7 @@ public class MinetestAssetCopy extends Activity
|
|||||||
dst.write(buf, 0, len);
|
dst.write(buf, 0, len);
|
||||||
total_filesize += len;
|
total_filesize += len;
|
||||||
|
|
||||||
while ((len = src.read(buf)) > 0)
|
while ((len = src.read(buf)) > 0) {
|
||||||
{
|
|
||||||
dst.write(buf, 0, len);
|
dst.write(buf, 0, len);
|
||||||
total_filesize += len;
|
total_filesize += len;
|
||||||
}
|
}
|
||||||
@ -224,16 +221,12 @@ public class MinetestAssetCopy extends Activity
|
|||||||
Log.v("MinetestAssetCopy", "Copied file: " +
|
Log.v("MinetestAssetCopy", "Copied file: " +
|
||||||
m_tocopy.get(i) + " (" + total_filesize +
|
m_tocopy.get(i) + " (" + total_filesize +
|
||||||
" bytes)");
|
" bytes)");
|
||||||
}
|
} else if (len < 0) {
|
||||||
else if (len < 0)
|
|
||||||
{
|
|
||||||
Log.e("MinetestAssetCopy", "Copying file: " +
|
Log.e("MinetestAssetCopy", "Copying file: " +
|
||||||
m_tocopy.get(i) + " failed, size < 0");
|
m_tocopy.get(i) + " failed, size < 0");
|
||||||
}
|
}
|
||||||
src.close();
|
src.close();
|
||||||
}
|
} catch (IOException e) {
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
Log.e("MinetestAssetCopy", "Copying file: " +
|
Log.e("MinetestAssetCopy", "Copying file: " +
|
||||||
m_tocopy.get(i) + " failed");
|
m_tocopy.get(i) + " failed");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -242,22 +235,17 @@ public class MinetestAssetCopy extends Activity
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* update progress bar
|
* update progress bar
|
||||||
*/
|
*/
|
||||||
protected void onProgressUpdate(Integer... progress)
|
protected void onProgressUpdate(Integer... progress) {
|
||||||
{
|
|
||||||
|
|
||||||
if (m_copy_started)
|
if (m_copy_started) {
|
||||||
{
|
|
||||||
boolean shortened = false;
|
boolean shortened = false;
|
||||||
String todisplay = m_tocopy.get(progress[0]);
|
String todisplay = m_tocopy.get(progress[0]);
|
||||||
m_ProgressBar.setProgress(progress[0]);
|
m_ProgressBar.setProgress(progress[0]);
|
||||||
m_Filename.setText(todisplay);
|
m_Filename.setText(todisplay);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
boolean shortened = false;
|
boolean shortened = false;
|
||||||
String todisplay = m_Foldername;
|
String todisplay = m_Foldername;
|
||||||
String full_text = "scanning " + todisplay + " ...";
|
String full_text = "scanning " + todisplay + " ...";
|
||||||
@ -266,37 +254,30 @@ public class MinetestAssetCopy extends Activity
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* check al files and folders in filelist
|
* check all files and folders in filelist
|
||||||
*/
|
*/
|
||||||
protected void ProcessFileList()
|
protected void ProcessFileList() {
|
||||||
{
|
|
||||||
String FlashBaseDir =
|
String FlashBaseDir =
|
||||||
Environment.getExternalStorageDirectory().getAbsolutePath();
|
Environment.getExternalStorageDirectory().getAbsolutePath();
|
||||||
|
|
||||||
Iterator itr = m_filenames.iterator();
|
Iterator itr = m_filenames.iterator();
|
||||||
|
|
||||||
while (itr.hasNext())
|
while (itr.hasNext()) {
|
||||||
{
|
|
||||||
String current_path = (String) itr.next();
|
String current_path = (String) itr.next();
|
||||||
String FlashPath = FlashBaseDir + "/" + current_path;
|
String FlashPath = FlashBaseDir + "/" + current_path;
|
||||||
|
|
||||||
if (isAssetFolder(current_path))
|
if (isAssetFolder(current_path)) {
|
||||||
{
|
|
||||||
/* store information and update gui */
|
/* store information and update gui */
|
||||||
m_Foldername = current_path;
|
m_Foldername = current_path;
|
||||||
publishProgress(0);
|
publishProgress(0);
|
||||||
|
|
||||||
/* open file in order to check if it's a folder */
|
/* open file in order to check if it's a folder */
|
||||||
File current_folder = new File(FlashPath);
|
File current_folder = new File(FlashPath);
|
||||||
if (!current_folder.exists())
|
if (!current_folder.exists()) {
|
||||||
{
|
if (!current_folder.mkdirs()) {
|
||||||
if (!current_folder.mkdirs())
|
|
||||||
{
|
|
||||||
Log.e("MinetestAssetCopy", "\t failed create folder: " +
|
Log.e("MinetestAssetCopy", "\t failed create folder: " +
|
||||||
FlashPath);
|
FlashPath);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
Log.v("MinetestAssetCopy", "\t created folder: " +
|
Log.v("MinetestAssetCopy", "\t created folder: " +
|
||||||
FlashPath);
|
FlashPath);
|
||||||
}
|
}
|
||||||
@ -313,16 +294,12 @@ public class MinetestAssetCopy extends Activity
|
|||||||
long asset_filesize = -1;
|
long asset_filesize = -1;
|
||||||
long stored_filesize = -1;
|
long stored_filesize = -1;
|
||||||
|
|
||||||
if (testme.exists())
|
if (testme.exists()) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
AssetFileDescriptor fd = getAssets().openFd(current_path);
|
AssetFileDescriptor fd = getAssets().openFd(current_path);
|
||||||
asset_filesize = fd.getLength();
|
asset_filesize = fd.getLength();
|
||||||
fd.close();
|
fd.close();
|
||||||
}
|
} catch (IOException e) {
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
refresh = true;
|
refresh = true;
|
||||||
m_asset_size_unknown.add(current_path);
|
m_asset_size_unknown.add(current_path);
|
||||||
Log.e("MinetestAssetCopy", "Failed to open asset file \"" +
|
Log.e("MinetestAssetCopy", "Failed to open asset file \"" +
|
||||||
@ -331,15 +308,13 @@ public class MinetestAssetCopy extends Activity
|
|||||||
|
|
||||||
stored_filesize = testme.length();
|
stored_filesize = testme.length();
|
||||||
|
|
||||||
if (asset_filesize == stored_filesize)
|
if (asset_filesize == stored_filesize) {
|
||||||
{
|
|
||||||
refresh = false;
|
refresh = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (refresh)
|
if (refresh) {
|
||||||
{
|
|
||||||
m_tocopy.add(current_path);
|
m_tocopy.add(current_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -348,22 +323,18 @@ public class MinetestAssetCopy extends Activity
|
|||||||
/**
|
/**
|
||||||
* read list of folders prepared on package build
|
* read list of folders prepared on package build
|
||||||
*/
|
*/
|
||||||
protected void BuildFolderList()
|
protected void BuildFolderList() {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
InputStream is = getAssets().open("index.txt");
|
InputStream is = getAssets().open("index.txt");
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||||
|
|
||||||
String line = reader.readLine();
|
String line = reader.readLine();
|
||||||
while (line != null)
|
while (line != null) {
|
||||||
{
|
|
||||||
m_foldernames.add(line);
|
m_foldernames.add(line);
|
||||||
line = reader.readLine();
|
line = reader.readLine();
|
||||||
}
|
}
|
||||||
is.close();
|
is.close();
|
||||||
} catch (IOException e1)
|
} catch (IOException e1) {
|
||||||
{
|
|
||||||
Log.e("MinetestAssetCopy", "Error on processing index.txt");
|
Log.e("MinetestAssetCopy", "Error on processing index.txt");
|
||||||
e1.printStackTrace();
|
e1.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -372,45 +343,31 @@ public class MinetestAssetCopy extends Activity
|
|||||||
/**
|
/**
|
||||||
* read list of asset files prepared on package build
|
* read list of asset files prepared on package build
|
||||||
*/
|
*/
|
||||||
protected void BuildFileList()
|
protected void BuildFileList() {
|
||||||
{
|
|
||||||
long entrycount = 0;
|
long entrycount = 0;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
InputStream is = getAssets().open("filelist.txt");
|
InputStream is = getAssets().open("filelist.txt");
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||||
|
|
||||||
String line = reader.readLine();
|
String line = reader.readLine();
|
||||||
while (line != null)
|
while (line != null) {
|
||||||
{
|
|
||||||
m_filenames.add(line);
|
m_filenames.add(line);
|
||||||
line = reader.readLine();
|
line = reader.readLine();
|
||||||
entrycount++;
|
entrycount++;
|
||||||
}
|
}
|
||||||
is.close();
|
is.close();
|
||||||
}
|
} catch (IOException e1) {
|
||||||
catch (IOException e1)
|
|
||||||
{
|
|
||||||
Log.e("MinetestAssetCopy", "Error on processing filelist.txt");
|
Log.e("MinetestAssetCopy", "Error on processing filelist.txt");
|
||||||
e1.printStackTrace();
|
e1.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onPostExecute (String result)
|
protected void onPostExecute(String result) {
|
||||||
{
|
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isAssetFolder(String path)
|
protected boolean isAssetFolder(String path) {
|
||||||
{
|
|
||||||
return m_foldernames.contains(path);
|
return m_foldernames.contains(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean m_copy_started = false;
|
|
||||||
String m_Foldername = "media";
|
|
||||||
Vector<String> m_foldernames;
|
|
||||||
Vector<String> m_filenames;
|
|
||||||
Vector<String> m_tocopy;
|
|
||||||
Vector<String> m_asset_size_unknown;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,24 +6,21 @@ import android.content.DialogInterface;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnKeyListener;
|
import android.view.View.OnKeyListener;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
|
||||||
public class MinetestTextEntry extends Activity {
|
public class MinetestTextEntry extends Activity {
|
||||||
public AlertDialog mTextInputDialog;
|
|
||||||
public EditText mTextInputWidget;
|
|
||||||
|
|
||||||
private final int MultiLineTextInput = 1;
|
private final int MultiLineTextInput = 1;
|
||||||
private final int SingleLineTextInput = 2;
|
private final int SingleLineTextInput = 2;
|
||||||
private final int SingleLinePasswordInput = 3;
|
private final int SingleLinePasswordInput = 3;
|
||||||
|
public AlertDialog mTextInputDialog;
|
||||||
|
public EditText mTextInputWidget;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
Bundle b = getIntent().getExtras();
|
Bundle b = getIntent().getExtras();
|
||||||
String acceptButton = b.getString("EnterButton");
|
String acceptButton = b.getString("EnterButton");
|
||||||
String hint = b.getString("hint");
|
String hint = b.getString("hint");
|
||||||
@ -38,18 +35,17 @@ public class MinetestTextEntry extends Activity {
|
|||||||
if (editType == SingleLinePasswordInput) {
|
if (editType == SingleLinePasswordInput) {
|
||||||
mTextInputWidget.setInputType(InputType.TYPE_CLASS_TEXT |
|
mTextInputWidget.setInputType(InputType.TYPE_CLASS_TEXT |
|
||||||
InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
mTextInputWidget.setInputType(InputType.TYPE_CLASS_TEXT);
|
mTextInputWidget.setInputType(InputType.TYPE_CLASS_TEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
builder.setView(mTextInputWidget);
|
builder.setView(mTextInputWidget);
|
||||||
|
|
||||||
if (editType == MultiLineTextInput) {
|
if (editType == MultiLineTextInput) {
|
||||||
builder.setPositiveButton(acceptButton, new DialogInterface.OnClickListener() {
|
builder.setPositiveButton(acceptButton, new DialogInterface.OnClickListener() {
|
||||||
public void onClick(DialogInterface dialog, int whichButton)
|
public void onClick(DialogInterface dialog, int whichButton) {
|
||||||
{ pushResult(mTextInputWidget.getText().toString()); }
|
pushResult(mTextInputWidget.getText().toString());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,22 +2,54 @@ package net.minetest.minetest;
|
|||||||
|
|
||||||
import android.app.NativeActivity;
|
import android.app.NativeActivity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.view.View;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
|
||||||
public class MtNativeActivity extends NativeActivity {
|
public class MtNativeActivity extends NativeActivity {
|
||||||
|
|
||||||
|
static {
|
||||||
|
System.loadLibrary("c++_shared");
|
||||||
|
System.loadLibrary("openal");
|
||||||
|
System.loadLibrary("ogg");
|
||||||
|
System.loadLibrary("vorbis");
|
||||||
|
System.loadLibrary("iconv");
|
||||||
|
System.loadLibrary("minetest");
|
||||||
|
}
|
||||||
|
|
||||||
|
private int m_MessagReturnCode;
|
||||||
|
private String m_MessageReturnValue;
|
||||||
|
|
||||||
|
public static native void putMessageBoxResult(String text);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
m_MessagReturnCode = -1;
|
m_MessagReturnCode = -1;
|
||||||
m_MessageReturnValue = "";
|
m_MessageReturnValue = "";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
protected void onResume() {
|
||||||
super.onDestroy();
|
super.onResume();
|
||||||
|
makeFullScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void makeFullScreen() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||||
|
this.getWindow().getDecorView().setSystemUiVisibility(
|
||||||
|
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onWindowFocusChanged(boolean hasFocus) {
|
||||||
|
super.onWindowFocusChanged(hasFocus);
|
||||||
|
if (hasFocus) {
|
||||||
|
makeFullScreen();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void copyAssets() {
|
public void copyAssets() {
|
||||||
@ -40,8 +72,6 @@ public class MtNativeActivity extends NativeActivity {
|
|||||||
m_MessagReturnCode = -1;
|
m_MessagReturnCode = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static native void putMessageBoxResult(String text);
|
|
||||||
|
|
||||||
/* ugly code to workaround putMessageBoxResult not beeing found */
|
/* ugly code to workaround putMessageBoxResult not beeing found */
|
||||||
public int getDialogState() {
|
public int getDialogState() {
|
||||||
return m_MessagReturnCode;
|
return m_MessagReturnCode;
|
||||||
@ -72,28 +102,9 @@ public class MtNativeActivity extends NativeActivity {
|
|||||||
String text = data.getStringExtra("text");
|
String text = data.getStringExtra("text");
|
||||||
m_MessagReturnCode = 0;
|
m_MessagReturnCode = 0;
|
||||||
m_MessageReturnValue = text;
|
m_MessageReturnValue = text;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
m_MessagReturnCode = 1;
|
m_MessagReturnCode = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static {
|
|
||||||
System.loadLibrary("openal");
|
|
||||||
System.loadLibrary("ogg");
|
|
||||||
System.loadLibrary("vorbis");
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 5.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.2 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3.0 KiB |
Binary file not shown.
Before Width: | Height: | Size: 7.4 KiB |
BIN
build/android/src/main/res/drawable/background.png
Normal file
BIN
build/android/src/main/res/drawable/background.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 83 B |
4
build/android/src/main/res/drawable/bg.xml
Normal file
4
build/android/src/main/res/drawable/bg.xml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:src="@drawable/background"
|
||||||
|
android:tileMode="repeat" />
|
@ -1,24 +1,24 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="fill_parent"
|
android:id="@+id/activity_main"
|
||||||
android:layout_height="fill_parent"
|
android:layout_width="match_parent"
|
||||||
android:orientation="vertical" >
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/progressBar1"
|
android:id="@+id/progressBar1"
|
||||||
style="?android:attr/progressBarStyleHorizontal"
|
style="?android:attr/progressBarStyleHorizontal"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="30dp"
|
||||||
android:layout_gravity="center_vertical" />
|
android:layout_centerInParent="true"
|
||||||
|
android:layout_marginLeft="90dp"
|
||||||
|
android:layout_marginRight="90dp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/textView1"
|
android:id="@+id/textView1"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:ellipsize="middle"
|
android:layout_below="@+id/progressBar1"
|
||||||
android:singleLine="true"
|
android:layout_centerInParent="true"
|
||||||
android:layout_gravity="center_horizontal"
|
android:text="@string/preparing_media" />
|
||||||
android:text="@string/preparing_media"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
</RelativeLayout>
|
||||||
|
BIN
build/android/src/main/res/mipmap/ic_launcher.png
Normal file
BIN
build/android/src/main/res/mipmap/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.6 KiB |
12
build/android/src/main/res/values-v21/styles.xml
Normal file
12
build/android/src/main/res/values-v21/styles.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<style name="AppTheme" parent="@android:style/android:Theme.Material.Light.NoActionBar.Fullscreen">
|
||||||
|
<item name="android:windowNoTitle">true</item>
|
||||||
|
<item name="android:windowAnimationStyle">@null</item>
|
||||||
|
<item name="android:windowBackground">@drawable/bg</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="Theme.Dialog" parent="@android:style/Theme.Material.Light.Dialog.NoActionBar"/>
|
||||||
|
|
||||||
|
</resources>
|
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="preparing_media">Preparing media...</string>
|
<string name="preparing_media">Preparing media…</string>
|
||||||
|
<string name="not_granted">Required permission wasn\'t granted, Minetest can\'t run without it</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<style name="Theme.Transparent" parent="android:Theme">
|
|
||||||
<item name="android:windowIsTranslucent">true</item>
|
<style name="AppTheme" parent="@android:style/android:Theme.Holo.Light.NoActionBar.Fullscreen">
|
||||||
<item name="android:windowBackground">@android:color/transparent</item>
|
|
||||||
<item name="android:windowContentOverlay">@null</item>
|
|
||||||
<item name="android:windowNoTitle">true</item>
|
<item name="android:windowNoTitle">true</item>
|
||||||
<item name="android:windowIsFloating">true</item>
|
<item name="android:windowAnimationStyle">@null</item>
|
||||||
<item name="android:backgroundDimEnabled">false</item>
|
<item name="android:windowBackground">@drawable/bg</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="Theme.Dialog" parent="@android:style/android:Theme.Holo.Light.Dialog.NoActionBar"/>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
@ -120,7 +120,12 @@ end
|
|||||||
-- The dumped and level arguments are internal-only.
|
-- The dumped and level arguments are internal-only.
|
||||||
|
|
||||||
function dump(o, indent, nested, level)
|
function dump(o, indent, nested, level)
|
||||||
if type(o) ~= "table" then
|
local t = type(o)
|
||||||
|
if not level and t == "userdata" then
|
||||||
|
-- when userdata (e.g. player) is passed directly, print its metatable:
|
||||||
|
return "userdata metatable: " .. dump(getmetatable(o))
|
||||||
|
end
|
||||||
|
if t ~= "table" then
|
||||||
return basic_dump(o)
|
return basic_dump(o)
|
||||||
end
|
end
|
||||||
-- Contains table -> true/nil of currently nested tables
|
-- Contains table -> true/nil of currently nested tables
|
||||||
@ -308,59 +313,25 @@ function core.formspec_escape(text)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function core.wrap_text(text, charlimit)
|
function core.wrap_text(text, max_length, as_table)
|
||||||
local retval = {}
|
local result = {}
|
||||||
|
local line = {}
|
||||||
local current_idx = 1
|
if #text <= max_length then
|
||||||
|
return as_table and {text} or text
|
||||||
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
|
|
||||||
stop = nl_stop
|
|
||||||
gotnewline = true
|
|
||||||
end
|
|
||||||
local last_line = ""
|
|
||||||
while start ~= nil do
|
|
||||||
if string.len(last_line) + (stop-start) > charlimit then
|
|
||||||
retval[#retval + 1] = last_line
|
|
||||||
last_line = ""
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if last_line ~= "" then
|
for word in text:gmatch('%S+') do
|
||||||
last_line = last_line .. " "
|
local cur_length = #table.concat(line, ' ')
|
||||||
|
if cur_length > 0 and cur_length + #word + 1 >= max_length then
|
||||||
|
-- word wouldn't fit on current line, move to next line
|
||||||
|
table.insert(result, table.concat(line, ' '))
|
||||||
|
line = {}
|
||||||
|
end
|
||||||
|
table.insert(line, word)
|
||||||
end
|
end
|
||||||
|
|
||||||
last_line = last_line .. string_sub(text, current_idx, stop - 1)
|
table.insert(result, table.concat(line, ' '))
|
||||||
|
return as_table and result or table.concat(result, '\n')
|
||||||
if gotnewline then
|
|
||||||
retval[#retval + 1] = 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)
|
|
||||||
|
|
||||||
if nl_start ~= nil and (start == nil or nl_start < start) then
|
|
||||||
start = nl_start
|
|
||||||
stop = nl_stop
|
|
||||||
gotnewline = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--add last part of text
|
|
||||||
if string.len(last_line) + (string.len(text) - current_idx) > charlimit then
|
|
||||||
retval[#retval + 1] = last_line
|
|
||||||
retval[#retval + 1] = string_sub(text, current_idx)
|
|
||||||
else
|
|
||||||
last_line = last_line .. " " .. string_sub(text, current_idx)
|
|
||||||
retval[#retval + 1] = last_line
|
|
||||||
end
|
|
||||||
|
|
||||||
return retval
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
@ -370,7 +341,7 @@ if INIT == "game" then
|
|||||||
local dirs2 = {20, 23, 22, 21}
|
local dirs2 = {20, 23, 22, 21}
|
||||||
|
|
||||||
function core.rotate_and_place(itemstack, placer, pointed_thing,
|
function core.rotate_and_place(itemstack, placer, pointed_thing,
|
||||||
infinitestacks, orient_flags)
|
infinitestacks, orient_flags, prevent_after_place)
|
||||||
orient_flags = orient_flags or {}
|
orient_flags = orient_flags or {}
|
||||||
|
|
||||||
local unode = core.get_node_or_nil(pointed_thing.under)
|
local unode = core.get_node_or_nil(pointed_thing.under)
|
||||||
@ -379,41 +350,20 @@ if INIT == "game" then
|
|||||||
end
|
end
|
||||||
local undef = core.registered_nodes[unode.name]
|
local undef = core.registered_nodes[unode.name]
|
||||||
if undef and undef.on_rightclick then
|
if undef and undef.on_rightclick then
|
||||||
undef.on_rightclick(pointed_thing.under, unode, placer,
|
return undef.on_rightclick(pointed_thing.under, unode, placer,
|
||||||
itemstack, pointed_thing)
|
itemstack, pointed_thing)
|
||||||
return
|
|
||||||
end
|
end
|
||||||
local fdir = core.dir_to_facedir(placer:get_look_dir())
|
local fdir = placer and core.dir_to_facedir(placer:get_look_dir()) or 0
|
||||||
local wield_name = itemstack:get_name()
|
|
||||||
|
|
||||||
local above = pointed_thing.above
|
local above = pointed_thing.above
|
||||||
local under = pointed_thing.under
|
local under = pointed_thing.under
|
||||||
local iswall = (above.y == under.y)
|
local iswall = (above.y == under.y)
|
||||||
local isceiling = not iswall and (above.y < under.y)
|
local isceiling = not iswall and (above.y < under.y)
|
||||||
local anode = core.get_node_or_nil(above)
|
|
||||||
if not anode then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local pos = pointed_thing.above
|
|
||||||
local node = anode
|
|
||||||
|
|
||||||
if undef and undef.buildable_to then
|
if undef and undef.buildable_to then
|
||||||
pos = pointed_thing.under
|
|
||||||
node = unode
|
|
||||||
iswall = false
|
iswall = false
|
||||||
end
|
end
|
||||||
|
|
||||||
if core.is_protected(pos, placer:get_player_name()) then
|
|
||||||
core.record_protection_violation(pos,
|
|
||||||
placer:get_player_name())
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local ndef = core.registered_nodes[node.name]
|
|
||||||
if not ndef or not ndef.buildable_to then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if orient_flags.force_floor then
|
if orient_flags.force_floor then
|
||||||
iswall = false
|
iswall = false
|
||||||
isceiling = false
|
isceiling = false
|
||||||
@ -427,31 +377,26 @@ if INIT == "game" then
|
|||||||
iswall = not iswall
|
iswall = not iswall
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local param2 = fdir
|
||||||
if iswall then
|
if iswall then
|
||||||
core.set_node(pos, {name = wield_name,
|
param2 = dirs1[fdir + 1]
|
||||||
param2 = dirs1[fdir + 1]})
|
|
||||||
elseif isceiling then
|
elseif isceiling then
|
||||||
if orient_flags.force_facedir then
|
if orient_flags.force_facedir then
|
||||||
core.set_node(pos, {name = wield_name,
|
cparam2 = 20
|
||||||
param2 = 20})
|
|
||||||
else
|
else
|
||||||
core.set_node(pos, {name = wield_name,
|
param2 = dirs2[fdir + 1]
|
||||||
param2 = dirs2[fdir + 1]})
|
|
||||||
end
|
end
|
||||||
else -- place right side up
|
else -- place right side up
|
||||||
if orient_flags.force_facedir then
|
if orient_flags.force_facedir then
|
||||||
core.set_node(pos, {name = wield_name,
|
param2 = 0
|
||||||
param2 = 0})
|
|
||||||
else
|
|
||||||
core.set_node(pos, {name = wield_name,
|
|
||||||
param2 = fdir})
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if not infinitestacks then
|
local old_itemstack = ItemStack(itemstack)
|
||||||
itemstack:take_item()
|
local new_itemstack, removed = core.item_place_node(
|
||||||
return itemstack
|
itemstack, placer, pointed_thing, param2, prevent_after_place
|
||||||
end
|
)
|
||||||
|
return infinitestacks and old_itemstack or new_itemstack
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -459,12 +404,18 @@ if INIT == "game" then
|
|||||||
--Wrapper for rotate_and_place() to check for sneak and assume Creative mode
|
--Wrapper for rotate_and_place() to check for sneak and assume Creative mode
|
||||||
--implies infinite stacks when performing a 6d rotation.
|
--implies infinite stacks when performing a 6d rotation.
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
local creative_mode_cache = core.settings:get_bool("creative_mode")
|
||||||
|
local function is_creative(name)
|
||||||
|
return creative_mode_cache or
|
||||||
|
core.check_player_privs(name, {creative = true})
|
||||||
|
end
|
||||||
|
|
||||||
core.rotate_node = function(itemstack, placer, pointed_thing)
|
core.rotate_node = function(itemstack, placer, pointed_thing)
|
||||||
|
local name = placer and placer:get_player_name() or ""
|
||||||
|
local invert_wall = placer and placer:get_player_control().sneak or false
|
||||||
core.rotate_and_place(itemstack, placer, pointed_thing,
|
core.rotate_and_place(itemstack, placer, pointed_thing,
|
||||||
core.settings:get_bool("creative_mode"),
|
is_creative(name),
|
||||||
{invert_wall = placer:get_player_control().sneak})
|
{invert_wall = invert_wall}, true)
|
||||||
return itemstack
|
return itemstack
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -642,23 +593,6 @@ end
|
|||||||
|
|
||||||
local ESCAPE_CHAR = string.char(0x1b)
|
local ESCAPE_CHAR = string.char(0x1b)
|
||||||
|
|
||||||
-- Client-side mods don't have access to settings
|
|
||||||
if core.settings and core.settings:get_bool("disable_escape_sequences") then
|
|
||||||
|
|
||||||
function core.get_color_escape_sequence(color)
|
|
||||||
return ""
|
|
||||||
end
|
|
||||||
|
|
||||||
function core.get_background_escape_sequence(color)
|
|
||||||
return ""
|
|
||||||
end
|
|
||||||
|
|
||||||
function core.colorize(color, message)
|
|
||||||
return message
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
function core.get_color_escape_sequence(color)
|
function core.get_color_escape_sequence(color)
|
||||||
return ESCAPE_CHAR .. "(c@" .. color .. ")"
|
return ESCAPE_CHAR .. "(c@" .. color .. ")"
|
||||||
end
|
end
|
||||||
@ -678,7 +612,6 @@ else
|
|||||||
return table.concat(lines, "\n") .. core.get_color_escape_sequence("#ffffff")
|
return table.concat(lines, "\n") .. core.get_color_escape_sequence("#ffffff")
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
function core.strip_foreground_colors(str)
|
function core.strip_foreground_colors(str)
|
||||||
return (str:gsub(ESCAPE_CHAR .. "%(c@[^)]+%)", ""))
|
return (str:gsub(ESCAPE_CHAR .. "%(c@[^)]+%)", ""))
|
||||||
|
@ -67,16 +67,15 @@ local function save_auth_file()
|
|||||||
assert(type(stuff.privileges) == "table")
|
assert(type(stuff.privileges) == "table")
|
||||||
assert(stuff.last_login == nil or type(stuff.last_login) == "number")
|
assert(stuff.last_login == nil or type(stuff.last_login) == "number")
|
||||||
end
|
end
|
||||||
local file, errmsg = io.open(core.auth_file_path, 'w+b')
|
local content = {}
|
||||||
if not file then
|
|
||||||
error(core.auth_file_path.." could not be opened for writing: "..errmsg)
|
|
||||||
end
|
|
||||||
for name, stuff in pairs(core.auth_table) do
|
for name, stuff in pairs(core.auth_table) do
|
||||||
local priv_string = core.privs_to_string(stuff.privileges)
|
local priv_string = core.privs_to_string(stuff.privileges)
|
||||||
local parts = {name, stuff.password, priv_string, stuff.last_login or ""}
|
local parts = {name, stuff.password, priv_string, stuff.last_login or ""}
|
||||||
file:write(table.concat(parts, ":").."\n")
|
content[#content + 1] = table.concat(parts, ":")
|
||||||
|
end
|
||||||
|
if not core.safe_file_write(core.auth_file_path, table.concat(content, "\n")) then
|
||||||
|
error(core.auth_file_path.." could not be written to")
|
||||||
end
|
end
|
||||||
io.close(file)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
read_auth_file()
|
read_auth_file()
|
||||||
|
@ -653,8 +653,8 @@ core.register_chatcommand("pulverize", {
|
|||||||
core.rollback_punch_callbacks = {}
|
core.rollback_punch_callbacks = {}
|
||||||
|
|
||||||
core.register_on_punchnode(function(pos, node, puncher)
|
core.register_on_punchnode(function(pos, node, puncher)
|
||||||
local name = puncher:get_player_name()
|
local name = puncher and puncher:get_player_name()
|
||||||
if core.rollback_punch_callbacks[name] then
|
if name and core.rollback_punch_callbacks[name] then
|
||||||
core.rollback_punch_callbacks[name](pos, node, puncher)
|
core.rollback_punch_callbacks[name](pos, node, puncher)
|
||||||
core.rollback_punch_callbacks[name] = nil
|
core.rollback_punch_callbacks[name] = nil
|
||||||
end
|
end
|
||||||
@ -814,7 +814,7 @@ core.register_chatcommand("shutdown", {
|
|||||||
message = message or ""
|
message = message or ""
|
||||||
|
|
||||||
if delay ~= "" then
|
if delay ~= "" then
|
||||||
delay = tonumber(param) or 0
|
delay = tonumber(delay) or 0
|
||||||
else
|
else
|
||||||
delay = 0
|
delay = 0
|
||||||
core.log("action", name .. " shuts down server")
|
core.log("action", name .. " shuts down server")
|
||||||
|
@ -60,8 +60,13 @@ core.register_entity(":__builtin:falling_node", {
|
|||||||
local pos = self.object:getpos()
|
local pos = self.object:getpos()
|
||||||
-- Position of bottom center point
|
-- Position of bottom center point
|
||||||
local bcp = {x = pos.x, y = pos.y - 0.7, z = pos.z}
|
local bcp = {x = pos.x, y = pos.y - 0.7, z = pos.z}
|
||||||
-- Avoid bugs caused by an unloaded node below
|
-- 'bcn' is nil for unloaded nodes
|
||||||
local bcn = core.get_node_or_nil(bcp)
|
local bcn = core.get_node_or_nil(bcp)
|
||||||
|
-- Delete on contact with ignore at world edges
|
||||||
|
if bcn and bcn.name == "ignore" then
|
||||||
|
self.object:remove()
|
||||||
|
return
|
||||||
|
end
|
||||||
local bcd = bcn and core.registered_nodes[bcn.name]
|
local bcd = bcn and core.registered_nodes[bcn.name]
|
||||||
if bcn and
|
if bcn and
|
||||||
(not bcd or bcd.walkable or
|
(not bcd or bcd.walkable or
|
||||||
@ -93,7 +98,7 @@ core.register_entity(":__builtin:falling_node", {
|
|||||||
core.remove_node(np)
|
core.remove_node(np)
|
||||||
if nd and nd.buildable_to == false then
|
if nd and nd.buildable_to == false then
|
||||||
-- Add dropped items
|
-- Add dropped items
|
||||||
local drops = core.get_node_drops(n2.name, "")
|
local drops = core.get_node_drops(n2, "")
|
||||||
for _, dropped_item in pairs(drops) do
|
for _, dropped_item in pairs(drops) do
|
||||||
core.add_item(np, dropped_item)
|
core.add_item(np, dropped_item)
|
||||||
end
|
end
|
||||||
@ -145,9 +150,9 @@ function core.spawn_falling_node(pos)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function drop_attached_node(p)
|
local function drop_attached_node(p)
|
||||||
local nn = core.get_node(p).name
|
local n = core.get_node(p)
|
||||||
core.remove_node(p)
|
core.remove_node(p)
|
||||||
for _, item in pairs(core.get_node_drops(nn, "")) do
|
for _, item in pairs(core.get_node_drops(n, "")) do
|
||||||
local pos = {
|
local pos = {
|
||||||
x = p.x + math.random()/2 - 0.25,
|
x = p.x + math.random()/2 - 0.25,
|
||||||
y = p.y + math.random()/2 - 0.25,
|
y = p.y + math.random()/2 - 0.25,
|
||||||
|
@ -155,11 +155,45 @@ function core.yaw_to_dir(yaw)
|
|||||||
return {x = -math.sin(yaw), y = 0, z = math.cos(yaw)}
|
return {x = -math.sin(yaw), y = 0, z = math.cos(yaw)}
|
||||||
end
|
end
|
||||||
|
|
||||||
function core.get_node_drops(nodename, toolname)
|
function core.is_colored_paramtype(ptype)
|
||||||
|
return (ptype == "color") or (ptype == "colorfacedir") or
|
||||||
|
(ptype == "colorwallmounted")
|
||||||
|
end
|
||||||
|
|
||||||
|
function core.strip_param2_color(param2, paramtype2)
|
||||||
|
if not core.is_colored_paramtype(paramtype2) then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
if paramtype2 == "colorfacedir" then
|
||||||
|
param2 = math.floor(param2 / 32) * 32
|
||||||
|
elseif paramtype2 == "colorwallmounted" then
|
||||||
|
param2 = math.floor(param2 / 8) * 8
|
||||||
|
end
|
||||||
|
-- paramtype2 == "color" requires no modification.
|
||||||
|
return param2
|
||||||
|
end
|
||||||
|
|
||||||
|
function core.get_node_drops(node, toolname)
|
||||||
|
-- Compatibility, if node is string
|
||||||
|
local nodename = node
|
||||||
|
local param2 = 0
|
||||||
|
-- New format, if node is table
|
||||||
|
if (type(node) == "table") then
|
||||||
|
nodename = node.name
|
||||||
|
param2 = node.param2
|
||||||
|
end
|
||||||
local def = core.registered_nodes[nodename]
|
local def = core.registered_nodes[nodename]
|
||||||
local drop = def and def.drop
|
local drop = def and def.drop
|
||||||
|
local ptype = def and def.paramtype2
|
||||||
|
-- get color, if there is color (otherwise nil)
|
||||||
|
local palette_index = core.strip_param2_color(param2, ptype)
|
||||||
if drop == nil then
|
if drop == nil then
|
||||||
-- default drop
|
-- default drop
|
||||||
|
if palette_index then
|
||||||
|
local stack = ItemStack(nodename)
|
||||||
|
stack:get_meta():set_int("palette_index", palette_index)
|
||||||
|
return {stack:to_string()}
|
||||||
|
end
|
||||||
return {nodename}
|
return {nodename}
|
||||||
elseif type(drop) == "string" then
|
elseif type(drop) == "string" then
|
||||||
-- itemstring drop
|
-- itemstring drop
|
||||||
@ -181,6 +215,8 @@ function core.get_node_drops(nodename, toolname)
|
|||||||
end
|
end
|
||||||
if item.tools ~= nil then
|
if item.tools ~= nil then
|
||||||
good_tool = false
|
good_tool = false
|
||||||
|
end
|
||||||
|
if item.tools ~= nil and toolname then
|
||||||
for _, tool in ipairs(item.tools) do
|
for _, tool in ipairs(item.tools) do
|
||||||
if tool:sub(1, 1) == '~' then
|
if tool:sub(1, 1) == '~' then
|
||||||
good_tool = toolname:find(tool:sub(2)) ~= nil
|
good_tool = toolname:find(tool:sub(2)) ~= nil
|
||||||
@ -195,6 +231,12 @@ function core.get_node_drops(nodename, toolname)
|
|||||||
if good_rarity and good_tool then
|
if good_rarity and good_tool then
|
||||||
got_count = got_count + 1
|
got_count = got_count + 1
|
||||||
for _, add_item in ipairs(item.items) do
|
for _, add_item in ipairs(item.items) do
|
||||||
|
-- add color, if necessary
|
||||||
|
if item.inherit_color and palette_index then
|
||||||
|
local stack = ItemStack(add_item)
|
||||||
|
stack:get_meta():set_int("palette_index", palette_index)
|
||||||
|
add_item = stack:to_string()
|
||||||
|
end
|
||||||
got_items[#got_items+1] = add_item
|
got_items[#got_items+1] = add_item
|
||||||
end
|
end
|
||||||
if drop.max_items ~= nil and got_count == drop.max_items then
|
if drop.max_items ~= nil and got_count == drop.max_items then
|
||||||
@ -205,7 +247,22 @@ function core.get_node_drops(nodename, toolname)
|
|||||||
return got_items
|
return got_items
|
||||||
end
|
end
|
||||||
|
|
||||||
function core.item_place_node(itemstack, placer, pointed_thing, param2)
|
local function user_name(user)
|
||||||
|
return user and user:get_player_name() or ""
|
||||||
|
end
|
||||||
|
|
||||||
|
local function is_protected(pos, name)
|
||||||
|
return core.is_protected(pos, name) and
|
||||||
|
not minetest.check_player_privs(name, "protection_bypass")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Returns a logging function. For empty names, does not log.
|
||||||
|
local function make_log(name)
|
||||||
|
return name ~= "" and core.log or function() end
|
||||||
|
end
|
||||||
|
|
||||||
|
function core.item_place_node(itemstack, placer, pointed_thing, param2,
|
||||||
|
prevent_after_place)
|
||||||
local def = itemstack:get_definition()
|
local def = itemstack:get_definition()
|
||||||
if def.type ~= "node" or pointed_thing.type ~= "node" then
|
if def.type ~= "node" or pointed_thing.type ~= "node" then
|
||||||
return itemstack, false
|
return itemstack, false
|
||||||
@ -215,10 +272,11 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2)
|
|||||||
local oldnode_under = core.get_node_or_nil(under)
|
local oldnode_under = core.get_node_or_nil(under)
|
||||||
local above = pointed_thing.above
|
local above = pointed_thing.above
|
||||||
local oldnode_above = core.get_node_or_nil(above)
|
local oldnode_above = core.get_node_or_nil(above)
|
||||||
local playername = placer:get_player_name()
|
local playername = user_name(placer)
|
||||||
|
local log = make_log(playername)
|
||||||
|
|
||||||
if not oldnode_under or not oldnode_above then
|
if not oldnode_under or not oldnode_above then
|
||||||
core.log("info", playername .. " tried to place"
|
log("info", playername .. " tried to place"
|
||||||
.. " node in unloaded position " .. core.pos_to_string(above))
|
.. " node in unloaded position " .. core.pos_to_string(above))
|
||||||
return itemstack, false
|
return itemstack, false
|
||||||
end
|
end
|
||||||
@ -229,7 +287,7 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2)
|
|||||||
olddef_above = olddef_above or core.nodedef_default
|
olddef_above = olddef_above or core.nodedef_default
|
||||||
|
|
||||||
if not olddef_above.buildable_to and not olddef_under.buildable_to then
|
if not olddef_above.buildable_to and not olddef_under.buildable_to then
|
||||||
core.log("info", playername .. " tried to place"
|
log("info", playername .. " tried to place"
|
||||||
.. " node in invalid position " .. core.pos_to_string(above)
|
.. " node in invalid position " .. core.pos_to_string(above)
|
||||||
.. ", replacing " .. oldnode_above.name)
|
.. ", replacing " .. oldnode_above.name)
|
||||||
return itemstack, false
|
return itemstack, false
|
||||||
@ -240,13 +298,12 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2)
|
|||||||
|
|
||||||
-- If node under is buildable_to, place into it instead (eg. snow)
|
-- If node under is buildable_to, place into it instead (eg. snow)
|
||||||
if olddef_under.buildable_to then
|
if olddef_under.buildable_to then
|
||||||
core.log("info", "node under is buildable to")
|
log("info", "node under is buildable to")
|
||||||
place_to = {x = under.x, y = under.y, z = under.z}
|
place_to = {x = under.x, y = under.y, z = under.z}
|
||||||
end
|
end
|
||||||
|
|
||||||
if core.is_protected(place_to, playername) and
|
if is_protected(place_to, playername) then
|
||||||
not minetest.check_player_privs(placer, "protection_bypass") then
|
log("action", playername
|
||||||
core.log("action", playername
|
|
||||||
.. " tried to place " .. def.name
|
.. " tried to place " .. def.name
|
||||||
.. " at protected position "
|
.. " at protected position "
|
||||||
.. core.pos_to_string(place_to))
|
.. core.pos_to_string(place_to))
|
||||||
@ -254,11 +311,11 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2)
|
|||||||
return itemstack
|
return itemstack
|
||||||
end
|
end
|
||||||
|
|
||||||
core.log("action", playername .. " places node "
|
log("action", playername .. " places node "
|
||||||
.. def.name .. " at " .. core.pos_to_string(place_to))
|
.. def.name .. " at " .. core.pos_to_string(place_to))
|
||||||
|
|
||||||
local oldnode = core.get_node(place_to)
|
local oldnode = core.get_node(place_to)
|
||||||
local newnode = {name = def.name, param1 = 0, param2 = param2}
|
local newnode = {name = def.name, param1 = 0, param2 = param2 or 0}
|
||||||
|
|
||||||
-- Calculate direction for wall mounted stuff like torches and signs
|
-- Calculate direction for wall mounted stuff like torches and signs
|
||||||
if def.place_param2 ~= nil then
|
if def.place_param2 ~= nil then
|
||||||
@ -274,7 +331,7 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2)
|
|||||||
-- Calculate the direction for furnaces and chests and stuff
|
-- Calculate the direction for furnaces and chests and stuff
|
||||||
elseif (def.paramtype2 == "facedir" or
|
elseif (def.paramtype2 == "facedir" or
|
||||||
def.paramtype2 == "colorfacedir") and not param2 then
|
def.paramtype2 == "colorfacedir") and not param2 then
|
||||||
local placer_pos = placer:getpos()
|
local placer_pos = placer and placer:getpos()
|
||||||
if placer_pos then
|
if placer_pos then
|
||||||
local dir = {
|
local dir = {
|
||||||
x = above.x - placer_pos.x,
|
x = above.x - placer_pos.x,
|
||||||
@ -282,14 +339,33 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2)
|
|||||||
z = above.z - placer_pos.z
|
z = above.z - placer_pos.z
|
||||||
}
|
}
|
||||||
newnode.param2 = core.dir_to_facedir(dir)
|
newnode.param2 = core.dir_to_facedir(dir)
|
||||||
core.log("action", "facedir: " .. newnode.param2)
|
log("action", "facedir: " .. newnode.param2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local metatable = itemstack:get_meta():to_table().fields
|
||||||
|
|
||||||
|
-- Transfer color information
|
||||||
|
if metatable.palette_index and not def.place_param2 then
|
||||||
|
local color_divisor = nil
|
||||||
|
if def.paramtype2 == "color" then
|
||||||
|
color_divisor = 1
|
||||||
|
elseif def.paramtype2 == "colorwallmounted" then
|
||||||
|
color_divisor = 8
|
||||||
|
elseif def.paramtype2 == "colorfacedir" then
|
||||||
|
color_divisor = 32
|
||||||
|
end
|
||||||
|
if color_divisor then
|
||||||
|
local color = math.floor(metatable.palette_index / color_divisor)
|
||||||
|
local other = newnode.param2 % color_divisor
|
||||||
|
newnode.param2 = color * color_divisor + other
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check if the node is attached and if it can be placed there
|
-- Check if the node is attached and if it can be placed there
|
||||||
if core.get_item_group(def.name, "attached_node") ~= 0 and
|
if core.get_item_group(def.name, "attached_node") ~= 0 and
|
||||||
not builtin_shared.check_attached_node(place_to, newnode) then
|
not builtin_shared.check_attached_node(place_to, newnode) then
|
||||||
core.log("action", "attached node " .. def.name ..
|
log("action", "attached node " .. def.name ..
|
||||||
" can not be placed at " .. core.pos_to_string(place_to))
|
" can not be placed at " .. core.pos_to_string(place_to))
|
||||||
return itemstack, false
|
return itemstack, false
|
||||||
end
|
end
|
||||||
@ -300,7 +376,7 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2)
|
|||||||
local take_item = true
|
local take_item = true
|
||||||
|
|
||||||
-- Run callback
|
-- Run callback
|
||||||
if def.after_place_node then
|
if def.after_place_node and not prevent_after_place then
|
||||||
-- Deepcopy place_to and pointed_thing because callback can modify it
|
-- Deepcopy place_to and pointed_thing because callback can modify it
|
||||||
local place_to_copy = {x=place_to.x, y=place_to.y, z=place_to.z}
|
local place_to_copy = {x=place_to.x, y=place_to.y, z=place_to.z}
|
||||||
local pointed_thing_copy = copy_pointed_thing(pointed_thing)
|
local pointed_thing_copy = copy_pointed_thing(pointed_thing)
|
||||||
@ -360,29 +436,28 @@ function core.item_secondary_use(itemstack, placer)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function core.item_drop(itemstack, dropper, pos)
|
function core.item_drop(itemstack, dropper, pos)
|
||||||
if dropper and dropper:is_player() then
|
local dropper_is_player = dropper and dropper:is_player()
|
||||||
local v = dropper:get_look_dir()
|
local p = table.copy(pos)
|
||||||
local p = {x=pos.x, y=pos.y+1.2, z=pos.z}
|
local cnt = itemstack:get_count()
|
||||||
local cs = itemstack:get_count()
|
if dropper_is_player then
|
||||||
|
p.y = p.y + 1.2
|
||||||
if dropper:get_player_control().sneak then
|
if dropper:get_player_control().sneak then
|
||||||
cs = 1
|
cnt = 1
|
||||||
end
|
end
|
||||||
local item = itemstack:take_item(cs)
|
end
|
||||||
|
local item = itemstack:take_item(cnt)
|
||||||
local obj = core.add_item(p, item)
|
local obj = core.add_item(p, item)
|
||||||
if obj then
|
if obj then
|
||||||
v.x = v.x*2
|
if dropper_is_player then
|
||||||
v.y = v.y*2 + 2
|
local dir = dropper:get_look_dir()
|
||||||
v.z = v.z*2
|
dir.x = dir.x * 2.9
|
||||||
obj:setvelocity(v)
|
dir.y = dir.y * 2.9 + 2
|
||||||
|
dir.z = dir.z * 2.9
|
||||||
|
obj:set_velocity(dir)
|
||||||
obj:get_luaentity().dropped_by = dropper:get_player_name()
|
obj:get_luaentity().dropped_by = dropper:get_player_name()
|
||||||
return itemstack
|
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
|
||||||
if core.add_item(pos, itemstack) then
|
|
||||||
return itemstack
|
return itemstack
|
||||||
end
|
end
|
||||||
end
|
|
||||||
-- If we reach this, adding the object to the
|
-- If we reach this, adding the object to the
|
||||||
-- environment failed
|
-- environment failed
|
||||||
end
|
end
|
||||||
@ -402,7 +477,8 @@ function core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed
|
|||||||
itemstack:add_item(replace_with_item)
|
itemstack:add_item(replace_with_item)
|
||||||
else
|
else
|
||||||
local inv = user:get_inventory()
|
local inv = user:get_inventory()
|
||||||
if inv:room_for_item("main", {name=replace_with_item}) then
|
-- Check if inv is null, since non-players don't have one
|
||||||
|
if inv and inv:room_for_item("main", {name=replace_with_item}) then
|
||||||
inv:add_item("main", replace_with_item)
|
inv:add_item("main", replace_with_item)
|
||||||
else
|
else
|
||||||
local pos = user:getpos()
|
local pos = user:getpos()
|
||||||
@ -417,9 +493,11 @@ end
|
|||||||
|
|
||||||
function core.item_eat(hp_change, replace_with_item)
|
function core.item_eat(hp_change, replace_with_item)
|
||||||
return function(itemstack, user, pointed_thing) -- closure
|
return function(itemstack, user, pointed_thing) -- closure
|
||||||
|
if user then
|
||||||
return core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing)
|
return core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function core.node_punch(pos, node, puncher, pointed_thing)
|
function core.node_punch(pos, node, puncher, pointed_thing)
|
||||||
-- Run script hook
|
-- Run script hook
|
||||||
@ -434,10 +512,21 @@ end
|
|||||||
|
|
||||||
function core.handle_node_drops(pos, drops, digger)
|
function core.handle_node_drops(pos, drops, digger)
|
||||||
-- Add dropped items to object's inventory
|
-- Add dropped items to object's inventory
|
||||||
if digger:get_inventory() then
|
local inv = digger and digger:get_inventory()
|
||||||
local _, dropped_item
|
local give_item
|
||||||
for _, dropped_item in ipairs(drops) do
|
if inv then
|
||||||
local left = digger:get_inventory():add_item("main", dropped_item)
|
give_item = function(item)
|
||||||
|
return inv:add_item("main", item)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
give_item = function(item)
|
||||||
|
-- itemstring to ItemStack for left:is_empty()
|
||||||
|
return ItemStack(item)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, dropped_item in pairs(drops) do
|
||||||
|
local left = give_item(dropped_item)
|
||||||
if not left:is_empty() then
|
if not left:is_empty() then
|
||||||
local p = {
|
local p = {
|
||||||
x = pos.x + math.random()/2-0.25,
|
x = pos.x + math.random()/2-0.25,
|
||||||
@ -448,34 +537,35 @@ function core.handle_node_drops(pos, drops, digger)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
function core.node_dig(pos, node, digger)
|
function core.node_dig(pos, node, digger)
|
||||||
|
local diggername = user_name(digger)
|
||||||
|
local log = make_log(diggername)
|
||||||
local def = core.registered_nodes[node.name]
|
local def = core.registered_nodes[node.name]
|
||||||
if def and (not def.diggable or
|
if def and (not def.diggable or
|
||||||
(def.can_dig and not def.can_dig(pos, digger))) then
|
(def.can_dig and not def.can_dig(pos, digger))) then
|
||||||
core.log("info", digger:get_player_name() .. " tried to dig "
|
log("info", diggername .. " tried to dig "
|
||||||
.. node.name .. " which is not diggable "
|
.. node.name .. " which is not diggable "
|
||||||
.. core.pos_to_string(pos))
|
.. core.pos_to_string(pos))
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if core.is_protected(pos, digger:get_player_name()) and
|
if is_protected(pos, diggername) then
|
||||||
not minetest.check_player_privs(digger, "protection_bypass") then
|
log("action", diggername
|
||||||
core.log("action", digger:get_player_name()
|
|
||||||
.. " tried to dig " .. node.name
|
.. " tried to dig " .. node.name
|
||||||
.. " at protected position "
|
.. " at protected position "
|
||||||
.. core.pos_to_string(pos))
|
.. core.pos_to_string(pos))
|
||||||
core.record_protection_violation(pos, digger:get_player_name())
|
core.record_protection_violation(pos, diggername)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
core.log('action', digger:get_player_name() .. " digs "
|
log('action', diggername .. " digs "
|
||||||
.. node.name .. " at " .. core.pos_to_string(pos))
|
.. node.name .. " at " .. core.pos_to_string(pos))
|
||||||
|
|
||||||
local wielded = digger:get_wielded_item()
|
local wielded = digger and digger:get_wielded_item()
|
||||||
local drops = core.get_node_drops(node.name, wielded:get_name())
|
local drops = core.get_node_drops(node, wielded and wielded:get_name())
|
||||||
|
|
||||||
|
if wielded then
|
||||||
local wdef = wielded:get_definition()
|
local wdef = wielded:get_definition()
|
||||||
local tp = wielded:get_tool_capabilities()
|
local tp = wielded:get_tool_capabilities()
|
||||||
local dp = core.get_dig_params(def and def.groups, tp)
|
local dp = core.get_dig_params(def and def.groups, tp)
|
||||||
@ -491,6 +581,7 @@ function core.node_dig(pos, node, digger)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
digger:set_wielded_item(wielded)
|
digger:set_wielded_item(wielded)
|
||||||
|
end
|
||||||
|
|
||||||
-- Handle drops
|
-- Handle drops
|
||||||
core.handle_node_drops(pos, drops, digger)
|
core.handle_node_drops(pos, drops, digger)
|
||||||
|
@ -174,19 +174,18 @@ core.register_entity(":__builtin:item", {
|
|||||||
local p = self.object:getpos()
|
local p = self.object:getpos()
|
||||||
p.y = p.y - 0.5
|
p.y = p.y - 0.5
|
||||||
local node = core.get_node_or_nil(p)
|
local node = core.get_node_or_nil(p)
|
||||||
local in_unloaded = (node == nil)
|
-- Delete in 'ignore' nodes
|
||||||
if in_unloaded then
|
if node and node.name == "ignore" then
|
||||||
-- Don't infinetly fall into unloaded map
|
self.itemstring = ""
|
||||||
self.object:setvelocity({x = 0, y = 0, z = 0})
|
self.object:remove()
|
||||||
self.object:setacceleration({x = 0, y = 0, z = 0})
|
|
||||||
self.physical_state = false
|
|
||||||
self.object:set_properties({physical = false})
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local nn = node.name
|
|
||||||
-- If node is not registered or node is walkably solid and resting on nodebox
|
-- If node is nil (unloaded area), or node is not registered, or node is
|
||||||
|
-- walkably solid and item is resting on nodebox
|
||||||
local v = self.object:getvelocity()
|
local v = self.object:getvelocity()
|
||||||
if not core.registered_nodes[nn] or core.registered_nodes[nn].walkable and v.y == 0 then
|
if not node or not core.registered_nodes[node.name] or
|
||||||
|
core.registered_nodes[node.name].walkable and v.y == 0 then
|
||||||
if self.physical_state then
|
if self.physical_state then
|
||||||
local own_stack = ItemStack(self.object:get_luaentity().itemstring)
|
local own_stack = ItemStack(self.object:get_luaentity().itemstring)
|
||||||
-- Merge with close entities of the same item
|
-- Merge with close entities of the same item
|
||||||
|
@ -5,12 +5,11 @@
|
|||||||
--
|
--
|
||||||
|
|
||||||
function core.check_player_privs(name, ...)
|
function core.check_player_privs(name, ...)
|
||||||
local arg_type = type(name)
|
if core.is_player(name) then
|
||||||
if (arg_type == "userdata" or arg_type == "table") and
|
|
||||||
name.get_player_name then -- If it quacks like a Player...
|
|
||||||
name = name:get_player_name()
|
name = name:get_player_name()
|
||||||
elseif arg_type ~= "string" then
|
elseif type(name) ~= "string" then
|
||||||
error("Invalid core.check_player_privs argument type: " .. arg_type, 2)
|
error("core.check_player_privs expects a player or playername as " ..
|
||||||
|
"argument.", 2)
|
||||||
end
|
end
|
||||||
|
|
||||||
local requested_privs = {...}
|
local requested_privs = {...}
|
||||||
@ -70,6 +69,16 @@ function core.get_connected_players()
|
|||||||
return temp_table
|
return temp_table
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function core.is_player(player)
|
||||||
|
-- a table being a player is also supported because it quacks sufficiently
|
||||||
|
-- like a player if it has the is_player function
|
||||||
|
local t = type(player)
|
||||||
|
return (t == "userdata" or t == "table") and
|
||||||
|
type(player.is_player) == "function" and player:is_player()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
function minetest.player_exists(name)
|
function minetest.player_exists(name)
|
||||||
return minetest.get_auth_handler().get_auth(name) ~= nil
|
return minetest.get_auth_handler().get_auth(name) ~= nil
|
||||||
end
|
end
|
||||||
|
@ -116,6 +116,8 @@ function core.register_item(name, itemdef)
|
|||||||
end
|
end
|
||||||
itemdef.name = name
|
itemdef.name = name
|
||||||
|
|
||||||
|
local is_overriding = core.registered_items[name]
|
||||||
|
|
||||||
-- Apply defaults and add to registered_* table
|
-- Apply defaults and add to registered_* table
|
||||||
if itemdef.type == "node" then
|
if itemdef.type == "node" then
|
||||||
-- Use the nodebox as selection box if it's not set manually
|
-- Use the nodebox as selection box if it's not set manually
|
||||||
@ -177,7 +179,13 @@ function core.register_item(name, itemdef)
|
|||||||
--core.log("Registering item: " .. itemdef.name)
|
--core.log("Registering item: " .. itemdef.name)
|
||||||
core.registered_items[itemdef.name] = itemdef
|
core.registered_items[itemdef.name] = itemdef
|
||||||
core.registered_aliases[itemdef.name] = nil
|
core.registered_aliases[itemdef.name] = nil
|
||||||
|
|
||||||
|
-- Used to allow builtin to register ignore to registered_items
|
||||||
|
if name ~= "ignore" then
|
||||||
register_item_raw(itemdef)
|
register_item_raw(itemdef)
|
||||||
|
elseif is_overriding then
|
||||||
|
core.log("warning", "Attempted redefinition of \"ignore\"")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function core.unregister_item(name)
|
function core.unregister_item(name)
|
||||||
|
@ -21,7 +21,6 @@ if core.print then
|
|||||||
core.print = nil -- don't pollute our namespace
|
core.print = nil -- don't pollute our namespace
|
||||||
end
|
end
|
||||||
math.randomseed(os.time())
|
math.randomseed(os.time())
|
||||||
os.setlocale("C", "numeric")
|
|
||||||
minetest = core
|
minetest = core
|
||||||
|
|
||||||
-- Load other files
|
-- Load other files
|
||||||
@ -47,7 +46,6 @@ elseif INIT == "mainmenu" then
|
|||||||
elseif INIT == "async" then
|
elseif INIT == "async" then
|
||||||
dofile(asyncpath .. "init.lua")
|
dofile(asyncpath .. "init.lua")
|
||||||
elseif INIT == "client" then
|
elseif INIT == "client" then
|
||||||
os.setlocale = nil
|
|
||||||
dofile(clientpath .. "init.lua")
|
dofile(clientpath .. "init.lua")
|
||||||
else
|
else
|
||||||
error(("Unrecognized builtin initialization type %s!"):format(tostring(INIT)))
|
error(("Unrecognized builtin initialization type %s!"):format(tostring(INIT)))
|
||||||
|
@ -250,7 +250,7 @@ end
|
|||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
function text2textlist(xpos, ypos, width, height, tl_name, textlen, text, transparency)
|
function text2textlist(xpos, ypos, width, height, tl_name, textlen, text, transparency)
|
||||||
local textlines = core.wrap_text(text, textlen)
|
local textlines = core.wrap_text(text, textlen, true)
|
||||||
local retval = "textlist[" .. xpos .. "," .. ypos .. ";" .. width ..
|
local retval = "textlist[" .. xpos .. "," .. ypos .. ";" .. width ..
|
||||||
"," .. height .. ";" .. tl_name .. ";"
|
"," .. height .. ";" .. tl_name .. ";"
|
||||||
|
|
||||||
|
@ -17,19 +17,17 @@
|
|||||||
|
|
||||||
|
|
||||||
local function delete_world_formspec(dialogdata)
|
local function delete_world_formspec(dialogdata)
|
||||||
|
|
||||||
local retval =
|
local retval =
|
||||||
"size[11.5,4.5,true]" ..
|
"size[10,2.5,true]" ..
|
||||||
"label[2,2;" ..
|
"label[0.5,0.5;" ..
|
||||||
fgettext("Delete World \"$1\"?", dialogdata.delete_name) .. "]" ..
|
fgettext("Delete World \"$1\"?", dialogdata.delete_name) .. "]" ..
|
||||||
"button[3.25,3.5;2.5,0.5;world_delete_confirm;" .. fgettext("Delete") .. "]" ..
|
"button[0.5,1.5;2.5,0.5;world_delete_confirm;" .. fgettext("Delete") .. "]" ..
|
||||||
"button[5.75,3.5;2.5,0.5;world_delete_cancel;" .. fgettext("Cancel") .. "]"
|
"button[7.0,1.5;2.5,0.5;world_delete_cancel;" .. fgettext("Cancel") .. "]"
|
||||||
return retval
|
return retval
|
||||||
end
|
end
|
||||||
|
|
||||||
local function delete_world_buttonhandler(this, fields)
|
local function delete_world_buttonhandler(this, fields)
|
||||||
if fields["world_delete_confirm"] then
|
if fields["world_delete_confirm"] then
|
||||||
|
|
||||||
if this.data.delete_index > 0 and
|
if this.data.delete_index > 0 and
|
||||||
this.data.delete_index <= #menudata.worldlist:get_raw_list() then
|
this.data.delete_index <= #menudata.worldlist:get_raw_list() then
|
||||||
core.delete_world(this.data.delete_index)
|
core.delete_world(this.data.delete_index)
|
||||||
@ -49,7 +47,6 @@ end
|
|||||||
|
|
||||||
|
|
||||||
function create_delete_world_dlg(name_to_del, index_to_del)
|
function create_delete_world_dlg(name_to_del, index_to_del)
|
||||||
|
|
||||||
assert(name_to_del ~= nil and type(name_to_del) == "string" and name_to_del ~= "")
|
assert(name_to_del ~= nil and type(name_to_del) == "string" and name_to_del ~= "")
|
||||||
assert(index_to_del ~= nil and type(index_to_del) == "number")
|
assert(index_to_del ~= nil and type(index_to_del) == "number")
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ local previous_contributors = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
local function buildCreditList(source)
|
local function buildCreditList(source)
|
||||||
ret = {}
|
local ret = {}
|
||||||
for i = 1, #source do
|
for i = 1, #source do
|
||||||
ret[i] = core.formspec_escape(source[i])
|
ret[i] = core.formspec_escape(source[i])
|
||||||
end
|
end
|
||||||
|
@ -75,7 +75,7 @@ local function get_formspec(tabview, name, tabdata)
|
|||||||
if error == nil then
|
if error == nil then
|
||||||
local descriptiontext = descriptionfile:read("*all")
|
local descriptiontext = descriptionfile:read("*all")
|
||||||
|
|
||||||
descriptionlines = core.wrap_text(descriptiontext, 42)
|
descriptionlines = core.wrap_text(descriptiontext, 42, true)
|
||||||
descriptionfile:close()
|
descriptionfile:close()
|
||||||
else
|
else
|
||||||
descriptionlines = {}
|
descriptionlines = {}
|
||||||
|
@ -176,7 +176,7 @@ end
|
|||||||
|
|
||||||
local function formspec(tabview, name, tabdata)
|
local function formspec(tabview, name, tabdata)
|
||||||
local tab_string =
|
local tab_string =
|
||||||
"box[0,0;3.5,4.5;#999999]" ..
|
"box[0,0;3.75,4.5;#999999]" ..
|
||||||
"checkbox[0.25,0;cb_smooth_lighting;" .. fgettext("Smooth Lighting") .. ";"
|
"checkbox[0.25,0;cb_smooth_lighting;" .. fgettext("Smooth Lighting") .. ";"
|
||||||
.. dump(core.settings:get_bool("smooth_lighting")) .. "]" ..
|
.. dump(core.settings:get_bool("smooth_lighting")) .. "]" ..
|
||||||
"checkbox[0.25,0.5;cb_particles;" .. fgettext("Particles") .. ";"
|
"checkbox[0.25,0.5;cb_particles;" .. fgettext("Particles") .. ";"
|
||||||
@ -187,38 +187,38 @@ local function formspec(tabview, name, tabdata)
|
|||||||
.. dump(core.settings:get_bool("opaque_water")) .. "]" ..
|
.. dump(core.settings:get_bool("opaque_water")) .. "]" ..
|
||||||
"checkbox[0.25,2.0;cb_connected_glass;" .. fgettext("Connected Glass") .. ";"
|
"checkbox[0.25,2.0;cb_connected_glass;" .. fgettext("Connected Glass") .. ";"
|
||||||
.. dump(core.settings:get_bool("connected_glass")) .. "]" ..
|
.. dump(core.settings:get_bool("connected_glass")) .. "]" ..
|
||||||
"dropdown[0.25,2.8;3.3;dd_node_highlighting;" .. dd_options.node_highlighting[1] .. ";"
|
"dropdown[0.25,2.8;3.5;dd_node_highlighting;" .. dd_options.node_highlighting[1] .. ";"
|
||||||
.. getSettingIndex.NodeHighlighting() .. "]" ..
|
.. getSettingIndex.NodeHighlighting() .. "]" ..
|
||||||
"dropdown[0.25,3.6;3.3;dd_leaves_style;" .. dd_options.leaves[1] .. ";"
|
"dropdown[0.25,3.6;3.5;dd_leaves_style;" .. dd_options.leaves[1] .. ";"
|
||||||
.. getSettingIndex.Leaves() .. "]" ..
|
.. getSettingIndex.Leaves() .. "]" ..
|
||||||
"box[3.75,0;3.75,4.45;#999999]" ..
|
"box[4,0;3.75,4.5;#999999]" ..
|
||||||
"label[3.85,0.1;" .. fgettext("Texturing:") .. "]" ..
|
"label[4.25,0.1;" .. fgettext("Texturing:") .. "]" ..
|
||||||
"dropdown[3.85,0.55;3.85;dd_filters;" .. dd_options.filters[1] .. ";"
|
"dropdown[4.25,0.55;3.5;dd_filters;" .. dd_options.filters[1] .. ";"
|
||||||
.. getSettingIndex.Filter() .. "]" ..
|
.. getSettingIndex.Filter() .. "]" ..
|
||||||
"dropdown[3.85,1.35;3.85;dd_mipmap;" .. dd_options.mipmap[1] .. ";"
|
"dropdown[4.25,1.35;3.5;dd_mipmap;" .. dd_options.mipmap[1] .. ";"
|
||||||
.. getSettingIndex.Mipmap() .. "]" ..
|
.. getSettingIndex.Mipmap() .. "]" ..
|
||||||
"label[3.85,2.15;" .. fgettext("Antialiasing:") .. "]" ..
|
"label[4.25,2.15;" .. fgettext("Antialiasing:") .. "]" ..
|
||||||
"dropdown[3.85,2.6;3.85;dd_antialiasing;" .. dd_options.antialiasing[1] .. ";"
|
"dropdown[4.25,2.6;3.5;dd_antialiasing;" .. dd_options.antialiasing[1] .. ";"
|
||||||
.. getSettingIndex.Antialiasing() .. "]" ..
|
.. getSettingIndex.Antialiasing() .. "]" ..
|
||||||
"label[3.85,3.45;" .. fgettext("Screen:") .. "]" ..
|
"label[4.25,3.45;" .. fgettext("Screen:") .. "]" ..
|
||||||
"checkbox[3.85,3.6;cb_autosave_screensize;" .. fgettext("Autosave screen size") .. ";"
|
"checkbox[4.25,3.6;cb_autosave_screensize;" .. fgettext("Autosave screen size") .. ";"
|
||||||
.. dump(core.settings:get_bool("autosave_screensize")) .. "]" ..
|
.. dump(core.settings:get_bool("autosave_screensize")) .. "]" ..
|
||||||
"box[7.75,0;4,4.4;#999999]" ..
|
"box[8,0;3.75,4.5;#999999]" ..
|
||||||
"checkbox[8,0;cb_shaders;" .. fgettext("Shaders") .. ";"
|
"checkbox[8.25,0;cb_shaders;" .. fgettext("Shaders") .. ";"
|
||||||
.. dump(core.settings:get_bool("enable_shaders")) .. "]"
|
.. dump(core.settings:get_bool("enable_shaders")) .. "]"
|
||||||
|
|
||||||
if PLATFORM == "Android" then
|
if PLATFORM == "Android" then
|
||||||
tab_string = tab_string ..
|
tab_string = tab_string ..
|
||||||
"button[8,4.75;3.75,0.5;btn_reset_singleplayer;"
|
"button[8,4.75;4.1,1;btn_reset_singleplayer;"
|
||||||
.. fgettext("Reset singleplayer world") .. "]"
|
.. fgettext("Reset singleplayer world") .. "]"
|
||||||
else
|
else
|
||||||
tab_string = tab_string ..
|
tab_string = tab_string ..
|
||||||
"button[8,4.85;3.75,0.5;btn_change_keys;"
|
"button[8,4.75;4,1;btn_change_keys;"
|
||||||
.. fgettext("Change keys") .. "]"
|
.. fgettext("Change keys") .. "]"
|
||||||
end
|
end
|
||||||
|
|
||||||
tab_string = tab_string ..
|
tab_string = tab_string ..
|
||||||
"button[0,4.85;3.75,0.5;btn_advanced_settings;"
|
"button[0,4.75;4,1;btn_advanced_settings;"
|
||||||
.. fgettext("Advanced Settings") .. "]"
|
.. fgettext("Advanced Settings") .. "]"
|
||||||
|
|
||||||
|
|
||||||
@ -231,19 +231,19 @@ local function formspec(tabview, name, tabdata)
|
|||||||
|
|
||||||
if core.settings:get_bool("enable_shaders") then
|
if core.settings:get_bool("enable_shaders") then
|
||||||
tab_string = tab_string ..
|
tab_string = tab_string ..
|
||||||
"checkbox[8,0.5;cb_bumpmapping;" .. fgettext("Bump Mapping") .. ";"
|
"checkbox[8.25,0.5;cb_bumpmapping;" .. fgettext("Bump Mapping") .. ";"
|
||||||
.. dump(core.settings:get_bool("enable_bumpmapping")) .. "]" ..
|
.. dump(core.settings:get_bool("enable_bumpmapping")) .. "]" ..
|
||||||
"checkbox[8,1;cb_tonemapping;" .. fgettext("Tone Mapping") .. ";"
|
"checkbox[8.25,1;cb_tonemapping;" .. fgettext("Tone Mapping") .. ";"
|
||||||
.. dump(core.settings:get_bool("tone_mapping")) .. "]" ..
|
.. dump(core.settings:get_bool("tone_mapping")) .. "]" ..
|
||||||
"checkbox[8,1.5;cb_generate_normalmaps;" .. fgettext("Normal Mapping") .. ";"
|
"checkbox[8.25,1.5;cb_generate_normalmaps;" .. fgettext("Normal Mapping") .. ";"
|
||||||
.. dump(core.settings:get_bool("generate_normalmaps")) .. "]" ..
|
.. dump(core.settings:get_bool("generate_normalmaps")) .. "]" ..
|
||||||
"checkbox[8,2;cb_parallax;" .. fgettext("Parallax Occlusion") .. ";"
|
"checkbox[8.25,2;cb_parallax;" .. fgettext("Parallax Occlusion") .. ";"
|
||||||
.. dump(core.settings:get_bool("enable_parallax_occlusion")) .. "]" ..
|
.. dump(core.settings:get_bool("enable_parallax_occlusion")) .. "]" ..
|
||||||
"checkbox[8,2.5;cb_waving_water;" .. fgettext("Waving Water") .. ";"
|
"checkbox[8.25,2.5;cb_waving_water;" .. fgettext("Waving Water") .. ";"
|
||||||
.. dump(core.settings:get_bool("enable_waving_water")) .. "]" ..
|
.. dump(core.settings:get_bool("enable_waving_water")) .. "]" ..
|
||||||
"checkbox[8,3;cb_waving_leaves;" .. fgettext("Waving Leaves") .. ";"
|
"checkbox[8.25,3;cb_waving_leaves;" .. fgettext("Waving Leaves") .. ";"
|
||||||
.. dump(core.settings:get_bool("enable_waving_leaves")) .. "]" ..
|
.. dump(core.settings:get_bool("enable_waving_leaves")) .. "]" ..
|
||||||
"checkbox[8,3.5;cb_waving_plants;" .. fgettext("Waving Plants") .. ";"
|
"checkbox[8.25,3.5;cb_waving_plants;" .. fgettext("Waving Plants") .. ";"
|
||||||
.. dump(core.settings:get_bool("enable_waving_plants")) .. "]"
|
.. dump(core.settings:get_bool("enable_waving_plants")) .. "]"
|
||||||
else
|
else
|
||||||
tab_string = tab_string ..
|
tab_string = tab_string ..
|
||||||
|
@ -133,7 +133,7 @@ local function instrument_register(func, func_name)
|
|||||||
return func(instrument {
|
return func(instrument {
|
||||||
func = callback,
|
func = callback,
|
||||||
func_name = register_name
|
func_name = register_name
|
||||||
}), ...
|
}, ...)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -166,10 +166,6 @@ keymap_cmd (Command key) key /
|
|||||||
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
|
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
|
||||||
keymap_cmd_local (Command key) key .
|
keymap_cmd_local (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.
|
# Key for toggling unlimited view range.
|
||||||
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
|
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
|
||||||
keymap_rangeselect (Range select key) key KEY_KEY_R
|
keymap_rangeselect (Range select key) key KEY_KEY_R
|
||||||
@ -476,6 +472,12 @@ pause_fps_max (FPS in pause menu) int 20
|
|||||||
# View distance in nodes.
|
# View distance in nodes.
|
||||||
viewing_range (Viewing range) int 100 20 4000
|
viewing_range (Viewing range) int 100 20 4000
|
||||||
|
|
||||||
|
# Camera near plane distance in nodes, between 0 and 0.5
|
||||||
|
# Most users will not need to change this.
|
||||||
|
# Increasing can reduce artifacting on weaker GPUs.
|
||||||
|
# 0.1 = Default, 0.25 = Good value for weaker tablets.
|
||||||
|
near_plane (Near plane) float 0.1 0 0.5
|
||||||
|
|
||||||
# Width component of the initial window size.
|
# Width component of the initial window size.
|
||||||
screenW (Screen width) int 800
|
screenW (Screen width) int 800
|
||||||
|
|
||||||
@ -721,10 +723,9 @@ server_announce (Announce server) bool false
|
|||||||
# If you want to announce your ipv6 address, use serverlist_url = v6.servers.minetest.net.
|
# If you want to announce your ipv6 address, use serverlist_url = v6.servers.minetest.net.
|
||||||
serverlist_url (Serverlist URL) string servers.minetest.net
|
serverlist_url (Serverlist URL) string servers.minetest.net
|
||||||
|
|
||||||
# Disable escape sequences, e.g. chat coloring.
|
# Remove color codes from incoming chat messages
|
||||||
# Use this if you want to run a server with pre-0.4.14 clients and you want to disable
|
# Use this to stop players from being able to use color in their messages
|
||||||
# the escape sequences generated by mods.
|
strip_color_codes (Strip color codes) bool false
|
||||||
disable_escape_sequences (Disable escape sequences) bool false
|
|
||||||
|
|
||||||
[*Network]
|
[*Network]
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
FIND_PATH(LUA_INCLUDE_DIR luajit.h
|
FIND_PATH(LUA_INCLUDE_DIR luajit.h
|
||||||
HINTS
|
HINTS
|
||||||
$ENV{LUA_DIR}
|
$ENV{LUA_DIR}
|
||||||
PATH_SUFFIXES include/luajit-2.0 include/luajit-5_1-2.0 include
|
PATH_SUFFIXES include/luajit-2.1 include/luajit-2.0 include/luajit-5_1-2.1 include/luajit-5_1-2.0 include
|
||||||
PATHS
|
PATHS
|
||||||
~/Library/Frameworks
|
~/Library/Frameworks
|
||||||
/Library/Frameworks
|
/Library/Frameworks
|
||||||
|
@ -628,6 +628,9 @@ Minetest namespace reference
|
|||||||
version entirely. To check for the presence of engine features, test
|
version entirely. To check for the presence of engine features, test
|
||||||
whether the functions exported by the wanted features exist. For example:
|
whether the functions exported by the wanted features exist. For example:
|
||||||
`if minetest.nodeupdate then ... end`.
|
`if minetest.nodeupdate then ... end`.
|
||||||
|
* `minetest.sha1(data, [raw])`: returns the sha1 hash of data
|
||||||
|
* `data`: string of data to hash
|
||||||
|
* `raw`: return raw bytes instead of hex digits, default: false
|
||||||
|
|
||||||
### Logging
|
### Logging
|
||||||
* `minetest.debug(...)`
|
* `minetest.debug(...)`
|
||||||
@ -1117,15 +1120,15 @@ The following functions provide escape sequences:
|
|||||||
`minetest.get_color_escape_sequence(color) ..
|
`minetest.get_color_escape_sequence(color) ..
|
||||||
message ..
|
message ..
|
||||||
minetest.get_color_escape_sequence("#ffffff")`
|
minetest.get_color_escape_sequence("#ffffff")`
|
||||||
* `color.get_background_escape_sequence(color)`
|
* `minetest.get_background_escape_sequence(color)`
|
||||||
* `color` is a [ColorString](#colorstring)
|
* `color` is a [ColorString](#colorstring)
|
||||||
* The escape sequence sets the background of the whole text element to
|
* The escape sequence sets the background of the whole text element to
|
||||||
`color`. Only defined for item descriptions and tooltips.
|
`color`. Only defined for item descriptions and tooltips.
|
||||||
* `color.strip_foreground_colors(str)`
|
* `minetest.strip_foreground_colors(str)`
|
||||||
* Removes foreground colors added by `get_color_escape_sequence`.
|
* Removes foreground colors added by `get_color_escape_sequence`.
|
||||||
* `color.strip_background_colors(str)`
|
* `minetest.strip_background_colors(str)`
|
||||||
* Removes background colors added by `get_background_escape_sequence`.
|
* Removes background colors added by `get_background_escape_sequence`.
|
||||||
* `color.strip_colors(str)`
|
* `minetest.strip_colors(str)`
|
||||||
* Removes all color escape sequences.
|
* Removes all color escape sequences.
|
||||||
|
|
||||||
`ColorString`
|
`ColorString`
|
||||||
|
282
doc/lua_api.txt
282
doc/lua_api.txt
@ -1,4 +1,4 @@
|
|||||||
Minetest Lua Modding API Reference 0.4.16
|
Minetest Lua Modding API Reference 0.4.17
|
||||||
=========================================
|
=========================================
|
||||||
* More information at <http://www.minetest.net/>
|
* More information at <http://www.minetest.net/>
|
||||||
* Developer Wiki: <http://dev.minetest.net/>
|
* Developer Wiki: <http://dev.minetest.net/>
|
||||||
@ -211,7 +211,8 @@ when registering it.
|
|||||||
|
|
||||||
The `:` prefix can also be used for maintaining backwards compatibility.
|
The `:` prefix can also be used for maintaining backwards compatibility.
|
||||||
|
|
||||||
### Aliases
|
Aliases
|
||||||
|
-------
|
||||||
Aliases can be added by using `minetest.register_alias(name, convert_to)` or
|
Aliases can be added by using `minetest.register_alias(name, convert_to)` or
|
||||||
`minetest.register_alias_force(name, convert_to)`.
|
`minetest.register_alias_force(name, convert_to)`.
|
||||||
|
|
||||||
@ -232,6 +233,75 @@ you have an item called `epiclylongmodname:stuff`, you could do
|
|||||||
|
|
||||||
and be able to use `/giveme stuff`.
|
and be able to use `/giveme stuff`.
|
||||||
|
|
||||||
|
Mapgen aliases
|
||||||
|
--------------
|
||||||
|
In a game, a certain number of these must be set to tell core mapgens which
|
||||||
|
of the game's nodes are to be used by the core mapgens. For example:
|
||||||
|
|
||||||
|
minetest.register_alias("mapgen_stone", "default:stone")
|
||||||
|
|
||||||
|
### Aliases needed for all mapgens except Mapgen v6
|
||||||
|
|
||||||
|
Base terrain:
|
||||||
|
|
||||||
|
"mapgen_stone"
|
||||||
|
"mapgen_water_source"
|
||||||
|
"mapgen_river_water_source"
|
||||||
|
|
||||||
|
Caves:
|
||||||
|
|
||||||
|
"mapgen_lava_source"
|
||||||
|
|
||||||
|
Dungeons:
|
||||||
|
|
||||||
|
Only needed for registered biomes where 'node_stone' is stone:
|
||||||
|
"mapgen_cobble"
|
||||||
|
"mapgen_stair_cobble"
|
||||||
|
"mapgen_mossycobble"
|
||||||
|
Only needed for registered biomes where 'node_stone' is desert stone:
|
||||||
|
"mapgen_desert_stone"
|
||||||
|
"mapgen_stair_desert_stone"
|
||||||
|
Only needed for registered biomes where 'node_stone' is sandstone:
|
||||||
|
"mapgen_sandstone"
|
||||||
|
"mapgen_sandstonebrick"
|
||||||
|
"mapgen_stair_sandstone_block"
|
||||||
|
|
||||||
|
### Aliases needed for Mapgen v6
|
||||||
|
|
||||||
|
Terrain and biomes:
|
||||||
|
|
||||||
|
"mapgen_stone"
|
||||||
|
"mapgen_water_source"
|
||||||
|
"mapgen_lava_source"
|
||||||
|
"mapgen_dirt"
|
||||||
|
"mapgen_dirt_with_grass"
|
||||||
|
"mapgen_sand"
|
||||||
|
"mapgen_gravel"
|
||||||
|
"mapgen_desert_stone"
|
||||||
|
"mapgen_desert_sand"
|
||||||
|
"mapgen_dirt_with_snow"
|
||||||
|
"mapgen_snowblock"
|
||||||
|
"mapgen_snow"
|
||||||
|
"mapgen_ice"
|
||||||
|
|
||||||
|
Flora:
|
||||||
|
|
||||||
|
"mapgen_tree"
|
||||||
|
"mapgen_leaves"
|
||||||
|
"mapgen_apple"
|
||||||
|
"mapgen_jungletree"
|
||||||
|
"mapgen_jungleleaves"
|
||||||
|
"mapgen_junglegrass"
|
||||||
|
"mapgen_pine_tree"
|
||||||
|
"mapgen_pine_needles"
|
||||||
|
|
||||||
|
Dungeons:
|
||||||
|
|
||||||
|
"mapgen_cobble"
|
||||||
|
"mapgen_stair_cobble"
|
||||||
|
"mapgen_mossycobble"
|
||||||
|
"mapgen_stair_desert_stone"
|
||||||
|
|
||||||
Textures
|
Textures
|
||||||
--------
|
--------
|
||||||
Mods should generally prefix their textures with `modname_`, e.g. given
|
Mods should generally prefix their textures with `modname_`, e.g. given
|
||||||
@ -531,9 +601,26 @@ for conversion.
|
|||||||
If the `ItemStack`'s metadata contains the `color` field, it will be
|
If the `ItemStack`'s metadata contains the `color` field, it will be
|
||||||
lost on placement, because nodes on the map can only use palettes.
|
lost on placement, because nodes on the map can only use palettes.
|
||||||
|
|
||||||
If the `ItemStack`'s metadata contains the `palette_index` field, you
|
If the `ItemStack`'s metadata contains the `palette_index` field, it is
|
||||||
currently must manually convert between it and the node's `param2` with
|
automatically transferred between node and item forms by the engine,
|
||||||
custom `on_place` and `on_dig` callbacks.
|
when a player digs or places a colored node.
|
||||||
|
You can disable this feature by setting the `drop` field of the node
|
||||||
|
to itself (without metadata).
|
||||||
|
To transfer the color to a special drop, you need a drop table.
|
||||||
|
Example:
|
||||||
|
|
||||||
|
minetest.register_node("mod:stone", {
|
||||||
|
description = "Stone",
|
||||||
|
tiles = {"default_stone.png"},
|
||||||
|
paramtype2 = "color",
|
||||||
|
palette = "palette.png",
|
||||||
|
drop = {
|
||||||
|
items = {
|
||||||
|
-- assume that mod:cobblestone also has the same palette
|
||||||
|
{items = {"mod:cobblestone"}, inherit_color = true },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
### Colored items in craft recipes
|
### Colored items in craft recipes
|
||||||
Craft recipes only support item strings, but fortunately item strings
|
Craft recipes only support item strings, but fortunately item strings
|
||||||
@ -792,6 +879,11 @@ node definition:
|
|||||||
0 = y+ 1 = z+ 2 = z- 3 = x+ 4 = x- 5 = y-
|
0 = y+ 1 = z+ 2 = z- 3 = x+ 4 = x- 5 = y-
|
||||||
facedir modulo 4 = rotation around that axis
|
facedir modulo 4 = rotation around that axis
|
||||||
paramtype2 == "leveled"
|
paramtype2 == "leveled"
|
||||||
|
^ Only valid for "nodebox" with type = "leveled".
|
||||||
|
The level of the top face of the nodebox is stored in param2.
|
||||||
|
The other faces are defined by 'fixed = {}' like 'type = "fixed"' nodeboxes.
|
||||||
|
The nodebox height is param2 / 64 nodes.
|
||||||
|
The maximum accepted value of param2 is 127.
|
||||||
paramtype2 == "degrotate"
|
paramtype2 == "degrotate"
|
||||||
^ The rotation of this node is stored in param2. Plants are rotated this way.
|
^ The rotation of this node is stored in param2. Plants are rotated this way.
|
||||||
Values range 0 - 179. The value stored in param2 is multiplied by two to
|
Values range 0 - 179. The value stored in param2 is multiplied by two to
|
||||||
@ -2060,15 +2152,15 @@ The following functions provide escape sequences:
|
|||||||
`minetest.get_color_escape_sequence(color) ..
|
`minetest.get_color_escape_sequence(color) ..
|
||||||
message ..
|
message ..
|
||||||
minetest.get_color_escape_sequence("#ffffff")`
|
minetest.get_color_escape_sequence("#ffffff")`
|
||||||
* `color.get_background_escape_sequence(color)`
|
* `minetest.get_background_escape_sequence(color)`
|
||||||
* `color` is a ColorString
|
* `color` is a ColorString
|
||||||
* The escape sequence sets the background of the whole text element to
|
* The escape sequence sets the background of the whole text element to
|
||||||
`color`. Only defined for item descriptions and tooltips.
|
`color`. Only defined for item descriptions and tooltips.
|
||||||
* `color.strip_foreground_colors(str)`
|
* `minetest.strip_foreground_colors(str)`
|
||||||
* Removes foreground colors added by `get_color_escape_sequence`.
|
* Removes foreground colors added by `get_color_escape_sequence`.
|
||||||
* `color.strip_background_colors(str)`
|
* `minetest.strip_background_colors(str)`
|
||||||
* Removes background colors added by `get_background_escape_sequence`.
|
* Removes background colors added by `get_background_escape_sequence`.
|
||||||
* `color.strip_colors(str)`
|
* `minetest.strip_colors(str)`
|
||||||
* Removes all color escape sequences.
|
* Removes all color escape sequences.
|
||||||
|
|
||||||
Spatial Vectors
|
Spatial Vectors
|
||||||
@ -2111,9 +2203,11 @@ Helper functions
|
|||||||
* e.g. `string:split("a,b", ",") == {"a","b"}`
|
* e.g. `string:split("a,b", ",") == {"a","b"}`
|
||||||
* `string:trim()`
|
* `string:trim()`
|
||||||
* e.g. `string.trim("\n \t\tfoo bar\t ") == "foo bar"`
|
* e.g. `string.trim("\n \t\tfoo bar\t ") == "foo bar"`
|
||||||
* `minetest.wrap_text(str, limit)`: returns a string
|
* `minetest.wrap_text(str, limit, [as_table])`: returns a string or table
|
||||||
* Adds newlines to the string to keep it within the specified character limit
|
* Adds newlines to the string to keep it within the specified character limit
|
||||||
|
Note that returned lines may be longer than the limit since it only splits at word borders.
|
||||||
* limit: Maximal amount of characters in one line
|
* limit: Maximal amount of characters in one line
|
||||||
|
* as_table: optional, if true return table of lines instead of string
|
||||||
* `minetest.pos_to_string({x=X,y=Y,z=Z}, decimal_places))`: returns string `"(X,Y,Z)"`
|
* `minetest.pos_to_string({x=X,y=Y,z=Z}, decimal_places))`: returns string `"(X,Y,Z)"`
|
||||||
* Convert position to a printable string
|
* Convert position to a printable string
|
||||||
Optional: 'decimal_places' will round the x, y and z of the pos to the given decimal place.
|
Optional: 'decimal_places' will round the x, y and z of the pos to the given decimal place.
|
||||||
@ -2181,7 +2275,7 @@ Helper functions
|
|||||||
max_jitter = 0.5, -- maximum packet time jitter
|
max_jitter = 0.5, -- maximum packet time jitter
|
||||||
avg_jitter = 0.03, -- average packet time jitter
|
avg_jitter = 0.03, -- average packet time jitter
|
||||||
connection_uptime = 200, -- seconds since client connected
|
connection_uptime = 200, -- seconds since client connected
|
||||||
prot_vers = 31, -- protocol version used by client
|
protocol_version = 32, -- protocol version used by client
|
||||||
-- following information is available on debug build only!!!
|
-- following information is available on debug build only!!!
|
||||||
-- DO NOT USE IN MODS
|
-- DO NOT USE IN MODS
|
||||||
--ser_vers = 26, -- serialization version used by client
|
--ser_vers = 26, -- serialization version used by client
|
||||||
@ -2199,6 +2293,10 @@ Helper functions
|
|||||||
* nil: return all entries,
|
* nil: return all entries,
|
||||||
* true: return only subdirectory names, or
|
* true: return only subdirectory names, or
|
||||||
* false: return only file names.
|
* false: return only file names.
|
||||||
|
* `minetest.safe_file_write(path, content)`: returns boolean indicating success
|
||||||
|
* Replaces contents of file at path with new contents in a safe (atomic) way.
|
||||||
|
Use this instead of below code when writing e.g. database files:
|
||||||
|
`local f = io.open(path, "wb"); f:write(content); f:close()`
|
||||||
* `minetest.get_version()`: returns a table containing components of the
|
* `minetest.get_version()`: returns a table containing components of the
|
||||||
engine version. Components:
|
engine version. Components:
|
||||||
* `project`: Name of the project, eg, "Minetest"
|
* `project`: Name of the project, eg, "Minetest"
|
||||||
@ -2210,6 +2308,9 @@ Helper functions
|
|||||||
version entirely. To check for the presence of engine features, test
|
version entirely. To check for the presence of engine features, test
|
||||||
whether the functions exported by the wanted features exist. For example:
|
whether the functions exported by the wanted features exist. For example:
|
||||||
`if minetest.nodeupdate then ... end`.
|
`if minetest.nodeupdate then ... end`.
|
||||||
|
* `minetest.sha1(data, [raw])`: returns the sha1 hash of data
|
||||||
|
* `data`: string of data to hash
|
||||||
|
* `raw`: return raw bytes instead of hex digits, default: false
|
||||||
|
|
||||||
### Logging
|
### Logging
|
||||||
* `minetest.debug(...)`
|
* `minetest.debug(...)`
|
||||||
@ -2229,6 +2330,8 @@ Call these functions only at load time!
|
|||||||
* `minetest.register_craftitem(name, item definition)`
|
* `minetest.register_craftitem(name, item definition)`
|
||||||
* `minetest.unregister_item(name)`
|
* `minetest.unregister_item(name)`
|
||||||
* `minetest.register_alias(name, convert_to)`
|
* `minetest.register_alias(name, convert_to)`
|
||||||
|
* Also use this to set the 'mapgen aliases' needed in a game for the core
|
||||||
|
* mapgens. See 'Mapgen aliases' section above.
|
||||||
* `minetest.register_alias_force(name, convert_to)`
|
* `minetest.register_alias_force(name, convert_to)`
|
||||||
* `minetest.register_craft(recipe)`
|
* `minetest.register_craft(recipe)`
|
||||||
* Check recipe table syntax for different types below.
|
* Check recipe table syntax for different types below.
|
||||||
@ -2263,6 +2366,7 @@ Call these functions only at load time!
|
|||||||
* `minetest.register_on_placenode(func(pos, newnode, placer, oldnode, itemstack, pointed_thing))`
|
* `minetest.register_on_placenode(func(pos, newnode, placer, oldnode, itemstack, pointed_thing))`
|
||||||
* Called when a node has been placed
|
* Called when a node has been placed
|
||||||
* If return `true` no item is taken from `itemstack`
|
* If return `true` no item is taken from `itemstack`
|
||||||
|
* `placer` may be any valid ObjectRef or nil.
|
||||||
* **Not recommended**; use `on_construct` or `after_place_node` in node definition
|
* **Not recommended**; use `on_construct` or `after_place_node` in node definition
|
||||||
whenever possible
|
whenever possible
|
||||||
* `minetest.register_on_dignode(func(pos, oldnode, digger))`
|
* `minetest.register_on_dignode(func(pos, oldnode, digger))`
|
||||||
@ -2356,8 +2460,9 @@ Call these functions only at load time!
|
|||||||
* `definition`: `{ description = "description text", give_to_singleplayer = boolean}`
|
* `definition`: `{ description = "description text", give_to_singleplayer = boolean}`
|
||||||
the default of `give_to_singleplayer` is true
|
the default of `give_to_singleplayer` is true
|
||||||
* To allow players with `basic_privs` to grant, see `basic_privs` minetest.conf setting.
|
* To allow players with `basic_privs` to grant, see `basic_privs` minetest.conf setting.
|
||||||
* `minetest.register_authentication_handler(handler)`
|
* `minetest.register_authentication_handler(authentication handler definition)`
|
||||||
* See `minetest.builtin_auth_handler` in `builtin.lua` for reference
|
* Registers an auth handler that overrides the builtin one
|
||||||
|
* This function can be called by a single mod once only.
|
||||||
|
|
||||||
### Setting-related
|
### Setting-related
|
||||||
* `minetest.settings`: Settings object containing all of the settings from the
|
* `minetest.settings`: Settings object containing all of the settings from the
|
||||||
@ -2366,37 +2471,44 @@ Call these functions only at load time!
|
|||||||
parses it as a position (in the format `(1,2,3)`). Returns a position or nil.
|
parses it as a position (in the format `(1,2,3)`). Returns a position or nil.
|
||||||
|
|
||||||
### Authentication
|
### Authentication
|
||||||
* `minetest.notify_authentication_modified(name)`
|
|
||||||
* Should be called by the authentication handler if privileges changes.
|
|
||||||
* To report everybody, set `name=nil`.
|
|
||||||
* `minetest.check_password_entry(name, entry, password)`
|
|
||||||
* Returns true if the "db entry" for a player with name matches given
|
|
||||||
* password, false otherwise.
|
|
||||||
* The "db entry" is the usually player-individual value that is derived
|
|
||||||
* from the player's chosen password and stored on the server in order to allow
|
|
||||||
* authentication whenever the player desires to log in.
|
|
||||||
* Only use this function for making it possible to log in via the password from
|
|
||||||
* via protocols like IRC, other uses for inside the game are frowned upon.
|
|
||||||
* `minetest.get_password_hash(name, raw_password)`
|
|
||||||
* Convert a name-password pair to a password hash that Minetest can use.
|
|
||||||
* The returned value alone is not a good basis for password checks based
|
|
||||||
* on comparing the password hash in the database with the password hash
|
|
||||||
* from the function, with an externally provided password, as the hash
|
|
||||||
* in the db might use the new SRP verifier format.
|
|
||||||
* For this purpose, use `minetest.check_password_entry` instead.
|
|
||||||
* `minetest.string_to_privs(str)`: returns `{priv1=true,...}`
|
* `minetest.string_to_privs(str)`: returns `{priv1=true,...}`
|
||||||
* `minetest.privs_to_string(privs)`: returns `"priv1,priv2,..."`
|
* `minetest.privs_to_string(privs)`: returns `"priv1,priv2,..."`
|
||||||
* Convert between two privilege representations
|
* Convert between two privilege representations
|
||||||
* `minetest.set_player_password(name, password_hash)`
|
|
||||||
* `minetest.set_player_privs(name, {priv1=true,...})`
|
|
||||||
* `minetest.get_player_privs(name) -> {priv1=true,...}`
|
* `minetest.get_player_privs(name) -> {priv1=true,...}`
|
||||||
* `minetest.auth_reload()`
|
|
||||||
* `minetest.check_player_privs(player_or_name, ...)`: returns `bool, missing_privs`
|
* `minetest.check_player_privs(player_or_name, ...)`: returns `bool, missing_privs`
|
||||||
* A quickhand for checking privileges.
|
* A quickhand for checking privileges.
|
||||||
* `player_or_name`: Either a Player object or the name of a player.
|
* `player_or_name`: Either a Player object or the name of a player.
|
||||||
* `...` is either a list of strings, e.g. `"priva", "privb"` or
|
* `...` is either a list of strings, e.g. `"priva", "privb"` or
|
||||||
a table, e.g. `{ priva = true, privb = true }`.
|
a table, e.g. `{ priva = true, privb = true }`.
|
||||||
* `minetest.get_player_ip(name)`: returns an IP address string
|
|
||||||
|
* `minetest.check_password_entry(name, entry, password)`
|
||||||
|
* Returns true if the "password entry" for a player with name matches given
|
||||||
|
password, false otherwise.
|
||||||
|
* The "password entry" is the password representation generated by the engine
|
||||||
|
as returned as part of a `get_auth()` call on the auth handler.
|
||||||
|
* Only use this function for making it possible to log in via password from
|
||||||
|
external protocols such as IRC, other uses are frowned upon.
|
||||||
|
* `minetest.get_password_hash(name, raw_password)`
|
||||||
|
* Convert a name-password pair to a password hash that Minetest can use.
|
||||||
|
* The returned value alone is not a good basis for password checks based
|
||||||
|
on comparing the password hash in the database with the password hash
|
||||||
|
from the function, with an externally provided password, as the hash
|
||||||
|
in the db might use the new SRP verifier format.
|
||||||
|
* For this purpose, use `minetest.check_password_entry` instead.
|
||||||
|
* `minetest.get_player_ip(name)`: returns an IP address string for the player `name`
|
||||||
|
* The player needs to be online for this to be successful.
|
||||||
|
|
||||||
|
* `minetest.get_auth_handler()`: Return the currently active auth handler
|
||||||
|
* See the `Authentication handler definition`
|
||||||
|
* Use this to e.g. get the authentication data for a player:
|
||||||
|
`local auth_data = minetest.get_auth_handler().get_auth(playername)`
|
||||||
|
* `minetest.notify_authentication_modified(name)`
|
||||||
|
* Must be called by the authentication handler for privilege changes.
|
||||||
|
* `name`: string; if omitted, all auth data should be considered modified
|
||||||
|
* `minetest.set_player_password(name, password_hash)`: Set password hash of player `name`
|
||||||
|
* `minetest.set_player_privs(name, {priv1=true,...})`: Set privileges of player `name`
|
||||||
|
* `minetest.auth_reload()`
|
||||||
|
* See `reload()` in authentication handler definition
|
||||||
|
|
||||||
`minetest.set_player_password`, `minetest_set_player_privs`, `minetest_get_player_privs`
|
`minetest.set_player_password`, `minetest_set_player_privs`, `minetest_get_player_privs`
|
||||||
and `minetest.auth_reload` call the authetification handler.
|
and `minetest.auth_reload` call the authetification handler.
|
||||||
@ -2462,12 +2574,15 @@ and `minetest.auth_reload` call the authetification handler.
|
|||||||
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
|
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
|
||||||
* `search_center` is an optional boolean (default: `false`)
|
* `search_center` is an optional boolean (default: `false`)
|
||||||
If true `pos` is also checked for the nodes
|
If true `pos` is also checked for the nodes
|
||||||
* `minetest.find_nodes_in_area(minp, maxp, nodenames)`: returns a list of positions
|
* `minetest.find_nodes_in_area(pos1, pos2, 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"`
|
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
|
||||||
* `minetest.find_nodes_in_area_under_air(minp, maxp, nodenames)`: returns a list of positions
|
* First return value: Table with all node positions
|
||||||
* returned positions are nodes with a node air above
|
* Second return value: Table with the count of each node with the node name as index
|
||||||
|
* Area volume is limited to 4,096,000 nodes
|
||||||
|
* `minetest.find_nodes_in_area_under_air(pos1, pos2, nodenames)`: returns a list of positions
|
||||||
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
|
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
|
||||||
|
* Return value: Table with all node positions with a node air above
|
||||||
|
* Area volume is limited to 4,096,000 nodes
|
||||||
* `minetest.get_perlin(noiseparams)`
|
* `minetest.get_perlin(noiseparams)`
|
||||||
* `minetest.get_perlin(seeddiff, octaves, persistence, scale)`
|
* `minetest.get_perlin(seeddiff, octaves, persistence, scale)`
|
||||||
* Return world-specific perlin noise (`int(worldseed)+seeddiff`)
|
* Return world-specific perlin noise (`int(worldseed)+seeddiff`)
|
||||||
@ -2676,6 +2791,13 @@ and `minetest.auth_reload` call the authetification handler.
|
|||||||
* Convert a vector into a yaw (angle)
|
* Convert a vector into a yaw (angle)
|
||||||
* `minetest.yaw_to_dir(yaw)`
|
* `minetest.yaw_to_dir(yaw)`
|
||||||
* Convert yaw (angle) to a vector
|
* Convert yaw (angle) to a vector
|
||||||
|
* `minetest.is_colored_paramtype(ptype)`
|
||||||
|
* Returns a boolean. Returns `true` if the given `paramtype2` contains color
|
||||||
|
information (`color`, `colorwallmounted` or `colorfacedir`).
|
||||||
|
* `minetest.strip_param2_color(param2, paramtype2)`
|
||||||
|
* Removes everything but the color information from the
|
||||||
|
given `param2` value.
|
||||||
|
* Returns `nil` if the given `paramtype2` does not contain color information
|
||||||
* `minetest.get_node_drops(nodename, toolname)`
|
* `minetest.get_node_drops(nodename, toolname)`
|
||||||
* Returns list of item names.
|
* Returns list of item names.
|
||||||
* **Note**: This will be removed or modified in a future version.
|
* **Note**: This will be removed or modified in a future version.
|
||||||
@ -2711,9 +2833,9 @@ and `minetest.auth_reload` call the authetification handler.
|
|||||||
* Example query for `"default:gold_ingot"` will return table:
|
* Example query for `"default:gold_ingot"` will return table:
|
||||||
|
|
||||||
{
|
{
|
||||||
[1]={type = "cooking", width = 3, output = "default:gold_ingot",
|
[1]={method = "cooking", width = 3, output = "default:gold_ingot",
|
||||||
items = {1 = "default:gold_lump"}},
|
items = {1 = "default:gold_lump"}},
|
||||||
[2]={type = "normal", width = 1, output = "default:gold_ingot 9",
|
[2]={method = "normal", width = 1, output = "default:gold_ingot 9",
|
||||||
items = {1 = "default:goldblock"}}
|
items = {1 = "default:goldblock"}}
|
||||||
}
|
}
|
||||||
* `minetest.handle_node_drops(pos, drops, digger)`
|
* `minetest.handle_node_drops(pos, drops, digger)`
|
||||||
@ -2735,9 +2857,11 @@ and `minetest.auth_reload` call the authetification handler.
|
|||||||
### Defaults for the `on_*` item definition functions
|
### Defaults for the `on_*` item definition functions
|
||||||
These functions return the leftover itemstack.
|
These functions return the leftover itemstack.
|
||||||
|
|
||||||
* `minetest.item_place_node(itemstack, placer, pointed_thing, param2)`
|
* `minetest.item_place_node(itemstack, placer, pointed_thing[, param2, prevent_after_place])`
|
||||||
* Place item as a node
|
* Place item as a node
|
||||||
* `param2` overrides `facedir` and wallmounted `param2`
|
* `param2` overrides `facedir` and wallmounted `param2`
|
||||||
|
* `prevent_after_place`: if set to `true`, `after_place_node` is not called
|
||||||
|
for the newly placed node to prevent a callback and placement loop
|
||||||
* returns `itemstack, success`
|
* returns `itemstack, success`
|
||||||
* `minetest.item_place_object(itemstack, placer, pointed_thing)`
|
* `minetest.item_place_object(itemstack, placer, pointed_thing)`
|
||||||
* Place item as-is
|
* Place item as-is
|
||||||
@ -2893,6 +3017,7 @@ These functions return the leftover itemstack.
|
|||||||
|
|
||||||
### Misc.
|
### Misc.
|
||||||
* `minetest.get_connected_players()`: returns list of `ObjectRefs`
|
* `minetest.get_connected_players()`: returns list of `ObjectRefs`
|
||||||
|
* `minetest.is_player(o)`: boolean, whether `o` is a player
|
||||||
* `minetest.player_exists(name)`: boolean, whether player exists (regardless of online status)
|
* `minetest.player_exists(name)`: boolean, whether player exists (regardless of online status)
|
||||||
* `minetest.hud_replace_builtin(name, hud_definition)`
|
* `minetest.hud_replace_builtin(name, hud_definition)`
|
||||||
* Replaces definition of a builtin hud element
|
* Replaces definition of a builtin hud element
|
||||||
@ -2960,6 +3085,7 @@ These functions return the leftover itemstack.
|
|||||||
* Returns true, if player `name` shouldn't be abled to dig at `pos` or do other
|
* 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.
|
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.
|
Returns false or nil, if the player is allowed to do such actions.
|
||||||
|
* `name` will be "" for non-players or unknown players.
|
||||||
* This function should be overridden by protection mods and should be used to
|
* This function should be overridden by protection mods and should be used to
|
||||||
check if a player can interact at a position.
|
check if a player can interact at a position.
|
||||||
* This function should call the old version of itself if the position is not
|
* This function should call the old version of itself if the position is not
|
||||||
@ -2976,25 +3102,29 @@ These functions return the leftover itemstack.
|
|||||||
* `minetest.record_protection_violation(pos, name)`
|
* `minetest.record_protection_violation(pos, name)`
|
||||||
* This function calls functions registered with
|
* This function calls functions registered with
|
||||||
`minetest.register_on_protection_violation`.
|
`minetest.register_on_protection_violation`.
|
||||||
* `minetest.rotate_and_place(itemstack, placer, pointed_thing, infinitestacks, orient_flags)`
|
* `minetest.rotate_and_place(itemstack, placer, pointed_thing[, infinitestacks,
|
||||||
|
orient_flags, prevent_after_place])`
|
||||||
* Attempt to predict the desired orientation of the facedir-capable node
|
* Attempt to predict the desired orientation of the facedir-capable node
|
||||||
defined by `itemstack`, and place it accordingly (on-wall, on the floor, or
|
defined by `itemstack`, and place it accordingly (on-wall, on the floor,
|
||||||
hanging from the ceiling). Stacks are handled normally if the `infinitestacks`
|
or hanging from the ceiling).
|
||||||
field is false or omitted (else, the itemstack is not changed). `orient_flags`
|
* `infinitestacks`: if `true`, the itemstack is not changed. Otherwise the
|
||||||
is an optional table containing extra tweaks to the placement code:
|
stacks are handled normally.
|
||||||
* `invert_wall`: if `true`, place wall-orientation on the ground and ground-
|
* `orient_flags`: Optional table containing extra tweaks to the placement code:
|
||||||
orientation on the wall.
|
* `invert_wall`: if `true`, place wall-orientation on the ground and
|
||||||
|
ground-orientation on the wall.
|
||||||
* `force_wall` : if `true`, always place the node in wall orientation.
|
* `force_wall` : if `true`, always place the node in wall orientation.
|
||||||
* `force_ceiling`: if `true`, always place on the ceiling.
|
* `force_ceiling`: if `true`, always place on the ceiling.
|
||||||
* `force_floor`: if `true`, always place the node on the floor.
|
* `force_floor`: if `true`, always place the node on the floor.
|
||||||
* `force_facedir`: if `true`, forcefully reset the facedir to north when placing on
|
* `force_facedir`: if `true`, forcefully reset the facedir to north
|
||||||
the floor or ceiling
|
when placing on the floor or ceiling.
|
||||||
* The first four options are mutually-exclusive; the last in the list takes
|
* The first four options are mutually-exclusive; the last in the list
|
||||||
precedence over the first.
|
takes precedence over the first.
|
||||||
|
* `prevent_after_place` is directly passed to `minetest.item_place_node`
|
||||||
|
* Returns the new itemstack after placement
|
||||||
* `minetest.rotate_node(itemstack, placer, pointed_thing)`
|
* `minetest.rotate_node(itemstack, placer, pointed_thing)`
|
||||||
* calls `rotate_and_place()` with infinitestacks set according to the state of
|
* calls `rotate_and_place()` with `infinitestacks` set according to the state
|
||||||
the creative mode setting, and checks for "sneak" to set the `invert_wall`
|
of the creative mode setting, checks for "sneak" to set the `invert_wall`
|
||||||
parameter.
|
parameter and `prevent_after_place` set to `true`.
|
||||||
|
|
||||||
* `minetest.forceload_block(pos[, transient])`
|
* `minetest.forceload_block(pos[, transient])`
|
||||||
* forceloads the position `pos`.
|
* forceloads the position `pos`.
|
||||||
@ -3150,7 +3280,7 @@ This is basically a reference to a C++ `ServerActiveObject`
|
|||||||
* `set_attach(parent, bone, position, rotation)`
|
* `set_attach(parent, bone, position, rotation)`
|
||||||
* `bone`: string
|
* `bone`: string
|
||||||
* `position`: `{x=num, y=num, z=num}` (relative)
|
* `position`: `{x=num, y=num, z=num}` (relative)
|
||||||
* `rotation`: `{x=num, y=num, z=num}`
|
* `rotation`: `{x=num, y=num, z=num}` = Rotation on each axis, in degrees
|
||||||
* `get_attach()`: returns parent, bone, position, rotation or nil if it isn't attached
|
* `get_attach()`: returns parent, bone, position, rotation or nil if it isn't attached
|
||||||
* `set_detach()`
|
* `set_detach()`
|
||||||
* `set_bone_position(bone, position, rotation)`
|
* `set_bone_position(bone, position, rotation)`
|
||||||
@ -3218,7 +3348,7 @@ This is basically a reference to a C++ `ServerActiveObject`
|
|||||||
* `11`: bubbles bar is not shown
|
* `11`: bubbles bar is not shown
|
||||||
* `set_attribute(attribute, value)`:
|
* `set_attribute(attribute, value)`:
|
||||||
* Sets an extra attribute with value on player.
|
* Sets an extra attribute with value on player.
|
||||||
* `value` must be a string.
|
* `value` must be a string, or a number which will be converted to a string.
|
||||||
* If `value` is `nil`, remove attribute from player.
|
* If `value` is `nil`, remove attribute from player.
|
||||||
* `get_attribute(attribute)`:
|
* `get_attribute(attribute)`:
|
||||||
* Returns value (a string) for extra attribute.
|
* Returns value (a string) for extra attribute.
|
||||||
@ -3322,8 +3452,9 @@ An `InvRef` is a reference to an inventory.
|
|||||||
* `add_item(listname, stack)`: add item somewhere in list, returns leftover `ItemStack`
|
* `add_item(listname, stack)`: add item somewhere in list, returns leftover `ItemStack`
|
||||||
* `room_for_item(listname, stack):` returns `true` if the stack of items
|
* `room_for_item(listname, stack):` returns `true` if the stack of items
|
||||||
can be fully added to the list
|
can be fully added to the list
|
||||||
* `contains_item(listname, stack)`: returns `true` if the stack of items
|
* `contains_item(listname, stack, [match_meta])`: returns `true` if
|
||||||
can be fully taken from the list
|
the stack of items can be fully taken from the list.
|
||||||
|
If `match_meta` is false, only the items' names are compared (default: `false`).
|
||||||
* `remove_item(listname, stack)`: take as many items as specified from the list,
|
* `remove_item(listname, stack)`: take as many items as specified from the list,
|
||||||
returns the items that were actually removed (as an `ItemStack`) -- note that
|
returns the items that were actually removed (as an `ItemStack`) -- note that
|
||||||
any item metadata is ignored, so attempting to remove a specific unique
|
any item metadata is ignored, so attempting to remove a specific unique
|
||||||
@ -4212,6 +4343,7 @@ Definition tables
|
|||||||
{
|
{
|
||||||
items = {"foo:bar", "baz:frob"}, -- Items to drop.
|
items = {"foo:bar", "baz:frob"}, -- Items to drop.
|
||||||
rarity = 1, -- Probability of dropping is 1 / rarity.
|
rarity = 1, -- Probability of dropping is 1 / rarity.
|
||||||
|
inherit_color = true, -- To inherit palette color from the node
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -4242,6 +4374,7 @@ Definition tables
|
|||||||
^ Called after constructing node when node was placed using
|
^ Called after constructing node when node was placed using
|
||||||
minetest.item_place_node / minetest.place_node
|
minetest.item_place_node / minetest.place_node
|
||||||
^ If return true no item is taken from itemstack
|
^ If return true no item is taken from itemstack
|
||||||
|
^ `placer` may be any valid ObjectRef or nil
|
||||||
^ default: nil ]]
|
^ default: nil ]]
|
||||||
after_dig_node = func(pos, oldnode, oldmetadata, digger), --[[
|
after_dig_node = func(pos, oldnode, oldmetadata, digger), --[[
|
||||||
^ oldmetadata is in table format
|
^ oldmetadata is in table format
|
||||||
@ -4257,9 +4390,11 @@ Definition tables
|
|||||||
^ By default: Calls minetest.register_on_punchnode callbacks ]]
|
^ By default: Calls minetest.register_on_punchnode callbacks ]]
|
||||||
on_rightclick = func(pos, node, clicker, itemstack, pointed_thing), --[[
|
on_rightclick = func(pos, node, clicker, itemstack, pointed_thing), --[[
|
||||||
^ default: nil
|
^ default: nil
|
||||||
^ if defined, itemstack will hold clicker's wielded item
|
^ itemstack will hold clicker's wielded item
|
||||||
^ Shall return the leftover itemstack
|
^ Shall return the leftover itemstack
|
||||||
^ Note: pointed_thing can be nil, if a mod calls this function ]]
|
^ Note: pointed_thing can be nil, if a mod calls this function
|
||||||
|
This function does not get triggered by clients <=0.4.16 if the
|
||||||
|
"formspec" node metadata field is set ]]
|
||||||
|
|
||||||
on_dig = func(pos, node, digger), --[[
|
on_dig = func(pos, node, digger), --[[
|
||||||
^ default: minetest.node_dig
|
^ default: minetest.node_dig
|
||||||
@ -4674,3 +4809,26 @@ The Biome API is still in an experimental phase and subject to change.
|
|||||||
-- ^ HTTP status code
|
-- ^ HTTP status code
|
||||||
data = "response"
|
data = "response"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
### Authentication handler definition
|
||||||
|
|
||||||
|
{
|
||||||
|
get_auth = func(name),
|
||||||
|
-- ^ Get authentication data for existing player `name` (`nil` if player doesn't exist)
|
||||||
|
-- ^ returns following structure `{password=<string>, privileges=<table>, last_login=<number or nil>}`
|
||||||
|
create_auth = func(name, password),
|
||||||
|
-- ^ Create new auth data for player `name`
|
||||||
|
-- ^ Note that `password` is not plain-text but an arbitrary representation decided by the engine
|
||||||
|
set_password = func(name, password),
|
||||||
|
-- ^ Set password of player `name` to `password`
|
||||||
|
Auth data should be created if not present
|
||||||
|
set_privileges = func(name, privileges),
|
||||||
|
-- ^ Set privileges of player `name`
|
||||||
|
-- ^ `privileges` is in table form, auth data should be created if not present
|
||||||
|
reload = func(),
|
||||||
|
-- ^ Reload authentication data from the storage location
|
||||||
|
-- ^ Returns boolean indicating success
|
||||||
|
record_login = func(name),
|
||||||
|
-- ^ Called when player joins, used for keeping track of last_login
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Minetest Lua Mainmenu API Reference 0.4.16
|
Minetest Lua Mainmenu API Reference 0.4.17
|
||||||
========================================
|
========================================
|
||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
|
@ -1270,7 +1270,9 @@ minetest.register_node("default:chest_locked", {
|
|||||||
sounds = default.node_sound_wood_defaults(),
|
sounds = default.node_sound_wood_defaults(),
|
||||||
after_place_node = function(pos, placer)
|
after_place_node = function(pos, placer)
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
meta:set_string("owner", placer:get_player_name() or "")
|
local pname =
|
||||||
|
placer and placer:get_player_name() or ""
|
||||||
|
meta:set_string("owner", pname)
|
||||||
meta:set_string("infotext", "Locked Chest (owned by "..
|
meta:set_string("infotext", "Locked Chest (owned by "..
|
||||||
meta:get_string("owner")..")")
|
meta:get_string("owner")..")")
|
||||||
end,
|
end,
|
||||||
|
@ -161,11 +161,6 @@
|
|||||||
# type: key
|
# type: key
|
||||||
# keymap_cmd_local = .
|
# keymap_cmd_local = .
|
||||||
|
|
||||||
# Key for opening the chat console.
|
|
||||||
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
|
|
||||||
# type: key
|
|
||||||
# keyman_console = KEY_F10
|
|
||||||
|
|
||||||
# Key for toggling unlimited view range.
|
# Key for toggling unlimited view range.
|
||||||
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
|
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
|
||||||
# type: key
|
# type: key
|
||||||
@ -344,8 +339,8 @@
|
|||||||
# serverlist_file = favoriteservers.txt
|
# serverlist_file = favoriteservers.txt
|
||||||
|
|
||||||
# Maximum size of the out chat queue. 0 to disable queueing and -1 to make the queue size unlimited
|
# Maximum size of the out chat queue. 0 to disable queueing and -1 to make the queue size unlimited
|
||||||
# type: int min: -1
|
# type: int
|
||||||
max_out_chat_queue_size = 20
|
# max_out_chat_queue_size = 20
|
||||||
|
|
||||||
## Graphics
|
## Graphics
|
||||||
|
|
||||||
@ -555,7 +550,7 @@ max_out_chat_queue_size = 20
|
|||||||
# type: int
|
# type: int
|
||||||
# screenH = 600
|
# screenH = 600
|
||||||
|
|
||||||
# Save the window size automatically when modified.
|
# Save window size automatically when modified.
|
||||||
# type: bool
|
# type: bool
|
||||||
# autosave_screensize = true
|
# autosave_screensize = true
|
||||||
|
|
||||||
@ -867,11 +862,10 @@ max_out_chat_queue_size = 20
|
|||||||
# type: string
|
# type: string
|
||||||
# serverlist_url = servers.minetest.net
|
# serverlist_url = servers.minetest.net
|
||||||
|
|
||||||
# Disable escape sequences, e.g. chat coloring.
|
# Remove color codes from incoming chat messages
|
||||||
# Use this if you want to run a server with pre-0.4.14 clients and you want to disable
|
# Use this to stop players from being able to use color in their messages
|
||||||
# the escape sequences generated by mods.
|
|
||||||
# type: bool
|
# type: bool
|
||||||
# disable_escape_sequences = false
|
# strip_color_codes = false
|
||||||
|
|
||||||
## Network
|
## Network
|
||||||
|
|
||||||
@ -1841,3 +1835,4 @@ max_out_chat_queue_size = 20
|
|||||||
# Print the engine's profiling data in regular intervals (in seconds). 0 = disable. Useful for developers.
|
# Print the engine's profiling data in regular intervals (in seconds). 0 = disable. Useful for developers.
|
||||||
# type: int
|
# type: int
|
||||||
# profiler_print_interval = 0
|
# profiler_print_interval = 0
|
||||||
|
|
||||||
|
@ -268,7 +268,7 @@ if(WIN32)
|
|||||||
else() # Probably MinGW = GCC
|
else() # Probably MinGW = GCC
|
||||||
set(PLATFORM_LIBS "")
|
set(PLATFORM_LIBS "")
|
||||||
endif()
|
endif()
|
||||||
set(PLATFORM_LIBS ws2_32.lib shlwapi.lib ${PLATFORM_LIBS})
|
set(PLATFORM_LIBS ws2_32.lib version.lib shlwapi.lib ${PLATFORM_LIBS})
|
||||||
|
|
||||||
# Zlib stuff
|
# Zlib stuff
|
||||||
set(ZLIB_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/../../zlib/zlib-1.2.5"
|
set(ZLIB_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/../../zlib/zlib-1.2.5"
|
||||||
@ -325,10 +325,12 @@ else()
|
|||||||
endif(HAVE_LIBRT)
|
endif(HAVE_LIBRT)
|
||||||
endif(APPLE)
|
endif(APPLE)
|
||||||
|
|
||||||
|
if(NOT APPLE)
|
||||||
# This way Xxf86vm is found on OpenBSD too
|
# This way Xxf86vm is found on OpenBSD too
|
||||||
find_library(XXF86VM_LIBRARY Xxf86vm)
|
find_library(XXF86VM_LIBRARY Xxf86vm)
|
||||||
mark_as_advanced(XXF86VM_LIBRARY)
|
mark_as_advanced(XXF86VM_LIBRARY)
|
||||||
set(CLIENT_PLATFORM_LIBS ${CLIENT_PLATFORM_LIBS} ${XXF86VM_LIBRARY})
|
set(CLIENT_PLATFORM_LIBS ${CLIENT_PLATFORM_LIBS} ${XXF86VM_LIBRARY})
|
||||||
|
endif(NOT APPLE)
|
||||||
|
|
||||||
# Prefer local iconv if installed
|
# Prefer local iconv if installed
|
||||||
find_library(ICONV_LIBRARY iconv)
|
find_library(ICONV_LIBRARY iconv)
|
||||||
|
@ -386,8 +386,9 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime,
|
|||||||
// *100.0 helps in large map coordinates
|
// *100.0 helps in large map coordinates
|
||||||
m_cameranode->setTarget(my_cp-intToFloat(m_camera_offset, BS) + 100 * m_camera_direction);
|
m_cameranode->setTarget(my_cp-intToFloat(m_camera_offset, BS) + 100 * m_camera_direction);
|
||||||
|
|
||||||
// update the camera position in front-view mode to render blocks behind player
|
// update the camera position in third-person mode to render blocks behind player
|
||||||
if (m_camera_mode == CAMERA_MODE_THIRD_FRONT)
|
// and correctly apply liquid post FX.
|
||||||
|
if (m_camera_mode != CAMERA_MODE_FIRST)
|
||||||
m_camera_position = my_cp;
|
m_camera_position = my_cp;
|
||||||
|
|
||||||
// Get FOV
|
// Get FOV
|
||||||
@ -487,7 +488,9 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime,
|
|||||||
void Camera::updateViewingRange()
|
void Camera::updateViewingRange()
|
||||||
{
|
{
|
||||||
f32 viewing_range = g_settings->getFloat("viewing_range");
|
f32 viewing_range = g_settings->getFloat("viewing_range");
|
||||||
|
f32 near_plane = g_settings->getFloat("near_plane");
|
||||||
m_draw_control.wanted_range = viewing_range;
|
m_draw_control.wanted_range = viewing_range;
|
||||||
|
m_cameranode->setNearValue(rangelim(near_plane, 0.0f, 0.5f) * BS);
|
||||||
if (m_draw_control.range_all) {
|
if (m_draw_control.range_all) {
|
||||||
m_cameranode->setFarValue(100000.0);
|
m_cameranode->setFarValue(100000.0);
|
||||||
return;
|
return;
|
||||||
|
@ -332,7 +332,7 @@ void CavesRandomWalk::makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax,
|
|||||||
|
|
||||||
route_y_min = 0;
|
route_y_min = 0;
|
||||||
// Allow half a diameter + 7 over stone surface
|
// Allow half a diameter + 7 over stone surface
|
||||||
route_y_max = -of.Y + max_stone_y + max_tunnel_diameter / 2 + 7;
|
route_y_max = -of.Y + max_stone_height + max_tunnel_diameter / 2 + 7;
|
||||||
|
|
||||||
// Limit maximum to area
|
// Limit maximum to area
|
||||||
route_y_max = rangelim(route_y_max, 0, ar.Y - 1);
|
route_y_max = rangelim(route_y_max, 0, ar.Y - 1);
|
||||||
|
@ -134,7 +134,6 @@ public:
|
|||||||
bool large_cave_is_flat;
|
bool large_cave_is_flat;
|
||||||
bool flooded;
|
bool flooded;
|
||||||
|
|
||||||
s16 max_stone_y;
|
|
||||||
v3s16 node_min;
|
v3s16 node_min;
|
||||||
v3s16 node_max;
|
v3s16 node_max;
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
#ifndef __IRR_USTRING_H_INCLUDED__
|
#ifndef __IRR_USTRING_H_INCLUDED__
|
||||||
#define __IRR_USTRING_H_INCLUDED__
|
#define __IRR_USTRING_H_INCLUDED__
|
||||||
|
|
||||||
#if (__cplusplus > 199711L) || (_MSC_VER >= 1600) || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1600) || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||||
# define USTRING_CPP0X
|
# define USTRING_CPP0X
|
||||||
# if defined(__GXX_EXPERIMENTAL_CXX0X__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)))
|
# if defined(__GXX_EXPERIMENTAL_CXX0X__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)))
|
||||||
# define USTRING_CPP0X_NEWLITERALS
|
# define USTRING_CPP0X_NEWLITERALS
|
||||||
|
@ -73,7 +73,6 @@ Client::Client(
|
|||||||
m_connection_reinit_timer(0.1),
|
m_connection_reinit_timer(0.1),
|
||||||
m_avg_rtt_timer(0.0),
|
m_avg_rtt_timer(0.0),
|
||||||
m_playerpos_send_timer(0.0),
|
m_playerpos_send_timer(0.0),
|
||||||
m_ignore_damage_timer(0.0),
|
|
||||||
m_tsrc(tsrc),
|
m_tsrc(tsrc),
|
||||||
m_shsrc(shsrc),
|
m_shsrc(shsrc),
|
||||||
m_itemdef(itemdef),
|
m_itemdef(itemdef),
|
||||||
@ -231,6 +230,8 @@ Client::~Client()
|
|||||||
m_shutdown = true;
|
m_shutdown = true;
|
||||||
m_con.Disconnect();
|
m_con.Disconnect();
|
||||||
|
|
||||||
|
deleteAuthData();
|
||||||
|
|
||||||
m_mesh_update_thread.stop();
|
m_mesh_update_thread.stop();
|
||||||
m_mesh_update_thread.wait();
|
m_mesh_update_thread.wait();
|
||||||
while (!m_mesh_update_thread.m_queue_out.empty()) {
|
while (!m_mesh_update_thread.m_queue_out.empty()) {
|
||||||
@ -258,6 +259,7 @@ Client::~Client()
|
|||||||
}
|
}
|
||||||
|
|
||||||
delete m_minimap;
|
delete m_minimap;
|
||||||
|
delete m_media_downloader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::connect(Address address, bool is_local_server)
|
void Client::connect(Address address, bool is_local_server)
|
||||||
@ -278,11 +280,6 @@ void Client::step(float dtime)
|
|||||||
if (dtime > 2.0)
|
if (dtime > 2.0)
|
||||||
dtime = 2.0;
|
dtime = 2.0;
|
||||||
|
|
||||||
if(m_ignore_damage_timer > dtime)
|
|
||||||
m_ignore_damage_timer -= dtime;
|
|
||||||
else
|
|
||||||
m_ignore_damage_timer = 0.0;
|
|
||||||
|
|
||||||
m_animation_time += dtime;
|
m_animation_time += dtime;
|
||||||
if(m_animation_time > 60.0)
|
if(m_animation_time > 60.0)
|
||||||
m_animation_time -= 60.0;
|
m_animation_time -= 60.0;
|
||||||
@ -429,7 +426,6 @@ void Client::step(float dtime)
|
|||||||
ClientEnvEvent envEvent = m_env.getClientEnvEvent();
|
ClientEnvEvent envEvent = m_env.getClientEnvEvent();
|
||||||
|
|
||||||
if (envEvent.type == CEE_PLAYER_DAMAGE) {
|
if (envEvent.type == CEE_PLAYER_DAMAGE) {
|
||||||
if (m_ignore_damage_timer <= 0) {
|
|
||||||
u8 damage = envEvent.player_damage.amount;
|
u8 damage = envEvent.player_damage.amount;
|
||||||
|
|
||||||
if (envEvent.player_damage.send_to_server)
|
if (envEvent.player_damage.send_to_server)
|
||||||
@ -441,7 +437,6 @@ void Client::step(float dtime)
|
|||||||
event.player_damage.amount = damage;
|
event.player_damage.amount = damage;
|
||||||
m_client_event_queue.push(event);
|
m_client_event_queue.push(event);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Protocol v29 or greater obsoleted this event
|
// Protocol v29 or greater obsoleted this event
|
||||||
else if (envEvent.type == CEE_PLAYER_BREATH && m_proto_ver < 29) {
|
else if (envEvent.type == CEE_PLAYER_BREATH && m_proto_ver < 29) {
|
||||||
u16 breath = envEvent.player_breath.amount;
|
u16 breath = envEvent.player_breath.amount;
|
||||||
|
@ -574,7 +574,6 @@ private:
|
|||||||
float m_connection_reinit_timer;
|
float m_connection_reinit_timer;
|
||||||
float m_avg_rtt_timer;
|
float m_avg_rtt_timer;
|
||||||
float m_playerpos_send_timer;
|
float m_playerpos_send_timer;
|
||||||
float m_ignore_damage_timer; // Used after server moves player
|
|
||||||
IntervalLimiter m_map_timer_and_unload_interval;
|
IntervalLimiter m_map_timer_and_unload_interval;
|
||||||
|
|
||||||
IWritableTextureSource *m_tsrc;
|
IWritableTextureSource *m_tsrc;
|
||||||
|
@ -60,6 +60,8 @@ struct JoystickButtonCmb : public JoystickCombination {
|
|||||||
this->key = key;
|
this->key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual ~JoystickButtonCmb() {}
|
||||||
|
|
||||||
virtual bool isTriggered(const irr::SEvent::SJoystickEvent &ev) const;
|
virtual bool isTriggered(const irr::SEvent::SJoystickEvent &ev) const;
|
||||||
|
|
||||||
u32 filter_mask;
|
u32 filter_mask;
|
||||||
@ -77,6 +79,8 @@ struct JoystickAxisCmb : public JoystickCombination {
|
|||||||
this->key = key;
|
this->key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual ~JoystickAxisCmb() {}
|
||||||
|
|
||||||
virtual bool isTriggered(const irr::SEvent::SJoystickEvent &ev) const;
|
virtual bool isTriggered(const irr::SEvent::SJoystickEvent &ev) const;
|
||||||
|
|
||||||
u16 axis_to_compare;
|
u16 axis_to_compare;
|
||||||
|
@ -1138,13 +1138,14 @@ video::IImage * Align2Npot2(video::IImage * image,
|
|||||||
|
|
||||||
core::dimension2d<u32> dim = image->getDimension();
|
core::dimension2d<u32> dim = image->getDimension();
|
||||||
|
|
||||||
std::string extensions = (char*) glGetString(GL_EXTENSIONS);
|
|
||||||
|
|
||||||
// Only GLES2 is trusted to correctly report npot support
|
// Only GLES2 is trusted to correctly report npot support
|
||||||
if (get_GL_major_version() > 1 &&
|
// Note: we cache the boolean result. GL context will never change on Android.
|
||||||
extensions.find("GL_OES_texture_npot") != std::string::npos) {
|
static const bool hasNPotSupport = get_GL_major_version() > 1 &&
|
||||||
|
glGetString(GL_EXTENSIONS) &&
|
||||||
|
strstr(glGetString(GL_EXTENSIONS), "GL_OES_texture_npot");
|
||||||
|
|
||||||
|
if (hasNPotSupport)
|
||||||
return image;
|
return image;
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int height = npot2(dim.Height);
|
unsigned int height = npot2(dim.Height);
|
||||||
unsigned int width = npot2(dim.Width);
|
unsigned int width = npot2(dim.Width);
|
||||||
@ -1805,7 +1806,8 @@ bool TextureSource::generateImagePart(std::string part_of_name,
|
|||||||
* mix high- and low-res textures, or for mods with least-common-denominator
|
* mix high- and low-res textures, or for mods with least-common-denominator
|
||||||
* textures that don't have the resources to offer high-res alternatives.
|
* textures that don't have the resources to offer high-res alternatives.
|
||||||
*/
|
*/
|
||||||
s32 scaleto = g_settings->getS32("texture_min_size");
|
const bool filter = m_setting_trilinear_filter || m_setting_bilinear_filter;
|
||||||
|
const s32 scaleto = filter ? g_settings->getS32("texture_min_size") : 1;
|
||||||
if (scaleto > 1) {
|
if (scaleto > 1) {
|
||||||
const core::dimension2d<u32> dim = baseimg->getDimension();
|
const core::dimension2d<u32> dim = baseimg->getDimension();
|
||||||
|
|
||||||
|
@ -159,7 +159,8 @@ enum MaterialType{
|
|||||||
TILE_MATERIAL_LIQUID_TRANSPARENT,
|
TILE_MATERIAL_LIQUID_TRANSPARENT,
|
||||||
TILE_MATERIAL_LIQUID_OPAQUE,
|
TILE_MATERIAL_LIQUID_OPAQUE,
|
||||||
TILE_MATERIAL_WAVING_LEAVES,
|
TILE_MATERIAL_WAVING_LEAVES,
|
||||||
TILE_MATERIAL_WAVING_PLANTS
|
TILE_MATERIAL_WAVING_PLANTS,
|
||||||
|
TILE_MATERIAL_OPAQUE
|
||||||
};
|
};
|
||||||
|
|
||||||
// Material flags
|
// Material flags
|
||||||
@ -243,18 +244,20 @@ struct TileLayer
|
|||||||
void applyMaterialOptions(video::SMaterial &material) const
|
void applyMaterialOptions(video::SMaterial &material) const
|
||||||
{
|
{
|
||||||
switch (material_type) {
|
switch (material_type) {
|
||||||
|
case TILE_MATERIAL_OPAQUE:
|
||||||
|
case TILE_MATERIAL_LIQUID_OPAQUE:
|
||||||
|
material.MaterialType = video::EMT_SOLID;
|
||||||
|
break;
|
||||||
case TILE_MATERIAL_BASIC:
|
case TILE_MATERIAL_BASIC:
|
||||||
case TILE_MATERIAL_WAVING_LEAVES:
|
case TILE_MATERIAL_WAVING_LEAVES:
|
||||||
case TILE_MATERIAL_WAVING_PLANTS:
|
case TILE_MATERIAL_WAVING_PLANTS:
|
||||||
|
material.MaterialTypeParam = 0.5;
|
||||||
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||||
break;
|
break;
|
||||||
case TILE_MATERIAL_ALPHA:
|
case TILE_MATERIAL_ALPHA:
|
||||||
case TILE_MATERIAL_LIQUID_TRANSPARENT:
|
case TILE_MATERIAL_LIQUID_TRANSPARENT:
|
||||||
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||||
break;
|
break;
|
||||||
case TILE_MATERIAL_LIQUID_OPAQUE:
|
|
||||||
material.MaterialType = video::EMT_SOLID;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING)
|
material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING)
|
||||||
? true : false;
|
? true : false;
|
||||||
|
@ -633,6 +633,16 @@ std::vector<u16> ClientInterface::getClientIDs(ClientState min_state)
|
|||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify if user limit was reached.
|
||||||
|
* User limit count all clients from HelloSent state (MT protocol user) to Active state
|
||||||
|
* @return true if user limit was reached
|
||||||
|
*/
|
||||||
|
bool ClientInterface::isUserLimitReached()
|
||||||
|
{
|
||||||
|
return getClientIDs(CS_HelloSent).size() >= g_settings->getU16("max_users");
|
||||||
|
}
|
||||||
|
|
||||||
void ClientInterface::step(float dtime)
|
void ClientInterface::step(float dtime)
|
||||||
{
|
{
|
||||||
m_print_info_timer += dtime;
|
m_print_info_timer += dtime;
|
||||||
|
@ -449,6 +449,9 @@ public:
|
|||||||
/* get list of active client id's */
|
/* get list of active client id's */
|
||||||
std::vector<u16> getClientIDs(ClientState min_state=CS_Active);
|
std::vector<u16> getClientIDs(ClientState min_state=CS_Active);
|
||||||
|
|
||||||
|
/* verify is server user limit was reached */
|
||||||
|
bool isUserLimitReached();
|
||||||
|
|
||||||
/* get list of client player names */
|
/* get list of client player names */
|
||||||
const std::vector<std::string> &getPlayerNames() const { return m_clients_names; }
|
const std::vector<std::string> &getPlayerNames() const { return m_clients_names; }
|
||||||
|
|
||||||
@ -493,7 +496,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static std::string state2Name(ClientState state);
|
static std::string state2Name(ClientState state);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//TODO find way to avoid this functions
|
//TODO find way to avoid this functions
|
||||||
void lock() { m_clients_mutex.lock(); }
|
void lock() { m_clients_mutex.lock(); }
|
||||||
|
@ -290,49 +290,46 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver)
|
|||||||
|
|
||||||
struct MeshBufList
|
struct MeshBufList
|
||||||
{
|
{
|
||||||
/*!
|
|
||||||
* Specifies in which layer the list is.
|
|
||||||
* All lists which are in a lower layer are rendered before this list.
|
|
||||||
*/
|
|
||||||
u8 layer;
|
|
||||||
video::SMaterial m;
|
video::SMaterial m;
|
||||||
std::vector<scene::IMeshBuffer*> bufs;
|
std::vector<scene::IMeshBuffer*> bufs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MeshBufListList
|
struct MeshBufListList
|
||||||
{
|
{
|
||||||
std::vector<MeshBufList> lists;
|
/*!
|
||||||
|
* Stores the mesh buffers of the world.
|
||||||
|
* The array index is the material's layer.
|
||||||
|
* The vector part groups vertices by material.
|
||||||
|
*/
|
||||||
|
std::vector<MeshBufList> lists[MAX_TILE_LAYERS];
|
||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
lists.clear();
|
for (int l = 0; l < MAX_TILE_LAYERS; l++)
|
||||||
|
lists[l].clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void add(scene::IMeshBuffer *buf, u8 layer)
|
void add(scene::IMeshBuffer *buf, u8 layer)
|
||||||
{
|
{
|
||||||
|
// Append to the correct layer
|
||||||
|
std::vector<MeshBufList> &list = lists[layer];
|
||||||
const video::SMaterial &m = buf->getMaterial();
|
const video::SMaterial &m = buf->getMaterial();
|
||||||
for(std::vector<MeshBufList>::iterator i = lists.begin();
|
for (std::vector<MeshBufList>::iterator it = list.begin(); it != list.end();
|
||||||
i != lists.end(); ++i){
|
++it) {
|
||||||
MeshBufList &l = *i;
|
|
||||||
|
|
||||||
// comparing a full material is quite expensive so we don't do it if
|
// comparing a full material is quite expensive so we don't do it if
|
||||||
// not even first texture is equal
|
// not even first texture is equal
|
||||||
if (l.m.TextureLayer[0].Texture != m.TextureLayer[0].Texture)
|
if ((*it).m.TextureLayer[0].Texture != m.TextureLayer[0].Texture)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if(l.layer != layer)
|
if ((*it).m == m) {
|
||||||
continue;
|
(*it).bufs.push_back(buf);
|
||||||
|
|
||||||
if (l.m == m) {
|
|
||||||
l.bufs.push_back(buf);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MeshBufList l;
|
MeshBufList l;
|
||||||
l.layer = layer;
|
|
||||||
l.m = m;
|
l.m = m;
|
||||||
l.bufs.push_back(buf);
|
l.bufs.push_back(buf);
|
||||||
lists.push_back(l);
|
list.push_back(l);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -360,7 +357,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
|||||||
Measuring time is very useful for long delays when the
|
Measuring time is very useful for long delays when the
|
||||||
machine is swapping a lot.
|
machine is swapping a lot.
|
||||||
*/
|
*/
|
||||||
int time1 = time(0);
|
time_t time1 = time(0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Get animation parameters
|
Get animation parameters
|
||||||
@ -476,15 +473,17 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<MeshBufList> &lists = drawbufs.lists;
|
// Render all layers in order
|
||||||
|
for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) {
|
||||||
|
std::vector<MeshBufList> &lists = drawbufs.lists[layer];
|
||||||
|
|
||||||
int timecheck_counter = 0;
|
int timecheck_counter = 0;
|
||||||
for (std::vector<MeshBufList>::iterator i = lists.begin();
|
for (std::vector<MeshBufList>::iterator it = lists.begin(); it != lists.end();
|
||||||
i != lists.end(); ++i) {
|
++it) {
|
||||||
timecheck_counter++;
|
timecheck_counter++;
|
||||||
if (timecheck_counter > 50) {
|
if (timecheck_counter > 50) {
|
||||||
timecheck_counter = 0;
|
timecheck_counter = 0;
|
||||||
int time2 = time(0);
|
time_t time2 = time(0);
|
||||||
if (time2 > time1 + 4) {
|
if (time2 > time1 + 4) {
|
||||||
infostream << "ClientMap::renderMap(): "
|
infostream << "ClientMap::renderMap(): "
|
||||||
"Rendering takes ages, returning."
|
"Rendering takes ages, returning."
|
||||||
@ -493,18 +492,15 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MeshBufList &list = *i;
|
driver->setMaterial((*it).m);
|
||||||
|
|
||||||
driver->setMaterial(list.m);
|
for (std::vector<scene::IMeshBuffer*>::iterator it2 = (*it).bufs.begin();
|
||||||
|
it2 != (*it).bufs.end(); ++it2) {
|
||||||
for (std::vector<scene::IMeshBuffer*>::iterator j = list.bufs.begin();
|
driver->drawMeshBuffer(*it2);
|
||||||
j != list.bufs.end(); ++j) {
|
vertex_count += (*it2)->getVertexCount();
|
||||||
scene::IMeshBuffer *buf = *j;
|
|
||||||
driver->drawMeshBuffer(buf);
|
|
||||||
vertex_count += buf->getVertexCount();
|
|
||||||
meshbuffer_count++;
|
meshbuffer_count++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} // ScopeProfiler
|
} // ScopeProfiler
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#define VERSION_MAJOR @VERSION_MAJOR@
|
#define VERSION_MAJOR @VERSION_MAJOR@
|
||||||
#define VERSION_MINOR @VERSION_MINOR@
|
#define VERSION_MINOR @VERSION_MINOR@
|
||||||
#define VERSION_PATCH @VERSION_PATCH@
|
#define VERSION_PATCH @VERSION_PATCH@
|
||||||
|
#define VERSION_TWEAK @VERSION_TWEAK@
|
||||||
#define VERSION_EXTRA "@VERSION_EXTRA@"
|
#define VERSION_EXTRA "@VERSION_EXTRA@"
|
||||||
#define VERSION_STRING "@VERSION_STRING@"
|
#define VERSION_STRING "@VERSION_STRING@"
|
||||||
#define PRODUCT_VERSION_STRING "@VERSION_MAJOR@.@VERSION_MINOR@"
|
#define PRODUCT_VERSION_STRING "@VERSION_MAJOR@.@VERSION_MINOR@"
|
||||||
|
@ -258,27 +258,32 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
|||||||
//TimeTaker tt2("collisionMoveSimple collect boxes");
|
//TimeTaker tt2("collisionMoveSimple collect boxes");
|
||||||
ScopeProfiler sp(g_profiler, "collisionMoveSimple collect boxes avg", SPT_AVG);
|
ScopeProfiler sp(g_profiler, "collisionMoveSimple collect boxes avg", SPT_AVG);
|
||||||
|
|
||||||
v3s16 oldpos_i = floatToInt(*pos_f, BS);
|
v3f newpos_f = *pos_f + *speed_f * dtime;
|
||||||
v3s16 newpos_i = floatToInt(*pos_f + *speed_f * dtime, BS);
|
v3f minpos_f(
|
||||||
s16 min_x = MYMIN(oldpos_i.X, newpos_i.X) + (box_0.MinEdge.X / BS) - 1;
|
MYMIN(pos_f->X, newpos_f.X),
|
||||||
s16 min_y = MYMIN(oldpos_i.Y, newpos_i.Y) + (box_0.MinEdge.Y / BS) - 1;
|
MYMIN(pos_f->Y, newpos_f.Y) + 0.01 * BS, // bias rounding, player often at +/-n.5
|
||||||
s16 min_z = MYMIN(oldpos_i.Z, newpos_i.Z) + (box_0.MinEdge.Z / BS) - 1;
|
MYMIN(pos_f->Z, newpos_f.Z)
|
||||||
s16 max_x = MYMAX(oldpos_i.X, newpos_i.X) + (box_0.MaxEdge.X / BS) + 1;
|
);
|
||||||
s16 max_y = MYMAX(oldpos_i.Y, newpos_i.Y) + (box_0.MaxEdge.Y / BS) + 1;
|
v3f maxpos_f(
|
||||||
s16 max_z = MYMAX(oldpos_i.Z, newpos_i.Z) + (box_0.MaxEdge.Z / BS) + 1;
|
MYMAX(pos_f->X, newpos_f.X),
|
||||||
|
MYMAX(pos_f->Y, newpos_f.Y),
|
||||||
|
MYMAX(pos_f->Z, newpos_f.Z)
|
||||||
|
);
|
||||||
|
v3s16 min = floatToInt(minpos_f + box_0.MinEdge, BS) - v3s16(1, 1, 1);
|
||||||
|
v3s16 max = floatToInt(maxpos_f + box_0.MaxEdge, BS) + v3s16(1, 1, 1);
|
||||||
|
|
||||||
bool any_position_valid = false;
|
bool any_position_valid = false;
|
||||||
|
|
||||||
for(s16 x = min_x; x <= max_x; x++)
|
for(s16 x = min.X; x <= max.X; x++)
|
||||||
for(s16 y = min_y; y <= max_y; y++)
|
for(s16 y = min.Y; y <= max.Y; y++)
|
||||||
for(s16 z = min_z; z <= max_z; z++)
|
for(s16 z = min.Z; z <= max.Z; z++)
|
||||||
{
|
{
|
||||||
v3s16 p(x,y,z);
|
v3s16 p(x,y,z);
|
||||||
|
|
||||||
bool is_position_valid;
|
bool is_position_valid;
|
||||||
MapNode n = map->getNodeNoEx(p, &is_position_valid);
|
MapNode n = map->getNodeNoEx(p, &is_position_valid);
|
||||||
|
|
||||||
if (is_position_valid) {
|
if (is_position_valid && n.getContent() != CONTENT_IGNORE) {
|
||||||
// Object collides into walkable nodes
|
// Object collides into walkable nodes
|
||||||
|
|
||||||
any_position_valid = true;
|
any_position_valid = true;
|
||||||
@ -328,7 +333,8 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
|||||||
false, n_bouncy_value, p, box));
|
false, n_bouncy_value, p, box));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Collide with unloaded nodes
|
// Collide with unloaded nodes (position invalid) and loaded
|
||||||
|
// CONTENT_IGNORE nodes (position valid)
|
||||||
aabb3f box = getNodeBox(p, BS);
|
aabb3f box = getNodeBox(p, BS);
|
||||||
cinfo.push_back(NearbyCollisionInfo(true, false, 0, p, box));
|
cinfo.push_back(NearbyCollisionInfo(true, false, 0, p, box));
|
||||||
}
|
}
|
||||||
@ -336,6 +342,8 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
|||||||
|
|
||||||
// Do not move if world has not loaded yet, since custom node boxes
|
// Do not move if world has not loaded yet, since custom node boxes
|
||||||
// are not available for collision detection.
|
// are not available for collision detection.
|
||||||
|
// This also intentionally occurs in the case of the object being positioned
|
||||||
|
// solely on loaded CONTENT_IGNORE nodes, no matter where they come from.
|
||||||
if (!any_position_valid) {
|
if (!any_position_valid) {
|
||||||
*speed_f = v3f(0, 0, 0);
|
*speed_f = v3f(0, 0, 0);
|
||||||
return result;
|
return result;
|
||||||
|
@ -1184,16 +1184,17 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
|
|||||||
|
|
||||||
float moved = lastpos.getDistanceFrom(pos_translator.vect_show);
|
float moved = lastpos.getDistanceFrom(pos_translator.vect_show);
|
||||||
m_step_distance_counter += moved;
|
m_step_distance_counter += moved;
|
||||||
if(m_step_distance_counter > 1.5*BS)
|
if (m_step_distance_counter > 1.5f * BS) {
|
||||||
{
|
m_step_distance_counter = 0.0f;
|
||||||
m_step_distance_counter = 0;
|
if (!m_is_local_player && m_prop.makes_footstep_sound) {
|
||||||
if(!m_is_local_player && m_prop.makes_footstep_sound)
|
|
||||||
{
|
|
||||||
INodeDefManager *ndef = m_client->ndef();
|
INodeDefManager *ndef = m_client->ndef();
|
||||||
v3s16 p = floatToInt(getPosition() + v3f(0,
|
v3s16 p = floatToInt(getPosition() +
|
||||||
(m_prop.collisionbox.MinEdge.Y-0.5)*BS, 0), BS);
|
v3f(0.0f, (m_prop.collisionbox.MinEdge.Y - 0.5f) * BS, 0.0f), BS);
|
||||||
MapNode n = m_env->getMap().getNodeNoEx(p);
|
MapNode n = m_env->getMap().getNodeNoEx(p);
|
||||||
SimpleSoundSpec spec = ndef->get(n).sound_footstep;
|
SimpleSoundSpec spec = ndef->get(n).sound_footstep;
|
||||||
|
// Reduce footstep gain, as non-local-player footsteps are
|
||||||
|
// somehow louder.
|
||||||
|
spec.gain *= 0.6f;
|
||||||
m_client->sound()->playSoundAt(spec, false, getPosition());
|
m_client->sound()->playSoundAt(spec, false, getPosition());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1354,6 +1355,13 @@ void GenericCAO::updateTextures(std::string mod)
|
|||||||
material.setFlag(video::EMF_LIGHTING, false);
|
material.setFlag(video::EMF_LIGHTING, false);
|
||||||
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
|
||||||
|
// don't filter low-res textures, makes them look blurry
|
||||||
|
// player models have a res of 64
|
||||||
|
const core::dimension2d<u32> &size = texture->getOriginalSize();
|
||||||
|
const u32 res = std::min(size.Height, size.Width);
|
||||||
|
use_trilinear_filter &= res > 64;
|
||||||
|
use_bilinear_filter &= res > 64;
|
||||||
|
|
||||||
m_animated_meshnode->getMaterial(i)
|
m_animated_meshnode->getMaterial(i)
|
||||||
.setFlag(video::EMF_TRILINEAR_FILTER, use_trilinear_filter);
|
.setFlag(video::EMF_TRILINEAR_FILTER, use_trilinear_filter);
|
||||||
m_animated_meshnode->getMaterial(i)
|
m_animated_meshnode->getMaterial(i)
|
||||||
|
@ -43,7 +43,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
// Corresponding offsets are listed in g_27dirs
|
// Corresponding offsets are listed in g_27dirs
|
||||||
#define FRAMED_NEIGHBOR_COUNT 18
|
#define FRAMED_NEIGHBOR_COUNT 18
|
||||||
|
|
||||||
static constexpr v3s16 light_dirs[8] = {
|
static const v3s16 light_dirs[8] = {
|
||||||
v3s16(-1, -1, -1),
|
v3s16(-1, -1, -1),
|
||||||
v3s16(-1, -1, 1),
|
v3s16(-1, -1, 1),
|
||||||
v3s16(-1, 1, -1),
|
v3s16(-1, 1, -1),
|
||||||
|
@ -59,7 +59,7 @@ public:
|
|||||||
m_age += dtime;
|
m_age += dtime;
|
||||||
if(m_age > 10)
|
if(m_age > 10)
|
||||||
{
|
{
|
||||||
m_removed = true;
|
m_pending_removal = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,20 +406,6 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
|
|||||||
m_env->getScriptIface()->luaentity_Step(m_id, dtime);
|
m_env->getScriptIface()->luaentity_Step(m_id, dtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove LuaEntity beyond terrain edges
|
|
||||||
{
|
|
||||||
ServerMap *map = dynamic_cast<ServerMap *>(&m_env->getMap());
|
|
||||||
assert(map);
|
|
||||||
if (!m_pending_deactivation &&
|
|
||||||
map->saoPositionOverLimit(m_base_position)) {
|
|
||||||
infostream << "Remove SAO " << m_id << "(" << m_init_name
|
|
||||||
<< "), outside of limits" << std::endl;
|
|
||||||
m_pending_deactivation = true;
|
|
||||||
m_removed = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(send_recommended == false)
|
if(send_recommended == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -557,7 +543,7 @@ int LuaEntitySAO::punch(v3f dir,
|
|||||||
{
|
{
|
||||||
if (!m_registered) {
|
if (!m_registered) {
|
||||||
// Delete unknown LuaEntities when punched
|
// Delete unknown LuaEntities when punched
|
||||||
m_removed = true;
|
m_pending_removal = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -601,7 +587,7 @@ int LuaEntitySAO::punch(v3f dir,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (getHP() == 0)
|
if (getHP() == 0)
|
||||||
m_removed = true;
|
m_pending_removal = true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1361,11 +1347,10 @@ void PlayerSAO::setWieldIndex(int i)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Erase the peer id and make the object for removal
|
|
||||||
void PlayerSAO::disconnected()
|
void PlayerSAO::disconnected()
|
||||||
{
|
{
|
||||||
m_peer_id = 0;
|
m_peer_id = 0;
|
||||||
m_removed = true;
|
m_pending_removal = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerSAO::unlinkPlayerSessionAndSave()
|
void PlayerSAO::unlinkPlayerSessionAndSave()
|
||||||
@ -1402,26 +1387,38 @@ bool PlayerSAO::checkMovementCheat()
|
|||||||
too, and much more lightweight.
|
too, and much more lightweight.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
float player_max_speed = 0;
|
float player_max_walk = 0; // horizontal movement
|
||||||
|
float player_max_jump = 0; // vertical upwards movement
|
||||||
|
|
||||||
if (m_privs.count("fast") != 0) {
|
if (m_privs.count("fast") != 0)
|
||||||
// Fast speed
|
player_max_walk = m_player->movement_speed_fast; // Fast speed
|
||||||
player_max_speed = m_player->movement_speed_fast * m_physics_override_speed;
|
else
|
||||||
} else {
|
player_max_walk = m_player->movement_speed_walk; // Normal speed
|
||||||
// Normal speed
|
player_max_walk *= m_physics_override_speed;
|
||||||
player_max_speed = m_player->movement_speed_walk * m_physics_override_speed;
|
player_max_jump = m_player->movement_speed_jump * m_physics_override_jump;
|
||||||
}
|
// FIXME: Bouncy nodes cause practically unbound increase in Y speed,
|
||||||
// Tolerance. The lag pool does this a bit.
|
// until this can be verified correctly, tolerate higher jumping speeds
|
||||||
//player_max_speed *= 2.5;
|
player_max_jump *= 2.0;
|
||||||
|
|
||||||
|
// Don't divide by zero!
|
||||||
|
if (player_max_walk < 0.0001f)
|
||||||
|
player_max_walk = 0.0001f;
|
||||||
|
if (player_max_jump < 0.0001f)
|
||||||
|
player_max_jump = 0.0001f;
|
||||||
|
|
||||||
v3f diff = (m_base_position - m_last_good_position);
|
v3f diff = (m_base_position - m_last_good_position);
|
||||||
float d_vert = diff.Y;
|
float d_vert = diff.Y;
|
||||||
diff.Y = 0;
|
diff.Y = 0;
|
||||||
float d_horiz = diff.getLength();
|
float d_horiz = diff.getLength();
|
||||||
float required_time = d_horiz / player_max_speed;
|
float required_time = d_horiz / player_max_walk;
|
||||||
|
|
||||||
if (d_vert > 0 && d_vert / player_max_speed > required_time)
|
// FIXME: Checking downwards movement is not easily possible currently,
|
||||||
required_time = d_vert / player_max_speed; // Moving upwards
|
// the server could calculate speed differences to examine the gravity
|
||||||
|
if (d_vert > 0) {
|
||||||
|
// In certain cases (water, ladders) walking speed is applied vertically
|
||||||
|
float s = MYMAX(player_max_jump, player_max_walk);
|
||||||
|
required_time = MYMAX(required_time, d_vert / s);
|
||||||
|
}
|
||||||
|
|
||||||
if (m_move_pool.grab(required_time)) {
|
if (m_move_pool.grab(required_time)) {
|
||||||
m_last_good_position = m_base_position;
|
m_last_good_position = m_base_position;
|
||||||
|
@ -923,8 +923,19 @@ public:
|
|||||||
<< " against " << def->dump() << std::endl;*/
|
<< " against " << def->dump() << std::endl;*/
|
||||||
|
|
||||||
if (def->check(input, gamedef)) {
|
if (def->check(input, gamedef)) {
|
||||||
|
// Check if the crafted node/item exists
|
||||||
|
CraftOutput out = def->getOutput(input, gamedef);
|
||||||
|
ItemStack is;
|
||||||
|
is.deSerialize(out.item, gamedef->idef());
|
||||||
|
if (!is.isKnown(gamedef->idef())) {
|
||||||
|
infostream << "trying to craft non-existent "
|
||||||
|
<< out.item << ", ignoring recipe" << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Get output, then decrement input (if requested)
|
// Get output, then decrement input (if requested)
|
||||||
output = def->getOutput(input, gamedef);
|
output = out;
|
||||||
|
|
||||||
if (decrementInput)
|
if (decrementInput)
|
||||||
def->decrementInput(input, output_replacement, gamedef);
|
def->decrementInput(input, output_replacement, gamedef);
|
||||||
/*errorstream << "Check RETURNS TRUE" << std::endl;*/
|
/*errorstream << "Check RETURNS TRUE" << std::endl;*/
|
||||||
|
@ -125,6 +125,7 @@ void set_default_settings(Settings *settings)
|
|||||||
settings->setDefault("fps_max", "60");
|
settings->setDefault("fps_max", "60");
|
||||||
settings->setDefault("pause_fps_max", "20");
|
settings->setDefault("pause_fps_max", "20");
|
||||||
settings->setDefault("viewing_range", "100");
|
settings->setDefault("viewing_range", "100");
|
||||||
|
settings->setDefault("near_plane", "0.1");
|
||||||
settings->setDefault("screenW", "800");
|
settings->setDefault("screenW", "800");
|
||||||
settings->setDefault("screenH", "600");
|
settings->setDefault("screenH", "600");
|
||||||
settings->setDefault("autosave_screensize", "true");
|
settings->setDefault("autosave_screensize", "true");
|
||||||
@ -252,6 +253,7 @@ void set_default_settings(Settings *settings)
|
|||||||
|
|
||||||
// Server
|
// Server
|
||||||
settings->setDefault("disable_escape_sequences", "false");
|
settings->setDefault("disable_escape_sequences", "false");
|
||||||
|
settings->setDefault("strip_color_codes", "false");
|
||||||
|
|
||||||
// Network
|
// Network
|
||||||
settings->setDefault("enable_ipv6", "true");
|
settings->setDefault("enable_ipv6", "true");
|
||||||
|
@ -431,8 +431,10 @@ void DungeonGen::makeCorridor(v3s16 doorplace, v3s16 doordir,
|
|||||||
VMANIP_FLAG_DUNGEON_UNTOUCHABLE,
|
VMANIP_FLAG_DUNGEON_UNTOUCHABLE,
|
||||||
MapNode(dp.c_wall),
|
MapNode(dp.c_wall),
|
||||||
0);
|
0);
|
||||||
makeHole(p);
|
makeFill(p, dp.holesize, VMANIP_FLAG_DUNGEON_UNTOUCHABLE,
|
||||||
makeHole(p - dir);
|
MapNode(CONTENT_AIR), VMANIP_FLAG_DUNGEON_INSIDE);
|
||||||
|
makeFill(p - dir, dp.holesize, VMANIP_FLAG_DUNGEON_UNTOUCHABLE,
|
||||||
|
MapNode(CONTENT_AIR), VMANIP_FLAG_DUNGEON_INSIDE);
|
||||||
|
|
||||||
// TODO: fix stairs code so it works 100%
|
// TODO: fix stairs code so it works 100%
|
||||||
// (quite difficult)
|
// (quite difficult)
|
||||||
@ -451,16 +453,21 @@ void DungeonGen::makeCorridor(v3s16 doorplace, v3s16 doordir,
|
|||||||
v3s16 swv = (dir.Z != 0) ? v3s16(1, 0, 0) : v3s16(0, 0, 1);
|
v3s16 swv = (dir.Z != 0) ? v3s16(1, 0, 0) : v3s16(0, 0, 1);
|
||||||
|
|
||||||
for (u16 st = 0; st < stair_width; st++) {
|
for (u16 st = 0; st < stair_width; st++) {
|
||||||
|
if (make_stairs == -1) {
|
||||||
u32 vi = vm->m_area.index(ps.X - dir.X, ps.Y - 1, ps.Z - dir.Z);
|
u32 vi = vm->m_area.index(ps.X - dir.X, ps.Y - 1, ps.Z - dir.Z);
|
||||||
if (vm->m_area.contains(ps + v3s16(-dir.X, -1, -dir.Z)) &&
|
if (vm->m_area.contains(ps + v3s16(-dir.X, -1, -dir.Z)) &&
|
||||||
vm->m_data[vi].getContent() == dp.c_wall)
|
vm->m_data[vi].getContent() == dp.c_wall) {
|
||||||
|
vm->m_flags[vi] |= VMANIP_FLAG_DUNGEON_UNTOUCHABLE;
|
||||||
vm->m_data[vi] = MapNode(dp.c_stair, 0, facedir);
|
vm->m_data[vi] = MapNode(dp.c_stair, 0, facedir);
|
||||||
|
}
|
||||||
vi = vm->m_area.index(ps.X, ps.Y, ps.Z);
|
} else if (make_stairs == 1) {
|
||||||
if (vm->m_area.contains(ps) &&
|
u32 vi = vm->m_area.index(ps.X, ps.Y - 1, ps.Z);
|
||||||
vm->m_data[vi].getContent() == dp.c_wall)
|
if (vm->m_area.contains(ps + v3s16(0, -1, 0)) &&
|
||||||
|
vm->m_data[vi].getContent() == dp.c_wall) {
|
||||||
|
vm->m_flags[vi] |= VMANIP_FLAG_DUNGEON_UNTOUCHABLE;
|
||||||
vm->m_data[vi] = MapNode(dp.c_stair, 0, facedir);
|
vm->m_data[vi] = MapNode(dp.c_stair, 0, facedir);
|
||||||
|
}
|
||||||
|
}
|
||||||
ps += swv;
|
ps += swv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -146,6 +146,9 @@ EmergeManager::~EmergeManager()
|
|||||||
}
|
}
|
||||||
|
|
||||||
delete thread;
|
delete thread;
|
||||||
|
|
||||||
|
// Mapgen init might not be finished if there is an error during startup.
|
||||||
|
if (m_mapgens.size() > i)
|
||||||
delete m_mapgens[i];
|
delete m_mapgens[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -570,6 +573,12 @@ MapBlock *EmergeThread::finishGen(v3s16 pos, BlockMakeData *bmdata,
|
|||||||
m_server->setAsyncFatalError("Lua: finishGen" + std::string(e.what()));
|
m_server->setAsyncFatalError("Lua: finishGen" + std::string(e.what()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Clear generate notifier events
|
||||||
|
*/
|
||||||
|
Mapgen *mg = m_emerge->getCurrentMapgen();
|
||||||
|
mg->gennotify.clearEvents();
|
||||||
|
|
||||||
EMERGE_DBG_OUT("ended up with: " << analyze_block(block));
|
EMERGE_DBG_OUT("ended up with: " << analyze_block(block));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -27,6 +27,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
#include "settings.h" // For g_settings
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace fs
|
namespace fs
|
||||||
{
|
{
|
||||||
@ -374,7 +377,7 @@ std::string TempPath()
|
|||||||
configuration hardcodes mkstemp("/tmp/lua_XXXXXX").
|
configuration hardcodes mkstemp("/tmp/lua_XXXXXX").
|
||||||
*/
|
*/
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
return DIR_DELIM "sdcard" DIR_DELIM PROJECT_NAME DIR_DELIM "tmp";
|
return g_settings->get("TMPFolder");
|
||||||
#else
|
#else
|
||||||
return DIR_DELIM "tmp";
|
return DIR_DELIM "tmp";
|
||||||
#endif
|
#endif
|
||||||
|
@ -341,14 +341,33 @@ void FontEngine::initFont(unsigned int basesize, FontMode mode)
|
|||||||
font_path.c_str(), size, true, true, font_shadow,
|
font_path.c_str(), size, true, true, font_shadow,
|
||||||
font_shadow_alpha);
|
font_shadow_alpha);
|
||||||
|
|
||||||
if (font != NULL) {
|
if (font) {
|
||||||
m_font_cache[mode][basesize] = font;
|
m_font_cache[mode][basesize] = font;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (font_config_prefix == "mono_") {
|
||||||
|
const std::string &mono_font_path = m_settings->getDefault("mono_font_path");
|
||||||
|
|
||||||
|
if (font_path != mono_font_path) {
|
||||||
|
// try original mono font
|
||||||
|
errorstream << "FontEngine: failed to load custom mono "
|
||||||
|
"font: " << font_path << ", trying to fall back to "
|
||||||
|
"original mono font" << std::endl;
|
||||||
|
|
||||||
|
font = gui::CGUITTFont::createTTFont(m_env,
|
||||||
|
mono_font_path.c_str(), size, true, true,
|
||||||
|
font_shadow, font_shadow_alpha);
|
||||||
|
|
||||||
|
if (font) {
|
||||||
|
m_font_cache[mode][basesize] = font;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
// try fallback font
|
// try fallback font
|
||||||
errorstream << "FontEngine: failed to load: " << font_path << ", trying to fall back "
|
errorstream << "FontEngine: failed to load: " << font_path <<
|
||||||
"to fallback font" << std::endl;
|
", trying to fall back to fallback font" << std::endl;
|
||||||
|
|
||||||
font_path = g_settings->get(font_config_prefix + "fallback_font_path");
|
font_path = g_settings->get(font_config_prefix + "fallback_font_path");
|
||||||
|
|
||||||
@ -356,17 +375,36 @@ void FontEngine::initFont(unsigned int basesize, FontMode mode)
|
|||||||
font_path.c_str(), size, true, true, font_shadow,
|
font_path.c_str(), size, true, true, font_shadow,
|
||||||
font_shadow_alpha);
|
font_shadow_alpha);
|
||||||
|
|
||||||
if (font != NULL) {
|
if (font) {
|
||||||
m_font_cache[mode][basesize] = font;
|
m_font_cache[mode][basesize] = font;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string &fallback_font_path = m_settings->getDefault("fallback_font_path");
|
||||||
|
|
||||||
|
if (font_path != fallback_font_path) {
|
||||||
|
// try original fallback font
|
||||||
|
errorstream << "FontEngine: failed to load custom fallback "
|
||||||
|
"font: " << font_path << ", trying to fall back to "
|
||||||
|
"original fallback font" << std::endl;
|
||||||
|
|
||||||
|
font = gui::CGUITTFont::createTTFont(m_env,
|
||||||
|
fallback_font_path.c_str(), size, true, true,
|
||||||
|
font_shadow, font_shadow_alpha);
|
||||||
|
|
||||||
|
if (font) {
|
||||||
|
m_font_cache[mode][basesize] = font;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// give up
|
// give up
|
||||||
errorstream << "FontEngine: failed to load freetype font: "
|
errorstream << "FontEngine: failed to load freetype font: "
|
||||||
<< font_path << std::endl;
|
<< font_path << std::endl;
|
||||||
errorstream << "minetest can not continue without a valid font. Please correct "
|
errorstream << "minetest can not continue without a valid font. "
|
||||||
"the 'font_path' setting or install the font file in the proper "
|
"Please correct the 'font_path' setting or install the font "
|
||||||
"location" << std::endl;
|
"file in the proper location" << std::endl;
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -468,7 +506,7 @@ void FontEngine::initSimpleFont(unsigned int basesize, FontMode mode)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (font != NULL) {
|
if (font) {
|
||||||
font->grab();
|
font->grab();
|
||||||
m_font_cache[mode][basesize] = font;
|
m_font_cache[mode][basesize] = font;
|
||||||
}
|
}
|
||||||
|
68
src/game.cpp
68
src/game.cpp
@ -170,6 +170,7 @@ struct LocalFormspecHandler : public TextDest
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Don't disable this part when modding is disabled, it's used in builtin
|
// Don't disable this part when modding is disabled, it's used in builtin
|
||||||
|
if (m_client && m_client->getScript())
|
||||||
m_client->getScript()->on_formspec_input(m_formname, fields);
|
m_client->getScript()->on_formspec_input(m_formname, fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -774,8 +775,8 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
bool nodePlacementPrediction(Client &client,
|
bool nodePlacementPrediction(Client &client, const ItemDefinition &playeritem_def,
|
||||||
const ItemDefinition &playeritem_def, v3s16 nodepos, v3s16 neighbourpos)
|
const ItemStack &playeritem, v3s16 nodepos, v3s16 neighbourpos)
|
||||||
{
|
{
|
||||||
std::string prediction = playeritem_def.node_placement_prediction;
|
std::string prediction = playeritem_def.node_placement_prediction;
|
||||||
INodeDefManager *nodedef = client.ndef();
|
INodeDefManager *nodedef = client.ndef();
|
||||||
@ -818,11 +819,13 @@ bool nodePlacementPrediction(Client &client,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ContentFeatures &predicted_f = nodedef->get(id);
|
||||||
|
|
||||||
// Predict param2 for facedir and wallmounted nodes
|
// Predict param2 for facedir and wallmounted nodes
|
||||||
u8 param2 = 0;
|
u8 param2 = 0;
|
||||||
|
|
||||||
if (nodedef->get(id).param_type_2 == CPT2_WALLMOUNTED ||
|
if (predicted_f.param_type_2 == CPT2_WALLMOUNTED ||
|
||||||
nodedef->get(id).param_type_2 == CPT2_COLORED_WALLMOUNTED) {
|
predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED) {
|
||||||
v3s16 dir = nodepos - neighbourpos;
|
v3s16 dir = nodepos - neighbourpos;
|
||||||
|
|
||||||
if (abs(dir.Y) > MYMAX(abs(dir.X), abs(dir.Z))) {
|
if (abs(dir.Y) > MYMAX(abs(dir.X), abs(dir.Z))) {
|
||||||
@ -834,8 +837,8 @@ bool nodePlacementPrediction(Client &client,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nodedef->get(id).param_type_2 == CPT2_FACEDIR ||
|
if (predicted_f.param_type_2 == CPT2_FACEDIR ||
|
||||||
nodedef->get(id).param_type_2 == CPT2_COLORED_FACEDIR) {
|
predicted_f.param_type_2 == CPT2_COLORED_FACEDIR) {
|
||||||
v3s16 dir = nodepos - floatToInt(client.getEnv().getLocalPlayer()->getPosition(), BS);
|
v3s16 dir = nodepos - floatToInt(client.getEnv().getLocalPlayer()->getPosition(), BS);
|
||||||
|
|
||||||
if (abs(dir.X) > abs(dir.Z)) {
|
if (abs(dir.X) > abs(dir.Z)) {
|
||||||
@ -848,7 +851,7 @@ bool nodePlacementPrediction(Client &client,
|
|||||||
assert(param2 <= 5);
|
assert(param2 <= 5);
|
||||||
|
|
||||||
//Check attachment if node is in group attached_node
|
//Check attachment if node is in group attached_node
|
||||||
if (((ItemGroupList) nodedef->get(id).groups)["attached_node"] != 0) {
|
if (((ItemGroupList) predicted_f.groups)["attached_node"] != 0) {
|
||||||
static v3s16 wallmounted_dirs[8] = {
|
static v3s16 wallmounted_dirs[8] = {
|
||||||
v3s16(0, 1, 0),
|
v3s16(0, 1, 0),
|
||||||
v3s16(0, -1, 0),
|
v3s16(0, -1, 0),
|
||||||
@ -859,8 +862,8 @@ bool nodePlacementPrediction(Client &client,
|
|||||||
};
|
};
|
||||||
v3s16 pp;
|
v3s16 pp;
|
||||||
|
|
||||||
if (nodedef->get(id).param_type_2 == CPT2_WALLMOUNTED ||
|
if (predicted_f.param_type_2 == CPT2_WALLMOUNTED ||
|
||||||
nodedef->get(id).param_type_2 == CPT2_COLORED_WALLMOUNTED)
|
predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED)
|
||||||
pp = p + wallmounted_dirs[param2];
|
pp = p + wallmounted_dirs[param2];
|
||||||
else
|
else
|
||||||
pp = p + v3s16(0, -1, 0);
|
pp = p + v3s16(0, -1, 0);
|
||||||
@ -869,6 +872,28 @@ bool nodePlacementPrediction(Client &client,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply color
|
||||||
|
if ((predicted_f.param_type_2 == CPT2_COLOR
|
||||||
|
|| predicted_f.param_type_2 == CPT2_COLORED_FACEDIR
|
||||||
|
|| predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED)) {
|
||||||
|
const std::string &indexstr = playeritem.metadata.getString(
|
||||||
|
"palette_index", 0);
|
||||||
|
if (!indexstr.empty()) {
|
||||||
|
s32 index = mystoi(indexstr);
|
||||||
|
if (predicted_f.param_type_2 == CPT2_COLOR) {
|
||||||
|
param2 = index;
|
||||||
|
} else if (predicted_f.param_type_2
|
||||||
|
== CPT2_COLORED_WALLMOUNTED) {
|
||||||
|
// param2 = pure palette index + other
|
||||||
|
param2 = (index & 0xf8) | (param2 & 0x07);
|
||||||
|
} else if (predicted_f.param_type_2
|
||||||
|
== CPT2_COLORED_FACEDIR) {
|
||||||
|
// param2 = pure palette index + other
|
||||||
|
param2 = (index & 0xe0) | (param2 & 0x1f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Add node to client map
|
// Add node to client map
|
||||||
MapNode n(id, 0, param2);
|
MapNode n(id, 0, param2);
|
||||||
|
|
||||||
@ -1277,7 +1302,8 @@ protected:
|
|||||||
const core::line3d<f32> &shootline, bool liquids_pointable,
|
const core::line3d<f32> &shootline, bool liquids_pointable,
|
||||||
bool look_for_object, const v3s16 &camera_offset);
|
bool look_for_object, const v3s16 &camera_offset);
|
||||||
void handlePointingAtNothing(const ItemStack &playerItem);
|
void handlePointingAtNothing(const ItemStack &playerItem);
|
||||||
void handlePointingAtNode(const PointedThing &pointed, const ItemDefinition &playeritem_def,
|
void handlePointingAtNode(const PointedThing &pointed,
|
||||||
|
const ItemDefinition &playeritem_def, const ItemStack &playeritem,
|
||||||
const ToolCapabilities &playeritem_toolcap, f32 dtime);
|
const ToolCapabilities &playeritem_toolcap, f32 dtime);
|
||||||
void handlePointingAtObject(const PointedThing &pointed, const ItemStack &playeritem,
|
void handlePointingAtObject(const PointedThing &pointed, const ItemStack &playeritem,
|
||||||
const v3f &player_position, bool show_debug);
|
const v3f &player_position, bool show_debug);
|
||||||
@ -2949,8 +2975,8 @@ void Game::decreaseViewRange()
|
|||||||
void Game::toggleFullViewRange()
|
void Game::toggleFullViewRange()
|
||||||
{
|
{
|
||||||
static const wchar_t *msg[] = {
|
static const wchar_t *msg[] = {
|
||||||
L"Disabled full viewing range",
|
L"Normal view range",
|
||||||
L"Enabled full viewing range"
|
L"Infinite view range"
|
||||||
};
|
};
|
||||||
|
|
||||||
draw_control->range_all = !draw_control->range_all;
|
draw_control->range_all = !draw_control->range_all;
|
||||||
@ -3525,6 +3551,9 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug)
|
|||||||
|
|
||||||
if ((g_settings->getBool("touchtarget")) && (g_touchscreengui)) {
|
if ((g_settings->getBool("touchtarget")) && (g_touchscreengui)) {
|
||||||
shootline = g_touchscreengui->getShootline();
|
shootline = g_touchscreengui->getShootline();
|
||||||
|
// Scale shootline to the acual distance the player can reach
|
||||||
|
shootline.end = shootline.start
|
||||||
|
+ shootline.getVector().normalize() * BS * d;
|
||||||
shootline.start += intToFloat(camera_offset, BS);
|
shootline.start += intToFloat(camera_offset, BS);
|
||||||
shootline.end += intToFloat(camera_offset, BS);
|
shootline.end += intToFloat(camera_offset, BS);
|
||||||
}
|
}
|
||||||
@ -3597,10 +3626,11 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug)
|
|||||||
} else if (pointed.type == POINTEDTHING_NODE) {
|
} else if (pointed.type == POINTEDTHING_NODE) {
|
||||||
ToolCapabilities playeritem_toolcap =
|
ToolCapabilities playeritem_toolcap =
|
||||||
playeritem.getToolCapabilities(itemdef_manager);
|
playeritem.getToolCapabilities(itemdef_manager);
|
||||||
if (playeritem.name.empty()) {
|
if (playeritem.name.empty() && hand_def.tool_capabilities != NULL) {
|
||||||
playeritem_toolcap = *hand_def.tool_capabilities;
|
playeritem_toolcap = *hand_def.tool_capabilities;
|
||||||
}
|
}
|
||||||
handlePointingAtNode(pointed, playeritem_def, playeritem_toolcap, dtime);
|
handlePointingAtNode(pointed, playeritem_def, playeritem,
|
||||||
|
playeritem_toolcap, dtime);
|
||||||
} else if (pointed.type == POINTEDTHING_OBJECT) {
|
} else if (pointed.type == POINTEDTHING_OBJECT) {
|
||||||
handlePointingAtObject(pointed, playeritem, player_position, show_debug);
|
handlePointingAtObject(pointed, playeritem, player_position, show_debug);
|
||||||
} else if (isLeftPressed()) {
|
} else if (isLeftPressed()) {
|
||||||
@ -3735,7 +3765,8 @@ void Game::handlePointingAtNothing(const ItemStack &playerItem)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Game::handlePointingAtNode(const PointedThing &pointed, const ItemDefinition &playeritem_def,
|
void Game::handlePointingAtNode(const PointedThing &pointed,
|
||||||
|
const ItemDefinition &playeritem_def, const ItemStack &playeritem,
|
||||||
const ToolCapabilities &playeritem_toolcap, f32 dtime)
|
const ToolCapabilities &playeritem_toolcap, f32 dtime)
|
||||||
{
|
{
|
||||||
v3s16 nodepos = pointed.node_undersurface;
|
v3s16 nodepos = pointed.node_undersurface;
|
||||||
@ -3774,6 +3805,11 @@ void Game::handlePointingAtNode(const PointedThing &pointed, const ItemDefinitio
|
|||||||
|
|
||||||
if (meta && meta->getString("formspec") != "" && !random_input
|
if (meta && meta->getString("formspec") != "" && !random_input
|
||||||
&& !isKeyDown(KeyType::SNEAK)) {
|
&& !isKeyDown(KeyType::SNEAK)) {
|
||||||
|
// Report right click to server
|
||||||
|
if (nodedef_manager->get(map.getNodeNoEx(nodepos)).rightclickable) {
|
||||||
|
client->interact(3, pointed);
|
||||||
|
}
|
||||||
|
|
||||||
infostream << "Launching custom inventory view" << std::endl;
|
infostream << "Launching custom inventory view" << std::endl;
|
||||||
|
|
||||||
InventoryLocation inventoryloc;
|
InventoryLocation inventoryloc;
|
||||||
@ -3796,7 +3832,7 @@ void Game::handlePointingAtNode(const PointedThing &pointed, const ItemDefinitio
|
|||||||
// If the wielded item has node placement prediction,
|
// If the wielded item has node placement prediction,
|
||||||
// make that happen
|
// make that happen
|
||||||
bool placed = nodePlacementPrediction(*client,
|
bool placed = nodePlacementPrediction(*client,
|
||||||
playeritem_def,
|
playeritem_def, playeritem,
|
||||||
nodepos, neighbourpos);
|
nodepos, neighbourpos);
|
||||||
|
|
||||||
if (placed) {
|
if (placed) {
|
||||||
|
@ -51,12 +51,13 @@ extern wchar_t *utf8_to_wide_c(const char *str);
|
|||||||
// The returned string is allocated using new
|
// The returned string is allocated using new
|
||||||
inline const wchar_t *wgettext(const char *str)
|
inline const wchar_t *wgettext(const char *str)
|
||||||
{
|
{
|
||||||
return utf8_to_wide_c(gettext(str));
|
// We must check here that is not an empty string to avoid trying to translate it
|
||||||
|
return str[0] ? utf8_to_wide_c(gettext(str)) : utf8_to_wide_c("");
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string strgettext(const std::string &text)
|
inline std::string strgettext(const std::string &text)
|
||||||
{
|
{
|
||||||
return gettext(text.c_str());
|
return text.empty() ? "" : gettext(text.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -204,8 +204,8 @@ void GUIChatConsole::draw()
|
|||||||
// scale current console height to new window size
|
// scale current console height to new window size
|
||||||
if (m_screensize.Y != 0)
|
if (m_screensize.Y != 0)
|
||||||
m_height = m_height * screensize.Y / m_screensize.Y;
|
m_height = m_height * screensize.Y / m_screensize.Y;
|
||||||
m_desired_height = m_desired_height_fraction * m_screensize.Y;
|
|
||||||
m_screensize = screensize;
|
m_screensize = screensize;
|
||||||
|
m_desired_height = m_desired_height_fraction * m_screensize.Y;
|
||||||
reformatConsole();
|
reformatConsole();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,6 +231,7 @@ void GUIChatConsole::reformatConsole()
|
|||||||
s32 rows = m_desired_height / m_fontsize.Y - 1; // make room for the input prompt
|
s32 rows = m_desired_height / m_fontsize.Y - 1; // make room for the input prompt
|
||||||
if (cols <= 0 || rows <= 0)
|
if (cols <= 0 || rows <= 0)
|
||||||
cols = rows = 0;
|
cols = rows = 0;
|
||||||
|
recalculateConsolePosition();
|
||||||
m_chat_backend->reformat(cols, rows);
|
m_chat_backend->reformat(cols, rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,20 +89,28 @@ video::ITexture* MenuTextureSource::getTexture(const std::string &name, u32 *id)
|
|||||||
{
|
{
|
||||||
if (id)
|
if (id)
|
||||||
*id = 0;
|
*id = 0;
|
||||||
|
|
||||||
if (name.empty())
|
if (name.empty())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
m_to_delete.insert(name);
|
m_to_delete.insert(name);
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
|
video::ITexture *retval = m_driver->findTexture(name.c_str());
|
||||||
|
if (retval)
|
||||||
|
return retval;
|
||||||
|
|
||||||
video::IImage *image = m_driver->createImageFromFile(name.c_str());
|
video::IImage *image = m_driver->createImageFromFile(name.c_str());
|
||||||
if (image) {
|
if (!image)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
image = Align2Npot2(image, m_driver);
|
image = Align2Npot2(image, m_driver);
|
||||||
video::ITexture* retval = m_driver->addTexture(name.c_str(), image);
|
retval = m_driver->addTexture(name.c_str(), image);
|
||||||
image->drop();
|
image->drop();
|
||||||
return retval;
|
return retval;
|
||||||
}
|
#else
|
||||||
#endif
|
|
||||||
return m_driver->getTexture(name.c_str());
|
return m_driver->getTexture(name.c_str());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -3681,19 +3681,25 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
|
|||||||
a->from_i = m_selected_item->i;
|
a->from_i = m_selected_item->i;
|
||||||
m_invmgr->inventoryAction(a);
|
m_invmgr->inventoryAction(a);
|
||||||
} else if (craft_amount > 0) {
|
} else if (craft_amount > 0) {
|
||||||
|
assert(s.isValid());
|
||||||
|
|
||||||
|
// if there are no items selected or the selected item
|
||||||
|
// belongs to craftresult list, proceed with crafting
|
||||||
|
if (m_selected_item == NULL ||
|
||||||
|
!m_selected_item->isValid() || m_selected_item->listname == "craftresult") {
|
||||||
|
|
||||||
m_selected_content_guess = ItemStack(); // Clear
|
m_selected_content_guess = ItemStack(); // Clear
|
||||||
|
|
||||||
// Send IACTION_CRAFT
|
|
||||||
|
|
||||||
assert(s.isValid());
|
|
||||||
assert(inv_s);
|
assert(inv_s);
|
||||||
|
|
||||||
|
// Send IACTION_CRAFT
|
||||||
infostream << "Handing IACTION_CRAFT to manager" << std::endl;
|
infostream << "Handing IACTION_CRAFT to manager" << std::endl;
|
||||||
ICraftAction *a = new ICraftAction();
|
ICraftAction *a = new ICraftAction();
|
||||||
a->count = craft_amount;
|
a->count = craft_amount;
|
||||||
a->craft_inv = s.inventoryloc;
|
a->craft_inv = s.inventoryloc;
|
||||||
m_invmgr->inventoryAction(a);
|
m_invmgr->inventoryAction(a);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If m_selected_amount has been decreased to zero, deselect
|
// If m_selected_amount has been decreased to zero, deselect
|
||||||
if (m_selected_amount == 0) {
|
if (m_selected_amount == 0) {
|
||||||
|
@ -248,6 +248,7 @@ HTTPFetchOngoing::HTTPFetchOngoing(const HTTPFetchRequest &request_,
|
|||||||
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
|
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
|
||||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
|
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||||
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 1);
|
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_ENCODING, "gzip");
|
||||||
|
|
||||||
std::string bind_address = g_settings->get("bind_address");
|
std::string bind_address = g_settings->get("bind_address");
|
||||||
if (!bind_address.empty()) {
|
if (!bind_address.empty()) {
|
||||||
|
22
src/hud.cpp
22
src/hud.cpp
@ -407,24 +407,32 @@ void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture,
|
|||||||
p += offset;
|
p += offset;
|
||||||
|
|
||||||
v2s32 steppos;
|
v2s32 steppos;
|
||||||
|
core::rect<s32> srchalfrect, dsthalfrect;
|
||||||
switch (drawdir) {
|
switch (drawdir) {
|
||||||
case HUD_DIR_RIGHT_LEFT:
|
case HUD_DIR_RIGHT_LEFT:
|
||||||
steppos = v2s32(-1, 0);
|
steppos = v2s32(-1, 0);
|
||||||
|
srchalfrect = core::rect<s32>(srcd.Width / 2, 0, srcd.Width, srcd.Height);
|
||||||
|
dsthalfrect = core::rect<s32>(dstd.Width / 2, 0, dstd.Width, dstd.Height);
|
||||||
break;
|
break;
|
||||||
case HUD_DIR_TOP_BOTTOM:
|
case HUD_DIR_TOP_BOTTOM:
|
||||||
steppos = v2s32(0, 1);
|
steppos = v2s32(0, 1);
|
||||||
|
srchalfrect = core::rect<s32>(0, 0, srcd.Width, srcd.Height / 2);
|
||||||
|
dsthalfrect = core::rect<s32>(0, 0, dstd.Width, dstd.Height / 2);
|
||||||
break;
|
break;
|
||||||
case HUD_DIR_BOTTOM_TOP:
|
case HUD_DIR_BOTTOM_TOP:
|
||||||
steppos = v2s32(0, -1);
|
steppos = v2s32(0, -1);
|
||||||
|
srchalfrect = core::rect<s32>(0, srcd.Height / 2, srcd.Width, srcd.Height);
|
||||||
|
dsthalfrect = core::rect<s32>(0, dstd.Height / 2, dstd.Width, dstd.Height);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
steppos = v2s32(1, 0);
|
steppos = v2s32(1, 0);
|
||||||
|
srchalfrect = core::rect<s32>(0, 0, srcd.Width / 2, srcd.Height);
|
||||||
|
dsthalfrect = core::rect<s32>(0, 0, dstd.Width / 2, dstd.Height);
|
||||||
}
|
}
|
||||||
steppos.X *= dstd.Width;
|
steppos.X *= dstd.Width;
|
||||||
steppos.Y *= dstd.Height;
|
steppos.Y *= dstd.Height;
|
||||||
|
|
||||||
for (s32 i = 0; i < count / 2; i++)
|
for (s32 i = 0; i < count / 2; i++) {
|
||||||
{
|
|
||||||
core::rect<s32> srcrect(0, 0, srcd.Width, srcd.Height);
|
core::rect<s32> srcrect(0, 0, srcd.Width, srcd.Height);
|
||||||
core::rect<s32> dstrect(0,0, dstd.Width, dstd.Height);
|
core::rect<s32> dstrect(0,0, dstd.Width, dstd.Height);
|
||||||
|
|
||||||
@ -433,13 +441,9 @@ void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture,
|
|||||||
p += steppos;
|
p += steppos;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count % 2 == 1)
|
if (count % 2 == 1) {
|
||||||
{
|
dsthalfrect += p;
|
||||||
core::rect<s32> srcrect(0, 0, srcd.Width / 2, srcd.Height);
|
draw2DImageFilterScaled(driver, stat_texture, dsthalfrect, srchalfrect, NULL, colors, true);
|
||||||
core::rect<s32> dstrect(0,0, dstd.Width / 2, dstd.Height);
|
|
||||||
|
|
||||||
dstrect += p;
|
|
||||||
draw2DImageFilterScaled(driver, stat_texture, dstrect, srcrect, NULL, colors, true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1418,14 +1418,14 @@ void intlGUIEditBox::calculateScrollPos()
|
|||||||
// todo: adjust scrollbar
|
// todo: adjust scrollbar
|
||||||
}
|
}
|
||||||
|
|
||||||
// vertical scroll position
|
if (!WordWrap && !MultiLine)
|
||||||
if (FrameRect.LowerRightCorner.Y < CurrentTextRect.LowerRightCorner.Y + VScrollPos)
|
return;
|
||||||
VScrollPos = CurrentTextRect.LowerRightCorner.Y - FrameRect.LowerRightCorner.Y + VScrollPos;
|
|
||||||
|
|
||||||
else if (FrameRect.UpperLeftCorner.Y > CurrentTextRect.UpperLeftCorner.Y + VScrollPos)
|
// vertical scroll position
|
||||||
VScrollPos = CurrentTextRect.UpperLeftCorner.Y - FrameRect.UpperLeftCorner.Y + VScrollPos;
|
if (FrameRect.LowerRightCorner.Y < CurrentTextRect.LowerRightCorner.Y)
|
||||||
else
|
VScrollPos += CurrentTextRect.LowerRightCorner.Y - FrameRect.LowerRightCorner.Y; // scrolling downwards
|
||||||
VScrollPos = 0;
|
else if (FrameRect.UpperLeftCorner.Y > CurrentTextRect.UpperLeftCorner.Y)
|
||||||
|
VScrollPos += CurrentTextRect.UpperLeftCorner.Y - FrameRect.UpperLeftCorner.Y; // scrolling upwards
|
||||||
|
|
||||||
// todo: adjust scrollbar
|
// todo: adjust scrollbar
|
||||||
}
|
}
|
||||||
|
@ -659,7 +659,7 @@ bool InventoryList::roomForItem(const ItemStack &item_) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InventoryList::containsItem(const ItemStack &item) const
|
bool InventoryList::containsItem(const ItemStack &item, bool match_meta) const
|
||||||
{
|
{
|
||||||
u32 count = item.count;
|
u32 count = item.count;
|
||||||
if(count == 0)
|
if(count == 0)
|
||||||
@ -670,8 +670,8 @@ bool InventoryList::containsItem(const ItemStack &item) const
|
|||||||
{
|
{
|
||||||
if(count == 0)
|
if(count == 0)
|
||||||
break;
|
break;
|
||||||
if(i->name == item.name)
|
if (i->name == item.name
|
||||||
{
|
&& (!match_meta || (i->metadata == item.metadata))) {
|
||||||
if (i->count >= count)
|
if (i->count >= count)
|
||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
|
@ -223,9 +223,10 @@ public:
|
|||||||
// Checks whether there is room for a given item
|
// Checks whether there is room for a given item
|
||||||
bool roomForItem(const ItemStack &item) const;
|
bool roomForItem(const ItemStack &item) const;
|
||||||
|
|
||||||
// Checks whether the given count of the given item name
|
// Checks whether the given count of the given item
|
||||||
// exists in this inventory list.
|
// exists in this inventory list.
|
||||||
bool containsItem(const ItemStack &item) const;
|
// If match_meta is false, only the items' names are compared.
|
||||||
|
bool containsItem(const ItemStack &item, bool match_meta) const;
|
||||||
|
|
||||||
// Removes the given count of the given item name from
|
// Removes the given count of the given item name from
|
||||||
// this inventory list. Walks the list in reverse order.
|
// this inventory list. Walks the list in reverse order.
|
||||||
|
@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include <vector3d.h>
|
#include <vector3d.h>
|
||||||
|
|
||||||
typedef core::vector3df v3f;
|
typedef core::vector3df v3f;
|
||||||
|
typedef core::vector3d<double> v3d;
|
||||||
typedef core::vector3d<s16> v3s16;
|
typedef core::vector3d<s16> v3s16;
|
||||||
typedef core::vector3d<u16> v3u16;
|
typedef core::vector3d<u16> v3u16;
|
||||||
typedef core::vector3d<s32> v3s32;
|
typedef core::vector3d<s32> v3s32;
|
||||||
|
@ -13,11 +13,11 @@ void ItemStackMetadata::serialize(std::ostream &os) const
|
|||||||
{
|
{
|
||||||
std::ostringstream os2;
|
std::ostringstream os2;
|
||||||
os2 << DESERIALIZE_START;
|
os2 << DESERIALIZE_START;
|
||||||
for (StringMap::const_iterator
|
for (StringMap::const_iterator it = m_stringvars.begin(); it != m_stringvars.end();
|
||||||
it = m_stringvars.begin();
|
++it) {
|
||||||
it != m_stringvars.end(); ++it) {
|
if (!(*it).first.empty() || !(*it).second.empty())
|
||||||
os2 << it->first << DESERIALIZE_KV_DELIM
|
os2 << (*it).first << DESERIALIZE_KV_DELIM
|
||||||
<< it->second << DESERIALIZE_PAIR_DELIM;
|
<< (*it).second << DESERIALIZE_PAIR_DELIM;
|
||||||
}
|
}
|
||||||
os << serializeJsonStringIfNeeded(os2.str());
|
os << serializeJsonStringIfNeeded(os2.str());
|
||||||
}
|
}
|
||||||
@ -28,7 +28,8 @@ void ItemStackMetadata::deSerialize(std::istream &is)
|
|||||||
|
|
||||||
m_stringvars.clear();
|
m_stringvars.clear();
|
||||||
|
|
||||||
if (!in.empty() && in[0] == DESERIALIZE_START) {
|
if (!in.empty()) {
|
||||||
|
if (in[0] == DESERIALIZE_START) {
|
||||||
Strfnd fnd(in);
|
Strfnd fnd(in);
|
||||||
fnd.to(1);
|
fnd.to(1);
|
||||||
while (!fnd.at_end()) {
|
while (!fnd.at_end()) {
|
||||||
@ -41,3 +42,4 @@ void ItemStackMetadata::deSerialize(std::istream &is)
|
|||||||
m_stringvars[""] = in;
|
m_stringvars[""] = in;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -34,7 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
LocalPlayer::LocalPlayer(Client *client, const char *name):
|
LocalPlayer::LocalPlayer(Client *client, const char *name):
|
||||||
Player(name, client->idef()),
|
Player(name, client->idef()),
|
||||||
parent(0),
|
parent(NULL),
|
||||||
hp(PLAYER_MAX_HP),
|
hp(PLAYER_MAX_HP),
|
||||||
isAttached(false),
|
isAttached(false),
|
||||||
touching_ground(false),
|
touching_ground(false),
|
||||||
@ -53,8 +53,8 @@ LocalPlayer::LocalPlayer(Client *client, const char *name):
|
|||||||
overridePosition(v3f(0,0,0)),
|
overridePosition(v3f(0,0,0)),
|
||||||
last_position(v3f(0,0,0)),
|
last_position(v3f(0,0,0)),
|
||||||
last_speed(v3f(0,0,0)),
|
last_speed(v3f(0,0,0)),
|
||||||
last_pitch(0),
|
last_pitch(0.0f),
|
||||||
last_yaw(0),
|
last_yaw(0.0f),
|
||||||
last_keyPressed(0),
|
last_keyPressed(0),
|
||||||
last_camera_fov(0),
|
last_camera_fov(0),
|
||||||
last_wanted_range(0),
|
last_wanted_range(0),
|
||||||
@ -68,12 +68,11 @@ LocalPlayer::LocalPlayer(Client *client, const char *name):
|
|||||||
hurt_tilt_strength(0.0f),
|
hurt_tilt_strength(0.0f),
|
||||||
m_position(0,0,0),
|
m_position(0,0,0),
|
||||||
m_sneak_node(32767, 32767, 32767),
|
m_sneak_node(32767, 32767, 32767),
|
||||||
m_sneak_node_bb_ymax(0), // To support temporary option for old move code
|
m_sneak_node_bb_top(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f),
|
||||||
m_sneak_node_bb_top(0,0,0,0,0,0),
|
|
||||||
m_sneak_node_exists(false),
|
m_sneak_node_exists(false),
|
||||||
m_need_to_get_new_sneak_node(true),
|
|
||||||
m_sneak_ladder_detected(false),
|
m_sneak_ladder_detected(false),
|
||||||
m_ledge_detected(false),
|
m_sneak_node_bb_ymax(0.0f),
|
||||||
|
m_need_to_get_new_sneak_node(true),
|
||||||
m_old_node_below(32767,32767,32767),
|
m_old_node_below(32767,32767,32767),
|
||||||
m_old_node_below_type("air"),
|
m_old_node_below_type("air"),
|
||||||
m_can_jump(false),
|
m_can_jump(false),
|
||||||
@ -96,91 +95,142 @@ LocalPlayer::~LocalPlayer()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static aabb3f getTopBoundingBox(const std::vector<aabb3f> &nodeboxes)
|
static aabb3f getNodeBoundingBox(const std::vector<aabb3f> &nodeboxes)
|
||||||
{
|
{
|
||||||
|
if (nodeboxes.size() == 0)
|
||||||
|
return aabb3f(0, 0, 0, 0, 0, 0);
|
||||||
|
|
||||||
aabb3f b_max;
|
aabb3f b_max;
|
||||||
b_max.reset(-BS, -BS, -BS);
|
|
||||||
for (std::vector<aabb3f>::const_iterator it = nodeboxes.begin();
|
std::vector<aabb3f>::const_iterator it = nodeboxes.begin();
|
||||||
it != nodeboxes.end(); ++it) {
|
b_max = aabb3f(it->MinEdge, it->MaxEdge);
|
||||||
aabb3f box = *it;
|
|
||||||
if (box.MaxEdge.Y > b_max.MaxEdge.Y)
|
++it;
|
||||||
b_max = box;
|
for (; it != nodeboxes.end(); ++it)
|
||||||
else if (box.MaxEdge.Y == b_max.MaxEdge.Y)
|
b_max.addInternalBox(*it);
|
||||||
b_max.addInternalBox(box);
|
|
||||||
}
|
return b_max;
|
||||||
return aabb3f(v3f(b_max.MinEdge.X, b_max.MaxEdge.Y, b_max.MinEdge.Z), b_max.MaxEdge);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define GETNODE(map, p3, v2, y, valid) \
|
bool LocalPlayer::updateSneakNode(Map *map, const v3f &position,
|
||||||
(map)->getNodeNoEx((p3) + v3s16((v2).X, y, (v2).Y), valid)
|
const v3f &sneak_max)
|
||||||
|
|
||||||
// pos is the node the player is standing inside(!)
|
|
||||||
static bool detectSneakLadder(Map *map, INodeDefManager *nodemgr, v3s16 pos)
|
|
||||||
{
|
{
|
||||||
// Detects a structure known as "sneak ladder" or "sneak elevator"
|
static const v3s16 dir9_center[9] = {
|
||||||
// that relies on bugs to provide a fast means of vertical transportation,
|
v3s16( 0, 0, 0),
|
||||||
// the bugs have since been fixed but this function remains to keep it working.
|
v3s16( 1, 0, 0),
|
||||||
// NOTE: This is just entirely a huge hack and causes way too many problems.
|
v3s16(-1, 0, 0),
|
||||||
bool is_valid_position;
|
v3s16( 0, 0, 1),
|
||||||
|
v3s16( 0, 0, -1),
|
||||||
|
v3s16( 1, 0, 1),
|
||||||
|
v3s16(-1, 0, 1),
|
||||||
|
v3s16( 1, 0, -1),
|
||||||
|
v3s16(-1, 0, -1)
|
||||||
|
};
|
||||||
|
|
||||||
|
INodeDefManager *nodemgr = m_client->ndef();
|
||||||
MapNode node;
|
MapNode node;
|
||||||
// X/Z vectors for 4 neighboring nodes
|
bool is_valid_position;
|
||||||
static const v2s16 vecs[] = { v2s16(-1, 0), v2s16(1, 0), v2s16(0, -1), v2s16(0, 1) };
|
bool new_sneak_node_exists = m_sneak_node_exists;
|
||||||
|
|
||||||
for (u16 i = 0; i < ARRLEN(vecs); i++) {
|
// We want the top of the sneak node to be below the players feet
|
||||||
const v2s16 vec = vecs[i];
|
f32 position_y_mod = 0.05 * BS;
|
||||||
|
if (m_sneak_node_exists)
|
||||||
|
position_y_mod = m_sneak_node_bb_top.MaxEdge.Y - position_y_mod;
|
||||||
|
|
||||||
// walkability of bottom & top node should differ
|
// Get position of current standing node
|
||||||
node = GETNODE(map, pos, vec, 0, &is_valid_position);
|
const v3s16 current_node = floatToInt(position - v3f(0, position_y_mod, 0), BS);
|
||||||
if (!is_valid_position)
|
|
||||||
continue;
|
|
||||||
bool w = nodemgr->get(node).walkable;
|
|
||||||
node = GETNODE(map, pos, vec, 1, &is_valid_position);
|
|
||||||
if (!is_valid_position || w == nodemgr->get(node).walkable)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// check one more node above OR below with corresponding walkability
|
if (current_node != m_sneak_node) {
|
||||||
node = GETNODE(map, pos, vec, -1, &is_valid_position);
|
new_sneak_node_exists = false;
|
||||||
bool ok = is_valid_position && w != nodemgr->get(node).walkable;
|
} else {
|
||||||
if (!ok) {
|
node = map->getNodeNoEx(current_node, &is_valid_position);
|
||||||
node = GETNODE(map, pos, vec, 2, &is_valid_position);
|
if (!is_valid_position || !nodemgr->get(node).walkable)
|
||||||
ok = is_valid_position && w == nodemgr->get(node).walkable;
|
new_sneak_node_exists = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ok)
|
// Keep old sneak node
|
||||||
|
if (new_sneak_node_exists)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
// Get new sneak node
|
||||||
|
m_sneak_ladder_detected = false;
|
||||||
|
f32 min_distance_f = 100000.0 * BS;
|
||||||
|
|
||||||
|
for (s16 d = 0; d < 9; d++) {
|
||||||
|
const v3s16 p = current_node + dir9_center[d];
|
||||||
|
const v3f pf = intToFloat(p, BS);
|
||||||
|
const v2f diff(position.X - pf.X, position.Z - pf.Z);
|
||||||
|
f32 distance_f = diff.getLength();
|
||||||
|
|
||||||
|
if (distance_f > min_distance_f ||
|
||||||
|
fabs(diff.X) > (.5 + .1) * BS + sneak_max.X ||
|
||||||
|
fabs(diff.Y) > (.5 + .1) * BS + sneak_max.Z)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
|
||||||
|
// The node to be sneaked on has to be walkable
|
||||||
|
node = map->getNodeNoEx(p, &is_valid_position);
|
||||||
|
if (!is_valid_position || !nodemgr->get(node).walkable)
|
||||||
|
continue;
|
||||||
|
// And the node(s) above have to be nonwalkable
|
||||||
|
bool ok = true;
|
||||||
|
if (!physics_override_sneak_glitch) {
|
||||||
|
u16 height = ceilf(
|
||||||
|
(m_collisionbox.MaxEdge.Y - m_collisionbox.MinEdge.Y) / BS
|
||||||
|
);
|
||||||
|
for (u16 y = 1; y <= height; y++) {
|
||||||
|
node = map->getNodeNoEx(p + v3s16(0, y, 0), &is_valid_position);
|
||||||
|
if (!is_valid_position || nodemgr->get(node).walkable) {
|
||||||
|
ok = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// legacy behaviour: check just one node
|
||||||
|
node = map->getNodeNoEx(p + v3s16(0, 1, 0), &is_valid_position);
|
||||||
|
ok = is_valid_position && !nodemgr->get(node).walkable;
|
||||||
|
}
|
||||||
|
if (!ok)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
min_distance_f = distance_f;
|
||||||
|
m_sneak_node = p;
|
||||||
|
new_sneak_node_exists = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!new_sneak_node_exists)
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
static bool detectLedge(Map *map, INodeDefManager *nodemgr, v3s16 pos)
|
// Update saved top bounding box of sneak node
|
||||||
{
|
node = map->getNodeNoEx(m_sneak_node);
|
||||||
bool is_valid_position;
|
std::vector<aabb3f> nodeboxes;
|
||||||
MapNode node;
|
node.getCollisionBoxes(nodemgr, &nodeboxes);
|
||||||
// X/Z vectors for 4 neighboring nodes
|
m_sneak_node_bb_top = getNodeBoundingBox(nodeboxes);
|
||||||
static const v2s16 vecs[] = {v2s16(-1, 0), v2s16(1, 0), v2s16(0, -1), v2s16(0, 1)};
|
|
||||||
|
|
||||||
for (u16 i = 0; i < ARRLEN(vecs); i++) {
|
if (physics_override_sneak_glitch) {
|
||||||
const v2s16 vec = vecs[i];
|
// Detect sneak ladder:
|
||||||
|
// Node two meters above sneak node must be solid
|
||||||
node = GETNODE(map, pos, vec, 1, &is_valid_position);
|
node = map->getNodeNoEx(m_sneak_node + v3s16(0, 2, 0),
|
||||||
|
&is_valid_position);
|
||||||
if (is_valid_position && nodemgr->get(node).walkable) {
|
if (is_valid_position && nodemgr->get(node).walkable) {
|
||||||
// Ledge exists
|
// Node three meters above: must be non-solid
|
||||||
node = GETNODE(map, pos, vec, 2, &is_valid_position);
|
node = map->getNodeNoEx(m_sneak_node + v3s16(0, 3, 0),
|
||||||
if (is_valid_position && !nodemgr->get(node).walkable)
|
&is_valid_position);
|
||||||
// Space above ledge exists
|
m_sneak_ladder_detected = is_valid_position &&
|
||||||
|
!nodemgr->get(node).walkable;
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef GETNODE
|
|
||||||
|
|
||||||
void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
|
void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
|
||||||
std::vector<CollisionInfo> *collision_info)
|
std::vector<CollisionInfo> *collision_info)
|
||||||
{
|
{
|
||||||
|
if (!collision_info || collision_info->empty()) {
|
||||||
|
// Node below the feet, update each ClientEnvironment::step()
|
||||||
|
m_standing_node = floatToInt(m_position, BS) - v3s16(0, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// Temporary option for old move code
|
// Temporary option for old move code
|
||||||
if (!physics_override_new_move) {
|
if (!physics_override_new_move) {
|
||||||
old_move(dtime, env, pos_max_d, collision_info);
|
old_move(dtime, env, pos_max_d, collision_info);
|
||||||
@ -193,10 +243,8 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
|
|||||||
v3f position = getPosition();
|
v3f position = getPosition();
|
||||||
|
|
||||||
// Copy parent position if local player is attached
|
// Copy parent position if local player is attached
|
||||||
if(isAttached)
|
if (isAttached) {
|
||||||
{
|
|
||||||
setPosition(overridePosition);
|
setPosition(overridePosition);
|
||||||
m_sneak_node_exists = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,11 +252,11 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
|
|||||||
bool fly_allowed = m_client->checkLocalPrivilege("fly");
|
bool fly_allowed = m_client->checkLocalPrivilege("fly");
|
||||||
bool noclip = m_client->checkLocalPrivilege("noclip") &&
|
bool noclip = m_client->checkLocalPrivilege("noclip") &&
|
||||||
g_settings->getBool("noclip");
|
g_settings->getBool("noclip");
|
||||||
bool free_move = noclip && fly_allowed && g_settings->getBool("free_move");
|
bool free_move = g_settings->getBool("free_move") && fly_allowed;
|
||||||
if (free_move) {
|
|
||||||
|
if (noclip && free_move) {
|
||||||
position += m_speed * dtime;
|
position += m_speed * dtime;
|
||||||
setPosition(position);
|
setPosition(position);
|
||||||
m_sneak_node_exists = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,7 +327,6 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
|
|||||||
|| nodemgr->get(node2.getContent()).climbable) && !free_move;
|
|| nodemgr->get(node2.getContent()).climbable) && !free_move;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Collision uncertainty radius
|
Collision uncertainty radius
|
||||||
Make it a bit larger than the maximum distance of movement
|
Make it a bit larger than the maximum distance of movement
|
||||||
@ -291,28 +338,85 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
|
|||||||
// This should always apply, otherwise there are glitches
|
// This should always apply, otherwise there are glitches
|
||||||
sanity_check(d > pos_max_d);
|
sanity_check(d > pos_max_d);
|
||||||
|
|
||||||
|
// TODO: this shouldn't be hardcoded but transmitted from server
|
||||||
|
float player_stepheight = (touching_ground) ? (BS * 0.6f) : (BS * 0.2f);
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
if (touching_ground)
|
||||||
|
player_stepheight += (0.6f * BS);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
v3f accel_f = v3f(0,0,0);
|
||||||
|
|
||||||
|
collisionMoveResult result = collisionMoveSimple(env, m_client,
|
||||||
|
pos_max_d, m_collisionbox, player_stepheight, dtime,
|
||||||
|
&position, &m_speed, accel_f);
|
||||||
|
|
||||||
|
bool could_sneak = control.sneak && !free_move && !in_liquid &&
|
||||||
|
!is_climbing && physics_override_sneak;
|
||||||
|
|
||||||
|
// Add new collisions to the vector
|
||||||
|
if (collision_info && !free_move) {
|
||||||
|
v3f diff = intToFloat(m_standing_node, BS) - position;
|
||||||
|
f32 distance = diff.getLength();
|
||||||
|
// Force update each ClientEnvironment::step()
|
||||||
|
bool is_first = collision_info->empty();
|
||||||
|
|
||||||
|
for (std::vector<CollisionInfo>::const_iterator
|
||||||
|
colinfo = result.collisions.begin();
|
||||||
|
colinfo != result.collisions.end(); ++colinfo) {
|
||||||
|
collision_info->push_back(*colinfo);
|
||||||
|
|
||||||
|
if (colinfo->type != COLLISION_NODE ||
|
||||||
|
colinfo->new_speed.Y != 0 ||
|
||||||
|
(could_sneak && m_sneak_node_exists))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
diff = intToFloat(colinfo->node_p, BS) - position;
|
||||||
|
|
||||||
|
// Find nearest colliding node
|
||||||
|
f32 len = diff.getLength();
|
||||||
|
if (is_first || len < distance) {
|
||||||
|
m_standing_node = colinfo->node_p;
|
||||||
|
distance = len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
If the player's feet touch the topside of any node, this is
|
||||||
|
set to true.
|
||||||
|
|
||||||
|
Player is allowed to jump when this is true.
|
||||||
|
*/
|
||||||
|
bool touching_ground_was = touching_ground;
|
||||||
|
touching_ground = result.touching_ground;
|
||||||
|
bool sneak_can_jump = false;
|
||||||
|
|
||||||
// Max. distance (X, Z) over border for sneaking determined by collision box
|
// Max. distance (X, Z) over border for sneaking determined by collision box
|
||||||
// * 0.49 to keep the center just barely on the node
|
// * 0.49 to keep the center just barely on the node
|
||||||
v3f sneak_max = m_collisionbox.getExtent() * 0.49;
|
v3f sneak_max = m_collisionbox.getExtent() * 0.49;
|
||||||
|
|
||||||
if (m_sneak_ladder_detected) {
|
if (m_sneak_ladder_detected) {
|
||||||
// restore legacy behaviour (this makes the m_speed.Y hack necessary)
|
// restore legacy behaviour (this makes the m_speed.Y hack necessary)
|
||||||
sneak_max = v3f(0.4 * BS, 0, 0.4 * BS);
|
sneak_max = v3f(0.4 * BS, 0, 0.4 * BS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If sneaking, keep in range from the last walked node and don't
|
If sneaking, keep on top of last walked node and don't fall off
|
||||||
fall off from it
|
|
||||||
*/
|
*/
|
||||||
if (control.sneak && m_sneak_node_exists &&
|
if (could_sneak && m_sneak_node_exists) {
|
||||||
!(fly_allowed && g_settings->getBool("free_move")) &&
|
|
||||||
!in_liquid && !is_climbing &&
|
|
||||||
physics_override_sneak) {
|
|
||||||
const v3f sn_f = intToFloat(m_sneak_node, BS);
|
const v3f sn_f = intToFloat(m_sneak_node, BS);
|
||||||
const v3f bmin = sn_f + m_sneak_node_bb_top.MinEdge;
|
const v3f bmin = sn_f + m_sneak_node_bb_top.MinEdge;
|
||||||
const v3f bmax = sn_f + m_sneak_node_bb_top.MaxEdge;
|
const v3f bmax = sn_f + m_sneak_node_bb_top.MaxEdge;
|
||||||
const v3f old_pos = position;
|
const v3f old_pos = position;
|
||||||
const v3f old_speed = m_speed;
|
const v3f old_speed = m_speed;
|
||||||
|
f32 y_diff = bmax.Y - position.Y;
|
||||||
|
m_standing_node = m_sneak_node;
|
||||||
|
|
||||||
|
// (BS * 0.6f) is the basic stepheight while standing on ground
|
||||||
|
if (y_diff < BS * 0.6f) {
|
||||||
|
// Only center player when they're on the node
|
||||||
position.X = rangelim(position.X,
|
position.X = rangelim(position.X,
|
||||||
bmin.X - sneak_max.X, bmax.X + sneak_max.X);
|
bmin.X - sneak_max.X, bmax.X + sneak_max.X);
|
||||||
position.Z = rangelim(position.Z,
|
position.Z = rangelim(position.Z,
|
||||||
@ -322,18 +426,21 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
|
|||||||
m_speed.X = 0;
|
m_speed.X = 0;
|
||||||
if (position.Z != old_pos.Z)
|
if (position.Z != old_pos.Z)
|
||||||
m_speed.Z = 0;
|
m_speed.Z = 0;
|
||||||
|
|
||||||
// Because we keep the player collision box on the node, limiting
|
|
||||||
// position.Y is not necessary but useful to prevent players from
|
|
||||||
// being inside a node if sneaking on e.g. the lower part of a stair
|
|
||||||
if (!m_sneak_ladder_detected) {
|
|
||||||
position.Y = MYMAX(position.Y, bmax.Y);
|
|
||||||
} else {
|
|
||||||
// legacy behaviour that sometimes causes some weird slow sinking
|
|
||||||
m_speed.Y = MYMAX(m_speed.Y, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (collision_info != NULL &&
|
if (y_diff > 0 && m_speed.Y < 0 &&
|
||||||
|
(physics_override_sneak_glitch || y_diff < BS * 0.6f)) {
|
||||||
|
// Move player to the maximal height when falling or when
|
||||||
|
// the ledge is climbed on the next step.
|
||||||
|
position.Y = bmax.Y;
|
||||||
|
m_speed.Y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow jumping on node edges while sneaking
|
||||||
|
if (m_speed.Y == 0 || m_sneak_ladder_detected)
|
||||||
|
sneak_can_jump = true;
|
||||||
|
|
||||||
|
if (collision_info &&
|
||||||
m_speed.Y - old_speed.Y > BS) {
|
m_speed.Y - old_speed.Y > BS) {
|
||||||
// Collide with sneak node, report fall damage
|
// Collide with sneak node, report fall damage
|
||||||
CollisionInfo sn_info;
|
CollisionInfo sn_info;
|
||||||
@ -344,144 +451,24 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this shouldn't be hardcoded but transmitted from server
|
|
||||||
float player_stepheight = (touching_ground) ? (BS * 0.6f) : (BS * 0.2f);
|
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
|
||||||
player_stepheight += (0.6f * BS);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
v3f accel_f = v3f(0,0,0);
|
|
||||||
|
|
||||||
collisionMoveResult result = collisionMoveSimple(env, m_client,
|
|
||||||
pos_max_d, m_collisionbox, player_stepheight, dtime,
|
|
||||||
&position, &m_speed, accel_f);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If the player's feet touch the topside of any node, this is
|
Find the next sneak node if necessary
|
||||||
set to true.
|
|
||||||
|
|
||||||
Player is allowed to jump when this is true.
|
|
||||||
*/
|
*/
|
||||||
bool touching_ground_was = touching_ground;
|
bool new_sneak_node_exists = false;
|
||||||
touching_ground = result.touching_ground;
|
|
||||||
|
|
||||||
// We want the top of the sneak node to be below the players feet
|
if (could_sneak)
|
||||||
f32 position_y_mod;
|
new_sneak_node_exists = updateSneakNode(map, position, sneak_max);
|
||||||
if (m_sneak_node_exists)
|
|
||||||
position_y_mod = m_sneak_node_bb_top.MaxEdge.Y - 0.05 * BS;
|
|
||||||
else
|
|
||||||
position_y_mod = (0.5 - 0.05) * BS;
|
|
||||||
v3s16 current_node = floatToInt(position - v3f(0, position_y_mod, 0), BS);
|
|
||||||
/*
|
|
||||||
Check the nodes under the player to see from which node the
|
|
||||||
player is sneaking from, if any. If the node from under
|
|
||||||
the player has been removed, the player falls.
|
|
||||||
*/
|
|
||||||
if (m_sneak_node_exists &&
|
|
||||||
nodemgr->get(map->getNodeNoEx(m_old_node_below)).name == "air" &&
|
|
||||||
m_old_node_below_type != "air") {
|
|
||||||
// Old node appears to have been removed; that is,
|
|
||||||
// it wasn't air before but now it is
|
|
||||||
m_need_to_get_new_sneak_node = false;
|
|
||||||
m_sneak_node_exists = false;
|
|
||||||
} else if (nodemgr->get(map->getNodeNoEx(current_node)).name != "air") {
|
|
||||||
// We are on something, so make sure to recalculate the sneak
|
|
||||||
// node.
|
|
||||||
m_need_to_get_new_sneak_node = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_need_to_get_new_sneak_node && physics_override_sneak) {
|
|
||||||
v2f player_p2df(position.X, position.Z);
|
|
||||||
f32 min_distance_f = 100000.0 * BS;
|
|
||||||
v3s16 new_sneak_node = m_sneak_node;
|
|
||||||
for(s16 x=-1; x<=1; x++)
|
|
||||||
for(s16 z=-1; z<=1; z++)
|
|
||||||
{
|
|
||||||
v3s16 p = current_node + v3s16(x,0,z);
|
|
||||||
v3f pf = intToFloat(p, BS);
|
|
||||||
v2f node_p2df(pf.X, pf.Z);
|
|
||||||
f32 distance_f = player_p2df.getDistanceFrom(node_p2df);
|
|
||||||
|
|
||||||
if (distance_f > min_distance_f ||
|
|
||||||
fabs(player_p2df.X-node_p2df.X) > (.5+.1)*BS + sneak_max.X ||
|
|
||||||
fabs(player_p2df.Y-node_p2df.Y) > (.5+.1)*BS + sneak_max.Z)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
|
|
||||||
// The node to be sneaked on has to be walkable
|
|
||||||
node = map->getNodeNoEx(p, &is_valid_position);
|
|
||||||
if (!is_valid_position || !nodemgr->get(node).walkable)
|
|
||||||
continue;
|
|
||||||
// And the node(s) above have to be nonwalkable
|
|
||||||
bool ok = true;
|
|
||||||
if (!physics_override_sneak_glitch) {
|
|
||||||
u16 height = ceilf(
|
|
||||||
(m_collisionbox.MaxEdge.Y - m_collisionbox.MinEdge.Y) / BS
|
|
||||||
);
|
|
||||||
for (u16 y = 1; y <= height; y++) {
|
|
||||||
node = map->getNodeNoEx(p + v3s16(0,y,0), &is_valid_position);
|
|
||||||
if (!is_valid_position || nodemgr->get(node).walkable) {
|
|
||||||
ok = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// legacy behaviour: check just one node
|
|
||||||
node = map->getNodeNoEx(p + v3s16(0,1,0), &is_valid_position);
|
|
||||||
ok = is_valid_position && !nodemgr->get(node).walkable;
|
|
||||||
}
|
|
||||||
if (!ok)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
min_distance_f = distance_f;
|
|
||||||
new_sneak_node = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sneak_node_found = (min_distance_f < 100000.0 * BS);
|
|
||||||
m_sneak_node = new_sneak_node;
|
|
||||||
m_sneak_node_exists = sneak_node_found;
|
|
||||||
|
|
||||||
if (sneak_node_found) {
|
|
||||||
// Update saved top bounding box of sneak node
|
|
||||||
MapNode n = map->getNodeNoEx(m_sneak_node);
|
|
||||||
std::vector<aabb3f> nodeboxes;
|
|
||||||
n.getCollisionBoxes(nodemgr, &nodeboxes);
|
|
||||||
m_sneak_node_bb_top = getTopBoundingBox(nodeboxes);
|
|
||||||
|
|
||||||
m_sneak_ladder_detected = physics_override_sneak_glitch &&
|
|
||||||
detectSneakLadder(map, nodemgr, floatToInt(position, BS));
|
|
||||||
} else {
|
|
||||||
m_sneak_ladder_detected = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
If 'sneak glitch' enabled detect ledge for old sneak-jump
|
|
||||||
behaviour of climbing onto a ledge 2 nodes up.
|
|
||||||
*/
|
|
||||||
if (physics_override_sneak_glitch && control.sneak && control.jump)
|
|
||||||
m_ledge_detected = detectLedge(map, nodemgr, floatToInt(position, BS));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Set new position but keep sneak node set
|
Set new position but keep sneak node set
|
||||||
*/
|
*/
|
||||||
bool sneak_node_exists = m_sneak_node_exists;
|
|
||||||
setPosition(position);
|
setPosition(position);
|
||||||
m_sneak_node_exists = sneak_node_exists;
|
m_sneak_node_exists = new_sneak_node_exists;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Report collisions
|
Report collisions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Dont report if flying
|
|
||||||
if(collision_info && !(g_settings->getBool("free_move") && fly_allowed)) {
|
|
||||||
for(size_t i=0; i<result.collisions.size(); i++) {
|
|
||||||
const CollisionInfo &info = result.collisions[i];
|
|
||||||
collision_info->push_back(info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!result.standing_on_object && !touching_ground_was && touching_ground) {
|
if(!result.standing_on_object && !touching_ground_was && touching_ground) {
|
||||||
MtEvent *e = new SimpleTriggerEvent("PlayerRegainGround");
|
MtEvent *e = new SimpleTriggerEvent("PlayerRegainGround");
|
||||||
m_client->event()->put(e);
|
m_client->event()->put(e);
|
||||||
@ -501,22 +488,15 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Update the node last under the player
|
|
||||||
*/
|
|
||||||
m_old_node_below = floatToInt(position - v3f(0,BS/2,0), BS);
|
|
||||||
m_old_node_below_type = nodemgr->get(map->getNodeNoEx(m_old_node_below)).name;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Check properties of the node on which the player is standing
|
Check properties of the node on which the player is standing
|
||||||
*/
|
*/
|
||||||
const ContentFeatures &f = nodemgr->get(map->getNodeNoEx(getStandingNodePos()));
|
const ContentFeatures &f = nodemgr->get(map->getNodeNoEx(m_standing_node));
|
||||||
// Determine if jumping is possible
|
// Determine if jumping is possible
|
||||||
m_can_jump = touching_ground && !in_liquid;
|
m_can_jump = (touching_ground && !in_liquid && !is_climbing)
|
||||||
|
|| sneak_can_jump;
|
||||||
if (itemgroup_get(f.groups, "disable_jump"))
|
if (itemgroup_get(f.groups, "disable_jump"))
|
||||||
m_can_jump = false;
|
m_can_jump = false;
|
||||||
else if (control.sneak && m_sneak_ladder_detected && !in_liquid && !is_climbing)
|
|
||||||
m_can_jump = true;
|
|
||||||
|
|
||||||
// Jump key pressed while jumping off from a bouncy block
|
// Jump key pressed while jumping off from a bouncy block
|
||||||
if (m_can_jump && control.jump && itemgroup_get(f.groups, "bouncy") &&
|
if (m_can_jump && control.jump && itemgroup_get(f.groups, "bouncy") &&
|
||||||
@ -705,17 +685,8 @@ void LocalPlayer::applyControl(float dtime)
|
|||||||
*/
|
*/
|
||||||
v3f speedJ = getSpeed();
|
v3f speedJ = getSpeed();
|
||||||
if(speedJ.Y >= -0.5 * BS) {
|
if(speedJ.Y >= -0.5 * BS) {
|
||||||
if (m_ledge_detected) {
|
|
||||||
// Limit jump speed to a minimum that allows
|
|
||||||
// jumping up onto a ledge 2 nodes up.
|
|
||||||
speedJ.Y = movement_speed_jump *
|
|
||||||
MYMAX(physics_override_jump, 1.3f);
|
|
||||||
setSpeed(speedJ);
|
|
||||||
m_ledge_detected = false;
|
|
||||||
} else {
|
|
||||||
speedJ.Y = movement_speed_jump * physics_override_jump;
|
speedJ.Y = movement_speed_jump * physics_override_jump;
|
||||||
setSpeed(speedJ);
|
setSpeed(speedJ);
|
||||||
}
|
|
||||||
|
|
||||||
MtEvent *e = new SimpleTriggerEvent("PlayerJump");
|
MtEvent *e = new SimpleTriggerEvent("PlayerJump");
|
||||||
m_client->event()->put(e);
|
m_client->event()->put(e);
|
||||||
@ -772,7 +743,7 @@ v3s16 LocalPlayer::getStandingNodePos()
|
|||||||
{
|
{
|
||||||
if(m_sneak_node_exists)
|
if(m_sneak_node_exists)
|
||||||
return m_sneak_node;
|
return m_sneak_node;
|
||||||
return floatToInt(getPosition() - v3f(0, BS, 0), BS);
|
return m_standing_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
v3s16 LocalPlayer::getFootstepNodePos()
|
v3s16 LocalPlayer::getFootstepNodePos()
|
||||||
|
@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "environment.h"
|
#include "environment.h"
|
||||||
|
#include "constants.h"
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
class Client;
|
class Client;
|
||||||
@ -46,6 +47,8 @@ public:
|
|||||||
|
|
||||||
ClientActiveObject *parent;
|
ClientActiveObject *parent;
|
||||||
|
|
||||||
|
// Initialize hp to 0, so that no hearts will be shown if server
|
||||||
|
// doesn't support health points
|
||||||
u16 hp;
|
u16 hp;
|
||||||
bool isAttached;
|
bool isAttached;
|
||||||
bool touching_ground;
|
bool touching_ground;
|
||||||
@ -108,7 +111,7 @@ public:
|
|||||||
|
|
||||||
void setCAO(GenericCAO *toset)
|
void setCAO(GenericCAO *toset)
|
||||||
{
|
{
|
||||||
assert(m_cao == NULL); // Pre-condition
|
assert(!m_cao); // Pre-condition
|
||||||
m_cao = toset;
|
m_cao = toset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,30 +143,31 @@ public:
|
|||||||
private:
|
private:
|
||||||
void accelerateHorizontal(const v3f &target_speed, const f32 max_increase);
|
void accelerateHorizontal(const v3f &target_speed, const f32 max_increase);
|
||||||
void accelerateVertical(const v3f &target_speed, const f32 max_increase);
|
void accelerateVertical(const v3f &target_speed, const f32 max_increase);
|
||||||
|
bool updateSneakNode(Map *map, const v3f &position, const v3f &sneak_max);
|
||||||
|
|
||||||
v3f m_position;
|
v3f m_position;
|
||||||
|
v3s16 m_standing_node;
|
||||||
|
|
||||||
v3s16 m_sneak_node;
|
v3s16 m_sneak_node;
|
||||||
// Stores the max player uplift by m_sneak_node
|
|
||||||
// To support temporary option for old move code
|
|
||||||
f32 m_sneak_node_bb_ymax;
|
|
||||||
// Stores the top bounding box of m_sneak_node
|
// Stores the top bounding box of m_sneak_node
|
||||||
aabb3f m_sneak_node_bb_top;
|
aabb3f m_sneak_node_bb_top;
|
||||||
// Whether the player is allowed to sneak
|
// Whether the player is allowed to sneak
|
||||||
bool m_sneak_node_exists;
|
bool m_sneak_node_exists;
|
||||||
// Whether recalculation of m_sneak_node and its top bbox is needed
|
|
||||||
bool m_need_to_get_new_sneak_node;
|
|
||||||
// Whether a "sneak ladder" structure is detected at the players pos
|
// Whether a "sneak ladder" structure is detected at the players pos
|
||||||
// see detectSneakLadder() in the .cpp for more info (always false if disabled)
|
// see detectSneakLadder() in the .cpp for more info (always false if disabled)
|
||||||
bool m_sneak_ladder_detected;
|
bool m_sneak_ladder_detected;
|
||||||
// Whether a 2-node-up ledge is detected at the players pos,
|
|
||||||
// see detectLedge() in the .cpp for more info (always false if disabled).
|
|
||||||
bool m_ledge_detected;
|
|
||||||
|
|
||||||
|
// ***** Variables for temporary option of the old move code *****
|
||||||
|
// Stores the max player uplift by m_sneak_node
|
||||||
|
f32 m_sneak_node_bb_ymax;
|
||||||
|
// Whether recalculation of m_sneak_node and its top bbox is needed
|
||||||
|
bool m_need_to_get_new_sneak_node;
|
||||||
// Node below player, used to determine whether it has been removed,
|
// Node below player, used to determine whether it has been removed,
|
||||||
// and its old type
|
// and its old type
|
||||||
v3s16 m_old_node_below;
|
v3s16 m_old_node_below;
|
||||||
std::string m_old_node_below_type;
|
std::string m_old_node_below_type;
|
||||||
|
// ***** End of variables for temporary option *****
|
||||||
|
|
||||||
bool m_can_jump;
|
bool m_can_jump;
|
||||||
u16 m_breath;
|
u16 m_breath;
|
||||||
f32 m_yaw;
|
f32 m_yaw;
|
||||||
|
@ -347,13 +347,10 @@ void StringBuffer::push_back(char c)
|
|||||||
flush(std::string(buffer, buffer_index));
|
flush(std::string(buffer, buffer_index));
|
||||||
buffer_index = 0;
|
buffer_index = 0;
|
||||||
} else {
|
} else {
|
||||||
int index = buffer_index;
|
buffer[buffer_index++] = c;
|
||||||
buffer[index++] = c;
|
if (buffer_index >= BUFFER_LENGTH) {
|
||||||
if (index >= BUFFER_LENGTH) {
|
|
||||||
flush(std::string(buffer, buffer_index));
|
flush(std::string(buffer, buffer_index));
|
||||||
buffer_index = 0;
|
buffer_index = 0;
|
||||||
} else {
|
|
||||||
buffer_index = index;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1378,11 +1378,6 @@ s16 ServerMap::getWaterLevel()
|
|||||||
return getMapgenParams()->water_level;
|
return getMapgenParams()->water_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ServerMap::saoPositionOverLimit(const v3f &p)
|
|
||||||
{
|
|
||||||
return getMapgenParams()->saoPosOverLimit(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ServerMap::blockpos_over_mapgen_limit(v3s16 p)
|
bool ServerMap::blockpos_over_mapgen_limit(v3s16 p)
|
||||||
{
|
{
|
||||||
const s16 mapgen_limit_bp = rangelim(
|
const s16 mapgen_limit_bp = rangelim(
|
||||||
@ -2737,6 +2732,7 @@ void MMVManip::blitBackAll(std::map<v3s16, MapBlock*> *modified_blocks,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
block->copyFrom(*this);
|
block->copyFrom(*this);
|
||||||
|
block->raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_VMANIP);
|
||||||
|
|
||||||
if(modified_blocks)
|
if(modified_blocks)
|
||||||
(*modified_blocks)[p] = block;
|
(*modified_blocks)[p] = block;
|
||||||
|
@ -377,8 +377,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
ServerMapSector *createSector(v2s16 p);
|
ServerMapSector *createSector(v2s16 p);
|
||||||
|
|
||||||
bool saoPositionOverLimit(const v3f &p);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Blocks are generated by using these and makeBlock().
|
Blocks are generated by using these and makeBlock().
|
||||||
*/
|
*/
|
||||||
|
@ -122,7 +122,8 @@ public:
|
|||||||
#define MOD_REASON_STATIC_DATA_REMOVED (1 << 16)
|
#define MOD_REASON_STATIC_DATA_REMOVED (1 << 16)
|
||||||
#define MOD_REASON_STATIC_DATA_CHANGED (1 << 17)
|
#define MOD_REASON_STATIC_DATA_CHANGED (1 << 17)
|
||||||
#define MOD_REASON_EXPIRE_DAYNIGHTDIFF (1 << 18)
|
#define MOD_REASON_EXPIRE_DAYNIGHTDIFF (1 << 18)
|
||||||
#define MOD_REASON_UNKNOWN (1 << 19)
|
#define MOD_REASON_VMANIP (1 << 19)
|
||||||
|
#define MOD_REASON_UNKNOWN (1 << 20)
|
||||||
|
|
||||||
////
|
////
|
||||||
//// MapBlock itself
|
//// MapBlock itself
|
||||||
|
@ -809,7 +809,16 @@ void MapgenBasic::dustTopNodes()
|
|||||||
}
|
}
|
||||||
|
|
||||||
content_t c = vm->m_data[vi].getContent();
|
content_t c = vm->m_data[vi].getContent();
|
||||||
if (!ndef->get(c).buildable_to && c != CONTENT_IGNORE && c != biome->c_dust) {
|
NodeDrawType dtype = ndef->get(c).drawtype;
|
||||||
|
// Only place on walkable cubic non-liquid nodes
|
||||||
|
// Dust check needed due to vertical overgeneration
|
||||||
|
if ((dtype == NDT_NORMAL ||
|
||||||
|
dtype == NDT_ALLFACES_OPTIONAL ||
|
||||||
|
dtype == NDT_GLASSLIKE_FRAMED_OPTIONAL ||
|
||||||
|
dtype == NDT_GLASSLIKE ||
|
||||||
|
dtype == NDT_GLASSLIKE_FRAMED ||
|
||||||
|
dtype == NDT_ALLFACES) &&
|
||||||
|
ndef->get(c).walkable && c != biome->c_dust) {
|
||||||
vm->m_area.add_y(em, vi, 1);
|
vm->m_area.add_y(em, vi, 1);
|
||||||
vm->m_data[vi] = MapNode(biome->c_dust);
|
vm->m_data[vi] = MapNode(biome->c_dust);
|
||||||
}
|
}
|
||||||
@ -973,8 +982,7 @@ bool GenerateNotifier::addEvent(GenNotifyType type, v3s16 pos, u32 id)
|
|||||||
|
|
||||||
|
|
||||||
void GenerateNotifier::getEvents(
|
void GenerateNotifier::getEvents(
|
||||||
std::map<std::string, std::vector<v3s16> > &event_map,
|
std::map<std::string, std::vector<v3s16> > &event_map)
|
||||||
bool peek_events)
|
|
||||||
{
|
{
|
||||||
std::list<GenNotifyEvent>::iterator it;
|
std::list<GenNotifyEvent>::iterator it;
|
||||||
|
|
||||||
@ -986,8 +994,11 @@ void GenerateNotifier::getEvents(
|
|||||||
|
|
||||||
event_map[name].push_back(gn.pos);
|
event_map[name].push_back(gn.pos);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!peek_events)
|
|
||||||
|
void GenerateNotifier::clearEvents()
|
||||||
|
{
|
||||||
m_notify_events.clear();
|
m_notify_events.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1049,16 +1060,15 @@ void MapgenParams::writeParams(Settings *settings) const
|
|||||||
bparams->writeParams(settings);
|
bparams->writeParams(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate edges of outermost generated mapchunks (less than
|
|
||||||
// 'mapgen_limit'), and corresponding exact limits for SAO entities.
|
// Calculate exact edges of the outermost mapchunks that are within the
|
||||||
|
// set 'mapgen_limit'.
|
||||||
void MapgenParams::calcMapgenEdges()
|
void MapgenParams::calcMapgenEdges()
|
||||||
{
|
{
|
||||||
// Central chunk offset, in blocks
|
// Central chunk offset, in blocks
|
||||||
s16 ccoff_b = -chunksize / 2;
|
s16 ccoff_b = -chunksize / 2;
|
||||||
|
|
||||||
// Chunksize, in nodes
|
// Chunksize, in nodes
|
||||||
s32 csize_n = chunksize * MAP_BLOCKSIZE;
|
s32 csize_n = chunksize * MAP_BLOCKSIZE;
|
||||||
|
|
||||||
// Minp/maxp of central chunk, in nodes
|
// Minp/maxp of central chunk, in nodes
|
||||||
s16 ccmin = ccoff_b * MAP_BLOCKSIZE;
|
s16 ccmin = ccoff_b * MAP_BLOCKSIZE;
|
||||||
s16 ccmax = ccmin + csize_n - 1;
|
s16 ccmax = ccmin + csize_n - 1;
|
||||||
@ -1077,25 +1087,17 @@ void MapgenParams::calcMapgenEdges()
|
|||||||
s16 numcmin = MYMAX((ccfmin - mapgen_limit_min) / csize_n, 0);
|
s16 numcmin = MYMAX((ccfmin - mapgen_limit_min) / csize_n, 0);
|
||||||
s16 numcmax = MYMAX((mapgen_limit_max - ccfmax) / csize_n, 0);
|
s16 numcmax = MYMAX((mapgen_limit_max - ccfmax) / csize_n, 0);
|
||||||
// Mapgen edges, in nodes
|
// Mapgen edges, in nodes
|
||||||
// These values may be useful later as additional class members
|
mapgen_edge_min = ccmin - numcmin * csize_n;
|
||||||
s16 mapgen_edge_min = ccmin - numcmin * csize_n;
|
mapgen_edge_max = ccmax + numcmax * csize_n;
|
||||||
s16 mapgen_edge_max = ccmax + numcmax * csize_n;
|
|
||||||
// SAO position limits, in Irrlicht units
|
m_mapgen_edges_calculated = true;
|
||||||
m_sao_limit_min = mapgen_edge_min * BS - 3.0f;
|
|
||||||
m_sao_limit_max = mapgen_edge_max * BS + 3.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool MapgenParams::saoPosOverLimit(const v3f &p)
|
s32 MapgenParams::getSpawnRangeMax()
|
||||||
{
|
{
|
||||||
if (!m_sao_limit_calculated) {
|
if (!m_mapgen_edges_calculated)
|
||||||
calcMapgenEdges();
|
calcMapgenEdges();
|
||||||
m_sao_limit_calculated = true;
|
|
||||||
}
|
return MYMIN(-mapgen_edge_min, mapgen_edge_max);
|
||||||
return p.X < m_sao_limit_min ||
|
|
||||||
p.X > m_sao_limit_max ||
|
|
||||||
p.Y < m_sao_limit_min ||
|
|
||||||
p.Y > m_sao_limit_max ||
|
|
||||||
p.Z < m_sao_limit_min ||
|
|
||||||
p.Z > m_sao_limit_max;
|
|
||||||
}
|
}
|
||||||
|
21
src/mapgen.h
21
src/mapgen.h
@ -101,8 +101,8 @@ public:
|
|||||||
void setNotifyOnDecoIds(std::set<u32> *notify_on_deco_ids);
|
void setNotifyOnDecoIds(std::set<u32> *notify_on_deco_ids);
|
||||||
|
|
||||||
bool addEvent(GenNotifyType type, v3s16 pos, u32 id=0);
|
bool addEvent(GenNotifyType type, v3s16 pos, u32 id=0);
|
||||||
void getEvents(std::map<std::string, std::vector<v3s16> > &event_map,
|
void getEvents(std::map<std::string, std::vector<v3s16> > &event_map);
|
||||||
bool peek_events=false);
|
void clearEvents();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
u32 m_notify_on;
|
u32 m_notify_on;
|
||||||
@ -131,6 +131,9 @@ struct MapgenParams {
|
|||||||
|
|
||||||
BiomeParams *bparams;
|
BiomeParams *bparams;
|
||||||
|
|
||||||
|
s16 mapgen_edge_min;
|
||||||
|
s16 mapgen_edge_max;
|
||||||
|
|
||||||
MapgenParams() :
|
MapgenParams() :
|
||||||
mgtype(MAPGEN_DEFAULT),
|
mgtype(MAPGEN_DEFAULT),
|
||||||
chunksize(5),
|
chunksize(5),
|
||||||
@ -139,9 +142,10 @@ struct MapgenParams {
|
|||||||
mapgen_limit(MAX_MAP_GENERATION_LIMIT),
|
mapgen_limit(MAX_MAP_GENERATION_LIMIT),
|
||||||
flags(MG_CAVES | MG_LIGHT | MG_DECORATIONS),
|
flags(MG_CAVES | MG_LIGHT | MG_DECORATIONS),
|
||||||
bparams(NULL),
|
bparams(NULL),
|
||||||
m_sao_limit_min(MAX_MAP_GENERATION_LIMIT * BS),
|
|
||||||
m_sao_limit_max(MAX_MAP_GENERATION_LIMIT * BS),
|
mapgen_edge_min(-MAX_MAP_GENERATION_LIMIT),
|
||||||
m_sao_limit_calculated(false)
|
mapgen_edge_max(MAX_MAP_GENERATION_LIMIT),
|
||||||
|
m_mapgen_edges_calculated(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,13 +154,12 @@ struct MapgenParams {
|
|||||||
virtual void readParams(const Settings *settings);
|
virtual void readParams(const Settings *settings);
|
||||||
virtual void writeParams(Settings *settings) const;
|
virtual void writeParams(Settings *settings) const;
|
||||||
|
|
||||||
bool saoPosOverLimit(const v3f &p);
|
s32 getSpawnRangeMax();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void calcMapgenEdges();
|
void calcMapgenEdges();
|
||||||
|
|
||||||
float m_sao_limit_min;
|
bool m_mapgen_edges_calculated;
|
||||||
float m_sao_limit_max;
|
|
||||||
bool m_sao_limit_calculated;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -57,13 +57,17 @@ MapgenV7::MapgenV7(int mapgenid, MapgenV7Params *params, EmergeManager *emerge)
|
|||||||
this->spflags = params->spflags;
|
this->spflags = params->spflags;
|
||||||
this->cave_width = params->cave_width;
|
this->cave_width = params->cave_width;
|
||||||
this->float_mount_density = params->float_mount_density;
|
this->float_mount_density = params->float_mount_density;
|
||||||
this->float_mount_height = params->float_mount_height;
|
|
||||||
this->floatland_level = params->floatland_level;
|
this->floatland_level = params->floatland_level;
|
||||||
this->shadow_limit = params->shadow_limit;
|
this->shadow_limit = params->shadow_limit;
|
||||||
this->cavern_limit = params->cavern_limit;
|
this->cavern_limit = params->cavern_limit;
|
||||||
this->cavern_taper = params->cavern_taper;
|
this->cavern_taper = params->cavern_taper;
|
||||||
this->cavern_threshold = params->cavern_threshold;
|
this->cavern_threshold = params->cavern_threshold;
|
||||||
|
|
||||||
|
// This is to avoid a divide-by-zero.
|
||||||
|
// Parameter will be saved to map_meta.txt in limited form.
|
||||||
|
params->float_mount_height = MYMAX(params->float_mount_height, 1.0f);
|
||||||
|
this->float_mount_height = params->float_mount_height;
|
||||||
|
|
||||||
// 2D noise
|
// 2D noise
|
||||||
noise_terrain_base = new Noise(¶ms->np_terrain_base, seed, csize.X, csize.Z);
|
noise_terrain_base = new Noise(¶ms->np_terrain_base, seed, csize.X, csize.Z);
|
||||||
noise_terrain_alt = new Noise(¶ms->np_terrain_alt, seed, csize.X, csize.Z);
|
noise_terrain_alt = new Noise(¶ms->np_terrain_alt, seed, csize.X, csize.Z);
|
||||||
@ -376,7 +380,8 @@ float MapgenV7::baseTerrainLevelFromMap(int index)
|
|||||||
|
|
||||||
bool MapgenV7::getMountainTerrainAtPoint(s16 x, s16 y, s16 z)
|
bool MapgenV7::getMountainTerrainAtPoint(s16 x, s16 y, s16 z)
|
||||||
{
|
{
|
||||||
float mnt_h_n = NoisePerlin2D(&noise_mount_height->np, x, z, seed);
|
float mnt_h_n =
|
||||||
|
MYMAX(NoisePerlin2D(&noise_mount_height->np, x, z, seed), 1.0f);
|
||||||
float density_gradient = -((float)y / mnt_h_n);
|
float density_gradient = -((float)y / mnt_h_n);
|
||||||
float mnt_n = NoisePerlin3D(&noise_mountain->np, x, y, z, seed);
|
float mnt_n = NoisePerlin3D(&noise_mountain->np, x, y, z, seed);
|
||||||
|
|
||||||
@ -386,7 +391,7 @@ bool MapgenV7::getMountainTerrainAtPoint(s16 x, s16 y, s16 z)
|
|||||||
|
|
||||||
bool MapgenV7::getMountainTerrainFromMap(int idx_xyz, int idx_xz, s16 y)
|
bool MapgenV7::getMountainTerrainFromMap(int idx_xyz, int idx_xz, s16 y)
|
||||||
{
|
{
|
||||||
float mounthn = noise_mount_height->result[idx_xz];
|
float mounthn = MYMAX(noise_mount_height->result[idx_xz], 1.0f);
|
||||||
float density_gradient = -((float)y / mounthn);
|
float density_gradient = -((float)y / mounthn);
|
||||||
float mountn = noise_mountain->result[idx_xyz];
|
float mountn = noise_mountain->result[idx_xyz];
|
||||||
|
|
||||||
@ -415,7 +420,8 @@ void MapgenV7::floatBaseExtentFromMap(s16 *float_base_min, s16 *float_base_max,
|
|||||||
|
|
||||||
float n_base = noise_floatland_base->result[idx_xz];
|
float n_base = noise_floatland_base->result[idx_xz];
|
||||||
if (n_base > 0.0f) {
|
if (n_base > 0.0f) {
|
||||||
float n_base_height = noise_float_base_height->result[idx_xz];
|
float n_base_height =
|
||||||
|
MYMAX(noise_float_base_height->result[idx_xz], 1.0f);
|
||||||
float amp = n_base * n_base_height;
|
float amp = n_base * n_base_height;
|
||||||
float ridge = n_base_height / 3.0f;
|
float ridge = n_base_height / 3.0f;
|
||||||
base_min = floatland_level - amp / 1.5f;
|
base_min = floatland_level - amp / 1.5f;
|
||||||
|
@ -251,16 +251,13 @@ void transformNodeBox(const MapNode &n, const NodeBox &nodebox,
|
|||||||
facedir&=0x03;
|
facedir&=0x03;
|
||||||
for (std::vector<aabb3f>::const_iterator
|
for (std::vector<aabb3f>::const_iterator
|
||||||
i = fixed.begin();
|
i = fixed.begin();
|
||||||
i != fixed.end(); ++i)
|
i != fixed.end(); ++i) {
|
||||||
{
|
|
||||||
aabb3f box = *i;
|
aabb3f box = *i;
|
||||||
|
|
||||||
if (nodebox.type == NODEBOX_LEVELED) {
|
if (nodebox.type == NODEBOX_LEVELED)
|
||||||
box.MaxEdge.Y = -BS/2 + BS*((float)1/LEVELED_MAX) * n.getLevel(nodemgr);
|
box.MaxEdge.Y = (-0.5f + n.getLevel(nodemgr) / 64.0f) * BS;
|
||||||
}
|
|
||||||
|
|
||||||
switch (axisdir)
|
switch (axisdir) {
|
||||||
{
|
|
||||||
case 0:
|
case 0:
|
||||||
if(facedir == 1)
|
if(facedir == 1)
|
||||||
{
|
{
|
||||||
|
@ -103,8 +103,8 @@ enum Rotation {
|
|||||||
|
|
||||||
#define LIQUID_INFINITY_MASK 0x80 //0b10000000
|
#define LIQUID_INFINITY_MASK 0x80 //0b10000000
|
||||||
|
|
||||||
// mask for param2, now as for liquid
|
// mask for leveled nodebox param2
|
||||||
#define LEVELED_MASK 0x3F
|
#define LEVELED_MASK 0x7F
|
||||||
#define LEVELED_MAX LEVELED_MASK
|
#define LEVELED_MAX LEVELED_MASK
|
||||||
|
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user