Merged Minetest

master
Elias Fleckenstein 2020-11-28 13:48:33 +01:00
commit eb6aca8b4a
315 changed files with 9306 additions and 8202 deletions

View File

@ -43,6 +43,12 @@ Contributions are welcome! Here's how you can help:
4. The code's interfaces are well designed, regardless of other aspects that might need more work in the future. 4. The code's interfaces are well designed, regardless of other aspects that might need more work in the future.
5. It uses protocols and formats which include the required compatibility. 5. It uses protocols and formats which include the required compatibility.
### Important note about automated GitHub checks
When you submit a pull request, GitHub automatically runs checks on the Minetest Engine combined with your changes. One of these checks is called 'cpp lint / clang format', which checks code formatting. Because formatting for readability requires human judgement this check often fails and often makes unsuitable formatting requests which make code readability worse.
If this check fails, look at the details to check for any clear mistakes and correct those. However, you should not apply everything ClangFormat requests. Ignore requests that make code readability worse and any other clearly unsuitable requests. Discuss in the pull request with a core developer about how to progress.
## Issues ## Issues
If you experience an issue, we would like to know the details - especially when a stable release is on the way. If you experience an issue, we would like to know the details - especially when a stable release is on the way.

42
.github/workflows/android.yml vendored Normal file
View File

@ -0,0 +1,42 @@
name: android
# build on c/cpp changes or workflow changes
on:
push:
paths:
- 'lib/**.[ch]'
- 'lib/**.cpp'
- 'src/**.[ch]'
- 'src/**.cpp'
- 'build/android/**'
- '.github/workflows/android.yml'
pull_request:
paths:
- 'lib/**.[ch]'
- 'lib/**.cpp'
- 'src/**.[ch]'
- 'src/**.cpp'
- 'build/android/**'
- '.github/workflows/android.yml'
jobs:
build:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Build with Gradle
run: cd build/android; ./gradlew assemblerelease
- name: Save armeabi artifact
uses: actions/upload-artifact@v2
with:
name: Minetest-armeabi-v7a.apk
path: build/android/app/build/outputs/apk/release/app-armeabi-v7a-release-unsigned.apk
- name: Save arm64 artifact
uses: actions/upload-artifact@v2
with:
name: Minetest-arm64-v8a.apk
path: build/android/app/build/outputs/apk/release/app-arm64-v8a-release-unsigned.apk

View File

@ -221,8 +221,8 @@ jobs:
name: VS 2019 ${{ matrix.config.arch }}-${{ matrix.type }} name: VS 2019 ${{ matrix.config.arch }}-${{ matrix.type }}
runs-on: windows-2019 runs-on: windows-2019
env: env:
VCPKG_VERSION: c7ab9d3110813979a873b2dbac630a9ab79850dc VCPKG_VERSION: 0bf3923f9fab4001c00f0f429682a0853b5749e0
# 2020.04 # 2020.11
vcpkg_packages: irrlicht zlib curl[winssl] openal-soft libvorbis libogg sqlite3 freetype luajit vcpkg_packages: irrlicht zlib curl[winssl] openal-soft libvorbis libogg sqlite3 freetype luajit
strategy: strategy:
fail-fast: false fail-fast: false
@ -248,7 +248,7 @@ jobs:
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Restore from cache and run vcpkg - name: Restore from cache and run vcpkg
uses: lukka/run-vcpkg@v2 uses: lukka/run-vcpkg@v5
with: with:
vcpkgArguments: ${{env.vcpkg_packages}} vcpkgArguments: ${{env.vcpkg_packages}}
vcpkgDirectory: '${{ github.workspace }}\vcpkg' vcpkgDirectory: '${{ github.workspace }}\vcpkg'

View File

@ -36,7 +36,7 @@ variables:
- cp misc/debpkg-control build/deb/minetest/DEBIAN/control - cp misc/debpkg-control build/deb/minetest/DEBIAN/control
- cp -Rp artifact/minetest/usr build/deb/minetest/ - cp -Rp artifact/minetest/usr build/deb/minetest/
script: script:
- git clone $MINETEST_GAME_REPO build/deb/minetest/usr/share/minetest/games/minetest - git clone $MINETEST_GAME_REPO build/deb/minetest/usr/share/minetest/games/minetest_game
- rm -Rf build/deb/minetest/usr/share/minetest/games/minetest/.git - rm -Rf build/deb/minetest/usr/share/minetest/games/minetest/.git
- sed -i 's/DATEPLACEHOLDER/'$(date +%y.%m.%d)'/g' build/deb/minetest/DEBIAN/control - sed -i 's/DATEPLACEHOLDER/'$(date +%y.%m.%d)'/g' build/deb/minetest/DEBIAN/control
- sed -i 's/LEVELDB_PLACEHOLDER/'$LEVELDB_PKG'/g' build/deb/minetest/DEBIAN/control - sed -i 's/LEVELDB_PLACEHOLDER/'$LEVELDB_PKG'/g' build/deb/minetest/DEBIAN/control
@ -142,36 +142,6 @@ deploy:debian-10:
## Ubuntu ## Ubuntu
## ##
# Trusty
build:ubuntu-14.04:
extends: .build_template
image: ubuntu:trusty
before_script:
- echo "deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu trusty main" > /etc/apt/sources.list.d/uptodate-toolchain.list
- apt-key adv --keyserver keyserver.ubuntu.com --recv BA9EF27F
- apt-get update -y
- apt-get -y install build-essential gcc-6 g++-6 libirrlicht-dev cmake libbz2-dev libpng-dev libjpeg-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev libjsoncpp-dev
variables:
CC: gcc-6
CXX: g++-6
package:ubuntu-14.04:
extends: .debpkg_template
image: ubuntu:trusty
dependencies:
- build:ubuntu-14.04
variables:
LEVELDB_PKG: libleveldb1
deploy:ubuntu-14.04:
extends: .debpkg_install
image: ubuntu:trusty
dependencies:
- package:ubuntu-14.04
variables:
LEVELDB_PKG: libleveldb1
# Xenial # Xenial
build:ubuntu-16.04: build:ubuntu-16.04:
@ -197,6 +167,31 @@ deploy:ubuntu-16.04:
variables: variables:
LEVELDB_PKG: libleveldb1v5 LEVELDB_PKG: libleveldb1v5
# Bionic
build:ubuntu-18.04:
extends: .build_template
image: ubuntu:bionic
before_script:
- apt-get update -y
- apt-get -y install build-essential libirrlicht-dev cmake libbz2-dev libpng-dev libjpeg-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev libjsoncpp-dev
package:ubuntu-18.04:
extends: .debpkg_template
image: ubuntu:bionic
dependencies:
- build:ubuntu-18.04
variables:
LEVELDB_PKG: libleveldb1v5
deploy:ubuntu-18.04:
extends: .debpkg_install
image: ubuntu:bionic
dependencies:
- package:ubuntu-18.04
variables:
LEVELDB_PKG: libleveldb1v5
## ##
## Fedora ## Fedora
## ##
@ -308,3 +303,28 @@ pages:
only: only:
- master - master
package:appimage-client:
stage: package
image: appimagecrafters/appimage-builder
dependencies:
- build:ubuntu-18.04
before_script:
- apt-get update -y
- apt-get install -y git wget
# Collect files
- mkdir AppDir
- cp -a artifact/minetest/usr/ AppDir/usr/
- rm AppDir/usr/bin/minetestserver
- cp -R clientmods AppDir/usr/share/minetest
script:
- git clone $MINETEST_GAME_REPO AppDir/usr/share/minetest/games/minetest_game
- rm -Rf AppDir/usr/share/minetest/games/minetest/.git
- export VERSION=$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA
# Remove PrefersNonDefaultGPU property due to validation errors
- sed -i '/PrefersNonDefaultGPU/d' AppDir/usr/share/applications/net.minetest.minetest.desktop
- appimage-builder --skip-test
artifacts:
when: on_success
expire_in: 90 day
paths:
- ./*.AppImage

View File

@ -72,3 +72,11 @@ files["builtin/mainmenu"] = {
"PLATFORM", "PLATFORM",
}, },
} }
files["builtin/common/tests"] = {
read_globals = {
"describe",
"it",
"assert",
},
}

51
AppImageBuilder.yml Normal file
View File

@ -0,0 +1,51 @@
version: 1
AppDir:
path: ./AppDir
app_info:
id: minetest
name: Minetest
icon: minetest
version: !ENV ${VERSION}
exec: usr/bin/minetest
exec_args: $@
runtime:
env:
APPDIR_LIBRARY_PATH: $APPDIR/usr/lib/x86_64-linux-gnu
apt:
arch: amd64
sources:
- sourceline: deb http://archive.ubuntu.com/ubuntu/ bionic main universe
key_url: 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x3b4fe6acc0b21f32'
- sourceline: deb http://archive.ubuntu.com/ubuntu/ bionic-updates main universe
- sourceline: deb http://archive.ubuntu.com/ubuntu/ bionic-backports main universe
- sourceline: deb http://archive.ubuntu.com/ubuntu/ bionic-security main universe
include:
- libirrlicht1.8
- libxxf86vm1
- libgl1-mesa-glx
- libsqlite3-0
- libogg0
- libvorbis0a
- libopenal1
- libcurl3-gnutls
- libfreetype6
- zlib1g
- libgmp10
- libjsoncpp1
files:
exclude:
- usr/share/man
- usr/share/doc/*/README.*
- usr/share/doc/*/changelog.*
- usr/share/doc/*/NEWS.*
- usr/share/doc/*/TODO.*
AppImage:
update-information: None
sign-key: None
arch: x86_64

View File

@ -249,15 +249,15 @@ cpack_add_component(Docs
cpack_add_component(SUBGAME_MINETEST_GAME cpack_add_component(SUBGAME_MINETEST_GAME
DISPLAY_NAME "Minetest Game" DISPLAY_NAME "Minetest Game"
DESCRIPTION "The official subgame for the Minetest engine, that can easily extended by mods." DESCRIPTION "The default game bundled in the Minetest engine. Mainly used as a modding base."
GROUP "Subgames" GROUP "Games"
) )
cpack_add_component(SUBGAME_MINIMAL cpack_add_component(SUBGAME_MINIMAL
DISPLAY_NAME "Development Test" DISPLAY_NAME "Development Test"
DESCRIPTION "A minimal test game helping to develop the engine." DESCRIPTION "A basic testing environment used for engine development and sometimes for testing mods."
DISABLED #DISABLED does not mean it is disabled, and is just not selected by default. DISABLED #DISABLED does not mean it is disabled, and is just not selected by default.
GROUP "Subgames" GROUP "Games"
) )
cpack_add_component_group(Subgames cpack_add_component_group(Subgames

View File

@ -21,7 +21,7 @@ WORKDIR /usr/src/minetest
RUN apk add --no-cache git build-base irrlicht-dev cmake bzip2-dev libpng-dev \ RUN apk add --no-cache git build-base irrlicht-dev cmake bzip2-dev libpng-dev \
jpeg-dev libxxf86vm-dev mesa-dev sqlite-dev libogg-dev \ jpeg-dev libxxf86vm-dev mesa-dev sqlite-dev libogg-dev \
libvorbis-dev openal-soft-dev curl-dev freetype-dev zlib-dev \ libvorbis-dev openal-soft-dev curl-dev freetype-dev zlib-dev \
gmp-dev jsoncpp-dev postgresql-dev ca-certificates && \ gmp-dev jsoncpp-dev postgresql-dev luajit-dev ca-certificates && \
git clone --depth=1 -b ${MINETEST_GAME_VERSION} https://github.com/minetest/minetest_game.git ./games/minetest_game && \ git clone --depth=1 -b ${MINETEST_GAME_VERSION} https://github.com/minetest/minetest_game.git ./games/minetest_game && \
rm -fr ./games/minetest_game/.git rm -fr ./games/minetest_game/.git
@ -51,7 +51,7 @@ RUN mkdir build && \
FROM alpine:3.11 FROM alpine:3.11
RUN apk add --no-cache sqlite-libs curl gmp libstdc++ libgcc libpq && \ RUN apk add --no-cache sqlite-libs curl gmp libstdc++ libgcc libpq luajit && \
adduser -D minetest --uid 30000 -h /var/lib/minetest && \ adduser -D minetest --uid 30000 -h /var/lib/minetest && \
chown -R minetest:minetest /var/lib/minetest chown -R minetest:minetest /var/lib/minetest

View File

@ -314,13 +314,14 @@ 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 irrlicht zlib curl[winssl] openal-soft libvorbis libogg sqlite3 freetype luajit --triplet x64-windows vcpkg install irrlicht zlib curl[winssl] openal-soft libvorbis libogg sqlite3 freetype luajit gmp jsoncpp --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.
- `openal-soft`, `libvorbis` and `libogg` are optional, but required to use sound. - `openal-soft`, `libvorbis` and `libogg` are optional, but required to use sound.
- `freetype` is optional, it allows true-type font rendering. - `freetype` is optional, it allows true-type font rendering.
- `luajit` is optional, it replaces the integrated Lua interpreter with a faster just-in-time interpreter. - `luajit` is optional, it replaces the integrated Lua interpreter with a faster just-in-time interpreter.
- `gmp` and `jsoncpp` are optional, otherwise the bundled versions will be compiled
There are other optional libraries, but they are not tested if they can build and link correctly. There are other optional libraries, but they are not tested if they can build and link correctly.
@ -353,7 +354,7 @@ This is outdated and not recommended. Follow the instructions on https://dev.min
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=0 -DENABLE_CURSES=0 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 -DENABLE_SYSTEM_JSONCPP=ON
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,8 +1,8 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
android { android {
compileSdkVersion 29 compileSdkVersion 29
buildToolsVersion '29.0.3' buildToolsVersion '30.0.2'
ndkVersion '21.1.6352462' ndkVersion '21.3.6528147'
defaultConfig { defaultConfig {
applicationId 'net.minetest.minetest' applicationId 'net.minetest.minetest'
minSdkVersion 16 minSdkVersion 16
@ -11,8 +11,11 @@ android {
versionCode project.versionCode versionCode project.versionCode
} }
// load properties
Properties props = new Properties() Properties props = new Properties()
props.load(new FileInputStream(file('../local.properties'))) def propfile = file('../local.properties')
if (propfile.exists())
props.load(new FileInputStream(propfile))
if (props.getProperty('keystore') != null) { if (props.getProperty('keystore') != null) {
signingConfigs { signingConfigs {
@ -61,10 +64,9 @@ task prepareAssets() {
copy { copy {
from "${projRoot}/builtin" into "${assetsFolder}/builtin" from "${projRoot}/builtin" into "${assetsFolder}/builtin"
} }
/*copy { copy {
// ToDo: fix Minetest shaders that currently don't work with OpenGL ES
from "${projRoot}/client/shaders" into "${assetsFolder}/client/shaders" from "${projRoot}/client/shaders" into "${assetsFolder}/client/shaders"
}*/ }
copy { copy {
from "../native/deps/Android/Irrlicht/shaders" into "${assetsFolder}/client/shaders/Irrlicht" from "../native/deps/Android/Irrlicht/shaders" into "${assetsFolder}/client/shaders/Irrlicht"
} }
@ -107,5 +109,5 @@ android.applicationVariants.all { variant ->
dependencies { dependencies {
implementation project(':native') implementation project(':native')
implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.appcompat:appcompat:1.2.0'
} }

View File

@ -17,8 +17,8 @@
android:allowBackup="false" android:allowBackup="false"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/label" android:label="@string/label"
android:resizeableActivity="false"
android:requestLegacyExternalStorage="true" android:requestLegacyExternalStorage="true"
android:resizeableActivity="false"
tools:ignore="UnusedAttribute"> tools:ignore="UnusedAttribute">
<meta-data <meta-data
@ -53,11 +53,6 @@
android:value="Minetest" /> android:value="Minetest" />
</activity> </activity>
<activity
android:name=".InputDialogActivity"
android:maxAspectRatio="3.0"
android:theme="@style/InputTheme" />
<service <service
android:name=".UnzipService" android:name=".UnzipService"
android:enabled="true" android:enabled="true"

View File

@ -0,0 +1,45 @@
/*
Minetest
Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik <MoNTE48@mail.ua>
Copyright (C) 2014-2020 ubulem, Bektur Mambetov <berkut87@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package net.minetest.minetest;
import android.content.Context;
import android.view.KeyEvent;
import android.view.inputmethod.InputMethodManager;
import androidx.appcompat.widget.AppCompatEditText;
import java.util.Objects;
public class CustomEditText extends AppCompatEditText {
public CustomEditText(Context context) {
super(context);
}
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
InputMethodManager mgr = (InputMethodManager)
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
Objects.requireNonNull(mgr).hideSoftInputFromWindow(this.getWindowToken(), 0);
}
return false;
}
}

View File

@ -25,8 +25,16 @@ import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.text.InputType;
import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.view.WindowManager; import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import androidx.appcompat.app.AlertDialog;
import java.util.Objects;
public class GameActivity extends NativeActivity { public class GameActivity extends NativeActivity {
static { static {
@ -34,8 +42,8 @@ public class GameActivity extends NativeActivity {
System.loadLibrary("Minetest"); System.loadLibrary("Minetest");
} }
private int messageReturnCode; private int messageReturnCode = -1;
private String messageReturnValue; private String messageReturnValue = "";
public static native void putMessageBoxResult(String text); public static native void putMessageBoxResult(String text);
@ -43,8 +51,6 @@ public class GameActivity extends NativeActivity {
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
messageReturnCode = -1;
messageReturnValue = "";
} }
private void makeFullScreen() { private void makeFullScreen() {
@ -73,29 +79,46 @@ public class GameActivity extends NativeActivity {
// Ignore the back press so Minetest can handle it // Ignore the back press so Minetest can handle it
} }
@Override public void showDialog(String acceptButton, String hint, String current, int editType) {
protected void onActivityResult(int requestCode, int resultCode, Intent data) { runOnUiThread(() -> showDialogUI(hint, current, editType));
if (requestCode == 101) {
if (resultCode == RESULT_OK) {
String text = data.getStringExtra("text");
messageReturnCode = 0;
messageReturnValue = text;
} else
messageReturnCode = 1;
}
} }
public void showDialog(String acceptButton, String hint, String current, int editType) { private void showDialogUI(String hint, String current, int editType) {
Intent intent = new Intent(this, InputDialogActivity.class); final AlertDialog.Builder builder = new AlertDialog.Builder(this);
Bundle params = new Bundle(); EditText editText = new CustomEditText(this);
params.putString("acceptButton", acceptButton); builder.setView(editText);
params.putString("hint", hint); AlertDialog alertDialog = builder.create();
params.putString("current", current); editText.requestFocus();
params.putInt("editType", editType); editText.setHint(hint);
intent.putExtras(params); editText.setText(current);
startActivityForResult(intent, 101); final InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
messageReturnValue = ""; Objects.requireNonNull(imm).toggleSoftInput(InputMethodManager.SHOW_FORCED,
messageReturnCode = -1; InputMethodManager.HIDE_IMPLICIT_ONLY);
if (editType == 1)
editText.setInputType(InputType.TYPE_CLASS_TEXT |
InputType.TYPE_TEXT_FLAG_MULTI_LINE);
else if (editType == 3)
editText.setInputType(InputType.TYPE_CLASS_TEXT |
InputType.TYPE_TEXT_VARIATION_PASSWORD);
else
editText.setInputType(InputType.TYPE_CLASS_TEXT);
editText.setSelection(editText.getText().length());
editText.setOnKeyListener((view, KeyCode, event) -> {
if (KeyCode == KeyEvent.KEYCODE_ENTER) {
imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
messageReturnCode = 0;
messageReturnValue = editText.getText().toString();
alertDialog.dismiss();
return true;
}
return false;
});
alertDialog.show();
alertDialog.setOnCancelListener(dialog -> {
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
messageReturnValue = current;
messageReturnCode = -1;
});
} }
public int getDialogState() { public int getDialogState() {

View File

@ -1,98 +0,0 @@
/*
Minetest
Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik <MoNTE48@mail.ua>
Copyright (C) 2014-2020 ubulem, Bektur Mambetov <berkut87@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package net.minetest.minetest;
import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.text.InputType;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import java.util.Objects;
public class InputDialogActivity extends AppCompatActivity {
private AlertDialog alertDialog;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle b = getIntent().getExtras();
int editType = Objects.requireNonNull(b).getInt("editType");
String hint = b.getString("hint");
String current = b.getString("current");
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
EditText editText = new EditText(this);
builder.setView(editText);
editText.requestFocus();
editText.setHint(hint);
editText.setText(current);
final InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
Objects.requireNonNull(imm).toggleSoftInput(InputMethodManager.SHOW_FORCED,
InputMethodManager.HIDE_IMPLICIT_ONLY);
if (editType == 3)
editText.setInputType(InputType.TYPE_CLASS_TEXT |
InputType.TYPE_TEXT_VARIATION_PASSWORD);
else
editText.setInputType(InputType.TYPE_CLASS_TEXT);
editText.setOnKeyListener((view, KeyCode, event) -> {
if (KeyCode == KeyEvent.KEYCODE_ENTER) {
imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
pushResult(editText.getText().toString());
return true;
}
return false;
});
alertDialog = builder.create();
if (!this.isFinishing())
alertDialog.show();
alertDialog.setOnCancelListener(dialog -> {
pushResult(editText.getText().toString());
setResult(Activity.RESULT_CANCELED);
alertDialog.dismiss();
makeFullScreen();
finish();
});
}
private void pushResult(String text) {
Intent resultData = new Intent();
resultData.putExtra("text", text);
setResult(AppCompatActivity.RESULT_OK, resultData);
alertDialog.dismiss();
makeFullScreen();
finish();
}
private void makeFullScreen() {
if (Build.VERSION.SDK_INT >= 19)
this.getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
}

View File

@ -8,15 +8,8 @@
<item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="p">shortEdges</item> <item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="p">shortEdges</item>
</style> </style>
<style name="InputTheme" parent="Theme.AppCompat.DayNight.Dialog"> <style name="CustomProgressBar" parent="Widget.AppCompat.ProgressBar.Horizontal">
<item name="windowNoTitle">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
</style>
<style name="CustomProgressBar" parent="@style/Widget.AppCompat.ProgressBar.Horizontal">
<item name="android:indeterminateOnly">false</item> <item name="android:indeterminateOnly">false</item>
<item name="android:minHeight">10dip</item>
<item name="android:maxHeight">20dip</item>
</style> </style>
</resources> </resources>

View File

@ -15,8 +15,8 @@ buildscript {
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.6.3' classpath 'com.android.tools.build:gradle:4.0.1'
classpath 'org.ajoberstar.grgit:grgit-gradle:4.0.2' 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
} }
@ -31,4 +31,5 @@ allprojects {
task clean(type: Delete) { task clean(type: Delete) {
delete rootProject.buildDir delete rootProject.buildDir
delete 'native/deps'
} }

View File

@ -1,2 +1,6 @@
#Mon Apr 06 00:06:16 CEST 2020 #Mon Sep 07 22:11:10 CEST 2020
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-all.zip

View File

@ -1,16 +1,16 @@
apply plugin: 'com.android.library' apply plugin: 'com.android.library'
import org.ajoberstar.grgit.Grgit apply plugin: 'de.undercouch.download'
android { android {
compileSdkVersion 29 compileSdkVersion 29
buildToolsVersion '29.0.3' buildToolsVersion '30.0.2'
ndkVersion '21.1.6352462' ndkVersion '21.3.6528147'
defaultConfig { defaultConfig {
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 29 targetSdkVersion 29
externalNativeBuild { externalNativeBuild {
ndkBuild { ndkBuild {
arguments '-j8', arguments '-j' + Runtime.getRuntime().availableProcessors(),
"versionMajor=${versionMajor}", "versionMajor=${versionMajor}",
"versionMinor=${versionMinor}", "versionMinor=${versionMinor}",
"versionPatch=${versionPatch}", "versionPatch=${versionPatch}",
@ -45,15 +45,54 @@ android {
} }
} }
task cloneGitRepo() { // get precompiled deps
def destination = file('deps') def folder = 'minetest_android_deps_binaries'
if(!destination.exists()) {
def grgit = Grgit.clone( task downloadDeps(type: Download) {
dir: destination, src 'https://github.com/minetest/' + folder + '/archive/master.zip'
uri: 'https://github.com/minetest/minetest_android_deps_binaries' dest new File(buildDir, 'deps.zip')
) overwrite false
grgit.close() }
task getDeps(dependsOn: downloadDeps, type: Copy) {
def deps = file('deps')
def f = file("$buildDir/" + folder + "-master")
if (!deps.exists() && !f.exists()) {
from zipTree(downloadDeps.dest)
into buildDir
}
doLast {
if (!deps.exists()) {
file(f).renameTo(file(deps))
}
} }
} }
preBuild.dependsOn cloneGitRepo // get sqlite
def sqlite_ver = '3320200'
task downloadSqlite(dependsOn: getDeps, type: Download) {
src 'https://www.sqlite.org/2020/sqlite-amalgamation-' + sqlite_ver + '.zip'
dest new File(buildDir, 'sqlite.zip')
overwrite false
}
task getSqlite(dependsOn: downloadSqlite, type: Copy) {
def sqlite = file('deps/Android/sqlite')
def f = file("$buildDir/sqlite-amalgamation-" + sqlite_ver)
if (!sqlite.exists() && !f.exists()) {
from zipTree(downloadSqlite.dest)
into buildDir
}
doLast {
if (!sqlite.exists()) {
file(f).renameTo(file(sqlite))
}
}
}
preBuild.dependsOn getDeps
preBuild.dependsOn getSqlite

View File

@ -22,6 +22,11 @@ core.register_on_sending_chat_message(function(message)
return true return true
end end
-- Run core.registered_on_chatcommand callbacks.
if core.run_callbacks(core.registered_on_chatcommand, 5, cmd, param) then
return true
end
local cmd_def = core.registered_chatcommands[cmd] local cmd_def = core.registered_chatcommands[cmd]
if cmd_def then if cmd_def then
core.set_last_run_mod(cmd_def.mod_origin) core.set_last_run_mod(cmd_def.mod_origin)

View File

@ -4,6 +4,13 @@ core.callback_origins = {}
local getinfo = debug.getinfo local getinfo = debug.getinfo
debug.getinfo = nil debug.getinfo = nil
--- Runs given callbacks.
--
-- Note: this function is also called from C++
-- @tparam table callbacks a table with registered callbacks, like `core.registered_on_*`
-- @tparam number mode a RunCallbacksMode, as defined in src/script/common/c_internal.h
-- @param ... arguments for the callback
-- @return depends on mode
function core.run_callbacks(callbacks, mode, ...) function core.run_callbacks(callbacks, mode, ...)
assert(type(callbacks) == "table") assert(type(callbacks) == "table")
local cb_len = #callbacks local cb_len = #callbacks
@ -83,6 +90,7 @@ core.registered_on_mods_loaded, core.register_on_mods_loaded = make_registration
core.registered_on_shutdown, core.register_on_shutdown = make_registration() core.registered_on_shutdown, core.register_on_shutdown = make_registration()
core.registered_on_receiving_chat_message, core.register_on_receiving_chat_message = make_registration() core.registered_on_receiving_chat_message, core.register_on_receiving_chat_message = make_registration()
core.registered_on_sending_chat_message, core.register_on_sending_chat_message = make_registration() core.registered_on_sending_chat_message, core.register_on_sending_chat_message = make_registration()
core.registered_on_chatcommand, core.register_on_chatcommand = make_registration()
core.registered_on_death, core.register_on_death = make_registration() core.registered_on_death, core.register_on_death = make_registration()
core.registered_on_hp_modification, core.register_on_hp_modification = make_registration() core.registered_on_hp_modification, core.register_on_hp_modification = make_registration()
core.registered_on_damage_taken, core.register_on_damage_taken = make_registration() core.registered_on_damage_taken, core.register_on_damage_taken = make_registration()

View File

@ -31,11 +31,13 @@ function core.after(after, func, ...)
assert(tonumber(after) and type(func) == "function", assert(tonumber(after) and type(func) == "function",
"Invalid minetest.after invocation") "Invalid minetest.after invocation")
local expire = time + after local expire = time + after
jobs[#jobs + 1] = { local new_job = {
func = func, func = func,
expire = expire, expire = expire,
arg = {...}, arg = {...},
mod_origin = core.get_last_run_mod() mod_origin = core.get_last_run_mod(),
} }
jobs[#jobs + 1] = new_job
time_next = math.min(time_next, expire) time_next = math.min(time_next, expire)
return { cancel = function() new_job.func = function() end end }
end end

View File

@ -44,6 +44,10 @@ describe("vector", function()
assert.same({ x = 2, y = 4, z = 6 }, vector.add(vector.new(1, 2, 3), { x = 1, y = 2, z = 3 })) assert.same({ x = 2, y = 4, z = 6 }, vector.add(vector.new(1, 2, 3), { x = 1, y = 2, z = 3 }))
end) end)
it("offset()", function()
assert.same({ x = 41, y = 52, z = 63 }, vector.offset(vector.new(1, 2, 3), 40, 50, 60))
end)
-- This function is needed because of floating point imprecision. -- This function is needed because of floating point imprecision.
local function almost_equal(a, b) local function almost_equal(a, b)
if type(a) == "number" then if type(a) == "number" then

View File

@ -137,6 +137,12 @@ function vector.divide(a, b)
end end
end end
function vector.offset(v, x, y, z)
return {x = v.x + x,
y = v.y + y,
z = v.z + z}
end
function vector.sort(a, b) function vector.sort(a, b)
return {x = math.min(a.x, b.x), y = math.min(a.y, b.y), z = math.min(a.z, b.z)}, return {x = math.min(a.x, b.x), y = math.min(a.y, b.y), z = math.min(a.z, b.z)},
{x = math.max(a.x, b.x), y = math.max(a.y, b.y), z = math.max(a.z, b.z)} {x = math.max(a.x, b.x), y = math.max(a.y, b.y), z = math.max(a.z, b.z)}

View File

@ -64,6 +64,7 @@ function ui.update()
formspec = { formspec = {
"size[14,8]", "size[14,8]",
"real_coordinates[true]", "real_coordinates[true]",
"set_focus[btn_reconnect_yes;true]",
"box[0.5,1.2;13,5;#000]", "box[0.5,1.2;13,5;#000]",
("textarea[0.5,1.2;13,5;;%s;%s]"):format( ("textarea[0.5,1.2;13,5;;%s;%s]"):format(
fgettext("The server has requested a reconnect:"), error_message), fgettext("The server has requested a reconnect:"), error_message),
@ -82,6 +83,7 @@ function ui.update()
formspec = { formspec = {
"size[14,8]", "size[14,8]",
"real_coordinates[true]", "real_coordinates[true]",
"set_focus[btn_error_confirm;true]",
"box[0.5,1.2;13,5;#000]", "box[0.5,1.2;13,5;#000]",
("textarea[0.5,1.2;13,5;;%s;%s]"):format( ("textarea[0.5,1.2;13,5;;%s;%s]"):format(
error_title, error_message), error_title, error_message),

View File

@ -58,6 +58,11 @@ core.register_on_chat_message(function(name, message)
param = param or "" param = param or ""
-- Run core.registered_on_chatcommands callbacks.
if core.run_callbacks(core.registered_on_chatcommands, 5, name, cmd, param) then
return true
end
local cmd_def = core.registered_chatcommands[cmd] local cmd_def = core.registered_chatcommands[cmd]
if not cmd_def then if not cmd_def then
core.chat_send_player(name, "-!- Invalid command: " .. cmd) core.chat_send_player(name, "-!- Invalid command: " .. cmd)
@ -66,8 +71,17 @@ core.register_on_chat_message(function(name, message)
local has_privs, missing_privs = core.check_player_privs(name, cmd_def.privs) local has_privs, missing_privs = core.check_player_privs(name, cmd_def.privs)
if has_privs then if has_privs then
core.set_last_run_mod(cmd_def.mod_origin) core.set_last_run_mod(cmd_def.mod_origin)
local _, result = cmd_def.func(name, param) local success, result = cmd_def.func(name, param)
if result then if success == false and result == nil then
core.chat_send_player(name, "-!- Invalid command usage")
local help_def = core.registered_chatcommands["help"]
if help_def then
local _, helpmsg = help_def.func(name, cmd)
if helpmsg then
core.chat_send_player(name, helpmsg)
end
end
elseif result then
core.chat_send_player(name, result) core.chat_send_player(name, result)
end end
else else
@ -1070,10 +1084,10 @@ core.register_chatcommand("last-login", {
local pauth = core.get_auth_handler().get_auth(param) local pauth = core.get_auth_handler().get_auth(param)
if pauth and pauth.last_login and pauth.last_login ~= -1 then if pauth and pauth.last_login and pauth.last_login ~= -1 then
-- Time in UTC, ISO 8601 format -- Time in UTC, ISO 8601 format
return true, "Last login time was " .. return true, param.."'s last login time was " ..
os.date("!%Y-%m-%dT%H:%M:%SZ", pauth.last_login) os.date("!%Y-%m-%dT%H:%M:%SZ", pauth.last_login)
end end
return false, "Last login time is unknown" return false, param.."'s last login time is unknown"
end, end,
}) })

View File

@ -52,6 +52,7 @@ core.register_entity(":__builtin:falling_node", {
floats = false, floats = false,
set_node = function(self, node, meta) set_node = function(self, node, meta)
node.param2 = node.param2 or 0
self.node = node self.node = node
meta = meta or {} meta = meta or {}
if type(meta.to_table) == "function" then if type(meta.to_table) == "function" then
@ -83,6 +84,9 @@ core.register_entity(":__builtin:falling_node", {
local textures local textures
if def.tiles and def.tiles[1] then if def.tiles and def.tiles[1] then
local tile = def.tiles[1] local tile = def.tiles[1]
if def.drawtype == "torchlike" and def.paramtype2 ~= "wallmounted" then
tile = def.tiles[2] or def.tiles[1]
end
if type(tile) == "table" then if type(tile) == "table" then
tile = tile.name tile = tile.name
end end
@ -143,7 +147,11 @@ core.register_entity(":__builtin:falling_node", {
-- Rotate entity -- Rotate entity
if def.drawtype == "torchlike" then if def.drawtype == "torchlike" then
self.object:set_yaw(math.pi*0.25) if def.paramtype2 == "wallmounted" then
self.object:set_yaw(math.pi*0.25)
else
self.object:set_yaw(-math.pi*0.25)
end
elseif (node.param2 ~= 0 and (def.wield_image == "" elseif (node.param2 ~= 0 and (def.wield_image == ""
or def.wield_image == nil)) or def.wield_image == nil))
or def.drawtype == "signlike" or def.drawtype == "signlike"

View File

@ -17,6 +17,7 @@ core.features = {
area_store_persistent_ids = true, area_store_persistent_ids = true,
pathfinder_works = true, pathfinder_works = true,
object_step_has_moveresult = true, object_step_has_moveresult = true,
direct_velocity_on_players = true,
} }
function core.has_feature(arg) function core.has_feature(arg)

View File

@ -538,8 +538,9 @@ function core.node_dig(pos, node, digger)
local diggername = user_name(digger) local diggername = user_name(digger)
local log = make_log(diggername) local log = make_log(diggername)
local def = core.registered_nodes[node.name] local def = core.registered_nodes[node.name]
-- Copy pos because the callback could modify it
if def and (not def.diggable or if def and (not def.diggable or
(def.can_dig and not def.can_dig(pos, digger))) then (def.can_dig and not def.can_dig(vector.new(pos), digger))) then
log("info", diggername .. " tried to dig " log("info", diggername .. " tried to dig "
.. node.name .. " which is not diggable " .. node.name .. " which is not diggable "
.. core.pos_to_string(pos)) .. core.pos_to_string(pos))

View File

@ -54,8 +54,9 @@ core.register_entity(":__builtin:item", {
local max_count = stack:get_stack_max() local max_count = stack:get_stack_max()
local count = math.min(stack:get_count(), max_count) local count = math.min(stack:get_count(), max_count)
local size = 0.2 + 0.1 * (count / max_count) ^ (1 / 3) local size = 0.2 + 0.1 * (count / max_count) ^ (1 / 3)
local def = core.registered_nodes[itemname] local def = core.registered_items[itemname]
local glow = def and math.floor(def.light_source / 2 + 0.5) local glow = def and def.light_source and
math.floor(def.light_source / 2 + 0.5)
self.object:set_properties({ self.object:set_properties({
is_visible = true, is_visible = true,

View File

@ -151,6 +151,12 @@ function core.setting_get_pos(name)
end end
-- See l_env.cpp for the other functions
function core.get_artificial_light(param1)
return math.floor(param1 / 16)
end
-- To be overriden by protection mods -- To be overriden by protection mods
function core.is_protected(pos, name) function core.is_protected(pos, name)

View File

@ -118,6 +118,10 @@ function core.register_item(name, itemdef)
end end
itemdef.name = name itemdef.name = name
-- default short_description to first line of description
itemdef.short_description = itemdef.short_description or
(itemdef.description or ""):gsub("\n.*","")
-- Apply defaults and add to registered_* table -- Apply defaults and add to registered_* table
if itemdef.type == "node" then if itemdef.type == "node" then
-- Use the nodebox as selection box if it's not set manually -- Use the nodebox as selection box if it's not set manually
@ -584,6 +588,7 @@ core.unregister_biome = make_wrap_deregistration(core.register_biome,
core.clear_registered_biomes, core.registered_biomes) core.clear_registered_biomes, core.registered_biomes)
core.registered_on_chat_messages, core.register_on_chat_message = make_registration() core.registered_on_chat_messages, core.register_on_chat_message = make_registration()
core.registered_on_chatcommands, core.register_on_chatcommand = make_registration()
core.registered_globalsteps, core.register_globalstep = make_registration() core.registered_globalsteps, core.register_globalstep = make_registration()
core.registered_playerevents, core.register_playerevent = make_registration() core.registered_playerevents, core.register_playerevent = make_registration()
core.registered_on_mods_loaded, core.register_on_mods_loaded = make_registration() core.registered_on_mods_loaded, core.register_on_mods_loaded = make_registration()

View File

@ -45,6 +45,9 @@ local filter_types_titles = {
fgettext("Texture packs"), fgettext("Texture packs"),
} }
local number_downloading = 0
local download_queue = {}
local filter_types_type = { local filter_types_type = {
nil, nil,
"game", "game",
@ -67,12 +70,14 @@ local function download_package(param)
end end
end end
local function start_install(calling_dialog, package) local function start_install(package)
local params = { local params = {
package = package, package = package,
filename = os.tempfolder() .. "_MODNAME_" .. package.name .. ".zip", filename = os.tempfolder() .. "_MODNAME_" .. package.name .. ".zip",
} }
number_downloading = number_downloading + 1
local function callback(result) local function callback(result)
if result.successful then if result.successful then
local path, msg = pkgmgr.install(package.type, local path, msg = pkgmgr.install(package.type,
@ -121,9 +126,20 @@ local function start_install(calling_dialog, package)
end end
package.downloading = false package.downloading = false
number_downloading = number_downloading - 1
local next = download_queue[1]
if next then
table.remove(download_queue, 1)
start_install(next)
end
ui.update() ui.update()
end end
package.queued = false
package.downloading = true package.downloading = true
if not core.handle_async(download_package, params, callback) then if not core.handle_async(download_package, params, callback) then
@ -133,6 +149,16 @@ local function start_install(calling_dialog, package)
end end
end end
local function queue_download(package)
local max_concurrent_downloads = tonumber(minetest.settings:get("contentdb_max_concurrent_downloads"))
if number_downloading < max_concurrent_downloads then
start_install(package)
else
table.insert(download_queue, package)
package.queued = true
end
end
local function get_file_extension(path) local function get_file_extension(path)
local parts = path:split(".") local parts = path:split(".")
return parts[#parts] return parts[#parts]
@ -279,7 +305,7 @@ function store.filter_packages(query)
table.insert(keywords, word) table.insert(keywords, word)
end end
local function matches_keywords(package, keywords) local function matches_keywords(package)
for k = 1, #keywords do for k = 1, #keywords do
local keyword = keywords[k] local keyword = keywords[k]
@ -296,7 +322,7 @@ function store.filter_packages(query)
store.packages = {} store.packages = {}
for _, package in pairs(store.packages_full) do for _, package in pairs(store.packages_full) do
if (query == "" or matches_keywords(package, keywords)) and if (query == "" or matches_keywords(package)) and
(filter_type == 1 or package.type == filter_types_type[filter_type]) then (filter_type == 1 or package.type == filter_types_type[filter_type]) then
store.packages[#store.packages + 1] = package store.packages[#store.packages + 1] = package
end end
@ -321,11 +347,14 @@ function store.get_formspec(dlgdata)
"formspec_version[3]", "formspec_version[3]",
"size[15.75,9.5]", "size[15.75,9.5]",
"position[0.5,0.55]", "position[0.5,0.55]",
"style[status;border=false]",
"container[0.375,0.375]", "container[0.375,0.375]",
"field[0,0;10.225,0.8;search_string;;", core.formspec_escape(search_string), "]", "field[0,0;7.225,0.8;search_string;;", core.formspec_escape(search_string), "]",
"field_close_on_enter[search_string;false]", "field_close_on_enter[search_string;false]",
"button[10.225,0;2,0.8;search;", fgettext("Search"), "]", "button[7.225,0;2,0.8;search;", fgettext("Search"), "]",
"dropdown[12.6,0;2.4,0.8;type;", table.concat(filter_types_titles, ","), ";", filter_type, "]", "dropdown[9.6,0;2.4,0.8;type;", table.concat(filter_types_titles, ","), ";", filter_type, "]",
"container_end[]", "container_end[]",
-- Page nav buttons -- Page nav buttons
@ -344,6 +373,35 @@ function store.get_formspec(dlgdata)
"container_end[]", "container_end[]",
} }
if number_downloading > 0 then
formspec[#formspec + 1] = "button[12.75,0.375;2.625,0.8;status;"
if #download_queue > 0 then
formspec[#formspec + 1] = fgettext("$1 downloading,\n$2 queued", number_downloading, #download_queue)
else
formspec[#formspec + 1] = fgettext("$1 downloading...", number_downloading)
end
formspec[#formspec + 1] = "]"
else
local num_avail_updates = 0
for i=1, #store.packages_full do
local package = store.packages_full[i]
if package.path and package.installed_release < package.release and
not (package.downloading or package.queued) then
num_avail_updates = num_avail_updates + 1
end
end
if num_avail_updates == 0 then
formspec[#formspec + 1] = "button[12.75,0.375;2.625,0.8;status;"
formspec[#formspec + 1] = fgettext("No updates")
formspec[#formspec + 1] = "]"
else
formspec[#formspec + 1] = "button[12.75,0.375;2.625,0.8;update_all;"
formspec[#formspec + 1] = fgettext("Update All [$1]", num_avail_updates)
formspec[#formspec + 1] = "]"
end
end
if #store.packages == 0 then if #store.packages == 0 then
formspec[#formspec + 1] = "label[4,3;" formspec[#formspec + 1] = "label[4,3;"
formspec[#formspec + 1] = fgettext("No results") formspec[#formspec + 1] = fgettext("No results")
@ -386,11 +444,13 @@ function store.get_formspec(dlgdata)
formspec[#formspec + 1] = ",0.1]" formspec[#formspec + 1] = ",0.1]"
if package.downloading then if package.downloading then
formspec[#formspec + 1] = "style[download;border=false]" formspec[#formspec + 1] = "button[-3.5,0;2,0.8;status;"
formspec[#formspec + 1] = "button[-3.5,0;2,0.8;download;"
formspec[#formspec + 1] = fgettext("Downloading...") formspec[#formspec + 1] = fgettext("Downloading...")
formspec[#formspec + 1] = "]" formspec[#formspec + 1] = "]"
elseif package.queued then
formspec[#formspec + 1] = "button[-3.5,0;2,0.8;status;"
formspec[#formspec + 1] = fgettext("Queued")
formspec[#formspec + 1] = "]"
elseif not package.path then elseif not package.path then
formspec[#formspec + 1] = "button[-3,0;1.5,0.8;install_" formspec[#formspec + 1] = "button[-3,0;1.5,0.8;install_"
formspec[#formspec + 1] = tostring(i) formspec[#formspec + 1] = tostring(i)
@ -485,6 +545,17 @@ function store.handle_submit(this, fields)
end end
end end
if fields.update_all then
for i=1, #store.packages_full do
local package = store.packages_full[i]
if package.path and package.installed_release < package.release and
not (package.downloading or package.queued) then
queue_download(package)
end
end
return true
end
local start_idx = (cur_page - 1) * num_per_page + 1 local start_idx = (cur_page - 1) * num_per_page + 1
assert(start_idx ~= nil) assert(start_idx ~= nil)
for i=start_idx, math.min(#store.packages, start_idx+num_per_page-1) do for i=start_idx, math.min(#store.packages, start_idx+num_per_page-1) do
@ -492,7 +563,7 @@ function store.handle_submit(this, fields)
assert(package) assert(package)
if fields["install_" .. i] then if fields["install_" .. i] then
start_install(this, package) queue_download(package)
return true return true
end end
@ -505,8 +576,9 @@ function store.handle_submit(this, fields)
end end
if fields["view_" .. i] then if fields["view_" .. i] then
local url = ("%s/packages/%s?protocol_version=%d"):format( local url = ("%s/packages/%s/%s?protocol_version=%d"):format(
core.settings:get("contentdb_url"), package.id, core.get_max_supp_proto()) core.settings:get("contentdb_url"),
package.author, package.name, core.get_max_supp_proto())
core.open_url(url) core.open_url(url)
return true return true
end end

View File

@ -61,6 +61,7 @@ local flag_checkboxes = {
fgettext("Low humidity and high heat causes shallow or dry rivers") }, fgettext("Low humidity and high heat causes shallow or dry rivers") },
}, },
flat = { flat = {
cb_caverns,
{ "hills", fgettext("Hills"), "hills" }, { "hills", fgettext("Hills"), "hills" },
{ "lakes", fgettext("Lakes"), "lakes" }, { "lakes", fgettext("Lakes"), "lakes" },
}, },
@ -362,10 +363,18 @@ local function create_world_buttonhandler(this, fields)
local gameindex = core.get_textlist_index("games") local gameindex = core.get_textlist_index("games")
if gameindex ~= nil then if gameindex ~= nil then
-- For unnamed worlds use the generated name 'world<number>',
-- where the number increments: it is set to 1 larger than the largest
-- generated name number found.
if worldname == "" then if worldname == "" then
local random_number = math.random(10000, 99999) local worldnum_max = 0
local random_world_name = "Unnamed" .. random_number for _, world in ipairs(menudata.worldlist:get_list()) do
worldname = random_world_name if world.name:match("^world%d+$") then
local worldnum = tonumber(world.name:sub(6))
worldnum_max = math.max(worldnum_max, worldnum)
end
end
worldname = "world" .. worldnum_max + 1
end end
core.settings:set("fixed_map_seed", fields["te_seed"]) core.settings:set("fixed_map_seed", fields["te_seed"])

View File

@ -22,7 +22,6 @@ mt_color_dark_green = "#25C191"
local menupath = core.get_mainmenu_path() local menupath = core.get_mainmenu_path()
local basepath = core.get_builtin_path() local basepath = core.get_builtin_path()
local menustyle = core.settings:get("main_menu_style")
defaulttexturedir = core.get_texturepath_share() .. DIR_DELIM .. "base" .. defaulttexturedir = core.get_texturepath_share() .. DIR_DELIM .. "base" ..
DIR_DELIM .. "pack" .. DIR_DELIM DIR_DELIM .. "pack" .. DIR_DELIM
@ -39,24 +38,18 @@ dofile(menupath .. DIR_DELIM .. "textures.lua")
dofile(menupath .. DIR_DELIM .. "dlg_config_world.lua") dofile(menupath .. DIR_DELIM .. "dlg_config_world.lua")
dofile(menupath .. DIR_DELIM .. "dlg_settings_advanced.lua") dofile(menupath .. DIR_DELIM .. "dlg_settings_advanced.lua")
dofile(menupath .. DIR_DELIM .. "dlg_contentstore.lua") dofile(menupath .. DIR_DELIM .. "dlg_contentstore.lua")
if menustyle ~= "simple" then dofile(menupath .. DIR_DELIM .. "dlg_create_world.lua")
dofile(menupath .. DIR_DELIM .. "dlg_create_world.lua") dofile(menupath .. DIR_DELIM .. "dlg_delete_content.lua")
dofile(menupath .. DIR_DELIM .. "dlg_delete_content.lua") dofile(menupath .. DIR_DELIM .. "dlg_delete_world.lua")
dofile(menupath .. DIR_DELIM .. "dlg_delete_world.lua") dofile(menupath .. DIR_DELIM .. "dlg_rename_modpack.lua")
dofile(menupath .. DIR_DELIM .. "dlg_rename_modpack.lua")
end
local tabs = {} local tabs = {}
tabs.settings = dofile(menupath .. DIR_DELIM .. "tab_settings.lua") tabs.settings = dofile(menupath .. DIR_DELIM .. "tab_settings.lua")
tabs.content = dofile(menupath .. DIR_DELIM .. "tab_content.lua") tabs.content = dofile(menupath .. DIR_DELIM .. "tab_content.lua")
tabs.credits = dofile(menupath .. DIR_DELIM .. "tab_credits.lua") tabs.credits = dofile(menupath .. DIR_DELIM .. "tab_credits.lua")
if menustyle == "simple" then tabs.local_game = dofile(menupath .. DIR_DELIM .. "tab_local.lua")
tabs.simple_main = dofile(menupath .. DIR_DELIM .. "tab_simple_main.lua") tabs.play_online = dofile(menupath .. DIR_DELIM .. "tab_online.lua")
else
tabs.local_game = dofile(menupath .. DIR_DELIM .. "tab_local.lua")
tabs.play_online = dofile(menupath .. DIR_DELIM .. "tab_online.lua")
end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
local function main_event_handler(tabview, event) local function main_event_handler(tabview, event)
@ -71,68 +64,35 @@ local function init_globals()
-- Init gamedata -- Init gamedata
gamedata.worldindex = 0 gamedata.worldindex = 0
if menustyle == "simple" then menudata.worldlist = filterlist.create(
local world_list = core.get_worlds() core.get_worlds,
local world_index compare_worlds,
-- Unique id comparison function
local found_singleplayerworld = false function(element, uid)
for i, world in ipairs(world_list) do return element.name == uid
if world.name == "singleplayerworld" then end,
found_singleplayerworld = true -- Filter function
world_index = i function(element, gameid)
break return element.gameid == gameid
end
end end
)
if not found_singleplayerworld then menudata.worldlist:add_sort_mechanism("alphabetic", sort_worlds_alphabetic)
core.create_world("singleplayerworld", 1) menudata.worldlist:set_sortmode("alphabetic")
world_list = core.get_worlds() if not core.settings:get("menu_last_game") then
local default_game = core.settings:get("default_game") or "minetest"
for i, world in ipairs(world_list) do core.settings:set("menu_last_game", default_game)
if world.name == "singleplayerworld" then
world_index = i
break
end
end
end
gamedata.worldindex = world_index
else
menudata.worldlist = filterlist.create(
core.get_worlds,
compare_worlds,
-- Unique id comparison function
function(element, uid)
return element.name == uid
end,
-- Filter function
function(element, gameid)
return element.gameid == gameid
end
)
menudata.worldlist:add_sort_mechanism("alphabetic", sort_worlds_alphabetic)
menudata.worldlist:set_sortmode("alphabetic")
if not core.settings:get("menu_last_game") then
local default_game = core.settings:get("default_game") or "minetest"
core.settings:set("menu_last_game", default_game)
end
mm_texture.init()
end end
mm_texture.init()
-- Create main tabview -- Create main tabview
local tv_main = tabview_create("maintab", {x = 12, y = 5.4}, {x = 0, y = 0}) local tv_main = tabview_create("maintab", {x = 12, y = 5.4}, {x = 0, y = 0})
if menustyle == "simple" then tv_main:set_autosave_tab(true)
tv_main:add(tabs.simple_main) tv_main:add(tabs.local_game)
else tv_main:add(tabs.play_online)
tv_main:set_autosave_tab(true)
tv_main:add(tabs.local_game)
tv_main:add(tabs.play_online)
end
tv_main:add(tabs.content) tv_main:add(tabs.content)
tv_main:add(tabs.settings) tv_main:add(tabs.settings)
@ -141,11 +101,9 @@ local function init_globals()
tv_main:set_global_event_handler(main_event_handler) tv_main:set_global_event_handler(main_event_handler)
tv_main:set_fixed_size(false) tv_main:set_fixed_size(false)
if menustyle ~= "simple" then local last_tab = core.settings:get("maintab_LAST")
local last_tab = core.settings:get("maintab_LAST") if last_tab and tv_main.current_tab ~= last_tab then
if last_tab and tv_main.current_tab ~= last_tab then tv_main:set_tab(last_tab)
tv_main:set_tab(last_tab)
end
end end
ui.set_default("maintab") ui.set_default("maintab")
tv_main:show() tv_main:show()

View File

@ -114,45 +114,44 @@ local function get_formspec(tabview, name, tabdata)
) )
retval = retval .. retval = retval ..
"button[4,3.95;2.6,1;world_delete;".. fgettext("Delete") .. "]" .. "button[3.9,3.8;2.8,1;world_delete;".. fgettext("Delete") .. "]" ..
"button[6.5,3.95;2.8,1;world_configure;".. fgettext("Configure") .. "]" .. "button[6.55,3.8;2.8,1;world_configure;".. fgettext("Configure") .. "]" ..
"button[9.2,3.95;2.5,1;world_create;".. fgettext("New") .. "]" .. "button[9.2,3.8;2.8,1;world_create;".. fgettext("New") .. "]" ..
"label[4,-0.25;".. fgettext("Select World:") .. "]".. "label[3.9,-0.05;".. fgettext("Select World:") .. "]"..
"checkbox[0.25,0.25;cb_creative_mode;".. fgettext("Creative Mode") .. ";" .. "checkbox[0,-0.20;cb_creative_mode;".. fgettext("Creative Mode") .. ";" ..
dump(core.settings:get_bool("creative_mode")) .. "]".. dump(core.settings:get_bool("creative_mode")) .. "]"..
"checkbox[0.25,0.7;cb_enable_damage;".. fgettext("Enable Damage") .. ";" .. "checkbox[0,0.25;cb_enable_damage;".. fgettext("Enable Damage") .. ";" ..
dump(core.settings:get_bool("enable_damage")) .. "]".. dump(core.settings:get_bool("enable_damage")) .. "]"..
"checkbox[0.25,1.15;cb_server;".. fgettext("Host Server") ..";" .. "checkbox[0,0.7;cb_server;".. fgettext("Host Server") ..";" ..
dump(core.settings:get_bool("enable_server")) .. "]" .. dump(core.settings:get_bool("enable_server")) .. "]" ..
"textlist[4,0.25;7.5,3.7;sp_worlds;" .. "textlist[3.9,0.4;7.9,3.45;sp_worlds;" ..
menu_render_worldlist() .. menu_render_worldlist() ..
";" .. index .. "]" ";" .. index .. "]"
if core.settings:get_bool("enable_server") then if core.settings:get_bool("enable_server") then
retval = retval .. retval = retval ..
"button[8.5,4.8;3.2,1;play;".. fgettext("Host Game") .. "]" .. "button[7.9,4.75;4.1,1;play;".. fgettext("Host Game") .. "]" ..
"checkbox[0.25,1.6;cb_server_announce;" .. fgettext("Announce Server") .. ";" .. "checkbox[0,1.15;cb_server_announce;" .. fgettext("Announce Server") .. ";" ..
dump(core.settings:get_bool("server_announce")) .. "]" .. dump(core.settings:get_bool("server_announce")) .. "]" ..
"label[0.25,2.2;" .. fgettext("Name/Password") .. "]" .. "field[0.3,2.85;3.8,0.5;te_playername;" .. fgettext("Name") .. ";" ..
"field[0.55,3.2;3.5,0.5;te_playername;;" ..
core.formspec_escape(core.settings:get("name")) .. "]" .. core.formspec_escape(core.settings:get("name")) .. "]" ..
"pwdfield[0.55,4;3.5,0.5;te_passwd;]" "pwdfield[0.3,4.05;3.8,0.5;te_passwd;" .. fgettext("Password") .. "]"
local bind_addr = core.settings:get("bind_address") local bind_addr = core.settings:get("bind_address")
if bind_addr ~= nil and bind_addr ~= "" then if bind_addr ~= nil and bind_addr ~= "" then
retval = retval .. retval = retval ..
"field[0.55,5.2;2.25,0.5;te_serveraddr;" .. fgettext("Bind Address") .. ";" .. "field[0.3,5.25;2.5,0.5;te_serveraddr;" .. fgettext("Bind Address") .. ";" ..
core.formspec_escape(core.settings:get("bind_address")) .. "]" .. core.formspec_escape(core.settings:get("bind_address")) .. "]" ..
"field[2.8,5.2;1.25,0.5;te_serverport;" .. fgettext("Port") .. ";" .. "field[2.85,5.25;1.25,0.5;te_serverport;" .. fgettext("Port") .. ";" ..
core.formspec_escape(core.settings:get("port")) .. "]" core.formspec_escape(core.settings:get("port")) .. "]"
else else
retval = retval .. retval = retval ..
"field[0.55,5.2;3.5,0.5;te_serverport;" .. fgettext("Server Port") .. ";" .. "field[0.3,5.25;3.8,0.5;te_serverport;" .. fgettext("Server Port") .. ";" ..
core.formspec_escape(core.settings:get("port")) .. "]" core.formspec_escape(core.settings:get("port")) .. "]"
end end
else else
retval = retval .. retval = retval ..
"button[8.5,4.8;3.2,1;play;".. fgettext("Play Game") .. "]" "button[7.9,4.75;4.1,1;play;" .. fgettext("Play Game") .. "]"
end end
return retval return retval

View File

@ -122,56 +122,6 @@ local function antialiasing_fname_to_name(fname)
return 0 return 0
end end
local function dlg_confirm_reset_formspec(data)
return "size[8,3]" ..
"label[1,1;" .. fgettext("Are you sure to reset your singleplayer world?") .. "]" ..
"button[1,2;2.6,0.5;dlg_reset_singleplayer_confirm;" .. fgettext("Yes") .. "]" ..
"button[4,2;2.8,0.5;dlg_reset_singleplayer_cancel;" .. fgettext("No") .. "]"
end
local function dlg_confirm_reset_btnhandler(this, fields, dialogdata)
if fields["dlg_reset_singleplayer_confirm"] ~= nil then
local worldlist = core.get_worlds()
local found_singleplayerworld = false
for i = 1, #worldlist do
if worldlist[i].name == "singleplayerworld" then
found_singleplayerworld = true
gamedata.worldindex = i
end
end
if found_singleplayerworld then
core.delete_world(gamedata.worldindex)
end
core.create_world("singleplayerworld", 1)
worldlist = core.get_worlds()
for i = 1, #worldlist do
if worldlist[i].name == "singleplayerworld" then
gamedata.worldindex = i
end
end
end
this.parent:show()
this:hide()
this:delete()
return true
end
local function showconfirm_reset(tabview)
local new_dlg = dialog_create("reset_spworld",
dlg_confirm_reset_formspec,
dlg_confirm_reset_btnhandler,
nil)
new_dlg:set_parent(tabview)
tabview:hide()
new_dlg:show()
end
local function formspec(tabview, name, tabdata) local function formspec(tabview, name, tabdata)
local tab_string = local tab_string =
"box[0,0;3.75,4.5;#999999]" .. "box[0,0;3.75,4.5;#999999]" ..
@ -204,30 +154,26 @@ local function formspec(tabview, name, tabdata)
"box[8,0;3.75,4.5;#999999]" "box[8,0;3.75,4.5;#999999]"
local video_driver = core.settings:get("video_driver") local video_driver = core.settings:get("video_driver")
local shaders_supported = video_driver == "opengl" local shaders_enabled = core.settings:get_bool("enable_shaders")
local shaders_enabled = false if video_driver == "opengl" then
if shaders_supported then
shaders_enabled = core.settings:get_bool("enable_shaders")
tab_string = tab_string .. tab_string = tab_string ..
"checkbox[8.25,0;cb_shaders;" .. fgettext("Shaders") .. ";" "checkbox[8.25,0;cb_shaders;" .. fgettext("Shaders") .. ";"
.. tostring(shaders_enabled) .. "]" .. tostring(shaders_enabled) .. "]"
elseif video_driver == "ogles2" then
tab_string = tab_string ..
"checkbox[8.25,0;cb_shaders;" .. fgettext("Shaders (experimental)") .. ";"
.. tostring(shaders_enabled) .. "]"
else else
core.settings:set_bool("enable_shaders", false) core.settings:set_bool("enable_shaders", false)
shaders_enabled = false
tab_string = tab_string .. tab_string = tab_string ..
"label[8.38,0.2;" .. core.colorize("#888888", "label[8.38,0.2;" .. core.colorize("#888888",
fgettext("Shaders (unavailable)")) .. "]" fgettext("Shaders (unavailable)")) .. "]"
end end
if core.settings:get("main_menu_style") == "simple" then tab_string = tab_string ..
-- 'Reset singleplayer world' only functions with simple menu "button[8,4.75;3.95,1;btn_change_keys;"
tab_string = tab_string .. .. fgettext("Change Keys") .. "]"
"button[8,4.75;3.95,1;btn_reset_singleplayer;"
.. fgettext("Reset singleplayer world") .. "]"
else
tab_string = tab_string ..
"button[8,4.75;3.95,1;btn_change_keys;"
.. fgettext("Change Keys") .. "]"
end
tab_string = tab_string .. tab_string = tab_string ..
"button[0,4.75;3.95,1;btn_advanced_settings;" "button[0,4.75;3.95,1;btn_advanced_settings;"
@ -244,35 +190,23 @@ local function formspec(tabview, name, tabdata)
if shaders_enabled then if shaders_enabled then
tab_string = tab_string .. tab_string = tab_string ..
"checkbox[8.25,0.5;cb_bumpmapping;" .. fgettext("Bump Mapping") .. ";" "checkbox[8.25,0.5;cb_tonemapping;" .. fgettext("Tone Mapping") .. ";"
.. dump(core.settings:get_bool("enable_bumpmapping")) .. "]" ..
"checkbox[8.25,1;cb_tonemapping;" .. fgettext("Tone Mapping") .. ";"
.. dump(core.settings:get_bool("tone_mapping")) .. "]" .. .. dump(core.settings:get_bool("tone_mapping")) .. "]" ..
"checkbox[8.25,1.5;cb_generate_normalmaps;" .. fgettext("Generate Normal Maps") .. ";" "checkbox[8.25,1;cb_waving_water;" .. fgettext("Waving Liquids") .. ";"
.. dump(core.settings:get_bool("generate_normalmaps")) .. "]" ..
"checkbox[8.25,2;cb_parallax;" .. fgettext("Parallax Occlusion") .. ";"
.. dump(core.settings:get_bool("enable_parallax_occlusion")) .. "]" ..
"checkbox[8.25,2.5;cb_waving_water;" .. fgettext("Waving Liquids") .. ";"
.. dump(core.settings:get_bool("enable_waving_water")) .. "]" .. .. dump(core.settings:get_bool("enable_waving_water")) .. "]" ..
"checkbox[8.25,3;cb_waving_leaves;" .. fgettext("Waving Leaves") .. ";" "checkbox[8.25,1.5;cb_waving_leaves;" .. fgettext("Waving Leaves") .. ";"
.. dump(core.settings:get_bool("enable_waving_leaves")) .. "]" .. .. dump(core.settings:get_bool("enable_waving_leaves")) .. "]" ..
"checkbox[8.25,3.5;cb_waving_plants;" .. fgettext("Waving Plants") .. ";" "checkbox[8.25,2;cb_waving_plants;" .. fgettext("Waving Plants") .. ";"
.. dump(core.settings:get_bool("enable_waving_plants")) .. "]" .. dump(core.settings:get_bool("enable_waving_plants")) .. "]"
else else
tab_string = tab_string .. tab_string = tab_string ..
"label[8.38,0.7;" .. core.colorize("#888888", "label[8.38,0.7;" .. core.colorize("#888888",
fgettext("Bump Mapping")) .. "]" ..
"label[8.38,1.2;" .. core.colorize("#888888",
fgettext("Tone Mapping")) .. "]" .. fgettext("Tone Mapping")) .. "]" ..
"label[8.38,1.7;" .. core.colorize("#888888", "label[8.38,1.2;" .. core.colorize("#888888",
fgettext("Generate Normal Maps")) .. "]" ..
"label[8.38,2.2;" .. core.colorize("#888888",
fgettext("Parallax Occlusion")) .. "]" ..
"label[8.38,2.7;" .. core.colorize("#888888",
fgettext("Waving Liquids")) .. "]" .. fgettext("Waving Liquids")) .. "]" ..
"label[8.38,3.2;" .. core.colorize("#888888", "label[8.38,1.7;" .. core.colorize("#888888",
fgettext("Waving Leaves")) .. "]" .. fgettext("Waving Leaves")) .. "]" ..
"label[8.38,3.7;" .. core.colorize("#888888", "label[8.38,2.2;" .. core.colorize("#888888",
fgettext("Waving Plants")) .. "]" fgettext("Waving Plants")) .. "]"
end end
@ -324,22 +258,10 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
end end
return true return true
end end
if fields["cb_bumpmapping"] then
core.settings:set("enable_bumpmapping", fields["cb_bumpmapping"])
return true
end
if fields["cb_tonemapping"] then if fields["cb_tonemapping"] then
core.settings:set("tone_mapping", fields["cb_tonemapping"]) core.settings:set("tone_mapping", fields["cb_tonemapping"])
return true return true
end end
if fields["cb_generate_normalmaps"] then
core.settings:set("generate_normalmaps", fields["cb_generate_normalmaps"])
return true
end
if fields["cb_parallax"] then
core.settings:set("enable_parallax_occlusion", fields["cb_parallax"])
return true
end
if fields["cb_waving_water"] then if fields["cb_waving_water"] then
core.settings:set("enable_waving_water", fields["cb_waving_water"]) core.settings:set("enable_waving_water", fields["cb_waving_water"])
return true return true
@ -359,10 +281,6 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
core.settings:set("touchtarget", fields["cb_touchscreen_target"]) core.settings:set("touchtarget", fields["cb_touchscreen_target"])
return true return true
end end
if fields["btn_reset_singleplayer"] then
showconfirm_reset(this)
return true
end
--Note dropdowns have to be handled LAST! --Note dropdowns have to be handled LAST!
local ddhandled = false local ddhandled = false

View File

@ -1,220 +0,0 @@
--Minetest
--Copyright (C) 2013 sapier
--
--This program is free software; you can redistribute it and/or modify
--it under the terms of the GNU Lesser General Public License as published by
--the Free Software Foundation; either version 2.1 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,
--but WITHOUT ANY WARRANTY; without even the implied warranty of
--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
--GNU Lesser General Public License for more details.
--
--You should have received a copy of the GNU Lesser General Public License along
--with this program; if not, write to the Free Software Foundation, Inc.,
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
--------------------------------------------------------------------------------
local function get_formspec(tabview, name, tabdata)
-- Update the cached supported proto info,
-- it may have changed after a change by the settings menu.
common_update_cached_supp_proto()
local fav_selected = menudata.favorites[tabdata.fav_selected]
local retval =
"label[9.5,0;".. fgettext("Name / Password") .. "]" ..
"field[0.25,3.35;5.5,0.5;te_address;;" ..
core.formspec_escape(core.settings:get("address")) .."]" ..
"field[5.75,3.35;2.25,0.5;te_port;;" ..
core.formspec_escape(core.settings:get("remote_port")) .."]" ..
"button[10,2.6;2,1.5;btn_mp_connect;".. fgettext("Connect") .. "]" ..
"field[9.8,1;2.6,0.5;te_name;;" ..
core.formspec_escape(core.settings:get("name")) .."]" ..
"pwdfield[9.8,2;2.6,0.5;te_pwd;]"
if tabdata.fav_selected and fav_selected then
if gamedata.fav then
retval = retval .. "button[7.7,2.6;2.3,1.5;btn_delete_favorite;" ..
fgettext("Del. Favorite") .. "]"
end
end
retval = retval .. "tablecolumns[" ..
image_column(fgettext("Favorite"), "favorite") .. ";" ..
image_column(fgettext("Ping"), "") .. ",padding=0.25;" ..
"color,span=3;" ..
"text,align=right;" .. -- clients
"text,align=center,padding=0.25;" .. -- "/"
"text,align=right,padding=0.25;" .. -- clients_max
image_column(fgettext("Creative mode"), "creative") .. ",padding=1;" ..
image_column(fgettext("Damage enabled"), "damage") .. ",padding=0.25;" ..
image_column(fgettext("PvP enabled"), "pvp") .. ",padding=0.25;" ..
"color,span=1;" ..
"text,padding=1]" .. -- name
"table[-0.05,0;9.2,2.75;favourites;"
if #menudata.favorites > 0 then
local favs = core.get_favorites("local")
if #favs > 0 then
for i = 1, #favs do
for j = 1, #menudata.favorites do
if menudata.favorites[j].address == favs[i].address and
menudata.favorites[j].port == favs[i].port then
table.insert(menudata.favorites, i,
table.remove(menudata.favorites, j))
end
end
if favs[i].address ~= menudata.favorites[i].address then
table.insert(menudata.favorites, i, favs[i])
end
end
end
retval = retval .. render_serverlist_row(menudata.favorites[1], (#favs > 0))
for i = 2, #menudata.favorites do
retval = retval .. "," .. render_serverlist_row(menudata.favorites[i], (i <= #favs))
end
end
if tabdata.fav_selected then
retval = retval .. ";" .. tabdata.fav_selected .. "]"
else
retval = retval .. ";0]"
end
-- separator
retval = retval .. "box[-0.28,3.75;12.4,0.1;#FFFFFF]"
-- checkboxes
retval = retval ..
"checkbox[8.0,3.9;cb_creative;".. fgettext("Creative Mode") .. ";" ..
dump(core.settings:get_bool("creative_mode")) .. "]"..
"checkbox[8.0,4.4;cb_damage;".. fgettext("Enable Damage") .. ";" ..
dump(core.settings:get_bool("enable_damage")) .. "]"
-- buttons
retval = retval ..
"button[0,3.7;8,1.5;btn_start_singleplayer;" .. fgettext("Start Singleplayer") .. "]" ..
"button[0,4.5;8,1.5;btn_config_sp_world;" .. fgettext("Config mods") .. "]"
return retval
end
--------------------------------------------------------------------------------
local function main_button_handler(tabview, fields, name, tabdata)
if fields.btn_start_singleplayer then
gamedata.selected_world = gamedata.worldindex
gamedata.singleplayer = true
core.start()
return true
end
if fields.favourites then
local event = core.explode_table_event(fields.favourites)
if event.type == "CHG" then
if event.row <= #menudata.favorites then
gamedata.fav = false
local favs = core.get_favorites("local")
local fav = menudata.favorites[event.row]
local address = fav.address
local port = fav.port
gamedata.serverdescription = fav.description
for i = 1, #favs do
if fav.address == favs[i].address and
fav.port == favs[i].port then
gamedata.fav = true
end
end
if address and port then
core.settings:set("address", address)
core.settings:set("remote_port", port)
end
tabdata.fav_selected = event.row
end
return true
end
end
if fields.btn_delete_favorite then
local current_favourite = core.get_table_index("favourites")
if not current_favourite then return end
core.delete_favorite(current_favourite)
asyncOnlineFavourites()
tabdata.fav_selected = nil
core.settings:set("address", "")
core.settings:set("remote_port", "30000")
return true
end
if fields.cb_creative then
core.settings:set("creative_mode", fields.cb_creative)
return true
end
if fields.cb_damage then
core.settings:set("enable_damage", fields.cb_damage)
return true
end
if fields.btn_mp_connect or fields.key_enter then
gamedata.playername = fields.te_name
gamedata.password = fields.te_pwd
gamedata.address = fields.te_address
gamedata.port = fields.te_port
local fav_idx = core.get_textlist_index("favourites")
if fav_idx and fav_idx <= #menudata.favorites and
menudata.favorites[fav_idx].address == fields.te_address and
menudata.favorites[fav_idx].port == fields.te_port then
local fav = menudata.favorites[fav_idx]
gamedata.servername = fav.name
gamedata.serverdescription = fav.description
if menudata.favorites_is_public and
not is_server_protocol_compat_or_error(
fav.proto_min, fav.proto_max) then
return true
end
else
gamedata.servername = ""
gamedata.serverdescription = ""
end
gamedata.selected_world = 0
core.settings:set("address", fields.te_address)
core.settings:set("remote_port", fields.te_port)
core.start()
return true
end
if fields.btn_config_sp_world then
local configdialog = create_configure_world_dlg(1)
if configdialog then
configdialog:set_parent(tabview)
tabview:hide()
configdialog:show()
end
return true
end
end
--------------------------------------------------------------------------------
local function on_activate(type,old_tab,new_tab)
if type == "LEAVE" then return end
asyncOnlineFavourites()
end
--------------------------------------------------------------------------------
return {
name = "main",
caption = fgettext("Main"),
cbf_formspec = get_formspec,
cbf_button_handler = main_button_handler,
on_change = on_activate
}

View File

@ -110,9 +110,9 @@ doubletap_jump (Double tap jump for fly) bool false
# enabled. # enabled.
always_fly_fast (Always fly and fast) bool true always_fly_fast (Always fly and fast) bool true
# The time in seconds it takes between repeated right clicks when holding the right # The time in seconds it takes between repeated node placements when holding
# mouse button. # the place button.
repeat_rightclick_time (Rightclick repetition interval) float 0.25 0.001 repeat_place_time (Place repetition interval) float 0.25 0.001
# Automatically jump up single-node obstacles. # Automatically jump up single-node obstacles.
autojump (Automatic jumping) bool false autojump (Automatic jumping) bool false
@ -182,6 +182,14 @@ keymap_jump (Jump key) key KEY_SPACE
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_sneak (Sneak key) key KEY_LSHIFT keymap_sneak (Sneak key) key KEY_LSHIFT
# Key for digging.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_dig (Dig key) key KEY_LBUTTON
# Key for placing.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_place (Place key) key KEY_RBUTTON
# Key for opening the inventory. # Key for opening the inventory.
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
keymap_inventory (Inventory key) key KEY_KEY_I keymap_inventory (Inventory key) key KEY_KEY_I
@ -517,8 +525,13 @@ texture_clean_transparent (Clean transparent textures) bool false
# texture autoscaling. # texture autoscaling.
texture_min_size (Minimum texture size) int 64 texture_min_size (Minimum texture size) int 64
# Experimental option, might cause visible spaces between blocks # Use multi-sample antialiasing (MSAA) to smooth out block edges.
# when set to higher number than 0. # This algorithm smooths out the 3D viewport while keeping the image sharp,
# but it doesn't affect the insides of textures
# (which is especially noticeable with transparent textures).
# This option is experimental and might cause visible spaces between blocks
# when set above 0.
# A restart is required after changing this option.
fsaa (FSAA) enum 0 0,1,2,4,8,16 fsaa (FSAA) enum 0 0,1,2,4,8,16
# Undersampling is similar to using a lower screen resolution, but it applies # Undersampling is similar to using a lower screen resolution, but it applies
@ -545,43 +558,6 @@ shader_path (Shader path) path
# enhanced, highlights and shadows are gradually compressed. # enhanced, highlights and shadows are gradually compressed.
tone_mapping (Filmic tone mapping) bool false tone_mapping (Filmic tone mapping) bool false
[***Bumpmapping]
# Enables bumpmapping for textures. Normalmaps need to be supplied by the texture pack
# or need to be auto-generated.
# Requires shaders to be enabled.
enable_bumpmapping (Bumpmapping) bool false
# Enables on the fly normalmap generation (Emboss effect).
# Requires bumpmapping to be enabled.
generate_normalmaps (Generate normalmaps) bool false
# Strength of generated normalmaps.
normalmaps_strength (Normalmaps strength) float 0.6
# Defines sampling step of texture.
# A higher value results in smoother normal maps.
normalmaps_smooth (Normalmaps sampling) int 0 0 2
[***Parallax Occlusion]
# Enables parallax occlusion mapping.
# Requires shaders to be enabled.
enable_parallax_occlusion (Parallax occlusion) bool false
# 0 = parallax occlusion with slope information (faster).
# 1 = relief mapping (slower, more accurate).
parallax_occlusion_mode (Parallax occlusion mode) int 1 0 1
# Number of parallax occlusion iterations.
parallax_occlusion_iterations (Parallax occlusion iterations) int 4
# Overall scale of parallax occlusion effect.
parallax_occlusion_scale (Parallax occlusion scale) float 0.08
# Overall bias of parallax occlusion effect, usually scale/2.
parallax_occlusion_bias (Parallax occlusion bias) float 0.04
[***Waving Nodes] [***Waving Nodes]
# Set to true to enable waving liquids (like water). # Set to true to enable waving liquids (like water).
@ -622,15 +598,15 @@ arm_inertia (Arm inertia) bool true
# to not waste CPU power for no benefit. # to not waste CPU power for no benefit.
fps_max (Maximum FPS) int 60 1 fps_max (Maximum FPS) int 60 1
# Maximum FPS when game is paused. # Maximum FPS when the window is not focused, or when the game is paused.
pause_fps_max (FPS in pause menu) int 20 1 fps_max_unfocused (FPS when unfocused or paused) int 20 1
# Open the pause menu when the window's focus is lost. Does not pause if a formspec is # Open the pause menu when the window's focus is lost. Does not pause if a formspec is
# open. # open.
pause_on_lost_focus (Pause on lost window focus) bool false pause_on_lost_focus (Pause on lost window focus) bool false
# View distance in nodes. # View distance in nodes.
viewing_range (Viewing range) int 100 20 4000 viewing_range (Viewing range) int 190 20 4000
# Camera 'near clipping plane' distance in nodes, between 0 and 0.25 # Camera 'near clipping plane' distance in nodes, between 0 and 0.25
# Only works on GLES platforms. Most users will not need to change this. # Only works on GLES platforms. Most users will not need to change this.
@ -694,8 +670,8 @@ texture_path (Texture path) path
# The rendering back-end for Irrlicht. # The rendering back-end for Irrlicht.
# A restart is required after changing this. # A restart is required after changing this.
# Note: On Android, stick with OGLES1 if unsure! App may fail to start otherwise. # Note: On Android, stick with OGLES1 if unsure! App may fail to start otherwise.
# On other platforms, OpenGL is recommended, and its the only driver with # On other platforms, OpenGL is recommended.
# shader support currently. # Shaders are supported by OpenGL (desktop only) and OGLES2 (experimental)
video_driver (Video driver) enum opengl null,software,burningsvideo,direct3d8,direct3d9,opengl,ogles1,ogles2 video_driver (Video driver) enum opengl null,software,burningsvideo,direct3d8,direct3d9,opengl,ogles1,ogles2
# Radius of cloud area stated in number of 64 node cloud squares. # Radius of cloud area stated in number of 64 node cloud squares.
@ -783,7 +759,7 @@ mesh_generation_interval (Mapblock mesh generation delay) int 0 0 50
# Size of the MapBlock cache of the mesh generator. Increasing this will # Size of the MapBlock cache of the mesh generator. Increasing this will
# increase the cache hit %, reducing the data being copied from the main # increase the cache hit %, reducing the data being copied from the main
# thread, thus reducing jitter. # thread, thus reducing jitter.
meshgen_block_cache_size (Mapblock mesh generator's MapBlock cache size in MB) int 20 0 1000 meshgen_block_cache_size (Mapblock mesh generator's MapBlock cache size in MB) int 40 0 1000
# Enables minimap. # Enables minimap.
enable_minimap (Minimap) bool true enable_minimap (Minimap) bool true
@ -1014,7 +990,7 @@ client_unload_unused_data_timeout (Mapblock unload timeout) int 600
# Maximum number of mapblocks for client to be kept in memory. # Maximum number of mapblocks for client to be kept in memory.
# Set to -1 for unlimited amount. # Set to -1 for unlimited amount.
client_mapblock_limit (Mapblock limit) int 5000 client_mapblock_limit (Mapblock limit) int 7500
# Whether to show the client debug info (has the same effect as hitting F5). # Whether to show the client debug info (has the same effect as hitting F5).
show_debug (Show debug info) bool false show_debug (Show debug info) bool false
@ -1073,7 +1049,7 @@ ipv6_server (IPv6 server) 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)
max_simultaneous_block_sends_per_client (Maximum simultaneous block sends per client) int 40 max_simultaneous_block_sends_per_client (Maximum simultaneous block sends per client) int 128
# To reduce lag, block transfers are slowed down when a player is building something. # To reduce lag, block transfers are slowed down when a player is building something.
# This determines how long they are slowed down after placing or removing a node. # This determines how long they are slowed down after placing or removing a node.
@ -1173,17 +1149,17 @@ ask_reconnect_on_crash (Ask to reconnect after crash) bool false
# Setting this larger than active_block_range will also cause the server # Setting this larger than active_block_range will also cause the server
# to maintain active objects up to this distance in the direction the # to maintain active objects up to this distance in the direction the
# player is looking. (This can avoid mobs suddenly disappearing from view) # player is looking. (This can avoid mobs suddenly disappearing from view)
active_object_send_range_blocks (Active object send range) int 4 active_object_send_range_blocks (Active object send range) int 8
# The radius of the volume of blocks around every player that is subject to the # The radius of the volume of blocks around every player that is subject to the
# active block stuff, stated in mapblocks (16 nodes). # active block stuff, stated in mapblocks (16 nodes).
# In active blocks objects are loaded and ABMs run. # In active blocks objects are loaded and ABMs run.
# This is also the minimum range in which active objects (mobs) are maintained. # This is also the minimum range in which active objects (mobs) are maintained.
# This should be configured together with active_object_send_range_blocks. # This should be configured together with active_object_send_range_blocks.
active_block_range (Active block range) int 3 active_block_range (Active block range) int 4
# From how far blocks are sent to clients, stated in mapblocks (16 nodes). # From how far blocks are sent to clients, stated in mapblocks (16 nodes).
max_block_send_distance (Max block send distance) int 10 max_block_send_distance (Max block send distance) int 12
# Maximum number of forceloaded mapblocks. # Maximum number of forceloaded mapblocks.
max_forceloaded_blocks (Maximum forceloaded blocks) int 16 max_forceloaded_blocks (Maximum forceloaded blocks) int 16
@ -1256,10 +1232,10 @@ movement_gravity (Gravity) float 9.81
[**Advanced] [**Advanced]
# Handling for deprecated Lua API calls: # Handling for deprecated Lua API calls:
# - legacy: (try to) mimic old behaviour (default for release). # - none: Do not log deprecated calls
# - log: mimic and log backtrace of deprecated call (default for debug). # - log: mimic and log backtrace of deprecated call (default).
# - error: abort on usage of deprecated call (suggested for mod developers). # - error: abort on usage of deprecated call (suggested for mod developers).
deprecated_lua_api_handling (Deprecated Lua API handling) enum legacy legacy,log,error deprecated_lua_api_handling (Deprecated Lua API handling) enum log none,log,error
# Number of extra blocks that can be loaded by /clearobjects at once. # Number of extra blocks that can be loaded by /clearobjects at once.
# This is a trade-off between sqlite transaction overhead and # This is a trade-off between sqlite transaction overhead and
@ -1286,6 +1262,10 @@ active_block_mgmt_interval (Active block management interval) float 2.0
# Length of time between Active Block Modifier (ABM) execution cycles # Length of time between Active Block Modifier (ABM) execution cycles
abm_interval (ABM interval) float 1.0 abm_interval (ABM interval) float 1.0
# The time budget allowed for ABMs to execute on each step
# (as a fraction of the ABM Interval)
abm_time_budget (ABM time budget) float 0.2 0.1 0.9
# Length of time between NodeTimer execution cycles # Length of time between NodeTimer execution cycles
nodetimer_interval (NodeTimer interval) float 0.2 nodetimer_interval (NodeTimer interval) float 0.2
@ -1446,12 +1426,6 @@ curl_file_download_timeout (cURL file download timeout) int 300000
# Makes DirectX work with LuaJIT. Disable if it causes troubles. # Makes DirectX work with LuaJIT. Disable if it causes troubles.
high_precision_fpu (High-precision FPU) bool true high_precision_fpu (High-precision FPU) bool true
# Changes the main menu UI:
# - Full: Multiple singleplayer worlds, game choice, texture pack chooser, etc.
# - Simple: One singleplayer world, no game or texture pack choosers. May be
# necessary for smaller screens.
main_menu_style (Main menu style) enum full full,simple
# Replaces the default main menu with a custom one. # Replaces the default main menu with a custom one.
main_menu_script (Main menu script) string main_menu_script (Main menu script) string
@ -1471,7 +1445,7 @@ mg_name (Mapgen name) enum v7 v7,valleys,carpathian,v5,flat,fractal,singlenode,v
water_level (Water level) int 1 water_level (Water level) int 1
# From how far blocks are generated for clients, stated in mapblocks (16 nodes). # From how far blocks are generated for clients, stated in mapblocks (16 nodes).
max_block_generate_distance (Max block generate distance) int 8 max_block_generate_distance (Max block generate distance) int 10
# Limit of map generation, in nodes, in all 6 directions from (0, 0, 0). # Limit of map generation, in nodes, in all 6 directions from (0, 0, 0).
# Only mapchunks completely within the mapgen limit are generated. # Only mapchunks completely within the mapgen limit are generated.
@ -1481,7 +1455,7 @@ mapgen_limit (Map generation limit) int 31000 0 31000
# Global map generation attributes. # Global map generation attributes.
# In Mapgen v6 the 'decorations' flag controls all decorations except trees # In Mapgen v6 the 'decorations' flag controls all decorations except trees
# and junglegrass, in all other mapgens this flag controls all decorations. # and junglegrass, in all other mapgens this flag controls all decorations.
mg_flags (Mapgen flags) flags caves,dungeons,light,decorations,biomes caves,dungeons,light,decorations,biomes,nocaves,nodungeons,nolight,nodecorations,nobiomes mg_flags (Mapgen flags) flags caves,dungeons,light,decorations,biomes,ores caves,dungeons,light,decorations,biomes,ores,nocaves,nodungeons,nolight,nodecorations,nobiomes,noores
[*Biome API temperature and humidity noise parameters] [*Biome API temperature and humidity noise parameters]
@ -1872,7 +1846,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 lakes,hills,nolakes,nohills mgflat_spflags (Mapgen Flat specific flags) flags nolakes,nohills,nocaverns lakes,hills,caverns,nolakes,nohills,nocaverns
# Y of flat ground. # Y of flat ground.
mgflat_ground_level (Ground level) int 8 mgflat_ground_level (Ground level) int 8
@ -1916,6 +1890,15 @@ mgflat_hill_threshold (Hill threshold) float 0.45
# Controls steepness/height of hills. # Controls steepness/height of hills.
mgflat_hill_steepness (Hill steepness) float 64.0 mgflat_hill_steepness (Hill steepness) float 64.0
# Y-level of cavern upper limit.
mgflat_cavern_limit (Cavern limit) int -256
# Y-distance over which caverns expand to full size.
mgflat_cavern_taper (Cavern taper) int 256
# Defines full size of caverns, smaller values create larger caverns.
mgflat_cavern_threshold (Cavern threshold) float 0.7
# Lower Y limit of dungeons. # Lower Y limit of dungeons.
mgflat_dungeon_ymin (Dungeon minimum Y) int -31000 mgflat_dungeon_ymin (Dungeon minimum Y) int -31000
@ -1936,6 +1919,9 @@ mgflat_np_cave1 (Cave1 noise) noise_params_3d 0, 12, (61, 61, 61), 52534, 3, 0.5
# Second of two 3D noises that together define tunnels. # Second of two 3D noises that together define tunnels.
mgflat_np_cave2 (Cave2 noise) noise_params_3d 0, 12, (67, 67, 67), 10325, 3, 0.5, 2.0 mgflat_np_cave2 (Cave2 noise) noise_params_3d 0, 12, (67, 67, 67), 10325, 3, 0.5, 2.0
# 3D noise defining giant caverns.
mgflat_np_cavern (Cavern noise) noise_params_3d 0, 1, (384, 128, 384), 723, 5, 0.63, 2.0
# 3D noise that determines number of dungeons per mapchunk. # 3D noise that determines number of dungeons per mapchunk.
mgflat_np_dungeons (Dungeon noise) noise_params_3d 0.9, 0.5, (500, 500, 500), 0, 2, 0.8, 2.0 mgflat_np_dungeons (Dungeon noise) noise_params_3d 0.9, 0.5, (500, 500, 500), 0, 2, 0.8, 2.0
@ -2178,15 +2164,15 @@ chunksize (Chunk size) int 5
enable_mapgen_debug_info (Mapgen debug) bool false enable_mapgen_debug_info (Mapgen debug) bool false
# Maximum number of blocks that can be queued for loading. # Maximum number of blocks that can be queued for loading.
emergequeue_limit_total (Absolute limit of queued blocks to emerge) int 512 emergequeue_limit_total (Absolute limit of queued blocks to emerge) int 1024
# Maximum number of blocks to be queued that are to be loaded from file. # Maximum number of blocks to be queued that are to be loaded from file.
# This limit is enforced per player. # This limit is enforced per player.
emergequeue_limit_diskonly (Per-player limit of queued blocks load from disk) int 64 emergequeue_limit_diskonly (Per-player limit of queued blocks load from disk) int 128
# Maximum number of blocks to be queued that are to be generated. # Maximum number of blocks to be queued that are to be generated.
# This limit is enforced per player. # This limit is enforced per player.
emergequeue_limit_generate (Per-player limit of queued blocks to generate) int 64 emergequeue_limit_generate (Per-player limit of queued blocks to generate) int 128
# Number of emerge threads to use. # Number of emerge threads to use.
# Value 0: # Value 0:
@ -2213,6 +2199,9 @@ contentdb_url (ContentDB URL) string https://content.minetest.net
# so see a full list at https://content.minetest.net/help/content_flags/ # so see a full list at https://content.minetest.net/help/content_flags/
contentdb_flag_blacklist (ContentDB Flag Blacklist) string nonfree, desktop_default contentdb_flag_blacklist (ContentDB Flag Blacklist) string nonfree, desktop_default
# Maximum number of concurrent downloads. Downloads exceeding this limit will be queued.
contentdb_max_concurrent_downloads (ContentDB Max Concurrent Downloads) int 3
[Cheat Menu] [Cheat Menu]
# Font to use for cheat menu # Font to use for cheat menu

View File

@ -6,9 +6,11 @@ uniform sampler2D textureFlags;
#define rightImage normalTexture #define rightImage normalTexture
#define maskImage textureFlags #define maskImage textureFlags
varying mediump vec2 varTexCoord;
void main(void) void main(void)
{ {
vec2 uv = gl_TexCoord[0].st; vec2 uv = varTexCoord.st;
vec4 left = texture2D(leftImage, uv).rgba; vec4 left = texture2D(leftImage, uv).rgba;
vec4 right = texture2D(rightImage, uv).rgba; vec4 right = texture2D(rightImage, uv).rgba;
vec4 mask = texture2D(maskImage, uv).rgba; vec4 mask = texture2D(maskImage, uv).rgba;

View File

@ -1,6 +1,7 @@
varying mediump vec2 varTexCoord;
void main(void) void main(void)
{ {
gl_TexCoord[0] = gl_MultiTexCoord0; varTexCoord = inTexCoord0;
gl_Position = gl_Vertex; gl_Position = inVertexPosition;
gl_FrontColor = gl_BackColor = gl_Color;
} }

View File

@ -1,4 +1,6 @@
varying lowp vec4 varColor;
void main(void) void main(void)
{ {
gl_FragColor = gl_Color; gl_FragColor = varColor;
} }

View File

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

View File

@ -2,9 +2,12 @@ uniform sampler2D baseTexture;
uniform sampler2D normalTexture; uniform sampler2D normalTexture;
uniform vec3 yawVec; uniform vec3 yawVec;
varying lowp vec4 varColor;
varying mediump vec2 varTexCoord;
void main (void) void main (void)
{ {
vec2 uv = gl_TexCoord[0].st; vec2 uv = varTexCoord.st;
//texture sampling rate //texture sampling rate
const float step = 1.0 / 256.0; const float step = 1.0 / 256.0;
@ -27,6 +30,6 @@ void main (void)
vec3 color = (1.1 * diffuse + 0.05 * height + 0.5 * specular) * base.rgb; vec3 color = (1.1 * diffuse + 0.05 * height + 0.5 * specular) * base.rgb;
vec4 col = vec4(color.rgb, base.a); vec4 col = vec4(color.rgb, base.a);
col *= gl_Color; col *= varColor;
gl_FragColor = vec4(col.rgb, base.a); gl_FragColor = vec4(col.rgb, base.a);
} }

View File

@ -1,9 +1,11 @@
uniform mat4 mWorldViewProj;
uniform mat4 mWorld; uniform mat4 mWorld;
varying lowp vec4 varColor;
varying mediump vec2 varTexCoord;
void main(void) void main(void)
{ {
gl_TexCoord[0] = gl_MultiTexCoord0; varTexCoord = inTexCoord0.st;
gl_Position = mWorldViewProj * gl_Vertex; gl_Position = mWorldViewProj * inVertexPosition;
gl_FrontColor = gl_BackColor = gl_Color; varColor = inVertexColor;
} }

View File

@ -1,6 +1,4 @@
uniform sampler2D baseTexture; uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D textureFlags;
uniform vec4 skyBgColor; uniform vec4 skyBgColor;
uniform float fogDistance; uniform float fogDistance;
@ -17,19 +15,12 @@ varying vec3 vPosition;
// cameraOffset + worldPosition (for large coordinates the limits of float // cameraOffset + worldPosition (for large coordinates the limits of float
// precision must be considered). // precision must be considered).
varying vec3 worldPosition; varying vec3 worldPosition;
varying float area_enable_parallax; varying lowp vec4 varColor;
varying mediump vec2 varTexCoord;
varying vec3 eyeVec; varying vec3 eyeVec;
varying vec3 tsEyeVec;
varying vec3 lightVec;
varying vec3 tsLightVec;
bool normalTexturePresent = false;
const float e = 2.718281828459;
const float BS = 10.0;
const float fogStart = FOG_START; const float fogStart = FOG_START;
const float fogShadingParameter = 1 / ( 1 - fogStart); const float fogShadingParameter = 1.0 / ( 1.0 - fogStart);
#ifdef ENABLE_TONE_MAPPING #ifdef ENABLE_TONE_MAPPING
@ -63,148 +54,24 @@ vec4 applyToneMapping(vec4 color)
} }
#endif #endif
void get_texture_flags()
{
vec4 flags = texture2D(textureFlags, vec2(0.0, 0.0));
if (flags.r > 0.5) {
normalTexturePresent = true;
}
}
float intensity(vec3 color)
{
return (color.r + color.g + color.b) / 3.0;
}
float get_rgb_height(vec2 uv)
{
return intensity(texture2D(baseTexture, uv).rgb);
}
vec4 get_normal_map(vec2 uv)
{
vec4 bump = texture2D(normalTexture, uv).rgba;
bump.xyz = normalize(bump.xyz * 2.0 - 1.0);
return bump;
}
float find_intersection(vec2 dp, vec2 ds)
{
float depth = 1.0;
float best_depth = 0.0;
float size = 0.0625;
for (int i = 0; i < 15; i++) {
depth -= size;
float h = texture2D(normalTexture, dp + ds * depth).a;
if (depth <= h) {
best_depth = depth;
break;
}
}
depth = best_depth;
for (int i = 0; i < 4; i++) {
size *= 0.5;
float h = texture2D(normalTexture,dp + ds * depth).a;
if (depth <= h) {
best_depth = depth;
depth += size;
} else {
depth -= size;
}
}
return best_depth;
}
float find_intersectionRGB(vec2 dp, vec2 ds)
{
const float depth_step = 1.0 / 24.0;
float depth = 1.0;
for (int i = 0 ; i < 24 ; i++) {
float h = get_rgb_height(dp + ds * depth);
if (h >= depth)
break;
depth -= depth_step;
}
return depth;
}
void main(void) void main(void)
{ {
vec3 color; vec3 color;
vec4 bump; vec2 uv = varTexCoord.st;
vec2 uv = gl_TexCoord[0].st;
bool use_normalmap = false;
get_texture_flags();
#ifdef ENABLE_PARALLAX_OCCLUSION
vec2 eyeRay = vec2 (tsEyeVec.x, -tsEyeVec.y);
const float scale = PARALLAX_OCCLUSION_SCALE / PARALLAX_OCCLUSION_ITERATIONS;
const float bias = PARALLAX_OCCLUSION_BIAS / PARALLAX_OCCLUSION_ITERATIONS;
#if PARALLAX_OCCLUSION_MODE == 0
// Parallax occlusion with slope information
if (normalTexturePresent && area_enable_parallax > 0.0) {
for (int i = 0; i < PARALLAX_OCCLUSION_ITERATIONS; i++) {
vec4 normal = texture2D(normalTexture, uv.xy);
float h = normal.a * scale - bias;
uv += h * normal.z * eyeRay;
}
#endif
#if PARALLAX_OCCLUSION_MODE == 1
// Relief mapping
if (normalTexturePresent && area_enable_parallax > 0.0) {
vec2 ds = eyeRay * PARALLAX_OCCLUSION_SCALE;
float dist = find_intersection(uv, ds);
uv += dist * ds;
#endif
} else if (GENERATE_NORMALMAPS == 1 && area_enable_parallax > 0.0) {
vec2 ds = eyeRay * PARALLAX_OCCLUSION_SCALE;
float dist = find_intersectionRGB(uv, ds);
uv += dist * ds;
}
#endif
#if USE_NORMALMAPS == 1
if (normalTexturePresent) {
bump = get_normal_map(uv);
use_normalmap = true;
}
#endif
#if GENERATE_NORMALMAPS == 1
if (normalTexturePresent == false) {
float tl = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y + SAMPLE_STEP));
float t = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y - SAMPLE_STEP));
float tr = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y + SAMPLE_STEP));
float r = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y));
float br = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y - SAMPLE_STEP));
float b = get_rgb_height(vec2(uv.x, uv.y - SAMPLE_STEP));
float bl = get_rgb_height(vec2(uv.x -SAMPLE_STEP, uv.y - SAMPLE_STEP));
float l = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y));
float dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl);
float dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr);
bump = vec4(normalize(vec3 (dX, dY, NORMALMAPS_STRENGTH)), 1.0);
use_normalmap = true;
}
#endif
vec4 base = texture2D(baseTexture, uv).rgba; vec4 base = texture2D(baseTexture, uv).rgba;
#ifdef USE_DISCARD
#ifdef ENABLE_BUMPMAPPING // If alpha is zero, we can just discard the pixel. This fixes transparency
if (use_normalmap) { // on GPUs like GC7000L, where GL_ALPHA_TEST is not implemented in mesa,
vec3 L = normalize(lightVec); // and also on GLES 2, where GL_ALPHA_TEST is missing entirely.
vec3 E = normalize(eyeVec); if (base.a == 0.0) {
float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0), 1.0); discard;
float diffuse = dot(-E,bump.xyz);
color = (diffuse + 0.1 * specular) * base.rgb;
} else {
color = base.rgb;
} }
#else
color = base.rgb;
#endif #endif
vec4 col = vec4(color.rgb * gl_Color.rgb, 1.0); color = base.rgb;
vec4 col = vec4(color.rgb * varColor.rgb, 1.0);
#ifdef ENABLE_TONE_MAPPING #ifdef ENABLE_TONE_MAPPING
col = applyToneMapping(col); col = applyToneMapping(col);

View File

@ -1,4 +1,3 @@
uniform mat4 mWorldViewProj;
uniform mat4 mWorld; uniform mat4 mWorld;
// Color of the light emitted by the sun. // Color of the light emitted by the sun.
@ -16,12 +15,9 @@ varying vec3 vPosition;
// cameraOffset + worldPosition (for large coordinates the limits of float // cameraOffset + worldPosition (for large coordinates the limits of float
// precision must be considered). // precision must be considered).
varying vec3 worldPosition; varying vec3 worldPosition;
varying lowp vec4 varColor;
varying mediump vec2 varTexCoord;
varying vec3 eyeVec; varying vec3 eyeVec;
varying vec3 lightVec;
varying vec3 tsEyeVec;
varying vec3 tsLightVec;
varying float area_enable_parallax;
// Color of the light emitted by the light sources. // Color of the light emitted by the light sources.
const vec3 artificialLight = vec3(1.04, 1.04, 1.04); const vec3 artificialLight = vec3(1.04, 1.04, 1.04);
@ -85,25 +81,13 @@ float snoise(vec3 p)
void main(void) void main(void)
{ {
gl_TexCoord[0] = gl_MultiTexCoord0; varTexCoord = inTexCoord0.st;
//TODO: make offset depending on view angle and parallax uv displacement
//thats for textures that doesnt align vertically, like dirt with grass
//gl_TexCoord[0].y += 0.008;
//Allow parallax/relief mapping only for certain kind of nodes float disp_x;
//Variable is also used to control area of the effect float disp_z;
#if (DRAW_TYPE == NDT_NORMAL || DRAW_TYPE == NDT_LIQUID || DRAW_TYPE == NDT_FLOWINGLIQUID)
area_enable_parallax = 1.0;
#else
area_enable_parallax = 0.0;
#endif
float disp_x;
float disp_z;
// OpenGL < 4.3 does not support continued preprocessor lines // OpenGL < 4.3 does not support continued preprocessor lines
#if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES && ENABLE_WAVING_LEAVES) || (MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS && ENABLE_WAVING_PLANTS) #if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES && ENABLE_WAVING_LEAVES) || (MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS && ENABLE_WAVING_PLANTS)
vec4 pos2 = mWorld * gl_Vertex; vec4 pos2 = mWorld * inVertexPosition;
float tOffset = (pos2.x + pos2.y) * 0.001 + pos2.z * 0.002; float tOffset = (pos2.x + pos2.y) * 0.001 + pos2.z * 0.002;
disp_x = (smoothTriangleWave(animationTimer * 23.0 + tOffset) + disp_x = (smoothTriangleWave(animationTimer * 23.0 + tOffset) +
smoothTriangleWave(animationTimer * 11.0 + tOffset)) * 0.4; smoothTriangleWave(animationTimer * 11.0 + tOffset)) * 0.4;
@ -112,68 +96,43 @@ float disp_z;
smoothTriangleWave(animationTimer * 13.0 + tOffset)) * 0.5; smoothTriangleWave(animationTimer * 13.0 + tOffset)) * 0.5;
#endif #endif
worldPosition = (mWorld * gl_Vertex).xyz; worldPosition = (mWorld * inVertexPosition).xyz;
// OpenGL < 4.3 does not support continued preprocessor lines // OpenGL < 4.3 does not support continued preprocessor lines
#if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_OPAQUE || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_BASIC) && ENABLE_WAVING_WATER #if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_OPAQUE || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_BASIC) && ENABLE_WAVING_WATER
// Generate waves with Perlin-type noise. // Generate waves with Perlin-type noise.
// The constants are calibrated such that they roughly // The constants are calibrated such that they roughly
// correspond to the old sine waves. // correspond to the old sine waves.
vec4 pos = gl_Vertex; vec4 pos = inVertexPosition;
vec3 wavePos = worldPosition + cameraOffset; vec3 wavePos = worldPosition + cameraOffset;
// The waves are slightly compressed along the z-axis to get // The waves are slightly compressed along the z-axis to get
// wave-fronts along the x-axis. // wave-fronts along the x-axis.
wavePos.x /= WATER_WAVE_LENGTH * 3; wavePos.x /= WATER_WAVE_LENGTH * 3.0;
wavePos.z /= WATER_WAVE_LENGTH * 2; wavePos.z /= WATER_WAVE_LENGTH * 2.0;
wavePos.z += animationTimer * WATER_WAVE_SPEED * 10; wavePos.z += animationTimer * WATER_WAVE_SPEED * 10.0;
pos.y += (snoise(wavePos) - 1) * WATER_WAVE_HEIGHT * 5; pos.y += (snoise(wavePos) - 1.0) * WATER_WAVE_HEIGHT * 5.0;
gl_Position = mWorldViewProj * pos; gl_Position = mWorldViewProj * pos;
#elif MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES && ENABLE_WAVING_LEAVES #elif MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES && ENABLE_WAVING_LEAVES
vec4 pos = gl_Vertex; vec4 pos = inVertexPosition;
pos.x += disp_x; pos.x += disp_x;
pos.y += disp_z * 0.1; pos.y += disp_z * 0.1;
pos.z += disp_z; pos.z += disp_z;
gl_Position = mWorldViewProj * pos; gl_Position = mWorldViewProj * pos;
#elif MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS && ENABLE_WAVING_PLANTS #elif MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS && ENABLE_WAVING_PLANTS
vec4 pos = gl_Vertex; vec4 pos = inVertexPosition;
if (gl_TexCoord[0].y < 0.05) { if (varTexCoord.y < 0.05) {
pos.x += disp_x; pos.x += disp_x;
pos.z += disp_z; pos.z += disp_z;
} }
gl_Position = mWorldViewProj * pos; gl_Position = mWorldViewProj * pos;
#else #else
gl_Position = mWorldViewProj * gl_Vertex; gl_Position = mWorldViewProj * inVertexPosition;
#endif #endif
vPosition = gl_Position.xyz; vPosition = gl_Position.xyz;
// Don't generate heightmaps when too far from the eye eyeVec = -(mWorldView * inVertexPosition).xyz;
float dist = distance (vec3(0.0, 0.0, 0.0), vPosition);
if (dist > 150.0) {
area_enable_parallax = 0.0;
}
vec3 sunPosition = vec3 (0.0, eyePosition.y * BS + 900.0, 0.0);
vec3 normal, tangent, binormal;
normal = normalize(gl_NormalMatrix * gl_Normal);
tangent = normalize(gl_NormalMatrix * gl_MultiTexCoord1.xyz);
binormal = normalize(gl_NormalMatrix * gl_MultiTexCoord2.xyz);
vec3 v;
lightVec = sunPosition - worldPosition;
v.x = dot(lightVec, tangent);
v.y = dot(lightVec, binormal);
v.z = dot(lightVec, normal);
tsLightVec = normalize (v);
eyeVec = -(gl_ModelViewMatrix * gl_Vertex).xyz;
v.x = dot(eyeVec, tangent);
v.y = dot(eyeVec, binormal);
v.z = dot(eyeVec, normal);
tsEyeVec = normalize (v);
// Calculate color. // Calculate color.
// Red, green and blue components are pre-multiplied with // Red, green and blue components are pre-multiplied with
@ -182,16 +141,16 @@ float disp_z;
// The pre-baked colors are halved to prevent overflow. // The pre-baked colors are halved to prevent overflow.
vec4 color; vec4 color;
// The alpha gives the ratio of sunlight in the incoming light. // The alpha gives the ratio of sunlight in the incoming light.
float nightRatio = 1 - gl_Color.a; float nightRatio = 1.0 - inVertexColor.a;
color.rgb = gl_Color.rgb * (gl_Color.a * dayLight.rgb + color.rgb = inVertexColor.rgb * (inVertexColor.a * dayLight.rgb +
nightRatio * artificialLight.rgb) * 2; nightRatio * artificialLight.rgb) * 2.0;
color.a = 1; color.a = 1.0;
// Emphase blue a bit in darker places // Emphase blue a bit in darker places
// See C++ implementation in mapblock_mesh.cpp final_color_blend() // See C++ implementation in mapblock_mesh.cpp final_color_blend()
float brightness = (color.r + color.g + color.b) / 3; float brightness = (color.r + color.g + color.b) / 3.0;
color.b += max(0.0, 0.021 - abs(0.2 * brightness - 0.021) + color.b += max(0.0, 0.021 - abs(0.2 * brightness - 0.021) +
0.07 * brightness); 0.07 * brightness);
gl_FrontColor = gl_BackColor = clamp(color, 0.0, 1.0); varColor = clamp(color, 0.0, 1.0);
} }

View File

@ -1,6 +1,4 @@
uniform sampler2D baseTexture; uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D textureFlags;
uniform vec4 emissiveColor; uniform vec4 emissiveColor;
uniform vec4 skyBgColor; uniform vec4 skyBgColor;
@ -10,20 +8,16 @@ uniform vec3 eyePosition;
varying vec3 vNormal; varying vec3 vNormal;
varying vec3 vPosition; varying vec3 vPosition;
varying vec3 worldPosition; varying vec3 worldPosition;
varying lowp vec4 varColor;
varying mediump vec2 varTexCoord;
varying vec3 eyeVec; varying vec3 eyeVec;
varying vec3 lightVec;
varying float vIDiff; varying float vIDiff;
bool normalTexturePresent = false;
bool texTileableHorizontal = false;
bool texTileableVertical = false;
bool texSeamless = false;
const float e = 2.718281828459; const float e = 2.718281828459;
const float BS = 10.0; const float BS = 10.0;
const float fogStart = FOG_START; const float fogStart = FOG_START;
const float fogShadingParameter = 1 / ( 1 - fogStart); const float fogShadingParameter = 1.0 / (1.0 - fogStart);
#ifdef ENABLE_TONE_MAPPING #ifdef ENABLE_TONE_MAPPING
@ -57,95 +51,27 @@ vec4 applyToneMapping(vec4 color)
} }
#endif #endif
void get_texture_flags()
{
vec4 flags = texture2D(textureFlags, vec2(0.0, 0.0));
if (flags.r > 0.5) {
normalTexturePresent = true;
}
if (flags.g > 0.5) {
texTileableHorizontal = true;
}
if (flags.b > 0.5) {
texTileableVertical = true;
}
if (texTileableHorizontal && texTileableVertical) {
texSeamless = true;
}
}
float intensity(vec3 color)
{
return (color.r + color.g + color.b) / 3.0;
}
float get_rgb_height(vec2 uv)
{
if (texSeamless) {
return intensity(texture2D(baseTexture, uv).rgb);
} else {
return intensity(texture2D(baseTexture, clamp(uv, 0.0, 0.999)).rgb);
}
}
vec4 get_normal_map(vec2 uv)
{
vec4 bump = texture2D(normalTexture, uv).rgba;
bump.xyz = normalize(bump.xyz * 2.0 - 1.0);
return bump;
}
void main(void) void main(void)
{ {
vec3 color; vec3 color;
vec4 bump; vec2 uv = varTexCoord.st;
vec2 uv = gl_TexCoord[0].st;
bool use_normalmap = false;
get_texture_flags();
#if USE_NORMALMAPS == 1
if (normalTexturePresent) {
bump = get_normal_map(uv);
use_normalmap = true;
}
#endif
#if GENERATE_NORMALMAPS == 1
if (normalTexturePresent == false) {
float tl = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y + SAMPLE_STEP));
float t = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y - SAMPLE_STEP));
float tr = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y + SAMPLE_STEP));
float r = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y));
float br = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y - SAMPLE_STEP));
float b = get_rgb_height(vec2(uv.x, uv.y - SAMPLE_STEP));
float bl = get_rgb_height(vec2(uv.x -SAMPLE_STEP, uv.y - SAMPLE_STEP));
float l = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y));
float dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl);
float dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr);
bump = vec4(normalize(vec3 (dX, dY, NORMALMAPS_STRENGTH)), 1.0);
use_normalmap = true;
}
#endif
vec4 base = texture2D(baseTexture, uv).rgba; vec4 base = texture2D(baseTexture, uv).rgba;
#ifdef ENABLE_BUMPMAPPING #ifdef USE_DISCARD
if (use_normalmap) { // If alpha is zero, we can just discard the pixel. This fixes transparency
vec3 L = normalize(lightVec); // on GPUs like GC7000L, where GL_ALPHA_TEST is not implemented in mesa,
vec3 E = normalize(eyeVec); // and also on GLES 2, where GL_ALPHA_TEST is missing entirely.
float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0), 1.0); if (base.a == 0.0) {
float diffuse = dot(-E,bump.xyz); discard;
color = (diffuse + 0.1 * specular) * base.rgb;
} else {
color = base.rgb;
} }
#else
color = base.rgb;
#endif #endif
color = base.rgb;
vec4 col = vec4(color.rgb, base.a); vec4 col = vec4(color.rgb, base.a);
col.rgb *= gl_Color.rgb; col.rgb *= varColor.rgb;
col.rgb *= emissiveColor.rgb * vIDiff; col.rgb *= emissiveColor.rgb * vIDiff;

View File

@ -1,4 +1,3 @@
uniform mat4 mWorldViewProj;
uniform mat4 mWorld; uniform mat4 mWorld;
uniform vec3 eyePosition; uniform vec3 eyePosition;
@ -7,9 +6,10 @@ uniform float animationTimer;
varying vec3 vNormal; varying vec3 vNormal;
varying vec3 vPosition; varying vec3 vPosition;
varying vec3 worldPosition; varying vec3 worldPosition;
varying lowp vec4 varColor;
varying mediump vec2 varTexCoord;
varying vec3 eyeVec; varying vec3 eyeVec;
varying vec3 lightVec;
varying float vIDiff; varying float vIDiff;
const float e = 2.718281828459; const float e = 2.718281828459;
@ -19,35 +19,31 @@ float directional_ambient(vec3 normal)
{ {
vec3 v = normal * normal; vec3 v = normal * normal;
if (normal.y < 0) if (normal.y < 0.0)
return dot(v, vec3(0.670820f, 0.447213f, 0.836660f)); return dot(v, vec3(0.670820, 0.447213, 0.836660));
return dot(v, vec3(0.670820f, 1.000000f, 0.836660f)); return dot(v, vec3(0.670820, 1.000000, 0.836660));
} }
void main(void) void main(void)
{ {
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; varTexCoord = (mTexture * inTexCoord0).st;
gl_Position = mWorldViewProj * gl_Vertex; gl_Position = mWorldViewProj * inVertexPosition;
vPosition = gl_Position.xyz; vPosition = gl_Position.xyz;
vNormal = gl_Normal; vNormal = inVertexNormal;
worldPosition = (mWorld * gl_Vertex).xyz; worldPosition = (mWorld * inVertexPosition).xyz;
eyeVec = -(mWorldView * inVertexPosition).xyz;
vec3 sunPosition = vec3 (0.0, eyePosition.y * BS + 900.0, 0.0);
lightVec = sunPosition - worldPosition;
eyeVec = -(gl_ModelViewMatrix * gl_Vertex).xyz;
#if (MATERIAL_TYPE == TILE_MATERIAL_PLAIN) || (MATERIAL_TYPE == TILE_MATERIAL_PLAIN_ALPHA) #if (MATERIAL_TYPE == TILE_MATERIAL_PLAIN) || (MATERIAL_TYPE == TILE_MATERIAL_PLAIN_ALPHA)
vIDiff = 1.0; vIDiff = 1.0;
#else #else
// This is intentional comparison with zero without any margin. // This is intentional comparison with zero without any margin.
// If normal is not equal to zero exactly, then we assume it's a valid, just not normalized vector // If normal is not equal to zero exactly, then we assume it's a valid, just not normalized vector
vIDiff = length(gl_Normal) == 0.0 vIDiff = length(inVertexNormal) == 0.0
? 1.0 ? 1.0
: directional_ambient(normalize(gl_Normal)); : directional_ambient(normalize(inVertexNormal));
#endif #endif
gl_FrontColor = gl_BackColor = gl_Color; varColor = inVertexColor;
} }

View File

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

View File

@ -1,9 +1,10 @@
uniform mat4 mWorldViewProj; varying lowp vec4 varColor;
varying mediump vec2 varTexCoord;
void main(void) void main(void)
{ {
gl_TexCoord[0] = gl_MultiTexCoord0; varTexCoord = inTexCoord0.st;
gl_Position = mWorldViewProj * gl_Vertex; gl_Position = mWorldViewProj * inVertexPosition;
gl_FrontColor = gl_BackColor = gl_Color; varColor = inVertexColor;
} }

View File

@ -0,0 +1,6 @@
uniform vec4 starColor;
void main(void)
{
gl_FragColor = starColor;
}

View File

@ -0,0 +1,4 @@
void main(void)
{
gl_Position = mWorldViewProj * inVertexPosition;
}

101
doc/builtin_entities.txt Normal file
View File

@ -0,0 +1,101 @@
# Builtin Entities
Minetest registers two entities by default: Falling nodes and dropped items.
This document describes how they behave and what you can do with them.
## Falling node (`__builtin:falling_node`)
This entity is created by `minetest.check_for_falling` in place of a node
with the special group `falling_node=1`. Falling nodes can also be created
artificially with `minetest.spawn_falling_node`.
Needs manual initialization when spawned using `/spawnentity`.
Default behaviour:
* Falls down in a straight line (gravity = `movement_gravity` setting)
* Collides with `walkable` node
* Collides with all physical objects except players
* If the node group `float=1` is set, it also collides with liquid nodes
* When it hits a solid (=`walkable`) node, it will try to place itself as a
node, replacing the node above.
* If the falling node cannot replace the destination node, it is dropped.
* If the destination node is a leveled node (`paramtype2="leveled"`) of the
same node name, the levels of both are summed.
### Entity fields
* `set_node(self, node[, meta])`
* Function to initialize the falling node
* `node` and `meta` are explained below.
* The `meta` argument is optional.
* `node`: Node table of the node (`name`, `param1`, `param2`) that this
entity represents. Read-only.
* `meta`: Node metadata of the falling node. Will be used when the falling
nodes tries to place itself as a node. Read-only.
### Rendering / supported nodes
Falling nodes have visuals to look as close as possible to the original node.
This works for most drawtypes, but there are limitations.
Supported drawtypes:
* `normal`
* `signlike`
* `torchlike`
* `nodebox`
* `raillike`
* `glasslike`
* `glasslike_framed`
* `glasslike_framed_optional`
* `allfaces`
* `allfaces_optional`
* `firelike`
* `mesh`
* `fencelike`
* `liquid`
* `airlike` (not pointable)
Other drawtypes still kinda work, but they might look weird.
Supported `paramtype2` values:
* `wallmounted`
* `facedir`
* `colorwallmounted`
* `colorfacedir`
* `color`
## Dropped item stack (`__builtin:item`)
This is an item stack in a collectable form.
Common cases that spawn a dropped item:
* Item dropped by player
* The root node of a node with the group `attached_node=1` is removed
* `minetest.add_item` is called
Needs manual initialization when spawned using `/spawnentity`.
### Behavior
* Players can collect it by punching
* Lifespan is defined by the setting `item_entity_ttl`
* Slides on `slippery` nodes
* Subject to gravity (uses `movement_gravity` setting)
* Collides with `walkable` nodes
* Does not collide physical objects
* When it's inside a solid (`walkable=true`) node, it tries to escape to a
neighboring non-solid (`walkable=false`) node
### Entity fields
* `set_item(self, item)`:
* Function to initialize the dropped item
* `item` (type `ItemStack`) specifies the item to represent
* `age`: Age in seconds. Behaviour according to the setting `item_entity_ttl`
* `itemstring`: Itemstring of the item that this item entity represents.
Read-only.
Other fields are for internal use only.

View File

@ -703,6 +703,11 @@ Call these functions only at load time!
* `add` adds something to the list * `add` adds something to the list
* `del` del removes something from the list * `del` del removes something from the list
* `list` lists all items on the list * `list` lists all items on the list
* `minetest.register_on_chatcommand(function(command, params))`
* Called always when a chatcommand is triggered, before `minetest.registered_chatcommands`
is checked to see if that the command exists, but after the input is parsed.
* Return `true` to mark the command as handled, which means that the default
handlers will be prevented.
* `minetest.register_on_death(function())` * `minetest.register_on_death(function())`
* Called when the local player dies * Called when the local player dies
* `minetest.register_on_hp_modification(function(hp))` * `minetest.register_on_hp_modification(function(hp))`
@ -1303,8 +1308,8 @@ Methods:
aux1 = boolean, aux1 = boolean,
sneak = boolean, sneak = boolean,
zoom = boolean, zoom = boolean,
LMB = boolean, dig = boolean,
RMB = boolean, place = boolean,
} }
``` ```

View File

@ -62,12 +62,12 @@ Where `<gameid>` is unique to each game.
The game directory can contain the following files: The game directory can contain the following files:
* `game.conf`, with the following keys: * `game.conf`, with the following keys:
* `name`: Required, human readable name e.g. `name = Minetest` * `name`: Required, a human readable title to address the game, e.g. `name = Minetest`.
* `description`: Short description to be shown in the content tab * `description`: Short description to be shown in the content tab
* `allowed_mapgens = <comma-separated mapgens>` * `allowed_mapgens = <comma-separated mapgens>`
e.g. `allowed_mapgens = v5,v6,flat` e.g. `allowed_mapgens = v5,v6,flat`
Mapgens not in this list are removed from the list of mapgens for Mapgens not in this list are removed from the list of mapgens for the
the game. game.
If not specified, all mapgens are allowed. If not specified, all mapgens are allowed.
* `disallowed_mapgens = <comma-separated mapgens>` * `disallowed_mapgens = <comma-separated mapgens>`
e.g. `disallowed_mapgens = v5,v6,flat` e.g. `disallowed_mapgens = v5,v6,flat`
@ -79,6 +79,10 @@ The game directory can contain the following files:
e.g. `disallowed_mapgen_settings = mgv5_spflags` e.g. `disallowed_mapgen_settings = mgv5_spflags`
These settings are hidden for this game in the world creation These settings are hidden for this game in the world creation
dialog and game start menu. dialog and game start menu.
* `author`: The author of the game. It only appears when downloaded from
ContentDB.
* `release`: Ignore this: Should only ever be set by ContentDB, as it is
an internal ID used to track versions.
* `minetest.conf`: * `minetest.conf`:
Used to set default settings when running this game. Used to set default settings when running this game.
* `settingtypes.txt`: * `settingtypes.txt`:
@ -134,9 +138,15 @@ Mods can be put in a subdirectory, if the parent directory, which otherwise
should be a mod, contains a file named `modpack.conf`. should be a mod, contains a file named `modpack.conf`.
The file is a key-value store of modpack details. The file is a key-value store of modpack details.
* `name`: The modpack name. * `name`: The modpack name. Allows Minetest to determine the modpack name even
if the folder is wrongly named.
* `description`: Description of mod to be shown in the Mods tab of the main * `description`: Description of mod to be shown in the Mods tab of the main
menu. menu.
* `author`: The author of the modpack. It only appears when downloaded from
ContentDB.
* `release`: Ignore this: Should only ever be set by ContentDB, as it is an
internal ID used to track versions.
* `title`: A human-readable title to address the modpack.
Note: to support 0.4.x, please also create an empty modpack.txt file. Note: to support 0.4.x, please also create an empty modpack.txt file.
@ -152,7 +162,12 @@ Mod directory structure
│   ├── models │   ├── models
│   ├── textures │   ├── textures
│   │   ├── modname_stuff.png │   │   ├── modname_stuff.png
│   │   └── modname_something_else.png │   │   ├── modname_stuff_normal.png
│   │   ├── modname_something_else.png
│   │   ├── subfolder_foo
│   │   │ ├── modname_more_stuff.png
│   │   │ └── another_subfolder
│   │   └── bar_subfolder
│   ├── sounds │   ├── sounds
│   ├── media │   ├── media
│   ├── locale │   ├── locale
@ -176,6 +191,11 @@ A `Settings` file that provides meta information about the mod.
loaded before this mod. loaded before this mod.
* `optional_depends`: A comma separated list of optional dependencies. * `optional_depends`: A comma separated list of optional dependencies.
Like a dependency, but no error if the mod doesn't exist. Like a dependency, but no error if the mod doesn't exist.
* `author`: The author of the mod. It only appears when downloaded from
ContentDB.
* `release`: Ignore this: Should only ever be set by ContentDB, as it is an
internal ID used to track versions.
* `title`: A human-readable title to address the mod.
Note: to support 0.4.x, please also provide depends.txt. Note: to support 0.4.x, please also provide depends.txt.
@ -221,18 +241,20 @@ registered callbacks.
`minetest.settings` can be used to read custom or existing settings at load `minetest.settings` can be used to read custom or existing settings at load
time, if necessary. (See [`Settings`]) time, if necessary. (See [`Settings`])
### `models` ### `textures`, `sounds`, `media`, `models`, `locale`
Models for entities or meshnodes.
### `textures`, `sounds`, `media`
Media files (textures, sounds, whatever) that will be transferred to the Media files (textures, sounds, whatever) that will be transferred to the
client and will be available for use by the mod. client and will be available for use by the mod and translation files for
the clients (see [Translations]).
### `locale` It is suggested to use the folders for the purpous they are thought for,
eg. put textures into `textures`, translation files into `locale`,
models for entities or meshnodes into `models` et cetera.
Translation files for the clients. (See [Translations]) These folders and subfolders can contain subfolders.
Subfolders with names starting with `_` or `.` are ignored.
If a subfolder contains a media file with the same name as a media file
in one of its parents, the parent's file is used.
Naming conventions Naming conventions
------------------ ------------------
@ -378,11 +400,14 @@ stripping out the file extension:
* e.g. `foomod_foothing.png` * e.g. `foomod_foothing.png`
* e.g. `foomod_foothing` * e.g. `foomod_foothing`
Texture modifiers Texture modifiers
----------------- -----------------
There are various texture modifiers that can be used There are various texture modifiers that can be used
to generate textures on-the-fly. to let the client generate textures on-the-fly.
The modifiers are applied directly in sRGB colorspace,
i.e. without gamma-correction.
### Texture overlaying ### Texture overlaying
@ -780,7 +805,7 @@ Example (colored grass block):
-- Overlay tiles: define them in the same style -- Overlay tiles: define them in the same style
-- The top and bottom tile does not have overlay -- The top and bottom tile does not have overlay
overlay_tiles = {"", "", overlay_tiles = {"", "",
{name = "default_grass_side.png", tileable_vertical = false}}, {name = "default_grass_side.png"}},
-- Global color, used in inventory -- Global color, used in inventory
color = "green", color = "green",
-- Palette in the world -- Palette in the world
@ -1150,7 +1175,7 @@ Look for examples in `games/devtest` or `games/minetest_game`.
base cube without affecting them. base cube without affecting them.
* The base cube texture tiles are defined as normal, the `plantlike` * The base cube texture tiles are defined as normal, the `plantlike`
extension uses the defined special tile, for example: extension uses the defined special tile, for example:
`special_tiles = {{name = "default_papyrus.png", tileable_vertical = true}},` `special_tiles = {{name = "default_papyrus.png"}},`
`*_optional` drawtypes need less rendering time if deactivated `*_optional` drawtypes need less rendering time if deactivated
(always client-side). (always client-side).
@ -1414,7 +1439,32 @@ Same as `image`, but does not accept a `position`; the position is instead deter
* `world_pos`: World position of the waypoint. * `world_pos`: World position of the waypoint.
* `offset`: offset in pixels from position. * `offset`: offset in pixels from position.
### `compass`
Displays an image oriented or translated according to current heading direction.
* `size`: The size of this element. Negative values represent percentage
of the screen; e.g. `x=-100` means 100% (width).
* `scale`: Scale of the translated image (used only for dir = 2 or dir = 3).
* `text`: The name of the texture to use.
* `alignment`: The alignment of the image.
* `offset`: Offset in pixels from position.
* `dir`: How the image is rotated/translated:
* 0 - Rotate as heading direction
* 1 - Rotate in reverse direction
* 2 - Translate as landscape direction
* 3 - Translate in reverse direction
If translation is chosen, texture is repeated horizontally to fill the whole element.
### `minimap`
Displays a minimap on the HUD.
* `size`: Size of the minimap to display. Minimap should be a square to avoid
distortion.
* `alignment`: The alignment of the minimap.
* `offset`: offset in pixels from position.
Representations of simple things Representations of simple things
================================ ================================
@ -1973,8 +2023,10 @@ Item metadata only contains a key-value store.
Some of the values in the key-value store are handled specially: Some of the values in the key-value store are handled specially:
* `description`: Set the item stack's description. Defaults to * `description`: Set the item stack's description.
`idef.description`. See also: `get_description` in [`ItemStack`]
* `short_description`: Set the item stack's short description.
See also: `get_short_description` in [`ItemStack`]
* `color`: A `ColorString`, which sets the stack's color. * `color`: A `ColorString`, which sets the stack's color.
* `palette_index`: If the item has a palette, this is used to get the * `palette_index`: If the item has a palette, this is used to get the
current color from the palette. current color from the palette.
@ -2220,6 +2272,18 @@ Elements
* `frame duration`: Milliseconds between each frame. `0` means the frames don't advance. * `frame duration`: Milliseconds between each frame. `0` means the frames don't advance.
* `frame start` (Optional): The index of the frame to start on. Default `1`. * `frame start` (Optional): The index of the frame to start on. Default `1`.
### `model[<X>,<Y>;<W>,<H>;<name>;<mesh>;<textures>;<rotation X,Y>;<continuous>;<mouse control>]`
* Show a mesh model.
* `name`: Element name that can be used for styling
* `mesh`: The mesh model to use.
* `textures`: The mesh textures to use according to the mesh materials.
Texture names must be separated by commas.
* `rotation {X,Y}` (Optional): Initial rotation of the camera.
The axes are euler angles in degrees.
* `continuous` (Optional): Whether the rotation is continuous. Default `false`.
* `mouse control` (Optional): Whether the model can be controlled with the mouse. Default `true`.
### `item_image[<X>,<Y>;<W>,<H>;<item name>]` ### `item_image[<X>,<Y>;<W>,<H>;<item name>]`
* Show an inventory image of registered item/node * Show an inventory image of registered item/node
@ -2442,6 +2506,8 @@ Elements
* Simple colored box * Simple colored box
* `color` is color specified as a `ColorString`. * `color` is color specified as a `ColorString`.
If the alpha component is left blank, the box will be semitransparent. If the alpha component is left blank, the box will be semitransparent.
If the color is not specified, the box will use the options specified by
its style. If the color is specified, all styling options will be ignored.
### `dropdown[<X>,<Y>;<W>;<name>;<item 1>,<item 2>, ...,<item n>;<selected idx>;<index event>]` ### `dropdown[<X>,<Y>;<W>;<name>;<item 1>,<item 2>, ...,<item n>;<selected idx>;<index event>]`
@ -2708,21 +2774,23 @@ Setting a property to nothing will reset it to the default value. For example:
Some types may inherit styles from parent types. Some types may inherit styles from parent types.
* animated_image, inherits from image * animated_image, inherits from image
* box
* button * button
* button_exit, inherits from button * button_exit, inherits from button
* checkbox * checkbox
* scrollbar
* table
* textlist
* dropdown * dropdown
* field * field
* pwdfield, inherits from field * image
* textarea
* label
* vertlabel, inherits from field
* image_button * image_button
* item_image_button * item_image_button
* label
* pwdfield, inherits from field
* scrollbar
* tabheader * tabheader
* table
* textarea
* textlist
* vertlabel, inherits from label
### Valid Properties ### Valid Properties
@ -2731,7 +2799,18 @@ Some types may inherit styles from parent types.
* noclip - boolean, set to true to allow the element to exceed formspec bounds. * noclip - boolean, set to true to allow the element to exceed formspec bounds.
* box * box
* noclip - boolean, set to true to allow the element to exceed formspec bounds. * noclip - boolean, set to true to allow the element to exceed formspec bounds.
* Default to false in formspec_version version 3 or higher * Defaults to false in formspec_version version 3 or higher
* **Note**: `colors`, `bordercolors`, and `borderwidths` accept multiple input types:
* Single value (e.g. `#FF0`): All corners/borders.
* Two values (e.g. `red,#FFAAFF`): top-left and bottom-right,top-right and bottom-left/
top and bottom,left and right.
* Four values (e.g. `blue,#A0F,green,#FFFA`): top-left/top and rotates clockwise.
* These work similarly to CSS borders.
* colors - `ColorString`. Sets the color(s) of the box corners. Default `black`.
* bordercolors - `ColorString`. Sets the color(s) of the borders. Default `black`.
* borderwidths - Integer. Sets the width(s) of the borders in pixels. If the width is
negative, the border will extend inside the box, whereas positive extends outside
the box. A width of zero results in no border; this is default.
* button, button_exit, image_button, item_image_button * button, button_exit, image_button, item_image_button
* alpha - boolean, whether to draw alpha in bgimg. Default true. * alpha - boolean, whether to draw alpha in bgimg. Default true.
* bgcolor - color, sets button tint. * bgcolor - color, sets button tint.
@ -2764,23 +2843,24 @@ Some types may inherit styles from parent types.
* noclip - boolean, set to true to allow the element to exceed formspec bounds. * noclip - boolean, set to true to allow the element to exceed formspec bounds.
* padding - rect, adds space between the edges of the button and the content. This value is * padding - rect, adds space between the edges of the button and the content. This value is
relative to bgimg_middle. relative to bgimg_middle.
* sound - a sound to be played when clicked.
* textcolor - color, default white. * textcolor - color, default white.
* checkbox * checkbox
* noclip - boolean, set to true to allow the element to exceed formspec bounds. * noclip - boolean, set to true to allow the element to exceed formspec bounds.
* scrollbar * sound - a sound to be played when clicked.
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
* table, textlist
* font - Sets font type. See button `font` property for more information.
* font_size - Sets font size. See button `font_size` property for more information.
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
* dropdown * dropdown
* noclip - boolean, set to true to allow the element to exceed formspec bounds. * noclip - boolean, set to true to allow the element to exceed formspec bounds.
* sound - a sound to be played when clicked.
* field, pwdfield, textarea * field, pwdfield, textarea
* border - set to false to hide the textbox background and border. Default true. * border - set to false to hide the textbox background and border. Default true.
* font - Sets font type. See button `font` property for more information. * font - Sets font type. See button `font` property for more information.
* font_size - Sets font size. See button `font_size` property for more information. * font_size - Sets font size. See button `font_size` property for more information.
* noclip - boolean, set to true to allow the element to exceed formspec bounds. * noclip - boolean, set to true to allow the element to exceed formspec bounds.
* textcolor - color. Default white. * textcolor - color. Default white.
* model
* bgcolor - color, sets background color.
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
* Default to false in formspec_version version 3 or higher
* image * image
* noclip - boolean, set to true to allow the element to exceed formspec bounds. * noclip - boolean, set to true to allow the element to exceed formspec bounds.
* Default to false in formspec_version version 3 or higher * Default to false in formspec_version version 3 or higher
@ -2797,9 +2877,17 @@ Some types may inherit styles from parent types.
* fgimg_pressed - image when pressed. Defaults to fgimg when not provided. * fgimg_pressed - image when pressed. Defaults to fgimg when not provided.
* This is deprecated, use states instead. * This is deprecated, use states instead.
* NOTE: The parameters of any given image_button will take precedence over fgimg/fgimg_pressed * NOTE: The parameters of any given image_button will take precedence over fgimg/fgimg_pressed
* sound - a sound to be played when clicked.
* scrollbar
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
* tabheader * tabheader
* noclip - boolean, set to true to allow the element to exceed formspec bounds. * noclip - boolean, set to true to allow the element to exceed formspec bounds.
* sound - a sound to be played when clicked.
* textcolor - color. Default white. * textcolor - color. Default white.
* table, textlist
* font - Sets font type. See button `font` property for more information.
* font_size - Sets font size. See button `font_size` property for more information.
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
### Valid States ### Valid States
@ -3014,7 +3102,8 @@ Internally, it is implemented as a table with the 3 fields
`x`, `y` and `z`. Example: `{x = 0, y = 1, z = 0}`. `x`, `y` and `z`. Example: `{x = 0, y = 1, z = 0}`.
For the following functions, `v`, `v1`, `v2` are vectors, For the following functions, `v`, `v1`, `v2` are vectors,
`p1`, `p2` are positions: `p1`, `p2` are positions,
`s` is a scalar (a number):
* `vector.new(a[, b, c])`: * `vector.new(a[, b, c])`:
* Returns a vector. * Returns a vector.
@ -3043,10 +3132,12 @@ For the following functions, `v`, `v1`, `v2` are vectors,
* Returns in order minp, maxp vectors of the cuboid defined by `v1`, `v2`. * Returns in order minp, maxp vectors of the cuboid defined by `v1`, `v2`.
* `vector.angle(v1, v2)`: * `vector.angle(v1, v2)`:
* Returns the angle between `v1` and `v2` in radians. * Returns the angle between `v1` and `v2` in radians.
* `vector.dot(v1, v2)` * `vector.dot(v1, v2)`:
* Returns the dot product of `v1` and `v2` * Returns the dot product of `v1` and `v2`.
* `vector.cross(v1, v2)` * `vector.cross(v1, v2)`:
* Returns the cross product of `v1` and `v2` * Returns the cross product of `v1` and `v2`.
* `vector.offset(v, x, y, z)`:
* Returns the sum of the vectors `v` and `{x = x, y = y, z = z}`.
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:
@ -3058,10 +3149,12 @@ For the following functions `x` can be either a vector or a number:
* Returns a vector. * Returns a vector.
* If `x` is a vector: Returns the difference of `v` subtracted by `x`. * If `x` is a vector: Returns the difference of `v` subtracted by `x`.
* If `x` is a number: Subtracts `x` from each component of `v`. * If `x` is a number: Subtracts `x` from each component of `v`.
* `vector.multiply(v, x)`: * `vector.multiply(v, s)`:
* Returns a scaled vector or Schur product. * Returns a scaled vector.
* `vector.divide(v, x)`: * Deprecated: If `s` is a vector: Returns the Schur product.
* Returns a scaled vector or Schur quotient. * `vector.divide(v, s)`:
* Returns a scaled vector.
* Deprecated: If `s` is a vector: Returns the Schur quotient.
For the following functions `a` is an angle in radians and `r` is a rotation For the following functions `a` is an angle in radians and `r` is a rotation
vector ({x = <pitch>, y = <yaw>, z = <roll>}) where pitch, yaw and roll are vector ({x = <pitch>, y = <yaw>, z = <roll>}) where pitch, yaw and roll are
@ -4254,6 +4347,8 @@ Utilities
pathfinder_works = true, pathfinder_works = true,
-- Whether Collision info is available to an objects' on_step (5.3.0) -- Whether Collision info is available to an objects' on_step (5.3.0)
object_step_has_moveresult = true, object_step_has_moveresult = true,
-- Whether get_velocity() and add_velocity() can be used on players (5.4.0)
direct_velocity_on_players = true,
} }
* `minetest.has_feature(arg)`: returns `boolean, missing_features` * `minetest.has_feature(arg)`: returns `boolean, missing_features`
@ -4520,6 +4615,11 @@ Call these functions only at load time!
* Called always when a player says something * Called always when a player says something
* Return `true` to mark the message as handled, which means that it will * Return `true` to mark the message as handled, which means that it will
not be sent to other players. not be sent to other players.
* `minetest.register_on_chatcommand(function(name, command, params))`
* Called always when a chatcommand is triggered, before `minetest.registered_chatcommands`
is checked to see if the command exists, but after the input is parsed.
* Return `true` to mark the command as handled, which means that the default
handlers will be prevented.
* `minetest.register_on_player_receive_fields(function(player, formname, fields))` * `minetest.register_on_player_receive_fields(function(player, formname, fields))`
* Called when the server received input from `player` in a formspec with * Called when the server received input from `player` in a formspec with
the given `formname`. Specifically, this is called on any of the the given `formname`. Specifically, this is called on any of the
@ -4722,6 +4822,22 @@ Environment access
* `pos`: The position where to measure the light. * `pos`: The position where to measure the light.
* `timeofday`: `nil` for current time, `0` for night, `0.5` for day * `timeofday`: `nil` for current time, `0` for night, `0.5` for day
* Returns a number between `0` and `15` or `nil` * Returns a number between `0` and `15` or `nil`
* `nil` is returned e.g. when the map isn't loaded at `pos`
* `minetest.get_natural_light(pos[, timeofday])`
* Figures out the sunlight (or moonlight) value at pos at the given time of
day.
* `pos`: The position of the node
* `timeofday`: `nil` for current time, `0` for night, `0.5` for day
* Returns a number between `0` and `15` or `nil`
* This function tests 203 nodes in the worst case, which happens very
unlikely
* `minetest.get_artificial_light(param1)`
* Calculates the artificial light (light from e.g. torches) value from the
`param1` value.
* `param1`: The param1 value of a `paramtype = "light"` node.
* Returns a number between `0` and `15`
* Currently it's the same as `math.floor(param1 / 16)`, except that it
ensures compatibility.
* `minetest.place_node(pos, node)` * `minetest.place_node(pos, node)`
* Place node with the same effects that a player would cause * Place node with the same effects that a player would cause
* `minetest.dig_node(pos)` * `minetest.dig_node(pos)`
@ -5240,17 +5356,23 @@ Sounds
* `minetest.sound_fade(handle, step, gain)` * `minetest.sound_fade(handle, step, gain)`
* `handle` is a handle returned by `minetest.sound_play` * `handle` is a handle returned by `minetest.sound_play`
* `step` determines how fast a sound will fade. * `step` determines how fast a sound will fade.
Negative step will lower the sound volume, positive step will increase The gain will change by this much per second,
the sound volume. until it reaches the target gain.
Note: Older versions used a signed step. This is deprecated, but old
code will still work. (the client uses abs(step) to correct it)
* `gain` the target gain for the fade. * `gain` the target gain for the fade.
Fading to zero will delete the sound.
Timing Timing
------ ------
* `minetest.after(time, func, ...)` * `minetest.after(time, func, ...)` : returns job table to use as below.
* Call the function `func` after `time` seconds, may be fractional * Call the function `func` after `time` seconds, may be fractional
* Optional: Variable number of arguments that are passed to `func` * Optional: Variable number of arguments that are passed to `func`
* `job:cancel()`
* Cancels the job function from being called
Server Server
------ ------
@ -5714,6 +5836,9 @@ Global tables
* Map of registered tool definitions, indexed by name * Map of registered tool definitions, indexed by name
* `minetest.registered_entities` * `minetest.registered_entities`
* Map of registered entity prototypes, indexed by name * Map of registered entity prototypes, indexed by name
* Values in this table may be modified directly.
Note: changes to initial properties will only affect entities spawned afterwards,
as they are only read when spawning.
* `minetest.object_refs` * `minetest.object_refs`
* Map of object references, indexed by active object id * Map of object references, indexed by active object id
* `minetest.luaentities` * `minetest.luaentities`
@ -5744,6 +5869,7 @@ Global tables
* Map of registered chat command definitions, indexed by name * Map of registered chat command definitions, indexed by name
* `minetest.registered_privileges` * `minetest.registered_privileges`
* Map of registered privilege definitions, indexed by name * Map of registered privilege definitions, indexed by name
* Registered privileges can be modified directly in this table.
### Registered callback tables ### Registered callback tables
@ -5858,6 +5984,31 @@ An `InvRef` is a reference to an inventory.
`minetest.get_inventory(location)`. `minetest.get_inventory(location)`.
* returns `{type="undefined"}` in case location is not known * returns `{type="undefined"}` in case location is not known
### Callbacks
Detached & nodemeta inventories provide the following callbacks for move actions:
#### Before
The `allow_*` callbacks return how many items can be moved.
* `allow_move`/`allow_metadata_inventory_move`: Moving items in the inventory
* `allow_take`/`allow_metadata_inventory_take`: Taking items from the inventory
* `allow_put`/`allow_metadata_inventory_put`: Putting items to the inventory
#### After
The `on_*` callbacks are called after the items have been placed in the inventories.
* `on_move`/`on_metadata_inventory_move`: Moving items in the inventory
* `on_take`/`on_metadata_inventory_take`: Taking items from the inventory
* `on_put`/`on_metadata_inventory_put`: Putting items to the inventory
#### Swapping
When a player tries to put an item to a place where another item is, the items are *swapped*.
This means that all callbacks will be called twice (once for each action).
`ItemStack` `ItemStack`
----------- -----------
@ -5883,6 +6034,18 @@ an itemstring, a table or `nil`.
stack). stack).
* `set_metadata(metadata)`: (DEPRECATED) Returns true. * `set_metadata(metadata)`: (DEPRECATED) Returns true.
* `get_description()`: returns the description shown in inventory list tooltips. * `get_description()`: returns the description shown in inventory list tooltips.
* The engine uses the same as this function for item descriptions.
* Fields for finding the description, in order:
* `description` in item metadata (See [Item Metadata].)
* `description` in item definition
* item name
* `get_short_description()`: returns the short description.
* Unlike the description, this does not include new lines.
* The engine uses the same as this function for short item descriptions.
* Fields for finding the short description, in order:
* `short_description` in item metadata (See [Item Metadata].)
* `short_description` in item definition
* first line of the description (See `get_description()`.)
* `clear()`: removes all items from the stack, making it empty. * `clear()`: removes all items from the stack, making it empty.
* `replace(item)`: replace the contents of this stack. * `replace(item)`: replace the contents of this stack.
* `item` can also be an itemstring or table. * `item` can also be an itemstring or table.
@ -6036,6 +6199,19 @@ object you are working with still exists.
* `get_pos()`: returns `{x=num, y=num, z=num}` * `get_pos()`: returns `{x=num, y=num, z=num}`
* `set_pos(pos)`: `pos`=`{x=num, y=num, z=num}` * `set_pos(pos)`: `pos`=`{x=num, y=num, z=num}`
* `get_velocity()`: returns the velocity, a vector.
* `add_velocity(vel)`
* `vel` is a vector, e.g. `{x=0.0, y=2.3, z=1.0}`
* In comparison to using get_velocity, adding the velocity and then using
set_velocity, add_velocity is supposed to avoid synchronization problems.
Additionally, players also do not support set_velocity.
* If a player:
* Does not apply during free_move.
* Note that since the player speed is normalized at each move step,
increasing e.g. Y velocity beyond what would usually be achieved
(see: physics overrides) will cause existing X/Z velocity to be reduced.
* Example: `add_velocity({x=0, y=6.5, z=0})` is equivalent to
pressing the jump key (assuming default settings)
* `move_to(pos, continuous=false)` * `move_to(pos, continuous=false)`
* Does an interpolated move for Lua entities for visually smooth transitions. * Does an interpolated move for Lua entities for visually smooth transitions.
* If `continuous` is true, the Lua entity will not be moved to the current * If `continuous` is true, the Lua entity will not be moved to the current
@ -6070,12 +6246,16 @@ object you are working with still exists.
`frame_loop`. `frame_loop`.
* `set_animation_frame_speed(frame_speed)` * `set_animation_frame_speed(frame_speed)`
* `frame_speed`: number, default: `15.0` * `frame_speed`: number, default: `15.0`
* `set_attach(parent, bone, position, rotation)` * `set_attach(parent, bone, position, rotation, forced_visible)`
* `bone`: string * `bone`: string
* `position`: `{x=num, y=num, z=num}` (relative) * `position`: `{x=num, y=num, z=num}` (relative)
* `rotation`: `{x=num, y=num, z=num}` = Rotation on each axis, in degrees * `rotation`: `{x=num, y=num, z=num}` = Rotation on each axis, in degrees
* `get_attach()`: returns parent, bone, position, rotation or nil if it isn't * `forced_visible`: Boolean to control whether the attached entity
attached. should appear in first person.
* `get_attach()`: returns parent, bone, position, rotation, forced_visible,
or nil if it isn't attached.
* `get_children()`: returns a list of ObjectRefs that are attached to the
object.
* `set_detach()` * `set_detach()`
* `set_bone_position(bone, position, rotation)` * `set_bone_position(bone, position, rotation)`
* `bone`: string * `bone`: string
@ -6107,11 +6287,6 @@ object you are working with still exists.
no effect and returning `nil`. no effect and returning `nil`.
* `set_velocity(vel)` * `set_velocity(vel)`
* `vel` is a vector, e.g. `{x=0.0, y=2.3, z=1.0}` * `vel` is a vector, e.g. `{x=0.0, y=2.3, z=1.0}`
* `add_velocity(vel)`
* `vel` is a vector, e.g. `{x=0.0, y=2.3, z=1.0}`
* In comparison to using get_velocity, adding the velocity and then using
set_velocity, add_velocity is supposed to avoid synchronization problems.
* `get_velocity()`: returns the velocity, a vector
* `set_acceleration(acc)` * `set_acceleration(acc)`
* `acc` is a vector * `acc` is a vector
* `get_acceleration()`: returns the acceleration, a vector * `get_acceleration()`: returns the acceleration, a vector
@ -6119,35 +6294,37 @@ object you are working with still exists.
* `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).
* `get_rotation()`: returns the rotation, a vector (radians) * `get_rotation()`: returns the rotation, a vector (radians)
* `set_yaw(radians)`: sets the yaw (heading). * `set_yaw(yaw)`: sets the yaw in radians (heading).
* `get_yaw()`: returns number in radians * `get_yaw()`: returns number in radians
* `set_texture_mod(mod)` * `set_texture_mod(mod)`
* Set a texture modifier to the base texture, for sprites and meshes.
* When calling `set_texture_mod` again, the previous one is discarded.
* `mod` the texture modifier. See [Texture modifiers].
* `get_texture_mod()` returns current texture modifier * `get_texture_mod()` returns current texture modifier
* `set_sprite(p, num_frames, framelength, select_horiz_by_yawpitch)` * `set_sprite(start_frame, num_frames, framelength, select_x_by_camera)`
* Select sprite from spritesheet with optional animation and Dungeon Master * Specifies and starts a sprite animation
style texture selection based on yaw relative to camera * Animations iterate along the frame `y` position.
* `p`: {x=number, y=number}, the coordinate of the first frame * `start_frame`: {x=column number, y=row number}, the coordinate of the
(x: column, y: row), default: `{x=0, y=0}` first frame, default: `{x=0, y=0}`
* `num_frames`: number, default: `1` * `num_frames`: Total frames in the texture, default: `1`
* `framelength`: number, default: `0.2` * `framelength`: Time per animated frame in seconds, default: `0.2`
* `select_horiz_by_yawpitch`: boolean, this was once used for the Dungeon * `select_x_by_camera`: Only for visual = `sprite`. Changes the frame `x`
Master mob, default: `false` position according to the view direction. default: `false`.
* First column: subject facing the camera
* Second column: subject looking to the left
* Third column: subject backing the camera
* Fourth column: subject looking to the right
* Fifth column: subject viewed from above
* Sixth column: subject viewed from below
* `get_entity_name()` (**Deprecated**: Will be removed in a future version) * `get_entity_name()` (**Deprecated**: Will be removed in a future version)
* `get_luaentity()` * `get_luaentity()`
#### Player only (no-op for other objects) #### Player only (no-op for other objects)
* `get_player_name()`: returns `""` if is not a player * `get_player_name()`: returns `""` if is not a player
* `get_player_velocity()`: returns `nil` if is not a player, otherwise a * `get_player_velocity()`: **DEPRECATED**, use get_velocity() instead.
table {x, y, z} representing the player's instantaneous velocity in nodes/s table {x, y, z} representing the player's instantaneous velocity in nodes/s
* `add_player_velocity(vel)` * `add_player_velocity(vel)`: **DEPRECATED**, use add_velocity(vel) instead.
* Adds to player velocity, this happens client-side and only once.
* Does not apply during free_move.
* Note that since the player speed is normalized at each move step,
increasing e.g. Y velocity beyond what would usually be achieved
(see: physics overrides) will cause existing X/Z velocity to be reduced.
* Example: `add_player_velocity({x=0, y=6.5, z=0})` is equivalent to
pressing the jump key (assuming default settings)
* `get_look_dir()`: get camera direction as a unit vector * `get_look_dir()`: get camera direction as a unit vector
* `get_look_vertical()`: pitch in radians * `get_look_vertical()`: pitch in radians
* Angle ranges between -pi/2 and pi/2, which are straight up and down * Angle ranges between -pi/2 and pi/2, which are straight up and down
@ -6209,15 +6386,23 @@ object you are working with still exists.
* Only affects formspecs shown after this is called. * Only affects formspecs shown after this is called.
* `get_formspec_prepend(formspec)`: returns a formspec string. * `get_formspec_prepend(formspec)`: returns a formspec string.
* `get_player_control()`: returns table with player pressed keys * `get_player_control()`: returns table with player pressed keys
* The table consists of fields with boolean value representing the pressed * The table consists of fields with the following boolean values
keys, the fields are jump, right, left, LMB, RMB, sneak, aux1, down, up, zoom. representing the pressed keys: `up`, `down`, `left`, `right`, `jump`,
* example: `{jump=false, right=true, left=false, LMB=false, RMB=false, `aux1`, `sneak`, `dig`, `place`, `LMB`, `RMB`, and `zoom`.
sneak=true, aux1=false, down=false, up=false, zoom=false}` * The fields `LMB` and `RMB` are equal to `dig` and `place` respectively,
* The `zoom` field is available since 5.3 and exist only to preserve backwards compatibility.
* `get_player_control_bits()`: returns integer with bit packed player pressed * `get_player_control_bits()`: returns integer with bit packed player pressed
keys. keys. Bits:
* bit nr/meaning: 0/up, 1/down, 2/left, 3/right, 4/jump, 5/aux1, 6/sneak, * 0 - up
7/LMB, 8/RMB, 9/zoom (zoom available since 5.3) * 1 - down
* 2 - left
* 3 - right
* 4 - jump
* 5 - aux1
* 6 - sneak
* 7 - dig
* 8 - place
* 9 - zoom
* `set_physics_override(override_table)` * `set_physics_override(override_table)`
* `override_table` is a table with the following fields: * `override_table` is a table with the following fields:
* `speed`: multiplier to default walking speed value (default: `1`) * `speed`: multiplier to default walking speed value (default: `1`)
@ -6262,8 +6447,29 @@ object you are working with still exists.
* `hud_set_hotbar_selected_image(texturename)` * `hud_set_hotbar_selected_image(texturename)`
* sets image for selected item of hotbar * sets image for selected item of hotbar
* `hud_get_hotbar_selected_image`: returns texturename * `hud_get_hotbar_selected_image`: returns texturename
* `set_sky(parameters)` * `set_minimap_modes({mode, mode, ...}, selected_mode)`
* `parameters` is a table with the following optional fields: * Overrides the available minimap modes (and toggle order), and changes the
selected mode.
* `mode` is a table consisting of up to four fields:
* `type`: Available type:
* `off`: Minimap off
* `surface`: Minimap in surface mode
* `radar`: Minimap in radar mode
* `texture`: Texture to be displayed instead of terrain map
(texture is centered around 0,0 and can be scaled).
Texture size is limited to 512 x 512 pixel.
* `label`: Optional label to display on minimap mode toggle
The translation must be handled within the mod.
* `size`: Sidelength or diameter, in number of nodes, of the terrain
displayed in minimap
* `texture`: Only for texture type, name of the texture to display
* `scale`: Only for texture type, scale of the texture map in nodes per
pixel (for example a `scale` of 2 means each pixel represents a 2x2
nodes square)
* `selected_mode` is the mode index to be selected after modes have been changed
(0 is the first mode).
* `set_sky(sky_parameters)`
* `sky_parameters` is a table with the following optional fields:
* `base_color`: ColorSpec, changes fog in "skybox" and "plain". * `base_color`: ColorSpec, changes fog in "skybox" and "plain".
* `type`: Available types: * `type`: Available types:
* `"regular"`: Uses 0 textures, `base_color` ignored * `"regular"`: Uses 0 textures, `base_color` ignored
@ -6307,8 +6513,8 @@ object you are working with still exists.
* `get_sky()`: returns base_color, type, table of textures, clouds. * `get_sky()`: returns base_color, type, table of textures, clouds.
* `get_sky_color()`: returns a table with the `sky_color` parameters as in * `get_sky_color()`: returns a table with the `sky_color` parameters as in
`set_sky`. `set_sky`.
* `set_sun(parameters)`: * `set_sun(sun_parameters)`:
* `parameters` is a table with the following optional fields: * `sun_parameters` is a table with the following optional fields:
* `visible`: Boolean for whether the sun is visible. * `visible`: Boolean for whether the sun is visible.
(default: `true`) (default: `true`)
* `texture`: A regular texture for the sun. Setting to `""` * `texture`: A regular texture for the sun. Setting to `""`
@ -6322,8 +6528,8 @@ object you are working with still exists.
* `scale`: Float controlling the overall size of the sun. (default: `1`) * `scale`: Float controlling the overall size of the sun. (default: `1`)
* `get_sun()`: returns a table with the current sun parameters as in * `get_sun()`: returns a table with the current sun parameters as in
`set_sun`. `set_sun`.
* `set_moon(parameters)`: * `set_moon(moon_parameters)`:
* `parameters` is a table with the following optional fields: * `moon_parameters` is a table with the following optional fields:
* `visible`: Boolean for whether the moon is visible. * `visible`: Boolean for whether the moon is visible.
(default: `true`) (default: `true`)
* `texture`: A regular texture for the moon. Setting to `""` * `texture`: A regular texture for the moon. Setting to `""`
@ -6333,8 +6539,8 @@ object you are working with still exists.
* `scale`: Float controlling the overall size of the moon (default: `1`) * `scale`: Float controlling the overall size of the moon (default: `1`)
* `get_moon()`: returns a table with the current moon parameters as in * `get_moon()`: returns a table with the current moon parameters as in
`set_moon`. `set_moon`.
* `set_stars(parameters)`: * `set_stars(star_parameters)`:
* `parameters` is a table with the following optional fields: * `star_parameters` is a table with the following optional fields:
* `visible`: Boolean for whether the stars are visible. * `visible`: Boolean for whether the stars are visible.
(default: `true`) (default: `true`)
* `count`: Integer number to set the number of stars in * `count`: Integer number to set the number of stars in
@ -6346,8 +6552,8 @@ object you are working with still exists.
* `scale`: Float controlling the overall size of the stars (default: `1`) * `scale`: Float controlling the overall size of the stars (default: `1`)
* `get_stars()`: returns a table with the current stars parameters as in * `get_stars()`: returns a table with the current stars parameters as in
`set_stars`. `set_stars`.
* `set_clouds(parameters)`: set cloud parameters * `set_clouds(cloud_parameters)`: set cloud parameters
* `parameters` is a table with the following optional fields: * `cloud_parameters` is a table with the following optional fields:
* `density`: from `0` (no clouds) to `1` (full clouds) (default `0.4`) * `density`: from `0` (no clouds) to `1` (full clouds) (default `0.4`)
* `color`: basic cloud color with alpha channel, ColorSpec * `color`: basic cloud color with alpha channel, ColorSpec
(default `#fff0f0e5`). (default `#fff0f0e5`).
@ -6365,21 +6571,17 @@ object you are working with still exists.
amount. amount.
* `nil`: Disables override, defaulting to sunlight based on day-night cycle * `nil`: Disables override, defaulting to sunlight based on day-night cycle
* `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(stand/idle, walk, dig, walk+dig, frame_speed=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.
* Every animation equals to a `{x=starting frame, y=ending frame}` table.
set_local_animation({x=0, y=79}, -- stand/idle animation key frames * `frame_speed` sets the animations frame speed. Default is 30.
{x=168, y=187}, -- walk animation key frames * `get_local_animation()`: returns idle, walk, dig, walk_while_dig tables and
{x=189, y=198}, -- dig animation key frames
{x=200, y=219}, -- walk+dig animation key frames
frame_speed=30) -- animation frame speed
* `get_local_animation()`: returns stand, walk, dig, dig+walk tables and
`frame_speed`. `frame_speed`.
* `set_eye_offset({x=0,y=0,z=0},{x=0,y=0,z=0})`: defines offset value for * `set_eye_offset(firstperson, thirdperson)`: defines offset vectors for camera
camera per player. per player.
* in first person view * in first person view
* in third person view (max. values `{x=-10/10,y=-10,15,z=-5/5}`) * in third person view (max. values `{x=-10/10,y=-10,15,z=-5/5}`)
* `get_eye_offset()`: returns `offset_first` and `offset_third` * `get_eye_offset()`: returns first and third person offsets.
* `send_mapblock(blockpos)`: * `send_mapblock(blockpos)`:
* Sends a server-side loaded mapblock to the player. * Sends a server-side loaded mapblock to the player.
* Returns `false` if failed. * Returns `false` if failed.
@ -6751,6 +6953,10 @@ Player properties need to be saved manually.
shaded = true, shaded = true,
-- Setting this to 'false' disables diffuse lighting of entity -- Setting this to 'false' disables diffuse lighting of entity
show_on_minimap = false,
-- Defaults to true for players, false for other entities.
-- If set to true the entity will show as a marker on the minimap.
} }
Entity definition Entity definition
@ -6885,13 +7091,8 @@ Tile definition
* `"image.png"` * `"image.png"`
* `{name="image.png", animation={Tile Animation definition}}` * `{name="image.png", animation={Tile Animation definition}}`
* `{name="image.png", backface_culling=bool, tileable_vertical=bool, * `{name="image.png", backface_culling=bool, align_style="node"/"world"/"user", scale=int}`
tileable_horizontal=bool, align_style="node"/"world"/"user", scale=int}`
* backface culling enabled by default for most nodes * backface culling enabled by default for most nodes
* tileable flags are info for shaders, how they should treat texture
when displacement mapping is used.
Directions are from the point of view of the tile texture,
not the node it's on.
* align style determines whether the texture will be rotated with the node * align style determines whether the texture will be rotated with the node
or kept aligned with its surroundings. "user" means that client or kept aligned with its surroundings. "user" means that client
setting will be used, similar to `glasslike_framed_optional`. setting will be used, similar to `glasslike_framed_optional`.
@ -6944,6 +7145,13 @@ Used by `minetest.register_node`, `minetest.register_craftitem`, and
{ {
description = "Steel Axe", description = "Steel Axe",
-- Can contain new lines. "\n" has to be used as new line character.
-- See also: `get_description` in [`ItemStack`]
short_description = "Steel Axe",
-- Must not contain new lines.
-- Defaults to the first line of description.
-- See also: `get_short_description` in [`ItemStack`]
groups = {}, groups = {},
-- key = name, value = rating; rating = 1..3. -- key = name, value = rating; rating = 1..3.
@ -6982,6 +7190,13 @@ Used by `minetest.register_node`, `minetest.register_craftitem`, and
liquids_pointable = false, liquids_pointable = false,
light_source = 0,
-- When used for nodes: Defines amount of light emitted by node.
-- Otherwise: Defines texture glow when viewed as a dropped item
-- To set the maximum (14), use the value 'minetest.LIGHT_MAX'.
-- A value outside the range 0 to minetest.LIGHT_MAX causes undefined
-- behavior.
-- See "Tools" section for an example including explanation -- See "Tools" section for an example including explanation
tool_capabilities = { tool_capabilities = {
full_punch_interval = 1.0, full_punch_interval = 1.0,
@ -7111,6 +7326,8 @@ Used by `minetest.register_node`.
use_texture_alpha = false, use_texture_alpha = false,
-- Use texture's alpha channel -- Use texture's alpha channel
-- If this is set to false, the node will be rendered fully opaque
-- regardless of any texture transparency.
palette = "palette.png", palette = "palette.png",
-- The node's `param2` is used to select a pixel from the image. -- The node's `param2` is used to select a pixel from the image.
@ -7179,12 +7396,6 @@ Used by `minetest.register_node`.
drowning = 0, drowning = 0,
-- Player will take this amount of damage if no bubbles are left -- Player will take this amount of damage if no bubbles are left
light_source = 0,
-- Amount of light emitted by node.
-- To set the maximum (14), use the value 'minetest.LIGHT_MAX'.
-- A value outside the range 0 to minetest.LIGHT_MAX causes undefined
-- behavior.
damage_per_second = 0, damage_per_second = 0,
-- If player is inside node, this damage is caused -- If player is inside node, this damage is caused
@ -7263,10 +7474,13 @@ Used by `minetest.register_node`.
-- Node was placed. Also played after falling -- Node was placed. Also played after falling
place_failed = <SimpleSoundSpec>, place_failed = <SimpleSoundSpec>,
-- When node placement failed -- When node placement failed.
-- Note: This happens if the _built-in_ node placement failed.
-- This sound will still be played if the node is placed in the
-- `on_place` callback manually.
fall = <SimpleSoundSpec>, fall = <SimpleSoundSpec>,
-- When node starts to fall -- When node starts to fall or is detached
}, },
drop = "", drop = "",
@ -7853,6 +8067,8 @@ Used by `minetest.register_chatcommand`.
func = function(name, param), func = function(name, param),
-- Called when command is run. Returns boolean success and text output. -- Called when command is run. Returns boolean success and text output.
-- Special case: The help message is shown to the player if `func`
-- returns false without a text output.
} }
Note that in params, use of symbols is as follows: Note that in params, use of symbols is as follows:
@ -7935,7 +8151,8 @@ Used by `Player:hud_add`. Returned by `Player:hud_get`.
{ {
hud_elem_type = "image", -- See HUD element types hud_elem_type = "image", -- See HUD element types
-- Type of element, can be "image", "text", "statbar", or "inventory" -- Type of element, can be "image", "text", "statbar", "inventory",
-- "compass" or "minimap"
position = {x=0.5, y=0.5}, position = {x=0.5, y=0.5},
-- Left corner position of element -- Left corner position of element
@ -8103,6 +8320,66 @@ Used by `minetest.add_particlespawner`.
-- Otherwise, the default behavior is used. (currently: any random tile) -- Otherwise, the default behavior is used. (currently: any random tile)
} }
`HTTPRequest` definition
------------------------
Used by `HTTPApiTable.fetch` and `HTTPApiTable.fetch_async`.
{
url = "http://example.org",
timeout = 10,
-- Timeout for connection in seconds. Default is 3 seconds.
method = "GET", "POST", "PUT" or "DELETE"
-- The http method to use. Defaults to "GET".
data = "Raw request data string" OR {field1 = "data1", field2 = "data2"},
-- Data for the POST, PUT or DELETE request.
-- Accepts both a string and a table. If a table is specified, encodes
-- table as x-www-form-urlencoded key-value pairs.
user_agent = "ExampleUserAgent",
-- Optional, if specified replaces the default minetest user agent with
-- given string
extra_headers = { "Accept-Language: en-us", "Accept-Charset: utf-8" },
-- Optional, if specified adds additional headers to the HTTP request.
-- You must make sure that the header strings follow HTTP specification
-- ("Key: Value").
multipart = boolean
-- Optional, if true performs a multipart HTTP request.
-- Default is false.
-- Post only, data must be array
post_data = "Raw POST request data string" OR {field1 = "data1", field2 = "data2"},
-- Deprecated, use `data` instead. Forces `method = "POST"`.
}
`HTTPRequestResult` definition
------------------------------
Passed to `HTTPApiTable.fetch` callback. Returned by
`HTTPApiTable.fetch_async_get`.
{
completed = true,
-- If true, the request has finished (either succeeded, failed or timed
-- out)
succeeded = true,
-- If true, the request was successful
timeout = false,
-- If true, the request timed out
code = 200,
-- HTTP status code
data = "response"
}
Authentication handler definition Authentication handler definition
--------------------------------- ---------------------------------

View File

@ -90,6 +90,7 @@ by texture packs. All existing fallback textures can be found in the directory
* `minimap_mask_square.png`: mask used for the square minimap * `minimap_mask_square.png`: mask used for the square minimap
* `minimap_overlay_round.png`: overlay texture for the round minimap * `minimap_overlay_round.png`: overlay texture for the round minimap
* `minimap_overlay_square.png`: overlay texture for the square minimap * `minimap_overlay_square.png`: overlay texture for the square minimap
* `no_texture_airlike.png`: fallback inventory image for airlike nodes
* `object_marker_red.png`: texture for players on the minimap * `object_marker_red.png`: texture for players on the minimap
* `player_marker.png`: texture for the own player on the square minimap * `player_marker.png`: texture for the own player on the square minimap
@ -194,11 +195,27 @@ Here are targets you can choose from:
| bottom | y- face | | bottom | y- face |
| sides | x-, x+, z-, z+ faces | | sides | x-, x+, z-, z+ faces |
| all | All faces. You can also use '*' instead of 'all'. | | all | All faces. You can also use '*' instead of 'all'. |
| special1 | The first entry in the special_tiles list |
| special2 | The second entry in the special_tiles list |
| special3 | The third entry in the special_tiles list |
| special4 | The fourth entry in the special_tiles list |
| special5 | The fifth entry in the special_tiles list |
| special6 | The sixth entry in the special_tiles list |
| inventory | The inventory texture | | inventory | The inventory texture |
| wield | The texture used when held by the player | | wield | The texture used when held by the player |
Nodes support all targets, but other items only support 'inventory' Nodes support all targets, but other items only support 'inventory'
and 'wield' and 'wield'.
### Using the special targets
The special* targets only apply to specific drawtypes:
* `flowingliquid`: special1 sets the top texture, special2 sets the side texture
* `allfaces_optional`: special1 is used by simple mode, see below
* `glasslike_framed`: When containing a liquid, special1 sets the liquid texture
* `glasslike_framed_optional`: Same as `glasslike_framed`
* `plantlike_rooted`: special1 sets the plant's texture
Designing leaves textures for the leaves rendering options Designing leaves textures for the leaves rendering options
---------------------------------------------------------- ----------------------------------------------------------

View File

@ -1,4 +1,4 @@
Copyright (C) 2008 The Android Open Source Project Copyright (C) 2012 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

Binary file not shown.

View File

@ -23,9 +23,8 @@ Basically, just create a world and start. A few important things to note:
* Use the `/infplace` command to toggle infinite node placement in-game * Use the `/infplace` command to toggle infinite node placement in-game
* Use the Param2 Tool to change the param2 of nodes; it's useful to experiment with the various drawtype test nodes * Use the Param2 Tool to change the param2 of nodes; it's useful to experiment with the various drawtype test nodes
* Check out the game settings and server commands for additional tests and features * Check out the game settings and server commands for additional tests and features
* Creative Mode does nothing (apart from default engine behavior)
Confused by a certain node or item? Check out for inline code comments. Confused by a certain node or item? Check out for inline code comments. The usages of most tools are explained in their tooltips.
### Example tests ### Example tests

View File

@ -124,8 +124,10 @@ minetest.register_node("basenodes:pine_needles", {
}) })
minetest.register_node("basenodes:water_source", { minetest.register_node("basenodes:water_source", {
description = "Water Source", description = "Water Source".."\n"..
"Drowning damage: 1",
drawtype = "liquid", drawtype = "liquid",
waving = 3,
tiles = {"default_water.png"}, tiles = {"default_water.png"},
special_tiles = { special_tiles = {
{name = "default_water.png", backface_culling = false}, {name = "default_water.png", backface_culling = false},
@ -148,8 +150,10 @@ minetest.register_node("basenodes:water_source", {
}) })
minetest.register_node("basenodes:water_flowing", { minetest.register_node("basenodes:water_flowing", {
description = "Flowing Water", description = "Flowing Water".."\n"..
"Drowning damage: 1",
drawtype = "flowingliquid", drawtype = "flowingliquid",
waving = 3,
tiles = {"default_water_flowing.png"}, tiles = {"default_water_flowing.png"},
special_tiles = { special_tiles = {
{name = "default_water_flowing.png", backface_culling = false}, {name = "default_water_flowing.png", backface_culling = false},
@ -173,8 +177,10 @@ minetest.register_node("basenodes:water_flowing", {
}) })
minetest.register_node("basenodes:river_water_source", { minetest.register_node("basenodes:river_water_source", {
description = "River Water Source", description = "River Water Source".."\n"..
"Drowning damage: 1",
drawtype = "liquid", drawtype = "liquid",
waving = 3,
tiles = { "default_river_water.png" }, tiles = { "default_river_water.png" },
special_tiles = { special_tiles = {
{name = "default_river_water.png", backface_culling = false}, {name = "default_river_water.png", backface_culling = false},
@ -199,8 +205,10 @@ minetest.register_node("basenodes:river_water_source", {
}) })
minetest.register_node("basenodes:river_water_flowing", { minetest.register_node("basenodes:river_water_flowing", {
description = "Flowing River Water", description = "Flowing River Water".."\n"..
"Drowning damage: 1",
drawtype = "flowingliquid", drawtype = "flowingliquid",
waving = 3,
tiles = {"default_river_water_flowing.png"}, tiles = {"default_river_water_flowing.png"},
special_tiles = { special_tiles = {
{name = "default_river_water_flowing.png", backface_culling = false}, {name = "default_river_water_flowing.png", backface_culling = false},
@ -226,7 +234,9 @@ minetest.register_node("basenodes:river_water_flowing", {
}) })
minetest.register_node("basenodes:lava_flowing", { minetest.register_node("basenodes:lava_flowing", {
description = "Flowing Lava", description = "Flowing Lava".."\n"..
"4 damage per second".."\n"..
"Drowning damage: 1",
drawtype = "flowingliquid", drawtype = "flowingliquid",
tiles = {"default_lava_flowing.png"}, tiles = {"default_lava_flowing.png"},
special_tiles = { special_tiles = {
@ -251,7 +261,9 @@ minetest.register_node("basenodes:lava_flowing", {
}) })
minetest.register_node("basenodes:lava_source", { minetest.register_node("basenodes:lava_source", {
description = "Lava Source", description = "Lava Source".."\n"..
"4 damage per second".."\n"..
"Drowning damage: 1",
drawtype = "liquid", drawtype = "liquid",
tiles = { "default_lava.png" }, tiles = { "default_lava.png" },
special_tiles = { special_tiles = {
@ -290,7 +302,8 @@ minetest.register_node("basenodes:mossycobble", {
}) })
minetest.register_node("basenodes:apple", { minetest.register_node("basenodes:apple", {
description = "Apple", description = "Apple".."\n"..
"Food (+2)",
drawtype = "plantlike", drawtype = "plantlike",
tiles ={"default_apple.png"}, tiles ={"default_apple.png"},
inventory_image = "default_apple.png", inventory_image = "default_apple.png",

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 B

View File

@ -0,0 +1,3 @@
This is for testing loading textures from subfolders.
If it works correctly, the default_grass_side.png file in this folder is used but
default_grass.png is not overwritten by the file in this folder.

View File

@ -6,7 +6,7 @@
Tool types: Tool types:
* Hand: basic tool/weapon (just for convenience, not optimized for testing) * Hand: basic tool/weapon (special capabilities in creative mode)
* Pickaxe: dig cracky * Pickaxe: dig cracky
* Axe: dig choppy * Axe: dig choppy
* Shovel: dig crumbly * Shovel: dig crumbly
@ -24,25 +24,54 @@ Tool materials:
]] ]]
-- The hand -- The hand
minetest.register_item(":", { if minetest.settings:get_bool("creative_mode") then
type = "none", local digtime = 42
wield_image = "wieldhand.png", local caps = {times = {digtime, digtime, digtime}, uses = 0, maxlevel = 256}
wield_scale = {x=1,y=1,z=2.5},
tool_capabilities = { minetest.register_item(":", {
full_punch_interval = 1.0, type = "none",
max_drop_level = 0, wield_image = "wieldhand.png",
groupcaps = { wield_scale = {x = 1, y = 1, z = 2.5},
crumbly = {times={[3]=1.50}, uses=0, maxlevel=0}, range = 10,
snappy = {times={[3]=1.50}, uses=0, maxlevel=0}, tool_capabilities = {
oddly_breakable_by_hand = {times={[1]=7.00,[2]=4.00,[3]=2.00}, uses=0, maxlevel=0}, full_punch_interval = 0.5,
}, max_drop_level = 3,
damage_groups = {fleshy=1}, groupcaps = {
} crumbly = caps,
}) cracky = caps,
snappy = caps,
choppy = caps,
oddly_breakable_by_hand = caps,
-- dig_immediate group doesn't use value 1. Value 3 is instant dig
dig_immediate =
{times = {[2] = digtime, [3] = 0}, uses = 0, maxlevel = 256},
},
damage_groups = {fleshy = 10},
}
})
else
minetest.register_item(":", {
type = "none",
wield_image = "wieldhand.png",
wield_scale = {x = 1, y = 1, z = 2.5},
tool_capabilities = {
full_punch_interval = 0.9,
max_drop_level = 0,
groupcaps = {
crumbly = {times = {[2] = 3.00, [3] = 0.70}, uses = 0, maxlevel = 1},
snappy = {times = {[3] = 0.40}, uses = 0, maxlevel = 1},
oddly_breakable_by_hand =
{times = {[1] = 3.50, [2] = 2.00, [3] = 0.70}, uses = 0}
},
damage_groups = {fleshy = 1},
}
})
end
-- Mese Pickaxe: special tool that digs "everything" instantly -- Mese Pickaxe: special tool that digs "everything" instantly
minetest.register_tool("basetools:pick_mese", { minetest.register_tool("basetools:pick_mese", {
description = "Mese Pickaxe", description = "Mese Pickaxe".."\n"..
"Digs diggable nodes instantly",
inventory_image = "basetools_mesepick.png", inventory_image = "basetools_mesepick.png",
tool_capabilities = { tool_capabilities = {
full_punch_interval = 1.0, full_punch_interval = 1.0,
@ -65,7 +94,9 @@ minetest.register_tool("basetools:pick_mese", {
-- This should break after only 1 use -- This should break after only 1 use
minetest.register_tool("basetools:pick_dirt", { minetest.register_tool("basetools:pick_dirt", {
description = "Dirt Pickaxe", description = "Dirt Pickaxe".."\n"..
"Digs cracky=3".."\n"..
"1 use only",
inventory_image = "basetools_dirtpick.png", inventory_image = "basetools_dirtpick.png",
tool_capabilities = { tool_capabilities = {
max_drop_level=0, max_drop_level=0,
@ -76,7 +107,8 @@ minetest.register_tool("basetools:pick_dirt", {
}) })
minetest.register_tool("basetools:pick_wood", { minetest.register_tool("basetools:pick_wood", {
description = "Wooden Pickaxe", description = "Wooden Pickaxe".."\n"..
"Digs cracky=3",
inventory_image = "basetools_woodpick.png", inventory_image = "basetools_woodpick.png",
tool_capabilities = { tool_capabilities = {
max_drop_level=0, max_drop_level=0,
@ -86,7 +118,8 @@ minetest.register_tool("basetools:pick_wood", {
}, },
}) })
minetest.register_tool("basetools:pick_stone", { minetest.register_tool("basetools:pick_stone", {
description = "Stone Pickaxe", description = "Stone Pickaxe".."\n"..
"Digs cracky=2..3",
inventory_image = "basetools_stonepick.png", inventory_image = "basetools_stonepick.png",
tool_capabilities = { tool_capabilities = {
max_drop_level=0, max_drop_level=0,
@ -96,7 +129,8 @@ minetest.register_tool("basetools:pick_stone", {
}, },
}) })
minetest.register_tool("basetools:pick_steel", { minetest.register_tool("basetools:pick_steel", {
description = "Steel Pickaxe", description = "Steel Pickaxe".."\n"..
"Digs cracky=1..3",
inventory_image = "basetools_steelpick.png", inventory_image = "basetools_steelpick.png",
tool_capabilities = { tool_capabilities = {
max_drop_level=1, max_drop_level=1,
@ -106,7 +140,9 @@ minetest.register_tool("basetools:pick_steel", {
}, },
}) })
minetest.register_tool("basetools:pick_steel_l1", { minetest.register_tool("basetools:pick_steel_l1", {
description = "Steel Pickaxe Level 1", description = "Steel Pickaxe Level 1".."\n"..
"Digs cracky=1..3".."\n"..
"maxlevel=1",
inventory_image = "basetools_steelpick_l1.png", inventory_image = "basetools_steelpick_l1.png",
tool_capabilities = { tool_capabilities = {
max_drop_level=1, max_drop_level=1,
@ -116,7 +152,9 @@ minetest.register_tool("basetools:pick_steel_l1", {
}, },
}) })
minetest.register_tool("basetools:pick_steel_l2", { minetest.register_tool("basetools:pick_steel_l2", {
description = "Steel Pickaxe Level 2", description = "Steel Pickaxe Level 2".."\n"..
"Digs cracky=1..3".."\n"..
"maxlevel=2",
inventory_image = "basetools_steelpick_l2.png", inventory_image = "basetools_steelpick_l2.png",
tool_capabilities = { tool_capabilities = {
max_drop_level=1, max_drop_level=1,
@ -131,7 +169,8 @@ minetest.register_tool("basetools:pick_steel_l2", {
-- --
minetest.register_tool("basetools:shovel_wood", { minetest.register_tool("basetools:shovel_wood", {
description = "Wooden Shovel", description = "Wooden Shovel".."\n"..
"Digs crumbly=3",
inventory_image = "basetools_woodshovel.png", inventory_image = "basetools_woodshovel.png",
tool_capabilities = { tool_capabilities = {
max_drop_level=0, max_drop_level=0,
@ -141,7 +180,8 @@ minetest.register_tool("basetools:shovel_wood", {
}, },
}) })
minetest.register_tool("basetools:shovel_stone", { minetest.register_tool("basetools:shovel_stone", {
description = "Stone Shovel", description = "Stone Shovel".."\n"..
"Digs crumbly=2..3",
inventory_image = "basetools_stoneshovel.png", inventory_image = "basetools_stoneshovel.png",
tool_capabilities = { tool_capabilities = {
max_drop_level=0, max_drop_level=0,
@ -151,7 +191,8 @@ minetest.register_tool("basetools:shovel_stone", {
}, },
}) })
minetest.register_tool("basetools:shovel_steel", { minetest.register_tool("basetools:shovel_steel", {
description = "Steel Shovel", description = "Steel Shovel".."\n"..
"Digs crumbly=1..3",
inventory_image = "basetools_steelshovel.png", inventory_image = "basetools_steelshovel.png",
tool_capabilities = { tool_capabilities = {
max_drop_level=1, max_drop_level=1,
@ -166,7 +207,8 @@ minetest.register_tool("basetools:shovel_steel", {
-- --
minetest.register_tool("basetools:axe_wood", { minetest.register_tool("basetools:axe_wood", {
description = "Wooden Axe", description = "Wooden Axe".."\n"..
"Digs choppy=3",
inventory_image = "basetools_woodaxe.png", inventory_image = "basetools_woodaxe.png",
tool_capabilities = { tool_capabilities = {
max_drop_level=0, max_drop_level=0,
@ -176,7 +218,8 @@ minetest.register_tool("basetools:axe_wood", {
}, },
}) })
minetest.register_tool("basetools:axe_stone", { minetest.register_tool("basetools:axe_stone", {
description = "Stone Axe", description = "Stone Axe".."\n"..
"Digs choppy=2..3",
inventory_image = "basetools_stoneaxe.png", inventory_image = "basetools_stoneaxe.png",
tool_capabilities = { tool_capabilities = {
max_drop_level=0, max_drop_level=0,
@ -186,7 +229,8 @@ minetest.register_tool("basetools:axe_stone", {
}, },
}) })
minetest.register_tool("basetools:axe_steel", { minetest.register_tool("basetools:axe_steel", {
description = "Steel Axe", description = "Steel Axe".."\n"..
"Digs choppy=1..3",
inventory_image = "basetools_steelaxe.png", inventory_image = "basetools_steelaxe.png",
tool_capabilities = { tool_capabilities = {
max_drop_level=1, max_drop_level=1,
@ -201,7 +245,8 @@ minetest.register_tool("basetools:axe_steel", {
-- --
minetest.register_tool("basetools:shears_wood", { minetest.register_tool("basetools:shears_wood", {
description = "Wooden Shears", description = "Wooden Shears".."\n"..
"Digs snappy=3",
inventory_image = "basetools_woodshears.png", inventory_image = "basetools_woodshears.png",
tool_capabilities = { tool_capabilities = {
max_drop_level=0, max_drop_level=0,
@ -211,7 +256,8 @@ minetest.register_tool("basetools:shears_wood", {
}, },
}) })
minetest.register_tool("basetools:shears_stone", { minetest.register_tool("basetools:shears_stone", {
description = "Stone Shears", description = "Stone Shears".."\n"..
"Digs snappy=2..3",
inventory_image = "basetools_stoneshears.png", inventory_image = "basetools_stoneshears.png",
tool_capabilities = { tool_capabilities = {
max_drop_level=0, max_drop_level=0,
@ -221,7 +267,8 @@ minetest.register_tool("basetools:shears_stone", {
}, },
}) })
minetest.register_tool("basetools:shears_steel", { minetest.register_tool("basetools:shears_steel", {
description = "Steel Shears", description = "Steel Shears".."\n"..
"Digs snappy=1..3",
inventory_image = "basetools_steelshears.png", inventory_image = "basetools_steelshears.png",
tool_capabilities = { tool_capabilities = {
max_drop_level=1, max_drop_level=1,
@ -236,7 +283,8 @@ minetest.register_tool("basetools:shears_steel", {
-- --
minetest.register_tool("basetools:sword_wood", { minetest.register_tool("basetools:sword_wood", {
description = "Wooden Sword", description = "Wooden Sword".."\n"..
"Damage: fleshy=2",
inventory_image = "basetools_woodsword.png", inventory_image = "basetools_woodsword.png",
tool_capabilities = { tool_capabilities = {
full_punch_interval = 1.0, full_punch_interval = 1.0,
@ -244,7 +292,8 @@ minetest.register_tool("basetools:sword_wood", {
} }
}) })
minetest.register_tool("basetools:sword_stone", { minetest.register_tool("basetools:sword_stone", {
description = "Stone Sword", description = "Stone Sword".."\n"..
"Damage: fleshy=4",
inventory_image = "basetools_stonesword.png", inventory_image = "basetools_stonesword.png",
tool_capabilities = { tool_capabilities = {
full_punch_interval = 1.0, full_punch_interval = 1.0,
@ -253,7 +302,8 @@ minetest.register_tool("basetools:sword_stone", {
} }
}) })
minetest.register_tool("basetools:sword_steel", { minetest.register_tool("basetools:sword_steel", {
description = "Steel Sword", description = "Steel Sword".."\n"..
"Damage: fleshy=6",
inventory_image = "basetools_steelsword.png", inventory_image = "basetools_steelsword.png",
tool_capabilities = { tool_capabilities = {
full_punch_interval = 1.0, full_punch_interval = 1.0,
@ -264,7 +314,8 @@ minetest.register_tool("basetools:sword_steel", {
-- Fire/Ice sword: Deal damage to non-fleshy damage groups -- Fire/Ice sword: Deal damage to non-fleshy damage groups
minetest.register_tool("basetools:sword_fire", { minetest.register_tool("basetools:sword_fire", {
description = "Fire Sword", description = "Fire Sword".."\n"..
"Damage: icy=6",
inventory_image = "basetools_firesword.png", inventory_image = "basetools_firesword.png",
tool_capabilities = { tool_capabilities = {
full_punch_interval = 1.0, full_punch_interval = 1.0,
@ -273,12 +324,13 @@ minetest.register_tool("basetools:sword_fire", {
} }
}) })
minetest.register_tool("basetools:sword_ice", { minetest.register_tool("basetools:sword_ice", {
description = "Ice Sword", description = "Ice Sword".."\n"..
"Damage: fiery=6",
inventory_image = "basetools_icesword.png", inventory_image = "basetools_icesword.png",
tool_capabilities = { tool_capabilities = {
full_punch_interval = 1.0, full_punch_interval = 1.0,
max_drop_level=0, max_drop_level=0,
damage_groups = {firy=6}, damage_groups = {fiery=6},
} }
}) })
@ -286,7 +338,9 @@ minetest.register_tool("basetools:sword_ice", {
-- Dagger: Low damage, fast punch interval -- Dagger: Low damage, fast punch interval
-- --
minetest.register_tool("basetools:dagger_steel", { minetest.register_tool("basetools:dagger_steel", {
description = "Steel Dagger", description = "Steel Dagger".."\n"..
"Damage: fleshy=2".."\n"..
"Full Punch Interval: 0.5s",
inventory_image = "basetools_steeldagger.png", inventory_image = "basetools_steeldagger.png",
tool_capabilities = { tool_capabilities = {
full_punch_interval = 0.5, full_punch_interval = 0.5,

View File

@ -1,7 +1,8 @@
-- Bucket: Punch liquid source or flowing liquid to collect it -- Bucket: Punch liquid source or flowing liquid to collect it
minetest.register_tool("bucket:bucket", { minetest.register_tool("bucket:bucket", {
description = "Bucket", description = "Bucket".."\n"..
"Picks up liquid nodes",
inventory_image = "bucket.png", inventory_image = "bucket.png",
stack_max = 1, stack_max = 1,
liquids_pointable = true, liquids_pointable = true,

View File

@ -1,5 +1,6 @@
minetest.register_node("chest:chest", { minetest.register_node("chest:chest", {
description = "Chest", description = "Chest" .. "\n" ..
"32 inventory slots",
tiles ={"chest_chest.png^[sheet:2x2:0,0", "chest_chest.png^[sheet:2x2:0,0", tiles ={"chest_chest.png^[sheet:2x2:0,0", "chest_chest.png^[sheet:2x2:0,0",
"chest_chest.png^[sheet:2x2:1,0", "chest_chest.png^[sheet:2x2:1,0", "chest_chest.png^[sheet:2x2:1,0", "chest_chest.png^[sheet:2x2:1,0",
"chest_chest.png^[sheet:2x2:1,0", "chest_chest.png^[sheet:2x2:0,1"}, "chest_chest.png^[sheet:2x2:1,0", "chest_chest.png^[sheet:2x2:0,1"},

View File

@ -43,7 +43,8 @@ local function get_chest_formspec(page)
end end
minetest.register_node("chest_of_everything:chest", { minetest.register_node("chest_of_everything:chest", {
description = "Chest of Everything", description = "Chest of Everything" .. "\n" ..
"Grants access to all items",
tiles ={"chest_of_everything_chest.png^[sheet:2x2:0,0", "chest_of_everything_chest.png^[sheet:2x2:0,0", tiles ={"chest_of_everything_chest.png^[sheet:2x2:0,0", "chest_of_everything_chest.png^[sheet:2x2:0,0",
"chest_of_everything_chest.png^[sheet:2x2:1,0", "chest_of_everything_chest.png^[sheet:2x2:1,0", "chest_of_everything_chest.png^[sheet:2x2:1,0", "chest_of_everything_chest.png^[sheet:2x2:1,0",
"chest_of_everything_chest.png^[sheet:2x2:1,0", "chest_of_everything_chest.png^[sheet:2x2:0,1"}, "chest_of_everything_chest.png^[sheet:2x2:1,0", "chest_of_everything_chest.png^[sheet:2x2:0,1"},

View File

@ -214,3 +214,6 @@ minetest.register_chatcommand("test_place_nodes", {
end, end,
}) })
core.register_on_chatcommand(function(name, command, params)
minetest.log("caught command '"..command.."', issued by '"..name.."'. Parameters: '"..params.."'")
end)

View File

@ -44,7 +44,8 @@ minetest.register_node("experimental:callback_node", {
}) })
minetest.register_tool("experimental:privatizer", { minetest.register_tool("experimental:privatizer", {
description = "Node Meta Privatizer", description = "Node Meta Privatizer".."\n"..
"Punch: Marks 'infotext' and 'formspec' meta fields of chest as private",
inventory_image = "experimental_tester_tool_1.png", inventory_image = "experimental_tester_tool_1.png",
groups = { testtool = 1, disable_repair = 1 }, groups = { testtool = 1, disable_repair = 1 },
on_use = function(itemstack, user, pointed_thing) on_use = function(itemstack, user, pointed_thing)
@ -67,7 +68,8 @@ minetest.register_tool("experimental:privatizer", {
}) })
minetest.register_tool("experimental:particle_spawner", { minetest.register_tool("experimental:particle_spawner", {
description = "Particle Spawner", description = "Particle Spawner".."\n"..
"Punch: Spawn random test particle",
inventory_image = "experimental_tester_tool_1.png^[invert:g", inventory_image = "experimental_tester_tool_1.png^[invert:g",
groups = { testtool = 1, disable_repair = 1 }, groups = { testtool = 1, disable_repair = 1 },
on_use = function(itemstack, user, pointed_thing) on_use = function(itemstack, user, pointed_thing)

View File

@ -107,7 +107,8 @@ minetest.register_node("soundstuff:footstep_climbable", {
minetest.register_craftitem("soundstuff:eat", { minetest.register_craftitem("soundstuff:eat", {
description = "Eat Sound Item", description = "Eat Sound Item".."\n"..
"Makes a sound when 'eaten' (with punch key)",
inventory_image = "soundstuff_eat.png", inventory_image = "soundstuff_eat.png",
on_use = minetest.item_eat(0), on_use = minetest.item_eat(0),
sound = { sound = {
@ -116,7 +117,9 @@ minetest.register_craftitem("soundstuff:eat", {
}) })
minetest.register_tool("soundstuff:breaks", { minetest.register_tool("soundstuff:breaks", {
description = "Break Sound Tool", description = "Break Sound Tool".."\n"..
"Digs cracky=3 and more".."\n"..
"Makes a sound when it breaks",
inventory_image = "soundstuff_node_dug.png", inventory_image = "soundstuff_node_dug.png",
sound = { sound = {
breaks = { name = "soundstuff_mono", gain = 1.0 }, breaks = { name = "soundstuff_mono", gain = 1.0 },

View File

@ -3,7 +3,7 @@
local phasearmor = { local phasearmor = {
[0]={icy=100}, [0]={icy=100},
[1]={firy=100}, [1]={fiery=100},
[2]={fleshy=100}, [2]={fleshy=100},
[3]={immortal=1}, [3]={immortal=1},
[4]={punch_operable=1}, [4]={punch_operable=1},

View File

@ -68,7 +68,7 @@ minetest.register_entity("testentities:mesh_unshaded", {
-- Advanced visual tests -- Advanced visual tests
-- A test entity for testing animated and yaw-modulated sprites -- An entity for testing animated and yaw-modulated sprites
minetest.register_entity("testentities:yawsprite", { minetest.register_entity("testentities:yawsprite", {
initial_properties = { initial_properties = {
selectionbox = {-0.3, -0.5, -0.3, 0.3, 0.3, 0.3}, selectionbox = {-0.3, -0.5, -0.3, 0.3, 0.3, 0.3},
@ -79,6 +79,18 @@ minetest.register_entity("testentities:yawsprite", {
initial_sprite_basepos = {x=0, y=0}, initial_sprite_basepos = {x=0, y=0},
}, },
on_activate = function(self, staticdata) on_activate = function(self, staticdata)
self.object:set_sprite({x=0, y=0}, 1, 0, true) self.object:set_sprite({x=0, y=0}, 3, 0.5, true)
end,
})
-- An entity for testing animated upright sprites
minetest.register_entity("testentities:upright_animated", {
initial_properties = {
visual = "upright_sprite",
textures = {"testnodes_anim.png"},
spritediv = {x = 1, y = 4},
},
on_activate = function(self)
self.object:set_sprite({x=0, y=0}, 4, 1.0, false)
end, end,
}) })

View File

@ -0,0 +1,14 @@
License of media files
----------------------
Content imported from minetest_game.
BlockMen (CC BY-SA 3.0)
default_chest_front.png
default_chest_lock.png
default_chest_side.png
default_chest_top.png
stujones11 (CC BY-SA 3.0)
An0n3m0us (CC BY-SA 3.0)
testformspec_character.b3d

View File

@ -164,7 +164,7 @@ local style_fs = [[
style[one_btn14:hovered+pressed;textcolor=purple] style[one_btn14:hovered+pressed;textcolor=purple]
image_button[0,9.6;1,1;testformspec_button_image.png;one_btn14;Bg] image_button[0,9.6;1,1;testformspec_button_image.png;one_btn14;Bg]
style[one_btn15;border=false;bgimg=testformspec_bg.png;bgimg_hovered=testformspec_bg_hovered.png;bgimg_pressed=testformspec_bg_pressed.png] style[one_btn15;border=false;bgcolor=#1cc;bgimg=testformspec_bg.png;bgimg_hovered=testformspec_bg_hovered.png;bgimg_pressed=testformspec_bg_pressed.png]
item_image_button[1.25,9.6;1,1;testformspec:item;one_btn15;Bg] item_image_button[1.25,9.6;1,1;testformspec:item;one_btn15;Bg]
style[one_btn16;border=false;bgimg=testformspec_bg_9slice.png;bgimg_hovered=testformspec_bg_9slice_hovered.png;bgimg_pressed=testformspec_bg_9slice_pressed.png;bgimg_middle=4,6] style[one_btn16;border=false;bgimg=testformspec_bg_9slice.png;bgimg_hovered=testformspec_bg_9slice_hovered.png;bgimg_pressed=testformspec_bg_9slice_pressed.png;bgimg_middle=4,6]
@ -327,6 +327,10 @@ Number]
animated_image[3,4.25;1,1;;testformspec_animation.png;4;0;3] animated_image[3,4.25;1,1;;testformspec_animation.png;4;0;3]
animated_image[5.5,0.5;5,2;;testformspec_animation.png;4;100] animated_image[5.5,0.5;5,2;;testformspec_animation.png;4;100]
animated_image[5.5,2.75;5,2;;testformspec_animation.jpg;4;100] animated_image[5.5,2.75;5,2;;testformspec_animation.jpg;4;100]
style[m1;bgcolor=black]
model[0.5,6;4,4;m1;testformspec_character.b3d;testformspec_character.png]
model[5,6;4,4;m2;testformspec_chest.obj;default_chest_top.png,default_chest_top.png,default_chest_side.png,default_chest_side.png,default_chest_front.png,default_chest_inside.png;30,1;true;true]
]], ]],
-- Scroll containers -- Scroll containers

View File

@ -0,0 +1,79 @@
# Blender v2.78 (sub 0) OBJ File: 'chest-open.blend'
# www.blender.org
o Top_Cube.002_None_Top_Cube.002_None_bottom
v -0.500000 0.408471 0.720970
v -0.500000 1.115578 0.013863
v -0.500000 0.894607 -0.207108
v -0.500000 0.187501 0.499999
v 0.500000 1.115578 0.013863
v 0.500000 0.408471 0.720970
v 0.500000 0.187501 0.499999
v 0.500000 0.894607 -0.207108
v -0.500000 0.187500 -0.500000
v -0.500000 -0.500000 -0.500000
v -0.500000 -0.500000 0.500000
v 0.500000 0.187500 -0.500000
v 0.500000 -0.500000 0.500000
v 0.500000 -0.500000 -0.500000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 0.0000 1.0000
vt 1.0000 1.0000
vt 1.0000 0.6875
vt 0.0000 0.6875
vt 1.0000 1.0000
vt 0.0000 0.6875
vt 1.0000 0.6875
vt 1.0000 0.6875
vt 1.0000 0.0000
vt 0.0000 0.0000
vt 1.0000 0.6875
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 1.0000 0.6875
vt 1.0000 0.0000
vt 0.0000 1.0000
vt 0.0000 0.6875
vt 0.0000 0.6875
vt 0.0000 0.0000
vt 1.0000 0.5000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.5000
vt 0.0000 0.0000
vt 1.0000 0.0000
vn 0.0000 0.7071 0.7071
vn -0.0000 -1.0000 -0.0000
vn -1.0000 0.0000 0.0000
vn 1.0000 0.0000 -0.0000
vn 0.0000 -0.7071 0.7071
vn 0.0000 0.0000 1.0000
vn -0.0000 0.7071 -0.7071
vn -0.0000 0.0000 -1.0000
vn -0.0000 -0.7071 -0.7071
vn -0.0000 1.0000 -0.0000
g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Top
s off
f 6/1/1 5/2/1 2/3/1 1/4/1
g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Bottom
f 11/5/2 10/6/2 14/7/2 13/8/2
g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Right-Left
f 1/9/3 2/10/3 3/11/3 4/12/3
f 5/13/4 6/1/4 7/14/4 8/15/4
f 4/12/3 9/16/3 10/17/3 11/18/3
f 12/19/4 7/14/4 13/8/4 14/20/4
g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Back
f 6/21/5 1/9/5 4/12/5 7/22/5
f 7/22/6 4/12/6 11/18/6 13/23/6
g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Front
f 2/10/7 5/24/7 8/25/7 3/11/7
f 9/16/8 12/26/8 14/27/8 10/17/8
g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Inside
f 4/28/9 3/29/9 8/30/9 7/31/9
f 7/31/10 12/32/10 9/33/10 4/28/10

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -145,6 +145,23 @@ minetest.register_node("testnodes:fencelike", {
}) })
minetest.register_node("testnodes:torchlike", { minetest.register_node("testnodes:torchlike", {
description = S("Torchlike Drawtype Test Node"),
drawtype = "torchlike",
paramtype = "light",
tiles = {
"testnodes_torchlike_floor.png",
"testnodes_torchlike_ceiling.png",
"testnodes_torchlike_wall.png",
},
walkable = false,
sunlight_propagates = true,
groups = { dig_immediate = 3 },
inventory_image = fallback_image("testnodes_torchlike_floor.png"),
})
minetest.register_node("testnodes:torchlike_wallmounted", {
description = S("Wallmounted Torchlike Drawtype Test Node"), description = S("Wallmounted Torchlike Drawtype Test Node"),
drawtype = "torchlike", drawtype = "torchlike",
paramtype = "light", paramtype = "light",
@ -162,6 +179,8 @@ minetest.register_node("testnodes:torchlike", {
inventory_image = fallback_image("testnodes_torchlike_floor.png"), inventory_image = fallback_image("testnodes_torchlike_floor.png"),
}) })
minetest.register_node("testnodes:signlike", { minetest.register_node("testnodes:signlike", {
description = S("Wallmounted Signlike Drawtype Test Node"), description = S("Wallmounted Signlike Drawtype Test Node"),
drawtype = "signlike", drawtype = "signlike",
@ -514,10 +533,19 @@ local scale = function(subname, desc_double, desc_half)
minetest.register_node("testnodes:"..subname.."_half", def) minetest.register_node("testnodes:"..subname.."_half", def)
end end
scale("allfaces",
S("Double-sized Allfaces Drawtype Test Node"),
S("Half-sized Allfaces Drawtype Test Node"))
scale("allfaces_optional",
S("Double-sized Allfaces Optional Drawtype Test Node"),
S("Half-sized Allfaces Optional Drawtype Test Node"))
scale("allfaces_optional_waving",
S("Double-sized Waving Allfaces Optional Drawtype Test Node"),
S("Half-sized Waving Allfaces Optional Drawtype Test Node"))
scale("plantlike", scale("plantlike",
S("Double-sized Plantlike Drawtype Test Node"), S("Double-sized Plantlike Drawtype Test Node"),
S("Half-sized Plantlike Drawtype Test Node")) S("Half-sized Plantlike Drawtype Test Node"))
scale("torchlike", scale("torchlike_wallmounted",
S("Double-sized Wallmounted Torchlike Drawtype Test Node"), S("Double-sized Wallmounted Torchlike Drawtype Test Node"),
S("Half-sized Wallmounted Torchlike Drawtype Test Node")) S("Half-sized Wallmounted Torchlike Drawtype Test Node"))
scale("signlike", scale("signlike",

View File

@ -22,7 +22,8 @@ end
-- Lets light through, but not sunlight, leading to a -- Lets light through, but not sunlight, leading to a
-- reduction in light level when light passes through -- reduction in light level when light passes through
minetest.register_node("testnodes:sunlight_filter", { minetest.register_node("testnodes:sunlight_filter", {
description = S("Sunlight Filter"), description = S("Sunlight Filter") .."\n"..
S("Lets light through, but weakens sunlight"),
paramtype = "light", paramtype = "light",
@ -35,7 +36,8 @@ minetest.register_node("testnodes:sunlight_filter", {
-- Lets light and sunlight through without obstruction -- Lets light and sunlight through without obstruction
minetest.register_node("testnodes:sunlight_propagator", { minetest.register_node("testnodes:sunlight_propagator", {
description = S("Sunlight Propagator"), description = S("Sunlight Propagator") .."\n"..
S("Lets all light through"),
paramtype = "light", paramtype = "light",
sunlight_propagates = true, sunlight_propagates = true,

View File

@ -1,2 +1,3 @@
name = testnodes name = testnodes
description = Contains a bunch of basic example nodes for demonstrative purposes, development and testing description = Contains a bunch of basic example nodes for demonstrative purposes, development and testing
depends = stairs

View File

@ -71,3 +71,52 @@ for a=1,#alphas do
groups = { dig_immediate = 3 }, groups = { dig_immediate = 3 },
}) })
end end
-- Bumpmapping and Parallax Occlusion
-- This node has a normal map which corresponds to a pyramid with sides tilted
-- by an angle of 45°, i.e. the normal map contains four vectors which point
-- diagonally away from the surface (e.g. (0.7, 0.7, 0)),
-- and the heights in the height map linearly increase towards the centre,
-- so that the surface corresponds to a simple pyramid.
-- The node can help to determine if e.g. tangent space transformations work
-- correctly.
-- If, for example, the light comes from above, then the (tilted) pyramids
-- should look like they're lit from this light direction on all node faces.
-- The white albedo texture has small black indicators which can be used to see
-- how it is transformed ingame (and thus see if there's rotation around the
-- normal vector).
minetest.register_node("testnodes:height_pyramid", {
description = "Bumpmapping and Parallax Occlusion Tester (height pyramid)",
tiles = {"testnodes_height_pyramid.png"},
groups = {dig_immediate = 3},
})
-- The stairs nodes should help to validate if shading works correctly for
-- rotated nodes (which have rotated textures).
stairs.register_stair_and_slab("height_pyramid", "experimantal:height_pyramid",
{dig_immediate = 3},
{"testnodes_height_pyramid.png"},
"Bumpmapping and Parallax Occlusion Tester Stair (height pyramid)",
"Bumpmapping and Parallax Occlusion Tester Slab (height pyramid)")
-- This node has a simple heightmap for parallax occlusion testing and flat
-- normalmap.
-- When parallax occlusion is enabled, the yellow scrawl should stick out of
-- the texture when viewed at an angle.
minetest.register_node("testnodes:parallax_extruded", {
description = "Parallax Occlusion Tester",
tiles = {"testnodes_parallax_extruded.png"},
groups = {dig_immediate = 3},
})
-- Analogously to the height pyramid stairs nodes,
-- these nodes should help to validate if parallax occlusion works correctly for
-- rotated nodes (which have rotated textures).
stairs.register_stair_and_slab("parallax_extruded",
"experimantal:parallax_extruded",
{dig_immediate = 3},
{"testnodes_parallax_extruded.png"},
"Parallax Occlusion Tester Stair",
"Parallax Occlusion Tester Slab")

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 591 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 B

View File

@ -121,7 +121,11 @@ end
-- Sneak+punch: Select pathfinding algorithm -- Sneak+punch: Select pathfinding algorithm
-- Place: Select destination node -- Place: Select destination node
minetest.register_tool("testpathfinder:testpathfinder", { minetest.register_tool("testpathfinder:testpathfinder", {
description = S("Pathfinder Tester"), description = S("Pathfinder Tester") .."\n"..
S("Finds path between 2 points") .."\n"..
S("Place on node: Select destination") .."\n"..
S("Punch: Find path from here") .."\n"..
S("Sneak+Punch: Change algorithm"),
inventory_image = "testpathfinder_testpathfinder.png", inventory_image = "testpathfinder_testpathfinder.png",
groups = { testtool = 1, disable_repair = 1 }, groups = { testtool = 1, disable_repair = 1 },
on_use = find_path_or_set_algorithm, on_use = find_path_or_set_algorithm,

View File

@ -1,15 +1,17 @@
local S = minetest.get_translator("testtools") local S = minetest.get_translator("testtools")
local F = minetest.formspec_escape local F = minetest.formspec_escape
dofile(minetest.get_modpath("testtools") .. "/light.lua")
-- TODO: Add a Node Metadata tool -- TODO: Add a Node Metadata tool
-- Param 2 Tool: Set param2 value of tools
-- Punch: +1
-- Punch+Shift: +8
-- Place: -1
-- Place+Shift: -8
minetest.register_tool("testtools:param2tool", { minetest.register_tool("testtools:param2tool", {
description = S("Param2 Tool"), description = S("Param2 Tool") .."\n"..
S("Modify param2 value of nodes") .."\n"..
S("Punch: +1") .."\n"..
S("Sneak+Punch: +8") .."\n"..
S("Place: -1") .."\n"..
S("Sneak+Place: -8"),
inventory_image = "testtools_param2tool.png", inventory_image = "testtools_param2tool.png",
groups = { testtool = 1, disable_repair = 1 }, groups = { testtool = 1, disable_repair = 1 },
on_use = function(itemstack, user, pointed_thing) on_use = function(itemstack, user, pointed_thing)
@ -47,7 +49,11 @@ minetest.register_tool("testtools:param2tool", {
}) })
minetest.register_tool("testtools:node_setter", { minetest.register_tool("testtools:node_setter", {
description = S("Node Setter"), description = S("Node Setter") .."\n"..
S("Replace pointed node with something else") .."\n"..
S("Punch: Select pointed node") .."\n"..
S("Place on node: Replace node with selected node") .."\n"..
S("Place in air: Manually select a node"),
inventory_image = "testtools_node_setter.png", inventory_image = "testtools_node_setter.png",
groups = { testtool = 1, disable_repair = 1 }, groups = { testtool = 1, disable_repair = 1 },
on_use = function(itemstack, user, pointed_thing) on_use = function(itemstack, user, pointed_thing)
@ -125,7 +131,8 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end) end)
minetest.register_tool("testtools:remover", { minetest.register_tool("testtools:remover", {
description = S("Remover"), description = S("Remover") .."\n"..
S("Punch: Remove pointed node or object"),
inventory_image = "testtools_remover.png", inventory_image = "testtools_remover.png",
groups = { testtool = 1, disable_repair = 1 }, groups = { testtool = 1, disable_repair = 1 },
on_use = function(itemstack, user, pointed_thing) on_use = function(itemstack, user, pointed_thing)
@ -136,13 +143,17 @@ minetest.register_tool("testtools:remover", {
local obj = pointed_thing.ref local obj = pointed_thing.ref
if not obj:is_player() then if not obj:is_player() then
obj:remove() obj:remove()
else
minetest.chat_send_player(user:get_player_name(), S("Can't remove players!"))
end end
end end
end, end,
}) })
minetest.register_tool("testtools:falling_node_tool", { minetest.register_tool("testtools:falling_node_tool", {
description = S("Falling Node Tool"), description = S("Falling Node Tool") .."\n"..
S("Punch: Make pointed node fall") .."\n"..
S("Place: Move pointed node 2 units upwards, then make it fall"),
inventory_image = "testtools_falling_node_tool.png", inventory_image = "testtools_falling_node_tool.png",
groups = { testtool = 1, disable_repair = 1 }, groups = { testtool = 1, disable_repair = 1 },
on_place = function(itemstack, user, pointed_thing) on_place = function(itemstack, user, pointed_thing)
@ -191,7 +202,11 @@ minetest.register_tool("testtools:falling_node_tool", {
}) })
minetest.register_tool("testtools:rotator", { minetest.register_tool("testtools:rotator", {
description = S("Entity Rotator"), description = S("Entity Rotator") .. "\n" ..
S("Rotate pointed entity") .."\n"..
S("Punch: Yaw") .."\n"..
S("Sneak+Punch: Pitch") .."\n"..
S("Aux1+Punch: Roll"),
inventory_image = "testtools_entity_rotator.png", inventory_image = "testtools_entity_rotator.png",
groups = { testtool = 1, disable_repair = 1 }, groups = { testtool = 1, disable_repair = 1 },
on_use = function(itemstack, user, pointed_thing) on_use = function(itemstack, user, pointed_thing)
@ -244,7 +259,12 @@ local mover_config = function(itemstack, user, pointed_thing)
end end
minetest.register_tool("testtools:object_mover", { minetest.register_tool("testtools:object_mover", {
description = S("Object Mover"), description = S("Object Mover") .."\n"..
S("Move pointed object towards or away from you") .."\n"..
S("Punch: Move by distance").."\n"..
S("Sneak+Punch: Move by negative distance").."\n"..
S("Place: Increase distance").."\n"..
S("Sneak+Place: Decrease distance"),
inventory_image = "testtools_object_mover.png", inventory_image = "testtools_object_mover.png",
groups = { testtool = 1, disable_repair = 1 }, groups = { testtool = 1, disable_repair = 1 },
on_place = mover_config, on_place = mover_config,
@ -287,7 +307,10 @@ minetest.register_tool("testtools:object_mover", {
minetest.register_tool("testtools:entity_scaler", { minetest.register_tool("testtools:entity_scaler", {
description = S("Entity Visual Scaler"), description = S("Entity Visual Scaler") .."\n"..
S("Scale visual size of entities") .."\n"..
S("Punch: Increase size") .."\n"..
S("Sneak+Punch: Decrease scale"),
inventory_image = "testtools_entity_scaler.png", inventory_image = "testtools_entity_scaler.png",
groups = { testtool = 1, disable_repair = 1 }, groups = { testtool = 1, disable_repair = 1 },
on_use = function(itemstack, user, pointed_thing) on_use = function(itemstack, user, pointed_thing)
@ -342,14 +365,21 @@ local function get_entity_list()
return entity_list return entity_list
end end
minetest.register_tool("testtools:entity_spawner", { minetest.register_tool("testtools:entity_spawner", {
description = S("Entity Spawner"), description = S("Entity Spawner") .."\n"..
S("Spawns entities") .."\n"..
S("Punch: Select entity to spawn") .."\n"..
S("Place: Spawn selected entity"),
inventory_image = "testtools_entity_spawner.png", inventory_image = "testtools_entity_spawner.png",
groups = { testtool = 1, disable_repair = 1 }, groups = { testtool = 1, disable_repair = 1 },
on_place = function(itemstack, user, pointed_thing) on_place = function(itemstack, user, pointed_thing)
local name = user:get_player_name() local name = user:get_player_name()
if selections[name] and pointed_thing.type == "node" then if pointed_thing.type == "node" then
local pos = pointed_thing.above if selections[name] then
minetest.add_entity(pos, get_entity_list()[selections[name]]) local pos = pointed_thing.above
minetest.add_entity(pos, get_entity_list()[selections[name]])
else
minetest.chat_send_player(name, S("Select an entity first (with punch key)!"))
end
end end
end, end,
on_use = function(itemstack, user, pointed_thing) on_use = function(itemstack, user, pointed_thing)
@ -435,7 +465,10 @@ local editor_formspec = function(playername, obj, value, sel)
end end
minetest.register_tool("testtools:object_editor", { minetest.register_tool("testtools:object_editor", {
description = S("Object Property Editor"), description = S("Object Property Editor") .."\n"..
S("Edit properties of objects") .."\n"..
S("Punch object: Edit object") .."\n"..
S("Punch air: Edit yourself"),
inventory_image = "testtools_object_editor.png", inventory_image = "testtools_object_editor.png",
groups = { testtool = 1, disable_repair = 1 }, groups = { testtool = 1, disable_repair = 1 },
on_use = function(itemstack, user, pointed_thing) on_use = function(itemstack, user, pointed_thing)
@ -515,7 +548,14 @@ local attacher_config = function(itemstack, user, pointed_thing)
end end
minetest.register_tool("testtools:object_attacher", { minetest.register_tool("testtools:object_attacher", {
description = S("Object Attacher"), description = S("Object Attacher") .."\n"..
S("Attach object to another") .."\n"..
S("Punch objects to first select parent object, then the child object to attach") .."\n"..
S("Punch air to select yourself") .."\n"..
S("Place: Incease attachment Y offset") .."\n"..
S("Sneak+Place: Decease attachment Y offset") .."\n"..
S("Aux1+Place: Incease attachment rotation") .."\n"..
S("Aux1+Sneak+Place: Decrease attachment rotation"),
inventory_image = "testtools_object_attacher.png", inventory_image = "testtools_object_attacher.png",
groups = { testtool = 1, disable_repair = 1 }, groups = { testtool = 1, disable_repair = 1 },
on_place = attacher_config, on_place = attacher_config,

View File

@ -0,0 +1,22 @@
local S = minetest.get_translator("testtools")
minetest.register_tool("testtools:lighttool", {
description = S("Light tool"),
inventory_image = "testtools_lighttool.png",
groups = { testtool = 1, disable_repair = 1 },
on_use = function(itemstack, user, pointed_thing)
local pos = pointed_thing.above
if pointed_thing.type ~= "node" or not pos then
return
end
local node = minetest.get_node(pos)
local time = minetest.get_timeofday()
local sunlight = minetest.get_natural_light(pos)
local artificial = minetest.get_artificial_light(node.param1)
local message = ("param1 0x%02x | time %.5f | sunlight %d | artificial %d")
:format(node.param1, time, sunlight, artificial)
minetest.chat_send_player(user:get_player_name(), message)
end
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -5,10 +5,12 @@ dofile(modpath .. "/random.lua")
dofile(modpath .. "/player.lua") dofile(modpath .. "/player.lua")
dofile(modpath .. "/crafting_prepare.lua") dofile(modpath .. "/crafting_prepare.lua")
dofile(modpath .. "/crafting.lua") dofile(modpath .. "/crafting.lua")
dofile(modpath .. "/itemdescription.lua")
if minetest.settings:get_bool("devtest_unittests_autostart", false) then if minetest.settings:get_bool("devtest_unittests_autostart", false) then
unittests.test_random() unittests.test_random()
unittests.test_crafting() unittests.test_crafting()
unittests.test_short_desc()
minetest.register_on_joinplayer(function(player) minetest.register_on_joinplayer(function(player)
unittests.test_player(player) unittests.test_player(player)
end) end)

View File

@ -0,0 +1,44 @@
local full_description = "Colorful Pickaxe\nThe best pick."
minetest.register_tool("unittests:colorful_pick", {
description = full_description,
inventory_image = "basetools_mesepick.png",
tool_capabilities = {
full_punch_interval = 1.0,
max_drop_level=3,
groupcaps={
cracky={times={[1]=2.0, [2]=1.0, [3]=0.5}, uses=20, maxlevel=3},
crumbly={times={[1]=2.0, [2]=1.0, [3]=0.5}, uses=20, maxlevel=3},
snappy={times={[1]=2.0, [2]=1.0, [3]=0.5}, uses=20, maxlevel=3}
},
damage_groups = {fleshy=4},
},
})
minetest.register_chatcommand("item_description", {
param = "",
description = "Show the short and full description of the wielded item.",
func = function(name)
local player = minetest.get_player_by_name(name)
local item = player:get_wielded_item()
return true, string.format("short_description: %s\ndescription: %s",
item:get_short_description(), item:get_description())
end
})
function unittests.test_short_desc()
local stack = ItemStack("unittests:colorful_pick")
assert(stack:get_short_description() == "Colorful Pickaxe")
assert(stack:get_short_description() == minetest.registered_items["unittests:colorful_pick"].short_description)
assert(stack:get_description() == full_description)
assert(stack:get_description() == minetest.registered_items["unittests:colorful_pick"].description)
stack:get_meta():set_string("description", "Hello World")
assert(stack:get_short_description() == "Colorful Pickaxe")
assert(stack:get_description() == "Hello World")
stack:get_meta():set_string("short_description", "Foo Bar")
assert(stack:get_short_description() == "Foo Bar")
assert(stack:get_description() == "Hello World")
return true
end

View File

@ -36,8 +36,12 @@ minetest.register_chatcommand("hp", {
end, end,
}) })
minetest.register_chatcommand("zoom", { minetest.register_on_joinplayer(function(player)
params = "[<zoom_fov>]", player:set_properties({zoom_fov = 15})
end)
minetest.register_chatcommand("zoomfov", {
params = "[<FOV>]",
description = "Set or display your zoom_fov", description = "Set or display your zoom_fov",
func = function(name, param) func = function(name, param)
local player = minetest.get_player_by_name(name) local player = minetest.get_player_by_name(name)
@ -58,8 +62,6 @@ minetest.register_chatcommand("zoom", {
end, end,
}) })
local s_infplace = minetest.settings:get("devtest_infplace") local s_infplace = minetest.settings:get("devtest_infplace")
if s_infplace == "true" then if s_infplace == "true" then
infplace = true infplace = true
@ -112,6 +114,62 @@ minetest.register_chatcommand("detach", {
end, end,
}) })
-- Use this to test waypoint capabilities
minetest.register_chatcommand("test_waypoints", {
params = "[change_immediate]",
description = "tests waypoint capabilities",
func = function(name, params)
local player = minetest.get_player_by_name(name)
local regular = player:hud_add {
hud_elem_type = "waypoint",
name = "regular waypoint",
text = "m",
number = 0xFF0000,
world_pos = vector.add(player:get_pos(), {x = 0, y = 1.5, z = 0})
}
local reduced_precision = player:hud_add {
hud_elem_type = "waypoint",
name = "better waypoint",
text = "m (0.5 steps, precision = 2)",
precision = 10,
number = 0xFFFF00,
world_pos = vector.add(player:get_pos(), {x = 0, y = 1, z = 0})
}
local function change()
if regular then
player:hud_change(regular, "world_pos", vector.add(player:get_pos(), {x = 0, y = 3, z = 0}))
end
if reduced_precision then
player:hud_change(reduced_precision, "precision", 2)
end
end
if params ~= "" then
-- change immediate
change()
else
minetest.after(0.5, change)
end
regular = regular or "error"
reduced_precision = reduced_precision or "error"
local hidden_distance = player:hud_add {
hud_elem_type = "waypoint",
name = "waypoint with hidden distance",
text = "this text is hidden as well (precision = 0)",
precision = 0,
number = 0x0000FF,
world_pos = vector.add(player:get_pos(), {x = 0, y = 0.5, z = 0})
} or "error"
local image_waypoint = player:hud_add {
hud_elem_type = "image_waypoint",
text = "wieldhand.png",
world_pos = player:get_pos(),
scale = {x = 10, y = 10},
offset = {x = 0, y = -32}
} or "error"
minetest.chat_send_player(name, "Waypoint IDs: regular: " .. regular .. ", reduced precision: " .. reduced_precision ..
", hidden distance: " .. hidden_distance .. ", image waypoint: " .. image_waypoint)
end
})
-- Unlimited node placement -- Unlimited node placement
minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack) minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack)

View File

@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
cd .. cd ..
git clone https://github.com/open-source-parsers/jsoncpp -b 1.8.3 --depth 1 git clone https://github.com/open-source-parsers/jsoncpp -b 1.9.4 --depth 1
cd jsoncpp cd jsoncpp
python amalgamate.py python amalgamate.py
cp -R dist/json ../json cp -R dist/json ../json

View File

@ -79,6 +79,151 @@ license you like.
/// to prevent private header inclusion. /// to prevent private header inclusion.
#define JSON_IS_AMALGAMATION #define JSON_IS_AMALGAMATION
// //////////////////////////////////////////////////////////////////////
// Beginning of content of file: include/json/version.h
// //////////////////////////////////////////////////////////////////////
#ifndef JSON_VERSION_H_INCLUDED
#define JSON_VERSION_H_INCLUDED
// Note: version must be updated in three places when doing a release. This
// annoying process ensures that amalgamate, CMake, and meson all report the
// correct version.
// 1. /meson.build
// 2. /include/json/version.h
// 3. /CMakeLists.txt
// IMPORTANT: also update the SOVERSION!!
#define JSONCPP_VERSION_STRING "1.9.4"
#define JSONCPP_VERSION_MAJOR 1
#define JSONCPP_VERSION_MINOR 9
#define JSONCPP_VERSION_PATCH 3
#define JSONCPP_VERSION_QUALIFIER
#define JSONCPP_VERSION_HEXA \
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
(JSONCPP_VERSION_PATCH << 8))
#ifdef JSONCPP_USING_SECURE_MEMORY
#undef JSONCPP_USING_SECURE_MEMORY
#endif
#define JSONCPP_USING_SECURE_MEMORY 0
// If non-zero, the library zeroes any memory that it has allocated before
// it frees its memory.
#endif // JSON_VERSION_H_INCLUDED
// //////////////////////////////////////////////////////////////////////
// End of content of file: include/json/version.h
// //////////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////////
// Beginning of content of file: include/json/allocator.h
// //////////////////////////////////////////////////////////////////////
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef JSON_ALLOCATOR_H_INCLUDED
#define JSON_ALLOCATOR_H_INCLUDED
#include <cstring>
#include <memory>
#pragma pack(push, 8)
namespace Json {
template <typename T> class SecureAllocator {
public:
// Type definitions
using value_type = T;
using pointer = T*;
using const_pointer = const T*;
using reference = T&;
using const_reference = const T&;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
/**
* Allocate memory for N items using the standard allocator.
*/
pointer allocate(size_type n) {
// allocate using "global operator new"
return static_cast<pointer>(::operator new(n * sizeof(T)));
}
/**
* Release memory which was allocated for N items at pointer P.
*
* The memory block is filled with zeroes before being released.
* The pointer argument is tagged as "volatile" to prevent the
* compiler optimizing out this critical step.
*/
void deallocate(volatile pointer p, size_type n) {
std::memset(p, 0, n * sizeof(T));
// free using "global operator delete"
::operator delete(p);
}
/**
* Construct an item in-place at pointer P.
*/
template <typename... Args> void construct(pointer p, Args&&... args) {
// construct using "placement new" and "perfect forwarding"
::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);
}
size_type max_size() const { return size_t(-1) / sizeof(T); }
pointer address(reference x) const { return std::addressof(x); }
const_pointer address(const_reference x) const { return std::addressof(x); }
/**
* Destroy an item in-place at pointer P.
*/
void destroy(pointer p) {
// destroy using "explicit destructor"
p->~T();
}
// Boilerplate
SecureAllocator() {}
template <typename U> SecureAllocator(const SecureAllocator<U>&) {}
template <typename U> struct rebind { using other = SecureAllocator<U>; };
};
template <typename T, typename U>
bool operator==(const SecureAllocator<T>&, const SecureAllocator<U>&) {
return true;
}
template <typename T, typename U>
bool operator!=(const SecureAllocator<T>&, const SecureAllocator<U>&) {
return false;
}
} // namespace Json
#pragma pack(pop)
#endif // JSON_ALLOCATOR_H_INCLUDED
// //////////////////////////////////////////////////////////////////////
// End of content of file: include/json/allocator.h
// //////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////
// Beginning of content of file: include/json/config.h // Beginning of content of file: include/json/config.h
// ////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////
@ -90,19 +235,14 @@ license you like.
#ifndef JSON_CONFIG_H_INCLUDED #ifndef JSON_CONFIG_H_INCLUDED
#define JSON_CONFIG_H_INCLUDED #define JSON_CONFIG_H_INCLUDED
#include <stddef.h> #include <cstddef>
#include <string> //typedef String #include <cstdint>
#include <stdint.h> //typedef int64_t, uint64_t #include <istream>
#include <memory>
/// If defined, indicates that json library is embedded in CppTL library. #include <ostream>
//# define JSON_IN_CPPTL 1 #include <sstream>
#include <string>
/// If defined, indicates that json may leverage CppTL library #include <type_traits>
//# define JSON_USE_CPPTL 1
/// If defined, indicates that cpptl vector based map should be used instead of
/// std::map
/// as Value container.
//# define JSON_USE_CPPTL_SMALLMAP 1
// If non-zero, the library uses exceptions to report bad input instead of C // If non-zero, the library uses exceptions to report bad input instead of C
// assertion macros. The default is to use exceptions. // assertion macros. The default is to use exceptions.
@ -110,164 +250,132 @@ license you like.
#define JSON_USE_EXCEPTION 1 #define JSON_USE_EXCEPTION 1
#endif #endif
// Temporary, tracked for removal with issue #982.
#ifndef JSON_USE_NULLREF
#define JSON_USE_NULLREF 1
#endif
/// If defined, indicates that the source file is amalgamated /// If defined, indicates that the source file is amalgamated
/// to prevent private header inclusion. /// to prevent private header inclusion.
/// Remarks: it is automatically defined in the generated amalgamated header. /// Remarks: it is automatically defined in the generated amalgamated header.
// #define JSON_IS_AMALGAMATION // #define JSON_IS_AMALGAMATION
#ifdef JSON_IN_CPPTL // Export macros for DLL visibility
#include <cpptl/config.h> #if defined(JSON_DLL_BUILD)
#ifndef JSON_USE_CPPTL
#define JSON_USE_CPPTL 1
#endif
#endif
#ifdef JSON_IN_CPPTL
#define JSON_API CPPTL_API
#elif defined(JSON_DLL_BUILD)
#if defined(_MSC_VER) || defined(__MINGW32__) #if defined(_MSC_VER) || defined(__MINGW32__)
#define JSON_API __declspec(dllexport) #define JSON_API __declspec(dllexport)
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
#elif defined(__GNUC__) || defined(__clang__)
#define JSON_API __attribute__((visibility("default")))
#endif // if defined(_MSC_VER) #endif // if defined(_MSC_VER)
#elif defined(JSON_DLL) #elif defined(JSON_DLL)
#if defined(_MSC_VER) || defined(__MINGW32__) #if defined(_MSC_VER) || defined(__MINGW32__)
#define JSON_API __declspec(dllimport) #define JSON_API __declspec(dllimport)
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
#endif // if defined(_MSC_VER) #endif // if defined(_MSC_VER)
#endif // ifdef JSON_IN_CPPTL #endif // ifdef JSON_DLL_BUILD
#if !defined(JSON_API) #if !defined(JSON_API)
#define JSON_API #define JSON_API
#endif #endif
#if defined(_MSC_VER) && _MSC_VER < 1800
#error \
"ERROR: Visual Studio 12 (2013) with _MSC_VER=1800 is the oldest supported compiler with sufficient C++11 capabilities"
#endif
#if defined(_MSC_VER) && _MSC_VER < 1900
// As recommended at
// https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
const char* format, ...);
#define jsoncpp_snprintf msvc_pre1900_c99_snprintf
#else
#define jsoncpp_snprintf std::snprintf
#endif
// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for // If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
// integer // integer
// Storages, and 64 bits integer support is disabled. // Storages, and 64 bits integer support is disabled.
// #define JSON_NO_INT64 1 // #define JSON_NO_INT64 1
#if defined(_MSC_VER) // MSVC // JSONCPP_OVERRIDE is maintained for backwards compatibility of external tools.
# if _MSC_VER <= 1200 // MSVC 6 // C++11 should be used directly in JSONCPP.
// Microsoft Visual Studio 6 only support conversion from __int64 to double #define JSONCPP_OVERRIDE override
// (no conversion from unsigned __int64).
# define JSON_USE_INT64_DOUBLE_CONVERSION 1
// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
// characters in the debug information)
// All projects I've ever seen with VS6 were using this globally (not bothering
// with pragma push/pop).
# pragma warning(disable : 4786)
# endif // MSVC 6
# if _MSC_VER >= 1500 // MSVC 2008
/// Indicates that the following function is deprecated.
# define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
# endif
#endif // defined(_MSC_VER)
// In c++11 the override keyword allows you to explicitly define that a function
// is intended to override the base-class version. This makes the code more
// managable and fixes a set of common hard-to-find bugs.
#if __cplusplus >= 201103L
# define JSONCPP_OVERRIDE override
# define JSONCPP_NOEXCEPT noexcept
#elif defined(_MSC_VER) && _MSC_VER > 1600 && _MSC_VER < 1900
# define JSONCPP_OVERRIDE override
# define JSONCPP_NOEXCEPT throw()
#elif defined(_MSC_VER) && _MSC_VER >= 1900
# define JSONCPP_OVERRIDE override
# define JSONCPP_NOEXCEPT noexcept
#else
# define JSONCPP_OVERRIDE
# define JSONCPP_NOEXCEPT throw()
#endif
#ifndef JSON_HAS_RVALUE_REFERENCES
#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010
#define JSON_HAS_RVALUE_REFERENCES 1
#endif // MSVC >= 2010
#ifdef __clang__ #ifdef __clang__
#if __has_feature(cxx_rvalue_references) #if __has_extension(attribute_deprecated_with_message)
#define JSON_HAS_RVALUE_REFERENCES 1 #define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
#endif // has_feature
#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
#define JSON_HAS_RVALUE_REFERENCES 1
#endif // GXX_EXPERIMENTAL
#endif // __clang__ || __GNUC__
#endif // not defined JSON_HAS_RVALUE_REFERENCES
#ifndef JSON_HAS_RVALUE_REFERENCES
#define JSON_HAS_RVALUE_REFERENCES 0
#endif #endif
#elif defined(__GNUC__) // not clang (gcc comes later since clang emulates gcc)
#ifdef __clang__ #if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
# if __has_extension(attribute_deprecated_with_message) #define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
# define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message))) #elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
# endif #define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__))
#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc) #endif // GNUC version
# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) #elif defined(_MSC_VER) // MSVC (after clang because clang on Windows emulates
# define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message))) // MSVC)
# elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) #define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
# define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) #endif // __clang__ || __GNUC__ || _MSC_VER
# endif // GNUC version
#endif // __clang__ || __GNUC__
#if !defined(JSONCPP_DEPRECATED) #if !defined(JSONCPP_DEPRECATED)
#define JSONCPP_DEPRECATED(message) #define JSONCPP_DEPRECATED(message)
#endif // if !defined(JSONCPP_DEPRECATED) #endif // if !defined(JSONCPP_DEPRECATED)
#if __GNUC__ >= 6 #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 6))
# define JSON_USE_INT64_DOUBLE_CONVERSION 1 #define JSON_USE_INT64_DOUBLE_CONVERSION 1
#endif #endif
#if !defined(JSON_IS_AMALGAMATION) #if !defined(JSON_IS_AMALGAMATION)
# include "version.h" #include "allocator.h"
#include "version.h"
# if JSONCPP_USING_SECURE_MEMORY
# include "allocator.h" //typedef Allocator
# endif
#endif // if !defined(JSON_IS_AMALGAMATION) #endif // if !defined(JSON_IS_AMALGAMATION)
namespace Json { namespace Json {
typedef int Int; using Int = int;
typedef unsigned int UInt; using UInt = unsigned int;
#if defined(JSON_NO_INT64) #if defined(JSON_NO_INT64)
typedef int LargestInt; using LargestInt = int;
typedef unsigned int LargestUInt; using LargestUInt = unsigned int;
#undef JSON_HAS_INT64 #undef JSON_HAS_INT64
#else // if defined(JSON_NO_INT64) #else // if defined(JSON_NO_INT64)
// For Microsoft Visual use specific types as long long is not supported // For Microsoft Visual use specific types as long long is not supported
#if defined(_MSC_VER) // Microsoft Visual Studio #if defined(_MSC_VER) // Microsoft Visual Studio
typedef __int64 Int64; using Int64 = __int64;
typedef unsigned __int64 UInt64; using UInt64 = unsigned __int64;
#else // if defined(_MSC_VER) // Other platforms, use long long #else // if defined(_MSC_VER) // Other platforms, use long long
typedef int64_t Int64; using Int64 = int64_t;
typedef uint64_t UInt64; using UInt64 = uint64_t;
#endif // if defined(_MSC_VER) #endif // if defined(_MSC_VER)
typedef Int64 LargestInt; using LargestInt = Int64;
typedef UInt64 LargestUInt; using LargestUInt = UInt64;
#define JSON_HAS_INT64 #define JSON_HAS_INT64
#endif // if defined(JSON_NO_INT64) #endif // if defined(JSON_NO_INT64)
#if JSONCPP_USING_SECURE_MEMORY
#define JSONCPP_STRING std::basic_string<char, std::char_traits<char>, Json::SecureAllocator<char> > template <typename T>
#define JSONCPP_OSTRINGSTREAM std::basic_ostringstream<char, std::char_traits<char>, Json::SecureAllocator<char> > using Allocator =
#define JSONCPP_OSTREAM std::basic_ostream<char, std::char_traits<char>> typename std::conditional<JSONCPP_USING_SECURE_MEMORY, SecureAllocator<T>,
#define JSONCPP_ISTRINGSTREAM std::basic_istringstream<char, std::char_traits<char>, Json::SecureAllocator<char> > std::allocator<T>>::type;
#define JSONCPP_ISTREAM std::istream using String = std::basic_string<char, std::char_traits<char>, Allocator<char>>;
#else using IStringStream =
#define JSONCPP_STRING std::string std::basic_istringstream<String::value_type, String::traits_type,
#define JSONCPP_OSTRINGSTREAM std::ostringstream String::allocator_type>;
#define JSONCPP_OSTREAM std::ostream using OStringStream =
#define JSONCPP_ISTRINGSTREAM std::istringstream std::basic_ostringstream<String::value_type, String::traits_type,
#define JSONCPP_ISTREAM std::istream String::allocator_type>;
#endif // if JSONCPP_USING_SECURE_MEMORY using IStream = std::istream;
} // end namespace Json using OStream = std::ostream;
} // namespace Json
// Legacy names (formerly macros).
using JSONCPP_STRING = Json::String;
using JSONCPP_ISTRINGSTREAM = Json::IStringStream;
using JSONCPP_OSTRINGSTREAM = Json::OStringStream;
using JSONCPP_ISTREAM = Json::IStream;
using JSONCPP_OSTREAM = Json::OStream;
#endif // JSON_CONFIG_H_INCLUDED #endif // JSON_CONFIG_H_INCLUDED
@ -299,17 +407,23 @@ typedef UInt64 LargestUInt;
namespace Json { namespace Json {
// writer.h // writer.h
class StreamWriter;
class StreamWriterBuilder;
class Writer;
class FastWriter; class FastWriter;
class StyledWriter; class StyledWriter;
class StyledStreamWriter;
// reader.h // reader.h
class Reader; class Reader;
class CharReader;
class CharReaderBuilder;
// features.h // json_features.h
class Features; class Features;
// value.h // value.h
typedef unsigned int ArrayIndex; using ArrayIndex = unsigned int;
class StaticString; class StaticString;
class Path; class Path;
class PathArgument; class PathArgument;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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