Merge branch 'minetest:master' into bfs-water-shaders

This commit is contained in:
DragonWrangler1 2024-09-17 09:47:52 -07:00 committed by GitHub
commit 7dfc91e616
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
454 changed files with 13379 additions and 15708 deletions

View File

@ -1,9 +1,16 @@
[*] [*]
end_of_line = lf end_of_line = lf
[*.{cpp,h,lua,txt,glsl,md,c,cmake,java,gradle}] [*.{cpp,h,lua,txt,glsl,c,cmake,java,gradle}]
charset = utf-8 charset = utf-8
indent_size = 4 indent_size = 4
indent_style = tab indent_style = tab
insert_final_newline = true insert_final_newline = true
trim_trailing_whitespace = true trim_trailing_whitespace = true
[*.md]
charset = utf-8
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

View File

@ -35,7 +35,12 @@ jobs:
- name: Install deps - name: Install deps
run: | run: |
sudo apt-get update sudo apt-get update
sudo apt-get install -y --no-install-recommends gettext openjdk-17-jdk-headless sudo apt-get install -y --no-install-recommends gettext
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
- name: Build AAB with Gradle - name: Build AAB with Gradle
# We build an AAB as well for uploading to the the Play Store. # We build an AAB as well for uploading to the the Play Store.
run: cd android; ./gradlew bundlerelease run: cd android; ./gradlew bundlerelease

View File

@ -10,6 +10,7 @@ on:
- 'src/**.cpp' - 'src/**.cpp'
- 'irr/**.[ch]' - 'irr/**.[ch]'
- 'irr/**.cpp' - 'irr/**.cpp'
- 'irr/**.mm' # Objective-C(++)
- '**/CMakeLists.txt' - '**/CMakeLists.txt'
- 'cmake/Modules/**' - 'cmake/Modules/**'
- '.github/workflows/macos.yml' - '.github/workflows/macos.yml'
@ -28,7 +29,8 @@ on:
jobs: jobs:
build: build:
runs-on: macos-latest # use lowest possible macOS running on x86_64 to support more users
runs-on: macos-12
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Install deps - name: Install deps
@ -58,6 +60,7 @@ jobs:
- name: CPack - name: CPack
run: | run: |
cd build cd build
rm -rf macos
cmake .. -DINSTALL_DEVTEST=FALSE cmake .. -DINSTALL_DEVTEST=FALSE
cpack -G ZIP -B macos cpack -G ZIP -B macos

45
.github/workflows/whitespace_checks.yml vendored Normal file
View File

@ -0,0 +1,45 @@
name: whitespace_checks
# Check whitespaces of the following file types
# Not checked: .lua, .yml, .properties, .conf, .java, .py, .svg, .gradle, .xml, ...
# (luacheck already checks .lua files)
on:
push:
paths:
- '**.txt'
- '**.md'
- '**.[ch]'
- '**.cpp'
- '**.hpp'
- '**.sh'
- '**.cmake'
- '**.glsl'
pull_request:
paths:
- '**.txt'
- '**.md'
- '**.[ch]'
- '**.cpp'
- '**.hpp'
- '**.sh'
- '**.cmake'
- '**.glsl'
jobs:
trailing_whitespaces:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Line endings are already ensured by .gitattributes
- name: Check trailing whitespaces
run: if git ls-files | grep -E '\.txt$|\.md$|\.[ch]$|\.cpp$|\.hpp$|\.sh$|\.cmake$|\.glsl$' | xargs grep -n '\s$'; then echo -e "\033[0;31mFound trailing whitespace"; (exit 1); else (exit 0); fi
tabs_lua_api_files:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Some files should not contain tabs
- name: Check tabs in Lua API files
run: if grep -n $'\t' doc/lua_api.md doc/client_lua_api.md; then echo -e "\033[0;31mFound tab in markdown file"; (exit 1); else (exit 0); fi

4
.gitignore vendored
View File

@ -43,6 +43,10 @@ build/.cmake/
*.zsync *.zsync
appimage-build appimage-build
AppDir AppDir
# Direnv
.direnv/
# Nix
/result
## Files related to Minetest development cycle ## Files related to Minetest development cycle
/*.patch /*.patch

View File

@ -20,7 +20,7 @@ read_globals = {
"PerlinNoise", "PerlinNoiseMap", "PerlinNoise", "PerlinNoiseMap",
string = {fields = {"split", "trim"}}, string = {fields = {"split", "trim"}},
table = {fields = {"copy", "getn", "indexof", "insert_all"}}, table = {fields = {"copy", "getn", "indexof", "keyof", "insert_all"}},
math = {fields = {"hypot", "round"}}, math = {fields = {"hypot", "round"}},
} }
@ -37,6 +37,12 @@ files["builtin/client/register.lua"] = {
} }
} }
files["builtin/common/math.lua"] = {
globals = {
"math",
},
}
files["builtin/common/misc_helpers.lua"] = { files["builtin/common/misc_helpers.lua"] = {
globals = { globals = {
"dump", "dump2", "table", "math", "string", "dump", "dump2", "table", "math", "string",
@ -46,7 +52,7 @@ files["builtin/common/misc_helpers.lua"] = {
} }
files["builtin/common/vector.lua"] = { files["builtin/common/vector.lua"] = {
globals = { "vector" }, globals = { "vector", "math" },
} }
files["builtin/game/voxelarea.lua"] = { files["builtin/game/voxelarea.lua"] = {

View File

@ -11,7 +11,7 @@ set(CLANG_MINIMUM_VERSION "7.0.1")
# You should not need to edit these manually, use util/bump_version.sh # You should not need to edit these manually, use util/bump_version.sh
set(VERSION_MAJOR 5) set(VERSION_MAJOR 5)
set(VERSION_MINOR 9) set(VERSION_MINOR 10)
set(VERSION_PATCH 0) set(VERSION_PATCH 0)
set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string") set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string")
@ -56,6 +56,11 @@ if((WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR APPLE)
endif() endif()
set(ENABLE_LTO ${DEFAULT_ENABLE_LTO} CACHE BOOL "Use Link Time Optimization") set(ENABLE_LTO ${DEFAULT_ENABLE_LTO} CACHE BOOL "Use Link Time Optimization")
set(BUILD_WITH_TRACY FALSE CACHE BOOL
"Fetch and build with the Tracy profiler client")
set(FETCH_TRACY_GIT_TAG "master" CACHE STRING
"Git tag for fetching Tracy client. Match with your server (gui) version")
set(DEFAULT_RUN_IN_PLACE FALSE) set(DEFAULT_RUN_IN_PLACE FALSE)
if(WIN32) if(WIN32)
set(DEFAULT_RUN_IN_PLACE TRUE) set(DEFAULT_RUN_IN_PLACE TRUE)
@ -283,6 +288,8 @@ if(BUILD_UNITTESTS OR BUILD_BENCHMARKS)
add_subdirectory(lib/catch2) add_subdirectory(lib/catch2)
endif() endif()
add_subdirectory(lib/tiniergltf)
# Subdirectories # Subdirectories
# Be sure to add all relevant definitions above this # Be sure to add all relevant definitions above this
add_subdirectory(src) add_subdirectory(src)
@ -368,3 +375,19 @@ if(BUILD_DOCUMENTATION)
) )
endif() endif()
endif() endif()
# Fetch Tracy
if(BUILD_WITH_TRACY)
include(FetchContent)
message(STATUS "Fetching Tracy (${FETCH_TRACY_GIT_TAG})...")
FetchContent_Declare(
tracy
GIT_REPOSITORY https://github.com/wolfpld/tracy.git
GIT_TAG ${FETCH_TRACY_GIT_TAG}
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(tracy)
message(STATUS "Fetching Tracy - done")
endif()

View File

@ -119,6 +119,7 @@ Command-line options
Compiling Compiling
--------- ---------
- [Compiling - common information](doc/compiling/README.md)
- [Compiling on GNU/Linux](doc/compiling/linux.md) - [Compiling on GNU/Linux](doc/compiling/linux.md)
- [Compiling on Windows](doc/compiling/windows.md) - [Compiling on Windows](doc/compiling/windows.md)
- [Compiling on MacOS](doc/compiling/macos.md) - [Compiling on MacOS](doc/compiling/macos.md)

View File

@ -1,15 +1,18 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
android { android {
compileSdkVersion 33
buildToolsVersion '33.0.2'
ndkVersion "$ndk_version" ndkVersion "$ndk_version"
defaultConfig { defaultConfig {
applicationId 'net.minetest.minetest' applicationId 'net.minetest.minetest'
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 33 compileSdk 34
targetSdkVersion 34
versionName "${versionMajor}.${versionMinor}.${versionPatch}" versionName "${versionMajor}.${versionMinor}.${versionPatch}"
versionCode project.versionCode versionCode versionMajor * 1000000 + versionMinor * 10000 + versionPatch * 100 + versionBuild
}
buildFeatures {
buildConfig true
} }
// load properties // load properties
@ -49,6 +52,7 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8
} }
namespace 'net.minetest.minetest'
} }
task prepareAssets() { task prepareAssets() {
@ -112,18 +116,6 @@ clean {
delete new File("src/main/assets", "Minetest.zip") delete new File("src/main/assets", "Minetest.zip")
} }
// Map for the version code that gives each ABI a value.
import com.android.build.OutputFile
def abiCodes = ['armeabi-v7a': 0, 'arm64-v8a': 1]
android.applicationVariants.all { variant ->
variant.outputs.each {
output ->
def abiName = output.getFilter(OutputFile.ABI)
output.versionCodeOverride = abiCodes.get(abiName, 0) + variant.versionCode
}
}
dependencies { dependencies {
implementation project(':native') implementation project(':native')
implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'androidx.appcompat:appcompat:1.6.1'

View File

@ -1,8 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
package="net.minetest.minetest" android:installLocation="auto">
android:installLocation="auto">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

View File

@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
package net.minetest.minetest; package net.minetest.minetest;
import android.annotation.SuppressLint;
import android.app.NotificationChannel; import android.app.NotificationChannel;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
@ -83,13 +84,18 @@ public class MainActivity extends AppCompatActivity {
} }
}; };
@SuppressLint("UnspecifiedRegisterReceiverFlag")
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); setContentView(R.layout.activity_main);
IntentFilter filter = new IntentFilter(ACTION_UPDATE); IntentFilter filter = new IntentFilter(ACTION_UPDATE);
registerReceiver(myReceiver, filter); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
registerReceiver(myReceiver, filter, RECEIVER_NOT_EXPORTED);
} else {
registerReceiver(myReceiver, filter);
}
mProgressBar = findViewById(R.id.progressBar); mProgressBar = findViewById(R.id.progressBar);
mTextView = findViewById(R.id.textView); mTextView = findViewById(R.id.textView);

View File

@ -186,6 +186,7 @@ public class UnzipService extends IntentService {
private void publishProgress(@Nullable Notification.Builder notificationBuilder, @StringRes int message, int progress) { private void publishProgress(@Nullable Notification.Builder notificationBuilder, @StringRes int message, int progress) {
Intent intentUpdate = new Intent(ACTION_UPDATE); Intent intentUpdate = new Intent(ACTION_UPDATE);
intentUpdate.setPackage(getPackageName());
intentUpdate.putExtra(ACTION_PROGRESS, progress); intentUpdate.putExtra(ACTION_PROGRESS, progress);
intentUpdate.putExtra(ACTION_PROGRESS_MESSAGE, message); intentUpdate.putExtra(ACTION_PROGRESS_MESSAGE, message);
if (!isSuccess) if (!isSuccess)

View File

@ -1,13 +1,12 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
project.ext.set("versionMajor", 5) // Version Major project.ext.set("versionMajor", 5) // Version Major
project.ext.set("versionMinor", 9) // Version Minor project.ext.set("versionMinor", 10) // Version Minor
project.ext.set("versionPatch", 0) // Version Patch project.ext.set("versionPatch", 0) // Version Patch
// ^ keep in sync with cmake // ^ keep in sync with cmake
project.ext.set("versionCode", 46) // Android Version Code
// NOTE: +2 after each release! project.ext.set("versionBuild", 0) // Version Build
// +1 for ARM and +1 for ARM64 APK's, because // ^ fourth version number to allow releasing Android-only fixes and beta versions
// each APK must have a larger `versionCode` than the previous
buildscript { buildscript {
ext.ndk_version = '26.2.11394342' ext.ndk_version = '26.2.11394342'
@ -16,7 +15,7 @@ buildscript {
mavenCentral() mavenCentral()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:7.4.1' classpath 'com.android.tools.build:gradle:8.5.1'
classpath 'de.undercouch:gradle-download-task:4.1.1' classpath 'de.undercouch:gradle-download-task:4.1.1'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files

View File

@ -9,3 +9,5 @@ org.gradle.parallel.threads=8
org.gradle.configureondemand=true org.gradle.configureondemand=true
android.enableJetifier=false android.enableJetifier=false
android.useAndroidX=true android.useAndroidX=true
android.nonTransitiveRClass=false
android.nonFinalResIds=false

View File

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

View File

@ -1,194 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="512"
viewBox="0 0 135.46666 135.46667"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r15371"
sodipodi:docname="gear_icon.svg"
inkscape:export-filename="/home/stu/Desktop/icons/png/gear_icon.png"
inkscape:export-xdpi="24"
inkscape:export-ydpi="24">
<defs
id="defs2">
<marker
style="overflow:visible"
refY="0.0"
refX="0.0"
orient="auto"
id="DistanceX">
<path
id="path4687"
style="stroke:#000000; stroke-width:0.5"
d="M 3,-3 L -3,3 M 0,-5 L 0,5" />
</marker>
<pattern
y="0"
x="0"
width="8"
patternUnits="userSpaceOnUse"
id="Hatch"
height="8">
<path
id="path4690"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M8 4 l-4,4" />
<path
id="path4692"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M6 2 l-4,4" />
<path
id="path4694"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M4 0 l-4,4" />
</pattern>
<marker
style="overflow:visible"
refY="0.0"
refX="0.0"
orient="auto"
id="DistanceX-3">
<path
id="path4756"
style="stroke:#000000; stroke-width:0.5"
d="M 3,-3 L -3,3 M 0,-5 L 0,5" />
</marker>
<pattern
y="0"
x="0"
width="8"
patternUnits="userSpaceOnUse"
id="Hatch-6"
height="8">
<path
id="path4759"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M8 4 l-4,4" />
<path
id="path4761"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M6 2 l-4,4" />
<path
id="path4763"
stroke-width="0.25"
stroke="#000000"
linecap="square"
d="M4 0 l-4,4" />
</pattern>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#404040"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.5"
inkscape:cx="-308.644"
inkscape:cy="171.10144"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1023"
inkscape:window-x="0"
inkscape:window-y="34"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="false"
inkscape:snap-page="true"
inkscape:snap-grids="true"
inkscape:snap-bbox="true"
inkscape:snap-bbox-midpoints="false"
inkscape:snap-object-midpoints="true"
inkscape:snap-to-guides="false"
inkscape:showpageshadow="false"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="false">
<inkscape:grid
type="xygrid"
id="grid16"
spacingx="2.1166666"
spacingy="2.1166666"
empspacing="2"
color="#40ff40"
opacity="0.1254902"
empcolor="#40ff40"
empopacity="0.25098039" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-161.53332)">
<g
id="g4792"
transform="matrix(0.68725287,0,0,0.65623884,67.477909,-509.24679)"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.74041259;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
<g
id="g4772"
inkscape:label="OpenJsCad"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.74041259;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 256,80.943359 -8.28125,0.72461 -3.63477,5.410156 -5.61328,12.685547 -2.28906,9.259768 -0.35156,5.1875 0.0937,0.86133 0.70703,2.44726 0.60547,9.80664 -2.66602,5.47461 -21.5957,5.78711 -5.04492,-3.40625 -4.37696,-8.79687 -0.61132,-2.47071 -0.35157,-0.79297 -2.89648,-4.31836 -6.60938,-6.87304 -11.20507,-8.17969 -5.84961,-2.86719 -7.53516,3.51367 -6.80859,4.76954 -0.44336,6.50195 1.48047,13.79297 2.64453,9.16406 2.28906,4.66992 0.51172,0.69922 1.83398,1.76563 5.42774,8.18945 0.42773,6.07422 -15.81054,15.81445 -6.07032,-0.42773 -8.18945,-5.42969 -1.76367,-1.83399 -0.69922,-0.51171 -4.66992,-2.28907 -9.15821,-2.64843 -13.79297,-1.47852 -6.5,0.44141 -4.76757,6.8125 -3.51367,7.53515 2.86914,5.85157 8.17382,11.20703 6.87305,6.61132 4.31641,2.90039 0.79297,0.34961 2.4707,0.61133 8.79492,4.37696 3.4043,5.04687 -5.78516,21.60156 -5.47265,2.66602 -9.80469,-0.60547 -2.44727,-0.70703 -0.85937,-0.0918 -5.1875,0.35156 -9.257816,2.28907 -12.68164,5.61523 -5.408203,3.63281 -0.72461,8.28516 0.72461,8.28516 5.408203,3.63281 12.68164,5.61523 9.257816,2.28907 5.1875,0.35156 0.85937,-0.0918 2.44727,-0.70703 9.80469,-0.60547 5.47265,2.66602 5.78516,21.60156 -3.4043,5.04687 -8.79492,4.37696 -2.4707,0.61133 -0.79297,0.34961 -4.31641,2.90039 -6.87305,6.61132 -8.17382,11.20703 -2.86914,5.85157 3.51367,7.53515 4.76757,6.8125 6.5,0.44141 13.79297,-1.47852 9.15821,-2.64843 4.66992,-2.28907 0.69922,-0.50976 1.76367,-1.83594 8.18945,-5.42969 6.07032,-0.42773 15.81054,15.81445 -0.42773,6.07422 -5.42774,8.18945 -1.83398,1.76563 -0.51172,0.69922 -2.28906,4.66992 -2.64453,9.16406 -1.48047,13.79297 0.44336,6.50195 6.80859,4.76758 7.53516,3.51758 5.84961,-2.86914 11.20507,-8.17969 6.60938,-6.87304 2.89648,-4.31836 0.35157,-0.79297 0.61132,-2.47071 4.37696,-8.79687 5.04492,-3.40625 21.5957,5.78711 2.66602,5.47461 -0.60547,9.80664 -0.70703,2.44726 -0.0937,0.85938 0.35156,5.18945 2.28906,9.25977 5.61328,12.68555 3.63477,5.41015 8.28125,0.72461 8.28125,-0.72461 3.63477,-5.41015 5.61328,-12.68555 2.28906,-9.25977 0.35156,-5.18945 -0.0937,-0.85938 -0.70703,-2.44726 -0.60547,-9.80664 2.66602,-5.47461 21.5957,-5.78711 5.04492,3.40625 4.37696,8.79687 0.61132,2.47071 0.35157,0.79297 2.89648,4.31836 6.60938,6.87304 11.20507,8.17969 5.84961,2.86914 7.53516,-3.51758 6.80859,-4.76758 0.44336,-6.50195 -1.48047,-13.79297 -2.64453,-9.16406 -2.28906,-4.66992 -0.51172,-0.69922 -1.83398,-1.76563 -5.42774,-8.18945 -0.42773,-6.07422 15.81054,-15.81445 6.07032,0.42773 8.18945,5.42969 1.76367,1.83594 0.69922,0.50976 4.66992,2.28907 9.15821,2.64843 13.79297,1.47852 6.5,-0.44141 v -0.002 l 4.76757,-6.81055 3.51367,-7.53711 -2.86914,-5.85156 -8.17382,-11.20508 -6.87305,-6.61328 -4.31641,-2.89843 -0.79297,-0.34961 -2.4707,-0.61133 -8.79492,-4.37891 -3.4043,-5.04492 5.78516,-21.60352 5.47265,-2.66797 9.80469,0.60938 2.44727,0.70703 0.85937,0.0918 5.1875,-0.35156 9.25782,-2.28907 12.68164,-5.61718 5.4082,-3.63282 0.72461,-8.28515 -0.72461,-8.28321 -5.4082,-3.63476 -12.68164,-5.61524 -9.25782,-2.28711 -5.1875,-0.35351 -0.85937,0.0937 -2.44727,0.70508 -9.80469,0.60937 -5.47265,-2.66797 -5.78516,-21.59961 3.4043,-5.04882 8.79492,-4.37696 2.4707,-0.61133 0.79297,-0.35156 4.31641,-2.89844 6.87305,-6.61132 8.17382,-11.20703 2.86914,-5.85157 -3.51367,-7.53711 -4.76757,-6.81054 -6.5,-0.44336 -13.79297,1.48047 -9.15821,2.64648 -4.66992,2.28906 -0.69922,0.51172 -1.76367,1.83594 -8.18945,5.42773 -6.07032,0.42774 -15.81054,-15.81446 0.42773,-6.07226 5.42774,-8.18945 1.83398,-1.76563 0.51172,-0.69922 2.28906,-4.67187 2.64453,-9.16016 1.48047,-13.79492 -0.44336,-6.50195 -6.80859,-4.76954 -7.53516,-3.51562 -5.84961,2.87109 -11.20507,8.17578 -6.60938,6.875 -2.89648,4.31836 -0.35157,0.79102 -0.61132,2.47266 -4.37696,8.79687 -5.04492,3.4082 -21.5957,-5.79101 -2.66602,-5.47266 0.60547,-9.80664 0.70703,-2.44726 0.0937,-0.85938 -0.35156,-5.19141 -2.28906,-9.259761 -5.61328,-12.683594 -3.63477,-5.412109 z m 0,97.111331 A 77.946197,77.946197 0 0 1 333.94531,256 77.946197,77.946197 0 0 1 256,333.94531 77.946197,77.946197 0 0 1 178.05469,256 77.946197,77.946197 0 0 1 256,178.05469 Z"
transform="matrix(0.38495268,0,0,0.40318156,-98.176247,1022.1341)"
id="path4768"
inkscape:connector-curvature="0" />
</g>
<g
id="g4774"
inkscape:label="0"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.74041259;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 9.7 KiB

View File

@ -2,23 +2,23 @@
<!-- Created with Inkscape (http://www.inkscape.org/) --> <!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg <svg
xmlns:dc="http://purl.org/dc/elements/1.1/" width="512"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="256"
height="512" height="512"
viewBox="0 0 67.73333 135.46667" viewBox="0 0 135.46666 135.46667"
version="1.1" version="1.1"
id="svg8" id="svg8"
inkscape:version="0.92.1 r15371" inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)"
sodipodi:docname="rare_controls.svg" sodipodi:docname="overflow_btn.svg"
inkscape:export-filename="/home/stu/Desktop/icons/png/rare_controls.png" inkscape:export-filename="../../textures/base/pack/overflow_btn.png"
inkscape:export-xdpi="24.000002" inkscape:export-xdpi="24.000002"
inkscape:export-ydpi="24.000002"> inkscape:export-ydpi="24.000002"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs <defs
id="defs2"> id="defs2">
<filter <filter
@ -397,22 +397,24 @@
borderopacity="1.0" borderopacity="1.0"
inkscape:pageopacity="0" inkscape:pageopacity="0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="0.7" inkscape:zoom="0.98994949"
inkscape:cx="-59.862018" inkscape:cx="41.921331"
inkscape:cy="260.34663" inkscape:cy="163.13964"
inkscape:document-units="mm" inkscape:document-units="mm"
inkscape:current-layer="layer2" inkscape:current-layer="layer2"
showgrid="true" showgrid="true"
units="px" units="px"
inkscape:window-width="1920" inkscape:window-width="1920"
inkscape:window-height="1023" inkscape:window-height="1011"
inkscape:window-x="0" inkscape:window-x="0"
inkscape:window-y="34" inkscape:window-y="32"
inkscape:window-maximized="1" inkscape:window-maximized="1"
inkscape:pagecheckerboard="false" inkscape:pagecheckerboard="false"
inkscape:snap-grids="true" inkscape:snap-grids="true"
inkscape:snap-page="true" inkscape:snap-page="true"
showguides="false"> showguides="false"
inkscape:showpageshadow="2"
inkscape:deskcolor="#d1d1d1">
<inkscape:grid <inkscape:grid
type="xygrid" type="xygrid"
id="grid16" id="grid16"
@ -422,7 +424,11 @@
color="#40ff40" color="#40ff40"
opacity="0.1254902" opacity="0.1254902"
empcolor="#40ff40" empcolor="#40ff40"
empopacity="0.25098039" /> empopacity="0.25098039"
originx="0"
originy="0"
units="px"
visible="true" />
</sodipodi:namedview> </sodipodi:namedview>
<metadata <metadata
id="metadata5"> id="metadata5">
@ -432,7 +438,6 @@
<dc:format>image/svg+xml</dc:format> <dc:format>image/svg+xml</dc:format>
<dc:type <dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license <cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" /> rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work> </cc:Work>
@ -496,26 +501,27 @@
x="264.65997" x="264.65997"
y="124.10143" y="124.10143"
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1" /></flowRegion><flowPara style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1" /></flowRegion><flowPara
id="flowPara4724" /></flowRoot> <rect id="flowPara4724" /></flowRoot>
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5231-9"
width="25.4"
height="25.400003"
x="21.166666"
y="101.6" />
<rect <rect
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" style="display:inline;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:5.38756;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5231-9-7"
width="25.4"
height="25.400003"
x="21.166666"
y="55.033333" />
<rect
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5231-9-5" id="rect5231-9-5"
width="25.4" width="96.212502"
height="25.400003" height="0.61243516"
x="21.166664" x="19.62678"
y="8.4666681" /> y="33.575779" />
<rect
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:5.38755;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5231-9-5-7"
width="96.212448"
height="0.6124543"
x="19.627108"
y="67.442772" />
<rect
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:5.38755;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5231-9-5-7-5"
width="96.212448"
height="0.6124543"
x="19.627108"
y="101.30978" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -2,14 +2,13 @@ apply plugin: 'com.android.library'
apply plugin: 'de.undercouch.download' apply plugin: 'de.undercouch.download'
android { android {
compileSdkVersion 33
buildToolsVersion '33.0.2'
ndkVersion "$ndk_version" ndkVersion "$ndk_version"
defaultConfig { defaultConfig {
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 33 compileSdk 34
targetSdkVersion 34
externalNativeBuild { externalNativeBuild {
cmake { cmake {
arguments "-DANDROID_STL=c++_shared", arguments "-DANDROID_STL=c++_shared",
"-DENABLE_CURL=1", "-DENABLE_SOUND=1", "-DENABLE_CURL=1", "-DENABLE_SOUND=1",
"-DENABLE_GETTEXT=1", "-DENABLE_GETTEXT=1",
@ -40,6 +39,7 @@ android {
} }
} }
} }
namespace 'net.minetest'
} }
// get precompiled deps // get precompiled deps

View File

@ -1 +1 @@
<manifest package="net.minetest" /> <manifest />

View File

@ -69,7 +69,7 @@ local function build_chatcommands_formspec(name, sel, copy)
description = cmds[2].description description = cmds[2].description
if copy then if copy then
local msg = S("Command: @1 @2", local msg = S("Command: @1 @2",
core.colorize("#0FF", "/" .. cmds[1]), cmds[2].params) core.colorize("#0FF", (INIT == "client" and "." or "/") .. cmds[1]), cmds[2].params)
if INIT == "client" then if INIT == "client" then
core.display_chat_message(msg) core.display_chat_message(msg)
else else

41
builtin/common/math.lua Normal file
View File

@ -0,0 +1,41 @@
--[[
Math utils.
--]]
function math.hypot(x, y)
return math.sqrt(x * x + y * y)
end
function math.sign(x, tolerance)
tolerance = tolerance or 0
if x > tolerance then
return 1
elseif x < -tolerance then
return -1
end
return 0
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
end
local v = 1
for k = 2, x do
v = v * k
end
return v
end
function math.round(x)
if x < 0 then
local int = math.ceil(x)
local frac = x - int
return int - ((frac <= -0.5) and 1 or 0)
end
local int = math.floor(x)
local frac = x - int
return int + ((frac >= 0.5) and 1 or 0)
end

View File

@ -1,6 +1,6 @@
-- Registered metatables, used by the C++ packer -- Registered metatables, used by the C++ packer
local known_metatables = {} local known_metatables = {}
function core.register_async_metatable(name, mt) function core.register_portable_metatable(name, mt)
assert(type(name) == "string", ("attempt to use %s value as metatable name"):format(type(name))) assert(type(name) == "string", ("attempt to use %s value as metatable name"):format(type(name)))
assert(type(mt) == "table", ("attempt to register a %s value as metatable"):format(type(mt))) assert(type(mt) == "table", ("attempt to register a %s value as metatable"):format(type(mt)))
assert(known_metatables[name] == nil or known_metatables[name] == mt, assert(known_metatables[name] == nil or known_metatables[name] == mt,
@ -10,4 +10,10 @@ function core.register_async_metatable(name, mt)
end end
core.known_metatables = known_metatables core.known_metatables = known_metatables
core.register_async_metatable("__builtin:vector", vector.metatable) function core.register_async_metatable(...)
core.log("deprecated", "minetest.register_async_metatable is deprecated. " ..
"Use minetest.register_portable_metatable instead.")
return core.register_portable_metatable(...)
end
core.register_portable_metatable("__builtin:vector", vector.metatable)

View File

@ -3,6 +3,7 @@
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Localize functions to avoid table lookups (better performance). -- Localize functions to avoid table lookups (better performance).
local string_sub, string_find = string.sub, string.find local string_sub, string_find = string.sub, string.find
local math = math
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
local function basic_dump(o) local function basic_dump(o)
@ -205,52 +206,21 @@ function table.indexof(list, val)
return -1 return -1
end end
--------------------------------------------------------------------------------
function table.keyof(tb, val)
for k, v in pairs(tb) do
if v == val then
return k
end
end
return nil
end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function string:trim() function string:trim()
return self:match("^%s*(.-)%s*$") return self:match("^%s*(.-)%s*$")
end end
--------------------------------------------------------------------------------
function math.hypot(x, y)
return math.sqrt(x * x + y * y)
end
--------------------------------------------------------------------------------
function math.sign(x, tolerance)
tolerance = tolerance or 0
if x > tolerance then
return 1
elseif x < -tolerance then
return -1
end
return 0
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
end
local v = 1
for k = 2, x do
v = v * k
end
return v
end
function math.round(x)
if x < 0 then
local int = math.ceil(x)
local frac = x - int
return int - ((frac <= -0.5) and 1 or 0)
end
local int = math.floor(x)
local frac = x - int
return int + ((frac >= 0.5) and 1 or 0)
end
local formspec_escapes = { local formspec_escapes = {
["\\"] = "\\\\", ["\\"] = "\\\\",
["["] = "\\[", ["["] = "\\[",
@ -692,6 +662,7 @@ function core.privs_to_string(privs, delim)
list[#list + 1] = priv list[#list + 1] = priv
end end
end end
table.sort(list)
return table.concat(list, delim) return table.concat(list, delim)
end end

View File

@ -1,6 +1,7 @@
_G.core = {} _G.core = {}
_G.vector = {metatable = {}} _G.vector = {metatable = {}}
dofile("builtin/common/math.lua")
dofile("builtin/common/vector.lua") dofile("builtin/common/vector.lua")
dofile("builtin/common/misc_helpers.lua") dofile("builtin/common/misc_helpers.lua")

View File

@ -0,0 +1,16 @@
_G.core = {}
dofile("builtin/common/math.lua")
describe("math", function()
it("round()", function()
assert.equal(0, math.round(0))
assert.equal(10, math.round(10.3))
assert.equal(11, math.round(10.5))
assert.equal(11, math.round(10.7))
assert.equal(-10, math.round(-10.3))
assert.equal(-11, math.round(-10.5))
assert.equal(-11, math.round(-10.7))
assert.equal(0, math.round(0.49999999999999994))
assert.equal(0, math.round(-0.49999999999999994))
end)
end)

View File

@ -1,4 +1,5 @@
_G.core = {} _G.core = {}
dofile("builtin/common/math.lua")
dofile("builtin/common/vector.lua") dofile("builtin/common/vector.lua")
dofile("builtin/common/misc_helpers.lua") dofile("builtin/common/misc_helpers.lua")
@ -166,6 +167,16 @@ describe("table", function()
it("indexof()", function() it("indexof()", function()
assert.equal(1, table.indexof({"foo", "bar"}, "foo")) assert.equal(1, table.indexof({"foo", "bar"}, "foo"))
assert.equal(-1, table.indexof({"foo", "bar"}, "baz")) assert.equal(-1, table.indexof({"foo", "bar"}, "baz"))
assert.equal(-1, table.indexof({[2] = "foo", [3] = "bar"}, "foo"))
assert.equal(-1, table.indexof({[1] = "foo", [3] = "bar"}, "bar"))
end)
it("keyof()", function()
assert.equal("a", table.keyof({a = "foo", b = "bar"}, "foo"))
assert.equal(nil, table.keyof({a = "foo", b = "bar"}, "baz"))
assert.equal(1, table.keyof({"foo", "bar"}, "foo"))
assert.equal(2, table.keyof({[2] = "foo", [3] = "bar"}, "foo"))
assert.equal(3, table.keyof({[1] = "foo", [3] = "bar"}, "bar"))
end) end)
end) end)

View File

@ -1,4 +1,5 @@
_G.vector = {} _G.vector = {}
dofile("builtin/common/math.lua")
dofile("builtin/common/vector.lua") dofile("builtin/common/vector.lua")
describe("vector", function() describe("vector", function()
@ -113,12 +114,35 @@ describe("vector", function()
assert.equal(vector.new(0, 1, -1), a:round()) assert.equal(vector.new(0, 1, -1), a:round())
end) end)
it("ceil()", function()
local a = vector.new(0.1, 0.9, -0.5)
assert.equal(vector.new(1, 1, 0), vector.ceil(a))
assert.equal(vector.new(1, 1, 0), a:ceil())
end)
it("sign()", function()
local a = vector.new(-120.3, 0, 231.5)
assert.equal(vector.new(-1, 0, 1), vector.sign(a))
assert.equal(vector.new(-1, 0, 1), a:sign())
assert.equal(vector.new(0, 0, 1), vector.sign(a, 200))
assert.equal(vector.new(0, 0, 1), a:sign(200))
end)
it("abs()", function()
local a = vector.new(-123.456, 0, 13)
assert.equal(vector.new(123.456, 0, 13), vector.abs(a))
assert.equal(vector.new(123.456, 0, 13), a:abs())
end)
it("apply()", function() it("apply()", function()
local i = 0 local i = 0
local f = function(x) local f = function(x)
i = i + 1 i = i + 1
return x + i return x + i
end end
local f2 = function(x, opt1, opt2, opt3)
return x + opt1 + opt2 + opt3
end
local a = vector.new(0.1, 0.9, -0.5) local a = vector.new(0.1, 0.9, -0.5)
assert.equal(vector.new(1, 1, 0), vector.apply(a, math.ceil)) assert.equal(vector.new(1, 1, 0), vector.apply(a, math.ceil))
assert.equal(vector.new(1, 1, 0), a:apply(math.ceil)) assert.equal(vector.new(1, 1, 0), a:apply(math.ceil))
@ -126,6 +150,9 @@ describe("vector", function()
assert.equal(vector.new(0.1, 0.9, 0.5), a:apply(math.abs)) assert.equal(vector.new(0.1, 0.9, 0.5), a:apply(math.abs))
assert.equal(vector.new(1.1, 2.9, 2.5), vector.apply(a, f)) assert.equal(vector.new(1.1, 2.9, 2.5), vector.apply(a, f))
assert.equal(vector.new(4.1, 5.9, 5.5), a:apply(f)) assert.equal(vector.new(4.1, 5.9, 5.5), a:apply(f))
local b = vector.new(1, 2, 3)
assert.equal(vector.new(4, 5, 6), vector.apply(b, f2, 1, 1, 1))
assert.equal(vector.new(4, 5, 6), b:apply(f2, 1, 1, 1))
end) end)
it("combine()", function() it("combine()", function()
@ -469,4 +496,13 @@ describe("vector", function()
assert.True(vector.in_area(vector.new(-10, -10, -10), vector.new(-10, -10, -10), vector.new(10, 10, 10))) assert.True(vector.in_area(vector.new(-10, -10, -10), vector.new(-10, -10, -10), vector.new(10, 10, 10)))
assert.False(vector.in_area(vector.new(-10, -10, -10), vector.new(10, 10, 10), vector.new(-11, -10, -10))) assert.False(vector.in_area(vector.new(-10, -10, -10), vector.new(10, 10, 10), vector.new(-11, -10, -10)))
end) end)
it("random_in_area()", function()
local min = vector.new(-100, -100, -100)
local max = vector.new(100, 100, 100)
for i = 1, 1000 do
local random = vector.random_in_area(min, max)
assert.True(vector.in_area(random, min, max))
end
end)
end) end)

View File

@ -5,6 +5,7 @@ Note: The vector.*-functions must be able to accept old vectors that had no meta
-- localize functions -- localize functions
local setmetatable = setmetatable local setmetatable = setmetatable
local math = math
vector = {} vector = {}
@ -97,18 +98,26 @@ function vector.floor(v)
end end
function vector.round(v) function vector.round(v)
return fast_new( return vector.apply(v, math.round)
math.round(v.x),
math.round(v.y),
math.round(v.z)
)
end end
function vector.apply(v, func) function vector.ceil(v)
return vector.apply(v, math.ceil)
end
function vector.sign(v, tolerance)
return vector.apply(v, math.sign, tolerance)
end
function vector.abs(v)
return vector.apply(v, math.abs)
end
function vector.apply(v, func, ...)
return fast_new( return fast_new(
func(v.x), func(v.x, ...),
func(v.y), func(v.y, ...),
func(v.z) func(v.z, ...)
) )
end end
@ -375,6 +384,26 @@ function vector.in_area(pos, min, max)
(pos.z >= min.z) and (pos.z <= max.z) (pos.z >= min.z) and (pos.z <= max.z)
end end
function vector.random_direction()
-- Generate a random direction of unit length, via rejection sampling
local x, y, z, l2
repeat -- expected less than two attempts on average (volume sphere vs. cube)
x, y, z = math.random() * 2 - 1, math.random() * 2 - 1, math.random() * 2 - 1
l2 = x*x + y*y + z*z
until l2 <= 1 and l2 >= 1e-6
-- normalize
local l = math.sqrt(l2)
return fast_new(x/l, y/l, z/l)
end
function vector.random_in_area(min, max)
return fast_new(
math.random(min.x, max.x),
math.random(min.y, max.y),
math.random(min.z, max.z)
)
end
if rawget(_G, "core") and core.set_read_vector and core.set_push_vector then if rawget(_G, "core") and core.set_read_vector and core.set_push_vector then
local function read_vector(v) local function read_vector(v)
return v.x, v.y, v.z return v.x, v.y, v.z

View File

@ -19,7 +19,7 @@
local BASE_SPACING = 0.1 local BASE_SPACING = 0.1
local function get_scroll_btn_width() local function get_scroll_btn_width()
return core.settings:get_bool("enable_touch") and 0.8 or 0.5 return core.settings:get_bool("touch_gui") and 0.8 or 0.5
end end
local function buttonbar_formspec(self) local function buttonbar_formspec(self)
@ -28,10 +28,8 @@ local function buttonbar_formspec(self)
end end
local formspec = { local formspec = {
"style_type[box;noclip=true]",
string.format("box[%f,%f;%f,%f;%s]", self.pos.x, self.pos.y, self.size.x, string.format("box[%f,%f;%f,%f;%s]", self.pos.x, self.pos.y, self.size.x,
self.size.y, self.bgcolor), self.size.y, self.bgcolor),
"style_type[box;noclip=false]",
} }
local btn_size = self.size.y - 2*BASE_SPACING local btn_size = self.size.y - 2*BASE_SPACING
@ -71,7 +69,7 @@ local function buttonbar_formspec(self)
y = self.pos.y + BASE_SPACING, y = self.pos.y + BASE_SPACING,
} }
table.insert(formspec, string.format("image_button[%f,%f;%f,%f;%s;%s;%s;true;false]tooltip[%s;%s]", table.insert(formspec, string.format("image_button[%f,%f;%f,%f;%s;%s;%s;false;false]tooltip[%s;%s]",
btn_pos.x, btn_pos.y, btn_size, btn_size, btn.image, btn.name, btn_pos.x, btn_pos.y, btn_size, btn_size, btn.image, btn.name,
btn.caption, btn.name, btn.tooltip)) btn.caption, btn.name, btn.tooltip))
end end
@ -86,9 +84,6 @@ local function buttonbar_formspec(self)
y = self.pos.y + BASE_SPACING, y = self.pos.y + BASE_SPACING,
} }
table.insert(formspec, string.format("style[%s,%s;noclip=true]",
self.btn_prev_name, self.btn_next_name))
table.insert(formspec, string.format("button[%f,%f;%f,%f;%s;<]", table.insert(formspec, string.format("button[%f,%f;%f,%f;%s;<]",
btn_prev_pos.x, btn_prev_pos.y, get_scroll_btn_width(), btn_size, btn_prev_pos.x, btn_prev_pos.y, get_scroll_btn_width(), btn_size,
self.btn_prev_name)) self.btn_prev_name))

View File

@ -66,11 +66,22 @@ local function get_formspec(self)
local content, prepend = tab.get_formspec(self, tab.name, tab.tabdata, tab.tabsize) local content, prepend = tab.get_formspec(self, tab.name, tab.tabdata, tab.tabsize)
local tsize = tab.tabsize or { width = self.width, height = self.height } local ENABLE_TOUCH = core.settings:get_bool("enable_touch")
local orig_tsize = tab.tabsize or { width = self.width, height = self.height }
local tsize = { width = orig_tsize.width, height = orig_tsize.height }
tsize.height = tsize.height
+ TABHEADER_H -- tabheader included in formspec size
+ (ENABLE_TOUCH and GAMEBAR_OFFSET_TOUCH or GAMEBAR_OFFSET_DESKTOP)
+ GAMEBAR_H -- gamebar included in formspec size
if self.parent == nil and not prepend then if self.parent == nil and not prepend then
prepend = string.format("size[%f,%f,%s]", tsize.width, tsize.height, prepend = string.format("size[%f,%f,%s]", tsize.width, tsize.height,
dump(self.fixed_size)) dump(self.fixed_size))
local anchor_pos = TABHEADER_H + orig_tsize.height / 2
prepend = prepend .. ("anchor[0.5,%f]"):format(anchor_pos / tsize.height)
if tab.formspec_version then if tab.formspec_version then
prepend = ("formspec_version[%d]"):format(tab.formspec_version) .. prepend prepend = ("formspec_version[%d]"):format(tab.formspec_version) .. prepend
end end
@ -78,12 +89,15 @@ local function get_formspec(self)
local end_button_size = 0.75 local end_button_size = 0.75
local tab_header_size = { width = tsize.width, height = 0.85 } local tab_header_size = { width = tsize.width, height = TABHEADER_H }
if self.end_button then if self.end_button then
tab_header_size.width = tab_header_size.width - end_button_size - 0.1 tab_header_size.width = tab_header_size.width - end_button_size - 0.1
end end
local formspec = (prepend or "") .. self:tab_header(tab_header_size) .. content local formspec = (prepend or "")
formspec = formspec .. ("bgcolor[;neither]container[0,%f]box[0,0;%f,%f;#0000008C]"):format(
TABHEADER_H, orig_tsize.width, orig_tsize.height)
formspec = formspec .. self:tab_header(tab_header_size) .. content
if self.end_button then if self.end_button then
formspec = formspec .. formspec = formspec ..
@ -98,6 +112,8 @@ local function get_formspec(self)
self.end_button.name) self.end_button.name)
end end
formspec = formspec .. "container_end[]"
return formspec return formspec
end end

View File

@ -221,6 +221,7 @@ core.register_chatcommand("haspriv", {
return true, S("No online player has the \"@1\" privilege.", return true, S("No online player has the \"@1\" privilege.",
param) param)
else else
table.sort(players_with_priv)
return true, S("Players online with the \"@1\" privilege: @2", return true, S("Players online with the \"@1\" privilege: @2",
param, param,
table.concat(players_with_priv, ", ")) table.concat(players_with_priv, ", "))

View File

@ -42,6 +42,7 @@ core.features = {
node_interaction_actor = true, node_interaction_actor = true,
moveresult_new_pos = true, moveresult_new_pos = true,
override_item_remove_fields = true, override_item_remove_fields = true,
hotbar_hud_element = true,
} }
function core.has_feature(arg) function core.has_feature(arg)

View File

@ -251,11 +251,31 @@ register_builtin_hud_element("minimap", {
position = {x = 1, y = 0}, position = {x = 1, y = 0},
alignment = {x = -1, y = 1}, alignment = {x = -1, y = 1},
offset = {x = -10, y = 10}, offset = {x = -10, y = 10},
size = {x = 256, y = 256}, size = {x = 0, y = -25},
}, },
show_elem = function(player, flags) show_elem = function(player, flags)
local proto_ver = core.get_player_information(player:get_player_name()).protocol_version
-- Don't add a minimap for clients which already have it hardcoded in C++. -- Don't add a minimap for clients which already have it hardcoded in C++.
return flags.minimap and return flags.minimap and proto_ver >= 44
core.get_player_information(player:get_player_name()).protocol_version >= 44 end,
update_def = function(player, elem_def)
local proto_ver = core.get_player_information(player:get_player_name()).protocol_version
-- Only use percentage when the client supports it.
elem_def.size = proto_ver >= 45 and {x = 0, y = -25} or {x = 256, y = 256}
end,
})
--- Hotbar
register_builtin_hud_element("hotbar", {
elem_def = {
type = "hotbar",
position = {x = 0.5, y = 1},
direction = 0,
alignment = {x = 0, y = -1},
offset = {x = 0, y = -4}, -- Extra padding below.
},
show_elem = function(player, flags)
return flags.hotbar
end, end,
}) })

View File

@ -6,14 +6,14 @@ local S = core.get_translator("__builtin")
-- Misc. API functions -- Misc. API functions
-- --
-- @spec core.kick_player(String, String) :: Boolean -- @spec core.kick_player(String, String, Boolean) :: Boolean
function core.kick_player(player_name, reason) function core.kick_player(player_name, reason, reconnect)
if type(reason) == "string" then if type(reason) == "string" then
reason = "Kicked: " .. reason reason = "Kicked: " .. reason
else else
reason = "Kicked." reason = "Kicked."
end end
return core.disconnect_player(player_name, reason) return core.disconnect_player(player_name, reason, reconnect)
end end
function core.check_player_privs(name, ...) function core.check_player_privs(name, ...)

View File

@ -42,6 +42,7 @@ local scriptdir = core.get_builtin_path()
local commonpath = scriptdir .. "common" .. DIR_DELIM local commonpath = scriptdir .. "common" .. DIR_DELIM
local asyncpath = scriptdir .. "async" .. DIR_DELIM local asyncpath = scriptdir .. "async" .. DIR_DELIM
dofile(commonpath .. "math.lua")
dofile(commonpath .. "vector.lua") dofile(commonpath .. "vector.lua")
dofile(commonpath .. "strict.lua") dofile(commonpath .. "strict.lua")
dofile(commonpath .. "serialize.lua") dofile(commonpath .. "serialize.lua")

View File

@ -0,0 +1,246 @@
# textdomain: __builtin
Invalid parameters (see /help @1).=Paramètres invalides (voir /help @1).
Too many arguments, try using just /help <command>=Trop de paramètres, essayez /help <command>
Available commands: @1=Commandes disponibles : @1
Use '/help <cmd>' to get more information, or '/help all' to list everything.=Essayez '/help <cmd>' pour obtenir plus d'informations, ou '/help all' pour tout lister.
Available commands:=Commandes disponibles :
Command not available: @1=Commande non disponible : @1
[all | privs | <cmd>] [-t]=[all | privs | <cmd>] [-t]
Get help for commands or list privileges (-t: output in chat)=Obtenir de l'aide pour les commandes ou pour lister les privilèges (-t : affichage dans le tchat)
Available privileges:=Privilèges disponibles :
Command=Commande
Parameters=Paramètres
For more information, click on any entry in the list.=Pour plus d'informations, cliquez sur une entrée dans la liste.
Double-click to copy the entry to the chat history.=Double-cliquez pour copier une entrée dans l'historique du tchat.
Command: @1 @2=Commande : @1 @2
Available commands: (see also: /help <cmd>)=Commandes disponibles : (voir aussi : /help <cmd>)
Close=Fermer
Privilege=Privilège
Description=Description
Empty command.=Commande vide.
Invalid command: @1=Commande invalide : @1
Invalid command usage.=Usage invalide de la commande.
(@1 s)= (@1 s)
Command execution took @1 s=L'exécution de la commande a pris @1 s.
You don't have permission to run this command (missing privileges: @1).=Vous n'avez pas la permission d'exécuter cette commande (privilèges manquants : @1)
Unable to get position of player @1.=Impossible d'obtenir la position du joueur @1.
Incorrect area format. Expected: (x1,y1,z1) (x2,y2,z2)=Format incorrect de la zone. Demandé : (x1, y1, z1) (x2, y2, z2)
<action>=<action>
Show chat action (e.g., '/me orders a pizza' displays '<player name> orders a pizza')=Affiche une action de tchat (ex : '/me commande une pizza' affichage '<joueur> commande une pizza')
Show the name of the server owner=Affiche le nom du propriétaire du serveur
The administrator of this server is @1.=L'administrateur de ce serveur est @1.
There's no administrator named in the config file.=Il n'y a pas d'administrateur indiqué dans le fichier de configuration.
@1 does not have any privileges.=@1 ne possède aucun privilège.
Privileges of @1: @2=Privilège(s) de @1 : @2
[<name>]=[<nom>]
Show privileges of yourself or another player=Affiche vos privilèges ou ceux d'un autre joueur.
Player @1 does not exist.=Le joueur @1 n'existe pas.
<privilege>=<privilège>
Return list of all online players with privilege=Renvoie la liste de tous les joueurs en ligne avec un privilège.
Invalid parameters (see /help haspriv).=Paramètres invalides (voir /help haspriv)
Unknown privilege!=Privilège inconnu !
No online player has the "@1" privilege.=Aucun joueur en ligne avant le privilège « @1 »
Players online with the "@1" privilege: @2=Joueurs en ligne avec le privilège « @1 » : @2
Your privileges are insufficient.=Vos privilèges sont insuffisants.
Your privileges are insufficient. '@1' only allows you to grant: @2=Vos privilèges sont insuffisants. '@1' vous autorise seulement d'accorder : @2
Unknown privilege: @1=Privilège inconnu : @1
@1 granted you privileges: @2=@1 vous a accordé les privilèges : @2
<name> (<privilege> [, <privilege2> [<...>]] | all)=<nom> (<privilège> [, <privilège2> [<...>]] | all)
Give privileges to player=Accorder le privilège au joueur
Invalid parameters (see /help grant).=Paramètres invalides (voir /help grant)
<privilege> [, <privilege2> [<...>]] | all=<privilège> [, <privilège2> [<...>]] | all
Grant privileges to yourself=Accorder des privilèges à vous-même
Invalid parameters (see /help grantme).=Paramètres invalides (voir /help grantme)
Your privileges are insufficient. '@1' only allows you to revoke: @2=Vos privilèges sont insuffisants. '@1' vous autorise seulement à révoquer : @2
Note: Cannot revoke in singleplayer: @1=Note : Impossible de révoquer en solo : @1
Note: Cannot revoke from admin: @1=Note : Impossible de révoquer à l'administrateur : @1
No privileges were revoked.=Aucun privilège n'a été révoqué.
@1 revoked privileges from you: @2=@1 vous a révoqué le privilège : @2
Remove privileges from player=Révoquer les privilèges au joueur
Invalid parameters (see /help revoke).=Paramètres invalides (voir /help revoke).
Revoke privileges from yourself=Révoquer des privilèges à vous-même
Invalid parameters (see /help revokeme).=Paramètres invalides (voir /help revokeme).
<name> <password>=<nom> <mot de passe>
Set player's password (sent unencrypted, thus insecure)=Voir le mot de passe d'un joueur (envoyé non crypté, soit non sécurisé)
Name field required.=Le champ « nom » est requis.
Your password was cleared by @1.=Votre mot de passe a été effacé par @1.
Password of player "@1" cleared.=Mot de passe du joueur « @1 » effacé.
Your password was set by @1.=Votre mot de passe a été défini par @1.
Password of player "@1" set.=Mot de passe « @1 » défini.
<name>=<nom>
Set empty password for a player=Définir un mot de passe pour un joueur
Reload authentication data=Recharger les données d'authentification
Done.=Fait.
Failed.=Échoué.
Remove a player's data=Supprimer les données d'un joueur
Player "@1" removed.=Joueur « @1 » supprimé.
No such player "@1" to remove.=Aucun joueur « @1 » à supprimer.
Player "@1" is connected, cannot remove.=Le joueur « @1 » est connecté, impossible de supprimer.
Unhandled remove_player return code @1.=La commande remove_player non gérée a retourné le code @1.
Cannot teleport out of map bounds!=Impossible de téléporter en dehors des limites de la carte !
Cannot get player with name @1.=Impossible d'obtenir le joueur @1.
Cannot teleport, @1 is attached to an object!=Impossible de téléporter, @1 est lié à un objet !
Teleporting @1 to @2.=Téléportation de @1 vers @2.
One does not teleport to oneself.=Impossible de se téléporter vers soi-même.
Cannot get teleportee with name @1.=Impossible d'obtenir le téléporté @1.
Cannot get target player with name @1.=Impossible d'obtenir le joueur cible @1.
Teleporting @1 to @2 at @3.=Téléportation de @1 vers @2 à @3.
<X>,<Y>,<Z> | <to_name> | <name> <X>,<Y>,<Z> | <name> <to_name>=<X>, <Y>, <Z> | <vers_nom> | <nom> <X>, <Y>, <Z> | <nom> <vers_nom>
Teleport to position or player=Se téléporter vers une position ou un joueur.
You don't have permission to teleport other players (missing privilege: @1).=Vous n'avez pas la permission de téléporter des joueurs (privilège manquant : @1).
([-n] <name> <value>) | <name>=([-n] <nom> <valeur>) | <nom>
Set or read server configuration setting=Définir ou lire un paramètre de configuration du serveur.
Failed. Cannot modify secure settings. Edit the settings file manually.=Échoué. Impossible de modifier les paramètres sécurisés. Éditez le fichier manuellement.
Failed. Use '/set -n <name> <value>' to create a new setting.=Échoué. Utilisez '/set -n <nom> <valeur>' pour créer un nouveau paramètre.
@1 @= @2=@1 @= @2
<not set>=<non défini>
Invalid parameters (see /help set).=Paramètres invalides (voir /help set).
Finished emerging @1 blocks in @2ms.=Fini de générer @1 blocks en @2 ms.
emergeblocks update: @1/@2 blocks emerged (@3%)=Mise à jour de emergeblocks : @1/@2 de blocs générés (@3%)
(here [<radius>]) | (<pos1> <pos2>)=(here [<rayon>]) | (<pos1> <pos1>)
Load (or, if nonexistent, generate) map blocks contained in area pos1 to pos2 (<pos1> and <pos2> must be in parentheses)=Charger (ou, si inexistant, générer), des blocs contenus dans la zone de pos1 à pos2 (<pos1> et <pos2> doivent être entre parenthèses)
Started emerge of area ranging from @1 to @2.=Début de la génération de la zone de @1 à @2.
Delete map blocks contained in area pos1 to pos2 (<pos1> and <pos2> must be in parentheses)=Supprimer les blocs contenus dans la zone de pos1 à pos2 (<pos1> et <pos2> doivent être entre parenthèses)
Successfully cleared area ranging from @1 to @2.=La zone de @1 à @2 a été nettoyée avec succès.
Failed to clear one or more blocks in area.=Le nettoyage d'un ou plusieurs blocs dans la zone a echoué.
Resets lighting in the area between pos1 and pos2 (<pos1> and <pos2> must be in parentheses)=Réinitialiser l'éclairage dans la zone de pos1 à pos2 (<pos1> et <pos2> doivent être entre parenthèses)
Successfully reset light in the area ranging from @1 to @2.=L'éclairage dans la zone de @1 à @2 a été réinitialisé avec succès.
Failed to load one or more blocks in area.=Le chargement d'un ou plusieurs blocs dans la zone a échoué.
List mods installed on the server=Liste les modules installés sur le serveur.
No mods installed.=Aucun module installé.
Cannot give an empty item.=Impossible de donner un objet vide.
Cannot give an unknown item.=Impossible de donner un objet inconnu.
Giving 'ignore' is not allowed.=Donner 'ignore' n'est pas autorisé.
@1 is not a known player.=Le joueur @1 est inconnu.
@1 partially added to inventory.=@1 été partiellement rajouté à l'inventaire.
@1 could not be added to inventory.=@1 n'a pas pu être rajouté à l'inventaire.
@1 added to inventory.=@1 a été rajouté à l'inventaire.
@1 partially added to inventory of @2.=@1 a été partiellement rajouté à l'inventaire de @2.
@1 could not be added to inventory of @2.=@1 n'a pas pu être rajouté à l'inventaire de @2.
@1 added to inventory of @2.=@1 a été rajouté à l'inventaire de @2.
<name> <ItemString> [<count> [<wear>]]=<nom> <CodeObjet> [<nombre> [<usure>]]
Give item to player=Donner un objet à un joueur
Name and ItemString required.=Le nom et le code de l'objet sont requis
<ItemString> [<count> [<wear>]]=<CodeObjet> [<nombre> [<usure>]]
Give item to yourself=Donner un objet à vous-même
ItemString required.=Code objet requis.
<EntityName> [<X>,<Y>,<Z>]=<NomEntité> [<X>, <Y>, <Z>]
Spawn entity at given (or your) position=Faire apparaître une entité à une position donnée (ou la vôtre)
EntityName required.=Nom de l'entité requis.
Unable to spawn entity, player is nil.=Impossible de faire apparaître l'entité, le joueur est inexistant.
Cannot spawn an unknown entity.=Impossible de faire apparaître une entité inconnue.
Invalid parameters (@1).=Paramètres invalides (@1).
@1 spawned.=@1 a apparu.
@1 failed to spawn.=@1 a échoué à apparaître.
Destroy item in hand=Détruire l'objet dans la main
Unable to pulverize, no player.=Impossible de détruire, pas de joueur.
Unable to pulverize, no item in hand.=Impossible de détruire, pas d'objet dans la main.
An item was pulverized.=Un objet a été détruit.
[<range>] [<seconds>] [<limit>]=[<rayon>] [<secondes>] [<limite>]
Check who last touched a node or a node near it within the time specified by <seconds>. Default: range @= 0, seconds @= 86400 @= 24h, limit @= 5. Set <seconds> to inf for no time limit=Vérifier qui a le dernier touché un nœud ou un autre aux environs dans le temps spécifié par <secondes>. Par défaut : rayon @= 0, secondes @= 86400 @= 24h, limite @= 5. Définissez <secondes> à inf pour aucune limite de temps.
Rollback functions are disabled.=Les fonctions retour sont désactivées.
That limit is too high!=Cette limite est trop grande !
Checking @1 ...=Vérification de @1 ...
Nobody has touched the specified location in @1 seconds.=Personne n'as touché la position spécificée dans les dernières @1 secondes.
@1 @2 @3 -> @4 @5 seconds ago.=@1 @2 @3 -> @4 il y a @5 secondes.
Punch a node (range@=@1, seconds@=@2, limit@=@3).=Taper un nœud (rayon @= @1, secondes @= @2, limite @= @3).
(<name> [<seconds>]) | (:<actor> [<seconds>])=(<nom> [<secondes>]) | (:<acteur> [<secondes>])
Revert actions of a player. Default for <seconds> is 60. Set <seconds> to inf for no time limit=Annuler les actions d'un joueur. La valeur par défaut de <secondes> est 60. Définissez <secondes> à inf pour aucune limite de temps.
Invalid parameters. See /help rollback and /help rollback_check.=Paramètres invalides. Voir /help rollback et /help rollback_check.
Reverting actions of player '@1' since @2 seconds.=Annuler les actions du joueur '@1' depuis @2 secondes.
Reverting actions of @1 since @2 seconds.=Annuler les actions de @1 depuis @2 secondes.
(log is too long to show)=(le journal est trop long à afficher)
Reverting actions succeeded.=Les actions ont été annulées avec succès.
Reverting actions FAILED.=L'annulation des actions a échoué.
Show server status=Afficher le statut du serveur.
This command was disabled by a mod or game.=Cette commande a été désactivée par un module ou un jeu.
[<0..23>:<0..59> | <0..24000>]=[<0..23>:<0..59> | <0.24000>]
Show or set time of day=Afficher ou définir l'heure du jour.
Current time is @1:@2.=L'heure actuelle est @1:@2.
You don't have permission to run this command (missing privilege: @1).=Vous n'avez pas la permission d'exécuter cette commande (privilège manquant : @1)
Invalid time (must be between 0 and 24000).=Heure invalide (doit être comprise entre 0 et 24000).
Time of day changed.=L'heure du jour a changé.
Invalid hour (must be between 0 and 23 inclusive).=Heure invalide (doit être comprise entre 0 et 23 inclus).
Invalid minute (must be between 0 and 59 inclusive).=Minute invalide (doit être comprise entre 0 et 59 inclus).
Show day count since world creation=Afficher le nombre de jours écoulés depuis la création du monde.
Current day is @1.=Le jour actuel est @1.
[<delay_in_seconds> | -1] [-r] [<message>]=[<délai_en_secondes> | -1] [-r] [<message>]
Shutdown server (-1 cancels a delayed shutdown, -r allows players to reconnect)=Éteindre le serveur (-1 annule une extinction programmée, -r autorise les joueurs à se reconnecter)
Server shutting down (operator request).=Extinction du serveur (requête de l'opérateur).
Ban the IP of a player or show the ban list=Bannir l'IP d'un joueur ou affiche la liste des bans.
The ban list is empty.=La liste des bans est vide.
Ban list: @1=Liste de bans : @1
You cannot ban players in singleplayer!=Vous ne pouvez pas bannir des joueurs en solo !
Player is not online.=Le joueur n'est pas en ligne.
Failed to ban player.=Le bannissement du joueur a échoué.
Banned @1.=@1 a été banni.
<name> | <IP_address>=<nom> | <adresse_IP>
Remove IP ban belonging to a player/IP=Rétablir un IP appartenant à un joueur ou une adresse IP.
Failed to unban player/IP.=Le rétablissement du joueur ou de l'adresse IP a échoué.
Unbanned @1.=@1 a été rétabli.
<name> [<reason>]=<nom> [<motif>]
Kick a player=Expulser un joueur
Failed to kick player @1.=L'expulsion du joueur @1 a échoué.
Kicked @1.=@1 a été expulsé.
[full | quick]=[full | quick]
Clear all objects in world=Nettoyer tous les objets dans le monde
Invalid usage, see /help clearobjects.=Usage invalide, voir /help clearobjects.
Clearing all objects. This may take a long time. You may experience a timeout. (by @1)=Nettoyage de tous les objects. Cela peut prendre du temps. Une inactivité peut surveni (par @1).
Cleared all objects.=Tous les objets ont été nettoyés.
<name> <message>=<nom> <message>
Send a direct message to a player=Envoyer un message privé à un joueur.
Invalid usage, see /help msg.=Usage invalide, voir /help msg.
The player @1 is not online.=Le joueur @1 n'est pas en ligne.
DM from @1: @2=Message privé de @1 : @2
Message sent.=Message privé envoyé.
Get the last login time of a player or yourself=Obtenir l'horodatage de la dernière connexion d'un joueur ou de vous-même.
@1's last login time was @2.=@1 s'est connecté pour la dernière fois au @2.
@1's last login time is unknown.=L'horodatage de la dernière connexion de @1 est inconnu.
Clear the inventory of yourself or another player=Vider votre inventaire ou celui d'un autre joueur.
You don't have permission to clear another player's inventory (missing privilege: @1).=Vous n'avez pas la permission de vider l'inventaire d'un autre joueur (privilège manquant : @1).
@1 cleared your inventory.=@1 a vidé votre inventaire.
Cleared @1's inventory.=L'inventaire de @1 a été vidé.
Player must be online to clear inventory!=Le joueur doit être en ligne pour pouvoir vider son inventaire.
Players can't be killed, damage has been disabled.=Les joueurs ne peuvent pas être tués, les dommages ont été désactivés.
Player @1 is not online.=Le joueur @1 n'est pas en ligne.
You are already dead.=Vous êtes déjà mort.
@1 is already dead.=@1 est déjà mort.
@1 has been killed.=@1 a été tué.
Kill player or yourself=Tuer un joueur ou vous-même.
@1 joined the game.=@1 a rejoint la partie.
@1 left the game.=@1 a quitté la partie.
@1 left the game (timed out).=@1 a quitté la partie (inactivité).
(no description)=(sans description)
Can interact with things and modify the world=Peut interagir avec des éléments ou modifier le monde.
Can speak in chat=Peut écrire dans le tchat.
Can modify basic privileges (@1)=Peut modifier les privilèges basiques (@1)
Can modify privileges=Peut modifier les privilèges
Can teleport self=Peut se téléporter
Can teleport other players=Peut téléporter d'autres joueurs
Can set the time of day using /time=Peut définir l'heure du jour avec /time
Can do server maintenance stuff=Peut effectuer des tâches de maintenance du serveur
Can bypass node protection in the world=Peut outrepasser la protection des nœuds dans le monde.
Can ban and unban players=Peut bannir et rétablir des joueurs.
Can kick players=Peut expulser des joueurs.
Can use /give and /giveme=Peut utiliser /give et /giveme
Can use /setpassword and /clearpassword=Peut utiliser /setpassword et /clearpassword
Can use fly mode=Peut utiliser le mode vol
Can use fast mode=Peut utiliser le mode rapide
Can fly through solid nodes using noclip mode=Peut voler à travers des nœuds solides en utilisant le mode de collisions désactivées.
Can use the rollback functionality=Peut utiliser la fonctionnalité de retour
Can enable wireframe=Peut activer la vue fil de fer
Unknown Item=Objet inconnu
Air=Air
Ignore=Ignorer
You can't place 'ignore' nodes!=Vous ne pouvez pas placé de nœuds 'ignorés' !
print [<filter>] | dump [<filter>] | save [<format> [<filter>]] | reset=print [<filtre>] | dump [<filtre>] | save [<format> [<filtre>]] | reset
Handle the profiler and profiling data=Traiter le profileur et les données de profilage
Statistics written to action log.=Les statistiques sont écrites dans les journaux d'actions.
Statistics were reset.=Les statistiques ont été réinitialisées.
Usage: @1=Usage : @1
Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).=Le format peut être txt, csv, lua, json ou json_pretty (les structures sont sujettes au changement).
Values below show absolute/relative times spend per server step by the instrumented function.=Les valeurs inférieures affichent les temps absolu et relatif dépensés par étape du serveur par la fonction utilisée.
A total of @1 sample(s) were taken.=@1 échantillons ont été collectés.
The output is limited to '@1'.=La sortie est limitée à '@1'.
Saving of profile failed: @1=La sauvegarde du profil a échoué : @1
Profile saved to @1=Le profil a été sauvegardé dans @1

View File

@ -0,0 +1,246 @@
# textdomain: __builtin
Invalid parameters (see /help @1).=Parâmetros inválidos (veja /help @1).
Too many arguments, try using just /help <command>=Muitos argumentos, tente usar apenas /help <comando>
Available commands: @1=Comandos disponíveis: @1
Use '/help <cmd>' to get more information, or '/help all' to list everything.=Use '/help <cmd>' para obter mais informações, ou '/help all' para listar tudo.
Available commands:=Comandos disponíveis:
Command not available: @1=Comando não disponível: @1
[all | privs | <cmd>] [-t]=[all | privs | <cmd>] [-t]
Get help for commands or list privileges (-t: output in chat)=Obtenha ajuda para comandos ou liste privilégios (-t: saída no chat)
Available privileges:=Privilégios disponíveis:
Command=Comando
Parameters=Parâmetros
For more information, click on any entry in the list.=Para mais informações, clique em qualquer entrada na lista.
Double-click to copy the entry to the chat history.=Clique duas vezes para copiar a entrada para o histórico do chat.
Command: @1 @2=Comando: @1 @2
Available commands: (see also: /help <cmd>)=Comandos disponíveis: (veja também: /help <cmd>)
Close=Fechar
Privilege=Privilégio
Description=Descrição
Empty command.=Comando vazio.
Invalid command: @1=Comando inválido: @1
Invalid command usage.=Uso de comando inválido.
(@1 s)= (@1 s)
Command execution took @1 s=A execução do comando levou @1 s
You don't have permission to run this command (missing privileges: @1).=Você não tem permissão para executar este comando (privilégios faltando: @1).
Unable to get position of player @1.=Incapaz de obter a posição do jogador @1.
Incorrect area format. Expected: (x1,y1,z1) (x2,y2,z2)=Formato de área incorreto. Esperado: (x1,y1,z1) (x2,y2,z2)
<action>=<ação>
Show chat action (e.g., '/me orders a pizza' displays '<player name> orders a pizza')=Mostra a ação do chat (por exemplo, '/me orders a pizza' exibe '<nome do jogador> pede uma pizza')
Show the name of the server owner=Mostra o nome do dono do servidor
The administrator of this server is @1.=O administrador deste servidor é @1.
There's no administrator named in the config file.=Não há administrador nomeado no arquivo de configuração.
@1 does not have any privileges.=@1 não tem nenhum privilégio.
Privileges of @1: @2=Privilégios de @1: @2
[<name>]=[<nome>]
Show privileges of yourself or another player=Mostrar privilégios seus ou de outro jogador
Player @1 does not exist.=O jogador @1 não existe.
<privilege>=<privilégio>
Return list of all online players with privilege=Retornar lista de todos os jogadores online com privilégio
Invalid parameters (see /help haspriv).=Parâmetros inválidos (veja /help haspriv).
Unknown privilege!=Privilégio desconhecido!
No online player has the "@1" privilege.=Nenhum jogador online tem o privilégio "@1".
Players online with the "@1" privilege: @2=Jogadores online com o privilégio "@1": @2
Your privileges are insufficient.=Seus privilégios são insuficientes.
Your privileges are insufficient. '@1' only allows you to grant: @2=Seus privilégios são insuficientes. '@1' só permite que você conceda: @2
Unknown privilege: @1=Privilégio desconhecido: @1
@1 granted you privileges: @2=@1 concedeu-lhe privilégios: @2
<name> (<privilege> [, <privilege2> [<...>]] | all)=<nome> (<privilégio> [, <privilégio2> [<...>]] | all)
Give privileges to player=Conceder privilégios ao jogador
Invalid parameters (see /help grant).=Parâmetros inválidos (veja /help grant).
<privilege> [, <privilege2> [<...>]] | all=<privilégio> [, <privilégio2> [<...>]] | all
Grant privileges to yourself=Concede privilégios a você mesmo
Invalid parameters (see /help grantme).=Parâmetros inválidos (veja /help grantme).
Your privileges are insufficient. '@1' only allows you to revoke: @2=Seus privilégios são insuficientes. '@1' só permite que você revogue: @2
Note: Cannot revoke in singleplayer: @1=Nota: Não é possível revogar em singleplayer: @1
Note: Cannot revoke from admin: @1=Nota: Não é possível revogar do administrador: @1
No privileges were revoked.=Nenhum privilégio foi revogado.
@1 revoked privileges from you: @2=@1 revogou seus privilégios: @2
Remove privileges from player=Remover privilégios do jogador
Invalid parameters (see /help revoke).=Parâmetros inválidos (veja /help revoke).
Revoke privileges from yourself=Revogar privilégios de si mesmo
Invalid parameters (see /help revokeme).=Parâmetros inválidos (veja /help revokeme).
<name> <password>=<nome> <senha>
Set player's password (sent unencrypted, thus insecure)=Definir a senha do jogador (enviada sem criptografia, portanto insegura)
Name field required.=Campo de nome obrigatório.
Your password was cleared by @1.=Sua senha foi limpa por @1.
Password of player "@1" cleared.=Senha do jogador "@1" limpa.
Your password was set by @1.=Sua senha foi definida por @1.
Password of player "@1" set.=Senha do jogador "@1" definida.
<name>=<nome>
Set empty password for a player=Definir senha vazia para um jogador
Reload authentication data=Recarregar dados de autenticação
Done.=Pronto.
Failed.=Erro.
Remove a player's data=Remover dados de um jogador
Player "@1" removed.=Jogador "@1" removido.
No such player "@1" to remove.=Não existe tal jogador "@1" para remover.
Player "@1" is connected, cannot remove.=Jogador "@1" está conectado, não pode ser removido.
Unhandled remove_player return code @1.=Código de retorno remove_player não tratado @1.
Cannot teleport out of map bounds!=Não é possível teleportar para fora dos limites do mapa!
Cannot get player with name @1.=Não é possível obter jogador com o nome @1.
Cannot teleport, @1 is attached to an object!=Não é possível teleportar, @1 está anexado a um objeto!
Teleporting @1 to @2.=Teleportando @1 para @2.
One does not teleport to oneself.=Não tem como se teletransportar para você mesmo.
Cannot get teleportee with name @1.=Não é possível teletransportar com o nome @1.
Cannot get target player with name @1.=Não é possível obter jogador alvo com o nome @1.
Teleporting @1 to @2 at @3.=Teleportando @1 para @2 em @3.
<X>,<Y>,<Z> | <to_name> | <name> <X>,<Y>,<Z> | <name> <to_name>=<X>,<Y>,<Z> | <para_nome> | <nome> <X>,<Y>,<Z> | <nome> <para_nome>
Teleport to position or player=Teleportar para posição ou um jogador
You don't have permission to teleport other players (missing privilege: @1).=Você não tem permissão para teleportar outros jogadores (privilégio faltando: @1).
([-n] <name> <value>) | <name>=([-n] <nome> <valor>) | <nome>
Set or read server configuration setting=Definir ou ler configuração do servidor
Failed. Cannot modify secure settings. Edit the settings file manually.=Falha. Não é possível modificar configurações seguras. Edite o arquivo de configurações manualmente.
Failed. Use '/set -n <name> <value>' to create a new setting.=Falhou. Use '/set -n <nome> <valor>' para criar uma nova configuração.
@1 @= @2=@1 @= @2
<not set>=<não definido>
Invalid parameters (see /help set).=Parâmetros inválidos (veja /help set).
Finished emerging @1 blocks in @2ms.=Finalizada a emergência de @1 blocos em @2ms.
emergeblocks update: @1/@2 blocks emerged (@3%)=atualização de emergeblocks: @1/@2 blocos emergidos (@3%)
(here [<radius>]) | (<pos1> <pos2>)=(aqui [<raio>]) | (<pos1> <pos2>)
Load (or, if nonexistent, generate) map blocks contained in area pos1 to pos2 (<pos1> and <pos2> must be in parentheses)=Carregar (ou, se inexistente, gerar) blocos de mapa contidos na área pos1 a pos2 (<pos1> e <pos2> devem estar entre parênteses)
Started emerge of area ranging from @1 to @2.=Iniciada o surgimento de áreas que vão de @1 a @2.
Delete map blocks contained in area pos1 to pos2 (<pos1> and <pos2> must be in parentheses)=Excluir blocos de mapa contidos na área pos1 a pos2 (<pos1> e <pos2> devem estar entre parênteses)
Successfully cleared area ranging from @1 to @2.=Área limpa com sucesso variando de @1 a @2.
Failed to clear one or more blocks in area.=Falha ao limpar um ou mais blocos na área.
Resets lighting in the area between pos1 and pos2 (<pos1> and <pos2> must be in parentheses)=Redefine a iluminação na área entre pos1 e pos2 (<pos1> e <pos2> devem estar entre parênteses)
Successfully reset light in the area ranging from @1 to @2.=Iluminação redefinida com sucesso na área variando de @1 a @2.
Failed to load one or more blocks in area.=Falha ao carregar um ou mais blocos na área.
List mods installed on the server=Listar mods instalados no servidor
No mods installed.=Sem mods instalados.
Cannot give an empty item.=Não é possível dar um item vazio.
Cannot give an unknown item.=Não é possível dar um item desconhecido.
Giving 'ignore' is not allowed.=Não é permitido dar 'ignore'.
@1 is not a known player.=@1 não é um jogador conhecido.
@1 partially added to inventory.=@1 parcialmente adicionado ao inventário.
@1 could not be added to inventory.=@1 não pôde ser adicionado ao inventário.
@1 added to inventory.=@1 adicionado ao inventário.
@1 partially added to inventory of @2.=@1 parcialmente adicionado ao inventário de @2.
@1 could not be added to inventory of @2.=@1 não pôde ser adicionado ao inventário de @2.
@1 added to inventory of @2.=@1 adicionado ao inventário de @2.
<name> <ItemString> [<count> [<wear>]]=<nome> <ItemString> [<quantidade> [<desgaste>]]
Give item to player=Dar item ao jogador
Name and ItemString required.=Nome e ItemString são obrigatórios.
<ItemString> [<count> [<wear>]]=<ItemString> [<quantidade> [<desgaste>]]
Give item to yourself=Dar item a si mesmo
ItemString required.=ItemString é obrigatório.
<EntityName> [<X>,<Y>,<Z>]=<NomeDaEntidade> [<X>,<Y>,<Z>]
Spawn entity at given (or your) position=Gerar entidade na posição fornecida (ou na sua)
EntityName required.=NomeDaEntidade é obrigatório.
Unable to spawn entity, player is nil.=Não é possível gerar a entidade, jogador é nulo.
Cannot spawn an unknown entity.=Não é possível gerar uma entidade desconhecida.
Invalid parameters (@1).=Parâmetros inválidos (@1).
@1 spawned.=@1 gerado.
@1 failed to spawn.=Falha ao gerar @1.
Destroy item in hand=Destruir item na mão
Unable to pulverize, no player.=Incapaz de pulverizar, sem jogador.
Unable to pulverize, no item in hand.=Incapaz de pulverizar, sem item na mão.
An item was pulverized.=Um item foi pulverizado.
[<range>] [<seconds>] [<limit>]=[<alcance>] [<segundos>] [<limite>]
Check who last touched a node or a node near it within the time specified by <seconds>. Default: range @= 0, seconds @= 86400 @= 24h, limit @= 5. Set <seconds> to inf for no time limit=Verificar quem tocou pela última vez um nó ou um nó próximo dentro do tempo especificado por <segundos>. Padrão: alcance @= 0, segundos @= 86400 @= 24h, limite @= 5. Defina <segundos> como inf para sem limite de tempo
Rollback functions are disabled.=Funções de rollback estão desativadas.
That limit is too high!=Esse limite é muito alto!
Checking @1 ...=Verificando @1 ...
Nobody has touched the specified location in @1 seconds.=Ninguém tocou a localização especificada em @1 segundos.
@1 @2 @3 -> @4 @5 seconds ago.=@1 @2 @3 -> @4 @5 segundos atrás.
Punch a node (range@=@1, seconds@=@2, limit@=@3).=Golpeie um nó (alcance@=@1, segundos@=@2, limite@=@3).
(<name> [<seconds>]) | (:<actor> [<seconds>])=(<nome> [<segundos>]) | (:<ator> [<segundos>])
Revert actions of a player. Default for <seconds> is 60. Set <seconds> to inf for no time limit=Reverter ações de um jogador. O padrão para <segundos> é 60. Defina <segundos> como inf para sem limite de tempo
Invalid parameters. See /help rollback and /help rollback_check.=Parâmetros inválidos. Veja /help rollback e /help rollback_check.
Reverting actions of player '@1' since @2 seconds.=Revertendo ações do jogador '@1' desde @2 segundos.
Reverting actions of @1 since @2 seconds.=Revertendo ações de @1 desde @2 segundos.
(log is too long to show)=O log é muito longo para mostrar
Reverting actions succeeded.=Ações revertidas com sucesso.
Reverting actions FAILED.=Reversão de ações FALHOU.
Show server status=Mostrar status do servidor
This command was disabled by a mod or game.=Este comando foi desativado por um mod ou jogo.
[<0..23>:<0..59> | <0..24000>]=[<0..23>:<0..59> | <0..24000>]
Show or set time of day=Mostrar ou definir hora do dia
Current time is @1:@2.=A hora atual é @1:@2.
You don't have permission to run this command (missing privilege: @1).=Você não tem permissão para executar este comando (privilégio faltando: @1).
Invalid time (must be between 0 and 24000).=Hora inválida (deve estar entre 0 e 24000).
Time of day changed.=Hora do dia alterada.
Invalid hour (must be between 0 and 23 inclusive).=Hora inválida (deve estar entre 0 e 23 inclusivo).
Invalid minute (must be between 0 and 59 inclusive).=Minuto inválido (deve estar entre 0 e 59 inclusivo).
Show day count since world creation=Mostrar contagem de dias desde a criação do mundo
Current day is @1.=O dia atual é @1.
[<delay_in_seconds> | -1] [-r] [<message>]=[<atraso_em_segundos> | -1] [-r] [<mensagem>]
Shutdown server (-1 cancels a delayed shutdown, -r allows players to reconnect)=Desligar servidor (-1 cancela o desligamento adiado, -r permite que os jogadores se reconectem)
Server shutting down (operator request).=Servidor desligando (solicitação do operador).
Ban the IP of a player or show the ban list=Banir o IP de um jogador ou mostrar a lista de banimentos
The ban list is empty.=A lista de banimentos está vazia.
Ban list: @1=Lista de banimentos: @1
You cannot ban players in singleplayer!=Você não pode banir jogadores em singleplayer!
Player is not online.=Jogador não está online.
Failed to ban player.=Falha ao banir jogador.
Banned @1.=Banido @1.
<name> | <IP_address>=<nome> | <endereço_IP>
Remove IP ban belonging to a player/IP=Remover banimento de IP pertencente a um jogador/IP
Failed to unban player/IP.=Falha ao desbanir jogador/IP.
Unbanned @1.=Desbanido @1.
<name> [<reason>]=<nome> [<motivo>]
Kick a player=Expulsar um jogador
Failed to kick player @1.=Falha ao expulsar jogador @1.
Kicked @1.=Expulso @1.
[full | quick]=[full | quick]
Clear all objects in world=Limpar todos os objetos no mundo
Invalid usage, see /help clearobjects.=Uso inválido, veja /help clearobjects.
Clearing all objects. This may take a long time. You may experience a timeout. (by @1)=Limpeza de todos os objetos. Isso pode levar muito tempo. Você pode experimentar um tempo limite. (por @1)
Cleared all objects.=Todos os objetos foram limpos.
<name> <message>=<nome> <mensagem>
Send a direct message to a player=Enviar uma mensagem direta a um jogador
Invalid usage, see /help msg.=Uso inválido, veja /help msg.
The player @1 is not online.=O jogador @1 não está online.
DM from @1: @2=DM de @1: @2
Message sent.=Mensagem enviada.
Get the last login time of a player or yourself=Pegue o último horário de login de um jogador ou de você mesmo
@1's last login time was @2.=O último login de @1 foi às @2.
@1's last login time is unknown.=O último login de @1 é desconhecido.
Clear the inventory of yourself or another player=Limpar o inventário de você mesmo ou de outro jogador
You don't have permission to clear another player's inventory (missing privilege: @1).=Você não tem permissão para limpar o inventário de outro jogador (privilégio faltando: @1).
@1 cleared your inventory.=@1 limpou seu inventário.
Cleared @1's inventory.=Inventário de @1 limpo.
Player must be online to clear inventory!=O jogador deve estar online para limpar o inventário!
Players can't be killed, damage has been disabled.=Jogadores não podem ser mortos, o dano foi desativado.
Player @1 is not online.=Jogador @1 não está online.
You are already dead.=Você já está morto.
@1 is already dead.=@1 já está morto.
@1 has been killed.=@1 foi morto.
Kill player or yourself=Matar jogador ou a si mesmo
@1 joined the game.=@1 entrou no jogo.
@1 left the game.=@1 saiu do jogo.
@1 left the game (timed out).=@1 saiu do jogo (tempo esgotado)
(no description)=(sem descrição)
Can interact with things and modify the world=Pode interagir com as coisas e modificar o mundo
Can speak in chat=Pode falar no chat
Can modify basic privileges (@1)=Pode modificar privilégios básicos (@1)
Can modify privileges=Pode modificar privilégios
Can teleport self=Pode se teletransportar
Can teleport other players=Pode teletransportar outros jogadores
Can set the time of day using /time=Pode definir a hora do dia usando /time
Can do server maintenance stuff=Pode realizar tarefas de manutenção do servidor
Can bypass node protection in the world=Pode ignorar a proteção de nós no mundo
Can ban and unban players=Pode banir e desbanir jogadores
Can kick players=Pode chutar jogadores
Can use /give and /giveme=Pode usar /give e /giveme
Can use /setpassword and /clearpassword=Pode usar /setpassword e /clearpassword
Can use fly mode=Pode usar o modo voar
Can use fast mode=Pode usar o modo rápido
Can fly through solid nodes using noclip mode=Pode voar através de nós sólidos usando o modo noclip
Can use the rollback functionality=Pode usar a funcionalidade de reversão
Can enable wireframe=Pode ativar wireframe
Unknown Item=Item desconhecido
Air=Ar
Ignore=Ignorar
You can't place 'ignore' nodes!=Você não pode colocar nós 'ignorar'!
print [<filter>] | dump [<filter>] | save [<format> [<filter>]] | reset=print [<filtro>] | dump [<filtro>] | save [<formato> [<filtro>]] | reset
Handle the profiler and profiling data=Lidar com o criador de perfil e os dados de criação de perfil
Statistics written to action log.=Estatísticas salvas no log de ações.
Statistics were reset.=As estatísticas foram redefinidas.
Usage: @1=Uso: @1
Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).=O formato pode ser txt, csv, lua, json, json_pretty (as estruturas podem estar sujeitas a alterações).
Values below show absolute/relative times spend per server step by the instrumented function.=Os valores abaixo mostram os tempos absolutos/relativos gastos por etapa do servidor pela função instrumentada.
A total of @1 sample(s) were taken.=Um total de @1 amostra(s) foi coletada.
The output is limited to '@1'.=A saída é limitada a '@1'.
Saving of profile failed: @1=Falha ao salvar o perfil: @1
Profile saved to @1=Perfil salvo em @1

View File

@ -181,7 +181,7 @@ local function get_info_formspec(text)
return table.concat({ return table.concat({
"formspec_version[6]", "formspec_version[6]",
"size[15.75,9.5]", "size[15.75,9.5]",
core.settings:get_bool("enable_touch") and "padding[0.01,0.01]" or "position[0.5,0.55]", core.settings:get_bool("touch_gui") and "padding[0.01,0.01]" or "position[0.5,0.55]",
"label[4,4.35;", text, "]", "label[4,4.35;", text, "]",
"container[0,", H - 0.8 - 0.375, "]", "container[0,", H - 0.8 - 0.375, "]",
@ -212,7 +212,7 @@ local function get_formspec(dlgdata)
local formspec = { local formspec = {
"formspec_version[6]", "formspec_version[6]",
"size[15.75,9.5]", "size[15.75,9.5]",
core.settings:get_bool("enable_touch") and "padding[0.01,0.01]" or "position[0.5,0.55]", core.settings:get_bool("touch_gui") and "padding[0.01,0.01]" or "position[0.5,0.55]",
"style[status,downloading,queued;border=false]", "style[status,downloading,queued;border=false]",
@ -463,7 +463,7 @@ end
local function handle_events(event) local function handle_events(event)
if event == "DialogShow" then if event == "DialogShow" then
-- On touchscreen, don't show the "MINETEST" header behind the dialog. -- On touchscreen, don't show the "MINETEST" header behind the dialog.
mm_game_theme.set_engine(core.settings:get_bool("enable_touch")) mm_game_theme.set_engine(core.settings:get_bool("touch_gui"))
-- If ContentDB is already loaded, auto-install packages here. -- If ContentDB is already loaded, auto-install packages here.
do_auto_install() do_auto_install()

View File

@ -22,13 +22,13 @@ end
local function get_loading_formspec() local function get_loading_formspec()
local ENABLE_TOUCH = core.settings:get_bool("enable_touch") local TOUCH_GUI = core.settings:get_bool("touch_gui")
local w = ENABLE_TOUCH and 14 or 7 local w = TOUCH_GUI and 14 or 7
local formspec = { local formspec = {
"formspec_version[3]", "formspec_version[3]",
"size[", w, ",9.05]", "size[", w, ",9.05]",
ENABLE_TOUCH and "padding[0.01,0.01]" or "position[0.5,0.55]", TOUCH_GUI and "padding[0.01,0.01]" or "position[0.5,0.55]",
"label[3,4.525;", fgettext("Loading..."), "]", "label[3,4.525;", fgettext("Loading..."), "]",
} }
return table.concat(formspec) return table.concat(formspec)
@ -110,18 +110,18 @@ local function get_formspec(data)
message_bg = mt_color_orange message_bg = mt_color_orange
end end
local ENABLE_TOUCH = core.settings:get_bool("enable_touch") local TOUCH_GUI = core.settings:get_bool("touch_gui")
local w = ENABLE_TOUCH and 14 or 7 local w = TOUCH_GUI and 14 or 7
local padded_w = w - 2*0.375 local padded_w = w - 2*0.375
local dropdown_w = ENABLE_TOUCH and 10.2 or 4.25 local dropdown_w = TOUCH_GUI and 10.2 or 4.25
local button_w = (padded_w - 0.25) / 3 local button_w = (padded_w - 0.25) / 3
local button_pad = button_w / 2 local button_pad = button_w / 2
local formspec = { local formspec = {
"formspec_version[3]", "formspec_version[3]",
"size[", w, ",9.05]", "size[", w, ",9.05]",
ENABLE_TOUCH and "padding[0.01,0.01]" or "position[0.5,0.55]", TOUCH_GUI and "padding[0.01,0.01]" or "position[0.5,0.55]",
"style[title;border=false]", "style[title;border=false]",
"box[0,0;", w, ",0.8;#3333]", "box[0,0;", w, ",0.8;#3333]",
"button[0,0;", w, ",0.8;title;", fgettext("Install $1", package.title) , "]", "button[0,0;", w, ",0.8;title;", fgettext("Install $1", package.title) , "]",

View File

@ -0,0 +1,85 @@
{
"#": "https://github.com/orgs/minetest/teams/engine/members",
"core_developers": [
"Perttu Ahola (celeron55) <celeron55@gmail.com> [Project founder]",
"sfan5 <sfan5@live.de>",
"ShadowNinja <shadowninja@minetest.net>",
"Nathanaëlle Courant (Nore/Ekdohibs) <nore@mesecons.net>",
"Loic Blot (nerzhul/nrz) <loic.blot@unix-experience.fr>",
"Andrew Ward (rubenwardy) <rw@rubenwardy.com>",
"Krock/SmallJoker <mk939@ymail.com>",
"Lars Hofhansl <larsh@apache.org>",
"v-rob <robinsonvincent89@gmail.com>",
"Desour/DS",
"srifqi",
"Gregor Parzefall (grorp)",
"Lars Müller (luatic)"
],
"previous_core_developers": [
"BlockMen",
"Maciej Kasatkin (RealBadAngel) [RIP]",
"Lisa Milne (darkrose) <lisa@ltmnet.com>",
"proller",
"Ilya Zhuravlev (xyz) <xyz@minetest.net>",
"PilzAdam <pilzadam@minetest.net>",
"est31 <MTest31@outlook.com>",
"kahrl <kahrl@gmx.net>",
"Ryan Kwolek (kwolekr) <kwolekr@minetest.net>",
"sapier",
"Zeno",
"Auke Kok (sofar) <sofar@foo-projects.org>",
"Aaron Suen <warr1024@gmail.com>",
"paramat",
"Pierre-Yves Rollo <dev@pyrollo.com>",
"hecks",
"Jude Melton-Houghton (TurkeyMcMac) [RIP]",
"Hugues Ross <hugues.ross@gmail.com>",
"Dmitry Kostenko (x2048) <codeforsmile@gmail.com>"
],
"#": "Currently only https://github.com/orgs/minetest/teams/triagers/members",
"core_team": [
"Zughy [Issue triager]",
"wsor [Issue triager]",
"Hugo Locurcio (Calinou) [Issue triager]"
],
"#": "For updating active/previous contributors, see the script in ./util/gather_git_credits.py",
"contributors": [
"cx384",
"numzero",
"AFCMS",
"sfence",
"Wuzzy",
"ROllerozxa",
"JosiahWI",
"OgelGames",
"David Heidelberg",
"1F616EMO",
"HybridDog",
"Bradley Pierce (Thresher)",
"savilli",
"Stvk imension",
"y5nw",
"chmodsayshello",
"jordan4ibanez",
"superfloh247"
],
"previous_contributors": [
"Nils Dagsson Moskopp (erlehmann) <nils@dieweltistgarnichtso.net> [Minetest logo]",
"red-001 <red-001@outlook.ie>",
"Giuseppe Bilotta",
"HybridDog",
"ClobberXD",
"Dániel Juhász (juhdanad) <juhdanad@gmail.com>",
"MirceaKitsune <mirceakitsune@gmail.com>",
"Jean-Patrick Guerrero (kilbith)",
"MoNTE48",
"Constantin Wenger (SpeedProg)",
"Ciaran Gultnieks (CiaranG)",
"Paul Ouellette (pauloue)",
"stujones11",
"Rogier <rogier777@gmail.com>",
"Gregory Currie (gregorycu)",
"JacobF",
"Jeija <jeija@mesecons.net>"
]
}

View File

@ -126,7 +126,7 @@ local function get_formspec(data)
local retval = local retval =
"size[11.5,7.5,true]" .. "size[11.5,7.5,true]" ..
"label[0.5,0;" .. fgettext("World:") .. "]" .. "label[0.5,0;" .. fgettext("World:") .. "]" ..
"label[1.75,0;" .. data.worldspec.name .. "]" "label[1.75,0;" .. core.formspec_escape(data.worldspec.name) .. "]"
if mod.is_modpack or mod.type == "game" then if mod.is_modpack or mod.type == "game" then
local info = core.formspec_escape( local info = core.formspec_escape(

View File

@ -23,6 +23,13 @@ mt_color_dark_green = "#25C191"
mt_color_orange = "#FF8800" mt_color_orange = "#FF8800"
mt_color_red = "#FF3300" mt_color_red = "#FF3300"
MAIN_TAB_W = 15.5
MAIN_TAB_H = 7.1
TABHEADER_H = 0.85
GAMEBAR_H = 1.25
GAMEBAR_OFFSET_DESKTOP = 0.375
GAMEBAR_OFFSET_TOUCH = 0.15
local menupath = core.get_mainmenu_path() local menupath = core.get_mainmenu_path()
local basepath = core.get_builtin_path() local basepath = core.get_builtin_path()
defaulttexturedir = core.get_texturepath_share() .. DIR_DELIM .. "base" .. defaulttexturedir = core.get_texturepath_share() .. DIR_DELIM .. "base" ..
@ -89,7 +96,7 @@ local function init_globals()
mm_game_theme.set_engine() -- This is just a fallback. mm_game_theme.set_engine() -- This is just a fallback.
-- Create main tabview -- Create main tabview
local tv_main = tabview_create("maintab", {x = 15.5, y = 7.1}, {x = 0, y = 0}) local tv_main = tabview_create("maintab", {x = MAIN_TAB_W, y = MAIN_TAB_H}, {x = 0, y = 0})
tv_main:set_autosave_tab(true) tv_main:set_autosave_tab(true)
tv_main:add(tabs.local_game) tv_main:add(tabs.local_game)

View File

@ -306,17 +306,36 @@ function make.flags(setting)
"label[0,0.1;" .. get_label(setting) .. "]", "label[0,0.1;" .. get_label(setting) .. "]",
} }
local value = core.settings:get(setting.name) or setting.default
self.resettable = core.settings:has(setting.name) self.resettable = core.settings:has(setting.name)
checkboxes = {} checkboxes = {}
for _, name in ipairs(value:split(",")) do for _, name in ipairs(setting.possible) do
name = name:trim() checkboxes[name] = false
if name:sub(1, 2) == "no" then end
checkboxes[name:sub(3)] = false local function apply_flags(flag_string, what)
elseif name ~= "" then local prefixed_flags = {}
checkboxes[name] = true for _, name in ipairs(flag_string:split(",")) do
prefixed_flags[name:trim()] = true
end end
for _, name in ipairs(setting.possible) do
local enabled = prefixed_flags[name]
local disabled = prefixed_flags["no" .. name]
if enabled and disabled then
core.log("warning", "Flag " .. name .. " in " .. what .. " " ..
setting.name .. " both enabled and disabled, ignoring")
elseif enabled then
checkboxes[name] = true
elseif disabled then
checkboxes[name] = false
end
end
end
-- First apply the default, which is necessary since flags
-- which are not overridden may be missing from the value.
apply_flags(setting.default, "default for setting")
local value = core.settings:get(setting.name)
if value then
apply_flags(value, "setting")
end end
local columns = math.max(math.floor(avail_w / 2.5), 1) local columns = math.max(math.floor(avail_w / 2.5), 1)
@ -325,18 +344,16 @@ function make.flags(setting)
local y = 0.55 local y = 0.55
for _, possible in ipairs(setting.possible) do for _, possible in ipairs(setting.possible) do
if possible:sub(1, 2) ~= "no" then if x >= avail_w then
if x >= avail_w then x = 0
x = 0 y = y + 0.5
y = y + 0.5
end
local is_checked = checkboxes[possible]
fs[#fs + 1] = ("checkbox[%f,%f;%s;%s;%s]"):format(
x, y, setting.name .. "_" .. possible,
core.formspec_escape(possible), tostring(is_checked))
x = x + column_width
end end
local is_checked = checkboxes[possible]
fs[#fs + 1] = ("checkbox[%f,%f;%s;%s;%s]"):format(
x, y, setting.name .. "_" .. possible,
core.formspec_escape(possible), tostring(is_checked))
x = x + column_width
end end
return table.concat(fs, ""), y + 0.25 return table.concat(fs, ""), y + 0.25
@ -355,12 +372,10 @@ function make.flags(setting)
if changed then if changed then
local values = {} local values = {}
for _, name in ipairs(setting.possible) do for _, name in ipairs(setting.possible) do
if name:sub(1, 2) ~= "no" then if checkboxes[name] then
if checkboxes[name] then table.insert(values, name)
table.insert(values, name) else
else table.insert(values, "no" .. name)
table.insert(values, "no" .. name)
end
end end
end end

View File

@ -110,7 +110,7 @@ local function load()
local change_keys = { local change_keys = {
query_text = "Controls", query_text = "Controls",
requires = { requires = {
keyboard_mouse = true, touch_controls = false,
}, },
get_formspec = function(self, avail_w) get_formspec = function(self, avail_w)
local btn_w = math.min(avail_w, 3) local btn_w = math.min(avail_w, 3)
@ -324,8 +324,6 @@ local function check_requirements(name, requires)
local special = { local special = {
android = PLATFORM == "Android", android = PLATFORM == "Android",
desktop = PLATFORM ~= "Android", desktop = PLATFORM ~= "Android",
touchscreen_gui = core.settings:get_bool("enable_touch"),
keyboard_mouse = not core.settings:get_bool("enable_touch"),
shaders_support = shaders_support, shaders_support = shaders_support,
shaders = core.settings:get_bool("enable_shaders") and shaders_support, shaders = core.settings:get_bool("enable_shaders") and shaders_support,
opengl = video_driver == "opengl", opengl = video_driver == "opengl",
@ -457,13 +455,13 @@ local function get_formspec(dialogdata)
local extra_h = 1 -- not included in tabsize.height local extra_h = 1 -- not included in tabsize.height
local tabsize = { local tabsize = {
width = core.settings:get_bool("enable_touch") and 16.5 or 15.5, width = core.settings:get_bool("touch_gui") and 16.5 or 15.5,
height = core.settings:get_bool("enable_touch") and (10 - extra_h) or 12, height = core.settings:get_bool("touch_gui") and (10 - extra_h) or 12,
} }
local scrollbar_w = core.settings:get_bool("enable_touch") and 0.6 or 0.4 local scrollbar_w = core.settings:get_bool("touch_gui") and 0.6 or 0.4
local left_pane_width = core.settings:get_bool("enable_touch") and 4.5 or 4.25 local left_pane_width = core.settings:get_bool("touch_gui") and 4.5 or 4.25
local left_pane_padding = 0.25 local left_pane_padding = 0.25
local search_width = left_pane_width + scrollbar_w - (0.75 * 2) local search_width = left_pane_width + scrollbar_w - (0.75 * 2)
@ -477,7 +475,7 @@ local function get_formspec(dialogdata)
local fs = { local fs = {
"formspec_version[6]", "formspec_version[6]",
"size[", tostring(tabsize.width), ",", tostring(tabsize.height + extra_h), "]", "size[", tostring(tabsize.width), ",", tostring(tabsize.height + extra_h), "]",
core.settings:get_bool("enable_touch") and "padding[0.01,0.01]" or "", core.settings:get_bool("touch_gui") and "padding[0.01,0.01]" or "",
"bgcolor[#0000]", "bgcolor[#0000]",
-- HACK: this is needed to allow resubmitting the same formspec -- HACK: this is needed to allow resubmitting the same formspec
@ -652,15 +650,15 @@ local function buttonhandler(this, fields)
write_settings_early() write_settings_early()
end end
-- enable_touch is a checkbox in a setting component. We handle this -- touch_controls is a checkbox in a setting component. We handle this
-- setting differently so we can hide/show pages using the next if-statement -- setting differently so we can hide/show pages using the next if-statement
if fields.enable_touch ~= nil then if fields.touch_controls ~= nil then
local value = core.is_yes(fields.enable_touch) local value = core.is_yes(fields.touch_controls)
core.settings:set_bool("enable_touch", value) core.settings:set_bool("touch_controls", value)
write_settings_early() write_settings_early()
end end
if fields.show_advanced ~= nil or fields.enable_touch ~= nil then if fields.show_advanced ~= nil or fields.touch_controls ~= nil then
local suggested_page_id = update_filtered_pages(dialogdata.query) local suggested_page_id = update_filtered_pages(dialogdata.query)
dialogdata.components = nil dialogdata.components = nil

View File

@ -15,90 +15,6 @@
--with this program; if not, write to the Free Software Foundation, Inc., --with this program; if not, write to the Free Software Foundation, Inc.,
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-- https://github.com/orgs/minetest/teams/engine/members
local core_developers = {
"Perttu Ahola (celeron55) <celeron55@gmail.com> [Project founder]",
"sfan5 <sfan5@live.de>",
"ShadowNinja <shadowninja@minetest.net>",
"Nathanaëlle Courant (Nore/Ekdohibs) <nore@mesecons.net>",
"Loic Blot (nerzhul/nrz) <loic.blot@unix-experience.fr>",
"Andrew Ward (rubenwardy) <rw@rubenwardy.com>",
"Krock/SmallJoker <mk939@ymail.com>",
"Lars Hofhansl <larsh@apache.org>",
"v-rob <robinsonvincent89@gmail.com>",
"Desour/DS",
"srifqi",
"Gregor Parzefall (grorp)",
}
-- currently only https://github.com/orgs/minetest/teams/triagers/members
local core_team = {
"Zughy [Issue triager]",
"wsor [Issue triager]",
"Hugo Locurcio (Calinou) [Issue triager]",
}
-- For updating active/previous contributors, see the script in ./util/gather_git_credits.py
local active_contributors = {
"Wuzzy [Features, translations, documentation]",
"numzero [Optimizations, work on OpenGL driver]",
"ROllerozxa [Bugfixes, Mainmenu]",
"Lars Müller [Bugfixes]",
"AFCMS [Documentation]",
"savilli [Bugfixes]",
"fluxionary [Bugfixes]",
"Bradley Pierce (Thresher) [Documentation]",
"Stvk imension [Android]",
"JosiahWI [Code cleanups]",
"OgelGames [UI, Bugfixes]",
"ndren [Bugfixes]",
"Abdou-31 [Documentation]",
}
local previous_core_developers = {
"BlockMen",
"Maciej Kasatkin (RealBadAngel) [RIP]",
"Lisa Milne (darkrose) <lisa@ltmnet.com>",
"proller",
"Ilya Zhuravlev (xyz) <xyz@minetest.net>",
"PilzAdam <pilzadam@minetest.net>",
"est31 <MTest31@outlook.com>",
"kahrl <kahrl@gmx.net>",
"Ryan Kwolek (kwolekr) <kwolekr@minetest.net>",
"sapier",
"Zeno",
"Auke Kok (sofar) <sofar@foo-projects.org>",
"Aaron Suen <warr1024@gmail.com>",
"paramat",
"Pierre-Yves Rollo <dev@pyrollo.com>",
"hecks",
"Jude Melton-Houghton (TurkeyMcMac) [RIP]",
"Hugues Ross <hugues.ross@gmail.com>",
"Dmitry Kostenko (x2048) <codeforsmile@gmail.com>",
}
local previous_contributors = {
"Nils Dagsson Moskopp (erlehmann) <nils@dieweltistgarnichtso.net> [Minetest logo]",
"red-001 <red-001@outlook.ie>",
"Giuseppe Bilotta",
"HybridDog",
"ClobberXD",
"Dániel Juhász (juhdanad) <juhdanad@gmail.com>",
"MirceaKitsune <mirceakitsune@gmail.com>",
"Jean-Patrick Guerrero (kilbith)",
"MoNTE48",
"Constantin Wenger (SpeedProg)",
"Ciaran Gultnieks (CiaranG)",
"Paul Ouellette (pauloue)",
"stujones11",
"Rogier <rogier777@gmail.com>",
"Gregory Currie (gregorycu)",
"JacobF",
"Jeija <jeija@mesecons.net>",
}
local function prepare_credits(dest, source) local function prepare_credits(dest, source)
local string = table.concat(source, "\n") .. "\n" local string = table.concat(source, "\n") .. "\n"
@ -114,6 +30,13 @@ local function prepare_credits(dest, source)
table.insert(dest, string) table.insert(dest, string)
end end
local function get_credits()
local f = assert(io.open(core.get_mainmenu_path() .. "/credits.json"))
local json = core.parse_json(f:read("*all"))
f:close()
return json
end
return { return {
name = "about", name = "about",
caption = fgettext("About"), caption = fgettext("About"),
@ -127,30 +50,32 @@ return {
"<tag name=gray color=#aaa>", "<tag name=gray color=#aaa>",
} }
local credits = get_credits()
table.insert_all(hypertext, { table.insert_all(hypertext, {
"<heading>", fgettext_ne("Core Developers"), "</heading>\n", "<heading>", fgettext_ne("Core Developers"), "</heading>\n",
}) })
prepare_credits(hypertext, core_developers) prepare_credits(hypertext, credits.core_developers)
table.insert_all(hypertext, { table.insert_all(hypertext, {
"\n", "\n",
"<heading>", fgettext_ne("Core Team"), "</heading>\n", "<heading>", fgettext_ne("Core Team"), "</heading>\n",
}) })
prepare_credits(hypertext, core_team) prepare_credits(hypertext, credits.core_team)
table.insert_all(hypertext, { table.insert_all(hypertext, {
"\n", "\n",
"<heading>", fgettext_ne("Active Contributors"), "</heading>\n", "<heading>", fgettext_ne("Active Contributors"), "</heading>\n",
}) })
prepare_credits(hypertext, active_contributors) prepare_credits(hypertext, credits.contributors)
table.insert_all(hypertext, { table.insert_all(hypertext, {
"\n", "\n",
"<heading>", fgettext_ne("Previous Core Developers"), "</heading>\n", "<heading>", fgettext_ne("Previous Core Developers"), "</heading>\n",
}) })
prepare_credits(hypertext, previous_core_developers) prepare_credits(hypertext, credits.previous_core_developers)
table.insert_all(hypertext, { table.insert_all(hypertext, {
"\n", "\n",
"<heading>", fgettext_ne("Previous Contributors"), "</heading>\n", "<heading>", fgettext_ne("Previous Contributors"), "</heading>\n",
}) })
prepare_credits(hypertext, previous_contributors) prepare_credits(hypertext, credits.previous_contributors)
hypertext = table.concat(hypertext):sub(1, -2) hypertext = table.concat(hypertext):sub(1, -2)

View File

@ -92,10 +92,16 @@ function singleplayer_refresh_gamebar()
end end
end end
local ENABLE_TOUCH = core.settings:get_bool("enable_touch")
local gamebar_pos_y = MAIN_TAB_H
+ TABHEADER_H -- tabheader included in formspec size
+ (ENABLE_TOUCH and GAMEBAR_OFFSET_TOUCH or GAMEBAR_OFFSET_DESKTOP)
local btnbar = buttonbar_create( local btnbar = buttonbar_create(
"game_button_bar", "game_button_bar",
core.settings:get_bool("enable_touch") and {x = 0, y = 7.25} or {x = 0, y = 7.475}, {x = 0, y = gamebar_pos_y},
{x = 15.5, y = 1.25}, {x = MAIN_TAB_W, y = GAMEBAR_H},
"#000000", "#000000",
game_buttonbar_button_handler) game_buttonbar_button_handler)

View File

@ -61,7 +61,7 @@
# #
# # This is a comment # # This is a comment
# # # #
# # Requires: shaders, enable_dynamic_shadows, !touchscreen_gui # # Requires: shaders, enable_dynamic_shadows, !touch_controls
# name (Readable name) type type_args # name (Readable name) type type_args
# #
# A requirement can be the name of a boolean setting or an engine-defined value. # A requirement can be the name of a boolean setting or an engine-defined value.
@ -72,7 +72,6 @@
# * shaders_support (a video driver that supports shaders, may not be enabled) # * shaders_support (a video driver that supports shaders, may not be enabled)
# * shaders (both enable_shaders and shaders_support) # * shaders (both enable_shaders and shaders_support)
# * desktop / android # * desktop / android
# * touchscreen_gui / keyboard_mouse
# * opengl / gles # * opengl / gles
# * You can negate any requirement by prepending with ! # * You can negate any requirement by prepending with !
# #
@ -92,7 +91,7 @@ camera_smoothing (Camera smoothing) float 0.0 0.0 0.99
# Smooths rotation of camera when in cinematic mode, 0 to disable. Enter cinematic mode by using the key set in Controls. # Smooths rotation of camera when in cinematic mode, 0 to disable. Enter cinematic mode by using the key set in Controls.
# #
# Requires: keyboard_mouse # Requires: !touch_controls
cinematic_camera_smoothing (Camera smoothing in cinematic mode) float 0.7 0.0 0.99 cinematic_camera_smoothing (Camera smoothing in cinematic mode) float 0.7 0.0 0.99
# If enabled, you can place nodes at the position (feet + eye level) where you stand. # If enabled, you can place nodes at the position (feet + eye level) where you stand.
@ -113,7 +112,7 @@ always_fly_fast (Always fly fast) bool true
# The time in seconds it takes between repeated node placements when holding # The time in seconds it takes between repeated node placements when holding
# the place button. # the place button.
# #
# Requires: keyboard_mouse # Requires: !touch_controls
repeat_place_time (Place repetition interval) float 0.25 0.16 2.0 repeat_place_time (Place repetition interval) float 0.25 0.16 2.0
# The minimum time in seconds it takes between digging nodes when holding # The minimum time in seconds it takes between digging nodes when holding
@ -132,60 +131,60 @@ safe_dig_and_place (Safe digging and placing) bool false
# Invert vertical mouse movement. # Invert vertical mouse movement.
# #
# Requires: keyboard_mouse # Requires: !touch_controls
invert_mouse (Invert mouse) bool false invert_mouse (Invert mouse) bool false
# Mouse sensitivity multiplier. # Mouse sensitivity multiplier.
# #
# Requires: keyboard_mouse # Requires: !touch_controls
mouse_sensitivity (Mouse sensitivity) float 0.2 0.001 10.0 mouse_sensitivity (Mouse sensitivity) float 0.2 0.001 10.0
# Enable mouse wheel (scroll) for item selection in hotbar. # Enable mouse wheel (scroll) for item selection in hotbar.
# #
# Requires: keyboard_mouse # Requires: !touch_controls
enable_hotbar_mouse_wheel (Hotbar: Enable mouse wheel for selection) bool true enable_hotbar_mouse_wheel (Hotbar: Enable mouse wheel for selection) bool true
# Invert mouse wheel (scroll) direction for item selection in hotbar. # Invert mouse wheel (scroll) direction for item selection in hotbar.
# #
# Requires: keyboard_mouse # Requires: !touch_controls
invert_hotbar_mouse_wheel (Hotbar: Invert mouse wheel direction) bool false invert_hotbar_mouse_wheel (Hotbar: Invert mouse wheel direction) bool false
[*Touchscreen] [*Touchscreen]
# Enables touchscreen mode, allowing you to play the game with a touchscreen. # Enables the touchscreen controls, allowing you to play the game with a touchscreen.
enable_touch (Enable touchscreen) bool true touch_controls (Enable touchscreen controls) bool true
# Touchscreen sensitivity multiplier. # Touchscreen sensitivity multiplier.
# #
# Requires: touchscreen_gui # Requires: touch_controls
touchscreen_sensitivity (Touchscreen sensitivity) float 0.2 0.001 10.0 touchscreen_sensitivity (Touchscreen sensitivity) float 0.2 0.001 10.0
# The length in pixels after which a touch interaction is considered movement. # The length in pixels after which a touch interaction is considered movement.
# #
# Requires: touchscreen_gui # Requires: touch_controls
touchscreen_threshold (Movement threshold) int 20 0 100 touchscreen_threshold (Movement threshold) int 20 0 100
# The delay in milliseconds after which a touch interaction is considered a long tap. # The delay in milliseconds after which a touch interaction is considered a long tap.
# #
# Requires: touchscreen_gui # Requires: touch_controls
touch_long_tap_delay (Threshold for long taps) int 400 100 1000 touch_long_tap_delay (Threshold for long taps) int 400 100 1000
# Use crosshair to select object instead of whole screen. # Use crosshair to select object instead of whole screen.
# If enabled, a crosshair will be shown and will be used for selecting object. # If enabled, a crosshair will be shown and will be used for selecting object.
# #
# Requires: touchscreen_gui # Requires: touch_controls
touch_use_crosshair (Use crosshair for touch screen) bool false touch_use_crosshair (Use crosshair for touch screen) bool false
# Fixes the position of virtual joystick. # Fixes the position of virtual joystick.
# If disabled, virtual joystick will center to first-touch's position. # If disabled, virtual joystick will center to first-touch's position.
# #
# Requires: touchscreen_gui # Requires: touch_controls
fixed_virtual_joystick (Fixed virtual joystick) bool false fixed_virtual_joystick (Fixed virtual joystick) bool false
# Use virtual joystick to trigger "Aux1" button. # Use virtual joystick to trigger "Aux1" button.
# If enabled, virtual joystick will also tap "Aux1" button when out of main circle. # If enabled, virtual joystick will also tap "Aux1" button when out of main circle.
# #
# Requires: touchscreen_gui # Requires: touch_controls
virtual_joystick_triggers_aux1 (Virtual joystick triggers Aux1 button) bool false virtual_joystick_triggers_aux1 (Virtual joystick triggers Aux1 button) bool false
# The gesture for punching players/entities. # The gesture for punching players/entities.
@ -198,7 +197,7 @@ virtual_joystick_triggers_aux1 (Virtual joystick triggers Aux1 button) bool fals
# Known from the classic Minetest mobile controls. # Known from the classic Minetest mobile controls.
# Combat is more or less impossible. # Combat is more or less impossible.
# #
# Requires: touchscreen_gui # Requires: touch_controls
touch_punch_gesture (Punch gesture) enum short_tap short_tap,long_tap touch_punch_gesture (Punch gesture) enum short_tap short_tap,long_tap
@ -692,6 +691,10 @@ language (Language) enum ,be,bg,ca,cs,da,de,el,en,eo,es,et,eu,fi,fr,gd,gl,hu,i
[**GUI] [**GUI]
# When enabled, the GUI is optimized to be more usable on touchscreens.
# Whether this is enabled by default depends on your hardware form-factor.
touch_gui (Optimize GUI for touchscreens) bool false
# Scale GUI by a user specified value. # Scale GUI by a user specified value.
# Use a nearest-neighbor-anti-alias filter to scale the GUI. # Use a nearest-neighbor-anti-alias filter to scale the GUI.
# This will smooth over some of the rough edges, and blend # This will smooth over some of the rough edges, and blend
@ -699,6 +702,9 @@ language (Language) enum ,be,bg,ca,cs,da,de,el,en,eo,es,et,eu,fi,fr,gd,gl,hu,i
# edge pixels when images are scaled by non-integer sizes. # edge pixels when images are scaled by non-integer sizes.
gui_scaling (GUI scaling) float 1.0 0.5 20 gui_scaling (GUI scaling) float 1.0 0.5 20
# Enables smooth scrolling.
smooth_scrolling (Smooth scrolling) bool true
# Enables animation of inventory items. # Enables animation of inventory items.
inventory_items_animations (Inventory items animations) bool false inventory_items_animations (Inventory items animations) bool false
@ -737,6 +743,12 @@ hud_scaling (HUD scaling) float 1.0 0.5 20
# Mods may still set a background. # Mods may still set a background.
show_nametag_backgrounds (Show name tag backgrounds by default) bool true show_nametag_backgrounds (Show name tag backgrounds by default) bool true
# Whether to show the client debug info (has the same effect as hitting F5).
show_debug (Show debug info) bool false
# Radius to use when the block bounds HUD feature is set to near blocks.
show_block_bounds_radius_near (Block bounds HUD radius) int 4 0 1000
[**Chat] [**Chat]
# Maximum number of recent chat messages to show # Maximum number of recent chat messages to show
@ -830,6 +842,9 @@ server_url (Server URL) string https://minetest.net
# Automatically report to the serverlist. # Automatically report to the serverlist.
server_announce (Announce server) bool false server_announce (Announce server) bool false
# Send names of online players to the serverlist. If disabled only the player count is revealed.
server_announce_send_players (Send player names to the server list) bool true
# Announce to this serverlist. # Announce to this serverlist.
serverlist_url (Serverlist URL) string servers.minetest.net serverlist_url (Serverlist URL) string servers.minetest.net
@ -1019,7 +1034,7 @@ mapgen_limit (Map generation limit) int 31007 0 31007
# Global map generation attributes. # Global map generation attributes.
# In Mapgen v6 the 'decorations' flag controls all decorations except trees # In Mapgen v6 the 'decorations' flag controls all decorations except trees
# and jungle grass, in all other mapgens this flag controls all decorations. # and jungle grass, in all other mapgens this flag controls all decorations.
mg_flags (Mapgen flags) flags caves,dungeons,light,decorations,biomes,ores caves,dungeons,light,decorations,biomes,ores,nocaves,nodungeons,nolight,nodecorations,nobiomes,noores mg_flags (Mapgen flags) flags caves,dungeons,light,decorations,biomes,ores caves,dungeons,light,decorations,biomes,ores
[*Biome API] [*Biome API]
@ -1038,7 +1053,7 @@ mg_biome_np_humidity_blend (Humidity blend noise) noise_params_2d 0, 1.5, (8, 8,
[*Mapgen V5] [*Mapgen V5]
# Map generation attributes specific to Mapgen v5. # Map generation attributes specific to Mapgen v5.
mgv5_spflags (Mapgen V5 specific flags) flags caverns caverns,nocaverns mgv5_spflags (Mapgen V5 specific flags) flags caverns caverns
# Controls width of tunnels, a smaller value creates wider tunnels. # Controls width of tunnels, a smaller value creates wider tunnels.
# Value >= 10.0 completely disables generation of tunnels and avoids the # Value >= 10.0 completely disables generation of tunnels and avoids the
@ -1112,7 +1127,7 @@ mgv5_np_dungeons (Dungeon noise) noise_params_3d 0.9, 0.5, (500, 500, 500), 0, 2
# When the 'snowbiomes' flag is enabled jungles are automatically enabled and # When the 'snowbiomes' flag is enabled jungles are automatically enabled and
# the 'jungles' flag is ignored. # the 'jungles' flag is ignored.
# The 'temples' flag disables generation of desert temples. Normal dungeons will appear instead. # The 'temples' flag disables generation of desert temples. Normal dungeons will appear instead.
mgv6_spflags (Mapgen V6 specific flags) flags jungles,biomeblend,mudflow,snowbiomes,noflat,trees,temples jungles,biomeblend,mudflow,snowbiomes,flat,trees,temples,nojungles,nobiomeblend,nomudflow,nosnowbiomes,noflat,notrees,notemples mgv6_spflags (Mapgen V6 specific flags) flags jungles,biomeblend,mudflow,snowbiomes,noflat,trees,temples jungles,biomeblend,mudflow,snowbiomes,flat,trees,temples
# Deserts occur when np_biome exceeds this value. # Deserts occur when np_biome exceeds this value.
# When the 'snowbiomes' flag is enabled, this is ignored. # When the 'snowbiomes' flag is enabled, this is ignored.
@ -1168,7 +1183,7 @@ mgv6_np_apple_trees (Apple trees noise) noise_params_2d 0, 1, (100, 100, 100), 3
# 'ridges': Rivers. # 'ridges': Rivers.
# 'floatlands': Floating land masses in the atmosphere. # 'floatlands': Floating land masses in the atmosphere.
# 'caverns': Giant caves deep underground. # 'caverns': Giant caves deep underground.
mgv7_spflags (Mapgen V7 specific flags) flags mountains,ridges,nofloatlands,caverns mountains,ridges,floatlands,caverns,nomountains,noridges,nofloatlands,nocaverns mgv7_spflags (Mapgen V7 specific flags) flags mountains,ridges,nofloatlands,caverns mountains,ridges,floatlands,caverns
# Y of mountain density gradient zero level. Used to shift mountains vertically. # Y of mountain density gradient zero level. Used to shift mountains vertically.
mgv7_mount_zero_level (Mountain zero level) int 0 -31000 31000 mgv7_mount_zero_level (Mountain zero level) int 0 -31000 31000
@ -1302,7 +1317,7 @@ mgv7_np_dungeons (Dungeon noise) noise_params_3d 0.9, 0.5, (500, 500, 500), 0, 2
[*Mapgen Carpathian] [*Mapgen Carpathian]
# Map generation attributes specific to 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,norivers caverns,rivers
# Defines the base ground level. # Defines the base ground level.
mgcarpathian_base_level (Base ground level) float 12.0 mgcarpathian_base_level (Base ground level) float 12.0
@ -1411,7 +1426,7 @@ mgcarpathian_np_dungeons (Dungeon noise) noise_params_3d 0.9, 0.5, (500, 500, 50
# 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. # Occasional lakes and hills can be added to the flat world.
mgflat_spflags (Mapgen Flat specific flags) flags nolakes,nohills,nocaverns lakes,hills,caverns,nolakes,nohills,nocaverns mgflat_spflags (Mapgen Flat specific flags) flags nolakes,nohills,nocaverns lakes,hills,caverns
# Y of flat ground. # Y of flat ground.
mgflat_ground_level (Ground level) int 8 -31000 31000 mgflat_ground_level (Ground level) int 8 -31000 31000
@ -1495,7 +1510,7 @@ mgflat_np_dungeons (Dungeon noise) noise_params_3d 0.9, 0.5, (500, 500, 500), 0,
# Map generation attributes specific to Mapgen Fractal. # Map generation attributes specific to Mapgen Fractal.
# 'terrain' enables the generation of non-fractal terrain: # 'terrain' enables the generation of non-fractal terrain:
# ocean, islands and underground. # ocean, islands and underground.
mgfractal_spflags (Mapgen Fractal specific flags) flags terrain terrain,noterrain mgfractal_spflags (Mapgen Fractal specific flags) flags terrain terrain
# Controls width of tunnels, a smaller value creates wider tunnels. # Controls width of tunnels, a smaller value creates wider tunnels.
# Value >= 10.0 completely disables generation of tunnels and avoids the # Value >= 10.0 completely disables generation of tunnels and avoids the
@ -1629,7 +1644,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 # 'vary_river_depth': If enabled, low humidity and high heat causes rivers
# to become shallower and occasionally dry. # to become shallower and occasionally dry.
# 'altitude_dry': Reduces humidity with altitude. # '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,humid_rivers,vary_river_depth,altitude_dry
# The vertical distance over which heat drops by 20 if 'altitude_chill' is # 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 # enabled. Also, the vertical distance over which humidity drops by 10 if
@ -1844,11 +1859,11 @@ shader_path (Shader path) path
# The rendering back-end. # The rendering back-end.
# Note: A restart is required after changing this! # Note: A restart is required after changing this!
# OpenGL is the default for desktop, and OGLES2 for Android. # OpenGL is the default for desktop, and OGLES2 for Android.
# Shaders are supported by everything but OGLES1. video_driver (Video driver) enum ,opengl,opengl3,ogles2
video_driver (Video driver) enum ,opengl,opengl3,ogles1,ogles2
# Distance in nodes at which transparency depth sorting is enabled # Distance in nodes at which transparency depth sorting is enabled.
# Use this to limit the performance impact of transparency depth sorting # Use this to limit the performance impact of transparency depth sorting.
# Set to 0 to disable it entirely.
transparency_sorting_distance (Transparency Sorting Distance) int 16 0 128 transparency_sorting_distance (Transparency Sorting Distance) int 16 0 128
# Radius of cloud area stated in number of 64 node cloud squares. # Radius of cloud area stated in number of 64 node cloud squares.
@ -2008,9 +2023,6 @@ client_unload_unused_data_timeout (Mapblock unload timeout) float 600.0 0.0
# Set to -1 for unlimited amount. # Set to -1 for unlimited amount.
client_mapblock_limit (Mapblock limit) int 7500 -1 2147483647 client_mapblock_limit (Mapblock limit) int 7500 -1 2147483647
# Whether to show the client debug info (has the same effect as hitting F5).
show_debug (Show debug info) bool false
# Maximum number of blocks that are simultaneously sent per client. # Maximum number of blocks that are simultaneously sent per client.
# The maximum total count is calculated dynamically: # The maximum total count is calculated dynamically:
# max_total = ceil((#clients + max_users) * per_client / 4) # max_total = ceil((#clients + max_users) * per_client / 4)
@ -2020,9 +2032,8 @@ max_simultaneous_block_sends_per_client (Maximum simultaneous block sends per cl
# This determines how long they are slowed down after placing or removing a node. # This determines how long they are slowed down after placing or removing a node.
full_block_send_enable_min_time_from_building (Delay in sending blocks after building) float 2.0 0.0 full_block_send_enable_min_time_from_building (Delay in sending blocks after building) float 2.0 0.0
# Maximum number of packets sent per send step, if you have a slow connection # Maximum number of packets sent per send step in the low-level networking code.
# try reducing it, but don't reduce it to a number below double of targeted # You generally don't need to change this, however busy servers may benefit from a higher number.
# client number.
max_packets_per_iteration (Max. packets per iteration) int 1024 1 65535 max_packets_per_iteration (Max. packets per iteration) int 1024 1 65535
# Compression level to use when sending mapblocks to the client. # Compression level to use when sending mapblocks to the client.

View File

@ -1 +0,0 @@
../../irr/media/Shaders

View File

@ -11,7 +11,6 @@ attribute vec2 inTexCoord0;
uniform mat4 uWVPMatrix; uniform mat4 uWVPMatrix;
uniform mat4 uWVMatrix; uniform mat4 uWVMatrix;
uniform mat4 uNMatrix;
uniform mat4 uTMatrix0; uniform mat4 uTMatrix0;
uniform float uThickness; uniform float uThickness;

View File

@ -134,7 +134,7 @@ float directional_ambient(vec3 normal)
void main(void) void main(void)
{ {
varTexCoord = (mTexture * inTexCoord0).st; varTexCoord = (mTexture * vec4(inTexCoord0.xy, 1.0, 1.0)).st;
gl_Position = mWorldViewProj * inVertexPosition; gl_Position = mWorldViewProj * inVertexPosition;
vPosition = gl_Position.xyz; vPosition = gl_Position.xyz;

View File

@ -11,7 +11,7 @@ if(ENABLE_LUAJIT)
find_package(LuaJIT) find_package(LuaJIT)
if(LUAJIT_FOUND) if(LUAJIT_FOUND)
set(USE_LUAJIT TRUE) set(USE_LUAJIT TRUE)
message (STATUS "Using LuaJIT provided by system.") message (STATUS "Using LuaJIT")
elseif(REQUIRE_LUAJIT) elseif(REQUIRE_LUAJIT)
message(FATAL_ERROR "LuaJIT not found whereas REQUIRE_LUAJIT=\"TRUE\" is used.\n" message(FATAL_ERROR "LuaJIT not found whereas REQUIRE_LUAJIT=\"TRUE\" is used.\n"
"To continue, either install LuaJIT or do not use REQUIRE_LUAJIT=\"TRUE\".") "To continue, either install LuaJIT or do not use REQUIRE_LUAJIT=\"TRUE\".")

View File

@ -1,4 +1,4 @@
Minetest Lua Client Modding API Reference 5.9.0 Minetest Lua Client Modding API Reference 5.10.0
================================================ ================================================
* More information at <http://www.minetest.net/> * More information at <http://www.minetest.net/>
* Developer Wiki: <http://dev.minetest.net/> * Developer Wiki: <http://dev.minetest.net/>
@ -315,7 +315,7 @@ Call these functions only at load time!
* `minetest.register_globalstep(function(dtime))` * `minetest.register_globalstep(function(dtime))`
* Called every client environment step * Called every client environment step
* `dtime` is the time since last execution in seconds. * `dtime` is the time since last execution in seconds.
* `minetest.register_on_mods_loaded(function())` * `minetest.register_on_mods_loaded(function())`
* Called just after mods have finished loading. * Called just after mods have finished loading.
* `minetest.register_on_shutdown(function())` * `minetest.register_on_shutdown(function())`
@ -586,9 +586,9 @@ Call these functions only at load time!
* `minetest.camera` * `minetest.camera`
* Reference to the camera object. See [`Camera`](#camera) class reference for methods. * Reference to the camera object. See [`Camera`](#camera) class reference for methods.
* `minetest.show_formspec(formname, formspec)` : returns true on success * `minetest.show_formspec(formname, formspec)` : returns true on success
* Shows a formspec to the player * Shows a formspec to the player
* `minetest.display_chat_message(message)` returns true on success * `minetest.display_chat_message(message)` returns true on success
* Shows a chat message to the current player. * Shows a chat message to the current player.
Setting-related Setting-related
--------------- ---------------
@ -866,9 +866,9 @@ It can be created via `Raycast(pos1, pos2, objects, liquids)` or
----------------- -----------------
### Definitions ### Definitions
* `minetest.get_node_def(nodename)` * `minetest.get_node_def(nodename)`
* Returns [node definition](#node-definition) table of `nodename` * Returns [node definition](#node-definition) table of `nodename`
* `minetest.get_item_def(itemstring)` * `minetest.get_item_def(itemstring)`
* Returns item definition table of `itemstring` * Returns item definition table of `itemstring`
#### Node Definition #### Node Definition
@ -898,7 +898,7 @@ It can be created via `Raycast(pos1, pos2, objects, liquids)` or
"node1", "node1",
"node2" "node2"
}, },
post_effect_color = Color, -- Color overlayed on the screen when the player is in the node post_effect_color = Color, -- Color overlaid on the screen when the player is in the node
leveled = number, -- Max level for node leveled = number, -- Max level for node
sunlight_propogates = bool, -- Whether light passes through the block sunlight_propogates = bool, -- Whether light passes through the block
light_source = number, -- Light emitted by the block light_source = number, -- Light emitted by the block
@ -971,10 +971,10 @@ It can be created via `Raycast(pos1, pos2, objects, liquids)` or
```lua ```lua
{ {
address = "minetest.example.org", -- The domain name/IP address of a remote server or "" for a local server. address = "minetest.example.org", -- The domain name/IP address of a remote server or "" for a local server.
ip = "203.0.113.156", -- The IP address of the server. ip = "203.0.113.156", -- The IP address of the server.
port = 30000, -- The port the client is connected to. port = 30000, -- The port the client is connected to.
protocol_version = 30 -- Will not be accurate at start up as the client might not be connected to the server yet, in that case it will be 0. protocol_version = 30 -- Will not be accurate at start up as the client might not be connected to the server yet, in that case it will be 0.
} }
``` ```

View File

@ -22,6 +22,7 @@ General options and their default values:
MinSizeRel - Release build with -Os passed to compiler to make executable as small as possible MinSizeRel - Release build with -Os passed to compiler to make executable as small as possible
PRECOMPILE_HEADERS=FALSE - Precompile some headers (experimental; requires CMake 3.16 or later) PRECOMPILE_HEADERS=FALSE - Precompile some headers (experimental; requires CMake 3.16 or later)
PRECOMPILED_HEADERS_PATH= - Path to a file listing all headers to precompile (default points to src/precompiled_headers.txt) PRECOMPILED_HEADERS_PATH= - Path to a file listing all headers to precompile (default points to src/precompiled_headers.txt)
USE_SDL2=TRUE - Build with SDL2; Enables IrrlichtMt device SDL2
ENABLE_CURL=ON - Build with cURL; Enables use of online mod repo, public serverlist and remote media fetching via http ENABLE_CURL=ON - Build with cURL; Enables use of online mod repo, public serverlist and remote media fetching via http
ENABLE_CURSES=ON - Build with (n)curses; Enables a server side terminal (command line option: --terminal) ENABLE_CURSES=ON - Build with (n)curses; Enables a server side terminal (command line option: --terminal)
ENABLE_GETTEXT=ON - Build with Gettext; Allows using translations ENABLE_GETTEXT=ON - Build with Gettext; Allows using translations
@ -39,10 +40,15 @@ General options and their default values:
ENABLE_UPDATE_CHECKER=TRUE - Whether to enable update checks by default ENABLE_UPDATE_CHECKER=TRUE - Whether to enable update checks by default
INSTALL_DEVTEST=FALSE - Whether the Development Test game should be installed alongside Minetest INSTALL_DEVTEST=FALSE - Whether the Development Test game should be installed alongside Minetest
USE_GPROF=FALSE - Enable profiling using GProf USE_GPROF=FALSE - Enable profiling using GProf
BUILD_WITH_TRACY=FALSE - Fetch and build with the Tracy profiler client
FETCH_TRACY_GIT_TAG=master - Git tag for fetching Tracy client. Match with your server (gui) version
VERSION_EXTRA= - Text to append to version (e.g. VERSION_EXTRA=foobar -> Minetest 0.4.9-foobar) VERSION_EXTRA= - Text to append to version (e.g. VERSION_EXTRA=foobar -> Minetest 0.4.9-foobar)
Library specific options: Library specific options:
SDL2_DLL - Only if building with SDL2 on Windows; path to libSDL2.dll
SDL2_INCLUDE_DIRS - Only if building with SDL2; directory where SDL.h is located
SDL2_LIBRARIES - Only if building with SDL2; path to libSDL2.a/libSDL2.so/libSDL2.lib
CURL_DLL - Only if building with cURL on Windows; path to libcurl.dll CURL_DLL - Only if building with cURL on Windows; path to libcurl.dll
CURL_INCLUDE_DIR - Only if building with cURL; directory where curl.h is located CURL_INCLUDE_DIR - Only if building with cURL; directory where curl.h is located
CURL_LIBRARY - Only if building with cURL; path to libcurl.a/libcurl.so/libcurl.lib CURL_LIBRARY - Only if building with cURL; path to libcurl.a/libcurl.so/libcurl.lib

View File

@ -14,7 +14,7 @@ It is highly recommended to use vcpkg as package manager.
After you successfully built vcpkg you can easily install the required libraries: After you successfully built vcpkg you can easily install the required libraries:
```powershell ```powershell
vcpkg install zlib zstd curl[winssl] openal-soft libvorbis libogg libjpeg-turbo sqlite3 freetype luajit gmp jsoncpp gettext sdl2 --triplet x64-windows vcpkg install zlib zstd curl[winssl] openal-soft libvorbis libogg libjpeg-turbo sqlite3 freetype luajit gmp jsoncpp gettext[tools] sdl2 --triplet x64-windows
``` ```
- `curl` is optional, but required to read the serverlist, `curl[winssl]` is required to use the content store. - `curl` is optional, but required to read the serverlist, `curl[winssl]` is required to use the content store.
@ -52,7 +52,7 @@ Use `--triplet` to specify the target triplet, e.g. `x64-windows` or `x86-window
Run the following script in PowerShell: Run the following script in PowerShell:
```powershell ```powershell
cmake . -G"Visual Studio 15 2017 Win64" -DCMAKE_TOOLCHAIN_FILE=D:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_GETTEXT=OFF -DENABLE_CURSES=OFF cmake . -G"Visual Studio 16 2019" -DCMAKE_TOOLCHAIN_FILE=D:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_CURSES=OFF
cmake --build . --config Release cmake --build . --config Release
``` ```
Make sure that the right compiler is selected and the path to the vcpkg toolchain is correct. Make sure that the right compiler is selected and the path to the vcpkg toolchain is correct.

View File

@ -1,6 +1,6 @@
# Miscellaneous # Miscellaneous
## Profiling Minetest on Linux ## Profiling Minetest on Linux with perf
We will be using a tool called "perf", which you can get by installing `perf` or `linux-perf` or `linux-tools-common`. We will be using a tool called "perf", which you can get by installing `perf` or `linux-perf` or `linux-tools-common`.
@ -36,3 +36,54 @@ Give both files to the developer and also provide:
* commit the source was built from and/or modified source code (if applicable) * commit the source was built from and/or modified source code (if applicable)
Hotspot will resolve symbols correctly when pointing the sysroot option at the collected libs. Hotspot will resolve symbols correctly when pointing the sysroot option at the collected libs.
## Profiling with Tracy
[Tracy](https://github.com/wolfpld/tracy) is
> A real time, nanosecond resolution, remote telemetry, hybrid frame and sampling
> profiler for games and other applications.
It allows one to annotate important functions and generate traces, where one can
see when each individual function call happened, and how long it took.
Tracy can also record when frames, e.g. server step, start and end, and inspect
frames that took longer than usual. Minetest already contains annotations for
its frames.
See also [Tracy's official documentation](https://github.com/wolfpld/tracy/releases/latest/download/tracy.pdf).
### Installing
Tracy consists of a client (Minetest) and a server (the gui).
Install the server, e.g. using your package manager.
### Building
Build Minetest with `-DDBUILD_WITH_TRACY=1`, this will fetch Tracy for building
the Tracy client. And use `FETCH_TRACY_GIT_TAG` to get a version matching your
Tracy server, e.g. `-DFETCH_TRACY_GIT_TAG=v0.11.0` if it's `0.11.0`.
To actually use Tracy, you also have to enable it with Tracy's build options:
```
-DTRACY_ENABLE=1 -DTRACY_ONLY_LOCALHOST=1
```
See Tracy's documentation for more build options.
### Using in C++
Start the Tracy server and Minetest. You should see Minetest in the menu.
To actually get useful traces, you have to annotate functions with `ZoneScoped`
macros and recompile. Please refer to Tracy's official documentation.
### Using in Lua
Tracy also supports Lua.
If built with Tracy, Minetest loads its API in the global `tracy` table.
See Tracy's official documentation for more information.
Note: The whole Tracy Lua API is accessible to all mods. And we don't check if it
is or becomes insecure. Run untrusted mods at your own risk.

View File

@ -274,7 +274,7 @@ Accepted formats are:
images: .png, .jpg, .tga, (deprecated:) .bmp images: .png, .jpg, .tga, (deprecated:) .bmp
sounds: .ogg vorbis sounds: .ogg vorbis
models: .x, .b3d, .obj models: .x, .b3d, .obj, .gltf (Minetest 5.10 or newer)
Other formats won't be sent to the client (e.g. you can store .blend files Other formats won't be sent to the client (e.g. you can store .blend files
in a folder for convenience, without the risk that such files are transferred) in a folder for convenience, without the risk that such files are transferred)
@ -291,6 +291,43 @@ in one of its parents, the parent's file is used.
Although it is discouraged, a mod can overwrite a media file of any mod that it Although it is discouraged, a mod can overwrite a media file of any mod that it
depends on by supplying a file with an equal name. depends on by supplying a file with an equal name.
Only a subset of model file format features is supported:
Simple textured meshes (with multiple textures), optionally with normals.
The .x and .b3d formats additionally support skeletal animation.
#### glTF
The glTF model file format for now only serves as a
more modern alternative to the other static model file formats;
it unlocks no special rendering features.
This means that many glTF features are not supported *yet*, including:
* Animation
* Cameras
* Materials
* Only base color textures are supported
* Backface culling is overridden
* Double-sided materials don't work
* Alternative means of supplying data
* Embedded images
* References to files via URIs
Textures are supplied solely via the same means as for the other model file formats:
The `textures` object property, the `tiles` node definition field and
the list of textures used in the `model[]` formspec element.
The order in which textures are to be supplied
is that in which they appear in the `textures` array in the glTF file.
Do not rely on glTF features not being supported; they may be supported in the future.
The backwards compatibility guarantee does not extend to ignoring unsupported features.
For example, if your model used an emissive material,
you should expect that a future version of Minetest may respect this,
and thus cause your model to render differently there.
Naming conventions Naming conventions
------------------ ------------------
@ -1103,7 +1140,6 @@ Table used to specify how a sound is played:
-- its end in `-start_time` seconds. -- its end in `-start_time` seconds.
-- It is unspecified what happens if `loop` is false and `start_time` is -- It is unspecified what happens if `loop` is false and `start_time` is
-- smaller than minus the sound's length. -- smaller than minus the sound's length.
-- Available since feature `sound_params_start_time`. -- Available since feature `sound_params_start_time`.
loop = false, loop = false,
@ -1117,21 +1153,6 @@ Table used to specify how a sound is played:
-- Attach the sound to an object. -- Attach the sound to an object.
-- Can't be used together with `pos`. -- Can't be used together with `pos`.
-- For backward compatibility, sounds continue playing at the last location
-- of the object if an object is removed (for example if an entity dies).
-- It is not recommended to rely on this.
-- For death sounds, prefer playing a positional sound instead.
-- If you want to stop a sound when an entity dies or is deactivated,
-- store the handle and call `minetest.sound_stop` in `on_die` / `on_deactivate`.
-- Ephemeral sounds are entirely unaffected by the object being removed
-- or leaving the active object range.
-- Non-ephemeral sounds stop playing on clients if objects leave
-- the active object range; they should start playing again if objects
--- come back into range (but due to a known bug, they don't yet).
to_player = name, to_player = name,
-- Only play for this player. -- Only play for this player.
-- Can't be used together with `exclude_player`. -- Can't be used together with `exclude_player`.
@ -1504,7 +1525,7 @@ Look for examples in `games/devtest` or `games/minetest_game`.
* For supported model formats see Irrlicht engine documentation. * For supported model formats see Irrlicht engine documentation.
* `plantlike_rooted` * `plantlike_rooted`
* Enables underwater `plantlike` without air bubbles around the nodes. * Enables underwater `plantlike` without air bubbles around the nodes.
* Consists of a base cube at the co-ordinates of the node plus a * Consists of a base cube at the coordinates of the node plus a
`plantlike` extension above `plantlike` extension above
* If `paramtype2="leveled", the `plantlike` extension has a height * If `paramtype2="leveled", the `plantlike` extension has a height
of `param2 / 16` nodes, otherwise it's the height of 1 node of `param2 / 16` nodes, otherwise it's the height of 1 node
@ -1760,6 +1781,13 @@ Displays a horizontal bar made up of half-images with an optional background.
* `item`: Position of item that is selected. * `item`: Position of item that is selected.
* `direction`: Direction the list will be displayed in * `direction`: Direction the list will be displayed in
* `offset`: offset in pixels from position. * `offset`: offset in pixels from position.
* `alignment`: The alignment of the inventory. Aligned at the top left corner if not specified.
### `hotbar`
* `direction`: Direction the list will be displayed in
* `offset`: offset in pixels from position.
* `alignment`: The alignment of the inventory.
### `waypoint` ### `waypoint`
@ -1818,6 +1846,11 @@ Displays a minimap on the HUD.
* `size`: Size of the minimap to display. Minimap should be a square to avoid * `size`: Size of the minimap to display. Minimap should be a square to avoid
distortion. distortion.
* Negative values represent percentages of the screen. If either `x` or `y`
is specified as a percentage, the resulting pixel size will be used for
both `x` and `y`. Example: On a 1920x1080 screen, `{x = 0, y = -25}` will
result in a 270x270 minimap.
* Negative values are supported starting with protocol version 45.
* `alignment`: The alignment of the minimap. * `alignment`: The alignment of the minimap.
* `offset`: offset in pixels from position. * `offset`: offset in pixels from position.
@ -2641,6 +2674,9 @@ background elements are drawn before all other elements.
**WARNING**: do _not_ use an element name starting with `key_`; those names are **WARNING**: do _not_ use an element name starting with `key_`; those names are
reserved to pass key press events to formspec! reserved to pass key press events to formspec!
**WARNING**: names and values of elements cannot contain binary data such as ASCII
control characters. For values, escape sequences used by the engine are an exception to this.
**WARNING**: Minetest allows you to add elements to every single formspec instance **WARNING**: Minetest allows you to add elements to every single formspec instance
using `player:set_formspec_prepend()`, which may be the reason backgrounds are using `player:set_formspec_prepend()`, which may be the reason backgrounds are
appearing when you don't expect them to, or why things are styled differently appearing when you don't expect them to, or why things are styled differently
@ -2877,14 +2913,14 @@ Elements
* Requires formspec version >= 6. * Requires formspec version >= 6.
* See `background9[]` documentation for more information. * See `background9[]` documentation for more information.
### `model[<X>,<Y>;<W>,<H>;<name>;<mesh>;<textures>;<rotation X,Y>;<continuous>;<mouse control>;<frame loop range>;<animation speed>]` ### `model[<X>,<Y>;<W>,<H>;<name>;<mesh>;<textures>;<rotation>;<continuous>;<mouse control>;<frame loop range>;<animation speed>]`
* Show a mesh model. * Show a mesh model.
* `name`: Element name that can be used for styling * `name`: Element name that can be used for styling
* `mesh`: The mesh model to use. * `mesh`: The mesh model to use.
* `textures`: The mesh textures to use according to the mesh materials. * `textures`: The mesh textures to use according to the mesh materials.
Texture names must be separated by commas. Texture names must be separated by commas.
* `rotation {X,Y}` (Optional): Initial rotation of the camera. * `rotation` (Optional): Initial rotation of the camera, format `x,y`.
The axes are euler angles in degrees. The axes are euler angles in degrees.
* `continuous` (Optional): Whether the rotation is continuous. Default `false`. * `continuous` (Optional): Whether the rotation is continuous. Default `false`.
* `mouse control` (Optional): Whether the model can be controlled with the mouse. Default `true`. * `mouse control` (Optional): Whether the model can be controlled with the mouse. Default `true`.
@ -3078,7 +3114,7 @@ Elements
### `textlist[<X>,<Y>;<W>,<H>;<name>;<listelem 1>,<listelem 2>,...,<listelem n>]` ### `textlist[<X>,<Y>;<W>,<H>;<name>;<listelem 1>,<listelem 2>,...,<listelem n>]`
* Scrollable item list showing arbitrary text elements * Scrollable item list showing arbitrary text elements
* `name` fieldname sent to server on doubleclick value is current selected * `name` fieldname sent to server on double-click value is current selected
element. element.
* `listelements` can be prepended by #color in hexadecimal format RRGGBB * `listelements` can be prepended by #color in hexadecimal format RRGGBB
(only). (only).
@ -3087,7 +3123,7 @@ Elements
### `textlist[<X>,<Y>;<W>,<H>;<name>;<listelem 1>,<listelem 2>,...,<listelem n>;<selected idx>;<transparent>]` ### `textlist[<X>,<Y>;<W>,<H>;<name>;<listelem 1>,<listelem 2>,...,<listelem n>;<selected idx>;<transparent>]`
* Scrollable itemlist showing arbitrary text elements * Scrollable itemlist showing arbitrary text elements
* `name` fieldname sent to server on doubleclick value is current selected * `name` fieldname sent to server on double-click value is current selected
element. element.
* `listelements` can be prepended by #RRGGBB (only) in hexadecimal format * `listelements` can be prepended by #RRGGBB (only) in hexadecimal format
* if you want a listelement to start with "#" write "##" * if you want a listelement to start with "#" write "##"
@ -3224,7 +3260,7 @@ Elements
* Show scrollable table using options defined by the previous `tableoptions[]` * Show scrollable table using options defined by the previous `tableoptions[]`
* Displays cells as defined by the previous `tablecolumns[]` * Displays cells as defined by the previous `tablecolumns[]`
* `name`: fieldname sent to server on row select or doubleclick * `name`: fieldname sent to server on row select or double-click
* `cell 1`...`cell n`: cell contents given in row-major order * `cell 1`...`cell n`: cell contents given in row-major order
* `selected idx`: index of row to be selected within table (first row = `1`) * `selected idx`: index of row to be selected within table (first row = `1`)
* See also `minetest.explode_table_event` * See also `minetest.explode_table_event`
@ -3675,6 +3711,9 @@ Player Inventory lists
* Is not created automatically, use `InvRef:set_size` * Is not created automatically, use `InvRef:set_size`
* Is only used to enhance the empty hand's tool capabilities * Is only used to enhance the empty hand's tool capabilities
Custom lists can be added and deleted with `InvRef:set_size(name, size)` like
any other inventory.
ItemStack transaction order ItemStack transaction order
--------------------------- ---------------------------
@ -3833,6 +3872,8 @@ vectors are written like this: `(x, y, z)`:
`vector.new(v)` does the same as `vector.copy(v)` `vector.new(v)` does the same as `vector.copy(v)`
* `vector.zero()`: * `vector.zero()`:
* Returns a new vector `(0, 0, 0)`. * Returns a new vector `(0, 0, 0)`.
* `vector.random_direction()`:
* Returns a new vector of length 1, pointing into a direction chosen uniformly at random.
* `vector.copy(v)`: * `vector.copy(v)`:
* Returns a copy of the vector `v`. * Returns a copy of the vector `v`.
* `vector.from_string(s[, init])`: * `vector.from_string(s[, init])`:
@ -3858,15 +3899,23 @@ vectors are written like this: `(x, y, z)`:
* If `v` has zero length, returns `(0, 0, 0)`. * If `v` has zero length, returns `(0, 0, 0)`.
* `vector.floor(v)`: * `vector.floor(v)`:
* Returns a vector, each dimension rounded down. * Returns a vector, each dimension rounded down.
* `vector.ceil(v)`:
* Returns a vector, each dimension rounded up.
* `vector.round(v)`: * `vector.round(v)`:
* Returns a vector, each dimension rounded to nearest integer. * Returns a vector, each dimension rounded to nearest integer.
* At a multiple of 0.5, rounds away from zero. * At a multiple of 0.5, rounds away from zero.
* `vector.apply(v, func)`: * `vector.sign(v, tolerance)`:
* Returns a vector where `math.sign` was called for each component.
* See [Helper functions] for details.
* `vector.abs(v)`:
* Returns a vector with absolute values for each component.
* `vector.apply(v, func, ...)`:
* Returns a vector where the function `func` has been applied to each * Returns a vector where the function `func` has been applied to each
component. component.
* `...` are optional arguments passed to `func`.
* `vector.combine(v, w, func)`: * `vector.combine(v, w, func)`:
* Returns a vector where the function `func` has combined both components of `v` and `w` * Returns a vector where the function `func` has combined both components of `v` and `w`
for each component for each component
* `vector.equals(v1, v2)`: * `vector.equals(v1, v2)`:
* Returns a boolean, `true` if the vectors are identical. * Returns a boolean, `true` if the vectors are identical.
* `vector.sort(v1, v2)`: * `vector.sort(v1, v2)`:
@ -3884,10 +3933,14 @@ vectors are written like this: `(x, y, z)`:
by a `vector.*` function. by a `vector.*` function.
* Returns `false` for anything else, including tables like `{x=3,y=1,z=4}`. * Returns `false` for anything else, including tables like `{x=3,y=1,z=4}`.
* `vector.in_area(pos, min, max)`: * `vector.in_area(pos, min, max)`:
* Returns a boolean value indicating if `pos` is inside area formed by `min` and `max`. * Returns a boolean value indicating if `pos` is inside area formed by `min` and `max`.
* `min` and `max` are inclusive. * `min` and `max` are inclusive.
* If `min` is bigger than `max` on some axis, function always returns false. * If `min` is bigger than `max` on some axis, function always returns false.
* You can use `vector.sort` if you have two vectors and don't know which are the minimum and the maximum. * You can use `vector.sort` if you have two vectors and don't know which are the minimum and the maximum.
* `vector.random_in_area(min, max)`:
* Returns a random integer position in area formed by `min` and `max`
* `min` and `max` are inclusive.
* You can use `vector.sort` if you have two vectors and don't know which are the minimum and the maximum.
For the following functions `x` can be either a vector or a number: For the following functions `x` can be either a vector or a number:
@ -4036,6 +4089,10 @@ Helper functions
the value `val` in the table `list`. Non-numerical indices are ignored. the value `val` in the table `list`. Non-numerical indices are ignored.
If `val` could not be found, `-1` is returned. `list` must not have If `val` could not be found, `-1` is returned. `list` must not have
negative indices. negative indices.
* `table.keyof(table, val)`: returns the key containing
the value `val` in the table `table`. If multiple keys contain `val`,
it is unspecified which key will be returned.
If `val` could not be found, `nil` is returned.
* `table.insert_all(table, other_table)`: * `table.insert_all(table, other_table)`:
* Appends all values in `other_table` to `table` - uses `#table + 1` to * Appends all values in `other_table` to `table` - uses `#table + 1` to
find new indices. find new indices.
@ -4255,7 +4312,7 @@ Perlin noise
============ ============
Perlin noise creates a continuously-varying value depending on the input values. Perlin noise creates a continuously-varying value depending on the input values.
Usually in Minetest the input values are either 2D or 3D co-ordinates in nodes. Usually in Minetest the input values are either 2D or 3D coordinates in nodes.
The result is used during map generation to create the terrain shape, vary heat The result is used during map generation to create the terrain shape, vary heat
and humidity to distribute biomes, vary the density of decorations or vary the and humidity to distribute biomes, vary the density of decorations or vary the
structure of ores. structure of ores.
@ -4518,7 +4575,7 @@ computationally expensive than any other ore.
Creates a single undulating ore stratum that is continuous across mapchunk Creates a single undulating ore stratum that is continuous across mapchunk
borders and horizontally spans the world. borders and horizontally spans the world.
The 2D perlin noise described by `noise_params` defines the Y co-ordinate of The 2D perlin noise described by `noise_params` defines the Y coordinate of
the stratum midpoint. The 2D perlin noise described by `np_stratum_thickness` the stratum midpoint. The 2D perlin noise described by `np_stratum_thickness`
defines the stratum's vertical thickness (in units of nodes). Due to being defines the stratum's vertical thickness (in units of nodes). Due to being
continuous across mapchunk borders the stratum's vertical thickness is continuous across mapchunk borders the stratum's vertical thickness is
@ -5083,12 +5140,12 @@ Callbacks:
used for updating the entity state. used for updating the entity state.
* `on_deactivate(self, removal)` * `on_deactivate(self, removal)`
* Called when the object is about to get removed or unloaded. * Called when the object is about to get removed or unloaded.
* `removal`: boolean indicating whether the object is about to get removed. * `removal`: boolean indicating whether the object is about to get removed.
Calling `object:remove()` on an active object will call this with `removal=true`. Calling `object:remove()` on an active object will call this with `removal=true`.
The mapblock the entity resides in being unloaded will call this with `removal=false`. The mapblock the entity resides in being unloaded will call this with `removal=false`.
* Note that this won't be called if the object hasn't been activated in the first place. * Note that this won't be called if the object hasn't been activated in the first place.
In particular, `minetest.clear_objects({mode = "full"})` won't call this, In particular, `minetest.clear_objects({mode = "full"})` won't call this,
whereas `minetest.clear_objects({mode = "quick"})` might call this. whereas `minetest.clear_objects({mode = "quick"})` might call this.
* `on_step(self, dtime, moveresult)` * `on_step(self, dtime, moveresult)`
* Called on every server tick, after movement and collision processing. * Called on every server tick, after movement and collision processing.
* `dtime`: elapsed time since last call * `dtime`: elapsed time since last call
@ -5113,12 +5170,15 @@ Callbacks:
to the object (not necessarily an actual rightclick) to the object (not necessarily an actual rightclick)
* `clicker`: an `ObjectRef` (may or may not be a player) * `clicker`: an `ObjectRef` (may or may not be a player)
* `on_attach_child(self, child)` * `on_attach_child(self, child)`
* `child`: an `ObjectRef` of the child that attaches * Called after another object is attached to this object.
* `child`: an `ObjectRef` of the child
* `on_detach_child(self, child)` * `on_detach_child(self, child)`
* `child`: an `ObjectRef` of the child that detaches * Called after another object has detached from this object.
* `child`: an `ObjectRef` of the child
* `on_detach(self, parent)` * `on_detach(self, parent)`
* `parent`: an `ObjectRef` (can be `nil`) from where it got detached * Called after detaching from another object.
* This happens before the parent object is removed from the world * `parent`: an `ObjectRef` from where it got detached
* Note: this is also called before removal from the world.
* `get_staticdata(self)` * `get_staticdata(self)`
* Should return a string that will be passed to `on_activate` when the * Should return a string that will be passed to `on_activate` when the
object is instantiated the next time. object is instantiated the next time.
@ -5451,15 +5511,17 @@ Utilities
dynamic_add_media_filepath = true, dynamic_add_media_filepath = true,
-- L-system decoration type (5.9.0) -- L-system decoration type (5.9.0)
lsystem_decoration_type = true, lsystem_decoration_type = true,
-- Overrideable pointing range using the itemstack meta key `"range"` (5.9.0) -- Overridable pointing range using the itemstack meta key `"range"` (5.9.0)
item_meta_range = true, item_meta_range = true,
-- Allow passing an optional "actor" ObjectRef to the following functions: -- Allow passing an optional "actor" ObjectRef to the following functions:
-- minetest.place_node, minetest.dig_node, minetest.punch_node (5.9.0) -- minetest.place_node, minetest.dig_node, minetest.punch_node (5.9.0)
node_interaction_actor = true, node_interaction_actor = true,
-- "new_pos" field in entity moveresult (5.9.0) -- "new_pos" field in entity moveresult (5.9.0)
moveresult_new_pos = true, moveresult_new_pos = true,
-- Allow removing definition fields in `minetest.override_item` -- Allow removing definition fields in `minetest.override_item` (5.9.0)
override_item_remove_fields = true, override_item_remove_fields = true,
-- The predefined hotbar is a Lua HUD element of type `hotbar` (5.10.0)
hotbar_hud_element = true,
} }
``` ```
@ -5518,8 +5580,8 @@ Utilities
}, },
-- Estimated maximum formspec size before Minetest will start shrinking the -- Estimated maximum formspec size before Minetest will start shrinking the
-- formspec to fit. For a fullscreen formspec, use a size 10-20% larger than -- formspec to fit. For a fullscreen formspec, use this formspec size and
-- this and `padding[-0.01,-0.01]`. -- `padding[0,0]`. `bgcolor[;true]` is also recommended.
max_formspec_size = { max_formspec_size = {
x = 20, x = 20,
y = 11.25 y = 11.25
@ -5593,6 +5655,13 @@ Utilities
* `minetest.colorspec_to_bytes(colorspec)`: Converts a ColorSpec to a raw * `minetest.colorspec_to_bytes(colorspec)`: Converts a ColorSpec to a raw
string of four bytes in an RGBA layout, returned as a string. string of four bytes in an RGBA layout, returned as a string.
* `colorspec`: The ColorSpec to convert * `colorspec`: The ColorSpec to convert
* `minetest.colorspec_to_table(colorspec)`: Converts a ColorSpec into RGBA table
form. If the ColorSpec is invalid, returns `nil`. You can use this to parse
ColorStrings.
* `colorspec`: The ColorSpec to convert
* `minetest.time_to_day_night_ratio(time_of_day)`: Returns a "day-night ratio" value
(as accepted by `ObjectRef:override_day_night_ratio`) that is equivalent to
the given "time of day" value (as returned by `minetest.get_timeofday`).
* `minetest.encode_png(width, height, data, [compression])`: Encode a PNG * `minetest.encode_png(width, height, data, [compression])`: Encode a PNG
image and return it in string form. image and return it in string form.
* `width`: Width of the image * `width`: Width of the image
@ -5727,7 +5796,7 @@ Call these functions only at load time!
* `minetest.register_globalstep(function(dtime))` * `minetest.register_globalstep(function(dtime))`
* Called every server step, usually interval of 0.1s. * Called every server step, usually interval of 0.1s.
* `dtime` is the time since last execution in seconds. * `dtime` is the time since last execution in seconds.
* `minetest.register_on_mods_loaded(function())` * `minetest.register_on_mods_loaded(function())`
* Called after mods have finished loading and before the media is cached or the * Called after mods have finished loading and before the media is cached or the
aliases handled. aliases handled.
@ -5753,7 +5822,7 @@ Call these functions only at load time!
* `minetest.register_on_generated(function(minp, maxp, blockseed))` * `minetest.register_on_generated(function(minp, maxp, blockseed))`
* Called after generating a piece of world between `minp` and `maxp`. * Called after generating a piece of world between `minp` and `maxp`.
* **Avoid using this** whenever possible. As with other callbacks this blocks * **Avoid using this** whenever possible. As with other callbacks this blocks
the main thread and introduces noticable latency. the main thread and introduces noticeable latency.
Consider [Mapgen environment] for an alternative. Consider [Mapgen environment] for an alternative.
* `minetest.register_on_newplayer(function(ObjectRef))` * `minetest.register_on_newplayer(function(ObjectRef))`
* Called when a new player enters the world for the first time * Called when a new player enters the world for the first time
@ -6155,7 +6224,7 @@ Environment access
* **Warning**: The same warning as for `minetest.get_objects_inside_radius` applies. * **Warning**: The same warning as for `minetest.get_objects_inside_radius` applies.
Use `minetest.objects_in_area` instead to iterate only valid objects. Use `minetest.objects_in_area` instead to iterate only valid objects.
* `minetest.objects_in_area(min_pos, max_pos)` * `minetest.objects_in_area(min_pos, max_pos)`
* returns an iterator of valid objects * returns an iterator of valid objects
* `minetest.set_timeofday(val)`: set time of day * `minetest.set_timeofday(val)`: set time of day
* `val` is between `0` and `1`; `0` for midnight, `0.5` for midday * `val` is between `0` and `1`; `0` for midnight, `0.5` for midday
* `minetest.get_timeofday()`: get time of day * `minetest.get_timeofday()`: get time of day
@ -6417,11 +6486,11 @@ Environment access
* spread these updates to neighbors and can cause a cascade * spread these updates to neighbors and can cause a cascade
of nodes to fall. of nodes to fall.
* `minetest.get_spawn_level(x, z)` * `minetest.get_spawn_level(x, z)`
* Returns a player spawn y co-ordinate for the provided (x, z) * Returns a player spawn y coordinate for the provided (x, z)
co-ordinates, or `nil` for an unsuitable spawn point. coordinates, or `nil` for an unsuitable spawn point.
* For most mapgens a 'suitable spawn point' is one with y between * For most mapgens a 'suitable spawn point' is one with y between
`water_level` and `water_level + 16`, and in mgv7 well away from rivers, `water_level` and `water_level + 16`, and in mgv7 well away from rivers,
so `nil` will be returned for many (x, z) co-ordinates. so `nil` will be returned for many (x, z) coordinates.
* The spawn level returned is for a player spawn in unmodified terrain. * The spawn level returned is for a player spawn in unmodified terrain.
* The spawn level is intentionally above terrain level to cope with * The spawn level is intentionally above terrain level to cope with
full-node biome 'dust' nodes. full-node biome 'dust' nodes.
@ -6467,7 +6536,8 @@ Formspec
* `playername`: name of player to show formspec * `playername`: name of player to show formspec
* `formname`: name passed to `on_player_receive_fields` callbacks. * `formname`: name passed to `on_player_receive_fields` callbacks.
It should follow the `"modname:<whatever>"` naming convention. It should follow the `"modname:<whatever>"` naming convention.
`formname` must not be empty. * `formname` must not be empty, unless you want to reshow
the inventory formspec without updating it for future opens.
* `formspec`: formspec to display * `formspec`: formspec to display
* `minetest.close_formspec(playername, formname)` * `minetest.close_formspec(playername, formname)`
* `playername`: name of player to close formspec * `playername`: name of player to close formspec
@ -6731,7 +6801,7 @@ This allows you easy interoperability for delegating work to jobs.
* Register a path to a Lua file to be imported when an async environment * Register a path to a Lua file to be imported when an async environment
is initialized. You can use this to preload code which you can then call is initialized. You can use this to preload code which you can then call
later using `minetest.handle_async()`. later using `minetest.handle_async()`.
* `minetest.register_async_metatable(name, mt)`: * `minetest.register_portable_metatable(name, mt)`:
* Register a metatable that should be preserved when data is transferred * Register a metatable that should be preserved when data is transferred
between the main thread and the async environment. between the main thread and the async environment.
* `name` is a string that identifies the metatable. It is recommended to * `name` is a string that identifies the metatable. It is recommended to
@ -6771,7 +6841,7 @@ Functions:
* Standalone helpers such as logging, filesystem, encoding, * Standalone helpers such as logging, filesystem, encoding,
hashing or compression APIs hashing or compression APIs
* `minetest.register_async_metatable` (see above) * `minetest.register_portable_metatable` (see above)
Variables: Variables:
@ -6901,7 +6971,7 @@ Server
all players (optional) all players (optional)
* `ephemeral`: boolean that marks the media as ephemeral, * `ephemeral`: boolean that marks the media as ephemeral,
it will not be cached on the client (optional, default false) it will not be cached on the client (optional, default false)
* Exactly one of the paramters marked [*] must be specified. * Exactly one of the parameters marked [*] must be specified.
* `callback`: function with arguments `name`, which is a player name * `callback`: function with arguments `name`, which is a player name
* Pushes the specified media file to client(s). (details below) * Pushes the specified media file to client(s). (details below)
The file must be a supported image, sound or model format. The file must be a supported image, sound or model format.
@ -6936,10 +7006,11 @@ Bans
* Returns boolean indicating success * Returns boolean indicating success
* `minetest.unban_player_or_ip(ip_or_name)`: remove ban record matching * `minetest.unban_player_or_ip(ip_or_name)`: remove ban record matching
IP address or name IP address or name
* `minetest.kick_player(name, [reason])`: disconnect a player with an optional * `minetest.kick_player(name[, reason[, reconnect]])`: disconnect a player with an optional
reason. reason.
* Returns boolean indicating success (false if player nonexistent) * Returns boolean indicating success (false if player nonexistent)
* `minetest.disconnect_player(name, [reason])`: disconnect a player with an * If `reconnect` is true, allow the user to reconnect.
* `minetest.disconnect_player(name[, reason[, reconnect]])`: disconnect a player with an
optional reason, this will not prefix with 'Kicked: ' like kick_player. optional reason, this will not prefix with 'Kicked: ' like kick_player.
If no reason is given, it will default to 'Disconnected.' If no reason is given, it will default to 'Disconnected.'
* Returns boolean indicating success (false if player nonexistent) * Returns boolean indicating success (false if player nonexistent)
@ -7101,9 +7172,11 @@ Misc.
* `minetest.is_player(obj)`: boolean, whether `obj` is a player * `minetest.is_player(obj)`: boolean, whether `obj` is a player
* `minetest.player_exists(name)`: boolean, whether player exists * `minetest.player_exists(name)`: boolean, whether player exists
(regardless of online status) (regardless of online status)
* `minetest.is_valid_player_name(name)`: boolean, whether the given name
could be used as a player name (regardless of whether said player exists).
* `minetest.hud_replace_builtin(name, hud_definition)` * `minetest.hud_replace_builtin(name, hud_definition)`
* Replaces definition of a builtin hud element * Replaces definition of a builtin hud element
* `name`: `"breath"`, `"health"` or `"minimap"` * `name`: `"breath"`, `"health"`, `"minimap"` or `"hotbar"`
* `hud_definition`: definition to replace builtin definition * `hud_definition`: definition to replace builtin definition
* `minetest.parse_relative_number(arg, relative_to)`: returns number or nil * `minetest.parse_relative_number(arg, relative_to)`: returns number or nil
* Helper function for chat commands. * Helper function for chat commands.
@ -7509,6 +7582,8 @@ An `InvRef` is a reference to an inventory.
* `is_empty(listname)`: return `true` if list is empty * `is_empty(listname)`: return `true` if list is empty
* `get_size(listname)`: get size of a list * `get_size(listname)`: get size of a list
* `set_size(listname, size)`: set size of a list * `set_size(listname, size)`: set size of a list
* If `listname` is not known, a new list will be created
* Setting `size` to 0 deletes a list
* returns `false` on error (e.g. invalid `listname` or `size`) * returns `false` on error (e.g. invalid `listname` or `size`)
* `get_width(listname)`: get width of a list * `get_width(listname)`: get width of a list
* `set_width(listname, width)`: set width of list; currently used for crafting * `set_width(listname, width)`: set width of list; currently used for crafting
@ -7583,9 +7658,12 @@ an itemstring, a table or `nil`.
* `set_wear(wear)`: returns boolean indicating whether item was cleared * `set_wear(wear)`: returns boolean indicating whether item was cleared
* `wear`: number, unsigned 16 bit integer * `wear`: number, unsigned 16 bit integer
* `get_meta()`: returns ItemStackMetaRef. See section for more details * `get_meta()`: returns ItemStackMetaRef. See section for more details
* `get_metadata()`: (DEPRECATED) Returns metadata (a string attached to an item * `get_metadata()`: **Deprecated.** Returns metadata (a string attached to an item stack).
stack). * If you need to access this to maintain backwards compatibility,
* `set_metadata(metadata)`: (DEPRECATED) Returns true. use `stack:get_meta():get_string("")` instead.
* `set_metadata(metadata)`: **Deprecated.** Returns true.
* If you need to set this to maintain backwards compatibility,
use `stack:get_meta():set_string("", metadata)` instead.
* `get_description()`: returns the description shown in inventory list tooltips. * `get_description()`: returns the description shown in inventory list tooltips.
* The engine uses this when showing item descriptions in tooltips. * The engine uses this when showing item descriptions in tooltips.
* Fields for finding the description, in order: * Fields for finding the description, in order:
@ -7729,7 +7807,7 @@ metadata_table = {
-- metadata fields (key/value store) -- metadata fields (key/value store)
fields = { fields = {
infotext = "Container", infotext = "Container",
anoter_key = "Another Value", another_key = "Another Value",
}, },
-- inventory data (for nodes) -- inventory data (for nodes)
@ -7958,13 +8036,13 @@ child will follow movement and rotation of that bone.
object. object.
* `set_detach()`: Detaches object. No-op if object was not attached. * `set_detach()`: Detaches object. No-op if object was not attached.
* `set_bone_position([bone, position, rotation])` * `set_bone_position([bone, position, rotation])`
* Shorthand for `set_bone_override(bone, {position = position, rotation = rotation:apply(math.rad)})` using absolute values. * Shorthand for `set_bone_override(bone, {position = position, rotation = rotation:apply(math.rad)})` using absolute values.
* **Note:** Rotation is in degrees, not radians. * **Note:** Rotation is in degrees, not radians.
* **Deprecated:** Use `set_bone_override` instead. * **Deprecated:** Use `set_bone_override` instead.
* `get_bone_position(bone)`: returns the previously set position and rotation of the bone * `get_bone_position(bone)`: returns the previously set position and rotation of the bone
* Shorthand for `get_bone_override(bone).position.vec, get_bone_override(bone).rotation.vec:apply(math.deg)`. * Shorthand for `get_bone_override(bone).position.vec, get_bone_override(bone).rotation.vec:apply(math.deg)`.
* **Note:** Returned rotation is in degrees, not radians. * **Note:** Returned rotation is in degrees, not radians.
* **Deprecated:** Use `get_bone_override` instead. * **Deprecated:** Use `get_bone_override` instead.
* `set_bone_override(bone, override)` * `set_bone_override(bone, override)`
* `bone`: string * `bone`: string
* `override`: `{ position = property, rotation = property, scale = property }` or `nil` * `override`: `{ position = property, rotation = property, scale = property }` or `nil`
@ -7981,10 +8059,33 @@ child will follow movement and rotation of that bone.
* Compatibility note: Clients prior to 5.9.0 only support absolute position and rotation. * Compatibility note: Clients prior to 5.9.0 only support absolute position and rotation.
All values are treated as absolute and are set immediately (no interpolation). All values are treated as absolute and are set immediately (no interpolation).
* `get_bone_override(bone)`: returns `override` in the above format * `get_bone_override(bone)`: returns `override` in the above format
* **Note:** Unlike `get_bone_position`, the returned rotation is in radians, not degrees. * **Note:** Unlike `get_bone_position`, the returned rotation is in radians, not degrees.
* `get_bone_overrides()`: returns all bone overrides as table `{[bonename] = override, ...}` * `get_bone_overrides()`: returns all bone overrides as table `{[bonename] = override, ...}`
* `set_properties(object property table)` * `set_properties(object property table)`
* `get_properties()`: returns a table of all object properties * `get_properties()`: returns a table of all object properties
* `set_observers(observers)`: sets observers (players this object is sent to)
* If `observers` is `nil`, the object's observers are "unmanaged":
The object is sent to all players as governed by server settings. This is the default.
* `observers` is a "set" of player names: `{name1 = true, name2 = true, ...}`
* A set is a table where the keys are the elements of the set
(in this case, *valid* player names) and the values are all `true`.
* Attachments: The *effective observers* of an object are made up of
all players who can observe the object *and* are also effective observers
of its parent object (if there is one).
* Players are automatically added to their own observer sets.
Players **must** effectively observe themselves.
* Object activation and deactivation are unaffected by observability.
* Attached sounds do not work correctly and thus should not be used
on objects with managed observers yet.
* `get_observers()`:
* throws an error if the object is invalid
* returns `nil` if the observers are unmanaged
* returns a table with all observer names as keys and `true` values (a "set") otherwise
* `get_effective_observers()`:
* Like `get_observers()`, but returns the "effective" observers, taking into account attachments
* Time complexity: O(nm)
* n: number of observers of the involved entities
* m: number of ancestors along the attachment chain
* `is_player()`: returns true for players, false otherwise * `is_player()`: returns true for players, false otherwise
* `get_nametag_attributes()` * `get_nametag_attributes()`
* returns a table with the attributes of the nametag of an object * returns a table with the attributes of the nametag of an object
@ -8029,7 +8130,7 @@ child will follow movement and rotation of that bone.
* `rot` is a vector (radians). X is pitch (elevation), Y is yaw (heading) * `rot` is a vector (radians). X is pitch (elevation), Y is yaw (heading)
and Z is roll (bank). and Z is roll (bank).
* Does not reset rotation incurred through `automatic_rotate`. * Does not reset rotation incurred through `automatic_rotate`.
Remove & readd your objects to force a certain rotation. Remove & re-add your objects to force a certain rotation.
* `get_rotation()`: returns the rotation, a vector (radians) * `get_rotation()`: returns the rotation, a vector (radians)
* `set_yaw(yaw)`: sets the yaw in radians (heading). * `set_yaw(yaw)`: sets the yaw in radians (heading).
* `get_yaw()`: returns number in radians * `get_yaw()`: returns number in radians
@ -8055,8 +8156,8 @@ child will follow movement and rotation of that bone.
* Fifth column: subject viewed from above * Fifth column: subject viewed from above
* Sixth column: subject viewed from below * Sixth column: subject viewed from below
* `get_luaentity()`: * `get_luaentity()`:
* Returns the object's associated luaentity table, if there is one * Returns the object's associated luaentity table, if there is one
* Otherwise returns `nil` (e.g. for players) * Otherwise returns `nil` (e.g. for players)
* `get_entity_name()`: * `get_entity_name()`:
* **Deprecated**: Will be removed in a future version, * **Deprecated**: Will be removed in a future version,
use `:get_luaentity().name` instead. use `:get_luaentity().name` instead.
@ -8230,7 +8331,9 @@ child will follow movement and rotation of that bone.
* See `hud_set_flags` for a list of flags that can be toggled. * See `hud_set_flags` for a list of flags that can be toggled.
* `hud_set_hotbar_itemcount(count)`: sets number of items in builtin hotbar * `hud_set_hotbar_itemcount(count)`: sets number of items in builtin hotbar
* `count`: number of items, must be between `1` and `32` * `count`: number of items, must be between `1` and `32`
* If `count` exceeds the `"main"` list size, the list size will be used instead.
* `hud_get_hotbar_itemcount()`: returns number of visible items * `hud_get_hotbar_itemcount()`: returns number of visible items
* This value is also clamped by the `"main"` list size.
* `hud_set_hotbar_image(texturename)` * `hud_set_hotbar_image(texturename)`
* sets background image for hotbar * sets background image for hotbar
* `hud_get_hotbar_image()`: returns texturename * `hud_get_hotbar_image()`: returns texturename
@ -8409,7 +8512,8 @@ child will follow movement and rotation of that bone.
ColorSpec (alpha ignored, default `#000000`) ColorSpec (alpha ignored, default `#000000`)
* `height`: cloud height, i.e. y of cloud base (default per conf, * `height`: cloud height, i.e. y of cloud base (default per conf,
usually `120`) usually `120`)
* `thickness`: cloud thickness in nodes (default `16`) * `thickness`: cloud thickness in nodes (default `16`).
if set to zero the clouds are rendered flat.
* `speed`: 2D cloud speed + direction in nodes per second * `speed`: 2D cloud speed + direction in nodes per second
(default `{x=0, z=-2}`). (default `{x=0, z=-2}`).
* `get_clouds()`: returns a table with the current cloud parameters as in * `get_clouds()`: returns a table with the current cloud parameters as in
@ -8418,6 +8522,7 @@ child will follow movement and rotation of that bone.
* `0`...`1`: Overrides day-night ratio, controlling sunlight to a specific * `0`...`1`: Overrides day-night ratio, controlling sunlight to a specific
amount. amount.
* Passing no arguments disables override, defaulting to sunlight based on day-night cycle * Passing no arguments disables override, defaulting to sunlight based on day-night cycle
* See also `minetest.time_to_day_night_ratio`,
* `get_day_night_ratio()`: returns the ratio or nil if it isn't overridden * `get_day_night_ratio()`: returns the ratio or nil if it isn't overridden
* `set_local_animation(idle, walk, dig, walk_while_dig, frame_speed)`: * `set_local_animation(idle, walk, dig, walk_while_dig, frame_speed)`:
set animation for player model in third person view. set animation for player model in third person view.
@ -8444,8 +8549,17 @@ child will follow movement and rotation of that bone.
* Passing no arguments resets lighting to its default values. * Passing no arguments resets lighting to its default values.
* `light_definition` is a table with the following optional fields: * `light_definition` is a table with the following optional fields:
* `saturation` sets the saturation (vividness; default: `1.0`). * `saturation` sets the saturation (vividness; default: `1.0`).
* values > 1 increase the saturation * It is applied according to the function `result = b*(1-s) + c*s`, where:
* values in [0,1] decrease the saturation * `c` is the original color
* `b` is the greyscale version of the color with the same luma
* `s` is the saturation set here
* The resulting color always has the same luma (perceived brightness) as the original.
* This means that:
* values > 1 oversaturate
* values < 1 down to 0 desaturate, 0 being entirely greyscale
* values < 0 cause an effect similar to inversion,
but keeping original luma and being symmetrical in terms of saturation
(eg. -1 and 1 is the same saturation and luma, but different hues)
* `shadows` is a table that controls ambient shadows * `shadows` is a table that controls ambient shadows
* `intensity` sets the intensity of the shadows from 0 (no shadows, default) to 1 (blackness) * `intensity` sets the intensity of the shadows from 0 (no shadows, default) to 1 (blackness)
* This value has no effect on clients who have the "Dynamic Shadows" shader disabled. * This value has no effect on clients who have the "Dynamic Shadows" shader disabled.
@ -8465,6 +8579,14 @@ child will follow movement and rotation of that bone.
* Result is a table with the same fields as `light_definition` in `set_lighting`. * Result is a table with the same fields as `light_definition` in `set_lighting`.
* `respawn()`: Respawns the player using the same mechanism as the death screen, * `respawn()`: Respawns the player using the same mechanism as the death screen,
including calling `on_respawnplayer` callbacks. including calling `on_respawnplayer` callbacks.
* `get_flags()`: returns a table of player flags (the following boolean fields):
* `breathing`: Whether breathing (regaining air) is enabled, default `true`.
* `drowning`: Whether drowning (losing air) is enabled, default `true`.
* `node_damage`: Whether the player takes damage from nodes, default `true`.
* `set_flags(flags)`: sets flags
* takes a table in the same format as returned by `get_flags`
* absent fields are left unchanged
`PcgRandom` `PcgRandom`
----------- -----------
@ -8640,7 +8762,7 @@ In multiplayer mode, the error may be arbitrarily large.
Interface for the operating system's crypto-secure PRNG. Interface for the operating system's crypto-secure PRNG.
It can be created via `SecureRandom()`. The constructor returns nil if a It can be created via `SecureRandom()`. The constructor throws an error if a
secure random device cannot be found on the system. secure random device cannot be found on the system.
### Methods ### Methods
@ -8912,6 +9034,9 @@ Entity definition
----------------- -----------------
Used by `minetest.register_entity`. Used by `minetest.register_entity`.
The entity definition table becomes a metatable of a newly created per-entity
luaentity table, meaning its fields (e.g. `initial_properties`) will be shared
between all instances of an entity.
```lua ```lua
{ {
@ -8968,7 +9093,7 @@ Used by `minetest.register_abm`.
-- Operation interval in seconds -- Operation interval in seconds
chance = 50, chance = 50,
-- Chance of triggering `action` per-node per-interval is 1.0 / chance -- Probability of triggering `action` per-node per-interval is 1.0 / chance (integers only)
min_y = -32768, min_y = -32768,
max_y = 32767, max_y = 32767,
@ -9230,9 +9355,17 @@ Used by `minetest.register_node`, `minetest.register_craftitem`, and
-- If specified as a table, the field to be used is selected according to -- If specified as a table, the field to be used is selected according to
-- the current `pointed_thing`. -- the current `pointed_thing`.
-- There are three possible TouchInteractionMode values: -- There are three possible TouchInteractionMode values:
-- * "user" (meaning depends on client-side settings)
-- * "long_dig_short_place" (long tap = dig, short tap = place) -- * "long_dig_short_place" (long tap = dig, short tap = place)
-- * "short_dig_long_place" (short tap = dig, long tap = place) -- * "short_dig_long_place" (short tap = dig, long tap = place)
-- * "user":
-- * For `pointed_object`: Equivalent to "short_dig_long_place" if the
-- client-side setting "touch_punch_gesture" is "short_tap" (the
-- default value) and the item is able to punch (i.e. has no on_use
-- callback defined).
-- Equivalent to "long_dig_short_place" otherwise.
-- * For `pointed_node` and `pointed_nothing`:
-- Equivalent to "long_dig_short_place".
-- * The behavior of "user" may change in the future.
-- The default value is "user". -- The default value is "user".
sound = { sound = {
@ -10358,7 +10491,7 @@ See [Decoration types]. Used by `minetest.register_decoration`.
y_min = -31000, y_min = -31000,
y_max = 31000, y_max = 31000,
-- Lower and upper limits for decoration (inclusive). -- Lower and upper limits for decoration (inclusive).
-- These parameters refer to the Y co-ordinate of the 'place_on' node. -- These parameters refer to the Y coordinate of the 'place_on' node.
spawn_by = "default:water", spawn_by = "default:water",
-- Node (or list of nodes) that the decoration only spawns next to. -- Node (or list of nodes) that the decoration only spawns next to.
@ -10608,8 +10741,9 @@ Used by `ObjectRef:hud_add`. Returned by `ObjectRef:hud_get`.
```lua ```lua
{ {
type = "image", type = "image",
-- Type of element, can be "image", "text", "statbar", "inventory", -- Type of element, can be "compass", "hotbar" (46 ¹), "image", "image_waypoint",
-- "waypoint", "image_waypoint", "compass" or "minimap" -- "inventory", "minimap" (44 ¹), "statbar", "text" or "waypoint"
-- ¹: minimal protocol version for client-side support
-- If undefined "text" will be used. -- If undefined "text" will be used.
hud_elem_type = "image", hud_elem_type = "image",
@ -10955,7 +11089,7 @@ Types used are defined in the previous section.
* vec3 range `acc`: the direction and speed with which the particle * vec3 range `acc`: the direction and speed with which the particle
accelerates accelerates
* vec3 range `size`: scales the visual size of the particle texture. * float range `size`: scales the visual size of the particle texture.
if `node` is set, this can be set to 0 to spawn randomly-sized particles if `node` is set, this can be set to 0 to spawn randomly-sized particles
(just like actual node dig particles). (just like actual node dig particles).
@ -11260,6 +11394,16 @@ Functions: bit.tobit, bit.tohex, bit.bnot, bit.band, bit.bor, bit.bxor, bit.lshi
See http://bitop.luajit.org/ for advanced information. See http://bitop.luajit.org/ for advanced information.
Tracy Profiler
--------------
Minetest can be built with support for the Tracy profiler, which can also be
useful for profiling mods and is exposed to Lua as the global `tracy`.
See doc/developing/misc.md for details.
Note: This is a development feature and not covered by compatibility promises.
Error Handling Error Handling
-------------- --------------

View File

@ -1,4 +1,4 @@
Minetest Lua Mainmenu API Reference 5.9.0 Minetest Lua Mainmenu API Reference 5.10.0
========================================= =========================================
Introduction Introduction
@ -8,6 +8,15 @@ The main menu is defined as a formspec by Lua in `builtin/mainmenu/`
Description of formspec language to show your menu is in `lua_api.md` Description of formspec language to show your menu is in `lua_api.md`
Images and 3D models
------
Directory delimiters change according to the OS (e.g. on Unix-like systems
is `/`, on Windows is `\`). When putting an image or a 3D model inside a formspec,
be sure to sanitize it first with `core.formspec_escape(img)`; otherwise,
any resource located in a subpath won't be displayed on OSs using `\` as delimiter.
Callbacks Callbacks
--------- ---------
@ -62,6 +71,12 @@ Functions
Filesystem Filesystem
---------- ----------
To access specific subpaths, use `DIR_DELIM` as a directory delimiter instead
of manually putting one, as different OSs use different delimiters. E.g.
```lua
"my" .. DIR_DELIM .. "custom" .. DIR_DELIM .. "path" -- and not my/custom/path
```
* `core.get_builtin_path()` * `core.get_builtin_path()`
* returns path to builtin root * returns path to builtin root
* `core.create_dir(absolute_path)` (possible in async calls) * `core.create_dir(absolute_path)` (possible in async calls)
@ -238,8 +253,8 @@ GUI
}, },
-- Estimated maximum formspec size before Minetest will start shrinking the -- Estimated maximum formspec size before Minetest will start shrinking the
-- formspec to fit. For a fullscreen formspec, use a size 10-20% larger than -- formspec to fit. For a fullscreen formspec, use this formspec size and
-- this and `padding[-0.01,-0.01]`. -- `padding[0,0]`. `bgcolor[;true]` is also recommended.
max_formspec_size = { max_formspec_size = {
x = 20, x = 20,
y = 11.25 y = 11.25
@ -282,7 +297,7 @@ Package - content which is downloadable from the content db, may or may not be i
```lua ```lua
{ {
mods = "/home/user/.minetest/mods", mods = "/home/user/.minetest/mods",
share = "/usr/share/minetest/mods", share = "/usr/share/minetest/mods", -- only provided when RUN_IN_PLACE=0
-- Custom dirs can be specified by the MINETEST_MOD_DIR env variable -- Custom dirs can be specified by the MINETEST_MOD_DIR env variable
["/path/to/custom/dir"] = "/path/to/custom/dir", ["/path/to/custom/dir"] = "/path/to/custom/dir",

View File

@ -151,8 +151,7 @@ are placeholders intended to be overwritten by the game.
* `rangeview_btn.png` * `rangeview_btn.png`
* `debug_btn.png` * `debug_btn.png`
* `gear_icon.png` * `overflow_btn.png`
* `rare_controls.png`
* `exit_btn.png` * `exit_btn.png`
Texture Overrides Texture Overrides

View File

@ -0,0 +1,14 @@
glTF test model (and corresponding texture) licenses:
* Spider (`gltf_spider.gltf`, `gltf_spider.png`):
* By [archfan7411](https://github.com/archfan7411)
* Licensed under CC0, public domain "wherever public domain carries fewer rights or legal protections"
* Frog (`gltf_frog.gltf`, `gltf_frog.png`):
* By [Susybaka1234](https://sketchfab.com/3d-models/african-clawed-frog-v2-c81152c93948480c931c280d18957358)
* Licensed under CC-BY 4.0
* Snow Man (`gltf_snow_man.gltf`, `gltf_snow_man.png`):
* By [jordan4ibanez](https://github.com/jordan4ibanez)
* Licensed under CC0
* Minimal triangle, triangle without indices (`gltf_minimal_triangle.gltf`, `gltf_triangle_without_indices.gltf`)
* From [the glTF sample model collection](https://github.com/KhronosGroup/glTF-Sample-Models)
* Licensed under CC0 / public domain

View File

@ -0,0 +1,51 @@
local function register_entity(name, textures, backface_culling)
minetest.register_entity("gltf:" .. name, {
initial_properties = {
visual = "mesh",
mesh = "gltf_" .. name .. ".gltf",
textures = textures,
backface_culling = backface_culling,
},
})
end
-- These do not have texture coordinates; they simple render as black surfaces.
register_entity("minimal_triangle", {}, false)
register_entity("triangle_with_vertex_stride", {}, false)
register_entity("triangle_without_indices", {}, false)
do
local cube_textures = {"gltf_cube.png"}
register_entity("blender_cube", cube_textures)
register_entity("blender_cube_scaled", cube_textures)
register_entity("blender_cube_matrix_transform", cube_textures)
end
register_entity("snow_man", {"gltf_snow_man.png"})
register_entity("spider", {"gltf_spider.png"})
-- Note: Model has an animation, but we can use it as a static test nevertheless
-- The claws rendering incorrectly from one side is expected behavior:
-- They use an unsupported double-sided material.
register_entity("frog", {"gltf_frog.png"}, false)
minetest.register_node("gltf:frog", {
description = "glTF frog, but it's a node",
tiles = {{name = "gltf_frog.png", backface_culling = false}},
drawtype = "mesh",
mesh = "gltf_frog.gltf",
})
minetest.register_chatcommand("show_model", {
params = "<model> [textures]",
description = "Show a model (defaults to gltf models, for example '/show_model frog').",
func = function(name, param)
local model, textures = param:match"^(.-)%s+(.+)$"
if not model then
model = "gltf_" .. param .. ".gltf"
textures = "gltf_" .. param .. ".png"
end
minetest.show_formspec(name, "gltf:model", table.concat{
"formspec_version[7]",
"size[10,10]",
"model[0,0;10,10;model;", model, ";", textures, ";0,0;true;true;0,0;0]",
})
end,
})

View File

@ -0,0 +1 @@
{"scene":0,"scenes":[{"nodes":[0]}],"nodes":[{"mesh":0}],"meshes":[{"primitives":[{"attributes":{"POSITION":0}}]}],"buffers":[{"uri":"data:application/octet-stream;base64,AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAA","byteLength":36}],"bufferViews":[{"buffer":0,"byteOffset":1,"byteLength":36,"target":34962}],"accessors":[{"bufferView":0,"byteOffset":0,"componentType":5126,"count":3,"type":"VEC3","max":[1,1,0],"min":[0,0,0]}],"asset":{"version":"2.0"}}

View File

@ -0,0 +1 @@
{

View File

@ -0,0 +1,2 @@
name = gltf
description = Hosts gltf test models, both for the C++ unit tests and for in-game viewing

View File

@ -0,0 +1 @@
{"asset":{"generator":"Khronos glTF Blender I/O v1.7.33","version":"2.0"},"scene":0,"scenes":[{"name":"Scene","nodes":[0]}],"nodes":[{"mesh":0,"name":"Cube","scale":[10,10,10]}],"meshes":[{"name":"Cube.004","primitives":[{"attributes":{"POSITION":0,"NORMAL":1,"TEXCOORD_0":2},"indices":3}]}],"accessors":[{"bufferView":0,"componentType":5126,"count":24,"max":[1,1,1],"min":[-1,-1,-1],"type":"VEC3"},{"bufferView":1,"componentType":5126,"count":24,"type":"VEC3"},{"bufferView":2,"componentType":5126,"count":24,"type":"VEC2"},{"bufferView":3,"componentType":5123,"count":36,"type":"SCALAR"}],"bufferViews":[{"buffer":0,"byteLength":288,"byteOffset":0},{"buffer":0,"byteLength":288,"byteOffset":288},{"buffer":0,"byteLength":192,"byteOffset":576},{"buffer":0,"byteLength":72,"byteOffset":768}],"buffers":[{"byteLength":840,"uri":"data:application/octet-stream;base64,AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAvwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIA/AACAvwAAAAAAAACAAAAAAAAAAAAAAIA/AAAAAAAAgD8AAACAAACAvwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIC/AACAvwAAAAAAAACAAAAAAAAAAAAAAIC/AAAAAAAAgD8AAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIA/AACAPwAAAAAAAACAAAAAAAAAAAAAAIA/AAAAAAAAgD8AAACAAACAPwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIC/AACAPwAAAAAAAACAAAAAAAAAAAAAAIC/AAAAAAAAgD8AAACAAACAPwAAAAAAAACAAADAPgAAgD8AAAA+AACAPgAAwD4AAAAAAAAgPwAAgD8AACA/AAAAAAAAYD8AAIA+AADAPgAAQD8AAAA+AAAAPwAAwD4AAEA/AAAgPwAAQD8AACA/AABAPwAAYD8AAAA/AADAPgAAgD4AAMA+AACAPgAAwD4AAIA+AAAgPwAAgD4AACA/AACAPgAAID8AAIA+AADAPgAAAD8AAMA+AAAAPwAAwD4AAAA/AAAgPwAAAD8AACA/AAAAPwAAID8AAAA/AAADAAkAAAAJAAYACAAKABUACAAVABMAFAAXABEAFAARAA4ADQAPAAQADQAEAAIABwASAAwABwAMAAEAFgALAAUAFgAFABAA"}]}

View File

@ -0,0 +1 @@
{"asset":{"generator":"Khronos glTF Blender I/O v1.7.33","version":"2.0"},"scene":0,"scenes":[{"name":"Scene","nodes":[0]}],"nodes":[{"mesh":0,"name":"Cube","matrix":[1,0,0,0,0,2,0,0,0,0,3,0,4,5,6,1]}],"meshes":[{"name":"Cube.004","primitives":[{"attributes":{"POSITION":0,"NORMAL":1,"TEXCOORD_0":2},"indices":3}]}],"accessors":[{"bufferView":0,"componentType":5126,"count":24,"max":[1,1,1],"min":[-1,-1,-1],"type":"VEC3"},{"bufferView":1,"componentType":5126,"count":24,"type":"VEC3"},{"bufferView":2,"componentType":5126,"count":24,"type":"VEC2"},{"bufferView":3,"componentType":5123,"count":36,"type":"SCALAR"}],"bufferViews":[{"buffer":0,"byteLength":288,"byteOffset":0},{"buffer":0,"byteLength":288,"byteOffset":288},{"buffer":0,"byteLength":192,"byteOffset":576},{"buffer":0,"byteLength":72,"byteOffset":768}],"buffers":[{"byteLength":840,"uri":"data:application/octet-stream;base64,AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAvwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIA/AACAvwAAAAAAAACAAAAAAAAAAAAAAIA/AAAAAAAAgD8AAACAAACAvwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIC/AACAvwAAAAAAAACAAAAAAAAAAAAAAIC/AAAAAAAAgD8AAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIA/AACAPwAAAAAAAACAAAAAAAAAAAAAAIA/AAAAAAAAgD8AAACAAACAPwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIC/AACAPwAAAAAAAACAAAAAAAAAAAAAAIC/AAAAAAAAgD8AAACAAACAPwAAAAAAAACAAADAPgAAgD8AAAA+AACAPgAAwD4AAAAAAAAgPwAAgD8AACA/AAAAAAAAYD8AAIA+AADAPgAAQD8AAAA+AAAAPwAAwD4AAEA/AAAgPwAAQD8AACA/AABAPwAAYD8AAAA/AADAPgAAgD4AAMA+AACAPgAAwD4AAIA+AAAgPwAAgD4AACA/AACAPgAAID8AAIA+AADAPgAAAD8AAMA+AAAAPwAAwD4AAAA/AAAgPwAAAD8AACA/AAAAPwAAID8AAAA/AAADAAkAAAAJAAYACAAKABUACAAVABMAFAAXABEAFAARAA4ADQAPAAQADQAEAAIABwASAAwABwAMAAEAFgALAAUAFgAFABAA"}]}

View File

@ -0,0 +1 @@
{"asset":{"generator":"Khronos glTF Blender I/O v1.7.33","version":"2.0"},"scene":0,"scenes":[{"name":"Scene","nodes":[0]}],"nodes":[{"mesh":0,"name":"Cube","scale":[150,1,21.5]}],"meshes":[{"name":"Cube.004","primitives":[{"attributes":{"POSITION":0,"NORMAL":1,"TEXCOORD_0":2},"indices":3}]}],"accessors":[{"bufferView":0,"componentType":5126,"count":24,"max":[1,1,1],"min":[-1,-1,-1],"type":"VEC3"},{"bufferView":1,"componentType":5126,"count":24,"type":"VEC3"},{"bufferView":2,"componentType":5126,"count":24,"type":"VEC2"},{"bufferView":3,"componentType":5123,"count":36,"type":"SCALAR"}],"bufferViews":[{"buffer":0,"byteLength":288,"byteOffset":0},{"buffer":0,"byteLength":288,"byteOffset":288},{"buffer":0,"byteLength":192,"byteOffset":576},{"buffer":0,"byteLength":72,"byteOffset":768}],"buffers":[{"byteLength":840,"uri":"data:application/octet-stream;base64,AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAvwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIA/AACAvwAAAAAAAACAAAAAAAAAAAAAAIA/AAAAAAAAgD8AAACAAACAvwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIC/AACAvwAAAAAAAACAAAAAAAAAAAAAAIC/AAAAAAAAgD8AAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIA/AACAPwAAAAAAAACAAAAAAAAAAAAAAIA/AAAAAAAAgD8AAACAAACAPwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIC/AACAPwAAAAAAAACAAAAAAAAAAAAAAIC/AAAAAAAAgD8AAACAAACAPwAAAAAAAACAAADAPgAAgD8AAAA+AACAPgAAwD4AAAAAAAAgPwAAgD8AACA/AAAAAAAAYD8AAIA+AADAPgAAQD8AAAA+AAAAPwAAwD4AAEA/AAAgPwAAQD8AACA/AABAPwAAYD8AAAA/AADAPgAAgD4AAMA+AACAPgAAwD4AAIA+AAAgPwAAgD4AACA/AACAPgAAID8AAIA+AADAPgAAAD8AAMA+AAAAPwAAwD4AAAA/AAAgPwAAAD8AACA/AAAAPwAAID8AAAA/AAADAAkAAAAJAAYACAAKABUACAAVABMAFAAXABEAFAARAA4ADQAPAAQADQAEAAIABwASAAwABwAMAAEAFgALAAUAFgAFABAA"}]}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"scene":0,"scenes":[{"nodes":[0]}],"nodes":[{"mesh":0}],"meshes":[{"primitives":[{"attributes":{"POSITION":1},"indices":0}]}],"buffers":[{"uri":"data:application/octet-stream;base64,AAABAAIAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAA=","byteLength":44}],"bufferViews":[{"buffer":0,"byteOffset":0,"byteLength":6,"target":34963},{"buffer":0,"byteOffset":8,"byteLength":36,"target":34962}],"accessors":[{"bufferView":0,"byteOffset":0,"componentType":5123,"count":3,"type":"SCALAR","max":[2],"min":[0]},{"bufferView":1,"byteOffset":0,"componentType":5126,"count":3,"type":"VEC3","max":[1,1,0],"min":[0,0,0]}],"asset":{"version":"2.0"}}

View File

@ -0,0 +1 @@
{"scene":0,"scenes":[{"nodes":[0]}],"nodes":[{"mesh":0}],"meshes":[{"primitives":[{"attributes":{"POSITION":1},"indices":0}]}],"buffers":[{"uri":"data:application/gltf-buffer;base64,AAAIAAcAAAABAAgAAQAJAAgAAQACAAkAAgAKAAkAAgADAAoAAwALAAoAAwAEAAsABAAMAAsABAAFAAwABQANAAwABQAGAA0AAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAQAAAAAAAAAAAAABAQAAAAAAAAAAAAACAQAAAAAAAAAAAAACgQAAAAAAAAAAAAADAQAAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAQAAAgD8AAAAAAABAQAAAgD8AAAAAAACAQAAAgD8AAAAAAACgQAAAgD8AAAAAAADAQAAAgD8AAAAACAAKAAwAAAAAAIA/AAAAQAAAAAAAAEBAAABAQAAAAAAAAKBAAACAQAAAAAA=","byteLength":284}],"bufferViews":[{"buffer":0,"byteOffset":0,"byteLength":72,"target":34963},{"buffer":0,"byteOffset":72,"byteLength":168},{"buffer":0,"byteOffset":240,"byteLength":6},{"buffer":0,"byteOffset":248,"byteLength":36}],"accessors":[{"bufferView":0,"byteOffset":0,"componentType":5123,"count":36,"type":"SCALAR","max":[13],"min":[0]},{"bufferView":1,"byteOffset":0,"componentType":5126,"count":14,"type":"VEC3","max":[6,4,0],"min":[0,0,0],"sparse":{"count":3,"indices":{"bufferView":2,"byteOffset":0,"componentType":5123},"values":{"bufferView":3,"byteOffset":0}}}],"asset":{"version":"2.0"}}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"scene":0,"scenes":[{"nodes":[0]}],"nodes":[{"mesh":0}],"meshes":[{"primitives":[{"attributes":{"POSITION":1},"indices":0}]}],"buffers":[{"uri":"data:application/octet-stream;base64,AAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAA=","byteLength":80}],"bufferViews":[{"buffer":0,"byteOffset":0,"byteLength":6,"target":34963},{"buffer":0,"byteOffset":8,"byteLength":72,"byteStride":24,"target":34962}],"accessors":[{"bufferView":0,"byteOffset":0,"componentType":5123,"count":3,"type":"SCALAR","max":[2],"min":[0]},{"bufferView":1,"byteOffset":0,"componentType":5126,"count":3,"type":"VEC3","max":[1,1,0],"min":[0,0,0]}],"asset":{"version":"2.0"}}

View File

@ -0,0 +1 @@
{"scene":0,"scenes":[{"nodes":[0]}],"nodes":[{"mesh":0}],"meshes":[{"primitives":[{"attributes":{"POSITION":0}}]}],"buffers":[{"uri":"data:application/octet-stream;base64,AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAA","byteLength":36}],"bufferViews":[{"buffer":0,"byteOffset":0,"byteLength":36,"target":34962}],"accessors":[{"bufferView":0,"byteOffset":0,"componentType":5126,"count":3,"type":"VEC3","max":[1,1,0],"min":[0,0,0]}],"asset":{"version":"2.0"}}

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -1,4 +1,5 @@
dofile(minetest.get_modpath("testentities").."/visuals.lua") dofile(minetest.get_modpath("testentities").."/visuals.lua")
dofile(minetest.get_modpath("testentities").."/observers.lua")
dofile(minetest.get_modpath("testentities").."/selectionbox.lua") dofile(minetest.get_modpath("testentities").."/selectionbox.lua")
dofile(minetest.get_modpath("testentities").."/armor.lua") dofile(minetest.get_modpath("testentities").."/armor.lua")
dofile(minetest.get_modpath("testentities").."/pointable.lua") dofile(minetest.get_modpath("testentities").."/pointable.lua")

View File

@ -0,0 +1,7 @@
Original model by MirceaKitsune (CC BY-SA 3.0).
Various alterations and fixes by kilbith, sofar, xunto, Rogier-5, TeTpaAka, Desour,
stujones11, An0n3m0us (CC BY-SA 3.0):
testentities_sam.b3d
Jordach (CC BY-SA 3.0):
testentities_sam.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -0,0 +1,37 @@
local function player_names_excluding(exclude_player_name)
local player_names = {}
for _, player in ipairs(minetest.get_connected_players()) do
player_names[player:get_player_name()] = true
end
player_names[exclude_player_name] = nil
return player_names
end
minetest.register_entity("testentities:observable", {
initial_properties = {
visual = "sprite",
textures = { "testentities_sprite.png" },
static_save = false,
infotext = "Punch to set observers to anyone but you"
},
on_activate = function(self)
self.object:set_armor_groups({punch_operable = 1})
assert(self.object:get_observers() == nil)
-- Using a value of `false` in the table should error.
assert(not pcall(self.object, self.object.set_observers, self.object, {test = false}))
end,
on_punch = function(self, puncher)
local puncher_name = puncher:get_player_name()
local observers = player_names_excluding(puncher_name)
self.object:set_observers(observers)
local got_observers = self.object:get_observers()
for name in pairs(observers) do
assert(got_observers[name])
end
for name in pairs(got_observers) do
assert(observers[name])
end
self.object:set_properties({infotext = "Excluding " .. puncher_name})
return true
end
})

View File

@ -66,6 +66,19 @@ minetest.register_entity("testentities:mesh_unshaded", {
}, },
}) })
minetest.register_entity("testentities:sam", {
initial_properties = {
visual = "mesh",
mesh = "testentities_sam.b3d",
textures = {
"testentities_sam.png"
},
},
on_activate = function(self)
self.object:set_animation({x = 0, y = 219}, 30, 0, true)
end,
})
-- Advanced visual tests -- Advanced visual tests
-- An entity for testing animated and yaw-modulated sprites -- An entity for testing animated and yaw-modulated sprites

View File

@ -66,7 +66,7 @@ local inv_style_fs = [[
-- Some textures from textures/base/pack and Devtest, with many different sizes -- Some textures from textures/base/pack and Devtest, with many different sizes
-- and aspect ratios. -- and aspect ratios.
local image_column = "image,0=logo.png,1=rare_controls.png,2=checkbox_16.png," .. local image_column = "image,0=logo.png,1=crack_anylength.png^[invert:rgb,2=checkbox_16.png," ..
"3=checkbox_32.png,4=checkbox_64.png,5=default_lava.png," .. "3=checkbox_32.png,4=checkbox_64.png,5=default_lava.png," ..
"6=progress_bar.png,7=progress_bar_bg.png" "6=progress_bar.png,7=progress_bar_bg.png"
local words = { local words = {

View File

@ -1,18 +1,30 @@
local function show_fullscreen_fs(name) local function window_info_equal(a, b)
local window = minetest.get_player_window_information(name) return
if not window then -- size
return false, "Unable to get window info" a.size.x == b.size.x and a.size.y == b.size.y and
end -- real_gui_scaling, real_hud_scaling
a.real_gui_scaling == b.real_gui_scaling and
a.real_hud_scaling == b.real_hud_scaling and
-- max_formspec_size
a.max_formspec_size.x == b.max_formspec_size.x and
a.max_formspec_size.y == b.max_formspec_size.y and
-- touch_controls
a.touch_controls == b.touch_controls
end
local last_window_info = {}
local function show_fullscreen_fs(name, window)
print(dump(window)) print(dump(window))
local size = { x = window.max_formspec_size.x * 1.1, y = window.max_formspec_size.y * 1.1 } local size = window.max_formspec_size
local touch_text = window.touch_controls and "Touch controls enabled" or local touch_text = window.touch_controls and "Touch controls enabled" or
"Touch controls disabled" "Touch controls disabled"
local fs = { local fs = {
"formspec_version[4]", "formspec_version[4]",
("size[%f,%f]"):format(size.x, size.y), ("size[%f,%f]"):format(size.x, size.y),
"padding[-0.01,-0.01]", "padding[0,0]",
"bgcolor[;true]",
("button[%f,%f;1,1;%s;%s]"):format(0, 0, "tl", "TL"), ("button[%f,%f;1,1;%s;%s]"):format(0, 0, "tl", "TL"),
("button[%f,%f;1,1;%s;%s]"):format(size.x - 1, 0, "tr", "TR"), ("button[%f,%f;1,1;%s;%s]"):format(size.x - 1, 0, "tr", "TR"),
("button[%f,%f;1,1;%s;%s]"):format(size.x - 1, size.y - 1, "br", "BR"), ("button[%f,%f;1,1;%s;%s]"):format(size.x - 1, size.y - 1, "br", "BR"),
@ -23,10 +35,37 @@ local function show_fullscreen_fs(name)
} }
minetest.show_formspec(name, "testfullscreenfs:fs", table.concat(fs)) minetest.show_formspec(name, "testfullscreenfs:fs", table.concat(fs))
return true, ("Calculated size of %f, %f"):format(size.x, size.y) minetest.chat_send_player(name, ("Calculated size of %f, %f"):format(size.x, size.y))
last_window_info[name] = window
end end
minetest.register_chatcommand("testfullscreenfs", { minetest.register_chatcommand("testfullscreenfs", {
func = show_fullscreen_fs, func = function(name)
local window = minetest.get_player_window_information(name)
if not window then
return false, "Unable to get window info"
end
show_fullscreen_fs(name, window)
return true
end,
}) })
minetest.register_globalstep(function()
for name, last_window in pairs(last_window_info) do
local window = minetest.get_player_window_information(name)
if window and not window_info_equal(last_window, window) then
show_fullscreen_fs(name, window)
end
end
end)
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname == "testfullscreenfs:fs" and fields.quit then
last_window_info[player:get_player_name()] = nil
end
end)
minetest.register_on_leaveplayer(function(player)
last_window_info[player:get_player_name()] = nil
end)

View File

@ -208,9 +208,75 @@ minetest.register_chatcommand("zoomfov", {
end, end,
}) })
-- Hotbars
local hud_hotbar_defs = {
{
type = "hotbar",
position = {x=0.2, y=0.5},
direction = 0,
alignment = {x=1, y=-1},
},
{
type = "hotbar",
position = {x=0.2, y=0.5},
direction = 2,
alignment = {x=1, y=1},
},
{
type = "hotbar",
position = {x=0.7, y=0.5},
direction = 0,
offset = {x=140, y=20},
alignment = {x=-1, y=-1},
},
{
type = "hotbar",
position = {x=0.7, y=0.5},
direction = 2,
offset = {x=140, y=20},
alignment = {x=-1, y=1},
},
}
local player_hud_hotbars= {}
minetest.register_chatcommand("hudhotbars", {
description = "Shows some test Lua HUD elements of type hotbar. " ..
"(add: Adds elements (default). remove: Removes elements)",
params = "[ add | remove ]",
func = function(name, params)
local player = minetest.get_player_by_name(name)
if not player then
return false, "No player."
end
local id_table = player_hud_hotbars[name]
if not id_table then
id_table = {}
player_hud_hotbars[name] = id_table
end
if params == "remove" then
for _, id in ipairs(id_table) do
player:hud_remove(id)
end
return true, "Hotbars removed."
end
-- params == "add" or default
for _, def in ipairs(hud_hotbar_defs) do
table.insert(id_table, player:hud_add(def))
end
return true, #hud_hotbar_defs .." Hotbars added."
end
})
minetest.register_on_leaveplayer(function(player) minetest.register_on_leaveplayer(function(player)
player_font_huds[player:get_player_name()] = nil player_font_huds[player:get_player_name()] = nil
player_waypoints[player:get_player_name()] = nil player_waypoints[player:get_player_name()] = nil
player_hud_hotbars[player:get_player_name()] = nil
end) end)
minetest.register_chatcommand("hudprint", { minetest.register_chatcommand("hudprint", {
@ -232,3 +298,26 @@ minetest.register_chatcommand("hudprint", {
return true, s return true, s
end end
}) })
local hud_flags = {"hotbar", "healthbar", "crosshair", "wielditem", "breathbar",
"minimap", "minimap_radar", "basic_debug", "chat"}
minetest.register_chatcommand("hudtoggleflag", {
description = "Toggles a hud flag.",
params = "[ ".. table.concat(hud_flags, " | ") .." ]",
func = function(name, params)
local player = minetest.get_player_by_name(name)
if not player then
return false, "No player."
end
local flags = player:hud_get_flags()
if flags[params] == nil then
return false, "Unknown hud flag."
end
flags[params] = not flags[params]
player:hud_set_flags(flags)
return true, "Flag \"".. params .."\" set to ".. tostring(flags[params]) .. "."
end
})

View File

@ -89,10 +89,12 @@ for a=1,#alphas do
end end
minetest.register_node("testnodes:alpha_compositing", { minetest.register_node("testnodes:alpha_compositing", {
description = S("Alpha Compositing Test Node") .. "\n" .. description = S("Texture Overlay Test Node") .. "\n" ..
S("A regular grid should be visible where each cell contains two " .. S("A regular grid should be visible where each cell contains two " ..
"texels with the same colour.") .. "\n" .. "texels with the same color.") .. "\n" ..
S("Alpha compositing is gamma-incorrect for backwards compatibility."), S("Texture overlay is gamma-incorrect, " ..
"and in general it does not do alpha compositing, " ..
"both for backwards compatibility."),
drawtype = "glasslike", drawtype = "glasslike",
paramtype = "light", paramtype = "light",
tiles = {"testnodes_alpha_compositing_bottom.png^" .. tiles = {"testnodes_alpha_compositing_bottom.png^" ..

Binary file not shown.

Before

Width:  |  Height:  |  Size: 251 B

After

Width:  |  Height:  |  Size: 265 B

View File

@ -167,18 +167,18 @@ local function test_userdata_passing2(cb, _, pos)
end end
unittests.register("test_userdata_passing2", test_userdata_passing2, {map=true, async=true}) unittests.register("test_userdata_passing2", test_userdata_passing2, {map=true, async=true})
local function test_async_metatable_override() local function test_portable_metatable_override()
assert(pcall(core.register_async_metatable, "__builtin:vector", vector.metatable), assert(pcall(core.register_portable_metatable, "__builtin:vector", vector.metatable),
"Metatable name aliasing throws an error when it should be allowed") "Metatable name aliasing throws an error when it should be allowed")
assert(not pcall(core.register_async_metatable, "__builtin:vector", {}), assert(not pcall(core.register_portable_metatable, "__builtin:vector", {}),
"Illegal metatable overriding allowed") "Illegal metatable overriding allowed")
end end
unittests.register("test_async_metatable_override", test_async_metatable_override) unittests.register("test_portable_metatable_override", test_portable_metatable_override)
local function test_async_metatable_registration(cb) local function test_portable_metatable_registration(cb)
local custom_metatable = {} local custom_metatable = {}
core.register_async_metatable("unittests:custom_metatable", custom_metatable) core.register_portable_metatable("unittests:custom_metatable", custom_metatable)
core.handle_async(function(x) core.handle_async(function(x)
-- unittests.custom_metatable is registered in inside_async_env.lua -- unittests.custom_metatable is registered in inside_async_env.lua
@ -193,7 +193,7 @@ local function test_async_metatable_registration(cb)
cb() cb()
end, setmetatable({}, custom_metatable)) end, setmetatable({}, custom_metatable))
end end
unittests.register("test_async_metatable_registration", test_async_metatable_registration, {async=true}) unittests.register("test_portable_metatable_registration", test_portable_metatable_registration, {async=true})
local function test_vector_preserve(cb) local function test_vector_preserve(cb)
local vec = vector.new(1, 2, 3) local vec = vector.new(1, 2, 3)

View File

@ -0,0 +1,17 @@
local function assert_colors_equal(c1, c2)
if type(c1) == "table" and type(c2) == "table" then
assert(c1.r == c2.r and c1.g == c2.g and c1.b == c2.b and c1.a == c2.a)
else
assert(c1 == c2)
end
end
local function test_color_conversion()
assert_colors_equal(core.colorspec_to_table("#fff"), {r = 255, g = 255, b = 255, a = 255})
assert_colors_equal(core.colorspec_to_table(0xFF00FF00), {r = 0, g = 255, b = 0, a = 255})
assert_colors_equal(core.colorspec_to_table("#00000000"), {r = 0, g = 0, b = 0, a = 0})
assert_colors_equal(core.colorspec_to_table("green"), {r = 0, g = 128, b = 0, a = 255})
assert_colors_equal(core.colorspec_to_table("gren"), nil)
end
unittests.register("test_color_conversion", test_color_conversion)

View File

@ -40,12 +40,36 @@ core.register_entity("unittests:callbacks", {
end, end,
on_attach_child = function(self, child) on_attach_child = function(self, child)
insert_log("on_attach_child(%s)", objref_str(self, child)) insert_log("on_attach_child(%s)", objref_str(self, child))
assert(child:get_attach() == self.object)
local ok = false
for _, obj in ipairs(self.object:get_children()) do
if obj == child then
ok = true
end
end
assert(ok, "Child not found in get_children")
end, end,
on_detach_child = function(self, child) on_detach_child = function(self, child)
insert_log("on_detach_child(%s)", objref_str(self, child)) insert_log("on_detach_child(%s)", objref_str(self, child))
assert(child:get_attach() == nil)
local ok = true
for _, obj in ipairs(self.object:get_children()) do
if obj == child then
ok = false
end
end
assert(ok, "Former child found in get_children")
end, end,
on_detach = function(self, parent) on_detach = function(self, parent)
insert_log("on_detach(%s)", objref_str(self, parent)) insert_log("on_detach(%s)", objref_str(self, parent))
assert(self.object:get_attach() == nil)
local ok = true
for _, obj in ipairs(parent:get_children()) do
if obj == self.object then
ok = false
end
end
assert(ok, "Former child found in get_children")
end, end,
get_staticdata = function(self) get_staticdata = function(self)
assert(false) assert(false)
@ -118,19 +142,25 @@ local function test_entity_attach(player, pos)
-- attach player to entity -- attach player to entity
player:set_attach(obj) player:set_attach(obj)
check_log({"on_attach_child(player)"}) check_log({"on_attach_child(player)"})
assert(player:get_attach() == obj)
player:set_detach() player:set_detach()
check_log({"on_detach_child(player)"}) check_log({"on_detach_child(player)"})
assert(player:get_attach() == nil)
-- attach entity to player -- attach entity to player
obj:set_attach(player) obj:set_attach(player)
check_log({}) check_log({})
assert(obj:get_attach() == player)
obj:set_detach() obj:set_detach()
check_log({"on_detach(player)"}) check_log({"on_detach(player)"})
assert(obj:get_attach() == nil)
obj:remove() obj:remove()
end end
unittests.register("test_entity_attach", test_entity_attach, {player=true, map=true}) unittests.register("test_entity_attach", test_entity_attach, {player=true, map=true})
---------
core.register_entity("unittests:dummy", { core.register_entity("unittests:dummy", {
initial_properties = { initial_properties = {
hp_max = 1, hp_max = 1,
@ -184,3 +214,23 @@ unittests.register("test_objects_in_area", function(_, pos)
return core.objects_in_area(pos:offset(-1, -1, -1), pos:offset(1, 1, 1)) return core.objects_in_area(pos:offset(-1, -1, -1), pos:offset(1, 1, 1))
end) end)
end, {map=true}) end, {map=true})
-- Tests that bone rotation euler angles are preserved (see #14992)
local function test_get_bone_rot(_, pos)
local obj = core.add_entity(pos, "unittests:dummy")
for _ = 1, 100 do
local function assert_similar(euler_angles)
local _, rot = obj:get_bone_position("bonename")
assert(euler_angles:distance(rot) < 1e-3)
local override = obj:get_bone_override("bonename")
assert(euler_angles:distance(override.rotation.vec:apply(math.deg)) < 1e-3)
end
local deg = 1e3 * vector.new(math.random(), math.random(), math.random())
obj:set_bone_position("bonename", vector.zero(), deg)
assert_similar(deg)
local rad = 3 * math.pi * vector.new(math.random(), math.random(), math.random())
obj:set_bone_override("bonename", {rotation = {vec = rad}})
assert_similar(rad:apply(math.deg))
end
end
unittests.register("test_get_bone_rot", test_get_bone_rot, {map=true})

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