Compare commits

..

16 Commits
5.2.0 ... 5.0.1

Author SHA1 Message Date
sfan5
76325d0ba9 Bump version to 5.0.1 2019-03-31 22:57:45 +02:00
rubenwardy
cf1802a6de Prevent multi-line chat messages server-side (#8420) 2019-03-28 21:49:03 +00:00
sfan5
538a7b12bd Fix texture rotation for wallmounted nodeboxes
fixes #8358
2019-03-19 22:37:11 +01:00
sfan5
57e0f52aaa httpfetch: Disable IPv6 here too if requested by settings (#8399) 2019-03-19 02:18:34 +00:00
Paramat
1ae0335b62 num_emerge_threads: Initialise value to cope with setting syntax error (#8396) 2019-03-19 02:18:26 +00:00
paramat
ca1bff6b66 num_emerge_threads: Fix documentation of automatic selection 2019-03-19 02:18:17 +00:00
Paramat
10cc62d2ca num_emerge_threads: Warn of crashes when > 1 (#8357) 2019-03-14 17:58:19 +00:00
rubenwardy
dd451a8a00 Fix cast from const by accessing string data directly (#8354)
Fixes #8327
2019-03-12 20:25:55 +00:00
rubenwardy
444ec1e412 HPChange Reason: Fix push after free, and type being overwritten (#8359)
* HPChange Reason: Fix push after free, and type being overwritten

Fixes #8227 and #8344
2019-03-12 20:25:48 +00:00
Paramat
82739f4d7d Change 'num_emerge_threads' default to 1 (#8303) 2019-03-11 22:07:19 +00:00
sofar
19825d853e getS16NoEx() returns true unless syntactical error in conf. (#8304)
The getS16NoEx() handler will return true unless there is a
`[num_emerge_threads]` line in the `minetest.conf` at which
point the excption handler part is reached. Due to the fact that
`defaultsettings.cpp` has a default value set for this setting,
that never will happen.

Because of this, the code will never check the number of threads on
the system, and keep `nthreads = 0`. If that happens, the value is
changed to `1` and only 1 emerge thread will be used.

The default should be set to `1` instead, due to the potential unsafe
consequences for the standard sqlite map files, but that should be a
separate commit that also adds documentation for that setting. This
commit focuses on removing this `hiding` bug instead.
2019-03-11 22:07:19 +00:00
rubenwardy
d8ece2e3e9 Fix serialization of std::time_t by casting to u64 first (#8353)
Fixes #8332
2019-03-11 22:07:19 +00:00
Paramat
bf4deb0ce6 Confirm registration GUI: Remove positional strings to fix Windows bug (#8258)
Positional strings don't work on some Windows builds.
Remove server address string, leave player name string present.
2019-03-11 22:07:19 +00:00
rubenwardy
da4739a26c Fix detach inventory serialisation (#8331) 2019-03-11 22:07:19 +00:00
rubenwardy
fc24bf0915 Fix incorrect string length check after cast 2019-03-11 22:07:19 +00:00
rubenwardy
9329b99cba Continue with 5.0.1-dev 2019-03-11 22:07:12 +00:00
455 changed files with 44413 additions and 115386 deletions

View File

@@ -13,7 +13,6 @@ BraceWrapping:
AfterUnion: true
BeforeCatch: false
BeforeElse: false
FixNamespaceComments: false
AllowShortIfStatementsOnASingleLine: false
IndentCaseLabels: false
AccessModifierOffset: -8

View File

@@ -1,5 +1,4 @@
Checks: '-*,modernize-use-emplace,modernize-avoid-bind,misc-throw-by-value-catch-by-reference,misc-unconventional-assign-operator,performance-*'
WarningsAsErrors: '-*,modernize-use-emplace,performance-type-promotion-in-math-fn,performance-faster-string-find,performance-implicit-cast-in-loop'
Checks: '-*,modernize-use-emplace,modernize-use-default-member-init,modernize-use-equals-delete,modernize-use-equals-default,modernize-return-braced-init-list,modernize-loop-convert,modernize-avoid-bind,misc-throw-by-value-catch-by-reference,misc-string-compare,misc-inefficient-algorithm,misc-inaccurate-erase,misc-incorrect-roundings,misc-unconventional-assign-operator,bugprone-suspicious-memset-usage,performance-*'
CheckOptions:
- key: performance-unnecessary-value-param.AllowedTypes
value: v[23]f;v[23][su](16|32)
- key: modernize-use-default-member-init.UseAssignment
value: True

View File

@@ -1,11 +1,10 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: Unconfirmed bug
assignees: ''
---
##### Issue type
<!-- Pick one below and delete others -->
- Bug report
- Feature request
- Documentation issue
- Build issue
##### Minetest version
<!--
Paste Minetest version between quotes below

View File

@@ -1,25 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: Feature request
assignees: ''
---
## Problem
A clear and concise description of what the problem is.
ie: Why is this needed?
Ex. I'm always frustrated when [...]
## Solutions
A clear and concise description of what you want to happen.
## Alternatives
A clear and concise description of any alternative solutions or features you've considered.
## Additional context
Add any other context or screenshots about the feature request here.

View File

@@ -1,19 +0,0 @@
Add compact, short information about your PR for easier understanding:
- Goal of the PR
- How does the PR work?
- Does it resolve any reported issue?
- If not a bug fix, why is this PR needed? What usecases does it solve?
## To do
This PR is a Work in Progress / Ready for Review.
<!-- ^ delete one -->
- [ ] List
- [ ] Things
- [ ] To do
## How to test
<!-- Example code or instructions -->

20
.github/SECURITY.md vendored
View File

@@ -1,20 +0,0 @@
# Security Policy
## Supported Versions
We only support the latest stable version for security issues.
See the [releases page](https://github.com/minetest/minetest/releases).
## Reporting a Vulnerability
We ask that you report vulnerabilities privately, by contacting a core developer,
to give us time to fix them. You can do that by emailing one of the following addresses:
* celeron55@gmail.com
* rubenwardy@minetest.net
Depending on severity, we will either create a private issue for the vulnerability
and release a patch version of Minetest, or give you permission to file the issue publicly.
For more information on the justification of this policy, see
[Responsible Disclosure](https://en.wikipedia.org/wiki/Responsible_disclosure).

16
.gitignore vendored
View File

@@ -1,4 +1,4 @@
## Editors and development environments
## Editors and Development environments
*~
*.swp
*.bak*
@@ -21,13 +21,11 @@
tags
!tags/
gtags.files
.idea
.idea/*
# Codelite
*.project
# Visual Studio Code
.vscode/
## Files related to Minetest development cycle
## Files related to minetest development cycle
/*.patch
*.diff
# GNU Patch reject file
@@ -55,9 +53,8 @@ gtags.files
## Configuration/log files
minetest.conf
debug.txt
debug.txt.1
## Other files generated by Minetest
## Other files generated by minetest
screenshot_*.png
testbm.txt
@@ -66,11 +63,6 @@ doc/Doxyfile
doc/html/
doc/doxygen_*
## MkDocs files
public/
doc/mkdocs/docs/*.md
doc/mkdocs/mkdocs.yml
## Build files
CMakeFiles
Makefile

View File

@@ -239,13 +239,13 @@ build:fedora-24:
##
.generic_win_template: &generic_win_template
image: ubuntu:bionic
image: ubuntu:xenial
before_script:
- apt-get update -y
- apt-get install -y wget xz-utils unzip git cmake gettext
- wget -q http://minetest.kitsunemimi.pw/mingw-w64-${WIN_ARCH}_9.2.0_ubuntu18.04.tar.xz -O mingw.tar.xz
- apt-get install -y p7zip-full wget unzip git cmake gettext
- wget http://minetest.kitsunemimi.pw/mingw-w64-${WIN_ARCH}_7.1.1_ubuntu14.04.7z -O mingw.7z > /dev/null
- sed -e "s|%PREFIX%|${WIN_ARCH}-w64-mingw32|" -e "s|%ROOTPATH%|/usr/${WIN_ARCH}-w64-mingw32|" < util/travis/toolchain_mingw.cmake.in > ${TOOLCHAIN_OUTPUT}
- tar -xaf mingw.tar.xz -C /usr
- 7z x -y -o/usr mingw.7z > /dev/null
.build_win_template: &build_win_template
<<: *generic_win_template
@@ -322,19 +322,3 @@ package:docker:
- docker push ${CONTAINER_IMAGE}/server:$CI_COMMIT_SHA
- docker push ${CONTAINER_IMAGE}/server:$CI_COMMIT_REF_NAME
- docker push ${CONTAINER_IMAGE}/server:latest
pages:
stage: deploy
image: python:3.7
before_script:
- pip install pip==18.1
- pip install git+https://github.com/Python-Markdown/markdown.git
- pip install git+https://github.com/mkdocs/mkdocs.git
- pip install pygments
script:
- cd doc/mkdocs && ./build.sh
artifacts:
paths:
- public
only:
- master

View File

@@ -1,74 +0,0 @@
unused_args = false
allow_defined_top = true
ignore = {
"131", -- Unused global variable
"431", -- Shadowing an upvalue
"432", -- Shadowing an upvalue argument
}
read_globals = {
"ItemStack",
"INIT",
"DIR_DELIM",
"dump", "dump2",
"fgettext", "fgettext_ne",
"vector",
"VoxelArea",
"profiler",
"Settings",
string = {fields = {"split", "trim"}},
table = {fields = {"copy", "getn", "indexof", "insert_all"}},
math = {fields = {"hypot"}},
}
globals = {
"core",
"gamedata",
os = { fields = { "tempfolder" } },
"_",
}
files["builtin/client/register.lua"] = {
globals = {
debug = {fields={"getinfo"}},
}
}
files["builtin/common/misc_helpers.lua"] = {
globals = {
"dump", "dump2", "table", "math", "string",
"fgettext", "fgettext_ne", "basic_dump", "game", -- ???
"file_exists", "get_last_folder", "cleanup_path", -- ???
},
}
files["builtin/common/vector.lua"] = {
globals = { "vector" },
}
files["builtin/game/voxelarea.lua"] = {
globals = { "VoxelArea" },
}
files["builtin/game/init.lua"] = {
globals = { "profiler" },
}
files["builtin/common/filterlist.lua"] = {
globals = {
"filterlist",
"compare_worlds", "sort_worlds_alphabetic", "sort_mod_list", -- ???
},
}
files["builtin/mainmenu"] = {
globals = {
"gamedata",
},
read_globals = {
"PLATFORM",
},
}

View File

@@ -1,8 +1,8 @@
language: cpp
before_install: ./util/travis/before_install.sh
script: ./util/travis/script.sh
os: linux
dist: bionic
sudo: required
dist: trusty
group: edge
notifications:
email: false
@@ -10,50 +10,49 @@ matrix:
fast_finish: true
include:
- env: CLANG_FORMAT=clang-format-8
- env: LINT=1
compiler: clang
os: linux
addons:
apt:
packages: ['clang-format-8']
packages: ['clang-format-5.0']
sources: &sources
- llvm-toolchain-trusty-5.0
- name: "Builtin Luacheck and Unit Tests"
language: generic
compiler: null
os: linux
addons:
apt:
packages:
- luarocks
before_install:
- luarocks install --local luacheck
- luarocks install --local busted
script:
- $HOME/.luarocks/bin/luacheck builtin
- $HOME/.luarocks/bin/busted builtin
- env: CLANG_TIDY=clang-tidy-8
- env: CLANG_TIDY=1
compiler: clang
os: linux
script: ./util/travis/clangtidy.sh
addons:
apt:
packages: ['clang-tidy-8']
packages: ['clang-tidy-5.0']
sources: &sources
- llvm-toolchain-trusty-5.0
- name: "MinGW cross-compiler (32-bit)"
env: PLATFORM=Win32
- env: PLATFORM=Win32
compiler: gcc
os: linux
addons:
apt:
packages: ['gcc-mingw-w64-i686', 'g++-mingw-w64-i686', 'binutils-mingw-w64-i686']
sources: &sources
- ubuntu-toolchain-r-test
- sourceline: 'deb http://mirrors.kernel.org/ubuntu xenial main universe'
- name: "MinGW cross-compiler (64-bit)"
env: PLATFORM=Win64
- env: PLATFORM=Win64
compiler: gcc
os: linux
addons:
apt:
packages: ['gcc-mingw-w64-x86-64', 'g++-mingw-w64-x86-64', 'binutils-mingw-w64-x86-64']
sources: &sources
- ubuntu-toolchain-r-test
- sourceline: 'deb http://mirrors.kernel.org/ubuntu xenial main universe'
# - env: PLATFORM=Unix
# compiler: clang
# os: osx
# osx_image: xcode8
- env: PLATFORM=Unix
compiler: clang
os: osx
osx_image: xcode8
- env: PLATFORM=Unix COMPILER=gcc-6
compiler: gcc
@@ -61,38 +60,50 @@ matrix:
addons:
apt:
packages: ['gcc-6', 'g++-6']
sources: &sources
- ubuntu-toolchain-r-test
- env: PLATFORM=Unix COMPILER=gcc-8
- env: PLATFORM=Unix COMPILER=gcc-7
compiler: gcc
os: linux
addons:
apt:
packages: ['gcc-8', 'g++-8']
packages: ['gcc-7', 'g++-7']
sources: &sources
- ubuntu-toolchain-r-test
- env: PLATFORM=Unix COMPILER=clang-3.9
- env: PLATFORM=Unix COMPILER=clang-3.6
compiler: clang
os: linux
addons:
apt:
packages: ['clang-3.9']
packages: ['clang-3.6', 'clang++-3.6']
sources: &sources
- llvm-toolchain-trusty-3.6
- env: PLATFORM=Unix COMPILER=clang-9
- env: PLATFORM=Unix COMPILER=clang-5.0
compiler: clang
os: linux
addons:
apt:
packages: ['clang-9']
packages: ['clang-5.0', 'clang++-5.0']
sources: &sources
- llvm-toolchain-trusty-5.0
- env: PLATFORM=Unix COMPILER=clang-9 FREETYPE=0
- env: PLATFORM=Unix COMPILER=clang-5.0 FREETYPE=0
compiler: clang
os: linux
addons:
apt:
packages: ['clang-9']
packages: ['clang-5.0', 'clang++-5.0']
sources: &sources
- llvm-toolchain-trusty-5.0
- env: PLATFORM=Unix COMPILER=clang-9 VALGRIND=1
- env: PLATFORM=Unix COMPILER=clang-5.0 VALGRIND=1
compiler: clang
os: linux
addons:
apt:
packages: ['valgrind', 'clang-9']
packages: ['valgrind', 'clang-5.0', 'clang++-5.0']
sources: &sources
- llvm-toolchain-trusty-5.0

View File

@@ -16,8 +16,8 @@ set(CLANG_MINIMUM_VERSION "3.4")
# Also remember to set PROTOCOL_VERSION in network/networkprotocol.h when releasing
set(VERSION_MAJOR 5)
set(VERSION_MINOR 2)
set(VERSION_PATCH 0)
set(VERSION_MINOR 0)
set(VERSION_PATCH 1)
set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string")
# Change to false for releases
@@ -172,16 +172,16 @@ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/games/minimal" DESTINATION "${SHA
if(BUILD_CLIENT)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/client/shaders" DESTINATION "${SHAREDIR}/client")
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/textures/base/pack" DESTINATION "${SHAREDIR}/textures/base")
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/fonts" DESTINATION "${SHAREDIR}")
if(RUN_IN_PLACE)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/clientmods" DESTINATION "${SHAREDIR}")
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/client/serverlist" DESTINATION "${SHAREDIR}/client")
endif()
endif()
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/fonts" DESTINATION "${SHAREDIR}")
install(FILES "README.md" DESTINATION "${DOCDIR}" COMPONENT "Docs")
install(FILES "doc/lua_api.txt" DESTINATION "${DOCDIR}" COMPONENT "Docs")
install(FILES "doc/client_lua_api.txt" DESTINATION "${DOCDIR}" COMPONENT "Docs")
install(FILES "doc/menu_lua_api.txt" DESTINATION "${DOCDIR}" COMPONENT "Docs")
install(FILES "doc/texture_packs.txt" DESTINATION "${DOCDIR}" COMPONENT "Docs")
install(FILES "doc/world_format.txt" DESTINATION "${DOCDIR}" COMPONENT "Docs")
@@ -232,7 +232,7 @@ add_subdirectory(src)
# CPack
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A free open-source voxel game engine with easy modding and game creation.")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "An InfiniMiner/Minecraft inspired game")
set(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${VERSION_PATCH})

View File

@@ -3,7 +3,9 @@ FROM debian:stretch
USER root
RUN apt-get update -y && \
apt-get -y install build-essential libirrlicht-dev cmake libbz2-dev libpng-dev libjpeg-dev \
libsqlite3-dev libcurl4-gnutls-dev zlib1g-dev libgmp-dev libjsoncpp-dev git
libsqlite3-dev libcurl4-gnutls-dev zlib1g-dev libgmp-dev libjsoncpp-dev git && \
apt-get clean && rm -rf /var/cache/apt/archives/* && \
rm -rf /var/lib/apt/lists/*
COPY . /usr/src/minetest
@@ -14,8 +16,7 @@ RUN mkdir -p /usr/src/minetest/cmakebuild && cd /usr/src/minetest/cmakebuild &&
-DENABLE_SYSTEM_JSONCPP=1 \
.. && \
make -j2 && \
rm -Rf ../games/minetest_game && git clone --depth 1 https://github.com/minetest/minetest_game ../games/minetest_game && \
rm -Rf ../games/minetest_game/.git && \
rm -Rf ../games/minetest_game && git clone https://github.com/minetest/minetest_game ../games/minetest_game && \
make install
FROM debian:stretch
@@ -24,9 +25,7 @@ USER root
RUN groupadd minetest && useradd -m -g minetest -d /var/lib/minetest minetest && \
apt-get update -y && \
apt-get -y install libcurl3-gnutls libjsoncpp1 liblua5.1-0 libluajit-5.1-2 libpq5 libsqlite3-0 \
libstdc++6 zlib1g libc6 && \
apt-get clean && rm -rf /var/cache/apt/archives/* && \
rm -rf /var/lib/apt/lists/*
libstdc++6 zlib1g libc6
WORKDIR /var/lib/minetest

290
README.md
View File

@@ -7,11 +7,11 @@ Minetest
Minetest is a free open-source voxel game engine with easy modding and game creation.
Copyright (C) 2010-2019 Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2010-2018 Perttu Ahola <celeron55@gmail.com>
and contributors (see source file comments and the version control log)
In case you downloaded the source code
--------------------------------------
In case you downloaded the source code:
---------------------------------------
If you downloaded the Minetest Engine source code in which this file is
contained, you probably want to download the [Minetest Game](https://github.com/minetest/minetest_game/)
project too. See its README.txt for more information.
@@ -65,7 +65,7 @@ Some can be changed in the key config dialog in the settings tab.
| + | Increase view range |
| - | Decrease view range |
| K | Enable/disable fly mode (needs fly privilege) |
| P | Enable/disable pitch move mode |
| L | Enable/disable pitch move mode |
| J | Enable/disable fast mode (needs fast privilege) |
| H | Enable/disable noclip mode (needs noclip privilege) |
| E | Move fast in fast mode |
@@ -92,13 +92,13 @@ Locations:
Where each location is on each platform:
* Windows .zip / RUN_IN_PLACE source:
* `bin` = `bin`
* `share` = `.`
* `user` = `.`
* bin = `bin`
* share = `.`
* user = `.`
* Windows installed:
* `bin` = `C:\Program Files\Minetest\bin (Depends on the install location)`
* `share` = `C:\Program Files\Minetest (Depends on the install location)`
* `user` = `%APPDATA%\Minetest`
* $bin = `C:\Program Files\Minetest\bin (Depends on the install location)`
* $share = `C:\Program Files\Minetest (Depends on the install location)`
* $user = `%Appdata%\Minetest`
* Linux installed:
* `bin` = `/usr/bin`
* `share` = `/usr/share/minetest`
@@ -110,18 +110,18 @@ Where each location is on each platform:
Worlds can be found as separate folders in: `user/worlds/`
Configuration file
------------------
Configuration file:
-------------------
- Default location:
`user/minetest.conf`
- This file is created by closing Minetest for the first time.
- It is created by Minetest when it is ran the first time.
- A specific file can be specified on the command line:
`--config <path-to-file>`
- A run-in-place build will look for the configuration file in
`location_of_exe/../minetest.conf` and also `location_of_exe/../../minetest.conf`
Command-line options
--------------------
Command-line options:
---------------------
- Use `--help`
Compiling
@@ -140,21 +140,13 @@ Compiling
| GMP | 5.0.0+ | Bundled mini-GMP is used if not present |
| JsonCPP | 1.0.0+ | Bundled JsonCPP is used if not present |
For Debian/Ubuntu users:
For Debian/Ubuntu:
sudo apt install g++ make libc6-dev libirrlicht-dev cmake libbz2-dev libpng-dev libjpeg-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev libjsoncpp-dev
sudo apt install build-essential libirrlicht-dev cmake libbz2-dev libpng-dev libjpeg-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev libjsoncpp-dev
For Fedora users:
sudo dnf install make automake gcc gcc-c++ kernel-devel cmake libcurl-devel openal-soft-devel libvorbis-devel libXxf86vm-devel libogg-devel freetype-devel mesa-libGL-devel zlib-devel jsoncpp-devel irrlicht-devel bzip2-libs gmp-devel sqlite-devel luajit-devel leveldb-devel ncurses-devel doxygen spatialindex-devel bzip2-devel
For Arch users:
sudo pacman -S base-devel libcurl-gnutls cmake libxxf86vm irrlicht libpng sqlite libogg libvorbis openal freetype2 jsoncpp gmp luajit leveldb ncurses
For Alpine users:
sudo apk add build-base irrlicht-dev cmake bzip2-dev libpng-dev jpeg-dev libxxf86vm-dev mesa-dev sqlite-dev libogg-dev libvorbis-dev openal-soft-dev curl-dev freetype-dev zlib-dev gmp-dev jsoncpp-dev luajit-dev
#### Download
@@ -196,21 +188,21 @@ Download minetest_game, without using Git:
Build a version that runs directly from the source directory:
cmake . -DRUN_IN_PLACE=TRUE
make -j$(nproc)
make -j <number of processors>
Run it:
./bin/minetest
- Use `cmake . -LH` to see all CMake options and their current state.
- Use `cmake . -LH` to see all CMake options and their current state
- If you want to install it system-wide (or are making a distribution package),
you will want to use `-DRUN_IN_PLACE=FALSE`.
- You can build a bare server by specifying `-DBUILD_SERVER=TRUE`.
- You can disable the client build by specifying `-DBUILD_CLIENT=FALSE`.
- You can select between Release and Debug build by `-DCMAKE_BUILD_TYPE=<Debug or Release>`.
- Debug build is slower, but gives much more useful output in a debugger.
- If you build a bare server you don't need to have Irrlicht installed.
- In that case use `-DIRRLICHT_SOURCE_DIR=/the/irrlicht/source`.
you will want to use `-DRUN_IN_PLACE=FALSE`
- You can build a bare server by specifying `-DBUILD_SERVER=TRUE`
- You can disable the client build by specifying `-DBUILD_CLIENT=FALSE`
- You can select between Release and Debug build by `-DCMAKE_BUILD_TYPE=<Debug or Release>`
- Debug build is slower, but gives much more useful output in a debugger
- If you build a bare server, you don't need to have Irrlicht installed.
- In that case use `-DIRRLICHT_SOURCE_DIR=/the/irrlicht/source`
### CMake options
@@ -228,7 +220,7 @@ General options and their default values:
ENABLE_CURSES=ON - Build with (n)curses; Enables a server side terminal (command line option: --terminal)
ENABLE_FREETYPE=ON - Build with FreeType2; Allows using TTF fonts
ENABLE_GETTEXT=ON - Build with Gettext; Allows using translations
ENABLE_GLES=OFF - Build for OpenGL ES instead of OpenGL (requires support by Irrlicht)
ENABLE_GLES=OFF - Search for Open GLES headers & libraries and use them
ENABLE_LEVELDB=ON - Build with LevelDB; Enables use of LevelDB map backend
ENABLE_POSTGRESQL=ON - Build with libpq; Enables use of PostgreSQL map backend (PostgreSQL 9.5 or greater recommended)
ENABLE_REDIS=ON - Build with libhiredis; Enables use of Redis map backend
@@ -267,7 +259,7 @@ Library specific options:
LEVELDB_LIBRARY - Only when building with LevelDB; path to libleveldb.a/libleveldb.so/libleveldb.dll.a
LEVELDB_DLL - Only when building with LevelDB on Windows; path to libleveldb.dll
PostgreSQL_INCLUDE_DIR - Only when building with PostgreSQL; directory that contains libpq-fe.h
PostgreSQL_LIBRARY - Only when building with PostgreSQL; path to libpq.a/libpq.so/libpq.lib
POSTGRESQL_LIBRARY - Only when building with PostgreSQL; path to libpq.a/libpq.so
REDIS_INCLUDE_DIR - Only when building with Redis; directory that contains hiredis.h
REDIS_LIBRARY - Only when building with Redis; path to libhiredis.a/libhiredis.so
SPATIAL_INCLUDE_DIR - Only when building with LibSpatial; directory that contains spatialindex/SpatialIndex.h
@@ -292,93 +284,183 @@ Library specific options:
VORBIS_LIBRARY - Only if building with sound; path to libvorbis.a/libvorbis.so/libvorbis.dll.a
XXF86VM_LIBRARY - Only on Linux; path to libXXf86vm.a/libXXf86vm.so
ZLIB_DLL - Only on Windows; path to zlib1.dll
ZLIBWAPI_DLL - Only on Windows; path to zlibwapi.dll
ZLIB_INCLUDE_DIR - Directory that contains zlib.h
ZLIB_LIBRARY - Path to libz.a/libz.so/zlib.lib
ZLIB_LIBRARY - Path to libz.a/libz.so/zlibwapi.lib
### Compiling on Windows
### Requirements
* This section is outdated. In addition to what is described here:
* In addition to minetest, you need to download [minetest_game](https://github.com/minetest/minetest_game).
* If you wish to have sound support, you need libogg, libvorbis and libopenal
- [Visual Studio 2015 or newer](https://visualstudio.microsoft.com)
- [CMake](https://cmake.org/download/)
- [vcpkg](https://github.com/Microsoft/vcpkg)
- [Git](https://git-scm.com/downloads)
* You need:
* CMake:
http://www.cmake.org/cmake/resources/software.html
* A compiler
* MinGW: http://www.mingw.org/
* or Visual Studio: http://msdn.microsoft.com/en-us/vstudio/default
* Irrlicht SDK 1.7:
http://irrlicht.sourceforge.net/downloads.html
* Zlib headers (zlib125.zip)
http://www.winimage.com/zLibDll/index.html
* Zlib library (zlibwapi.lib and zlibwapi.dll from zlib125dll.zip):
http://www.winimage.com/zLibDll/index.html
* SQLite3 headers and library
https://www.sqlite.org/download.html
* Optional: gettext library and tools:
http://gnuwin32.sourceforge.net/downlinks/gettext.php
* This is used for other UI languages. Feel free to leave it out.
* And, of course, Minetest:
http://minetest.net/download
* Steps:
* Select a directory called DIR hereafter in which you will operate.
* Make sure you have CMake and a compiler installed.
* Download all the other stuff to DIR and extract them into there.
("extract here", not "extract to packagename/")
* NOTE: zlib125dll.zip needs to be extracted into zlib125dll
* NOTE: You need to extract sqlite3.h & sqlite3ext.h from the SQLite 3
source and sqlite3.dll & sqlite3.def from the SQLite 3 precompiled
binaries into "sqlite3" directory, and generate sqlite3.lib using
command "LIB /DEF:sqlite3.def /OUT:sqlite3.lib"
* All those packages contain a nice base directory in them, which
should end up being the direct subdirectories of DIR.
* You will end up with a directory structure like this (+=dir, -=file):
-----------------
+ DIR
* zlib-1.2.5.tar.gz
* zlib125dll.zip
* irrlicht-1.8.3.zip
* sqlite-amalgamation-3130000.zip (SQLite3 headers)
* sqlite-dll-win32-x86-3130000.zip (SQLite3 library for 32bit system)
* 110214175330.zip (or whatever, this is the minetest source)
+ zlib-1.2.5
* zlib.h
+ win32
...
+ zlib125dll
* readme.txt
+ dll32
...
+ irrlicht-1.8.3
+ lib
+ include
...
+ sqlite3
sqlite3.h
sqlite3ext.h
sqlite3.lib
sqlite3.dll
+ gettext (optional)
+bin
+include
+lib
+ minetest
+ src
+ doc
* CMakeLists.txt
...
-----------------
* Start up the CMake GUI
* Select "Browse Source..." and select DIR/minetest
* Now, if using MSVC:
* Select "Browse Build..." and select DIR/minetest-build
* Else if using MinGW:
* Select "Browse Build..." and select DIR/minetest
* Select "Configure"
* Select your compiler
* It will warn about missing stuff, ignore that at this point. (later don't)
* Make sure the configuration is as follows
(note that the versions may differ for you):
### Compiling and installing the dependencies
BUILD_CLIENT [X]
BUILD_SERVER [ ]
CMAKE_BUILD_TYPE Release
CMAKE_INSTALL_PREFIX DIR/minetest-install
IRRLICHT_SOURCE_DIR DIR/irrlicht-1.8.3
RUN_IN_PLACE [X]
WARN_ALL [ ]
ZLIB_DLL DIR/zlib125dll/dll32/zlibwapi.dll
ZLIB_INCLUDE_DIR DIR/zlib-1.2.5
ZLIB_LIBRARIES DIR/zlib125dll/dll32/zlibwapi.lib
GETTEXT_BIN_DIR DIR/gettext/bin
GETTEXT_INCLUDE_DIR DIR/gettext/include
GETTEXT_LIBRARIES DIR/gettext/lib/intl.lib
GETTEXT_MSGFMT DIR/gettext/bin/msgfmt
It is highly recommended to use vcpkg as package manager.
* If CMake complains it couldn't find SQLITE3, choose "Advanced" box on the
right top corner, then specify the location of SQLITE3_INCLUDE_DIR and
SQLITE3_LIBRARY manually.
* If you want to build 64-bit minetest, you will need to build 64-bit version
of irrlicht engine manually, as only 32-bit pre-built library is provided.
* Hit "Configure"
* Hit "Configure" once again 8)
* If something is still coloured red, you have a problem.
* Hit "Generate"
If using MSVC:
* Open the generated minetest.sln
* The project defaults to the "Debug" configuration. Make very sure to
select "Release", unless you want to debug some stuff (it's slower
and might not even work at all)
* Build the ALL_BUILD project
* Build the INSTALL project
* You should now have a working game with the executable in
DIR/minetest-install/bin/minetest.exe
* Additionally you may create a zip package by building the PACKAGE
project.
If using MinGW:
* Using the command line, browse to the build directory and run 'make'
(or mingw32-make or whatever it happens to be)
* You may need to copy some of the downloaded DLLs into bin/, see what
running the produced executable tells you it doesn't have.
* You should now have a working game with the executable in
DIR/minetest/bin/minetest.exe
#### a) Using vcpkg to install dependencies
### Bat script to build Windows releases of Minetest
After you successfully built vcpkg you can easily install the required libraries:
```powershell
vcpkg install irrlicht zlib curl[winssl] openal-soft libvorbis libogg sqlite3 freetype luajit --triplet x64-windows
```
This is how we build Windows releases.
- `curl` is optional, but required to read the serverlist, `curl[winssl]` is required to use the content store.
- `openal-soft`, `libvorbis` and `libogg` are optional, but required to use sound.
- `freetype` is optional, it allows true-type font rendering.
- `luajit` is optional, it replaces the integrated Lua interpreter with a faster just-in-time interpreter.
set sourcedir=%CD%
set installpath="C:\tmp\minetest_install"
set irrlichtpath="C:\tmp\irrlicht-1.7.2"
There are other optional libraries, but they are not tested if they can build and link correctly.
set builddir=%sourcedir%\bvc10
mkdir %builddir%
pushd %builddir%
cmake %sourcedir% -G "Visual Studio 10" -DIRRLICHT_SOURCE_DIR=%irrlichtpath% -DRUN_IN_PLACE=TRUE -DCMAKE_INSTALL_PREFIX=%installpath%
if %errorlevel% neq 0 goto fail
"C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" ALL_BUILD.vcxproj /p:Configuration=Release
if %errorlevel% neq 0 goto fail
"C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" INSTALL.vcxproj /p:Configuration=Release
if %errorlevel% neq 0 goto fail
"C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" PACKAGE.vcxproj /p:Configuration=Release
if %errorlevel% neq 0 goto fail
popd
echo Finished.
exit /b 0
Use `--triplet` to specify the target triplet, e.g. `x64-windows` or `x86-windows`.
:fail
popd
echo Failed.
exit /b 1
#### b) Compile the dependencies on your own
This is outdated and not recommended. Follow the instructions on https://dev.minetest.net/Build_Win32_Minetest_including_all_required_libraries#VS2012_Build
### Compile Minetest
#### a) Using the vcpkg toolchain and CMake GUI
1. Start up the CMake GUI
2. Select **Browse Source...** and select DIR/minetest
3. Select **Browse Build...** and select DIR/minetest-build
4. Select **Configure**
5. Choose the right visual Studio version and target platform. It has to match the version of the installed dependencies
6. Choose **Specify toolchain file for cross-compiling**
7. Click **Next**
8. Select the vcpkg toolchain file e.g. `D:/vcpkg/scripts/buildsystems/vcpkg.cmake`
9. Click Finish
10. Wait until cmake have generated the cash file
11. If there are any errors, solve them and hit **Configure**
12. Click **Generate**
13. Click **Open Project**
14. Compile Minetest inside Visual studio.
#### b) Using the vcpkg toolchain and the commandline
Run the following script in PowerShell:
```powershell
cmake . -G"Visual Studio 15 2017 Win64" -DCMAKE_TOOLCHAIN_FILE=D:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_GETTEXT=0 -DENABLE_CURSES=0
cmake --build . --config Release
```
Make sure that the right compiler is selected and the path to the vcpkg toolchain is correct.
#### c) Using your own compiled libraries
**This is outdated and not recommended**
Follow the instructions on https://dev.minetest.net/Build_Win32_Minetest_including_all_required_libraries#VS2012_Build
### Windows Installer using WiX Toolset
### Windows Installer using WIX Toolset
Requirements:
* [Visual Studio 2017](https://visualstudio.microsoft.com/)
* [WiX Toolset](https://wixtoolset.org/)
* Visual Studio 2017
* Wix Toolset
In the Visual Studio 2017 Installer select **Optional Features -> WiX Toolset**.
In Visual Studio 2017 Installer select "Optional Features" -> "Wix Toolset"
Build the binaries as described above, but make sure you unselect `RUN_IN_PLACE`.
Build the binaries like described above, but make sure you unselect "RUN_IN_PLACE".
Open the generated project file with Visual Studio. Right-click **Package** and choose **Generate**.
Open the generated Project file with VS. Right click "PACKAGE" and choose "Generate".
It may take some minutes to generate the installer.
Docker
------
We provide Minetest server Docker images using the GitLab mirror registry.
We provide Minetest server docker images using the Gitlab mirror registry.
Images are built on each commit and available using the following tag scheme:
@@ -386,20 +468,20 @@ Images are built on each commit and available using the following tag scheme:
* `registry.gitlab.com/minetest/minetest/server:<branch/tag>` (current branch or current tag)
* `registry.gitlab.com/minetest/minetest/server:<commit-id>` (current commit id)
If you want to test it on a Docker server you can easily run:
If you want to test it on a docker server, you can easily run:
sudo docker run registry.gitlab.com/minetest/minetest/server:<docker tag>
If you want to use it in a production environment you should use volumes bound to the Docker host
If you want to use it in a production environment you should use volumes bound to the docker host
to persist data and modify the configuration:
sudo docker create -v /home/minetest/data/:/var/lib/minetest/ -v /home/minetest/conf/:/etc/minetest/ registry.gitlab.com/minetest/minetest/server:master
Data will be written to `/home/minetest/data` on the host, and configuration will be read from `/home/minetest/conf/minetest.conf`.
**Note:** If you don't understand the previous commands please read the official Docker documentation before use.
Note: If you don't understand the previous commands, please read the official Docker documentation before use.
You can also host your Minetest server inside a Kubernetes cluster. See our example implementation in [`misc/kubernetes.yml`](misc/kubernetes.yml).
You can also host your minetest server inside a Kubernetes cluster. See our example implementation in `misc/kubernetes.yml`.
Version scheme

View File

@@ -112,7 +112,7 @@ FREETYPE_TIMESTAMP = $(FREETYPE_DIR)timestamp
FREETYPE_TIMESTAMP_INT = $(ANDR_ROOT)/deps/freetype_timestamp
FREETYPE_URL_GIT = https://github.com/cdave1/freetype2-android
ICONV_VERSION = 1.16
ICONV_VERSION = 1.14
ICONV_DIR = $(ANDR_ROOT)/deps/libiconv/
ICONV_LIB = $(ICONV_DIR)/lib/.libs/libiconv.so
ICONV_TIMESTAMP = $(ICONV_DIR)timestamp
@@ -445,6 +445,9 @@ iconv_download :
tar -xzf libiconv-${ICONV_VERSION}.tar.gz || exit 1; \
rm libiconv-${ICONV_VERSION}.tar.gz; \
ln -s libiconv-${ICONV_VERSION} libiconv; \
cd ${ICONV_DIR}; \
patch -p1 < ${ANDR_ROOT}/patches/libiconv_android.patch; \
patch -p1 < ${ANDR_ROOT}/patches/libiconv_stdio.patch; \
fi
iconv : $(ICONV_LIB)

View File

@@ -1,16 +1,16 @@
buildscript {
repositories {
google()
maven { url 'https://maven.google.com' }
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.1'
classpath 'com.android.tools.build:gradle:3.1.3'
}
}
allprojects {
repositories {
google()
maven { url 'https://maven.google.com' }
jcenter()
}
}
@@ -24,29 +24,24 @@ def sqlite3_version = "3240000"
apply plugin: "com.android.application"
android {
compileSdkVersion 29
buildToolsVersion '29.0.2'
compileSdkVersion 28
buildToolsVersion "28.0.3"
defaultConfig {
versionCode 26
versionCode 24
versionName "${System.env.VERSION_STR}.${versionCode}"
minSdkVersion 14
targetSdkVersion 29
targetSdkVersion 28
applicationId "net.minetest.minetest"
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'
abiFilters 'armeabi-v7a', 'x86', 'arm64-v8a'
abiFilters 'armeabi-v7a', 'x86'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
lintOptions {
disable "OldTargetApi", "GoogleAppIndexingWarning"
}
@@ -171,5 +166,5 @@ task cleanAll(type: Delete, dependsOn: [clean, cleanAssets, cleanIconv,
}
dependencies {
implementation 'androidx.core:core:1.1.0'
implementation 'com.android.support:support-v4:28.0.0'
}

View File

@@ -1,2 +0,0 @@
android.enableJetifier=true
android.useAndroidX=true

View File

@@ -1 +1,6 @@
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
#Mon Oct 15 00:47:03 CEST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip

View File

@@ -65,7 +65,6 @@ endif
LOCAL_CFLAGS := -D_IRR_ANDROID_PLATFORM_ \
-DHAVE_TOUCHSCREENGUI \
-DENABLE_GLES=1 \
-DUSE_CURL=1 \
-DUSE_SOUND=1 \
-DUSE_FREETYPE=1 \
@@ -178,25 +177,14 @@ LOCAL_SRC_FILES := \
jni/src/filesys.cpp \
jni/src/genericobject.cpp \
jni/src/gettext.cpp \
jni/src/gui/guiAnimatedImage.cpp \
jni/src/gui/guiBackgroundImage.cpp \
jni/src/gui/guiBox.cpp \
jni/src/gui/guiButton.cpp \
jni/src/gui/guiButtonImage.cpp \
jni/src/gui/guiButtonItemImage.cpp \
jni/src/gui/guiChatConsole.cpp \
jni/src/gui/guiConfirmRegistration.cpp \
jni/src/gui/guiEditBoxWithScrollbar.cpp \
jni/src/gui/guiEngine.cpp \
jni/src/gui/guiFormSpecMenu.cpp \
jni/src/gui/guiHyperText.cpp \
jni/src/gui/guiInventoryList.cpp \
jni/src/gui/guiItemImage.cpp \
jni/src/gui/guiKeyChangeMenu.cpp \
jni/src/gui/guiPasswordChange.cpp \
jni/src/gui/guiPathSelectMenu.cpp \
jni/src/gui/guiScrollBar.cpp \
jni/src/gui/guiSkin.cpp \
jni/src/gui/guiTable.cpp \
jni/src/gui/guiVolumeChange.cpp \
jni/src/gui/intlGUIEditBox.cpp \
@@ -249,6 +237,7 @@ LOCAL_SRC_FILES := \
jni/src/porting_android.cpp \
jni/src/porting.cpp \
jni/src/profiler.cpp \
jni/src/quicktune.cpp \
jni/src/raycast.cpp \
jni/src/reflowscan.cpp \
jni/src/remoteplayer.cpp \
@@ -297,7 +286,6 @@ LOCAL_SRC_FILES := \
jni/src/util/ieee_float.cpp \
jni/src/util/numeric.cpp \
jni/src/util/pointedthing.cpp \
jni/src/util/quicktune.cpp \
jni/src/util/serialize.cpp \
jni/src/util/sha1.cpp \
jni/src/util/srp.cpp \

Binary file not shown.

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="net.minetest.minetest"
android:installLocation="auto">
@@ -12,14 +11,14 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="${project}"
android:resizeableActivity="false"
tools:targetApi="n">
android:resizeableActivity="false">
<meta-data
android:name="android.max_aspect"
android:value="2.4" />
android:value="2.1" />
<activity
android:name=".MainActivity"
@@ -51,10 +50,10 @@
android:name=".MinetestTextEntry"
android:configChanges="keyboardHidden|orientation|screenSize"
android:theme="@style/Theme.Dialog"
android:windowSoftInputMode="stateAlwaysHidden" />
android:windowSoftInputMode="stateAlwaysHidden"/>
<activity
android:name=".MinetestAssetCopy"
android:screenOrientation="sensorLandscape"
android:theme="@style/AppTheme" />
android:theme="@style/AppTheme"/>
</application>
</manifest>

View File

@@ -6,17 +6,17 @@ 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 androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
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};
@@ -30,8 +30,8 @@ public class MainActivity extends Activity {
}
}
private void checkPermission() {
final List<String> missingPermissions = new ArrayList<>();
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);
@@ -42,7 +42,7 @@ public class MainActivity extends Activity {
if (!missingPermissions.isEmpty()) {
// request permission
final String[] permissions = missingPermissions
.toArray(new String[0]);
.toArray(new String[missingPermissions.size()]);
ActivityCompat.requestPermissions(this, permissions, PERMISSIONS);
} else {
final int[] grantResults = new int[REQUIRED_SDK_PERMISSIONS.length];
@@ -53,23 +53,25 @@ public class MainActivity extends Activity {
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[],
@NonNull int[] grantResults) {
if (requestCode == 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;
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();
// permission were granted - run
next();
break;
}
}
private void next() {
public void next() {
Intent intent = new Intent(this, MtNativeActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);

View File

@@ -1,6 +1,5 @@
package net.minetest.minetest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.res.AssetFileDescriptor;
import android.os.AsyncTask;
@@ -20,12 +19,13 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.Vector;
public class MinetestAssetCopy extends Activity {
private ProgressBar m_ProgressBar;
private TextView m_Filename;
private copyAssetTask m_AssetCopy;
ProgressBar m_ProgressBar;
TextView m_Filename;
copyAssetTask m_AssetCopy;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -54,25 +54,20 @@ public class MinetestAssetCopy extends Activity {
makeFullScreen();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (m_AssetCopy != null) {
m_AssetCopy.cancel(true);
}
}
private void makeFullScreen() {
if (Build.VERSION.SDK_INT >= 19)
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);
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)
if (hasFocus) {
makeFullScreen();
}
}
/* preserve asset copy background task to prevent restart of copying */
@@ -82,7 +77,6 @@ public class MinetestAssetCopy extends Activity {
return this;
}
@SuppressLint("StaticFieldLeak")
private class copyAssetTask extends AsyncTask<String, Integer, String> {
boolean m_copy_started = false;
String m_Foldername = "media";
@@ -97,7 +91,7 @@ public class MinetestAssetCopy extends Activity {
InputStream src = getAssets().open(filename);
byte[] buf = new byte[4096];
int len;
int len = 0;
while ((len = src.read(buf)) > 0) {
size += len;
}
@@ -109,10 +103,10 @@ public class MinetestAssetCopy extends Activity {
@Override
protected String doInBackground(String... files) {
m_foldernames = new Vector<>();
m_filenames = new Vector<>();
m_tocopy = new Vector<>();
m_asset_size_unknown = new Vector<>();
m_foldernames = new Vector<String>();
m_filenames = new Vector<String>();
m_tocopy = new Vector<String>();
m_asset_size_unknown = new Vector<String>();
String baseDir =
Environment.getExternalStorageDirectory().getAbsolutePath()
+ "/";
@@ -126,9 +120,9 @@ public class MinetestAssetCopy extends Activity {
} else {
File[] todel = TempFolder.listFiles();
for (File file : todel) {
Log.v("MinetestAssetCopy", "deleting: " + file.getAbsolutePath());
file.delete();
for (int i = 0; i < todel.length; i++) {
Log.v("MinetestAssetCopy", "deleting: " + todel[i].getAbsolutePath());
todel[i].delete();
}
}
@@ -164,9 +158,9 @@ public class MinetestAssetCopy extends Activity {
if (m_asset_size_unknown.contains(filename)) {
File testme = new File(baseDir + "/" + filename);
if (testme.exists())
if (testme.exists()) {
filesize = testme.length();
}
asset_size_unknown = true;
}
@@ -247,10 +241,12 @@ public class MinetestAssetCopy extends Activity {
protected void onProgressUpdate(Integer... progress) {
if (m_copy_started) {
boolean shortened = false;
String todisplay = m_tocopy.get(progress[0]);
m_ProgressBar.setProgress(progress[0]);
m_Filename.setText(todisplay);
} else {
boolean shortened = false;
String todisplay = m_Foldername;
String full_text = "scanning " + todisplay + " ...";
m_Filename.setText(full_text);
@@ -260,11 +256,14 @@ public class MinetestAssetCopy extends Activity {
/**
* check all files and folders in filelist
*/
void ProcessFileList() {
protected void ProcessFileList() {
String FlashBaseDir =
Environment.getExternalStorageDirectory().getAbsolutePath();
for (String current_path : m_filenames) {
Iterator itr = m_filenames.iterator();
while (itr.hasNext()) {
String current_path = (String) itr.next();
String FlashPath = FlashBaseDir + "/" + current_path;
if (isAssetFolder(current_path)) {
@@ -293,7 +292,7 @@ public class MinetestAssetCopy extends Activity {
File testme = new File(FlashPath);
long asset_filesize = -1;
long stored_filesize;
long stored_filesize = -1;
if (testme.exists()) {
try {
@@ -301,6 +300,7 @@ public class MinetestAssetCopy extends Activity {
asset_filesize = fd.getLength();
fd.close();
} catch (IOException e) {
refresh = true;
m_asset_size_unknown.add(current_path);
Log.e("MinetestAssetCopy", "Failed to open asset file \"" +
FlashPath + "\" for size check");
@@ -308,20 +308,22 @@ public class MinetestAssetCopy extends Activity {
stored_filesize = testme.length();
if (asset_filesize == stored_filesize)
if (asset_filesize == stored_filesize) {
refresh = false;
}
}
if (refresh)
if (refresh) {
m_tocopy.add(current_path);
}
}
}
/**
* read list of folders prepared on package build
*/
void BuildFolderList() {
protected void BuildFolderList() {
try {
InputStream is = getAssets().open("index.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
@@ -341,7 +343,7 @@ public class MinetestAssetCopy extends Activity {
/**
* read list of asset files prepared on package build
*/
void BuildFileList() {
protected void BuildFileList() {
long entrycount = 0;
try {
InputStream is = getAssets().open("filelist.txt");
@@ -364,7 +366,7 @@ public class MinetestAssetCopy extends Activity {
finish();
}
boolean isAssetFolder(String path) {
protected boolean isAssetFolder(String path) {
return m_foldernames.contains(path);
}
}

View File

@@ -15,8 +15,8 @@ public class MinetestTextEntry extends Activity {
private final int MultiLineTextInput = 1;
private final int SingleLineTextInput = 2;
private final int SingleLinePasswordInput = 3;
private AlertDialog mTextInputDialog;
private EditText mTextInputWidget;
public AlertDialog mTextInputDialog;
public EditText mTextInputWidget;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -71,7 +71,7 @@ public class MinetestTextEntry extends Activity {
mTextInputDialog.show();
}
private void pushResult(String text) {
public void pushResult(String text) {
Intent resultData = new Intent();
resultData.putExtra("text", text);
setResult(Activity.RESULT_OK, resultData);
@@ -79,7 +79,7 @@ public class MinetestTextEntry extends Activity {
finish();
}
private void cancelDialog() {
public void cancelDialog() {
setResult(Activity.RESULT_CANCELED);
mTextInputDialog.dismiss();
finish();

View File

@@ -37,17 +37,20 @@ public class MtNativeActivity extends NativeActivity {
makeFullScreen();
}
private void makeFullScreen() {
if (Build.VERSION.SDK_INT >= 19)
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);
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)
if (hasFocus) {
makeFullScreen();
}
}
public void copyAssets() {

View File

@@ -1,17 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<resources>
<style name="AppTheme" parent="android:Theme.Material.Light.NoActionBar.Fullscreen">
<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>
<item name="android:windowLayoutInDisplayCutoutMode" tools:ignore="NewApi" tools:targetApi="o_mr1">
shortEdges
</item>
</style>
<style name="Theme.Dialog" parent="@android:style/Theme.Material.Light.Dialog.NoActionBar">
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
</style>
<style name="Theme.Dialog" parent="@android:style/Theme.Material.Light.Dialog.NoActionBar"/>
</resources>

View File

@@ -1,14 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="android:Theme.Holo.Light.NoActionBar.Fullscreen">
<style name="AppTheme" parent="@android:style/android:Theme.Holo.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:Theme.Holo.Light.Dialog.NoActionBar">
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
</style>
<style name="Theme.Dialog" parent="@android:style/android:Theme.Holo.Light.Dialog.NoActionBar"/>
</resources>

View File

@@ -16,7 +16,7 @@ core.register_on_sending_chat_message(function(message)
end
local cmd, param = string.match(message, "^%.([^ ]+) *(.*)")
param = param or ""
param = param or ""
if not cmd then
core.display_chat_message(core.gettext("-!- Empty command"))
@@ -26,9 +26,9 @@ core.register_on_sending_chat_message(function(message)
local cmd_def = core.registered_chatcommands[cmd]
if cmd_def then
core.set_last_run_mod(cmd_def.mod_origin)
local _, result = cmd_def.func(param)
if result then
core.display_chat_message(result)
local _, message = cmd_def.func(param)
if message then
core.display_chat_message(message)
end
else
core.display_chat_message(core.gettext("-!- Invalid command: ") .. cmd)

View File

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

View File

@@ -250,6 +250,7 @@ end
--------------------------------------------------------------------------------
function compare_worlds(world1,world2)
if world1.path ~= world2.path then
return false
end

View File

@@ -1,152 +0,0 @@
local COLOR_BLUE = "#7AF"
local COLOR_GREEN = "#7F7"
local COLOR_GRAY = "#BBB"
local LIST_FORMSPEC = [[
size[13,6.5]
label[0,-0.1;%s]
tablecolumns[color;tree;text;text]
table[0,0.5;12.8,5.5;list;%s;0]
button_exit[5,6;3,1;quit;%s]
]]
local LIST_FORMSPEC_DESCRIPTION = [[
size[13,7.5]
label[0,-0.1;%s]
tablecolumns[color;tree;text;text]
table[0,0.5;12.8,4.8;list;%s;%i]
box[0,5.5;12.8,1.5;#000]
textarea[0.3,5.5;13.05,1.9;;;%s]
button_exit[5,7;3,1;quit;%s]
]]
local formspec_escape = core.formspec_escape
local check_player_privs = core.check_player_privs
-- CHAT COMMANDS FORMSPEC
local mod_cmds = {}
local function load_mod_command_tree()
mod_cmds = {}
for name, def in pairs(core.registered_chatcommands) do
mod_cmds[def.mod_origin] = mod_cmds[def.mod_origin] or {}
local cmds = mod_cmds[def.mod_origin]
-- Could be simplified, but avoid the priv checks whenever possible
cmds[#cmds + 1] = { name, def }
end
local sorted_mod_cmds = {}
for modname, cmds in pairs(mod_cmds) do
table.sort(cmds, function(a, b) return a[1] < b[1] end)
sorted_mod_cmds[#sorted_mod_cmds + 1] = { modname, cmds }
end
table.sort(sorted_mod_cmds, function(a, b) return a[1] < b[1] end)
mod_cmds = sorted_mod_cmds
end
core.after(0, load_mod_command_tree)
local function build_chatcommands_formspec(name, sel, copy)
local rows = {}
rows[1] = "#FFF,0,Command,Parameters"
local description = "For more information, click on any entry in the list.\n" ..
"Double-click to copy the entry to the chat history."
for i, data in ipairs(mod_cmds) do
rows[#rows + 1] = COLOR_BLUE .. ",0," .. formspec_escape(data[1]) .. ","
for j, cmds in ipairs(data[2]) do
local has_priv = check_player_privs(name, cmds[2].privs)
rows[#rows + 1] = ("%s,1,%s,%s"):format(
has_priv and COLOR_GREEN or COLOR_GRAY,
cmds[1], formspec_escape(cmds[2].params))
if sel == #rows then
description = cmds[2].description
if copy then
core.chat_send_player(name, ("Command: %s %s"):format(
core.colorize("#0FF", "/" .. cmds[1]), cmds[2].params))
end
end
end
end
return LIST_FORMSPEC_DESCRIPTION:format(
"Available commands: (see also: /help <cmd>)",
table.concat(rows, ","), sel or 0,
description, "Close"
)
end
-- PRIVILEGES FORMSPEC
local function build_privs_formspec(name)
local privs = {}
for priv_name, def in pairs(core.registered_privileges) do
privs[#privs + 1] = { priv_name, def }
end
table.sort(privs, function(a, b) return a[1] < b[1] end)
local rows = {}
rows[1] = "#FFF,0,Privilege,Description"
local player_privs = core.get_player_privs(name)
for i, data in ipairs(privs) do
rows[#rows + 1] = ("%s,0,%s,%s"):format(
player_privs[data[1]] and COLOR_GREEN or COLOR_GRAY,
data[1], formspec_escape(data[2].description))
end
return LIST_FORMSPEC:format(
"Available privileges:",
table.concat(rows, ","),
"Close"
)
end
-- DETAILED CHAT COMMAND INFORMATION
core.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "__builtin:help_cmds" or fields.quit then
return
end
local event = minetest.explode_table_event(fields.list)
if event.type ~= "INV" then
local name = player:get_player_name()
core.show_formspec(name, "__builtin:help_cmds",
build_chatcommands_formspec(name, event.row, event.type == "DCL"))
end
end)
local help_command = core.registered_chatcommands["help"]
local old_help_func = help_command.func
help_command.func = function(name, param)
local admin = core.settings:get("name")
-- If the admin ran help, put the output in the chat buffer as well to
-- work with the server terminal
if param == "privs" then
core.show_formspec(name, "__builtin:help_privs",
build_privs_formspec(name))
if name ~= admin then
return true
end
end
if param == "" or param == "all" then
core.show_formspec(name, "__builtin:help_cmds",
build_chatcommands_formspec(name))
if name ~= admin then
return true
end
end
return old_help_func(name, param)
end

View File

@@ -5,7 +5,7 @@
local string_sub, string_find = string.sub, string.find
--------------------------------------------------------------------------------
local function basic_dump(o)
function basic_dump(o)
local tp = type(o)
if tp == "number" then
return tostring(o)
@@ -128,7 +128,6 @@ function dump(o, indent, nested, level)
if t ~= "table" then
return basic_dump(o)
end
-- Contains table -> true/nil of currently nested tables
nested = nested or {}
if nested[o] then
@@ -137,11 +136,10 @@ function dump(o, indent, nested, level)
nested[o] = true
indent = indent or "\t"
level = level or 1
local ret = {}
local t = {}
local dumped_indexes = {}
for i, v in ipairs(o) do
ret[#ret + 1] = dump(v, indent, nested, level + 1)
t[#t + 1] = dump(v, indent, nested, level + 1)
dumped_indexes[i] = true
end
for k, v in pairs(o) do
@@ -150,7 +148,7 @@ function dump(o, indent, nested, level)
k = "["..dump(k, indent, nested, level + 1).."]"
end
v = dump(v, indent, nested, level + 1)
ret[#ret + 1] = k.." = "..v
t[#t + 1] = k.." = "..v
end
end
nested[o] = nil
@@ -159,10 +157,10 @@ function dump(o, indent, nested, level)
local end_indent_str = "\n"..string.rep(indent, level - 1)
return string.format("{%s%s%s}",
indent_str,
table.concat(ret, ","..indent_str),
table.concat(t, ","..indent_str),
end_indent_str)
end
return "{"..table.concat(ret, ", ").."}"
return "{"..table.concat(t, ", ").."}"
end
--------------------------------------------------------------------------------
@@ -200,11 +198,28 @@ function table.indexof(list, val)
return -1
end
assert(table.indexof({"foo", "bar"}, "foo") == 1)
assert(table.indexof({"foo", "bar"}, "baz") == -1)
--------------------------------------------------------------------------------
if INIT ~= "client" then
function file_exists(filename)
local f = io.open(filename, "r")
if f == nil then
return false
else
f:close()
return true
end
end
end
--------------------------------------------------------------------------------
function string:trim()
return (self:gsub("^%s*(.-)%s*$", "%1"))
end
assert(string.trim("\n \t\tfoo bar\t ") == "foo bar")
--------------------------------------------------------------------------------
function math.hypot(x, y)
local t
@@ -229,17 +244,61 @@ function math.sign(x, tolerance)
end
--------------------------------------------------------------------------------
function math.factorial(x)
assert(x % 1 == 0 and x >= 0, "factorial expects a non-negative integer")
if x >= 171 then
-- 171! is greater than the biggest double, no need to calculate
return math.huge
function get_last_folder(text,count)
local parts = text:split(DIR_DELIM)
if count == nil then
return parts[#parts]
end
local v = 1
for k = 2, x do
v = v * k
local retval = ""
for i=1,count,1 do
retval = retval .. parts[#parts - (count-i)] .. DIR_DELIM
end
return v
return retval
end
--------------------------------------------------------------------------------
function cleanup_path(temppath)
local parts = temppath:split("-")
temppath = ""
for i=1,#parts,1 do
if temppath ~= "" then
temppath = temppath .. "_"
end
temppath = temppath .. parts[i]
end
parts = temppath:split(".")
temppath = ""
for i=1,#parts,1 do
if temppath ~= "" then
temppath = temppath .. "_"
end
temppath = temppath .. parts[i]
end
parts = temppath:split("'")
temppath = ""
for i=1,#parts,1 do
if temppath ~= "" then
temppath = temppath .. ""
end
temppath = temppath .. parts[i]
end
parts = temppath:split(" ")
temppath = ""
for i=1,#parts,1 do
if temppath ~= "" then
temppath = temppath
end
temppath = temppath .. parts[i]
end
return temppath
end
function core.formspec_escape(text)
@@ -334,8 +393,9 @@ if INIT == "game" then
end
local old_itemstack = ItemStack(itemstack)
local new_itemstack = core.item_place_node(itemstack, placer,
pointed_thing, param2, prevent_after_place)
local new_itemstack, removed = core.item_place_node(
itemstack, placer, pointed_thing, param2, prevent_after_place
)
return infinitestacks and old_itemstack or new_itemstack
end
@@ -353,9 +413,10 @@ if INIT == "game" then
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
return core.rotate_and_place(itemstack, placer, pointed_thing,
core.rotate_and_place(itemstack, placer, pointed_thing,
is_creative(name),
{invert_wall = invert_wall}, true)
return itemstack
end
end
@@ -445,6 +506,9 @@ function core.string_to_pos(value)
return nil
end
assert(core.string_to_pos("10.0, 5, -2").x == 10)
assert(core.string_to_pos("( 10.0, 5, -2)").z == -2)
assert(core.string_to_pos("asd, 5, -2)") == nil)
--------------------------------------------------------------------------------
function core.string_to_area(value)
@@ -497,29 +561,6 @@ function table.insert_all(t, other)
end
function table.key_value_swap(t)
local ti = {}
for k,v in pairs(t) do
ti[v] = k
end
return ti
end
function table.shuffle(t, from, to, random)
from = from or 1
to = to or #t
random = random or math.random
local n = to - from + 1
while n > 1 do
local r = from + n-1
local l = from + random(0, n-1)
t[l], t[r] = t[r], t[l]
n = n-1
end
end
--------------------------------------------------------------------------------
-- mainmenu only functions
--------------------------------------------------------------------------------
@@ -700,3 +741,6 @@ function core.privs_to_string(privs, delim)
end
return table.concat(list, delim)
end
assert(core.string_to_privs("a,b").b == true)
assert(core.privs_to_string({a=true,b=true}) == "a,b")

View File

@@ -177,16 +177,13 @@ end
-- Deserialization
local function safe_loadstring(...)
local func, err = loadstring(...)
if func then
setfenv(func, {})
return func
end
return nil, err
end
local env = {
loadstring = loadstring,
}
local function dummy_func() end
local safe_env = {
loadstring = function() end,
}
function core.deserialize(str, safe)
if type(str) ~= "string" then
@@ -198,10 +195,7 @@ function core.deserialize(str, safe)
end
local f, err = loadstring(str)
if not f then return nil, err end
-- The environment is recreated every time so deseralized code cannot
-- pollute it with permanent references.
setfenv(f, {loadstring = safe and dummy_func or safe_loadstring})
setfenv(f, safe and safe_env or env)
local good, data = pcall(f)
if good then
@@ -210,3 +204,18 @@ function core.deserialize(str, safe)
return nil, data
end
end
-- Unit tests
local test_in = {cat={sound="nyan", speed=400}, dog={sound="woof"}}
local test_out = core.deserialize(core.serialize(test_in))
assert(test_in.cat.sound == test_out.cat.sound)
assert(test_in.cat.speed == test_out.cat.speed)
assert(test_in.dog.sound == test_out.dog.sound)
test_in = {escape_chars="\n\r\t\v\\\"\'", non_european="θשׁ٩∂"}
test_out = core.deserialize(core.serialize(test_in))
assert(test_in.escape_chars == test_out.escape_chars)
assert(test_in.non_european == test_out.non_european)

View File

@@ -1,73 +0,0 @@
_G.core = {}
dofile("builtin/common/misc_helpers.lua")
describe("string", function()
it("trim()", function()
assert.equal("foo bar", string.trim("\n \t\tfoo bar\t "))
end)
describe("split()", function()
it("removes empty", function()
assert.same({ "hello" }, string.split("hello"))
assert.same({ "hello", "world" }, string.split("hello,world"))
assert.same({ "hello", "world" }, string.split("hello,world,,,"))
assert.same({ "hello", "world" }, string.split(",,,hello,world"))
assert.same({ "hello", "world", "2" }, string.split("hello,,,world,2"))
assert.same({ "hello ", " world" }, string.split("hello :| world", ":|"))
end)
it("keeps empty", function()
assert.same({ "hello" }, string.split("hello", ",", true))
assert.same({ "hello", "world" }, string.split("hello,world", ",", true))
assert.same({ "hello", "world", "" }, string.split("hello,world,", ",", true))
assert.same({ "hello", "", "", "world", "2" }, string.split("hello,,,world,2", ",", true))
assert.same({ "", "", "hello", "world", "2" }, string.split(",,hello,world,2", ",", true))
assert.same({ "hello ", " world | :" }, string.split("hello :| world | :", ":|"))
end)
it("max_splits", function()
assert.same({ "one" }, string.split("one", ",", true, 2))
assert.same({ "one,two,three,four" }, string.split("one,two,three,four", ",", true, 0))
assert.same({ "one", "two", "three,four" }, string.split("one,two,three,four", ",", true, 2))
assert.same({ "one", "", "two,three,four" }, string.split("one,,two,three,four", ",", true, 2))
assert.same({ "one", "two", "three,four" }, string.split("one,,,,,,two,three,four", ",", false, 2))
end)
it("pattern", function()
assert.same({ "one", "two" }, string.split("one,two", ",", false, -1, true))
assert.same({ "one", "two", "three" }, string.split("one2two3three", "%d", false, -1, true))
end)
end)
end)
describe("privs", function()
it("from string", function()
assert.same({ a = true, b = true }, core.string_to_privs("a,b"))
end)
it("to string", function()
assert.equal("one", core.privs_to_string({ one=true }))
local ret = core.privs_to_string({ a=true, b=true })
assert(ret == "a,b" or ret == "b,a")
end)
end)
describe("pos", function()
it("from string", function()
assert.same({ x = 10, y = 5.1, z = -2}, core.string_to_pos("10.0, 5.1, -2"))
assert.same({ x = 10, y = 5.1, z = -2}, core.string_to_pos("( 10.0, 5.1, -2)"))
assert.is_nil(core.string_to_pos("asd, 5, -2)"))
end)
it("to string", function()
assert.equal("(10.1,5.2,-2.3)", core.pos_to_string({ x = 10.1, y = 5.2, z = -2.3}))
end)
end)
describe("table", function()
it("indexof()", function()
assert.equal(1, table.indexof({"foo", "bar"}, "foo"))
assert.equal(-1, table.indexof({"foo", "bar"}, "baz"))
end)
end)

View File

@@ -1,44 +0,0 @@
_G.core = {}
_G.setfenv = require 'busted.compatibility'.setfenv
dofile("builtin/common/serialize.lua")
describe("serialize", function()
it("works", function()
local test_in = {cat={sound="nyan", speed=400}, dog={sound="woof"}}
local test_out = core.deserialize(core.serialize(test_in))
assert.same(test_in, test_out)
end)
it("handles characters", function()
local test_in = {escape_chars="\n\r\t\v\\\"\'", non_european="θשׁ٩∂"}
local test_out = core.deserialize(core.serialize(test_in))
assert.same(test_in, test_out)
end)
it("handles recursive structures", function()
local test_in = { hello = "world" }
test_in.foo = test_in
local test_out = core.deserialize(core.serialize(test_in))
assert.same(test_in, test_out)
end)
it("strips functions in safe mode", function()
local test_in = {
func = function(a, b)
error("test")
end,
foo = "bar"
}
local str = core.serialize(test_in)
assert.not_nil(str:find("loadstring"))
local test_out = core.deserialize(str, true)
assert.is_nil(test_out.func)
assert.equals(test_out.foo, "bar")
end)
end)

View File

@@ -1,46 +0,0 @@
_G.vector = {}
dofile("builtin/common/vector.lua")
describe("vector", function()
describe("new()", function()
it("constructs", function()
assert.same({ x = 0, y = 0, z = 0 }, vector.new())
assert.same({ x = 1, y = 2, z = 3 }, vector.new(1, 2, 3))
assert.same({ x = 3, y = 2, z = 1 }, vector.new({ x = 3, y = 2, z = 1 }))
local input = vector.new({ x = 3, y = 2, z = 1 })
local output = vector.new(input)
assert.same(input, output)
assert.are_not.equal(input, output)
end)
it("throws on invalid input", function()
assert.has.errors(function()
vector.new({ x = 3 })
end)
assert.has.errors(function()
vector.new({ d = 3 })
end)
end)
end)
it("equal()", function()
local function assertE(a, b)
assert.is_true(vector.equals(a, b))
end
local function assertNE(a, b)
assert.is_false(vector.equals(a, b))
end
assertE({x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0})
assertE({x = -1, y = 0, z = 1}, {x = -1, y = 0, z = 1})
local a = { x = 2, y = 4, z = -10 }
assertE(a, a)
assertNE({x = -1, y = 0, z = 1}, a)
end)
it("add()", function()
assert.same({ x = 2, y = 4, z = 6 }, vector.add(vector.new(1, 2, 3), { x = 1, y = 2, z = 3 }))
end)
end)

View File

@@ -70,25 +70,6 @@ function vector.direction(pos1, pos2)
})
end
function vector.angle(a, b)
local dotp = vector.dot(a, b)
local cp = vector.cross(a, b)
local crossplen = vector.length(cp)
return math.atan2(crossplen, dotp)
end
function vector.dot(a, b)
return a.x * b.x + a.y * b.y + a.z * b.z
end
function vector.cross(a, b)
return {
x = a.y * b.z - a.z * b.y,
y = a.z * b.x - a.x * b.z,
z = a.x * b.y - a.y * b.x
}
end
function vector.add(a, b)
if type(b) == "table" then
return {x = a.x + b.x,

View File

@@ -54,39 +54,52 @@ end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local function wordwrap_quickhack(str)
local res = ""
local ar = str:split("\n")
for i = 1, #ar do
local text = ar[i]
-- Hack to add word wrapping.
-- TODO: Add engine support for wrapping in formspecs
while #text > 80 do
if res ~= "" then
res = res .. ","
end
res = res .. core.formspec_escape(string.sub(text, 1, 79))
text = string.sub(text, 80, #text)
end
if res ~= "" then
res = res .. ","
end
res = res .. core.formspec_escape(text)
end
return res
end
--------------------------------------------------------------------------------
function ui.update()
local formspec = {}
local formspec = ""
-- handle errors
if gamedata ~= nil and gamedata.reconnect_requested then
local error_message = core.formspec_escape(
gamedata.errormessage or "<none available>")
formspec = {
"size[14,8]",
"real_coordinates[true]",
"box[0.5,1.2;13,5;#000]",
("textarea[0.5,1.2;13,5;;%s;%s]"):format(
fgettext("The server has requested a reconnect:"), error_message),
"button[2,6.6;4,1;btn_reconnect_yes;" .. fgettext("Reconnect") .. "]",
"button[8,6.6;4,1;btn_reconnect_no;" .. fgettext("Main menu") .. "]"
}
formspec = wordwrap_quickhack(gamedata.errormessage or "")
formspec = "size[12,5]" ..
"label[0.5,0;" .. fgettext("The server has requested a reconnect:") ..
"]textlist[0.2,0.8;11.5,3.5;;" .. formspec ..
"]button[6,4.6;3,0.5;btn_reconnect_no;" .. fgettext("Main menu") .. "]" ..
"button[3,4.6;3,0.5;btn_reconnect_yes;" .. fgettext("Reconnect") .. "]"
elseif gamedata ~= nil and gamedata.errormessage ~= nil then
local error_message = core.formspec_escape(gamedata.errormessage)
formspec = wordwrap_quickhack(gamedata.errormessage)
local error_title
if string.find(gamedata.errormessage, "ModError") then
error_title = fgettext("An error occurred in a Lua script:")
error_title = fgettext("An error occurred in a Lua script, such as a mod:")
else
error_title = fgettext("An error occurred:")
end
formspec = {
"size[14,8]",
"real_coordinates[true]",
"box[0.5,1.2;13,5;#000]",
("textarea[0.5,1.2;13,5;;%s;%s]"):format(
error_title, error_message),
"button[5,6.6;4,1;btn_error_confirm;" .. fgettext("Ok") .. "]"
}
formspec = "size[12,5]" ..
"label[0.5,0;" .. error_title ..
"]textlist[0.2,0.8;11.5,3.5;;" .. formspec ..
"]button[4.5,4.6;3,0.5;btn_error_confirm;" .. fgettext("Ok") .. "]"
else
local active_toplevel_ui_elements = 0
for key,value in pairs(ui.childlist) do
@@ -94,8 +107,8 @@ function ui.update()
local retval = value:get_formspec()
if retval ~= nil and retval ~= "" then
active_toplevel_ui_elements = active_toplevel_ui_elements + 1
table.insert(formspec, retval)
active_toplevel_ui_elements = active_toplevel_ui_elements +1
formspec = formspec .. retval
end
end
end
@@ -107,7 +120,7 @@ function ui.update()
local retval = value:get_formspec()
if retval ~= nil and retval ~= "" then
table.insert(formspec, retval)
formspec = formspec .. retval
end
end
end
@@ -122,10 +135,10 @@ function ui.update()
core.log("warning", "no toplevel ui element "..
"active; switching to default")
ui.childlist[ui.default]:show()
formspec = {ui.childlist[ui.default]:get_formspec()}
formspec = ui.childlist[ui.default]:get_formspec()
end
end
core.update_formspec(table.concat(formspec))
core.update_formspec(formspec)
end
--------------------------------------------------------------------------------

View File

@@ -1,43 +1,4 @@
-- Minetest: builtin/game/chat.lua
-- Helper function that implements search and replace without pattern matching
-- Returns the string and a boolean indicating whether or not the string was modified
local function safe_gsub(s, replace, with)
local i1, i2 = s:find(replace, 1, true)
if not i1 then
return s, false
end
return s:sub(1, i1 - 1) .. with .. s:sub(i2 + 1), true
end
--
-- Chat message formatter
--
-- Implemented in Lua to allow redefinition
function core.format_chat_message(name, message)
local error_str = "Invalid chat message format - missing %s"
local str = core.settings:get("chat_message_format")
local replaced
-- Name
str, replaced = safe_gsub(str, "@name", name)
if not replaced then
error(error_str:format("@name"), 2)
end
-- Timestamp
str = safe_gsub(str, "@timestamp", os.date("%H:%M:%S", os.time()))
-- Insert the message into the string only after finishing all other processing
str, replaced = safe_gsub(str, "@message", message)
if not replaced then
error(error_str:format("@message"), 2)
end
return str
end
-- Minetest: builtin/game/chatcommands.lua
--
-- Chat command handler
@@ -66,9 +27,9 @@ core.register_on_chat_message(function(name, message)
local has_privs, missing_privs = core.check_player_privs(name, cmd_def.privs)
if has_privs then
core.set_last_run_mod(cmd_def.mod_origin)
local _, result = cmd_def.func(name, param)
if result then
core.chat_send_player(name, result)
local success, message = cmd_def.func(name, param)
if message then
core.chat_send_player(name, message)
end
else
core.chat_send_player(name, "You don't have permission"
@@ -115,7 +76,6 @@ core.register_chatcommand("me", {
privs = {shout=true},
func = function(name, param)
core.chat_send_all("* " .. name .. " " .. param)
return true
end,
})
@@ -142,7 +102,7 @@ core.register_chatcommand("privs", {
end
return true, "Privileges of " .. name .. ": "
.. core.privs_to_string(
core.get_player_privs(name), ", ")
core.get_player_privs(name), ' ')
end,
})
@@ -165,10 +125,10 @@ core.register_chatcommand("haspriv", {
if core.check_player_privs(player_name, privs) then
table.insert(players_with_priv, player_name)
end
end
end
return true, "Players online with the \"" .. param .. "\" privilege: " ..
table.concat(players_with_priv, ", ")
end
end
})
local function handle_grant_command(caller, grantname, grantprivstr)
@@ -201,7 +161,6 @@ local function handle_grant_command(caller, grantname, grantprivstr)
return false, privs_unknown
end
for priv, _ in pairs(grantprivs) do
-- call the on_grant callbacks
core.run_priv_callbacks(grantname, priv, caller, "grant")
end
core.set_player_privs(grantname, privs)
@@ -274,7 +233,6 @@ core.register_chatcommand("revoke", {
end
for priv, _ in pairs(revoke_privs) do
-- call the on_revoke callbacks
core.run_priv_callbacks(revoke_name, priv, name, "revoke")
end
@@ -303,12 +261,11 @@ core.register_chatcommand("setpassword", {
toname = param:match("^([^ ]+) *$")
raw_password = nil
end
if not toname then
return false, "Name field required"
end
local act_str_past, act_str_pres
local act_str_past = "?"
local act_str_pres = "?"
if not raw_password then
core.set_player_password(toname, "")
act_str_past = "cleared"
@@ -320,14 +277,13 @@ core.register_chatcommand("setpassword", {
act_str_past = "set"
act_str_pres = "sets"
end
if toname ~= name then
core.chat_send_player(toname, "Your password was "
.. act_str_past .. " by " .. name)
end
core.log("action", name .. " " .. act_str_pres ..
" password of " .. toname .. ".")
core.log("action", name .. " " .. act_str_pres
.. " password of " .. toname .. ".")
return true, "Password of player \"" .. toname .. "\" " .. act_str_past
end,
@@ -411,35 +367,35 @@ core.register_chatcommand("teleport", {
return pos, false
end
local teleportee = nil
local p = {}
p.x, p.y, p.z = string.match(param, "^([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+)$")
p.x = tonumber(p.x)
p.y = tonumber(p.y)
p.z = tonumber(p.z)
if p.x and p.y and p.z then
local lm = 31000
if p.x < -lm or p.x > lm or p.y < -lm or p.y > lm or p.z < -lm or p.z > lm then
return false, "Cannot teleport out of map bounds!"
end
local teleportee = core.get_player_by_name(name)
teleportee = core.get_player_by_name(name)
if teleportee then
teleportee:set_pos(p)
return true, "Teleporting to "..core.pos_to_string(p)
end
end
local target_name = param:match("^([^ ]+)$")
local teleportee = core.get_player_by_name(name)
p = nil
local teleportee = nil
local p = nil
local target_name = nil
target_name = param:match("^([^ ]+)$")
teleportee = core.get_player_by_name(name)
if target_name then
local target = core.get_player_by_name(target_name)
if target then
p = target:get_pos()
end
end
if teleportee and p then
p = find_free_position_near(p)
teleportee:set_pos(p)
@@ -451,9 +407,9 @@ core.register_chatcommand("teleport", {
return false, "You don't have permission to teleport other players (missing bring privilege)"
end
teleportee = nil
p = {}
local teleportee_name
local teleportee = nil
local p = {}
local teleportee_name = nil
teleportee_name, p.x, p.y, p.z = param:match(
"^([^ ]+) +([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+)$")
p.x, p.y, p.z = tonumber(p.x), tonumber(p.y), tonumber(p.z)
@@ -466,8 +422,10 @@ core.register_chatcommand("teleport", {
.. " to " .. core.pos_to_string(p)
end
teleportee = nil
p = nil
local teleportee = nil
local p = nil
local teleportee_name = nil
local target_name = nil
teleportee_name, target_name = string.match(param, "^([^ ]+) +([^ ]+)$")
if teleportee_name then
teleportee = core.get_player_by_name(teleportee_name)
@@ -501,8 +459,7 @@ core.register_chatcommand("set", {
core.settings:set(setname, setvalue)
return true, setname .. " = " .. setvalue
end
setname, setvalue = string.match(param, "([^ ]+) (.+)")
local setname, setvalue = string.match(param, "([^ ]+) (.+)")
if setname and setvalue then
if not core.settings:get(setname) then
return false, "Failed. Use '/set -n <name> <value>' to create a new setting."
@@ -510,16 +467,14 @@ core.register_chatcommand("set", {
core.settings:set(setname, setvalue)
return true, setname .. " = " .. setvalue
end
setname = string.match(param, "([^ ]+)")
local setname = string.match(param, "([^ ]+)")
if setname then
setvalue = core.settings:get(setname)
local setvalue = core.settings:get(setname)
if not setvalue then
setvalue = "<not set>"
end
return true, setname .. " = " .. setvalue
end
return false, "Invalid parameters (see /help set)."
end,
})
@@ -737,7 +692,7 @@ core.register_chatcommand("pulverize", {
end
core.log("action", name .. " pulverized \"" ..
wielded_item:get_name() .. " " .. wielded_item:get_count() .. "\"")
player:set_wielded_item(nil)
player:set_wielded_item(nil)
return true, "An item was pulverized."
end,
})
@@ -816,7 +771,7 @@ core.register_chatcommand("rollback", {
end
local target_name, seconds = string.match(param, ":([^ ]+) *(%d*)")
if not target_name then
local player_name
local player_name = nil
player_name, seconds = string.match(param, "([^ ]+) *(%d*)")
if not player_name then
return false, "Invalid parameters. See /help rollback"
@@ -920,13 +875,12 @@ core.register_chatcommand("shutdown", {
core.chat_send_all("*** Server shutting down (operator request).")
end
core.request_shutdown(message:trim(), core.is_yes(reconnect), delay)
return true
end,
})
core.register_chatcommand("ban", {
params = "[<name>]",
description = "Ban the IP of a player or show the ban list",
params = "[<name> | <IP_address>]",
description = "Ban player or show ban list",
privs = {ban=true},
func = function(name, param)
if param == "" then
@@ -938,7 +892,7 @@ core.register_chatcommand("ban", {
end
end
if not core.get_player_by_name(param) then
return false, "Player is not online."
return false, "No such player."
end
if not core.ban_player(param) then
return false, "Failed to ban player."
@@ -951,7 +905,7 @@ core.register_chatcommand("ban", {
core.register_chatcommand("unban", {
params = "<name> | <IP_address>",
description = "Remove IP ban belonging to a player/IP",
description = "Remove player ban",
privs = {ban=true},
func = function(name, param)
if not core.unban_player_or_ip(param) then
@@ -997,19 +951,18 @@ core.register_chatcommand("clearobjects", {
core.log("action", name .. " clears all objects ("
.. options.mode .. " mode).")
core.chat_send_all("Clearing all objects. This may take a long time."
.. " You may experience a timeout. (by "
core.chat_send_all("Clearing all objects. This may take long."
.. " You may experience a timeout. (by "
.. name .. ")")
core.clear_objects(options)
core.log("action", "Object clearing done.")
core.chat_send_all("*** Cleared all objects.")
return true
end,
})
core.register_chatcommand("msg", {
params = "<name> <message>",
description = "Send a direct message to a player",
description = "Send a private message",
privs = {shout=true},
func = function(name, param)
local sendto, message = param:match("^(%S+)%s(.+)$")
@@ -1020,9 +973,9 @@ core.register_chatcommand("msg", {
return false, "The player " .. sendto
.. " is not online."
end
core.log("action", "DM from " .. name .. " to " .. sendto
core.log("action", "PM from " .. name .. " to " .. sendto
.. ": " .. message)
core.chat_send_player(sendto, "DM from " .. name .. ": "
core.chat_send_player(sendto, "PM from " .. name .. ": "
.. message)
return true, "Message sent."
end,

View File

@@ -20,7 +20,7 @@ function core.node_metadata_inventory_move_allow_all()
end
function core.add_to_creative_inventory(itemstring)
core.log("deprecated", "core.add_to_creative_inventory is obsolete and does nothing.")
core.log("deprecated", "core.add_to_creative_inventory: This function is deprecated and does nothing.")
end
--

View File

@@ -1,34 +1,6 @@
-- Minetest: builtin/item.lua
local builtin_shared = ...
local SCALE = 0.667
local facedir_to_euler = {
{y = 0, x = 0, z = 0},
{y = -math.pi/2, x = 0, z = 0},
{y = math.pi, x = 0, z = 0},
{y = math.pi/2, x = 0, z = 0},
{y = math.pi/2, x = -math.pi/2, z = math.pi/2},
{y = math.pi/2, x = math.pi, z = math.pi/2},
{y = math.pi/2, x = math.pi/2, z = math.pi/2},
{y = math.pi/2, x = 0, z = math.pi/2},
{y = -math.pi/2, x = math.pi/2, z = math.pi/2},
{y = -math.pi/2, x = 0, z = math.pi/2},
{y = -math.pi/2, x = -math.pi/2, z = math.pi/2},
{y = -math.pi/2, x = math.pi, z = math.pi/2},
{y = 0, x = 0, z = math.pi/2},
{y = 0, x = -math.pi/2, z = math.pi/2},
{y = 0, x = math.pi, z = math.pi/2},
{y = 0, x = math.pi/2, z = math.pi/2},
{y = math.pi, x = math.pi, z = math.pi/2},
{y = math.pi, x = math.pi/2, z = math.pi/2},
{y = math.pi, x = 0, z = math.pi/2},
{y = math.pi, x = -math.pi/2, z = math.pi/2},
{y = math.pi, x = math.pi, z = 0},
{y = -math.pi/2, x = math.pi, z = 0},
{y = 0, x = math.pi, z = 0},
{y = math.pi/2, x = math.pi, z = 0}
}
--
-- Falling stuff
@@ -36,8 +8,8 @@ local facedir_to_euler = {
core.register_entity(":__builtin:falling_node", {
initial_properties = {
visual = "item",
visual_size = {x = SCALE, y = SCALE, z = SCALE},
visual = "wielditem",
visual_size = {x = 0.667, y = 0.667},
textures = {},
physical = true,
is_visible = false,
@@ -50,116 +22,11 @@ core.register_entity(":__builtin:falling_node", {
set_node = function(self, node, meta)
self.node = node
meta = meta or {}
if type(meta.to_table) == "function" then
meta = meta:to_table()
end
for _, list in pairs(meta.inventory or {}) do
for i, stack in pairs(list) do
if type(stack) == "userdata" then
list[i] = stack:to_string()
end
end
end
local def = core.registered_nodes[node.name]
if not def then
-- Don't allow unknown nodes to fall
core.log("info",
"Unknown falling node removed at "..
core.pos_to_string(self.object:get_pos()))
self.object:remove()
return
end
self.meta = meta
if def.drawtype == "torchlike" or def.drawtype == "signlike" then
local textures
if def.tiles and def.tiles[1] then
local tile = def.tiles[1]
if type(tile) == "table" then
tile = tile.name
end
if def.drawtype == "torchlike" then
textures = { "("..tile..")^[transformFX", tile }
else
textures = { tile, "("..tile..")^[transformFX" }
end
end
local vsize
if def.visual_scale then
local s = def.visual_scale
vsize = {x = s, y = s, z = s}
end
self.object:set_properties({
is_visible = true,
visual = "upright_sprite",
visual_size = vsize,
textures = textures,
glow = def.light_source,
})
elseif def.drawtype ~= "airlike" then
local itemstring = node.name
if core.is_colored_paramtype(def.paramtype2) then
itemstring = core.itemstring_with_palette(itemstring, node.param2)
end
local vsize
if def.visual_scale then
local s = def.visual_scale * SCALE
vsize = {x = s, y = s, z = s}
end
self.object:set_properties({
is_visible = true,
wield_item = itemstring,
visual_size = vsize,
glow = def.light_source,
})
end
-- Rotate entity
if def.drawtype == "torchlike" then
self.object:set_yaw(math.pi*0.25)
elseif (node.param2 ~= 0 and (def.wield_image == ""
or def.wield_image == nil))
or def.drawtype == "signlike"
or def.drawtype == "mesh"
or def.drawtype == "normal"
or def.drawtype == "nodebox" then
if (def.paramtype2 == "facedir" or def.paramtype2 == "colorfacedir") then
local fdir = node.param2 % 32
-- Get rotation from a precalculated lookup table
local euler = facedir_to_euler[fdir + 1]
if euler then
self.object:set_rotation(euler)
end
elseif (def.paramtype2 == "wallmounted" or def.paramtype2 == "colorwallmounted") then
local rot = node.param2 % 8
local pitch, yaw, roll = 0, 0, 0
if rot == 1 then
pitch, yaw = math.pi, math.pi
elseif rot == 2 then
pitch, yaw = math.pi/2, math.pi/2
elseif rot == 3 then
pitch, yaw = math.pi/2, -math.pi/2
elseif rot == 4 then
pitch, yaw = math.pi/2, math.pi
elseif rot == 5 then
pitch, yaw = math.pi/2, 0
end
if def.drawtype == "signlike" then
pitch = pitch - math.pi/2
if rot == 0 then
yaw = yaw + math.pi/2
elseif rot == 1 then
yaw = yaw - math.pi/2
end
elseif def.drawtype == "mesh" or def.drawtype == "normal" then
if rot >= 0 and rot <= 1 then
roll = roll + math.pi
else
yaw = yaw + math.pi
end
end
self.object:set_rotation({x=pitch, y=yaw, z=roll})
end
end
self.meta = meta or {}
self.object:set_properties({
is_visible = true,
textures = {node.name},
})
end,
get_staticdata = function(self)
@@ -249,8 +116,8 @@ core.register_entity(":__builtin:falling_node", {
local meta = core.get_meta(np)
meta:from_table(self.meta)
end
if def.sounds and def.sounds.place then
core.sound_play(def.sounds.place, {pos = np}, true)
if def.sounds and def.sounds.place and def.sounds.place.name then
core.sound_play(def.sounds.place, {pos = np})
end
end
self.object:remove()
@@ -274,11 +141,6 @@ local function convert_to_falling_node(pos, node)
local meta = core.get_meta(pos)
local metatable = meta and meta:to_table() or {}
local def = core.registered_nodes[node.name]
if def and def.sounds and def.sounds.fall then
core.sound_play(def.sounds.fall, {pos = pos}, true)
end
obj:get_luaentity():set_node(node, metatable)
core.remove_node(pos)
return true
@@ -308,9 +170,6 @@ local function drop_attached_node(p)
drops = drop_stacks
def.preserve_metadata(pos_copy, node_copy, oldmeta, drops)
end
if def and def.sounds and def.sounds.fall then
core.sound_play(def.sounds.fall, {pos = p}, true)
end
core.remove_node(p)
for _, item in pairs(drops) do
local pos = {

View File

@@ -12,10 +12,6 @@ core.features = {
no_chat_message_prediction = true,
object_use_texture_alpha = true,
object_independent_selectionbox = true,
httpfetch_binary_data = true,
formspec_version_element = true,
area_store_persistent_ids = true,
pathfinder_works = true,
}
function core.has_feature(arg)

View File

@@ -8,9 +8,6 @@ local blocks_forceloaded
local blocks_temploaded = {}
local total_forceloaded = 0
-- true, if the forceloaded blocks got changed (flag for persistence on-disk)
local forceload_blocks_changed = false
local BLOCKSIZE = core.MAP_BLOCKSIZE
local function get_blockpos(pos)
return {
@@ -34,9 +31,6 @@ local function get_relevant_tables(transient)
end
function core.forceload_block(pos, transient)
-- set changed flag
forceload_blocks_changed = true
local blockpos = get_blockpos(pos)
local hash = core.hash_node_position(blockpos)
local relevant_table, other_table = get_relevant_tables(transient)
@@ -57,9 +51,6 @@ function core.forceload_block(pos, transient)
end
function core.forceload_free_block(pos, transient)
-- set changed flag
forceload_blocks_changed = true
local blockpos = get_blockpos(pos)
local hash = core.hash_node_position(blockpos)
local relevant_table, other_table = get_relevant_tables(transient)
@@ -104,28 +95,6 @@ core.after(5, function()
end
end)
-- persists the currently forceloaded blocks to disk
local function persist_forceloaded_blocks()
core.register_on_shutdown(function()
write_file(wpath.."/force_loaded.txt", blocks_forceloaded)
end
-- periodical forceload persistence
local function periodically_persist_forceloaded_blocks()
-- only persist if the blocks actually changed
if forceload_blocks_changed then
persist_forceloaded_blocks()
-- reset changed flag
forceload_blocks_changed = false
end
-- recheck after some time
core.after(10, periodically_persist_forceloaded_blocks)
end
-- persist periodically
core.after(5, periodically_persist_forceloaded_blocks)
-- persist on shutdown
core.register_on_shutdown(persist_forceloaded_blocks)
end)

View File

@@ -1,38 +1,36 @@
local scriptpath = core.get_builtin_path()
local commonpath = scriptpath .. "common" .. DIR_DELIM
local gamepath = scriptpath .. "game".. DIR_DELIM
local commonpath = scriptpath.."common"..DIR_DELIM
local gamepath = scriptpath.."game"..DIR_DELIM
-- Shared between builtin files, but
-- not exposed to outer context
local builtin_shared = {}
dofile(commonpath .. "vector.lua")
dofile(commonpath.."vector.lua")
dofile(gamepath .. "constants.lua")
assert(loadfile(gamepath .. "item.lua"))(builtin_shared)
dofile(gamepath .. "register.lua")
dofile(gamepath.."constants.lua")
assert(loadfile(gamepath.."item.lua"))(builtin_shared)
dofile(gamepath.."register.lua")
if core.settings:get_bool("profiler.load") then
profiler = dofile(scriptpath .. "profiler" .. DIR_DELIM .. "init.lua")
profiler = dofile(scriptpath.."profiler"..DIR_DELIM.."init.lua")
end
dofile(commonpath .. "after.lua")
dofile(gamepath .. "item_entity.lua")
dofile(gamepath .. "deprecated.lua")
dofile(gamepath .. "misc.lua")
dofile(gamepath .. "privileges.lua")
dofile(gamepath .. "auth.lua")
dofile(gamepath.."item_entity.lua")
dofile(gamepath.."deprecated.lua")
dofile(gamepath.."misc.lua")
dofile(gamepath.."privileges.lua")
dofile(gamepath.."auth.lua")
dofile(commonpath .. "chatcommands.lua")
dofile(gamepath .. "chat.lua")
dofile(commonpath .. "information_formspecs.lua")
dofile(gamepath .. "static_spawn.lua")
dofile(gamepath .. "detached_inventory.lua")
assert(loadfile(gamepath .. "falling.lua"))(builtin_shared)
dofile(gamepath .. "features.lua")
dofile(gamepath .. "voxelarea.lua")
dofile(gamepath .. "forceloading.lua")
dofile(gamepath .. "statbars.lua")
dofile(gamepath .. "knockback.lua")
dofile(gamepath.."chatcommands.lua")
dofile(gamepath.."static_spawn.lua")
dofile(gamepath.."detached_inventory.lua")
assert(loadfile(gamepath.."falling.lua"))(builtin_shared)
dofile(gamepath.."features.lua")
dofile(gamepath.."voxelarea.lua")
dofile(gamepath.."forceloading.lua")
dofile(gamepath.."statbars.lua")
profiler = nil

View File

@@ -206,6 +206,7 @@ function core.get_node_drops(node, toolname)
-- Extended drop table
local got_items = {}
local got_count = 0
local _, item, tool
for _, item in ipairs(drop.items) do
local good_rarity = true
local good_tool = true
@@ -250,6 +251,11 @@ 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
@@ -259,7 +265,7 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2,
prevent_after_place)
local def = itemstack:get_definition()
if def.type ~= "node" or pointed_thing.type ~= "node" then
return itemstack, nil
return itemstack, false
end
local under = pointed_thing.under
@@ -272,7 +278,7 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2,
if not oldnode_under or not oldnode_above then
log("info", playername .. " tried to place"
.. " node in unloaded position " .. core.pos_to_string(above))
return itemstack, nil
return itemstack, false
end
local olddef_under = core.registered_nodes[oldnode_under.name]
@@ -284,7 +290,7 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2,
log("info", playername .. " tried to place"
.. " node in invalid position " .. core.pos_to_string(above)
.. ", replacing " .. oldnode_above.name)
return itemstack, nil
return itemstack, false
end
-- Place above pointed node
@@ -296,15 +302,18 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2,
place_to = {x = under.x, y = under.y, z = under.z}
end
if core.is_protected(place_to, playername) then
if is_protected(place_to, playername) then
log("action", playername
.. " tried to place " .. def.name
.. " at protected position "
.. core.pos_to_string(place_to))
core.record_protection_violation(place_to, playername)
return itemstack, nil
return itemstack
end
log("action", playername .. " places node "
.. def.name .. " at " .. core.pos_to_string(place_to))
local oldnode = core.get_node(place_to)
local newnode = {name = def.name, param1 = 0, param2 = param2 or 0}
@@ -330,7 +339,7 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2,
z = above.z - placer_pos.z
}
newnode.param2 = core.dir_to_facedir(dir)
log("info", "facedir: " .. newnode.param2)
log("action", "facedir: " .. newnode.param2)
end
end
@@ -358,23 +367,12 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2,
not builtin_shared.check_attached_node(place_to, newnode) then
log("action", "attached node " .. def.name ..
" can not be placed at " .. core.pos_to_string(place_to))
return itemstack, nil
return itemstack, false
end
log("action", playername .. " places node "
.. def.name .. " at " .. core.pos_to_string(place_to))
-- Add node and update
core.add_node(place_to, newnode)
-- Play sound if it was done by a player
if playername ~= "" and def.sounds and def.sounds.place then
core.sound_play(def.sounds.place, {
pos = place_to,
exclude_player = playername,
}, true)
end
local take_item = true
-- Run callback
@@ -403,10 +401,9 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2,
if take_item then
itemstack:take_item()
end
return itemstack, place_to
return itemstack, true
end
-- deprecated, item_place does not call this
function core.item_place_object(itemstack, placer, pointed_thing)
local pos = core.get_pointed_thing_position(pointed_thing, true)
if pos ~= nil then
@@ -424,15 +421,14 @@ function core.item_place(itemstack, placer, pointed_thing, param2)
local nn = n.name
if core.registered_nodes[nn] and core.registered_nodes[nn].on_rightclick then
return core.registered_nodes[nn].on_rightclick(pointed_thing.under, n,
placer, itemstack, pointed_thing) or itemstack, nil
placer, itemstack, pointed_thing) or itemstack, false
end
end
-- Place if node, otherwise do nothing
if itemstack:get_definition().type == "node" then
return core.item_place_node(itemstack, placer, pointed_thing, param2)
end
return itemstack, nil
return itemstack
end
function core.item_secondary_use(itemstack, placer)
@@ -470,15 +466,12 @@ function core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed
return result
end
end
local def = itemstack:get_definition()
if itemstack:take_item() ~= nil then
user:set_hp(user:get_hp() + hp_change)
local def = itemstack:get_definition()
if def and def.sound and def.sound.eat then
core.sound_play(def.sound.eat, {
pos = user:get_pos(),
max_hear_distance = 16
}, true)
minetest.sound_play(def.sound.eat, { pos = user:get_pos(), max_hear_distance = 16 })
end
if replace_with_item then
@@ -559,7 +552,7 @@ function core.node_dig(pos, node, digger)
return
end
if core.is_protected(pos, diggername) then
if is_protected(pos, diggername) then
log("action", diggername
.. " tried to dig " .. node.name
.. " at protected position "
@@ -585,10 +578,7 @@ function core.node_dig(pos, node, digger)
if not core.settings:get_bool("creative_mode") then
wielded:add_wear(dp.wear)
if wielded:get_count() == 0 and wdef.sound and wdef.sound.breaks then
core.sound_play(wdef.sound.breaks, {
pos = pos,
gain = 0.5
}, true)
core.sound_play(wdef.sound.breaks, {pos = pos, gain = 0.5})
end
end
end
@@ -620,14 +610,6 @@ function core.node_dig(pos, node, digger)
-- Remove node and update
core.remove_node(pos)
-- Play sound if it was done by a player
if diggername ~= "" and def and def.sounds and def.sounds.dug then
core.sound_play(def.sounds.dug, {
pos = pos,
exclude_player = diggername,
}, true)
end
-- Run callback
if def and def.after_dig_node then
-- Copy pos and node because callback can modify them
@@ -637,10 +619,15 @@ function core.node_dig(pos, node, digger)
end
-- Run script hook
local _, callback
for _, callback in ipairs(core.registered_on_dignodes) do
local origin = core.callback_origins[callback]
if origin then
core.set_last_run_mod(origin.mod)
--print("Running " .. tostring(callback) ..
-- " (a " .. origin.name .. " callback in " .. origin.mod .. ")")
else
--print("No data associated with callback")
end
-- Copy pos and node because callback can modify them

View File

@@ -35,12 +35,7 @@ core.register_entity(":__builtin:item", {
itemstring = "",
moving_state = true,
slippery_state = false,
physical_state = true,
-- Item expiry
age = 0,
-- Pushing item out of solid nodes
force_out = nil,
force_out_start = nil,
set_item = function(self, item)
local stack = ItemStack(item or self.itemstring)
@@ -58,8 +53,6 @@ core.register_entity(":__builtin:item", {
local count = math.min(stack:get_count(), max_count)
local size = 0.2 + 0.1 * (count / max_count) ^ (1 / 3)
local coll_height = size * 0.75
local def = core.registered_nodes[itemname]
local glow = def and math.floor(def.light_source / 2 + 0.5)
self.object:set_properties({
is_visible = true,
@@ -71,7 +64,6 @@ core.register_entity(":__builtin:item", {
selectionbox = {-size, -size, -size, size, size, size},
automatic_rotate = math.pi * 0.5 * 0.2 / size,
wield_item = self.itemstring,
glow = glow,
})
end,
@@ -139,24 +131,6 @@ core.register_entity(":__builtin:item", {
return true
end,
enable_physics = function(self)
if not self.physical_state then
self.physical_state = true
self.object:set_properties({physical = true})
self.object:set_velocity({x=0, y=0, z=0})
self.object:set_acceleration({x=0, y=-gravity, z=0})
end
end,
disable_physics = function(self)
if self.physical_state then
self.physical_state = false
self.object:set_properties({physical = false})
self.object:set_velocity({x=0, y=0, z=0})
self.object:set_acceleration({x=0, y=0, z=0})
end
end,
on_step = function(self, dtime)
self.age = self.age + dtime
if time_to_live > 0 and self.age > time_to_live then
@@ -178,74 +152,6 @@ core.register_entity(":__builtin:item", {
return
end
local is_stuck = false
local snode = core.get_node_or_nil(pos)
if snode then
local sdef = core.registered_nodes[snode.name] or {}
is_stuck = (sdef.walkable == nil or sdef.walkable == true)
and (sdef.collision_box == nil or sdef.collision_box.type == "regular")
and (sdef.node_box == nil or sdef.node_box.type == "regular")
end
-- Push item out when stuck inside solid node
if is_stuck then
local shootdir
local order = {
{x=1, y=0, z=0}, {x=-1, y=0, z= 0},
{x=0, y=0, z=1}, {x= 0, y=0, z=-1},
}
-- Check which one of the 4 sides is free
for o = 1, #order do
local cnode = core.get_node(vector.add(pos, order[o])).name
local cdef = core.registered_nodes[cnode] or {}
if cnode ~= "ignore" and cdef.walkable == false then
shootdir = order[o]
break
end
end
-- If none of the 4 sides is free, check upwards
if not shootdir then
shootdir = {x=0, y=1, z=0}
local cnode = core.get_node(vector.add(pos, shootdir)).name
if cnode == "ignore" then
shootdir = nil -- Do not push into ignore
end
end
if shootdir then
-- Set new item moving speed accordingly
local newv = vector.multiply(shootdir, 3)
self:disable_physics()
self.object:set_velocity(newv)
self.force_out = newv
self.force_out_start = vector.round(pos)
return
end
elseif self.force_out then
-- This code runs after the entity got a push from the above code.
-- It makes sure the entity is entirely outside the solid node
local c = self.object:get_properties().collisionbox
local s = self.force_out_start
local f = self.force_out
local ok = (f.x > 0 and pos.x + c[1] > s.x + 0.5) or
(f.y > 0 and pos.y + c[2] > s.y + 0.5) or
(f.z > 0 and pos.z + c[3] > s.z + 0.5) or
(f.x < 0 and pos.x + c[4] < s.x - 0.5) or
(f.z < 0 and pos.z + c[6] < s.z - 0.5)
if ok then
-- Item was successfully forced out
self.force_out = nil
self:enable_physics()
end
end
if not self.physical_state then
return -- Don't do anything
end
-- Slide on slippery nodes
local vel = self.object:get_velocity()
local def = node and core.registered_nodes[node.name]
local is_moving = (def and not def.walkable) or

View File

@@ -1,46 +0,0 @@
-- can be overriden by mods
function core.calculate_knockback(player, hitter, time_from_last_punch, tool_capabilities, dir, distance, damage)
if damage == 0 or player:get_armor_groups().immortal then
return 0.0
end
local m = 8
-- solve m - m*e^(k*4) = 4 for k
local k = -0.17328
local res = m - m * math.exp(k * damage)
if distance < 2.0 then
res = res * 1.1 -- more knockback when closer
elseif distance > 4.0 then
res = res * 0.9 -- less when far away
end
return res
end
local function vector_absmax(v)
local max, abs = math.max, math.abs
return max(max(abs(v.x), abs(v.y)), abs(v.z))
end
core.register_on_punchplayer(function(player, hitter, time_from_last_punch, tool_capabilities, unused_dir, damage)
if player:get_hp() == 0 then
return -- RIP
end
-- Server::handleCommand_Interact() adds eye offset to one but not the other
-- so the direction is slightly off, calculate it ourselves
local dir = vector.subtract(player:get_pos(), hitter:get_pos())
local d = vector.length(dir)
if d ~= 0.0 then
dir = vector.divide(dir, d)
end
local k = core.calculate_knockback(player, hitter, time_from_last_punch, tool_capabilities, dir, d, damage)
local kdir = vector.multiply(dir, k)
if vector_absmax(kdir) < 1.0 then
return -- barely noticeable, so don't even send
end
player:add_player_velocity(kdir)
end)

View File

@@ -40,6 +40,9 @@ function core.check_player_privs(name, ...)
end
local player_list = {}
function core.send_join_message(player_name)
if not core.is_singleplayer() then
core.chat_send_all("*** " .. player_name .. " joined the game.")
@@ -58,7 +61,8 @@ end
core.register_on_joinplayer(function(player)
local player_name = player:get_player_name()
if not core.is_singleplayer() then
player_list[player_name] = player
if not minetest.is_singleplayer() then
local status = core.get_server_status(player_name, true)
if status and status ~= "" then
core.chat_send_player(player_name, status)
@@ -70,10 +74,22 @@ end)
core.register_on_leaveplayer(function(player, timed_out)
local player_name = player:get_player_name()
player_list[player_name] = nil
core.send_leave_message(player_name, timed_out)
end)
function core.get_connected_players()
local temp_table = {}
for index, value in pairs(player_list) do
if value:is_player_connected() then
temp_table[#temp_table + 1] = value
end
end
return temp_table
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

View File

@@ -18,7 +18,7 @@ function core.register_privilege(name, param)
def.description = "(no description)"
end
end
local def
local def = {}
if type(param) == "table" then
def = param
else

View File

@@ -79,7 +79,6 @@ end
function core.register_abm(spec)
-- Add to core.registered_abms
assert(type(spec.action) == "function", "Required field 'action' of type function")
core.registered_abms[#core.registered_abms + 1] = spec
spec.mod_origin = core.get_current_modname() or "??"
end
@@ -87,7 +86,6 @@ end
function core.register_lbm(spec)
-- Add to core.registered_lbms
check_modname_prefix(spec.name)
assert(type(spec.action) == "function", "Required field 'action' of type function")
core.registered_lbms[#core.registered_lbms + 1] = spec
spec.mod_origin = core.get_current_modname() or "??"
end
@@ -256,18 +254,6 @@ function core.register_tool(name, tooldef)
end
-- END Legacy stuff
-- This isn't just legacy, but more of a convenience feature
local toolcaps = tooldef.tool_capabilities
if toolcaps and toolcaps.punch_attack_uses == nil then
for _, cap in pairs(toolcaps.groupcaps or {}) do
local level = (cap.maxlevel or 0) - 1
if (cap.uses or 0) ~= 0 and level >= 0 then
toolcaps.punch_attack_uses = cap.uses * (3 ^ level)
break
end
end
end
core.register_item(name, tooldef)
end
@@ -315,17 +301,18 @@ end
-- Alias the forbidden item names to "" so they can't be
-- created via itemstrings (e.g. /give)
local name
for name in pairs(forbidden_item_names) do
core.registered_aliases[name] = ""
register_alias_raw(name, "")
end
-- Obsolete:
-- Deprecated:
-- Aliases for core.register_alias (how ironic...)
-- core.alias_node = core.register_alias
-- core.alias_tool = core.register_alias
-- core.alias_craftitem = core.register_alias
--core.alias_node = core.register_alias
--core.alias_tool = core.register_alias
--core.alias_craftitem = core.register_alias
--
-- Built-in node definitions. Also defined in C.
@@ -374,9 +361,9 @@ core.register_node(":ignore", {
drop = "",
groups = {not_in_creative_inventory=1},
on_place = function(itemstack, placer, pointed_thing)
core.chat_send_player(
minetest.chat_send_player(
placer:get_player_name(),
core.colorize("#FF0000",
minetest.colorize("#FF0000",
"You can't place 'ignore' nodes!"))
return ""
end,
@@ -385,7 +372,6 @@ core.register_node(":ignore", {
-- The hand (bare definition)
core.register_item(":", {
type = "none",
wield_image = "wieldhand.png",
groups = {not_in_creative_inventory=1},
})
@@ -425,6 +411,10 @@ function core.run_callbacks(callbacks, mode, ...)
local origin = core.callback_origins[callbacks[i]]
if origin then
core.set_last_run_mod(origin.mod)
--print("Running " .. tostring(callbacks[i]) ..
-- " (a " .. origin.name .. " callback in " .. origin.mod .. ")")
else
--print("No data associated with callback")
end
local cb_ret = callbacks[i](...)
@@ -524,17 +514,11 @@ local function make_registration_wrap(reg_fn_name, clear_fn_name)
end
local function make_wrap_deregistration(reg_fn, clear_fn, list)
local unregister = function (key)
if type(key) ~= "string" then
error("key is not a string", 2)
end
if not list[key] then
error("Attempt to unregister non-existent element - '" .. key .. "'", 2)
end
local unregister = function (unregistered_key)
local temporary_list = table.copy(list)
clear_fn()
for k,v in pairs(temporary_list) do
if key ~= k then
if unregistered_key ~= k then
reg_fn(v)
end
end
@@ -545,7 +529,7 @@ end
core.registered_on_player_hpchanges = { modifiers = { }, loggers = { } }
function core.registered_on_player_hpchange(player, hp_change, reason)
local last
local last = false
for i = #core.registered_on_player_hpchanges.modifiers, 1, -1 do
local func = core.registered_on_player_hpchanges.modifiers[i]
hp_change, last = func(player, hp_change, reason)
@@ -580,8 +564,7 @@ core.registered_biomes = make_registration_wrap("register_biome", "cle
core.registered_ores = make_registration_wrap("register_ore", "clear_registered_ores")
core.registered_decorations = make_registration_wrap("register_decoration", "clear_registered_decorations")
core.unregister_biome = make_wrap_deregistration(core.register_biome,
core.clear_registered_biomes, core.registered_biomes)
core.unregister_biome = make_wrap_deregistration(core.register_biome, core.clear_registered_biomes, core.registered_biomes)
core.registered_on_chat_messages, core.register_on_chat_message = make_registration()
core.registered_globalsteps, core.register_globalstep = make_registration()

View File

@@ -1,7 +1,8 @@
-- cache setting
local enable_damage = core.settings:get_bool("enable_damage")
local health_bar_definition = {
local health_bar_definition =
{
hud_elem_type = "statbar",
position = { x=0.5, y=1 },
text = "heart.png",
@@ -11,7 +12,8 @@ local health_bar_definition = {
offset = { x=(-10*24)-25, y=-(48+24+16)},
}
local breath_bar_definition = {
local breath_bar_definition =
{
hud_elem_type = "statbar",
position = { x=0.5, y=1 },
text = "bubble.png",
@@ -28,8 +30,8 @@ local function scaleToDefault(player, field)
local current = player["get_" .. field](player)
local nominal = core["PLAYER_MAX_".. field:upper() .. "_DEFAULT"]
local max_display = math.max(nominal,
math.max(player:get_properties()[field .. "_max"], current))
return current / max_display * nominal
math.max(player:get_properties()[field .. "_max"], current))
return current / max_display * nominal
end
local function update_builtin_statbars(player)
@@ -48,11 +50,10 @@ local function update_builtin_statbars(player)
end
local hud = hud_ids[name]
local immortal = player:get_armor_groups().immortal == 1
if flags.healthbar and enable_damage and not immortal then
if flags.healthbar and enable_damage then
local number = scaleToDefault(player, "hp")
if hud.id_healthbar == nil then
local hud_def = table.copy(health_bar_definition)
if hud.id_healthbar == nil then
local hud_def = table.copy(health_bar_definition)
hud_def.number = number
hud.id_healthbar = player:hud_add(hud_def)
else
@@ -64,11 +65,11 @@ local function update_builtin_statbars(player)
end
local breath_max = player:get_properties().breath_max
if flags.breathbar and enable_damage and not immortal and
if flags.breathbar and enable_damage and
player:get_breath() < breath_max then
local number = 2 * scaleToDefault(player, "breath")
if hud.id_breathbar == nil then
local hud_def = table.copy(breath_bar_definition)
local hud_def = table.copy(breath_bar_definition)
hud_def.number = number
hud.id_breathbar = player:hud_add(hud_def)
else
@@ -115,7 +116,7 @@ local function player_event_handler(player,eventname)
end
end
if eventname == "hud_changed" or eventname == "properties_changed" then
if eventname == "hud_changed" then
update_builtin_statbars(player)
return true
end
@@ -123,14 +124,14 @@ local function player_event_handler(player,eventname)
return false
end
function core.hud_replace_builtin(hud_name, definition)
function core.hud_replace_builtin(name, definition)
if type(definition) ~= "table" or
definition.hud_elem_type ~= "statbar" then
return false
end
if hud_name == "health" then
if name == "health" then
health_bar_definition = definition
for name, ids in pairs(hud_ids) do
@@ -144,7 +145,7 @@ function core.hud_replace_builtin(hud_name, definition)
return true
end
if hud_name == "breath" then
if name == "breath" then
breath_bar_definition = definition
for name, ids in pairs(hud_ids) do

View File

@@ -93,9 +93,9 @@ function render_serverlist_row(spec, is_favorite)
end
end
local details = ""
local grey_out = not is_server_protocol_compat(spec.proto_min, spec.proto_max)
local details
if is_favorite then
details = "1,"
else
@@ -118,11 +118,11 @@ function render_serverlist_row(spec, is_favorite)
end
if spec.clients and spec.clients_max then
local clients_color = ''
local clients_percent = 100 * spec.clients / spec.clients_max
-- Choose a color depending on how many clients are connected
-- (relatively to clients_max)
local clients_color
if grey_out then clients_color = '#aaaaaa'
elseif spec.clients == 0 then clients_color = '' -- 0 players: default/white
elseif clients_percent <= 60 then clients_color = '#a1e587' -- 0-60%: green
@@ -171,7 +171,6 @@ os.tempfolder = function()
local filetocheck = os.tmpname()
os.remove(filetocheck)
-- luacheck: ignore
-- https://blogs.msdn.microsoft.com/vcblog/2014/06/18/c-runtime-crt-features-fixes-and-breaking-changes-in-visual-studio-14-ctp1/
-- The C runtime (CRT) function called by os.tmpname is tmpnam.
-- Microsofts tmpnam implementation in older CRT / MSVC releases is defective.

View File

@@ -31,6 +31,8 @@ local function get_formspec(data)
"label[0.5,0;" .. fgettext("World:") .. "]" ..
"label[1.75,0;" .. data.worldspec.name .. "]"
local hard_deps, soft_deps = pkgmgr.get_dependencies(mod.path)
if mod.is_modpack or mod.type == "game" then
local info = minetest.formspec_escape(
core.get_content_info(mod.path).description)
@@ -44,46 +46,15 @@ local function get_formspec(data)
retval = retval ..
"textarea[0.25,0.7;5.75,7.2;;" .. info .. ";]"
else
local hard_deps, soft_deps = pkgmgr.get_dependencies(mod.path)
local hard_deps_str = table.concat(hard_deps, ",")
local soft_deps_str = table.concat(soft_deps, ",")
retval = retval ..
"label[0,0.7;" .. fgettext("Mod:") .. "]" ..
"label[0.75,0.7;" .. mod.name .. "]"
if hard_deps_str == "" then
if soft_deps_str == "" then
retval = retval ..
"label[0,1.25;" ..
fgettext("No (optional) dependencies") .. "]"
else
retval = retval ..
"label[0,1.25;" .. fgettext("No hard dependencies") ..
"]" ..
"label[0,1.75;" .. fgettext("Optional dependencies:") ..
"]" ..
"textlist[0,2.25;5,4;world_config_optdepends;" ..
soft_deps_str .. ";0]"
end
else
if soft_deps_str == "" then
retval = retval ..
"label[0,1.25;" .. fgettext("Dependencies:") .. "]" ..
"textlist[0,1.75;5,4;world_config_depends;" ..
hard_deps_str .. ";0]" ..
"label[0,6;" .. fgettext("No optional dependencies") .. "]"
else
retval = retval ..
"label[0,1.25;" .. fgettext("Dependencies:") .. "]" ..
"textlist[0,1.75;5,2.125;world_config_depends;" ..
hard_deps_str .. ";0]" ..
"label[0,3.9;" .. fgettext("Optional dependencies:") ..
"]" ..
"textlist[0,4.375;5,1.8;world_config_optdepends;" ..
soft_deps_str .. ";0]"
end
end
"label[0.75,0.7;" .. mod.name .. "]" ..
"label[0,1.25;" .. fgettext("Dependencies:") .. "]" ..
"textlist[0,1.75;5,2.125;world_config_depends;" .. hard_deps ..
";0]" ..
"label[0,3.875;" .. fgettext("Optional dependencies:") .. "]" ..
"textlist[0,4.375;5,1.8;world_config_optdepends;" ..
soft_deps .. ";0]"
end
retval = retval ..
"button[3.25,7;2.5,0.5;btn_config_world_save;" ..

View File

@@ -96,16 +96,19 @@ local function start_install(calling_dialog, package)
if conf_path then
local conf = Settings(conf_path)
local function set_def(key, value)
if conf:get(key) == nil then
conf:set(key, value)
end
end
if name_is_title then
conf:set("name", result.package.title)
set_def("name", result.package.title)
else
conf:set("title", result.package.title)
conf:set("name", result.package.name)
set_def("title", result.package.title)
set_def("name", result.package.name)
end
if not conf:get("description") then
conf:set("description", result.package.short_description)
end
conf:set("author", result.package.author)
set_def("description", result.package.short_description)
set_def("author", result.package.author)
conf:set("release", result.package.release)
conf:write()
end
@@ -270,6 +273,7 @@ function store.load()
assert(core.create_dir(tmpdir))
local base_url = core.settings:get("contentdb_url")
local show_nonfree = core.settings:get_bool("show_nonfree_packages")
local url = base_url ..
"/api/packages/?type=mod&type=game&type=txp&protocol_version=" ..
core.get_max_supp_proto()
@@ -295,9 +299,9 @@ function store.load()
local name_len = #package.name
if package.type == "game" and name_len > 5 and package.name:sub(name_len - 4) == "_game" then
package.id = package.author:lower() .. "/" .. package.name:sub(1, name_len - 5)
package.id = package.author .. "/" .. package.name:sub(1, name_len - 5)
else
package.id = package.author:lower() .. "/" .. package.name
package.id = package.author .. "/" .. package.name
end
end
@@ -313,22 +317,22 @@ function store.update_paths()
pkgmgr.refresh_globals()
for _, mod in pairs(pkgmgr.global_mods:get_list()) do
if mod.author then
mod_hash[mod.author:lower() .. "/" .. mod.name] = mod
mod_hash[mod.author .. "/" .. mod.name] = mod
end
end
local game_hash = {}
pkgmgr.update_gamelist()
for _, game in pairs(pkgmgr.games) do
if game.author ~= "" then
game_hash[game.author:lower() .. "/" .. game.id] = game
if game.author then
game_hash[game.author .. "/" .. game.id] = game
end
end
local txp_hash = {}
for _, txp in pairs(pkgmgr.get_texture_packs()) do
if txp.author then
txp_hash[txp.author:lower() .. "/" .. txp.name] = txp
txp_hash[txp.author .. "/" .. txp.name] = txp
end
end

View File

@@ -24,11 +24,10 @@ local function create_world_formspec(dialogdata)
local current_mg = core.settings:get("mg_name")
local gameid = core.settings:get("menu_last_game")
local gameidx = 0
local game, gameidx = nil , 0
if gameid ~= nil then
local _
_, gameidx = pkgmgr.find_by_gameid(gameid)
game, gameidx = pkgmgr.find_by_gameid(gameid)
if gameidx == nil then
gameidx = 0
end
@@ -83,7 +82,7 @@ local function create_world_formspec(dialogdata)
"button[3.25,6;2.5,0.5;world_create_confirm;" .. fgettext("Create") .. "]" ..
"button[5.75,6;2.5,0.5;world_create_cancel;" .. fgettext("Cancel") .. "]"
if #pkgmgr.games == 0 then
retval = retval .. "box[2,4;8,1;#ff8800]label[2.25,4;" ..
fgettext("You have no games installed.") .. "]label[2.25,4.4;" ..
@@ -112,10 +111,10 @@ local function create_world_buttonhandler(this, fields)
local random_world_name = "Unnamed" .. random_number
worldname = random_world_name
end
local message = nil
core.settings:set("fixed_map_seed", fields["te_seed"])
local message
if not menudata.worldlist:uid_exists_raw(worldname) then
core.settings:set("mg_name",fields["dd_mapgen"])
message = core.create_world(worldname,gameindex)
@@ -166,6 +165,6 @@ function create_create_world_dlg(update_worldlistfilter)
create_world_buttonhandler,
nil)
retval.update_worldlist_filter = update_worldlistfilter
return retval
end

View File

@@ -22,7 +22,6 @@ local function delete_content_formspec(dialogdata)
"size[11.5,4.5,true]" ..
"label[2,2;" ..
fgettext("Are you sure you want to delete \"$1\"?", dialogdata.content.name) .. "]"..
"style[dlg_delete_content_confirm;bgcolor=red]" ..
"button[3.25,3.5;2.5,0.5;dlg_delete_content_confirm;" .. fgettext("Delete") .. "]" ..
"button[5.75,3.5;2.5,0.5;dlg_delete_content_cancel;" .. fgettext("Cancel") .. "]"

View File

@@ -21,7 +21,6 @@ local function delete_world_formspec(dialogdata)
"size[10,2.5,true]" ..
"label[0.5,0.5;" ..
fgettext("Delete World \"$1\"?", dialogdata.delete_name) .. "]" ..
"style[world_delete_confirm;bgcolor=red]" ..
"button[0.5,1.5;2.5,0.5;world_delete_confirm;" .. fgettext("Delete") .. "]" ..
"button[7.0,1.5;2.5,0.5;world_delete_cancel;" .. fgettext("Cancel") .. "]"
return retval

View File

@@ -148,9 +148,9 @@ local function parse_setting_line(settings, line, read_all, base_level, allow_se
local values = {}
local ti = 1
local index = 1
for match in default:gmatch("[+-]?[%d.-e]+") do -- All numeric characters
index = default:find("[+-]?[%d.-e]+", index) + match:len()
table.insert(values, match)
for line in default:gmatch("[+-]?[%d.-e]+") do -- All numeric characters
index = default:find("[+-]?[%d.-e]+", index) + line:len()
table.insert(values, line)
ti = ti + 1
if ti > 9 then
break
@@ -322,21 +322,18 @@ end
-- read_all: whether to ignore certain setting types for GUI or not
-- parse_mods: whether to parse settingtypes.txt in mods and games
local function parse_config_file(read_all, parse_mods)
local builtin_path = core.get_builtin_path() .. FILENAME
local file = io.open(builtin_path, "r")
local settings = {}
do
local builtin_path = core.get_builtin_path() .. FILENAME
local file = io.open(builtin_path, "r")
if not file then
core.log("error", "Can't load " .. FILENAME)
return settings
end
parse_single_file(file, builtin_path, read_all, settings, 0, true)
file:close()
if not file then
core.log("error", "Can't load " .. FILENAME)
return settings
end
parse_single_file(file, builtin_path, read_all, settings, 0, true)
file:close()
if parse_mods then
-- Parse games
local games_category_initialized = false
@@ -347,7 +344,7 @@ local function parse_config_file(read_all, parse_mods)
local file = io.open(path, "r")
if file then
if not games_category_initialized then
fgettext_ne("Games") -- not used, but needed for xgettext
local translation = fgettext_ne("Games"), -- not used, but needed for xgettext
table.insert(settings, {
name = "Games",
level = 0,
@@ -380,7 +377,7 @@ local function parse_config_file(read_all, parse_mods)
local file = io.open(path, "r")
if file then
if not mods_category_initialized then
fgettext_ne("Mods") -- not used, but needed for xgettext
local translation = fgettext_ne("Mods"), -- not used, but needed for xgettext
table.insert(settings, {
name = "Mods",
level = 0,
@@ -639,23 +636,12 @@ local function create_change_setting_formspec(dialogdata)
-- Flags
formspec = table.concat(fields)
.. "checkbox[0.5," .. height - 0.6 .. ";cb_defaults;"
--[[~ "defaults" is a noise parameter flag.
It describes the default processing options
for noise settings in main menu -> "All Settings". ]]
.. fgettext("defaults") .. ";" -- defaults
.. tostring(flags["defaults"] == true) .. "]" -- to get false if nil
.. "checkbox[5," .. height - 0.6 .. ";cb_eased;"
--[[~ "eased" is a noise parameter flag.
It is used to make the map smoother and
can be enabled in noise settings in
main menu -> "All Settings". ]]
.. fgettext("eased") .. ";" -- eased
.. tostring(flags["eased"] == true) .. "]"
.. "checkbox[5," .. height - 0.15 .. ";cb_absvalue;"
--[[~ "absvalue" is a noise parameter flag.
It is short for "absolute value".
It can be enabled in noise settings in
main menu -> "All Settings". ]]
.. fgettext("absvalue") .. ";" -- absvalue
.. tostring(flags["absvalue"] == true) .. "]"
height = height + 1
@@ -681,42 +667,34 @@ local function create_change_setting_formspec(dialogdata)
height = height + 1.1
elseif setting.type == "flags" then
local current_flags = flags_to_table(get_current_value(setting))
local enabled_flags = flags_to_table(get_current_value(setting))
local flags = {}
for _, name in ipairs(current_flags) do
for _, name in ipairs(enabled_flags) do
-- Index by name, to avoid iterating over all enabled_flags for every possible flag.
if name:sub(1, 2) == "no" then
flags[name:sub(3)] = false
else
flags[name] = true
end
flags[name] = true
end
local flags_count = #setting.possible / 2
local max_height = math.ceil(flags_count / 2) / 2
local flags_count = #setting.possible
local max_height = flags_count / 4
-- More space for flags
description_height = description_height - 1
height = height - 1
local fields = {} -- To build formspec
local j = 1
for _, name in ipairs(setting.possible) do
if name:sub(1, 2) ~= "no" then
local x = 0.5
local y = height + j / 2 - 0.75
if j - 1 >= flags_count / 2 then -- 2nd column
x = 5
y = y - max_height
end
j = j + 1;
local checkbox_name = "cb_" .. name
local is_enabled = flags[name] == true -- to get false if nil
checkboxes[checkbox_name] = is_enabled
fields[#fields + 1] = ("checkbox[%f,%f;%s;%s;%s]"):format(
x, y, checkbox_name, name, tostring(is_enabled)
)
for i, name in ipairs(setting.possible) do
local x = 0.5
local y = height + i / 2 - 0.75
if i - 1 >= flags_count / 2 then -- 2nd column
x = 5
y = y - max_height
end
local checkbox_name = "cb_" .. name
local is_enabled = flags[name] == true -- to get false if nil
checkboxes[checkbox_name] = is_enabled
fields[#fields + 1] = ("checkbox[%f,%f;%s;%s;%s]"):format(
x, y, checkbox_name, name, tostring(is_enabled)
)
end
formspec = table.concat(fields)
height = height + max_height + 0.25
@@ -775,7 +753,7 @@ local function create_change_setting_formspec(dialogdata)
" (" .. setting.name .. ")"
end
local comment_text
local comment_text = ""
if setting.comment == "" then
comment_text = fgettext_ne("(No description of setting given)")
else
@@ -852,12 +830,8 @@ local function handle_change_setting_buttons(this, fields)
elseif setting.type == "flags" then
local values = {}
for _, name in ipairs(setting.possible) do
if name:sub(1, 2) ~= "no" then
if checkboxes["cb_" .. name] then
table.insert(values, name)
else
table.insert(values, "no" .. name)
end
if checkboxes["cb_" .. name] then
table.insert(values, name)
end
end
@@ -944,7 +918,7 @@ local function handle_change_setting_buttons(this, fields)
return false
end
local function create_settings_formspec(tabview, _, tabdata)
local function create_settings_formspec(tabview, name, tabdata)
local formspec = "size[12,5.4;true]" ..
"tablecolumns[color;tree;text,width=28;text]" ..
"tableoptions[background=#00000000;border=false]" ..
@@ -976,7 +950,7 @@ local function create_settings_formspec(tabview, _, tabdata)
formspec = formspec .. "," .. (current_level + 1) .. "," .. core.formspec_escape(name) .. ","
.. value .. ","
elseif entry.type == "key" then --luacheck: ignore
elseif entry.type == "key" then
-- ignore key settings, since we have a special dialog for them
elseif entry.type == "noise_params_2d" or entry.type == "noise_params_3d" then
@@ -1055,8 +1029,8 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
if fields["btn_edit"] or list_enter then
local setting = settings[selected_setting]
if setting and setting.type ~= "category" then
local edit_dialog = dialog_create("change_setting",
create_change_setting_formspec, handle_change_setting_buttons)
local edit_dialog = dialog_create("change_setting", create_change_setting_formspec,
handle_change_setting_buttons)
edit_dialog:set_parent(this)
this:hide()
edit_dialog:show()
@@ -1102,5 +1076,4 @@ end
-- For RUN_IN_PLACE the generated files may appear in the 'bin' folder.
-- See comment and alternative line at the end of 'generate_from_settingtypes.lua'.
--assert(loadfile(core.get_builtin_path().."mainmenu"..DIR_DELIM..
-- "generate_from_settingtypes.lua"))(parse_config_file(true, false))
--assert(loadfile(core.get_builtin_path().."mainmenu"..DIR_DELIM.."generate_from_settingtypes.lua"))(parse_config_file(true, false))

View File

@@ -16,62 +16,6 @@
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
--------------------------------------------------------------------------------
local function get_last_folder(text,count)
local parts = text:split(DIR_DELIM)
if count == nil then
return parts[#parts]
end
local retval = ""
for i=1,count,1 do
retval = retval .. parts[#parts - (count-i)] .. DIR_DELIM
end
return retval
end
local function cleanup_path(temppath)
local parts = temppath:split("-")
temppath = ""
for i=1,#parts,1 do
if temppath ~= "" then
temppath = temppath .. "_"
end
temppath = temppath .. parts[i]
end
parts = temppath:split(".")
temppath = ""
for i=1,#parts,1 do
if temppath ~= "" then
temppath = temppath .. "_"
end
temppath = temppath .. parts[i]
end
parts = temppath:split("'")
temppath = ""
for i=1,#parts,1 do
if temppath ~= "" then
temppath = temppath .. ""
end
temppath = temppath .. parts[i]
end
parts = temppath:split(" ")
temppath = ""
for i=1,#parts,1 do
if temppath ~= "" then
temppath = temppath
end
temppath = temppath .. parts[i]
end
return temppath
end
function get_mods(path,retval,modpack)
local mods = core.get_dir_list(path, true)
@@ -341,14 +285,17 @@ function pkgmgr.identify_modname(modpath,filename)
end
--------------------------------------------------------------------------------
function pkgmgr.render_packagelist(render_list)
if not render_list then
if not pkgmgr.global_mods then
local retval = ""
if render_list == nil then
if pkgmgr.global_mods == nil then
pkgmgr.refresh_globals()
end
render_list = pkgmgr.global_mods
end
local list = render_list:get_list()
local last_modpack = nil
local retval = {}
for i, v in ipairs(list) do
local color = ""
@@ -385,11 +332,11 @@ end
--------------------------------------------------------------------------------
function pkgmgr.get_dependencies(path)
if path == nil then
return {}, {}
return "", ""
end
local info = core.get_content_info(path)
return info.depends or {}, info.optional_depends or {}
return table.concat(info.depends or {}, ","), table.concat(info.optional_depends or {}, ",")
end
----------- tests whether all of the mods in the modpack are enabled -----------
@@ -403,113 +350,35 @@ function pkgmgr.is_modpack_entirely_enabled(data, name)
return true
end
---------- toggles or en/disables a mod or modpack and its dependencies --------
---------- toggles or en/disables a mod or modpack -----------------------------
function pkgmgr.enable_mod(this, toset)
local list = this.data.list:get_list()
local mod = list[this.data.selected_mod]
local mod = this.data.list:get_list()[this.data.selected_mod]
-- Game mods can't be enabled or disabled
-- game mods can't be enabled or disabled
if mod.is_game_content then
return
end
local toggled_mods = {}
local enabled_mods = {}
-- toggle or en/disable the mod
if not mod.is_modpack then
-- Toggle or en/disable the mod
if toset == nil then
toset = not mod.enabled
end
if mod.enabled ~= toset then
mod.enabled = not mod.enabled
else
mod.enabled = toset
toggled_mods[#toggled_mods+1] = mod.name
end
if toset then
-- Mark this mod for recursive dependency traversal
enabled_mods[mod.name] = true
end
else
-- Toggle or en/disable every mod in the modpack,
-- interleaved unsupported
for i = 1, #list do
if list[i].modpack == mod.name then
if toset == nil then
toset = not list[i].enabled
end
if list[i].enabled ~= toset then
list[i].enabled = toset
toggled_mods[#toggled_mods+1] = list[i].name
end
if toset then
enabled_mods[list[i].name] = true
end
end
end
end
if not toset then
-- Mod(s) were disabled, so no dependencies need to be enabled
table.sort(toggled_mods)
minetest.log("info", "Following mods were disabled: " ..
table.concat(toggled_mods, ", "))
return
end
-- Enable mods' depends after activation
-- Make a list of mod ids indexed by their names
local mod_ids = {}
for id, mod2 in pairs(list) do
if mod2.type == "mod" and not mod2.is_modpack then
mod_ids[mod2.name] = id
end
end
-- to_enable is used as a DFS stack with sp as stack pointer
local to_enable = {}
local sp = 0
for name in pairs(enabled_mods) do
local depends = pkgmgr.get_dependencies(list[mod_ids[name]].path)
for i = 1, #depends do
local dependency_name = depends[i]
if not enabled_mods[dependency_name] then
sp = sp+1
to_enable[sp] = dependency_name
-- toggle or en/disable every mod in the modpack, interleaved unsupported
local list = this.data.list:get_raw_list()
for i = 1, #list do
if list[i].modpack == mod.name then
if toset == nil then
toset = not list[i].enabled
end
list[i].enabled = toset
end
end
-- If sp is 0, every dependency is already activated
while sp > 0 do
local name = to_enable[sp]
sp = sp-1
if not enabled_mods[name] then
enabled_mods[name] = true
local mod_to_enable = list[mod_ids[name]]
if not mod_to_enable then
minetest.log("warning", "Mod dependency \"" .. name ..
"\" not found!")
else
if mod_to_enable.enabled == false then
mod_to_enable.enabled = true
toggled_mods[#toggled_mods+1] = mod_to_enable.name
end
-- Push the dependencies of the dependency onto the stack
local depends = pkgmgr.get_dependencies(mod_to_enable.path)
for i = 1, #depends do
if not enabled_mods[name] then
sp = sp+1
to_enable[sp] = depends[i]
end
end
end
end
end
-- Log the list of enabled mods
table.sort(toggled_mods)
minetest.log("info", "Following mods were enabled: " ..
table.concat(toggled_mods, ", "))
end
--------------------------------------------------------------------------------
@@ -596,7 +465,7 @@ function pkgmgr.install_dir(type, path, basename, targetpath)
else
return nil,
fgettext("Install Mod: Unable to find suitable folder name for modpack $1",
path)
modfilename)
end
end
elseif basefolder.type == "mod" then
@@ -621,7 +490,7 @@ function pkgmgr.install_dir(type, path, basename, targetpath)
if targetfolder ~= nil and pkgmgr.isValidModname(targetfolder) then
targetpath = core.get_modpath() .. DIR_DELIM .. targetfolder
else
return nil, fgettext("Install Mod: Unable to find real mod name for: $1", path)
return nil, fgettext("Install Mod: Unable to find real mod name for: $1", modfilename)
end
end

View File

@@ -134,13 +134,9 @@ local function get_formspec(tabview, name, tabdata)
end
retval = retval .. "textarea[5.85,2.2;6.35,2.9;;" ..
fgettext("Information:") .. ";" .. desc .. "]"
if core.may_modify_path(selected_pkg.path) then
retval = retval ..
"button[5.5,4.65;3.25,1;btn_mod_mgr_delete_mod;" ..
fgettext("Uninstall Package") .. "]"
end
fgettext("Information:") .. ";" .. desc .. "]" ..
"button[5.5,4.65;3.25,1;btn_mod_mgr_delete_mod;" ..
fgettext("Uninstall Package") .. "]"
end
return retval
end
@@ -153,6 +149,11 @@ local function handle_buttons(tabview, fields, tabname, tabdata)
return true
end
if fields["btn_mod_mgr_install_local"] ~= nil then
core.show_file_open_dialog("mod_mgt_open_dlg", fgettext("Select Package File:"))
return true
end
if fields["btn_contentdb"] ~= nil then
local dlg = create_store_dlg()
dlg:set_parent(tabview)
@@ -196,6 +197,12 @@ local function handle_buttons(tabview, fields, tabname, tabdata)
return true
end
if fields["mod_mgt_open_dlg_accepted"] and
fields["mod_mgt_open_dlg_accepted"] ~= "" then
pkgmgr.install_mod(fields["mod_mgt_open_dlg_accepted"],nil)
return true
end
return false
end

View File

@@ -20,31 +20,51 @@
local core_developers = {
"Perttu Ahola (celeron55) <celeron55@gmail.com>",
"sfan5 <sfan5@live.de>",
"ShadowNinja <shadowninja@minetest.net>",
"Nathanaël Courant (Nore/Ekdohibs) <nore@mesecons.net>",
"Loic Blot (nerzhul/nrz) <loic.blot@unix-experience.fr>",
"paramat",
"Auke Kok (sofar) <sofar@foo-projects.org>",
"Andrew Ward (rubenwardy) <rw@rubenwardy.com>",
"rubenwardy <rw@rubenwardy.com>",
"Krock/SmallJoker <mk939@ymail.com>",
"Lars Hofhansl <larsh@apache.org>",
}
local active_contributors = {
"Hugues Ross [Formspecs]",
"Maksim (MoNTE48) [Android]",
"DS [Formspecs]",
"pyrollo [Formspecs: Hypertext]",
"v-rob [Formspecs]",
"Jordach [set_sky]",
"random-geek [Formspecs]",
"Wuzzy [Pathfinder, builtin, translations]",
"ANAND (ClobberXD) [Fixes, per-player FOV]",
"Warr1024 [Fixes]",
"Paul Ouellette (pauloue) [Fixes, Script API]",
"numberZero [Audiovisuals: meshgen]",
"stujones11 [Android UX improvements]",
"red-001 <red-001@outlook.ie> [CSM & Menu fixes]",
"Paul Ouellette (pauloue) [Docs, fixes]",
"Dániel Juhász (juhdanad) <juhdanad@gmail.com> [Audiovisuals: lighting]",
"Hybrid Dog [API]",
"srifqi [Android]",
"Vincent Glize (Dumbeldor) [Cleanups, CSM APIs]",
"Ben Deutsch [Rendering, Fixes, SQLite auth]",
"Wuzzy [Translation, Slippery]",
"ANAND (ClobberXD) [Docs, Fixes]",
"Shara/Ezhh [Docs, Game API]",
"DTA7 [Fixes, mute key]",
"Thomas-S [Disconnected, Formspecs]",
"Raymoo [Tool Capabilities]",
"Elijah Duffy (octacian) [Mainmenu]",
"noob3167 [Fixes]",
"adelcoding1 [Formspecs]",
"adrido [Windows Installer, Formspecs]",
"Rui [Sound Pitch]",
"Jean-Patrick G (kilbith) <jeanpatrick.guerrero@gmail.com> [Audiovisuals]",
"HybridDog [Script API]",
"dcbrwn [Object shading]",
"srifqi [Fixes]",
"Esteban (EXio4) [Cleanups]",
"Vaughan Lapsley (vlapsley) [Carpathian mapgen]",
"CoderForTheBetter [Add set_rotation]",
"Quentin Bazin (Unarelith) [Cleanups]",
"Maksim (MoNTE48) [Android]",
"Gaël-de-Sailly [Mapgen, pitch fly]",
"zeuner [Docs, Fixes]",
"ThomasMonroe314 (tre) [Fixes]",
"Rob Blanckaert (basicer) [Fixes]",
"Jozef Behran (osjc) [Fixes]",
"random-geek [Fixes]",
"Pedro Gimeno (pgimeno) [Fixes]",
"lisacvuk [Fixes]",
}
local previous_core_developers = {
@@ -59,31 +79,24 @@ local previous_core_developers = {
"Ryan Kwolek (kwolekr) <kwolekr@minetest.net>",
"sapier",
"Zeno",
"ShadowNinja <shadowninja@minetest.net>",
}
local previous_contributors = {
"Nils Dagsson Moskopp (erlehmann) <nils@dieweltistgarnichtso.net> [Minetest Logo]",
"Dániel Juhász (juhdanad) <juhdanad@gmail.com>",
"red-001 <red-001@outlook.ie>",
"numberZero [Audiovisuals: meshgen]",
"Giuseppe Bilotta",
"MirceaKitsune <mirceakitsune@gmail.com>",
"Constantin Wenger (SpeedProg)",
"Ciaran Gultnieks (CiaranG)",
"stujones11 [Android UX improvements]",
"Jeija <jeija@mesecons.net> [HTTP, particles]",
"Vincent Glize (Dumbeldor) [Cleanups, CSM APIs]",
"Ben Deutsch [Rendering, Fixes, SQLite auth]",
"TeTpaAka [Hand overriding, nametag colors]",
"Rui [Sound Pitch]",
"Duane Robertson <duane@duanerobertson.com> [MGValleys]",
"Raymoo [Tool Capabilities]",
"Rogier <rogier777@gmail.com> [Fixes]",
"Gregory Currie (gregorycu) [optimisation]",
"TriBlade9 <triblade9@mail.com> [Audiovisuals]",
"Diego Martínez (kaeza) <kaeza@users.sf.net>",
"T4im [Profiler]",
"Jurgen Doser (doserj) <jurgen.doser@gmail.com>",
"TeTpaAka [Hand overriding, nametag colors]",
"Duane Robertson <duane@duanerobertson.com> [MGValleys]",
"neoascetic [OS X Fixes]",
"TriBlade9 <triblade9@mail.com> [Audiovisuals]",
"Jurgen Doser (doserj) <jurgen.doser@gmail.com> [Fixes]",
"MirceaKitsune <mirceakitsune@gmail.com> [Audiovisuals]",
"Guiseppe Bilotta (Oblomov) <guiseppe.bilotta@gmail.com> [Fixes]",
"matttpt <matttpt@gmail.com> [Fixes]",
"Nils Dagsson Moskopp (erlehmann) <nils@dieweltistgarnichtso.net> [Minetest Logo]",
"Jeija <jeija@mesecons.net> [HTTP, particles]",
"bigfoot547 [CSM]",
"Rogier <rogier777@gmail.com> [Fixes]",
}
local function buildCreditList(source)

View File

@@ -21,7 +21,7 @@ local current_game, singleplayer_refresh_gamebar
if enable_gamebar then
function current_game()
local last_game_id = core.settings:get("menu_last_game")
local game = pkgmgr.find_by_gameid(last_game_id)
local game, index = pkgmgr.find_by_gameid(last_game_id)
return game
end
@@ -222,7 +222,7 @@ local function main_button_handler(this, fields, name, tabdata)
--update last game
local world = menudata.worldlist:get_raw_element(gamedata.selected_world)
if world then
local game = pkgmgr.find_by_gameid(world.gameid)
local game, index = pkgmgr.find_by_gameid(world.gameid)
core.settings:set("menu_last_game", game.id)
end

View File

@@ -20,7 +20,7 @@ local function get_formspec(tabview, name, tabdata)
-- Update the cached supported proto info,
-- it may have changed after a change by the settings menu.
common_update_cached_supp_proto()
local fav_selected
local fav_selected = nil
if menudata.search_result then
fav_selected = menudata.search_result[tabdata.fav_selected]
else
@@ -78,7 +78,6 @@ local function get_formspec(tabview, name, tabdata)
"text,align=right,padding=0.25;" .. -- clients_max
image_column(fgettext("Creative mode"), "creative") .. ",padding=1;" ..
image_column(fgettext("Damage enabled"), "damage") .. ",padding=0.25;" ..
--~ PvP = Player versus Player
image_column(fgettext("PvP enabled"), "pvp") .. ",padding=0.25;" ..
"color,span=1;" ..
"text,padding=1]" ..
@@ -274,8 +273,8 @@ local function main_button_handler(tabview, fields, name, tabdata)
for k = 1, #keywords do
local keyword = keywords[k]
if server.name then
local sername = server.name:lower()
local _, count = sername:gsub(keyword, keyword)
local name = server.name:lower()
local _, count = name:gsub(keyword, keyword)
found = found + count * 4
end

View File

@@ -148,9 +148,11 @@ local function dlg_confirm_reset_btnhandler(this, fields, dialogdata)
core.create_world("singleplayerworld", 1)
worldlist = core.get_worlds()
found_singleplayerworld = false
for i = 1, #worldlist do
if worldlist[i].name == "singleplayerworld" then
found_singleplayerworld = true
gamedata.worldindex = i
end
end
@@ -252,7 +254,7 @@ local function formspec(tabview, name, tabdata)
.. dump(core.settings:get_bool("generate_normalmaps")) .. "]" ..
"checkbox[8.25,2;cb_parallax;" .. fgettext("Parallax Occlusion") .. ";"
.. dump(core.settings:get_bool("enable_parallax_occlusion")) .. "]" ..
"checkbox[8.25,2.5;cb_waving_water;" .. fgettext("Waving Liquids") .. ";"
"checkbox[8.25,2.5;cb_waving_water;" .. fgettext("Waving Water") .. ";"
.. dump(core.settings:get_bool("enable_waving_water")) .. "]" ..
"checkbox[8.25,3;cb_waving_leaves;" .. fgettext("Waving Leaves") .. ";"
.. dump(core.settings:get_bool("enable_waving_leaves")) .. "]" ..
@@ -269,7 +271,7 @@ local function formspec(tabview, name, tabdata)
"label[8.38,2.2;" .. core.colorize("#888888",
fgettext("Parallax Occlusion")) .. "]" ..
"label[8.38,2.7;" .. core.colorize("#888888",
fgettext("Waving Liquids")) .. "]" ..
fgettext("Waving Water")) .. "]" ..
"label[8.38,3.2;" .. core.colorize("#888888",
fgettext("Waving Leaves")) .. "]" ..
"label[8.38,3.7;" .. core.colorize("#888888",

View File

@@ -188,10 +188,10 @@ local function main_button_handler(tabview, fields, name, tabdata)
core.settings:set("address", fields.te_address)
core.settings:set("remote_port", fields.te_port)
core.start()
return true
end
core.start()
return true
end
if fields.btn_config_sp_world then
local configdialog = create_configure_world_dlg(1)

View File

@@ -23,9 +23,9 @@ function mm_texture.init()
mm_texture.defaulttexturedir = core.get_texturepath() .. DIR_DELIM .. "base" ..
DIR_DELIM .. "pack" .. DIR_DELIM
mm_texture.basetexturedir = mm_texture.defaulttexturedir
mm_texture.texturepack = core.settings:get("texture_path")
mm_texture.gameid = nil
end
@@ -39,7 +39,7 @@ function mm_texture.update(tab,gamedetails)
if gamedetails == nil then
return
end
mm_texture.update_game(gamedetails)
end
@@ -48,18 +48,18 @@ function mm_texture.reset()
mm_texture.gameid = nil
local have_bg = false
local have_overlay = mm_texture.set_generic("overlay")
if not have_overlay then
have_bg = mm_texture.set_generic("background")
end
mm_texture.clear("header")
mm_texture.clear("footer")
core.set_clouds(false)
mm_texture.set_generic("footer")
mm_texture.set_generic("header")
if not have_bg then
if core.settings:get_bool("menu_clouds") then
core.set_clouds(true)
@@ -74,30 +74,30 @@ function mm_texture.update_game(gamedetails)
if mm_texture.gameid == gamedetails.id then
return
end
local have_bg = false
local have_overlay = mm_texture.set_game("overlay",gamedetails)
if not have_overlay then
have_bg = mm_texture.set_game("background",gamedetails)
end
mm_texture.clear("header")
mm_texture.clear("footer")
core.set_clouds(false)
if not have_bg then
if core.settings:get_bool("menu_clouds") then
core.set_clouds(true)
else
mm_texture.set_dirt_bg()
end
end
mm_texture.set_game("footer",gamedetails)
mm_texture.set_game("header",gamedetails)
mm_texture.gameid = gamedetails.id
end
@@ -116,7 +116,7 @@ function mm_texture.set_generic(identifier)
return true
end
end
if mm_texture.defaulttexturedir ~= nil then
local path = mm_texture.defaulttexturedir .. DIR_DELIM .."menu_" ..
identifier .. ".png"
@@ -124,13 +124,13 @@ function mm_texture.set_generic(identifier)
return true
end
end
return false
end
--------------------------------------------------------------------------------
function mm_texture.set_game(identifier, gamedetails)
if gamedetails == nil then
return false
end
@@ -142,7 +142,7 @@ function mm_texture.set_game(identifier, gamedetails)
return true
end
end
-- Find out how many randomized textures the game provides
local n = 0
local filename
@@ -167,7 +167,7 @@ function mm_texture.set_game(identifier, gamedetails)
if core.set_background(identifier, path) then
return true
end
return false
end
@@ -178,7 +178,7 @@ function mm_texture.set_dirt_bg()
return true
end
end
-- Use universal fallback texture in textures/base/pack
local minimalpath = defaulttexturedir .. "menu_bg.png"
core.set_background("background", minimalpath, true, 128)

View File

@@ -117,8 +117,7 @@ end
local function assert_can_be_called(func, func_name, level)
if not can_be_called(func) then
-- Then throw an *helpful* error, by pointing on our caller instead of us.
error(format("Invalid argument to %s. Expected function-like type instead of '%s'.",
func_name, type(func)), level + 1)
error(format("Invalid argument to %s. Expected function-like type instead of '%s'.", func_name, type(func)), level + 1)
end
end
@@ -162,7 +161,7 @@ local function init()
"on_activate",
"on_step",
"on_punch",
"on_rightclick",
"rightclick",
"get_staticdata",
}
-- Wrap register_entity() to instrument them on registration.

View File

@@ -112,7 +112,7 @@ always_fly_fast (Always fly and fast) bool true
# The time in seconds it takes between repeated right clicks when holding the right
# mouse button.
repeat_rightclick_time (Rightclick repetition interval) float 0.25 0.001
repeat_rightclick_time (Rightclick repetition interval) float 0.25
# Automatically jump up single-node obstacles.
autojump (Automatic jumping) bool false
@@ -150,7 +150,7 @@ joystick_type (Joystick type) enum auto auto,generic,xbox
# The time in seconds it takes between repeated events
# when holding down a joystick button combination.
repeat_joystick_button_time (Joystick button repetition interval) float 0.17 0.001
repeat_joystick_button_time (Joystick button repetition interval) float 0.17
# The sensitivity of the joystick axes for moving the
# ingame view frustum around.
@@ -212,7 +212,7 @@ keymap_freemove (Fly key) key KEY_KEY_K
# Key for toggling pitch move mode.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_pitchmove (Pitch move key) key KEY_KEY_P
keymap_pitchmove (Pitch move key) key KEY_KEY_L
# Key for toggling fast mode.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
@@ -440,8 +440,7 @@ keymap_decrease_viewing_range_min (View range decrease key) key -
[**Basic]
# Enable vertex buffer objects.
# This should greatly improve graphics performance.
# Enable VBO
enable_vbo (VBO) bool true
# Whether to fog out the end of the visible area.
@@ -509,11 +508,10 @@ texture_min_size (Minimum texture size) int 64
# when set to higher number than 0.
fsaa (FSAA) enum 0 0,1,2,4,8,16
# Undersampling is similar to using a lower screen resolution, but it applies
# Undersampling is similar to using lower screen resolution, but it applies
# to the game world only, keeping the GUI intact.
# It should give a significant performance boost at the cost of less detailed image.
# Higher values result in a less detailed image.
undersampling (Undersampling) int 1 1 8
# It should give significant performance boost at the cost of less detailed image.
undersampling (Undersampling) enum 0 0,2,3,4
[**Shaders]
@@ -527,10 +525,7 @@ shader_path (Shader path) path
[***Tone Mapping]
# Enables Hable's 'Uncharted 2' filmic tone mapping.
# Simulates the tone curve of photographic film and how this approximates the
# appearance of high dynamic range images. Mid-range contrast is slightly
# enhanced, highlights and shadows are gradually compressed.
# Enables filmic tone mapping
tone_mapping (Filmic tone mapping) bool false
[***Bumpmapping]
@@ -575,31 +570,21 @@ parallax_occlusion_bias (Parallax occlusion bias) float 0.04
[***Waving Nodes]
# Set to true to enable waving liquids (like water).
# Set to true enables waving water.
# Requires shaders to be enabled.
enable_waving_water (Waving liquids) bool false
enable_waving_water (Waving water) bool false
# The maximum height of the surface of waving liquids.
# 4.0 = Wave height is two nodes.
# 0.0 = Wave doesn't move at all.
# Default is 1.0 (1/2 node).
# Requires waving liquids to be enabled.
water_wave_height (Waving liquids wave height) float 1.0 0.0 4.0
water_wave_height (Waving water height) float 1.0
# Length of liquid waves.
# Requires waving liquids to be enabled.
water_wave_length (Waving liquids wavelength) float 20.0 0.1
water_wave_length (Waving water length) float 20.0
# How fast liquid waves will move. Higher = faster.
# If negative, liquid waves will move backwards.
# Requires waving liquids to be enabled.
water_wave_speed (Waving liquids wave speed) float 5.0
water_wave_speed (Waving water speed) float 5.0
# Set to true to enable waving leaves.
# Set to true enables waving leaves.
# Requires shaders to be enabled.
enable_waving_leaves (Waving leaves) bool false
# Set to true to enable waving plants.
# Set to true enables waving plants.
# Requires shaders to be enabled.
enable_waving_plants (Waving plants) bool false
@@ -611,10 +596,10 @@ arm_inertia (Arm inertia) bool true
# If FPS would go higher than this, limit it by sleeping
# to not waste CPU power for no benefit.
fps_max (Maximum FPS) int 60 1
fps_max (Maximum FPS) int 60
# Maximum FPS when game is paused.
pause_fps_max (FPS in pause menu) int 20 1
pause_fps_max (FPS in pause menu) int 20
# Open the pause menu when the window's focus is lost. Does not pause if a formspec is
# open.
@@ -623,17 +608,17 @@ pause_on_lost_focus (Pause on lost window focus) bool false
# View distance in nodes.
viewing_range (Viewing range) int 100 20 4000
# Camera 'near clipping plane' distance in nodes, between 0 and 0.25
# Only works on GLES platforms. Most users will not need to change this.
# 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.25
near_plane (Near plane) float 0.1 0 0.5
# Width component of the initial window size.
screen_w (Screen width) int 1024 1
screen_w (Screen width) int 1024
# Height component of the initial window size.
screen_h (Screen height) int 600 1
screen_h (Screen height) int 600
# Save window size automatically when modified.
autosave_screensize (Autosave screen size) bool true
@@ -650,34 +635,25 @@ vsync (VSync) bool false
# Field of view in degrees.
fov (Field of view) int 72 45 160
# Alters the light curve by applying 'gamma correction' to it.
# Higher values make middle and lower light levels brighter.
# Value '1.0' leaves the light curve unaltered.
# This only has significant effect on daylight and artificial
# light, it has very little effect on natural night light.
display_gamma (Light curve gamma) float 1.0 0.33 3.0
# Adjust the gamma encoding for the light tables. Higher numbers are brighter.
# This setting is for the client only and is ignored by the server.
display_gamma (Gamma) float 1.0 0.5 3.0
# Gradient of light curve at minimum light level.
# Controls the contrast of the lowest light levels.
lighting_alpha (Light curve low gradient) float 0.0 0.0 3.0
lighting_alpha (Darkness sharpness) float 0.0 0.0 4.0
# Gradient of light curve at maximum light level.
# Controls the contrast of the highest light levels.
lighting_beta (Light curve high gradient) float 1.5 0.0 3.0
lighting_beta (Lightness sharpness) float 1.5 0.0 4.0
# Strength of light curve boost.
# The 3 'boost' parameters define a range of the light
# curve that is boosted in brightness.
lighting_boost (Light curve boost) float 0.2 0.0 0.4
# Strength of light curve mid-boost.
lighting_boost (Light curve mid boost) float 0.2 0.0 1.0
# Center of light curve boost range.
# Where 0.0 is minimum light level, 1.0 is maximum light level.
lighting_boost_center (Light curve boost center) float 0.5 0.0 1.0
# Center of light curve mid-boost.
lighting_boost_center (Light curve mid boost center) float 0.5 0.0 1.0
# Spread of light curve boost range.
# Controls the width of the range to be boosted.
# Standard deviation of the light curve boost Gaussian.
lighting_boost_spread (Light curve boost spread) float 0.2 0.0 0.4
# Spread of light curve mid-boost.
# Standard deviation of the mid-boost gaussian.
lighting_boost_spread (Light curve mid boost spread) float 0.2 0.0 1.0
# Path to texture directory. All textures are first searched from here.
texture_path (Texture path) path
@@ -779,7 +755,7 @@ minimap_shape_round (Round minimap) bool true
# True = 256
# False = 128
# Usable to make minimap smoother on slower machines.
# Useable to make minimap smoother on slower machines.
minimap_double_scan_height (Minimap scan height) bool true
# Make fog and sky colors depend on daytime (dawn/sunset) and view direction.
@@ -829,7 +805,7 @@ menu_clouds (Clouds in menu) bool true
# This will smooth over some of the rough edges, and blend
# pixels when scaling down, at the cost of blurring some
# edge pixels when images are scaled by non-integer sizes.
gui_scaling (GUI scaling) float 1.0 0.001
gui_scaling (GUI scaling) float 1.0
# When gui_scaling_filter is true, all GUI images need to be
# filtered in software, but some images are generated directly
@@ -849,60 +825,29 @@ tooltip_show_delay (Tooltip delay) int 400
tooltip_append_itemname (Append item name) bool false
# Whether FreeType fonts are used, requires FreeType support to be compiled in.
# If disabled, bitmap and XML vectors fonts are used instead.
freetype (FreeType fonts) bool true
font_bold (Font bold by default) bool false
# Path to TrueTypeFont or bitmap.
font_path (Font path) filepath fonts/liberationsans.ttf
font_italic (Font italic by default) bool false
font_size (Font size) int 16
# Shadow offset (in pixels) of the default font. If 0, then shadow will not be drawn.
# Font shadow offset, if 0 then shadow will not be drawn.
font_shadow (Font shadow) int 1
# Opaqueness (alpha) of the shadow behind the default font, between 0 and 255.
# Font shadow alpha (opaqueness, between 0 and 255).
font_shadow_alpha (Font shadow alpha) int 127 0 255
# Font size of the default font in point (pt).
font_size (Font size) int 16 1
mono_font_path (Monospace font path) filepath fonts/liberationmono.ttf
# Path to the default font.
# If “freetype” setting is enabled: Must be a TrueType font.
# If “freetype” setting is disabled: Must be a bitmap or XML vectors font.
# The fallback font will be used if the font cannot be loaded.
font_path (Regular font path) filepath fonts/Arimo-Regular.ttf
mono_font_size (Monospace font size) int 15
font_path_bold (Bold font path) filepath fonts/Arimo-Bold.ttf
font_path_italic (Italic font path) filepath fonts/Arimo-Italic.ttf
font_path_bolditalic (Bold and italic font path) filepath fonts/Arimo-BoldItalic.ttf
# Font size of the monospace font in point (pt).
mono_font_size (Monospace font size) int 15 1
# Path to the monospace font.
# If “freetype” setting is enabled: Must be a TrueType font.
# If “freetype” setting is disabled: Must be a bitmap or XML vectors font.
# This font is used for e.g. the console and profiler screen.
mono_font_path (Monospace font path) filepath fonts/Cousine-Regular.ttf
mono_font_path_bold (Bold monospace font path) filepath fonts/Cousine-Bold.ttf
mono_font_path_italic (Italic monospace font path) filepath fonts/Cousine-Italic.ttf
mono_font_path_bolditalic (Bold and italic monospace font path) filepath fonts/Cousine-BoldItalic.ttf
# Font size of the fallback font in point (pt).
fallback_font_size (Fallback font size) int 15 1
# Shadow offset (in pixels) of the fallback font. If 0, then shadow will not be drawn.
# This font will be used for certain languages.
fallback_font_path (Fallback font) filepath fonts/DroidSansFallbackFull.ttf
fallback_font_size (Fallback font size) int 15
fallback_font_shadow (Fallback font shadow) int 1
# Opaqueness (alpha) of the shadow behind the fallback font, between 0 and 255.
fallback_font_shadow_alpha (Fallback font shadow alpha) int 128 0 255
# Path of the fallback font.
# If “freetype” setting is enabled: Must be a TrueType font.
# If “freetype” setting is disabled: Must be a bitmap or XML vectors font.
# This font will be used for certain languages or if the default font is unavailable.
fallback_font_path (Fallback font path) filepath fonts/DroidSansFallbackFull.ttf
# Path to save screenshots at.
screenshot_path (Screenshot folder) path
@@ -917,7 +862,7 @@ screenshot_quality (Screenshot quality) int 0 0 100
[*Advanced]
# Adjust dpi configuration to your screen (non X11/Android only) e.g. for 4k screens.
screen_dpi (DPI) int 72 1
screen_dpi (DPI) int 72
# Windows systems only: Start Minetest with the command line window in the background.
# Contains the same information as the file debug.txt (default name).
@@ -925,20 +870,10 @@ enable_console (Enable console window) bool false
[Sound]
# Enables the sound system.
# If disabled, this completely disables all sounds everywhere and the in-game
# sound controls will be non-functional.
# Changing this setting requires a restart.
enable_sound (Sound) bool true
# Volume of all sounds.
# Requires the sound system to be enabled.
sound_volume (Volume) float 0.7 0.0 1.0
# Whether to mute sounds. You can unmute sounds at any time, unless the
# sound system is disabled (enable_sound=false).
# In-game, you can toggle the mute state with the mute key or by using the
# pause menu.
mute_sound (Mute sound) bool false
[Client]
@@ -1039,7 +974,6 @@ remote_media (Remote media) string
# Enable/disable running an IPv6 server.
# Ignored if bind_address is set.
# Needs enable_ipv6 to be enabled.
ipv6_server (IPv6 server) bool false
[**Advanced]
@@ -1124,10 +1058,6 @@ disable_anticheat (Disable anticheat) bool false
# This option is only read when server starts.
enable_rollback_recording (Rollback recording) bool false
# Format of player chat messages. The following strings are valid placeholders:
# @name, @message, @timestamp (optional)
chat_message_format (Chat message format) string <@name> @message
# A message to be displayed to all clients when the server shuts down.
kick_msg_shutdown (Shutdown message) string Server shutting down.
@@ -1167,7 +1097,7 @@ time_send_interval (Time send interval) int 5
time_speed (Time speed) int 72
# Time of day when a new world is started, in millihours (0-23999).
world_start_time (World start time) int 6125 0 23999
world_start_time (World start time) int 5250 0 23999
# Interval of saving important changes in the world, stated in seconds.
server_map_save_interval (Map save interval) float 5.3
@@ -1183,49 +1113,22 @@ chat_message_limit_trigger_kick (Chat message kick threshold) int 50
[**Physics]
# Horizontal and vertical acceleration on ground or when climbing,
# in nodes per second per second.
movement_acceleration_default (Default acceleration) float 3
# Horizontal acceleration in air when jumping or falling,
# in nodes per second per second.
movement_acceleration_air (Acceleration in air) float 2
# Horizontal and vertical acceleration in fast mode,
# in nodes per second per second.
movement_acceleration_fast (Fast mode acceleration) float 10
# Walking and flying speed, in nodes per second.
movement_speed_walk (Walking speed) float 4
# Sneaking speed, in nodes per second.
movement_speed_crouch (Sneaking speed) float 1.35
# Walking, flying and climbing speed in fast mode, in nodes per second.
movement_speed_fast (Fast mode speed) float 20
# Vertical climbing speed, in nodes per second.
movement_speed_climb (Climbing speed) float 3
# Initial vertical speed when jumping, in nodes per second.
movement_speed_jump (Jumping speed) float 6.5
# Decrease this to increase liquid resistance to movement.
movement_liquid_fluidity (Liquid fluidity) float 1
# Maximum liquid resistance. Controls deceleration when entering liquid at
# high speed.
movement_liquid_fluidity_smooth (Liquid fluidity smoothing) float 0.5
# Controls sinking speed in liquid.
movement_liquid_sink (Liquid sinking) float 10
# Acceleration of gravity, in nodes per second per second.
movement_liquid_sink (Liquid sinking speed) float 10
movement_gravity (Gravity) float 9.81
[**Advanced]
# Handling for deprecated Lua API calls:
# Handling for deprecated lua api calls:
# - legacy: (try to) mimic old behaviour (default for release).
# - log: mimic and log backtrace of deprecated call (default for debug).
# - error: abort on usage of deprecated call (suggested for mod developers).
@@ -1372,7 +1275,8 @@ name (Player name) string
# Set the language. Leave empty to use the system language.
# A restart is required after changing this.
language (Language) enum ,ar,ca,cs,da,de,dv,el,eo,es,et,eu,fil,fr,hu,id,it,ja,ja_KS,jbo,kk,kn,lo,lt,ms,my,nb,nl,nn,pl,pt,pt_BR,ro,ru,sl,sr_Cyrl,sv,sw,th,tr,uk,vi
language (Language) enum ,be,ca,cs,da,de,dv,en,eo,es,et,fr,he,hu,id,it,ja,jbo,ko,ky,lt,ms,nb,nl,pl,pt,pt_BR,ro,ru,sl,sr_Cyrl,sv,sw,tr,uk,zh_CN,zh_TW
# Level of logging to be written to debug.txt:
# - <nothing> (no logging)
@@ -1384,14 +1288,7 @@ language (Language) enum ,ar,ca,cs,da,de,dv,el,eo,es,et,eu,fil,fr,hu,id,it,ja,
# - verbose
debug_log_level (Debug log level) enum action ,none,error,warning,action,info,verbose
# If the file size of debug.txt exceeds the number of megabytes specified in
# this setting when it is opened, the file is moved to debug.txt.1,
# deleting an older debug.txt.1 if it exists.
# debug.txt is only moved if this setting is positive.
debug_log_size_max (Debug log file size threshold) int 50
# Enable IPv6 support (for both client and server).
# Required for IPv6 connections to work at all.
# IPv6 support.
enable_ipv6 (IPv6) bool true
[*Advanced]
@@ -1430,9 +1327,11 @@ profiler_print_interval (Engine profiling data print interval) int 0
# Name of map generator to be used when creating a new world.
# Creating a world in the main menu will override this.
# Current mapgens in a highly unstable state:
# - The optional floatlands of v7 (disabled by default).
mg_name (Mapgen name) enum v7 v7,valleys,carpathian,v5,flat,fractal,singlenode,v6
# Current stable mapgens:
# v5, v6, v7 (except floatlands), singlenode.
# 'stable' means the terrain shape in an existing world will not be changed
# in the future. Note that biomes are defined by games and may still change.
mg_name (Mapgen name) enum v7 v5,v6,v7,valleys,carpathian,fractal,flat,singlenode
# Water surface level of the world.
water_level (Water level) int 1
@@ -1450,6 +1349,9 @@ mapgen_limit (Map generation limit) int 31000 0 31000
# and junglegrass, in all other mapgens this flag controls all decorations.
mg_flags (Mapgen flags) flags caves,dungeons,light,decorations,biomes caves,dungeons,light,decorations,biomes,nocaves,nodungeons,nolight,nodecorations,nobiomes
# Whether dungeons occasionally project from the terrain.
projecting_dungeons (Projecting dungeons) bool true
[*Biome API temperature and humidity noise parameters]
# Temperature variation for biomes.
@@ -1470,27 +1372,13 @@ mg_biome_np_humidity_blend (Humidity blend noise) noise_params_2d 0, 1.5, (8, 8,
mgv5_spflags (Mapgen V5 specific flags) flags caverns caverns,nocaverns
# Controls width of tunnels, a smaller value creates wider tunnels.
# Value >= 10.0 completely disables generation of tunnels and avoids the
# intensive noise calculations.
mgv5_cave_width (Cave width) float 0.09
# Y of upper limit of large caves.
mgv5_large_cave_depth (Large cave depth) int -256
# Minimum limit of random number of small caves per mapchunk.
mgv5_small_cave_num_min (Small cave minimum number) int 0 0 256
# Maximum limit of random number of small caves per mapchunk.
mgv5_small_cave_num_max (Small cave maximum number) int 0 0 256
# Minimum limit of random number of large caves per mapchunk.
mgv5_large_cave_num_min (Large cave minimum number) int 0 0 64
# Maximum limit of random number of large caves per mapchunk.
mgv5_large_cave_num_max (Large cave maximum number) int 2 0 64
# Proportion of large caves that contain liquid.
mgv5_large_cave_flooded (Large cave proportion flooded) float 0.5 0.0 1.0
# Y of upper limit of lava in large caves.
mgv5_lava_depth (Lava depth) int -256
# Y-level of cavern upper limit.
mgv5_cavern_limit (Cavern limit) int -256
@@ -1531,19 +1419,16 @@ mgv5_np_cavern (Cavern noise) noise_params_3d 0, 1, (384, 128, 384), 723, 5, 0.6
# 3D noise defining terrain.
mgv5_np_ground (Ground noise) noise_params_3d 0, 40, (80, 80, 80), 983240, 4, 0.55, 2.0, eased
# 3D noise that determines number of dungeons per mapchunk.
mgv5_np_dungeons (Dungeon noise) noise_params_3d 0.9, 0.5, (500, 500, 500), 0, 2, 0.8, 2.0
[*Mapgen V6]
# Map generation attributes specific to Mapgen v6.
# The 'snowbiomes' flag enables the new 5 biome system.
# When the 'snowbiomes' flag is enabled jungles are automatically enabled and
# When the new biome system is enabled jungles are automatically enabled and
# the 'jungles' flag is ignored.
mgv6_spflags (Mapgen V6 specific flags) flags jungles,biomeblend,mudflow,snowbiomes,noflat,trees jungles,biomeblend,mudflow,snowbiomes,flat,trees,nojungles,nobiomeblend,nomudflow,nosnowbiomes,noflat,notrees
mgv6_spflags (Mapgen V6 specific flags) flags jungles,biomeblend,mudflow,snowbiomes,trees jungles,biomeblend,mudflow,snowbiomes,flat,trees,nojungles,nobiomeblend,nomudflow,nosnowbiomes,noflat,notrees
# Deserts occur when np_biome exceeds this value.
# When the 'snowbiomes' flag is enabled, this is ignored.
# When the new biome system is enabled, this is ignored.
mgv6_freq_desert (Desert noise threshold) float 0.45
# Sandy beaches occur when np_beach exceeds this value.
@@ -1600,27 +1485,29 @@ mgv7_spflags (Mapgen V7 specific flags) flags mountains,ridges,nofloatlands,cave
mgv7_mount_zero_level (Mountain zero level) int 0
# Controls width of tunnels, a smaller value creates wider tunnels.
# Value >= 10.0 completely disables generation of tunnels and avoids the
# intensive noise calculations.
mgv7_cave_width (Cave width) float 0.09
# Y of upper limit of large caves.
mgv7_large_cave_depth (Large cave depth) int -33
# Minimum limit of random number of small caves per mapchunk.
mgv7_small_cave_num_min (Small cave minimum number) int 0 0 256
# Y of upper limit of lava in large caves.
mgv7_lava_depth (Lava depth) int -256
# Maximum limit of random number of small caves per mapchunk.
mgv7_small_cave_num_max (Small cave maximum number) int 0 0 256
# Controls the density of mountain-type floatlands.
# Is a noise offset added to the 'mgv7_np_mountain' noise value.
mgv7_float_mount_density (Floatland mountain density) float 0.6
# Minimum limit of random number of large caves per mapchunk.
mgv7_large_cave_num_min (Large cave minimum number) int 0 0 64
# Typical maximum height, above and below midpoint, of floatland mountains.
mgv7_float_mount_height (Floatland mountain height) float 128.0
# Maximum limit of random number of large caves per mapchunk.
mgv7_large_cave_num_max (Large cave maximum number) int 2 0 64
# Alters how mountain-type floatlands taper above and below midpoint.
mgv7_float_mount_exponent (Floatland mountain exponent) float 0.75
# Proportion of large caves that contain liquid.
mgv7_large_cave_flooded (Large cave proportion flooded) float 0.5 0.0 1.0
# Y-level of floatland midpoint and lake surface.
mgv7_floatland_level (Floatland level) int 1280
# Y-level to which floatland shadows extend.
mgv7_shadow_limit (Shadow limit) int 1024
# Y-level of cavern upper limit.
mgv7_cavern_limit (Cavern limit) int -256
@@ -1661,6 +1548,13 @@ mgv7_np_mount_height (Mountain height noise) noise_params_2d 256, 112, (1000, 10
# Defines large-scale river channel structure.
mgv7_np_ridge_uwater (Ridge underwater noise) noise_params_2d 0, 1, (1000, 1000, 1000), 85039, 5, 0.6, 2.0, eased
# Defines areas of floatland smooth terrain.
# Smooth floatlands occur when noise > 0.
mgv7_np_floatland_base (Floatland base noise) noise_params_2d -0.6, 1.5, (600, 600, 600), 114, 5, 0.6, 2.0, eased
# Variation of hill height and lake depth on floatland smooth terrain.
mgv7_np_float_base_height (Floatland base height noise) noise_params_2d 48, 24, (300, 300, 300), 907, 4, 0.7, 2.0, eased
# 3D noise defining mountain structure and height.
# Also defines structure of floatland mountain terrain.
mgv7_np_mountain (Mountain noise) noise_params_3d -0.6, 1, (250, 350, 250), 5333, 5, 0.63, 2.0
@@ -1677,48 +1571,22 @@ mgv7_np_cave1 (Cave1 noise) noise_params_3d 0, 12, (61, 61, 61), 52534, 3, 0.5,
# Second of two 3D noises that together define tunnels.
mgv7_np_cave2 (Cave2 noise) noise_params_3d 0, 12, (67, 67, 67), 10325, 3, 0.5, 2.0
# 3D noise that determines number of dungeons per mapchunk.
mgv7_np_dungeons (Dungeon noise) noise_params_3d 0.9, 0.5, (500, 500, 500), 0, 2, 0.8, 2.0
[*Mapgen Carpathian]
# Map generation attributes specific to Mapgen Carpathian.
mgcarpathian_spflags (Mapgen Carpathian specific flags) flags caverns,norivers caverns,rivers,nocaverns,norivers
mgcarpathian_spflags (Mapgen Carpathian specific flags) flags caverns caverns,nocaverns
# Defines the base ground level.
mgcarpathian_base_level (Base ground level) float 12.0
# Defines the width of the river channel.
mgcarpathian_river_width (River channel width) float 0.05
# Defines the depth of the river channel.
mgcarpathian_river_depth (River channel depth) float 24.0
# Defines the width of the river valley.
mgcarpathian_valley_width (River valley width) float 0.25
# Controls width of tunnels, a smaller value creates wider tunnels.
# Value >= 10.0 completely disables generation of tunnels and avoids the
# intensive noise calculations.
mgcarpathian_cave_width (Cave width) float 0.09
# Y of upper limit of large caves.
mgcarpathian_large_cave_depth (Large cave depth) int -33
# Minimum limit of random number of small caves per mapchunk.
mgcarpathian_small_cave_num_min (Small cave minimum number) int 0 0 256
# Maximum limit of random number of small caves per mapchunk.
mgcarpathian_small_cave_num_max (Small cave maximum number) int 0 0 256
# Minimum limit of random number of large caves per mapchunk.
mgcarpathian_large_cave_num_min (Large cave minimum number) int 0 0 64
# Maximum limit of random number of large caves per mapchunk.
mgcarpathian_large_cave_num_max (Large cave maximum number) int 2 0 64
# Proportion of large caves that contain liquid.
mgcarpathian_large_cave_flooded (Large cave proportion flooded) float 0.5 0.0 1.0
# Y of upper limit of lava in large caves.
mgcarpathian_lava_depth (Lava depth) int -256
# Y-level of cavern upper limit.
mgcarpathian_cavern_limit (Cavern limit) int -256
@@ -1770,9 +1638,6 @@ mgcarpathian_np_ridge_mnt (Ridged mountain size noise) noise_params_2d 0, 12, (7
# 2D noise that controls the shape/size of step mountains.
mgcarpathian_np_step_mnt (Step mountain size noise) noise_params_2d 0, 8, (509, 509, 509), 2590, 6, 0.6, 2.0, eased
# 2D noise that locates the river valleys and channels.
mgcarpathian_np_rivers (River noise) noise_params_2d 0, 1, (1000, 1000, 1000), 85039, 5, 0.6, 2.0, eased
# 3D noise for mountain overhangs, cliffs, etc. Usually small variations.
mgcarpathian_np_mnt_var (Mountain variation noise) noise_params_3d 0, 1, (499, 499, 499), 2490, 5, 0.55, 2.0
@@ -1785,12 +1650,9 @@ mgcarpathian_np_cave2 (Cave2 noise) noise_params_3d 0, 12, (67, 67, 67), 10325,
# 3D noise defining giant caverns.
mgcarpathian_np_cavern (Cavern noise) noise_params_3d 0, 1, (384, 128, 384), 723, 5, 0.63, 2.0
# 3D noise that determines number of dungeons per mapchunk.
mgcarpathian_np_dungeons (Dungeon noise) noise_params_3d 0.9, 0.5, (500, 500, 500), 0, 2, 0.8, 2.0
[*Mapgen Flat]
# Map generation attributes specific to Mapgen Flat.
# Map generation attributes specific to Mapgen flat.
# Occasional lakes and hills can be added to the flat world.
mgflat_spflags (Mapgen Flat specific flags) flags nolakes,nohills lakes,hills,nolakes,nohills
@@ -1800,24 +1662,10 @@ mgflat_ground_level (Ground level) int 8
# Y of upper limit of large caves.
mgflat_large_cave_depth (Large cave depth) int -33
# Minimum limit of random number of small caves per mapchunk.
mgflat_small_cave_num_min (Small cave minimum number) int 0 0 256
# Maximum limit of random number of small caves per mapchunk.
mgflat_small_cave_num_max (Small cave maximum number) int 0 0 256
# Minimum limit of random number of large caves per mapchunk.
mgflat_large_cave_num_min (Large cave minimum number) int 0 0 64
# Maximum limit of random number of large caves per mapchunk.
mgflat_large_cave_num_max (Large cave maximum number) int 2 0 64
# Proportion of large caves that contain liquid.
mgflat_large_cave_flooded (Large cave proportion flooded) float 0.5 0.0 1.0
# Y of upper limit of lava in large caves.
mgflat_lava_depth (Lava depth) int -256
# Controls width of tunnels, a smaller value creates wider tunnels.
# Value >= 10.0 completely disables generation of tunnels and avoids the
# intensive noise calculations.
mgflat_cave_width (Cave width) float 0.09
# Terrain noise threshold for lakes.
@@ -1856,38 +1704,16 @@ mgflat_np_cave1 (Cave1 noise) noise_params_3d 0, 12, (61, 61, 61), 52534, 3, 0.5
# Second of two 3D noises that together define tunnels.
mgflat_np_cave2 (Cave2 noise) noise_params_3d 0, 12, (67, 67, 67), 10325, 3, 0.5, 2.0
# 3D noise that determines number of dungeons per mapchunk.
mgflat_np_dungeons (Dungeon noise) noise_params_3d 0.9, 0.5, (500, 500, 500), 0, 2, 0.8, 2.0
[*Mapgen Fractal]
# Map generation attributes specific to Mapgen Fractal.
# 'terrain' enables the generation of non-fractal terrain:
# ocean, islands and underground.
mgfractal_spflags (Mapgen Fractal specific flags) flags terrain terrain,noterrain
# Controls width of tunnels, a smaller value creates wider tunnels.
# Value >= 10.0 completely disables generation of tunnels and avoids the
# intensive noise calculations.
mgfractal_cave_width (Cave width) float 0.09
# Y of upper limit of large caves.
mgfractal_large_cave_depth (Large cave depth) int -33
# Minimum limit of random number of small caves per mapchunk.
mgfractal_small_cave_num_min (Small cave minimum number) int 0 0 256
# Maximum limit of random number of small caves per mapchunk.
mgfractal_small_cave_num_max (Small cave maximum number) int 0 0 256
# Minimum limit of random number of large caves per mapchunk.
mgfractal_large_cave_num_min (Large cave minimum number) int 0 0 64
# Maximum limit of random number of large caves per mapchunk.
mgfractal_large_cave_num_max (Large cave maximum number) int 2 0 64
# Proportion of large caves that contain liquid.
mgfractal_large_cave_flooded (Large cave proportion flooded) float 0.5 0.0 1.0
# Y of upper limit of lava in large caves.
mgfractal_lava_depth (Lava depth) int -256
# Lower Y limit of dungeons.
mgfractal_dungeon_ymin (Dungeon minimum Y) int -31000
@@ -1896,24 +1722,24 @@ mgfractal_dungeon_ymin (Dungeon minimum Y) int -31000
mgfractal_dungeon_ymax (Dungeon maximum Y) int 31000
# Selects one of 18 fractal types.
# 1 = 4D "Roundy" Mandelbrot set.
# 2 = 4D "Roundy" Julia set.
# 3 = 4D "Squarry" Mandelbrot set.
# 4 = 4D "Squarry" Julia set.
# 5 = 4D "Mandy Cousin" Mandelbrot set.
# 6 = 4D "Mandy Cousin" Julia set.
# 7 = 4D "Variation" Mandelbrot set.
# 8 = 4D "Variation" Julia set.
# 9 = 3D "Mandelbrot/Mandelbar" Mandelbrot set.
# 10 = 3D "Mandelbrot/Mandelbar" Julia set.
# 11 = 3D "Christmas Tree" Mandelbrot set.
# 12 = 3D "Christmas Tree" Julia set.
# 13 = 3D "Mandelbulb" Mandelbrot set.
# 14 = 3D "Mandelbulb" Julia set.
# 15 = 3D "Cosine Mandelbulb" Mandelbrot set.
# 16 = 3D "Cosine Mandelbulb" Julia set.
# 17 = 4D "Mandelbulb" Mandelbrot set.
# 18 = 4D "Mandelbulb" Julia set.
# 1 = 4D "Roundy" mandelbrot set.
# 2 = 4D "Roundy" julia set.
# 3 = 4D "Squarry" mandelbrot set.
# 4 = 4D "Squarry" julia set.
# 5 = 4D "Mandy Cousin" mandelbrot set.
# 6 = 4D "Mandy Cousin" julia set.
# 7 = 4D "Variation" mandelbrot set.
# 8 = 4D "Variation" julia set.
# 9 = 3D "Mandelbrot/Mandelbar" mandelbrot set.
# 10 = 3D "Mandelbrot/Mandelbar" julia set.
# 11 = 3D "Christmas Tree" mandelbrot set.
# 12 = 3D "Christmas Tree" julia set.
# 13 = 3D "Mandelbulb" mandelbrot set.
# 14 = 3D "Mandelbulb" julia set.
# 15 = 3D "Cosine Mandelbulb" mandelbrot set.
# 16 = 3D "Cosine Mandelbulb" julia set.
# 17 = 4D "Mandelbulb" mandelbrot set.
# 18 = 4D "Mandelbulb" julia set.
mgfractal_fractal (Fractal type) int 1 1 18
# Iterations of the recursive function.
@@ -1935,7 +1761,7 @@ mgfractal_scale (Scale) v3f (4096.0, 1024.0, 4096.0)
# Can be used to move a desired point to (0, 0) to create a
# suitable spawn point, or to allow 'zooming in' on a desired
# point by increasing 'scale'.
# The default is tuned for a suitable spawn point for Mandelbrot
# The default is tuned for a suitable spawn point for mandelbrot
# sets with default parameters, it may need altering in other
# situations.
# Range roughly -2 to 2. Multiply by 'scale' for offset in nodes.
@@ -1987,9 +1813,6 @@ mgfractal_np_cave1 (Cave1 noise) noise_params_3d 0, 12, (61, 61, 61), 52534, 3,
# Second of two 3D noises that together define tunnels.
mgfractal_np_cave2 (Cave2 noise) noise_params_3d 0, 12, (67, 67, 67), 10325, 3, 0.5, 2.0
# 3D noise that determines number of dungeons per mapchunk.
mgfractal_np_dungeons (Dungeon noise) noise_params_3d 0.9, 0.5, (500, 500, 500), 0, 2, 0.8, 2.0
[*Mapgen Valleys]
# Map generation attributes specific to Mapgen Valleys.
@@ -1998,7 +1821,7 @@ mgfractal_np_dungeons (Dungeon noise) noise_params_3d 0.9, 0.5, (500, 500, 500),
# 'vary_river_depth': If enabled, low humidity and high heat causes rivers
# to become shallower and occasionally dry.
# 'altitude_dry': Reduces humidity with altitude.
mgvalleys_spflags (Mapgen Valleys specific flags) flags altitude_chill,humid_rivers,vary_river_depth,altitude_dry altitude_chill,humid_rivers,vary_river_depth,altitude_dry,noaltitude_chill,nohumid_rivers,novary_river_depth,noaltitude_dry
mgvalleys_spflags (Mapgen Valleys specific flags) flags altitude_chill,humid_rivers,vary_river_depth,altitude_dry altitude_chill,noaltitude_chill,humid_rivers,nohumid_rivers,vary_river_depth,novary_river_depth,altitude_dry,noaltitude_dry
# The vertical distance over which heat drops by 20 if 'altitude_chill' is
# enabled. Also the vertical distance over which humidity drops by 10 if
@@ -2008,20 +1831,8 @@ mgvalleys_altitude_chill (Altitude chill) int 90
# Depth below which you'll find large caves.
mgvalleys_large_cave_depth (Large cave depth) int -33
# Minimum limit of random number of small caves per mapchunk.
mgvalleys_small_cave_num_min (Small cave minimum number) int 0 0 256
# Maximum limit of random number of small caves per mapchunk.
mgvalleys_small_cave_num_max (Small cave maximum number) int 0 0 256
# Minimum limit of random number of large caves per mapchunk.
mgvalleys_large_cave_num_min (Large cave minimum number) int 0 0 64
# Maximum limit of random number of large caves per mapchunk.
mgvalleys_large_cave_num_max (Large cave maximum number) int 2 0 64
# Proportion of large caves that contain liquid.
mgvalleys_large_cave_flooded (Large cave proportion flooded) float 0.5 0.0 1.0
# Y of upper limit of lava in large caves.
mgvalleys_lava_depth (Lava depth) int 1
# Depth below which you'll find giant caverns.
mgvalleys_cavern_limit (Cavern upper limit) int -256
@@ -2039,8 +1850,6 @@ mgvalleys_river_depth (River depth) int 4
mgvalleys_river_size (River size) int 5
# Controls width of tunnels, a smaller value creates wider tunnels.
# Value >= 10.0 completely disables generation of tunnels and avoids the
# intensive noise calculations.
mgvalleys_cave_width (Cave width) float 0.09
# Lower Y limit of dungeons.
@@ -2081,9 +1890,6 @@ mgvalleys_np_valley_profile (Valley profile) noise_params_2d 0.6, 0.5, (512, 512
# Slope and fill work together to modify the heights.
mgvalleys_np_inter_valley_slope (Valley slope) noise_params_2d 0.5, 0.5, (128, 128, 128), 746, 1, 1.0, 2.0, eased
# 3D noise that determines number of dungeons per mapchunk.
mgvalleys_np_dungeons (Dungeon noise) noise_params_3d 0.9, 0.5, (500, 500, 500), 0, 2, 0.8, 2.0
[*Advanced]
# Size of mapchunks generated by mapgen, stated in mapblocks (16 nodes).

View File

@@ -6,16 +6,7 @@ uniform vec4 skyBgColor;
uniform float fogDistance;
uniform vec3 eyePosition;
// The cameraOffset is the current center of the visible world.
uniform vec3 cameraOffset;
uniform float animationTimer;
varying vec3 vPosition;
// World position in the visible world (i.e. relative to the cameraOffset.)
// This can be used for many shader effects without loss of precision.
// If the absolute position is required it can be calculated with
// cameraOffset + worldPosition (for large coordinates the limits of float
// precision must be considered).
varying vec3 worldPosition;
varying float area_enable_parallax;

View File

@@ -4,17 +4,9 @@ uniform mat4 mWorld;
// Color of the light emitted by the sun.
uniform vec3 dayLight;
uniform vec3 eyePosition;
// The cameraOffset is the current center of the visible world.
uniform vec3 cameraOffset;
uniform float animationTimer;
varying vec3 vPosition;
// World position in the visible world (i.e. relative to the cameraOffset.)
// This can be used for many shader effects without loss of precision.
// If the absolute position is required it can be calculated with
// cameraOffset + worldPosition (for large coordinates the limits of float
// precision must be considered).
varying vec3 worldPosition;
varying vec3 eyeVec;
@@ -46,42 +38,6 @@ float smoothTriangleWave(float x)
return smoothCurve(triangleWave(x)) * 2.0 - 1.0;
}
// OpenGL < 4.3 does not support continued preprocessor lines
#if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_OPAQUE || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_BASIC) && ENABLE_WAVING_WATER
//
// Simple, fast noise function.
// See: https://gist.github.com/patriciogonzalezvivo/670c22f3966e662d2f83
//
vec4 perm(vec4 x)
{
return mod(((x * 34.0) + 1.0) * x, 289.0);
}
float snoise(vec3 p)
{
vec3 a = floor(p);
vec3 d = p - a;
d = d * d * (3.0 - 2.0 * d);
vec4 b = a.xxyy + vec4(0.0, 1.0, 0.0, 1.0);
vec4 k1 = perm(b.xyxy);
vec4 k2 = perm(k1.xyxy + b.zzww);
vec4 c = k2 + a.zzzz;
vec4 k3 = perm(c);
vec4 k4 = perm(c + 1.0);
vec4 o1 = fract(k3 * (1.0 / 41.0));
vec4 o2 = fract(k4 * (1.0 / 41.0));
vec4 o3 = o2 * d.z + o1 * (1.0 - d.z);
vec2 o4 = o3.yw * d.x + o3.xz * (1.0 - d.x);
return o4.y * d.y + o4.x * (1.0 - d.y);
}
#endif
void main(void)
{
@@ -101,8 +57,7 @@ void main(void)
float disp_x;
float disp_z;
#if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES && ENABLE_WAVING_LEAVES) || \
(MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS && ENABLE_WAVING_PLANTS)
#if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES && ENABLE_WAVING_LEAVES) || (MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS && ENABLE_WAVING_PLANTS)
vec4 pos2 = mWorld * gl_Vertex;
float tOffset = (pos2.x + pos2.y) * 0.001 + pos2.z * 0.002;
disp_x = (smoothTriangleWave(animationTimer * 23.0 + tOffset) +
@@ -112,21 +67,12 @@ float disp_z;
smoothTriangleWave(animationTimer * 13.0 + tOffset)) * 0.5;
#endif
worldPosition = (mWorld * gl_Vertex).xyz;
// OpenGL < 4.3 does not support continued preprocessor lines
#if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_OPAQUE || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_BASIC) && ENABLE_WAVING_WATER
// Generate waves with Perlin-type noise.
// The constants are calibrated such that they roughly
// correspond to the old sine waves.
#if (MATERIAL_TYPE == TILE_MATERIAL_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_LIQUID_OPAQUE) && ENABLE_WAVING_WATER
vec4 pos = gl_Vertex;
vec3 wavePos = worldPosition + cameraOffset;
// The waves are slightly compressed along the z-axis to get
// wave-fronts along the x-axis.
wavePos.x /= WATER_WAVE_LENGTH * 3;
wavePos.z /= WATER_WAVE_LENGTH * 2;
wavePos.z += animationTimer * WATER_WAVE_SPEED * 10;
pos.y += (snoise(wavePos) - 1) * WATER_WAVE_HEIGHT * 5;
pos.y -= 2.0;
float posYbuf = (pos.z / WATER_WAVE_LENGTH + animationTimer * WATER_WAVE_SPEED * WATER_WAVE_LENGTH);
pos.y -= sin(posYbuf) * WATER_WAVE_HEIGHT + sin(posYbuf / 7.0) * WATER_WAVE_HEIGHT;
gl_Position = mWorldViewProj * pos;
#elif MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES && ENABLE_WAVING_LEAVES
vec4 pos = gl_Vertex;
@@ -147,6 +93,7 @@ float disp_z;
vPosition = gl_Position.xyz;
worldPosition = (mWorld * gl_Vertex).xyz;
// Don't generate heightmaps when too far from the eye
float dist = distance (vec3(0.0, 0.0, 0.0), vPosition);
@@ -186,12 +133,12 @@ float disp_z;
color.rgb = gl_Color.rgb * (gl_Color.a * dayLight.rgb +
nightRatio * artificialLight.rgb) * 2;
color.a = 1;
// Emphase blue a bit in darker places
// See C++ implementation in mapblock_mesh.cpp final_color_blend()
float brightness = (color.r + color.g + color.b) / 3;
color.b += max(0.0, 0.021 - abs(0.2 * brightness - 0.021) +
0.07 * brightness);
gl_FrontColor = gl_BackColor = clamp(color, 0.0, 1.0);
}

View File

@@ -1,131 +0,0 @@
uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D textureFlags;
uniform vec4 emissiveColor;
uniform vec4 skyBgColor;
uniform float fogDistance;
uniform vec3 eyePosition;
varying vec3 vNormal;
varying vec3 vPosition;
varying vec3 worldPosition;
varying vec3 eyeVec;
varying vec3 lightVec;
varying float vIDiff;
bool normalTexturePresent = false;
bool texTileableHorizontal = false;
bool texTileableVertical = false;
bool texSeamless = false;
const float e = 2.718281828459;
const float BS = 10.0;
const float fogStart = FOG_START;
const float fogShadingParameter = 1 / ( 1 - fogStart);
void get_texture_flags()
{
vec4 flags = texture2D(textureFlags, vec2(0.0, 0.0));
if (flags.r > 0.5) {
normalTexturePresent = true;
}
if (flags.g > 0.5) {
texTileableHorizontal = true;
}
if (flags.b > 0.5) {
texTileableVertical = true;
}
if (texTileableHorizontal && texTileableVertical) {
texSeamless = true;
}
}
float intensity(vec3 color)
{
return (color.r + color.g + color.b) / 3.0;
}
float get_rgb_height(vec2 uv)
{
if (texSeamless) {
return intensity(texture2D(baseTexture, uv).rgb);
} else {
return intensity(texture2D(baseTexture, clamp(uv, 0.0, 0.999)).rgb);
}
}
vec4 get_normal_map(vec2 uv)
{
vec4 bump = texture2D(normalTexture, uv).rgba;
bump.xyz = normalize(bump.xyz * 2.0 - 1.0);
return bump;
}
void main(void)
{
vec3 color;
vec4 bump;
vec2 uv = gl_TexCoord[0].st;
bool use_normalmap = false;
get_texture_flags();
#if USE_NORMALMAPS == 1
if (normalTexturePresent) {
bump = get_normal_map(uv);
use_normalmap = true;
}
#endif
#if GENERATE_NORMALMAPS == 1
if (normalTexturePresent == false) {
float tl = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y + SAMPLE_STEP));
float t = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y - SAMPLE_STEP));
float tr = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y + SAMPLE_STEP));
float r = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y));
float br = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y - SAMPLE_STEP));
float b = get_rgb_height(vec2(uv.x, uv.y - SAMPLE_STEP));
float bl = get_rgb_height(vec2(uv.x -SAMPLE_STEP, uv.y - SAMPLE_STEP));
float l = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y));
float dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl);
float dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr);
bump = vec4(normalize(vec3 (dX, dY, NORMALMAPS_STRENGTH)), 1.0);
use_normalmap = true;
}
#endif
vec4 base = texture2D(baseTexture, uv).rgba;
#ifdef ENABLE_BUMPMAPPING
if (use_normalmap) {
vec3 L = normalize(lightVec);
vec3 E = normalize(eyeVec);
float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0), 1.0);
float diffuse = dot(-E,bump.xyz);
color = (diffuse + 0.1 * specular) * base.rgb;
} else {
color = base.rgb;
}
#else
color = base.rgb;
#endif
vec4 col = vec4(color.rgb, base.a);
col.rgb *= emissiveColor.rgb * vIDiff;
// Due to a bug in some (older ?) graphics stacks (possibly in the glsl compiler ?),
// the fog will only be rendered correctly if the last operation before the
// clamp() is an addition. Else, the clamp() seems to be ignored.
// E.g. the following won't work:
// float clarity = clamp(fogShadingParameter
// * (fogDistance - length(eyeVec)) / fogDistance), 0.0, 1.0);
// As additions usually come for free following a multiplication, the new formula
// should be more efficient as well.
// Note: clarity = (1 - fogginess)
float clarity = clamp(fogShadingParameter
- fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0);
col = mix(skyBgColor, col, clarity);
gl_FragColor = vec4(col.rgb, base.a);
}

View File

@@ -1,44 +0,0 @@
uniform mat4 mWorldViewProj;
uniform mat4 mWorld;
uniform vec3 eyePosition;
uniform float animationTimer;
varying vec3 vNormal;
varying vec3 vPosition;
varying vec3 worldPosition;
varying vec3 eyeVec;
varying vec3 lightVec;
varying float vIDiff;
const float e = 2.718281828459;
const float BS = 10.0;
float directional_ambient(vec3 normal)
{
vec3 v = normal * normal;
if (normal.y < 0)
return dot(v, vec3(0.670820f, 0.447213f, 0.836660f));
return dot(v, vec3(0.670820f, 1.000000f, 0.836660f));
}
void main(void)
{
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
gl_Position = mWorldViewProj * gl_Vertex;
vPosition = gl_Position.xyz;
vNormal = gl_Normal;
worldPosition = (mWorld * gl_Vertex).xyz;
vec3 sunPosition = vec3 (0.0, eyePosition.y * BS + 900.0, 0.0);
lightVec = sunPosition - worldPosition;
eyeVec = -(gl_ModelViewMatrix * gl_Vertex).xyz;
vIDiff = directional_ambient(normalize(gl_Normal));
gl_FrontColor = gl_BackColor = gl_Color;
}

View File

@@ -1,2 +1,2 @@
print("Loaded example file!, loading more examples")
dofile(core.get_modpath(core.get_current_modname()) .. "/examples/first.lua")
dofile("preview:examples/first.lua")

View File

@@ -1,27 +1,19 @@
local modname = assert(core.get_current_modname())
local modname = core.get_current_modname() or "??"
local modstorage = core.get_mod_storage()
local mod_channel
dofile(core.get_modpath(modname) .. "example.lua")
dofile("preview:example.lua")
-- This is an example function to ensure it's working properly, should be removed before merge
core.register_on_shutdown(function()
print("[PREVIEW] shutdown client")
end)
local id = nil
do
local server_info = core.get_server_info()
print("Server version: " .. server_info.protocol_version)
print("Server ip: " .. server_info.ip)
print("Server address: " .. server_info.address)
print("Server port: " .. server_info.port)
print("CSM restrictions: " .. dump(core.get_csm_restrictions()))
local l1, l2 = core.get_language()
print("Configured language: " .. l1 .. " / " .. l2)
end
local server_info = core.get_server_info()
print("Server version: " .. server_info.protocol_version)
print("Server ip: " .. server_info.ip)
print("Server address: " .. server_info.address)
print("Server port: " .. server_info.port)
mod_channel = core.mod_channel_join("experimental_preview")
core.after(4, function()
@@ -73,26 +65,6 @@ core.register_on_item_use(function(itemstack, pointed_thing)
print("The local player used an item!")
print("pointed_thing :" .. dump(pointed_thing))
print("item = " .. itemstack:get_name())
if not itemstack:is_empty() then
return false
end
local pos = vector.add(core.localplayer:get_pos(), core.camera:get_offset())
local pos2 = vector.add(pos, vector.multiply(core.camera:get_look_dir(), 100))
local rc = core.raycast(pos, pos2)
local i = rc:next()
print("[PREVIEW] raycast next: " .. dump(i))
if i then
print("[PREVIEW] line of sight: " .. (core.line_of_sight(pos, i.above) and "yes" or "no"))
local n1 = core.find_nodes_in_area(pos, i.under, {"default:stone"})
local n2 = core.find_nodes_in_area_under_air(pos, i.under, {"default:stone"})
print(("[PREVIEW] found %s nodes, %s nodes under air"):format(
n1 and #n1 or "?", n2 and #n2 or "?"))
end
return false
end)
@@ -118,6 +90,11 @@ core.register_on_damage_taken(function(hp)
print("[PREVIEW] Damage taken " .. hp)
end)
-- This is an example function to ensure it's working properly, should be removed before merge
core.register_globalstep(function(dtime)
-- print("[PREVIEW] globalstep " .. dtime)
end)
-- This is an example function to ensure it's working properly, should be removed before merge
core.register_chatcommand("dump", {
func = function(param)
@@ -166,7 +143,8 @@ core.after(5, function()
core.ui.minimap:show()
end
print("[PREVIEW] Time of day " .. core.get_timeofday())
print("[PREVIEW] Day count: " .. core.get_day_count() ..
" time of day " .. core.get_timeofday())
print("[PREVIEW] Node level: " .. core.get_node_level({x=0, y=20, z=0}) ..
" max level " .. core.get_node_max_level({x=0, y=20, z=0}))

View File

@@ -1,16 +1,19 @@
mark_as_advanced(CURL_LIBRARY CURL_INCLUDE_DIR)
find_library(CURL_LIBRARY NAMES curl libcurl)
find_library(CURL_LIBRARY NAMES curl)
find_path(CURL_INCLUDE_DIR NAMES curl/curl.h)
set(CURL_REQUIRED_VARS CURL_LIBRARY CURL_INCLUDE_DIR)
if(WIN32)
# If VCPKG_APPLOCAL_DEPS is ON, dll's are automatically handled by VCPKG
if(NOT VCPKG_APPLOCAL_DEPS)
find_file(CURL_DLL NAMES libcurl-4.dll libcurl.dll
DOC "Path to the cURL DLL (for installation)")
mark_as_advanced(CURL_DLL)
endif()
find_file(CURL_DLL NAMES libcurl-4.dll
PATHS
"C:/Windows/System32"
DOC "Path to the cURL DLL (for installation)")
mark_as_advanced(CURL_DLL)
set(CURL_REQUIRED_VARS ${CURL_REQUIRED_VARS} CURL_DLL)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(CURL DEFAULT_MSG CURL_LIBRARY CURL_INCLUDE_DIR)
find_package_handle_standard_args(CURL DEFAULT_MSG ${CURL_REQUIRED_VARS})

View File

@@ -43,7 +43,6 @@ else()
/usr/local/include/irrlicht
/usr/include/irrlicht
/system/develop/headers/irrlicht #Haiku
PATH_SUFFIXES "include/irrlicht"
)
find_library(IRRLICHT_LIBRARY NAMES libIrrlicht.so libIrrlicht.a Irrlicht
@@ -57,19 +56,16 @@ endif()
# On Windows, find the DLL for installation
if(WIN32)
# If VCPKG_APPLOCAL_DEPS is ON, dll's are automatically handled by VCPKG
if(NOT VCPKG_APPLOCAL_DEPS)
if(MSVC)
set(IRRLICHT_COMPILER "VisualStudio")
else()
set(IRRLICHT_COMPILER "gcc")
endif()
find_file(IRRLICHT_DLL NAMES Irrlicht.dll
PATHS
"${IRRLICHT_SOURCE_DIR}/bin/Win32-${IRRLICHT_COMPILER}"
DOC "Path of the Irrlicht dll (for installation)"
)
if(MSVC)
set(IRRLICHT_COMPILER "VisualStudio")
else()
set(IRRLICHT_COMPILER "gcc")
endif()
find_file(IRRLICHT_DLL NAMES Irrlicht.dll
PATHS
"${IRRLICHT_SOURCE_DIR}/bin/Win32-${IRRLICHT_COMPILER}"
DOC "Path of the Irrlicht dll (for installation)"
)
endif(WIN32)
include(FindPackageHandleStandardArgs)

View File

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

View File

@@ -9,7 +9,7 @@
FIND_PATH(LUA_INCLUDE_DIR luajit.h
HINTS
$ENV{LUA_DIR}
PATH_SUFFIXES include/luajit-2.1 include/luajit-2.0 include/luajit-5_1-2.1 include/luajit-5_1-2.0 include luajit
PATH_SUFFIXES include/luajit-2.1 include/luajit-2.0 include/luajit-5_1-2.1 include/luajit-5_1-2.0 include
PATHS
~/Library/Frameworks
/Library/Frameworks
@@ -19,31 +19,19 @@ FIND_PATH(LUA_INCLUDE_DIR luajit.h
/opt
)
# Test if running on vcpkg toolchain
if(DEFINED VCPKG_TARGET_TRIPLET AND DEFINED VCPKG_APPLOCAL_DEPS)
# On vcpkg luajit is 'lua51' and normal lua is 'lua'
FIND_LIBRARY(LUA_LIBRARY
NAMES lua51
HINTS
$ENV{LUA_DIR}
PATH_SUFFIXES lib
)
else()
FIND_LIBRARY(LUA_LIBRARY
NAMES luajit-5.1
HINTS
$ENV{LUA_DIR}
PATH_SUFFIXES lib64 lib
PATHS
~/Library/Frameworks
/Library/Frameworks
/sw
/opt/local
/opt/csw
/opt
)
endif()
FIND_LIBRARY(LUA_LIBRARY
NAMES luajit-5.1
HINTS
$ENV{LUA_DIR}
PATH_SUFFIXES lib64 lib
PATHS
~/Library/Frameworks
/Library/Frameworks
/sw
/opt/local
/opt/csw
/opt
)
IF(LUA_INCLUDE_DIR AND EXISTS "${LUA_INCLUDE_DIR}/luajit.h")
FILE(STRINGS "${LUA_INCLUDE_DIR}/luajit.h" lua_version_str REGEX "^#define[ \t]+LUA_RELEASE[ \t]+\"LuaJIT .+\"")

View File

@@ -1,4 +1,6 @@
#-------------------------------------------------------------------
# This file is stolen from part of the CMake build system for OGRE (Object-oriented Graphics Rendering Engine) http://www.ogre3d.org/
#
# The contents of this file are placed in the public domain. Feel
# free to make use of it in any way you like.
#-------------------------------------------------------------------
@@ -14,18 +16,26 @@
# EGL_INCLUDE_DIR - the EGL include directory
# EGL_LIBRARIES - Link these to use EGL
# Win32 and Apple are not tested!
# Win32, Apple, and Android are not tested!
# Linux tested and works
if(WIN32)
find_path(OPENGLES2_INCLUDE_DIR GLES2/gl2.h)
find_library(OPENGLES2_LIBRARY libGLESv2)
if(CYGWIN)
find_path(OPENGLES2_INCLUDE_DIR GLES2/gl2.h)
find_library(OPENGLES2_LIBRARY libGLESv2)
else()
if(BORLAND)
set(OPENGLES2_LIBRARY import32 CACHE STRING "OpenGL ES 2.x library for Win32")
else()
# TODO
# set(OPENGLES_LIBRARY ${SOURCE_DIR}/Dependencies/lib/release/libGLESv2.lib CACHE STRING "OpenGL ES 2.x library for win32"
endif()
endif()
elseif(APPLE)
create_search_paths(/Developer/Platforms)
findpkg_framework(OpenGLES2)
set(OPENGLES2_LIBRARY "-framework OpenGLES")
else()
# Unix
find_path(OPENGLES2_INCLUDE_DIR GLES2/gl2.h
PATHS /usr/openwin/share/include
/opt/graphics/OpenGL/include
@@ -37,34 +47,55 @@ else()
NAMES GLESv2
PATHS /opt/graphics/OpenGL/lib
/usr/openwin/lib
/usr/X11R6/lib
/usr/shlib /usr/X11R6/lib
/usr/lib
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(OPENGLES2 DEFAULT_MSG OPENGLES2_LIBRARY OPENGLES2_INCLUDE_DIR)
if(NOT BUILD_ANDROID)
find_path(EGL_INCLUDE_DIR EGL/egl.h
PATHS /usr/openwin/share/include
/opt/graphics/OpenGL/include
/usr/X11R6/include
/usr/include
)
find_path(EGL_INCLUDE_DIR EGL/egl.h
PATHS /usr/openwin/share/include
/opt/graphics/OpenGL/include
/usr/X11R6/include
/usr/include
)
find_library(EGL_LIBRARY
NAMES EGL
PATHS /opt/graphics/OpenGL/lib
/usr/openwin/lib
/usr/shlib
/usr/X11R6/lib
/usr/lib
)
find_library(EGL_LIBRARY
NAMES EGL
PATHS /opt/graphics/OpenGL/lib
/usr/openwin/lib
/usr/X11R6/lib
/usr/lib
)
# On Unix OpenGL usually requires X11.
# It doesn't require X11 on OSX.
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(EGL DEFAULT_MSG EGL_LIBRARY EGL_INCLUDE_DIR)
if(OPENGLES2_LIBRARY)
if(NOT X11_FOUND)
include(FindX11)
endif()
if(X11_FOUND)
set(OPENGLES2_LIBRARIES ${X11_LIBRARIES})
endif()
endif()
endif()
endif()
set(OPENGLES2_LIBRARIES ${OPENGLES2_LIBRARY})
set(EGL_LIBRARIES ${EGL_LIBRARY})
set(OPENGLES2_LIBRARIES ${OPENGLES2_LIBRARIES} ${OPENGLES2_LIBRARY})
if(BUILD_ANDROID)
if(OPENGLES2_LIBRARY)
set(EGL_LIBRARIES)
set(OPENGLES2_FOUND TRUE)
endif()
else()
if(OPENGLES2_LIBRARY AND EGL_LIBRARY)
set(OPENGLES2_LIBRARIES ${OPENGLES2_LIBRARY} ${OPENGLES2_LIBRARIES})
set(EGL_LIBRARIES ${EGL_LIBRARY} ${EGL_LIBRARIES})
set(OPENGLES2_FOUND TRUE)
endif()
endif()
mark_as_advanced(
OPENGLES2_INCLUDE_DIR
@@ -72,3 +103,10 @@ mark_as_advanced(
EGL_INCLUDE_DIR
EGL_LIBRARY
)
if(OPENGLES2_FOUND)
message(STATUS "Found system OpenGL ES 2 library: ${OPENGLES2_LIBRARIES}")
else()
set(OPENGLES2_LIBRARIES "")
endif()

View File

@@ -1,5 +1,5 @@
Minetest Lua Client Modding API Reference 5.2.0
================================================
Minetest Lua Client Modding API Reference 5.0.1
===============================================
* More information at <http://www.minetest.net/>
* Developer Wiki: <http://dev.minetest.net/>
@@ -30,23 +30,17 @@ Startup
Mods are loaded during client startup from the mod load paths by running
the `init.lua` scripts in a shared environment.
In order to load client-side mods, the following conditions need to be satisfied:
1) `$path_user/minetest.conf` contains the setting `enable_client_modding = true`
2) The client-side mod located in `$path_user/clientmods/<modname>` is added to
`$path_user/clientmods/mods.conf` as `load_mod_<modname> = true`.
Note: Depending on the remote server's settings, client-side mods might not
be loaded or have limited functionality. See setting `csm_restriction_flags` for reference.
Paths
-----
* `RUN_IN_PLACE=1` (Windows release, local build)
* `$path_user`: `<build directory>`
* `$path_share`: `<build directory>`
* `$path_user`:
* Linux: `<build directory>`
* Windows: `<build directory>`
* `$path_share`
* Linux: `<build directory>`
* Windows: `<build directory>`
* `RUN_IN_PLACE=0`: (Linux release)
* `$path_share`:
* `$path_share`
* Linux: `/usr/share/minetest`
* Windows: `<install directory>/minetest-0.4.x`
* `$path_user`:
@@ -71,6 +65,7 @@ On an installed version on Linux:
Modpack support
----------------
**NOTE: Not implemented yet.**
Mods can be put in a subdirectory, if the parent directory, which otherwise
should be a mod, contains a file named `modpack.conf`.
@@ -85,36 +80,33 @@ Mod directory structure
clientmods
├── modname
│   ├── mod.conf
│   ├── init.lua
| ├── depends.txt
| ├── init.lua
└── another
### modname
The location of this directory.
### mod.conf
### depends.txt
List of mods that have to be loaded before loading this mod.
An (optional) settings file that provides meta information about the mod.
A single line contains a single modname.
* `name`: The mod name. Allows Minetest to determine the mod name even if the
folder is wrongly named.
* `description`: Description of mod to be shown in the Mods tab of the main
menu.
* `depends`: A comma separated list of dependencies. These are mods that must be
loaded before this mod.
* `optional_depends`: A comma separated list of optional dependencies.
Like a dependency, but no error if the mod doesn't exist.
### `init.lua`
Optional dependencies can be defined by appending a question mark
to a single modname. Their meaning is that if the specified mod
is missing, that does not prevent this mod from being loaded.
### init.lua
The main Lua script. Running this script should register everything it
wants to register. Subsequent execution depends on minetest calling the
registered callbacks.
**NOTE**: Client mods currently can't provide and textures, sounds or models by
themselves. Any media referenced in function calls must already be loaded
(provided by mods that exist on the server).
`minetest.setting_get(name)` and `minetest.setting_getbool(name)` can be used
to read custom or existing settings at load time, if necessary.
### `sounds`
Media files (sounds) that will be transferred to the
client and will be available for use by the mod.
Naming convention for registered textual names
----------------------------------------------
@@ -143,7 +135,7 @@ The `:` prefix can also be used for maintaining backwards compatibility.
Sounds
------
**NOTE: Connecting sounds to objects is not implemented.**
**NOTE: max_hear_distance and connecting to objects is not implemented.**
Only Ogg Vorbis files are supported.
@@ -183,11 +175,13 @@ Examples of sound parameter tables:
{
pos = {x = 1, y = 2, z = 3},
gain = 1.0, -- default
max_hear_distance = 32, -- default, uses an euclidean metric
}
-- Play connected to an object, looped
{
object = <an ObjectRef>,
gain = 1.0, -- default
max_hear_distance = 32, -- default, uses an euclidean metric
loop = true,
}
@@ -630,13 +624,7 @@ Minetest namespace reference
### Utilities
* `minetest.get_current_modname()`: returns the currently loading mod's name, when we are loading a mod
* `minetest.get_modpath(modname)`: returns virtual path of given mod including
the trailing separator. This is useful to load additional Lua files
contained in your mod:
e.g. `dofile(minetest.get_modpath(minetest.get_current_modname()) .. "stuff.lua")`
* `minetest.get_language()`: returns two strings
* the current gettext locale
* the current language code (the same as used for client-side translations)
* `minetest.get_language()`: returns the currently set gettext language.
* `minetest.get_version()`: returns a table containing components of the
engine version. Components:
* `project`: Name of the project, eg, "Minetest"
@@ -651,11 +639,6 @@ Minetest namespace reference
* `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
* `minetest.get_csm_restrictions()`: returns a table of `Flags` indicating the
restrictions applied to the current mod.
* If a flag in this table is set to true, the feature is RESTRICTED.
* Possible flags: `load_client_mods`, `chat_messages`, `read_itemdefs`,
`read_nodedefs`, `lookup_nodes`, `read_playerinfo`
### Logging
* `minetest.debug(...)`
@@ -741,6 +724,8 @@ Call these functions only at load time!
* Optional: Variable number of arguments that are passed to `func`
* `minetest.get_us_time()`
* Returns time with microsecond precision. May not return wall time.
* `minetest.get_day_count()`
* Returns number days elapsed since world was created, accounting for time changes.
* `minetest.get_timeofday()`
* Returns the time of day: `0` for midnight, `0.5` for midday
@@ -749,46 +734,11 @@ Call these functions only at load time!
* Returns the node at the given position as table in the format
`{name="node_name", param1=0, param2=0}`, returns `nil`
for unloaded areas or flavor limited areas.
* `minetest.get_node_light(pos, timeofday)`
* Gets the light value at the given position. Note that the light value
"inside" the node at the given position is returned, so you usually want
to get the light value of a neighbor.
* `pos`: The position where to measure the light.
* `timeofday`: `nil` for current time, `0` for night, `0.5` for day
* Returns a number between `0` and `15` or `nil`
* `minetest.find_node_near(pos, radius, nodenames, [search_center])`: returns pos or `nil`
* `radius`: using a maximum metric
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
* `search_center` is an optional boolean (default: `false`)
If true `pos` is also checked for the nodes
* `minetest.find_nodes_in_area(pos1, pos2, nodenames)`: returns a list of
positions.
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
* First return value: Table with all node positions
* 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"`
* Return value: Table with all node positions with a node air above
* Area volume is limited to 4,096,000 nodes
* `minetest.line_of_sight(pos1, pos2)`: returns `boolean, pos`
* Checks if there is anything other than air between pos1 and pos2.
* Returns false if something is blocking the sight.
* Returns the position of the blocking node when `false`
* `pos1`: First position
* `pos2`: Second position
* `minetest.raycast(pos1, pos2, objects, liquids)`: returns `Raycast`
* Creates a `Raycast` object.
* `pos1`: start of the ray
* `pos2`: end of the ray
* `objects`: if false, only nodes will be returned. Default is `true`.
* `liquids`: if false, liquid nodes won't be returned. Default is `false`.
* `minetest.find_nodes_with_meta(pos1, pos2)`
* Get a table of positions of nodes that have metadata within a region
{pos1, pos2}.
* `minetest.get_meta(pos)`
* Get a `NodeMetaRef` at that position
* `minetest.get_node_level(pos)`
@@ -1115,32 +1065,6 @@ Can be obtained via `minetest.get_meta(pos)`.
* `fields`: key-value storage
* `inventory`: `{list1 = {}, ...}}`
### `Raycast`
A raycast on the map. It works with selection boxes.
Can be used as an iterator in a for loop as:
local ray = Raycast(...)
for pointed_thing in ray do
...
end
The map is loaded as the ray advances. If the map is modified after the
`Raycast` is created, the changes may or may not have an effect on the object.
It can be created via `Raycast(pos1, pos2, objects, liquids)` or
`minetest.raycast(pos1, pos2, objects, liquids)` where:
* `pos1`: start of the ray
* `pos2`: end of the ray
* `objects`: if false, only nodes will be returned. Default is true.
* `liquids`: if false, liquid nodes won't be returned. Default is false.
#### Methods
* `next()`: returns a `pointed_thing` with exact pointing location
* Returns the next thing pointed by the ray or nil.
-----------------
### Definitions
* `minetest.get_node_def(nodename)`

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
Minetest Lua Mainmenu API Reference 5.2.0
Minetest Lua Mainmenu API Reference 5.0.1
=========================================
Introduction
@@ -79,8 +79,6 @@ core.explode_table_event(string) -> table
core.explode_textlist_event(string) -> table
^ returns e.g. {type="CHG", index=1}
^ type: "INV" (no row selected), "CHG" (selected) or "DCL" (double-click)
core.set_formspec_prepend(formspec)
^ string to be added to every mainmenu formspec, to be used for theming.
GUI:
core.set_background(type, texturepath,[tile],[minsize])
@@ -91,14 +89,13 @@ core.set_background(type, texturepath,[tile],[minsize])
core.set_clouds(<true/false>)
core.set_topleft_text(text)
core.show_keys_menu()
core.show_path_select_dialog(formname, caption, is_file_select)
^ shows a path select dialog
core.file_open_dialog(formname,caption)
^ shows a file open dialog
^ formname is base name of dialog response returned in fields
^ -if dialog was accepted "_accepted"
^ will be added to fieldname containing the path
^^ will be added to fieldname containing the path
^ -if dialog was canceled "_cancelled"
^ will be added to fieldname value is set to formname itself
^ if `is_file_select` is `true`, a file and not a folder will be selected
^ returns nil or selected file/folder
core.get_screen_info()
^ returns {
@@ -243,12 +240,4 @@ Limitations of Async operations
-No access to global lua variables, don't even try
-Limited set of available functions
e.g. No access to functions modifying menu like core.start,core.close,
core.show_path_select_dialog
Background music
----------------
The main menu supports background music.
It looks for a `main_menu` sound in `$USER_PATH/sounds`. The same naming
conventions as for normal sounds apply.
This means the player can add a custom sound.
It will be played in the main menu (gain = 1.0), looped.
core.file_open_dialog

View File

@@ -1,41 +0,0 @@
#!/bin/sh -e
# Patch Python-Markdown
MARKDOWN_FILE=$(pip show markdown | awk '/Location/ { print $2 }')/markdown/extensions/codehilite.py
patch -N -r - $MARKDOWN_FILE lua_highlight.patch || true
# Split lua_api.txt on top level headings
cat ../lua_api.txt | csplit -sz -f docs/section - '/^=/-1' '{*}'
cat > mkdocs.yml << EOF
site_name: Minetest API Documentation
theme:
name: readthedocs
highlightjs: False
extra_css:
- css/code_styles.css
- css/extra.css
markdown_extensions:
- toc:
permalink: True
- codehilite
plugins:
- search:
separator: '[\s\-\.\(]+'
nav:
- "Home": index.md
EOF
mv docs/section00 docs/index.md
for f in docs/section*
do
title=$(head -1 $f)
fname=$(echo $title | tr '[:upper:]' '[:lower:]')
fname=$(echo $fname | sed 's/ /-/g')
fname=$(echo $fname | sed "s/'//g").md
mv $f docs/$fname
echo "- \"$title\": $fname" >> mkdocs.yml
done
mkdocs build --site-dir ../../public

View File

@@ -1,68 +0,0 @@
.codehilite .hll { background-color: #ffffcc }
.codehilite .c { color: #408080; font-style: italic } /* Comment */
/* .codehilite .err { border: 1px solid #FF0000 } /* Error */
.codehilite .k { color: #008000; font-weight: bold } /* Keyword */
.codehilite .o { color: #666666 } /* Operator */
.codehilite .ch { color: #408080; font-style: italic } /* Comment.Hashbang */
.codehilite .cm { color: #408080; font-style: italic } /* Comment.Multiline */
.codehilite .cp { color: #BC7A00 } /* Comment.Preproc */
.codehilite .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */
.codehilite .c1 { color: #408080; font-style: italic } /* Comment.Single */
.codehilite .cs { color: #408080; font-style: italic } /* Comment.Special */
.codehilite .gd { color: #A00000 } /* Generic.Deleted */
.codehilite .ge { font-style: italic } /* Generic.Emph */
.codehilite .gr { color: #FF0000 } /* Generic.Error */
.codehilite .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.codehilite .gi { color: #00A000 } /* Generic.Inserted */
.codehilite .go { color: #888888 } /* Generic.Output */
.codehilite .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.codehilite .gs { font-weight: bold } /* Generic.Strong */
.codehilite .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.codehilite .gt { color: #0044DD } /* Generic.Traceback */
.codehilite .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
.codehilite .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
.codehilite .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
.codehilite .kp { color: #008000 } /* Keyword.Pseudo */
.codehilite .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
.codehilite .kt { color: #B00040 } /* Keyword.Type */
.codehilite .m { color: #666666 } /* Literal.Number */
.codehilite .s { color: #BA2121 } /* Literal.String */
.codehilite .na { color: #7D9029 } /* Name.Attribute */
.codehilite .nb { color: #008000 } /* Name.Builtin */
.codehilite .nc { color: #0000FF; font-weight: bold } /* Name.Class */
.codehilite .no { color: #880000 } /* Name.Constant */
.codehilite .nd { color: #AA22FF } /* Name.Decorator */
.codehilite .ni { color: #999999; font-weight: bold } /* Name.Entity */
.codehilite .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.codehilite .nf { color: #0000FF } /* Name.Function */
.codehilite .nl { color: #A0A000 } /* Name.Label */
.codehilite .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.codehilite .nt { color: #008000; font-weight: bold } /* Name.Tag */
.codehilite .nv { color: #19177C } /* Name.Variable */
.codehilite .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.codehilite .w { color: #bbbbbb } /* Text.Whitespace */
.codehilite .mb { color: #666666 } /* Literal.Number.Bin */
.codehilite .mf { color: #666666 } /* Literal.Number.Float */
.codehilite .mh { color: #666666 } /* Literal.Number.Hex */
.codehilite .mi { color: #666666 } /* Literal.Number.Integer */
.codehilite .mo { color: #666666 } /* Literal.Number.Oct */
.codehilite .sa { color: #BA2121 } /* Literal.String.Affix */
.codehilite .sb { color: #BA2121 } /* Literal.String.Backtick */
.codehilite .sc { color: #BA2121 } /* Literal.String.Char */
.codehilite .dl { color: #BA2121 } /* Literal.String.Delimiter */
.codehilite .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
.codehilite .s2 { color: #BA2121 } /* Literal.String.Double */
.codehilite .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.codehilite .sh { color: #BA2121 } /* Literal.String.Heredoc */
.codehilite .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.codehilite .sx { color: #008000 } /* Literal.String.Other */
.codehilite .sr { color: #BB6688 } /* Literal.String.Regex */
.codehilite .s1 { color: #BA2121 } /* Literal.String.Single */
.codehilite .ss { color: #19177C } /* Literal.String.Symbol */
.codehilite .bp { color: #008000 } /* Name.Builtin.Pseudo */
.codehilite .fm { color: #0000FF } /* Name.Function.Magic */
.codehilite .vc { color: #19177C } /* Name.Variable.Class */
.codehilite .vg { color: #19177C } /* Name.Variable.Global */
.codehilite .vi { color: #19177C } /* Name.Variable.Instance */
.codehilite .vm { color: #19177C } /* Name.Variable.Magic */
.codehilite .il { color: #666666 } /* Literal.Number.Integer.Long */

View File

@@ -1,15 +0,0 @@
/* Fix partly obscured last TOC element */
.wy-menu {
padding-bottom: 20px;
}
/* Use Minetest green instead of blue */
.wy-nav-content a {
color: hsl(100, 40%, 40%);
}
.wy-nav-content a:hover {
color: hsl(100, 30%, 30%);
}
.wy-side-nav-search, .wy-nav-top, .wy-menu-vertical a:active {
background: hsl(100, 40%, 40%);
}

View File

@@ -1 +0,0 @@
../../../../misc/minetest-icon.ico

View File

@@ -1,19 +0,0 @@
@@ -77,7 +77,7 @@
css_class="codehilite", lang=None, style='default',
noclasses=False, tab_length=4, hl_lines=None, use_pygments=True):
self.src = src
- self.lang = lang
+ self.lang = "lua"
self.linenums = linenums
self.guess_lang = guess_lang
self.css_class = css_class
@@ -119,7 +119,8 @@
cssclass=self.css_class,
style=self.style,
noclasses=self.noclasses,
- hl_lines=self.hl_lines)
+ hl_lines=self.hl_lines,
+ wrapcode=True)
return highlight(self.src, lexer, formatter)
else:
# just escape and build markup usable by JS highlighting libs

View File

@@ -63,7 +63,6 @@ by texture packs. All existing fallback textures can be found in the directory
### Gameplay textures
* `bubble.png`: the bubble texture when the player is drowning
(default size: 12×12)
* `crack_anylength.png`: node overlay texture when digging
@@ -75,7 +74,6 @@ by texture packs. All existing fallback textures can be found in the directory
* `halo.png`: used for the node highlighting mesh
* `heart.png`: used to display the health points of the player
(default size: 12×12)
* `minimap_mask_round.png`: round minimap mask, white gets replaced by the map
* `minimap_mask_square.png`: mask used for the square minimap
@@ -104,9 +102,6 @@ by texture packs. All existing fallback textures can be found in the directory
* `wieldhand.png`: texture of the wieldhand
Note: The default textures of `player.png`, `player_back.png` and `wieldhand.png`
are placeholders intended to be overwritten by the game.
### Mainmenu textures
* `menu_bg.png`: used as mainmenu background when the clouds are disabled

View File

@@ -13,6 +13,12 @@ The block serialization version does not fully specify every aspect of this
format; if compliance with this format is to be checked, it needs to be
done by detecting if the files and data indeed follows it.
Legacy stuff
=============
Data can, in theory, be contained in the flat file directory structure
described below in Version 17, but it is not officially supported. Also you
may stumble upon all kinds of oddities in not-so-recent formats.
Files
======
Everything is contained in a directory, the name of which is freeform, but
@@ -359,9 +365,7 @@ if map format version <= 22:
u16 content_size
u8[content_size] content of metadata. Format depends on type_id, see below.
if map format version >= 23:
u8 version -- Note: type was u16 for map format version <= 22
-- = 1 for map format version < 28
-- = 2 since map format version 28
u8 version (=1) -- Note the type is u8, while for map format version <= 22 it's u16
u16 count of metadata
foreach count:
u16 position (p.Z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + p.Y*MAP_BLOCKSIZE + p.X)
@@ -371,7 +375,6 @@ if map format version >= 23:
u8[key_len] key
u32 val_len
u8[val_len] value
u8 is_private -- only for version >= 2. 0 = not private, 1 = private
serialized inventory
- Node timers
@@ -494,10 +497,10 @@ Static objects are persistent freely moving objects in the world.
Object types:
1: Test object
2: Item
3: Rat (obsolete)
4: Oerkki (obsolete)
5: Firefly (obsolete)
6: MobV2 (obsolete)
3: Rat (deprecated)
4: Oerkki (deprecated)
5: Firefly (deprecated)
6: MobV2 (deprecated)
7: LuaEntity
1: Item:
@@ -507,20 +510,17 @@ Object types:
u8[len] itemstring
7: LuaEntity:
u8 compatibility_byte (always 1)
u16 len
u8[len] entity name
u32 len
u8[len] static data
s16 hp
s32 velocity.x * 10000
s32 velocity.y * 10000
s32 velocity.z * 10000
s32 yaw * 1000
if PROTOCOL_VERSION >= 37:
u8 version2 (=1)
s32 pitch * 1000
s32 roll * 1000
u8 version
version 1:
u16 len
u8[len] entity name
u32 len
u8[len] static data
s16 hp
s32 velocity.x * 10000
s32 velocity.y * 10000
s32 velocity.z * 10000
s32 yaw * 1000
Itemstring format
------------------
@@ -562,3 +562,107 @@ Empty
EndInventoryList
EndInventory
---
==============================================
Minetest World Format used as of 2011-05 or so
==============================================
Map data serialization format version 17.
0.3.1 does not use this format, but a more recent one. This exists here for
historical reasons.
Directory structure:
sectors/XXXXZZZZ or sectors2/XXX/ZZZ
XXXX, ZZZZ, XXX and ZZZ being the hexadecimal X and Z coordinates.
Under these, the block files are stored, called YYYY.
There also exists files map_meta.txt and chunk_meta, that are used by the
generator. If they are not found or invalid, the generator will currently
behave quite strangely.
The MapBlock file format (sectors2/XXX/ZZZ/YYYY):
-------------------------------------------------
NOTE: Byte order is MSB first.
u8 version
- map format version number, this one is version 17
u8 flags
- Flag bitmasks:
- 0x01: is_underground: Should be set to 0 if there will be no light
obstructions above the block. If/when sunlight of a block is updated and
there is no block above it, this value is checked for determining whether
sunlight comes from the top.
- 0x02: day_night_differs: Whether the lighting of the block is different on
day and night. Only blocks that have this bit set are updated when day
transforms to night.
- 0x04: lighting_expired: If true, lighting is invalid and should be updated.
If you can't calculate lighting in your generator properly, you could try
setting this 1 to everything and setting the uppermost block in every
sector as is_underground=0. I am quite sure it doesn't work properly,
though.
zlib-compressed map data:
- content:
u8[4096]: content types
u8[4096]: param1 values
u8[4096]: param2 values
zlib-compressed node metadata
- content:
u16 version (=1)
u16 count of metadata
foreach count:
u16 position (= p.Z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + p.Y*MAP_BLOCKSIZE + p.X)
u16 type_id
u16 content_size
u8[content_size] misc. stuff contained in the metadata
u16 mapblockobject_count
- always write as 0.
- if read != 0, just fail.
foreach mapblockobject_count:
- deprecated, should not be used. Length of this data can only be known by
properly parsing it. Just hope not to run into any of this.
u8 static object version:
- currently 0
u16 static_object_count
foreach static_object_count:
u8 type (object type-id)
s32 pos_x * 1000
s32 pos_y * 1000
s32 pos_z * 1000
u16 data_size
u8[data_size] data
u32 timestamp
- Timestamp when last saved, as seconds from starting the game.
- 0xffffffff = invalid/unknown timestamp, nothing will be done with the time
difference when loaded (recommended)
Node metadata format:
---------------------
Sign metadata:
u16 string_len
u8[string_len] string
Furnace metadata:
TBD
Chest metadata:
TBD
Locking Chest metadata:
u16 string_len
u8[string_len] string
TBD
// END

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1801,7 +1801,7 @@ function default.spawn_falling_node(p, nodename)
spawn_falling_node(p, nodename)
end
-- Horrible stuff to support old code
-- Horrible crap to support old code
-- Don't use this and never do what this does, it's completely wrong!
-- (More specifically, the client and the C++ code doesn't get the group)
function default.register_falling_node(nodename, texture)
@@ -1835,3 +1835,64 @@ minetest.register_on_dignode(on_dignode)
function on_punchnode(p, node)
end
minetest.register_on_punchnode(on_punchnode)
--
-- Test some things
--
local function test_get_craft_result()
minetest.log("info", "test_get_craft_result()")
-- normal
local input = {
method = "normal",
width = 2,
items = {"", "default:coal_lump", "", "default:stick"}
}
minetest.log("info", "torch crafting input: "..dump(input))
local output, decremented_input = minetest.get_craft_result(input)
minetest.log("info", "torch crafting output: "..dump(output))
minetest.log("info", "torch crafting decremented input: "..dump(decremented_input))
assert(output.item)
minetest.log("info", "torch crafting output.item:to_table(): "..dump(output.item:to_table()))
assert(output.item:get_name() == "default:torch")
assert(output.item:get_count() == 4)
-- fuel
local input = {
method = "fuel",
width = 1,
items = {"default:coal_lump"}
}
minetest.log("info", "coal fuel input: "..dump(input))
local output, decremented_input = minetest.get_craft_result(input)
minetest.log("info", "coal fuel output: "..dump(output))
minetest.log("info", "coal fuel decremented input: "..dump(decremented_input))
assert(output.time)
assert(output.time > 0)
-- cook
local input = {
method = "cooking",
width = 1,
items = {"default:cobble"}
}
minetest.log("info", "cobble cooking input: "..dump(output))
local output, decremented_input = minetest.get_craft_result(input)
minetest.log("info", "cobble cooking output: "..dump(output))
minetest.log("info", "cobble cooking decremented input: "..dump(decremented_input))
assert(output.time)
assert(output.time > 0)
assert(output.item)
minetest.log("info", "cobble cooking output.item:to_table(): "..dump(output.item:to_table()))
assert(output.item:get_name() == "default:stone")
assert(output.item:get_count() == 1)
end
test_get_craft_result()
--
-- Done, print some random stuff
--
--print("minetest.registered_entities:")
--dump2(minetest.registered_entities)
-- END

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 B

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