Merge Dragonfire
Dragonfire commit: 56d536ea5e1f98c760d7c78a4584df043fb7f0f8
This commit is contained in:
commit
be80a15bad
6
.github/CONTRIBUTING.md
vendored
6
.github/CONTRIBUTING.md
vendored
@ -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.
|
||||
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
|
||||
|
||||
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
42
.github/workflows/android.yml
vendored
Normal 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
|
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
@ -221,8 +221,8 @@ jobs:
|
||||
name: VS 2019 ${{ matrix.config.arch }}-${{ matrix.type }}
|
||||
runs-on: windows-2019
|
||||
env:
|
||||
VCPKG_VERSION: c7ab9d3110813979a873b2dbac630a9ab79850dc
|
||||
# 2020.04
|
||||
VCPKG_VERSION: 0bf3923f9fab4001c00f0f429682a0853b5749e0
|
||||
# 2020.11
|
||||
vcpkg_packages: irrlicht zlib curl[winssl] openal-soft libvorbis libogg sqlite3 freetype luajit
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@ -248,7 +248,7 @@ jobs:
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Restore from cache and run vcpkg
|
||||
uses: lukka/run-vcpkg@v2
|
||||
uses: lukka/run-vcpkg@v5
|
||||
with:
|
||||
vcpkgArguments: ${{env.vcpkg_packages}}
|
||||
vcpkgDirectory: '${{ github.workspace }}\vcpkg'
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -53,6 +53,7 @@ build/.cmake/
|
||||
/worlds
|
||||
/world/
|
||||
/client/mod_storage/
|
||||
!/clientmods/mods_here.txt
|
||||
|
||||
## Configuration/log files
|
||||
minetest.conf
|
||||
|
@ -36,7 +36,7 @@ variables:
|
||||
- cp misc/debpkg-control build/deb/minetest/DEBIAN/control
|
||||
- cp -Rp artifact/minetest/usr build/deb/minetest/
|
||||
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
|
||||
- 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
|
||||
@ -142,36 +142,6 @@ deploy:debian-10:
|
||||
## 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
|
||||
|
||||
build:ubuntu-16.04:
|
||||
@ -197,6 +167,31 @@ deploy:ubuntu-16.04:
|
||||
variables:
|
||||
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
|
||||
##
|
||||
@ -308,3 +303,28 @@ pages:
|
||||
only:
|
||||
- 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
|
||||
|
@ -72,3 +72,11 @@ files["builtin/mainmenu"] = {
|
||||
"PLATFORM",
|
||||
},
|
||||
}
|
||||
|
||||
files["builtin/common/tests"] = {
|
||||
read_globals = {
|
||||
"describe",
|
||||
"it",
|
||||
"assert",
|
||||
},
|
||||
}
|
||||
|
51
AppImageBuilder.yml
Normal file
51
AppImageBuilder.yml
Normal 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
|
@ -249,15 +249,15 @@ cpack_add_component(Docs
|
||||
|
||||
cpack_add_component(SUBGAME_MINETEST_GAME
|
||||
DISPLAY_NAME "Minetest Game"
|
||||
DESCRIPTION "The official subgame for the Minetest engine, that can easily extended by mods."
|
||||
GROUP "Subgames"
|
||||
DESCRIPTION "The default game bundled in the Minetest engine. Mainly used as a modding base."
|
||||
GROUP "Games"
|
||||
)
|
||||
|
||||
cpack_add_component(SUBGAME_MINIMAL
|
||||
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.
|
||||
GROUP "Subgames"
|
||||
GROUP "Games"
|
||||
)
|
||||
|
||||
cpack_add_component_group(Subgames
|
||||
|
@ -21,7 +21,7 @@ WORKDIR /usr/src/minetest
|
||||
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 \
|
||||
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 && \
|
||||
rm -fr ./games/minetest_game/.git
|
||||
|
||||
@ -51,7 +51,7 @@ RUN mkdir build && \
|
||||
|
||||
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 && \
|
||||
chown -R minetest:minetest /var/lib/minetest
|
||||
|
||||
|
@ -102,11 +102,11 @@ Where each location is on each platform:
|
||||
* `bin` = `bin`
|
||||
* `share` = `.`
|
||||
* `user` = `.`
|
||||
* Windows installed:
|
||||
* Windows installation:
|
||||
* `bin` = `C:\Program Files\Minetest\bin (Depends on the install location)`
|
||||
* `share` = `C:\Program Files\Minetest (Depends on the install location)`
|
||||
* `user` = `%APPDATA%\Minetest`
|
||||
* Linux installed:
|
||||
* Linux installation:
|
||||
* `bin` = `/usr/bin`
|
||||
* `share` = `/usr/share/minetest`
|
||||
* `user` = `~/.minetest`
|
||||
@ -321,13 +321,14 @@ It is highly recommended to use vcpkg as package manager.
|
||||
|
||||
After you successfully built vcpkg you can easily install the required libraries:
|
||||
```powershell
|
||||
vcpkg install irrlicht zlib curl[winssl] openal-soft libvorbis libogg sqlite3 freetype luajit --triplet x64-windows
|
||||
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.
|
||||
- `openal-soft`, `libvorbis` and `libogg` are optional, but required to use sound.
|
||||
- `freetype` is optional, it allows true-type font rendering.
|
||||
- `luajit` is optional, it replaces the integrated Lua interpreter with a faster just-in-time interpreter.
|
||||
- `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.
|
||||
|
||||
@ -360,7 +361,7 @@ This is outdated and not recommended. Follow the instructions on https://dev.min
|
||||
Run the following script in PowerShell:
|
||||
|
||||
```powershell
|
||||
cmake . -G"Visual Studio 15 2017 Win64" -DCMAKE_TOOLCHAIN_FILE=D:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_GETTEXT=0 -DENABLE_CURSES=0
|
||||
cmake . -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
|
||||
```
|
||||
Make sure that the right compiler is selected and the path to the vcpkg toolchain is correct.
|
||||
|
@ -1,8 +1,8 @@
|
||||
apply plugin: 'com.android.application'
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion '29.0.3'
|
||||
ndkVersion '21.1.6352462'
|
||||
buildToolsVersion '30.0.2'
|
||||
ndkVersion '21.3.6528147'
|
||||
defaultConfig {
|
||||
applicationId 'net.minetest.minetest'
|
||||
minSdkVersion 16
|
||||
@ -11,8 +11,11 @@ android {
|
||||
versionCode project.versionCode
|
||||
}
|
||||
|
||||
// load 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) {
|
||||
signingConfigs {
|
||||
@ -61,10 +64,9 @@ task prepareAssets() {
|
||||
copy {
|
||||
from "${projRoot}/builtin" into "${assetsFolder}/builtin"
|
||||
}
|
||||
/*copy {
|
||||
// ToDo: fix Minetest shaders that currently don't work with OpenGL ES
|
||||
copy {
|
||||
from "${projRoot}/client/shaders" into "${assetsFolder}/client/shaders"
|
||||
}*/
|
||||
}
|
||||
copy {
|
||||
from "../native/deps/Android/Irrlicht/shaders" into "${assetsFolder}/client/shaders/Irrlicht"
|
||||
}
|
||||
@ -107,5 +109,5 @@ android.applicationVariants.all { variant ->
|
||||
|
||||
dependencies {
|
||||
implementation project(':native')
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
}
|
||||
|
@ -17,8 +17,8 @@
|
||||
android:allowBackup="false"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/label"
|
||||
android:resizeableActivity="false"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:resizeableActivity="false"
|
||||
tools:ignore="UnusedAttribute">
|
||||
|
||||
<meta-data
|
||||
@ -53,11 +53,6 @@
|
||||
android:value="Minetest" />
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".InputDialogActivity"
|
||||
android:maxAspectRatio="3.0"
|
||||
android:theme="@style/InputTheme" />
|
||||
|
||||
<service
|
||||
android:name=".UnzipService"
|
||||
android:enabled="true"
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -25,8 +25,16 @@ import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.InputType;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
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 {
|
||||
static {
|
||||
@ -34,8 +42,8 @@ public class GameActivity extends NativeActivity {
|
||||
System.loadLibrary("Minetest");
|
||||
}
|
||||
|
||||
private int messageReturnCode;
|
||||
private String messageReturnValue;
|
||||
private int messageReturnCode = -1;
|
||||
private String messageReturnValue = "";
|
||||
|
||||
public static native void putMessageBoxResult(String text);
|
||||
|
||||
@ -43,8 +51,6 @@ public class GameActivity extends NativeActivity {
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
messageReturnCode = -1;
|
||||
messageReturnValue = "";
|
||||
}
|
||||
|
||||
private void makeFullScreen() {
|
||||
@ -73,29 +79,46 @@ public class GameActivity extends NativeActivity {
|
||||
// Ignore the back press so Minetest can handle it
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
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) {
|
||||
runOnUiThread(() -> showDialogUI(hint, current, editType));
|
||||
}
|
||||
|
||||
public void showDialog(String acceptButton, String hint, String current, int editType) {
|
||||
Intent intent = new Intent(this, InputDialogActivity.class);
|
||||
Bundle params = new Bundle();
|
||||
params.putString("acceptButton", acceptButton);
|
||||
params.putString("hint", hint);
|
||||
params.putString("current", current);
|
||||
params.putInt("editType", editType);
|
||||
intent.putExtras(params);
|
||||
startActivityForResult(intent, 101);
|
||||
messageReturnValue = "";
|
||||
messageReturnCode = -1;
|
||||
private void showDialogUI(String hint, String current, int editType) {
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
EditText editText = new CustomEditText(this);
|
||||
builder.setView(editText);
|
||||
AlertDialog alertDialog = builder.create();
|
||||
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 == 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() {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -8,15 +8,8 @@
|
||||
<item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="p">shortEdges</item>
|
||||
</style>
|
||||
|
||||
<style name="InputTheme" parent="Theme.AppCompat.DayNight.Dialog">
|
||||
<item name="windowNoTitle">true</item>
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
</style>
|
||||
|
||||
<style name="CustomProgressBar" parent="@style/Widget.AppCompat.ProgressBar.Horizontal">
|
||||
<style name="CustomProgressBar" parent="Widget.AppCompat.ProgressBar.Horizontal">
|
||||
<item name="android:indeterminateOnly">false</item>
|
||||
<item name="android:minHeight">10dip</item>
|
||||
<item name="android:maxHeight">20dip</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
@ -15,8 +15,8 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.6.3'
|
||||
classpath 'org.ajoberstar.grgit:grgit-gradle:4.0.2'
|
||||
classpath 'com.android.tools.build:gradle:4.0.1'
|
||||
classpath 'de.undercouch:gradle-download-task:4.1.1'
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
@ -31,4 +31,5 @@ allprojects {
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
delete 'native/deps'
|
||||
}
|
||||
|
@ -1,2 +1,6 @@
|
||||
#Mon Apr 06 00:06:16 CEST 2020
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip
|
||||
#Mon Sep 07 22:11:10 CEST 2020
|
||||
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
|
||||
|
@ -1,16 +1,16 @@
|
||||
apply plugin: 'com.android.library'
|
||||
import org.ajoberstar.grgit.Grgit
|
||||
apply plugin: 'de.undercouch.download'
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion '29.0.3'
|
||||
ndkVersion '21.1.6352462'
|
||||
buildToolsVersion '30.0.2'
|
||||
ndkVersion '21.3.6528147'
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 29
|
||||
externalNativeBuild {
|
||||
ndkBuild {
|
||||
arguments '-j8',
|
||||
arguments '-j' + Runtime.getRuntime().availableProcessors(),
|
||||
"versionMajor=${versionMajor}",
|
||||
"versionMinor=${versionMinor}",
|
||||
"versionPatch=${versionPatch}",
|
||||
@ -45,15 +45,54 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
task cloneGitRepo() {
|
||||
def destination = file('deps')
|
||||
if(!destination.exists()) {
|
||||
def grgit = Grgit.clone(
|
||||
dir: destination,
|
||||
uri: 'https://github.com/minetest/minetest_android_deps_binaries'
|
||||
)
|
||||
grgit.close()
|
||||
// get precompiled deps
|
||||
def folder = 'minetest_android_deps_binaries'
|
||||
|
||||
task downloadDeps(type: Download) {
|
||||
src 'https://github.com/minetest/' + folder + '/archive/master.zip'
|
||||
dest new File(buildDir, 'deps.zip')
|
||||
overwrite false
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -22,6 +22,11 @@ core.register_on_sending_chat_message(function(message)
|
||||
return true
|
||||
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]
|
||||
if cmd_def then
|
||||
core.set_last_run_mod(cmd_def.mod_origin)
|
||||
@ -40,4 +45,150 @@ function core.run_server_chatcommand(cmd, param)
|
||||
core.send_chat_message("/" .. cmd .. " " .. param)
|
||||
end
|
||||
|
||||
core.register_chatcommand("say", {
|
||||
description = "Send raw text",
|
||||
func = function(text)
|
||||
core.send_chat_message(text)
|
||||
return true
|
||||
end,
|
||||
})
|
||||
|
||||
core.register_chatcommand("teleport", {
|
||||
params = "<X>,<Y>,<Z>",
|
||||
description = "Teleport to coordinates.",
|
||||
func = function(param)
|
||||
local success, pos = core.parse_pos(param)
|
||||
if success then
|
||||
core.localplayer:set_pos(pos)
|
||||
return true, "Teleporting to " .. core.pos_to_string(pos)
|
||||
end
|
||||
return false, pos
|
||||
end,
|
||||
})
|
||||
|
||||
core.register_chatcommand("teleportjump", {
|
||||
params = "<X>,<Y>,<Z>",
|
||||
description = "Teleport to relative coordinates.",
|
||||
func = function(param)
|
||||
local success, pos = core.parse_relative_pos(param)
|
||||
if success then
|
||||
core.localplayer:set_pos(pos)
|
||||
return true, "Teleporting to " .. core.pos_to_string(pos)
|
||||
end
|
||||
return false, pos
|
||||
end,
|
||||
})
|
||||
|
||||
core.register_chatcommand("wielded", {
|
||||
description = "Print itemstring of wieleded item",
|
||||
func = function()
|
||||
return true, core.localplayer:get_wielded_item():get_name()
|
||||
end
|
||||
})
|
||||
|
||||
core.register_chatcommand("disconnect", {
|
||||
description = "Exit to main menu",
|
||||
func = function(param)
|
||||
core.disconnect()
|
||||
end,
|
||||
})
|
||||
|
||||
core.register_chatcommand("players", {
|
||||
description = "List online players",
|
||||
func = function(param)
|
||||
return true, "Online players: " .. table.concat(core.get_player_names(), ", ")
|
||||
end
|
||||
})
|
||||
|
||||
core.register_chatcommand("kill", {
|
||||
description = "Kill yourself",
|
||||
func = function()
|
||||
core.send_damage(10000)
|
||||
end,
|
||||
})
|
||||
|
||||
core.register_chatcommand("set", {
|
||||
params = "([-n] <name> <value>) | <name>",
|
||||
description = "Set or read client configuration setting",
|
||||
func = function(param)
|
||||
local arg, setname, setvalue = string.match(param, "(-[n]) ([^ ]+) (.+)")
|
||||
if arg and arg == "-n" and setname and setvalue then
|
||||
core.settings:set(setname, setvalue)
|
||||
return true, setname .. " = " .. setvalue
|
||||
end
|
||||
|
||||
setname, setvalue = string.match(param, "([^ ]+) (.+)")
|
||||
if setname and setvalue then
|
||||
if not core.settings:get(setname) then
|
||||
return false, "Failed. Use '.set -n <name> <value>' to create a new setting."
|
||||
end
|
||||
core.settings:set(setname, setvalue)
|
||||
return true, setname .. " = " .. setvalue
|
||||
end
|
||||
|
||||
setname = string.match(param, "([^ ]+)")
|
||||
if setname then
|
||||
setvalue = core.settings:get(setname)
|
||||
if not setvalue then
|
||||
setvalue = "<not set>"
|
||||
end
|
||||
return true, setname .. " = " .. setvalue
|
||||
end
|
||||
|
||||
return false, "Invalid parameters (see .help set)."
|
||||
end,
|
||||
})
|
||||
|
||||
core.register_chatcommand("place", {
|
||||
params = "<X>,<Y>,<Z>",
|
||||
description = "Place wielded item",
|
||||
func = function(param)
|
||||
local success, pos = core.parse_relative_pos(param)
|
||||
if success then
|
||||
core.place_node(pos)
|
||||
return true, "Node placed at " .. core.pos_to_string(pos)
|
||||
end
|
||||
return false, pos
|
||||
end,
|
||||
})
|
||||
|
||||
core.register_chatcommand("dig", {
|
||||
params = "<X>,<Y>,<Z>",
|
||||
description = "Dig node",
|
||||
func = function(param)
|
||||
local success, pos = core.parse_relative_pos(param)
|
||||
if success then
|
||||
core.dig_node(pos)
|
||||
return true, "Node at " .. core.pos_to_string(pos) .. " dug"
|
||||
end
|
||||
return false, pos
|
||||
end,
|
||||
})
|
||||
|
||||
core.register_chatcommand("setyaw", {
|
||||
params = "<yaw>",
|
||||
description = "Set your yaw",
|
||||
func = function(param)
|
||||
local yaw = tonumber(param)
|
||||
if yaw then
|
||||
core.localplayer:set_yaw(yaw)
|
||||
return true
|
||||
else
|
||||
return false, "Invalid usage (See /help setyaw)"
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
core.register_chatcommand("setpitch", {
|
||||
params = "<pitch>",
|
||||
description = "Set your pitch",
|
||||
func = function(param)
|
||||
local pitch = tonumber(param)
|
||||
if pitch then
|
||||
core.localplayer:set_pitch(pitch)
|
||||
return true
|
||||
else
|
||||
return false, "Invalid usage (See /help setpitch)"
|
||||
end
|
||||
end
|
||||
})
|
||||
|
@ -1,25 +1,24 @@
|
||||
core.cheats = {
|
||||
["Combat"] = {
|
||||
["Killaura"] = "killaura",
|
||||
["AntiKnockback"] = "antiknockback",
|
||||
["FastHit"] = "spamclick",
|
||||
["AttachmentFloat"] = "float_above_parent",
|
||||
["CrystalPvP"] = "crystal_pvp",
|
||||
["AutoTotem"] = "autototem",
|
||||
["ThroughWalls"] = "dont_point_nodes",
|
||||
["AutoHit"] = "autohit",
|
||||
},
|
||||
["Movement"] = {
|
||||
["Freecam"] = "freecam",
|
||||
["PrivBypass"] = "priv_bypass",
|
||||
["AutoForward"] = "continuous_forward",
|
||||
["PitchMove"] = "pitch_move",
|
||||
["AutoJump"] = "autojump",
|
||||
["Jesus"] = "jesus",
|
||||
["NoSlow"] = "no_slow",
|
||||
["AutoSneak"] = "autosneak",
|
||||
["Autosprint"] = 'autosprint',
|
||||
["AutoForwSprint"] = 'autofsprint',
|
||||
["Jetpack"] = 'jetpack',
|
||||
["SpeedOverride"] = "override_speed",
|
||||
["JumpOverride"] = "override_jump",
|
||||
["GravityOverride"] = "override_gravity",
|
||||
["AntiSlip"] = "antislip",
|
||||
},
|
||||
["Render"] = {
|
||||
["Xray"] = "xray",
|
||||
@ -28,9 +27,14 @@ core.cheats = {
|
||||
["NoHurtCam"] = "no_hurt_cam",
|
||||
["BrightNight"] = "no_night",
|
||||
["Coords"] = "coords",
|
||||
["Tracers"] = "enable_tracers",
|
||||
["ESP"] = "enable_esp",
|
||||
["Clouds"] = "enable_clouds",
|
||||
["CheatHUD"] = "cheat_hud",
|
||||
["EntityESP"] = "enable_entity_esp",
|
||||
["EntityTracers"] = "enable_entity_tracers",
|
||||
["PlayerESP"] = "enable_player_esp",
|
||||
["PlayerTracers"] = "enable_player_tracers",
|
||||
["NodeESP"] = "enable_node_esp",
|
||||
["NodeTracers"] = "enable_node_tracers",
|
||||
},
|
||||
["World"] = {
|
||||
["FastDig"] = "fastdig",
|
||||
@ -38,14 +42,6 @@ core.cheats = {
|
||||
["AutoDig"] = "autodig",
|
||||
["AutoPlace"] = "autoplace",
|
||||
["InstantBreak"] = "instant_break",
|
||||
["IncreasedRange"] = "increase_tool_range",
|
||||
["UnlimitedRange"] = "increase_tool_range_plus",
|
||||
["PointLiquids"] = "point_liquids",
|
||||
["Scaffold"] = "scaffold",
|
||||
["ScaffoldPlus"] = "scaffold_plus",
|
||||
["BlockWater"] = "block_water",
|
||||
["PlaceOnTop"] = "autotnt",
|
||||
["Replace"] = "replace",
|
||||
},
|
||||
["Exploit"] = {
|
||||
["EntitySpeed"] = "entity_speed",
|
||||
@ -62,15 +58,9 @@ core.cheats = {
|
||||
["UnlimitedRange"] = "increase_tool_range_plus",
|
||||
["PointLiquids"] = "point_liquids",
|
||||
["PrivBypass"] = "priv_bypass",
|
||||
["AutoRespawn"] = "autorespawn",
|
||||
},
|
||||
["Inventory"] = {
|
||||
["AutoEject"] = "autoeject",
|
||||
["AutoTool"] = "autotool",
|
||||
["Enderchest"] = core.open_enderchest,
|
||||
["HandSlot"] = core.open_handslot,
|
||||
["NextItem"] = "next_item",
|
||||
},
|
||||
["Chat"] = {},
|
||||
["Inventory"] = {}
|
||||
}
|
||||
|
||||
function core.register_cheat(cheatname, category, func)
|
||||
|
@ -4,6 +4,13 @@ core.callback_origins = {}
|
||||
local getinfo = debug.getinfo
|
||||
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, ...)
|
||||
assert(type(callbacks) == "table")
|
||||
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_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_chatcommand, core.register_on_chatcommand = 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_damage_taken, core.register_on_damage_taken = make_registration()
|
||||
@ -96,3 +104,6 @@ core.registered_on_modchannel_signal, core.register_on_modchannel_signal = make_
|
||||
core.registered_on_inventory_open, core.register_on_inventory_open = make_registration()
|
||||
core.registered_on_receiving_inventory_form, core.register_on_receiving_inventory_form = make_registration()
|
||||
core.registered_on_nodemeta_form_open, core.register_on_nodemeta_form_open = make_registration()
|
||||
core.registered_on_recieve_physics_override, core.register_on_recieve_physics_override = make_registration()
|
||||
core.registered_on_play_sound, core.register_on_play_sound = make_registration()
|
||||
core.registered_on_spawn_particle, core.register_on_spawn_particle = make_registration()
|
||||
|
@ -41,7 +41,7 @@ end
|
||||
|
||||
function core.get_pointed_thing()
|
||||
local pos = core.camera:get_pos()
|
||||
local pos2 = vector.add(pos, vector.multiply(core.camera:get_look_dir(), 5))
|
||||
local pos2 = vector.add(pos, vector.multiply(core.camera:get_look_dir(), 7))
|
||||
local player = core.localplayer
|
||||
if not player then return end
|
||||
local item = player:get_wielded_item()
|
||||
@ -49,4 +49,8 @@ function core.get_pointed_thing()
|
||||
local def = core.get_item_def(item:get_name())
|
||||
local ray = core.raycast(pos, pos2, true, core.settings:get_bool("point_liquids") or def and def.liquids_pointable)
|
||||
return ray and ray:next()
|
||||
end
|
||||
end
|
||||
|
||||
function core.close_formspec(formname)
|
||||
return core.show_formspec(formname, "")
|
||||
end
|
||||
|
@ -31,11 +31,13 @@ function core.after(after, func, ...)
|
||||
assert(tonumber(after) and type(func) == "function",
|
||||
"Invalid minetest.after invocation")
|
||||
local expire = time + after
|
||||
jobs[#jobs + 1] = {
|
||||
local new_job = {
|
||||
func = func,
|
||||
expire = expire,
|
||||
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)
|
||||
return { cancel = function() new_job.func = function() end end }
|
||||
end
|
||||
|
@ -29,6 +29,51 @@ function core.override_chatcommand(name, redefinition)
|
||||
core.registered_chatcommands[name] = chatcommand
|
||||
end
|
||||
|
||||
if INIT == "client" then
|
||||
function core.register_list_command(command, desc, setting)
|
||||
local def = {}
|
||||
def.description = desc
|
||||
def.params = "del <item> | add <item> | list"
|
||||
function def.func(param)
|
||||
local list = (minetest.settings:get(setting) or ""):split(",")
|
||||
if param == "list" then
|
||||
return true, table.concat(list, ", ")
|
||||
else
|
||||
local sparam = param:split(" ")
|
||||
local cmd = sparam[1]
|
||||
local item = sparam[2]
|
||||
if cmd == "del" then
|
||||
if not item then
|
||||
return false, "Missing item."
|
||||
end
|
||||
local i = table.indexof(list, item)
|
||||
if i == -1 then
|
||||
return false, item .. " is not on the list."
|
||||
else
|
||||
table.remove(list, i)
|
||||
core.settings:set(setting, table.concat(list, ","))
|
||||
return true, "Removed " .. item .. " from the list."
|
||||
end
|
||||
elseif cmd == "add" then
|
||||
if not item then
|
||||
return false, "Missing item."
|
||||
end
|
||||
local i = table.indexof(list, item)
|
||||
if i ~= -1 then
|
||||
return false, item .. " is already on the list."
|
||||
else
|
||||
table.insert(list, item)
|
||||
core.settings:set(setting, table.concat(list, ","))
|
||||
return true, "Added " .. item .. " to the list."
|
||||
end
|
||||
end
|
||||
end
|
||||
return false, "Invalid usage. (See .help " .. command .. ")"
|
||||
end
|
||||
core.register_chatcommand(command, def)
|
||||
end
|
||||
end
|
||||
|
||||
local cmd_marker = "/"
|
||||
|
||||
local function gettext(...)
|
||||
|
@ -594,6 +594,67 @@ function core.colorize(color, message)
|
||||
return table.concat(lines, "\n") .. core.get_color_escape_sequence("#ffffff")
|
||||
end
|
||||
|
||||
local function rgb_to_hex(rgb)
|
||||
local hexadecimal = '#'
|
||||
|
||||
for key, value in pairs(rgb) do
|
||||
local hex = ''
|
||||
|
||||
while(value > 0)do
|
||||
local index = math.fmod(value, 16) + 1
|
||||
value = math.floor(value / 16)
|
||||
hex = string.sub('0123456789ABCDEF', index, index) .. hex
|
||||
end
|
||||
|
||||
if(string.len(hex) == 0)then
|
||||
hex = '00'
|
||||
|
||||
elseif(string.len(hex) == 1)then
|
||||
hex = '0' .. hex
|
||||
end
|
||||
|
||||
hexadecimal = hexadecimal .. hex
|
||||
end
|
||||
|
||||
return hexadecimal
|
||||
end
|
||||
|
||||
local function color_from_hue(hue)
|
||||
local h = hue / 60
|
||||
local c = 255
|
||||
local x = (1 - math.abs(h%2 - 1)) * 255
|
||||
|
||||
local i = math.floor(h);
|
||||
if (i == 0) then
|
||||
return rgb_to_hex({c, x, 0})
|
||||
elseif (i == 1) then
|
||||
return rgb_to_hex({x, c, 0})
|
||||
elseif (i == 2) then
|
||||
return rgb_to_hex({0, c, x})
|
||||
elseif (i == 3) then
|
||||
return rgb_to_hex({0, x, c});
|
||||
elseif (i == 4) then
|
||||
return rgb_to_hex({x, 0, c});
|
||||
else
|
||||
return rgb_to_hex({c, 0, x});
|
||||
end
|
||||
end
|
||||
|
||||
function core.rainbow(input)
|
||||
local step = 360 / input:len()
|
||||
local hue = 0
|
||||
local output = ""
|
||||
for i = 1, input:len() do
|
||||
local char = input:sub(i,i)
|
||||
if char:match("%s") then
|
||||
output = output .. char
|
||||
else
|
||||
output = output .. core.get_color_escape_sequence(color_from_hue(hue)) .. char
|
||||
end
|
||||
hue = hue + step
|
||||
end
|
||||
return output
|
||||
end
|
||||
|
||||
function core.strip_foreground_colors(str)
|
||||
return (str:gsub(ESCAPE_CHAR .. "%(c@[^)]+%)", ""))
|
||||
@ -647,6 +708,19 @@ function core.get_translator(textdomain)
|
||||
return function(str, ...) return core.translate(textdomain or "", str, ...) end
|
||||
end
|
||||
|
||||
function core.get_pointed_thing_position(pointed_thing, above)
|
||||
if pointed_thing.type == "node" then
|
||||
if above then
|
||||
-- The position where a node would be placed
|
||||
return pointed_thing.above
|
||||
end
|
||||
-- The position where a node would be dug
|
||||
return pointed_thing.under
|
||||
elseif pointed_thing.type == "object" then
|
||||
return pointed_thing.ref and pointed_thing.ref:get_pos()
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Returns the exact coordinate of a pointed surface
|
||||
--------------------------------------------------------------------------------
|
||||
|
@ -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 }))
|
||||
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.
|
||||
local function almost_equal(a, b)
|
||||
if type(a) == "number" then
|
||||
|
@ -137,6 +137,12 @@ function vector.divide(a, b)
|
||||
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)
|
||||
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)}
|
||||
|
@ -64,6 +64,7 @@ function ui.update()
|
||||
formspec = {
|
||||
"size[14,8]",
|
||||
"real_coordinates[true]",
|
||||
"set_focus[btn_reconnect_yes;true]",
|
||||
"box[0.5,1.2;13,5;#000]",
|
||||
("textarea[0.5,1.2;13,5;;%s;%s]"):format(
|
||||
fgettext("The server has requested a reconnect:"), error_message),
|
||||
@ -82,6 +83,7 @@ function ui.update()
|
||||
formspec = {
|
||||
"size[14,8]",
|
||||
"real_coordinates[true]",
|
||||
"set_focus[btn_error_confirm;true]",
|
||||
"box[0.5,1.2;13,5;#000]",
|
||||
("textarea[0.5,1.2;13,5;;%s;%s]"):format(
|
||||
error_title, error_message),
|
||||
|
@ -58,6 +58,11 @@ core.register_on_chat_message(function(name, message)
|
||||
|
||||
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]
|
||||
if not cmd_def then
|
||||
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)
|
||||
if has_privs then
|
||||
core.set_last_run_mod(cmd_def.mod_origin)
|
||||
local _, result = cmd_def.func(name, param)
|
||||
if result then
|
||||
local success, result = cmd_def.func(name, param)
|
||||
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)
|
||||
end
|
||||
else
|
||||
@ -1070,10 +1084,10 @@ core.register_chatcommand("last-login", {
|
||||
local pauth = core.get_auth_handler().get_auth(param)
|
||||
if pauth and pauth.last_login and pauth.last_login ~= -1 then
|
||||
-- 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)
|
||||
end
|
||||
return false, "Last login time is unknown"
|
||||
return false, param.."'s last login time is unknown"
|
||||
end,
|
||||
})
|
||||
|
||||
|
@ -52,6 +52,7 @@ core.register_entity(":__builtin:falling_node", {
|
||||
floats = false,
|
||||
|
||||
set_node = function(self, node, meta)
|
||||
node.param2 = node.param2 or 0
|
||||
self.node = node
|
||||
meta = meta or {}
|
||||
if type(meta.to_table) == "function" then
|
||||
@ -83,6 +84,9 @@ core.register_entity(":__builtin:falling_node", {
|
||||
local textures
|
||||
if def.tiles and def.tiles[1] then
|
||||
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
|
||||
tile = tile.name
|
||||
end
|
||||
@ -143,7 +147,11 @@ core.register_entity(":__builtin:falling_node", {
|
||||
|
||||
-- Rotate entity
|
||||
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 == ""
|
||||
or def.wield_image == nil))
|
||||
or def.drawtype == "signlike"
|
||||
|
@ -17,6 +17,7 @@ core.features = {
|
||||
area_store_persistent_ids = true,
|
||||
pathfinder_works = true,
|
||||
object_step_has_moveresult = true,
|
||||
direct_velocity_on_players = true,
|
||||
}
|
||||
|
||||
function core.has_feature(arg)
|
||||
|
@ -24,19 +24,6 @@ function core.inventorycube(img1, img2, img3)
|
||||
.. "{" .. img3:gsub("%^", "&")
|
||||
end
|
||||
|
||||
function core.get_pointed_thing_position(pointed_thing, above)
|
||||
if pointed_thing.type == "node" then
|
||||
if above then
|
||||
-- The position where a node would be placed
|
||||
return pointed_thing.above
|
||||
end
|
||||
-- The position where a node would be dug
|
||||
return pointed_thing.under
|
||||
elseif pointed_thing.type == "object" then
|
||||
return pointed_thing.ref and pointed_thing.ref:get_pos()
|
||||
end
|
||||
end
|
||||
|
||||
function core.dir_to_facedir(dir, is6d)
|
||||
--account for y if requested
|
||||
if is6d and math.abs(dir.y) > math.abs(dir.x) and math.abs(dir.y) > math.abs(dir.z) then
|
||||
@ -551,8 +538,9 @@ function core.node_dig(pos, node, digger)
|
||||
local diggername = user_name(digger)
|
||||
local log = make_log(diggername)
|
||||
local def = core.registered_nodes[node.name]
|
||||
-- Copy pos because the callback could modify it
|
||||
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 "
|
||||
.. node.name .. " which is not diggable "
|
||||
.. core.pos_to_string(pos))
|
||||
|
@ -54,8 +54,9 @@ core.register_entity(":__builtin:item", {
|
||||
local max_count = stack:get_stack_max()
|
||||
local count = math.min(stack:get_count(), max_count)
|
||||
local size = 0.2 + 0.1 * (count / max_count) ^ (1 / 3)
|
||||
local def = core.registered_nodes[itemname]
|
||||
local glow = def and math.floor(def.light_source / 2 + 0.5)
|
||||
local def = core.registered_items[itemname]
|
||||
local glow = def and def.light_source and
|
||||
math.floor(def.light_source / 2 + 0.5)
|
||||
|
||||
self.object:set_properties({
|
||||
is_visible = true,
|
||||
|
@ -151,6 +151,12 @@ function core.setting_get_pos(name)
|
||||
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
|
||||
|
||||
function core.is_protected(pos, name)
|
||||
|
@ -118,6 +118,10 @@ function core.register_item(name, itemdef)
|
||||
end
|
||||
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
|
||||
if itemdef.type == "node" then
|
||||
-- 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.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_playerevents, core.register_playerevent = make_registration()
|
||||
core.registered_on_mods_loaded, core.register_on_mods_loaded = make_registration()
|
||||
|
@ -40,14 +40,17 @@ local num_per_page = 5
|
||||
local filter_type = 1
|
||||
local filter_types_titles = {
|
||||
fgettext("All packages"),
|
||||
fgettext("Games"),
|
||||
fgettext("Mods"),
|
||||
-- fgettext("Games"),
|
||||
fgettext("Clientmods"),
|
||||
fgettext("Texture packs"),
|
||||
}
|
||||
|
||||
local number_downloading = 0
|
||||
local download_queue = {}
|
||||
|
||||
local filter_types_type = {
|
||||
nil,
|
||||
"game",
|
||||
-- "game",
|
||||
"mod",
|
||||
"txp",
|
||||
}
|
||||
@ -67,12 +70,14 @@ local function download_package(param)
|
||||
end
|
||||
end
|
||||
|
||||
local function start_install(calling_dialog, package)
|
||||
local function start_install(package)
|
||||
local params = {
|
||||
package = package,
|
||||
filename = os.tempfolder() .. "_MODNAME_" .. package.name .. ".zip",
|
||||
}
|
||||
|
||||
number_downloading = number_downloading + 1
|
||||
|
||||
local function callback(result)
|
||||
if result.successful then
|
||||
local path, msg = pkgmgr.install(package.type,
|
||||
@ -121,9 +126,20 @@ local function start_install(calling_dialog, package)
|
||||
end
|
||||
|
||||
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()
|
||||
end
|
||||
|
||||
package.queued = false
|
||||
package.downloading = true
|
||||
|
||||
if not core.handle_async(download_package, params, callback) then
|
||||
@ -133,6 +149,16 @@ local function start_install(calling_dialog, package)
|
||||
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 parts = path:split(".")
|
||||
return parts[#parts]
|
||||
@ -228,7 +254,7 @@ end
|
||||
function store.update_paths()
|
||||
local mod_hash = {}
|
||||
pkgmgr.refresh_globals()
|
||||
for _, mod in pairs(pkgmgr.global_mods:get_list()) do
|
||||
for _, mod in pairs(pkgmgr.clientmods:get_list()) do
|
||||
if mod.author then
|
||||
mod_hash[mod.author:lower() .. "/" .. mod.name] = mod
|
||||
end
|
||||
@ -279,7 +305,7 @@ function store.filter_packages(query)
|
||||
table.insert(keywords, word)
|
||||
end
|
||||
|
||||
local function matches_keywords(package, keywords)
|
||||
local function matches_keywords(package)
|
||||
for k = 1, #keywords do
|
||||
local keyword = keywords[k]
|
||||
|
||||
@ -296,7 +322,7 @@ function store.filter_packages(query)
|
||||
|
||||
store.packages = {}
|
||||
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
|
||||
store.packages[#store.packages + 1] = package
|
||||
end
|
||||
@ -321,11 +347,14 @@ function store.get_formspec(dlgdata)
|
||||
"formspec_version[3]",
|
||||
"size[15.75,9.5]",
|
||||
"position[0.5,0.55]",
|
||||
|
||||
"style[status;border=false]",
|
||||
|
||||
"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]",
|
||||
"button[10.225,0;2,0.8;search;", fgettext("Search"), "]",
|
||||
"dropdown[12.6,0;2.4,0.8;type;", table.concat(filter_types_titles, ","), ";", filter_type, "]",
|
||||
"button[7.225,0;2,0.8;search;", fgettext("Search"), "]",
|
||||
"dropdown[9.6,0;2.4,0.8;type;", table.concat(filter_types_titles, ","), ";", filter_type, "]",
|
||||
"container_end[]",
|
||||
|
||||
-- Page nav buttons
|
||||
@ -344,6 +373,35 @@ function store.get_formspec(dlgdata)
|
||||
"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
|
||||
formspec[#formspec + 1] = "label[4,3;"
|
||||
formspec[#formspec + 1] = fgettext("No results")
|
||||
@ -386,11 +444,13 @@ function store.get_formspec(dlgdata)
|
||||
formspec[#formspec + 1] = ",0.1]"
|
||||
|
||||
if package.downloading then
|
||||
formspec[#formspec + 1] = "style[download;border=false]"
|
||||
|
||||
formspec[#formspec + 1] = "button[-3.5,0;2,0.8;download;"
|
||||
formspec[#formspec + 1] = "button[-3.5,0;2,0.8;status;"
|
||||
formspec[#formspec + 1] = fgettext("Downloading...")
|
||||
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
|
||||
formspec[#formspec + 1] = "button[-3,0;1.5,0.8;install_"
|
||||
formspec[#formspec + 1] = tostring(i)
|
||||
@ -485,6 +545,17 @@ function store.handle_submit(this, fields)
|
||||
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
|
||||
assert(start_idx ~= nil)
|
||||
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)
|
||||
|
||||
if fields["install_" .. i] then
|
||||
start_install(this, package)
|
||||
queue_download(package)
|
||||
return true
|
||||
end
|
||||
|
||||
@ -505,8 +576,9 @@ function store.handle_submit(this, fields)
|
||||
end
|
||||
|
||||
if fields["view_" .. i] then
|
||||
local url = ("%s/packages/%s?protocol_version=%d"):format(
|
||||
core.settings:get("contentdb_url"), package.id, core.get_max_supp_proto())
|
||||
local url = ("%s/packages/%s/%s?protocol_version=%d"):format(
|
||||
core.settings:get("contentdb_url"),
|
||||
package.author, package.name, core.get_max_supp_proto())
|
||||
core.open_url(url)
|
||||
return true
|
||||
end
|
||||
|
@ -61,6 +61,7 @@ local flag_checkboxes = {
|
||||
fgettext("Low humidity and high heat causes shallow or dry rivers") },
|
||||
},
|
||||
flat = {
|
||||
cb_caverns,
|
||||
{ "hills", fgettext("Hills"), "hills" },
|
||||
{ "lakes", fgettext("Lakes"), "lakes" },
|
||||
},
|
||||
@ -362,10 +363,18 @@ local function create_world_buttonhandler(this, fields)
|
||||
local gameindex = core.get_textlist_index("games")
|
||||
|
||||
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
|
||||
local random_number = math.random(10000, 99999)
|
||||
local random_world_name = "Unnamed" .. random_number
|
||||
worldname = random_world_name
|
||||
local worldnum_max = 0
|
||||
for _, world in ipairs(menudata.worldlist:get_list()) do
|
||||
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
|
||||
|
||||
core.settings:set("fixed_map_seed", fields["te_seed"])
|
||||
|
@ -22,7 +22,6 @@ mt_color_dark_green = "#25C191"
|
||||
|
||||
local menupath = core.get_mainmenu_path()
|
||||
local basepath = core.get_builtin_path()
|
||||
local menustyle = core.settings:get("main_menu_style")
|
||||
defaulttexturedir = core.get_texturepath_share() .. DIR_DELIM .. "base" ..
|
||||
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_settings_advanced.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_delete_content.lua")
|
||||
dofile(menupath .. DIR_DELIM .. "dlg_delete_world.lua")
|
||||
dofile(menupath .. DIR_DELIM .. "dlg_rename_modpack.lua")
|
||||
end
|
||||
dofile(menupath .. DIR_DELIM .. "dlg_create_world.lua")
|
||||
dofile(menupath .. DIR_DELIM .. "dlg_delete_content.lua")
|
||||
dofile(menupath .. DIR_DELIM .. "dlg_delete_world.lua")
|
||||
dofile(menupath .. DIR_DELIM .. "dlg_rename_modpack.lua")
|
||||
|
||||
local tabs = {}
|
||||
|
||||
tabs.settings = dofile(menupath .. DIR_DELIM .. "tab_settings.lua")
|
||||
tabs.content = dofile(menupath .. DIR_DELIM .. "tab_content.lua")
|
||||
tabs.credits = dofile(menupath .. DIR_DELIM .. "tab_credits.lua")
|
||||
if menustyle == "simple" then
|
||||
tabs.simple_main = dofile(menupath .. DIR_DELIM .. "tab_simple_main.lua")
|
||||
else
|
||||
tabs.local_game = dofile(menupath .. DIR_DELIM .. "tab_local.lua")
|
||||
tabs.play_online = dofile(menupath .. DIR_DELIM .. "tab_online.lua")
|
||||
end
|
||||
tabs.local_game = dofile(menupath .. DIR_DELIM .. "tab_local.lua")
|
||||
tabs.play_online = dofile(menupath .. DIR_DELIM .. "tab_online.lua")
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
local function main_event_handler(tabview, event)
|
||||
@ -71,68 +64,35 @@ local function init_globals()
|
||||
-- Init gamedata
|
||||
gamedata.worldindex = 0
|
||||
|
||||
if menustyle == "simple" then
|
||||
local world_list = core.get_worlds()
|
||||
local world_index
|
||||
|
||||
local found_singleplayerworld = false
|
||||
for i, world in ipairs(world_list) do
|
||||
if world.name == "singleplayerworld" then
|
||||
found_singleplayerworld = true
|
||||
world_index = i
|
||||
break
|
||||
end
|
||||
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
|
||||
)
|
||||
|
||||
if not found_singleplayerworld then
|
||||
core.create_world("singleplayerworld", 1)
|
||||
menudata.worldlist:add_sort_mechanism("alphabetic", sort_worlds_alphabetic)
|
||||
menudata.worldlist:set_sortmode("alphabetic")
|
||||
|
||||
world_list = core.get_worlds()
|
||||
|
||||
for i, world in ipairs(world_list) do
|
||||
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()
|
||||
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()
|
||||
|
||||
-- Create main tabview
|
||||
local tv_main = tabview_create("maintab", {x = 12, y = 5.4}, {x = 0, y = 0})
|
||||
|
||||
if menustyle == "simple" then
|
||||
tv_main:add(tabs.simple_main)
|
||||
else
|
||||
tv_main:set_autosave_tab(true)
|
||||
tv_main:add(tabs.local_game)
|
||||
tv_main:add(tabs.play_online)
|
||||
end
|
||||
tv_main:set_autosave_tab(true)
|
||||
tv_main:add(tabs.local_game)
|
||||
tv_main:add(tabs.play_online)
|
||||
|
||||
tv_main:add(tabs.content)
|
||||
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_fixed_size(false)
|
||||
|
||||
if menustyle ~= "simple" then
|
||||
local last_tab = core.settings:get("maintab_LAST")
|
||||
if last_tab and tv_main.current_tab ~= last_tab then
|
||||
tv_main:set_tab(last_tab)
|
||||
end
|
||||
local last_tab = core.settings:get("maintab_LAST")
|
||||
if last_tab and tv_main.current_tab ~= last_tab then
|
||||
tv_main:set_tab(last_tab)
|
||||
end
|
||||
ui.set_default("maintab")
|
||||
tv_main:show()
|
||||
|
@ -592,7 +592,7 @@ function pkgmgr.install_dir(type, path, basename, targetpath)
|
||||
clean_path = get_last_folder(cleanup_path(basefolder.path))
|
||||
end
|
||||
if clean_path then
|
||||
targetpath = core.get_modpath() .. DIR_DELIM .. clean_path
|
||||
targetpath = core.get_clientmodpath() .. DIR_DELIM .. clean_path
|
||||
else
|
||||
return nil,
|
||||
fgettext("Install Mod: Unable to find suitable folder name for modpack $1",
|
||||
@ -619,7 +619,7 @@ function pkgmgr.install_dir(type, path, basename, targetpath)
|
||||
end
|
||||
|
||||
if targetfolder ~= nil and pkgmgr.isValidModname(targetfolder) then
|
||||
targetpath = core.get_modpath() .. DIR_DELIM .. targetfolder
|
||||
targetpath = core.get_clientmodpath() .. DIR_DELIM .. targetfolder
|
||||
else
|
||||
return nil, fgettext("Install Mod: Unable to find real mod name for: $1", path)
|
||||
end
|
||||
@ -671,6 +671,54 @@ function pkgmgr.install(type, modfilename, basename, dest)
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
function pkgmgr.prepareclientmodlist(data)
|
||||
local retval = {}
|
||||
|
||||
local clientmods = {}
|
||||
|
||||
--read clientmods
|
||||
local modpath = core.get_clientmodpath()
|
||||
|
||||
if modpath ~= nil and
|
||||
modpath ~= "" then
|
||||
get_mods(modpath,clientmods)
|
||||
end
|
||||
|
||||
for i=1,#clientmods,1 do
|
||||
clientmods[i].type = "mod"
|
||||
clientmods[i].loc = "global"
|
||||
clientmods[i].is_clientside = true
|
||||
retval[#retval + 1] = clientmods[i]
|
||||
end
|
||||
|
||||
--read mods configuration
|
||||
local filename = modpath ..
|
||||
DIR_DELIM .. "mods.conf"
|
||||
|
||||
local conffile = Settings(filename)
|
||||
|
||||
for key,value in pairs(conffile:to_table()) do
|
||||
if key:sub(1, 9) == "load_mod_" then
|
||||
key = key:sub(10)
|
||||
local element = nil
|
||||
for i=1,#retval,1 do
|
||||
if retval[i].name == key and
|
||||
not retval[i].is_modpack then
|
||||
element = retval[i]
|
||||
break
|
||||
end
|
||||
end
|
||||
if element ~= nil then
|
||||
element.enabled = value ~= "false" and value ~= "nil" and value
|
||||
else
|
||||
core.log("info", "Clientmod: " .. key .. " " .. dump(value) .. " but not found")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return retval
|
||||
end
|
||||
|
||||
function pkgmgr.preparemodlist(data)
|
||||
local retval = {}
|
||||
|
||||
@ -813,6 +861,10 @@ function pkgmgr.refresh_globals()
|
||||
pkgmgr.comparemod, is_equal, nil, {})
|
||||
pkgmgr.global_mods:add_sort_mechanism("alphabetic", sort_mod_list)
|
||||
pkgmgr.global_mods:set_sortmode("alphabetic")
|
||||
pkgmgr.clientmods = filterlist.create(pkgmgr.prepareclientmodlist,
|
||||
pkgmgr.comparemod, is_equal, nil, {})
|
||||
pkgmgr.clientmods:add_sort_mechanism("alphabetic", sort_mod_list)
|
||||
pkgmgr.clientmods:set_sortmode("alphabetic")
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
@ -19,6 +19,10 @@
|
||||
local packages_raw
|
||||
local packages
|
||||
|
||||
local function modname_valid(name)
|
||||
return not name:find("[^a-z0-9_]")
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
local function get_formspec(tabview, name, tabdata)
|
||||
if pkgmgr.global_mods == nil then
|
||||
@ -33,6 +37,7 @@ local function get_formspec(tabview, name, tabdata)
|
||||
table.insert_all(packages_raw, pkgmgr.games)
|
||||
table.insert_all(packages_raw, pkgmgr.get_texture_packs())
|
||||
table.insert_all(packages_raw, pkgmgr.global_mods:get_list())
|
||||
table.insert_all(packages_raw, pkgmgr.clientmods:get_list())
|
||||
|
||||
local function get_data()
|
||||
return packages_raw
|
||||
@ -45,6 +50,38 @@ local function get_formspec(tabview, name, tabdata)
|
||||
|
||||
packages = filterlist.create(get_data, pkgmgr.compare_package,
|
||||
is_equal, nil, {})
|
||||
|
||||
local filename = core.get_clientmodpath() .. DIR_DELIM .. "mods.conf"
|
||||
|
||||
local conffile = Settings(filename)
|
||||
local mods = conffile:to_table()
|
||||
|
||||
for i = 1, #packages_raw do
|
||||
local mod = packages_raw[i]
|
||||
if mod.is_clientside and not mod.is_modpack then
|
||||
if modname_valid(mod.name) then
|
||||
conffile:set("load_mod_" .. mod.name,
|
||||
mod.enabled and "true" or "false")
|
||||
elseif mod.enabled then
|
||||
gamedata.errormessage = fgettext_ne("Failed to enable clientmo" ..
|
||||
"d \"$1\" as it contains disallowed characters. " ..
|
||||
"Only characters [a-z0-9_] are allowed.",
|
||||
mod.name)
|
||||
end
|
||||
mods["load_mod_" .. mod.name] = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Remove mods that are not present anymore
|
||||
for key in pairs(mods) do
|
||||
if key:sub(1, 9) == "load_mod_" then
|
||||
conffile:remove(key)
|
||||
end
|
||||
end
|
||||
|
||||
if not conffile:write() then
|
||||
core.log("error", "Failed to write clientmod config file")
|
||||
end
|
||||
end
|
||||
|
||||
if tabdata.selected_pkg == nil then
|
||||
@ -94,9 +131,21 @@ local function get_formspec(tabview, name, tabdata)
|
||||
|
||||
if selected_pkg.type == "mod" then
|
||||
if selected_pkg.is_modpack then
|
||||
retval = retval ..
|
||||
"button[8.65,4.65;3.25,1;btn_mod_mgr_rename_modpack;" ..
|
||||
fgettext("Rename") .. "]"
|
||||
if selected_pkg.is_clientside then
|
||||
if pkgmgr.is_modpack_entirely_enabled({list = packages}, selected_pkg.name) then
|
||||
retval = retval ..
|
||||
"button[8.65,4.65;3.25,1;btn_mod_mgr_mp_disable;" ..
|
||||
fgettext("Disable modpack") .. "]"
|
||||
else
|
||||
retval = retval ..
|
||||
"button[8.65,4.65;3.25,1;btn_mod_mgr_mp_enable;" ..
|
||||
fgettext("Enable modpack") .. "]"
|
||||
end
|
||||
else
|
||||
retval = retval ..
|
||||
"button[8.65,4.65;3.25,1;btn_mod_mgr_rename_modpack;" ..
|
||||
fgettext("Rename") .. "]"
|
||||
end
|
||||
else
|
||||
--show dependencies
|
||||
desc = desc .. "\n\n"
|
||||
@ -117,6 +166,17 @@ local function get_formspec(tabview, name, tabdata)
|
||||
"\n" .. toadd_soft
|
||||
end
|
||||
end
|
||||
if selected_pkg.is_clientside then
|
||||
if selected_pkg.enabled then
|
||||
retval = retval ..
|
||||
"button[8.65,4.65;3.25,1;btn_mod_mgr_disable_mod;" ..
|
||||
fgettext("Disable") .. "]"
|
||||
else
|
||||
retval = retval ..
|
||||
"button[8.65,4.65;3.25,1;btn_mod_mgr_enable_mod;" ..
|
||||
fgettext("Enable") .. "]"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
@ -150,6 +210,26 @@ local function handle_buttons(tabview, fields, tabname, tabdata)
|
||||
if fields["pkglist"] ~= nil then
|
||||
local event = core.explode_table_event(fields["pkglist"])
|
||||
tabdata.selected_pkg = event.row
|
||||
local mod = packages:get_list()[tabdata.selected_pkg]
|
||||
|
||||
if event.type == "DCL" and mod.is_clientside then
|
||||
pkgmgr.enable_mod({data = {list = packages, selected_mod = tabdata.selected_pkg}})
|
||||
packages = nil
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
if fields.btn_mod_mgr_mp_enable ~= nil or
|
||||
fields.btn_mod_mgr_mp_disable ~= nil then
|
||||
pkgmgr.enable_mod({data = {list = packages, selected_mod = tabdata.selected_pkg}}, fields.btn_mod_mgr_mp_enable ~= nil)
|
||||
packages = nil
|
||||
return true
|
||||
end
|
||||
|
||||
if fields.btn_mod_mgr_enable_mod ~= nil or
|
||||
fields.btn_mod_mgr_disable_mod ~= nil then
|
||||
pkgmgr.enable_mod({data = {list = packages, selected_mod = tabdata.selected_pkg}}, fields.btn_mod_mgr_enable_mod ~= nil)
|
||||
packages = nil
|
||||
return true
|
||||
end
|
||||
|
||||
|
@ -17,8 +17,13 @@
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
local dragonfire_team = {
|
||||
"Elias Fleckenstein <eliasfleckenstein@web.de> [Main Developer]",
|
||||
"DerZombiiie [Bots, User Support]",
|
||||
"Elias Fleckenstein [Main Developer]",
|
||||
"cora [Core Developer]",
|
||||
"emilia [Core Developer]",
|
||||
"oneplustwo [Developer]",
|
||||
"joshia_wi [Developer]",
|
||||
"Code-Sploit [Developer]",
|
||||
"DerZombiiie [User Support]",
|
||||
}
|
||||
|
||||
local core_developers = {
|
||||
|
@ -114,45 +114,44 @@ local function get_formspec(tabview, name, tabdata)
|
||||
)
|
||||
|
||||
retval = retval ..
|
||||
"button[4,3.95;2.6,1;world_delete;".. fgettext("Delete") .. "]" ..
|
||||
"button[6.5,3.95;2.8,1;world_configure;".. fgettext("Configure") .. "]" ..
|
||||
"button[9.2,3.95;2.5,1;world_create;".. fgettext("New") .. "]" ..
|
||||
"label[4,-0.25;".. fgettext("Select World:") .. "]"..
|
||||
"checkbox[0.25,0.25;cb_creative_mode;".. fgettext("Creative Mode") .. ";" ..
|
||||
"button[3.9,3.8;2.8,1;world_delete;".. fgettext("Delete") .. "]" ..
|
||||
"button[6.55,3.8;2.8,1;world_configure;".. fgettext("Configure") .. "]" ..
|
||||
"button[9.2,3.8;2.8,1;world_create;".. fgettext("New") .. "]" ..
|
||||
"label[3.9,-0.05;".. fgettext("Select World:") .. "]"..
|
||||
"checkbox[0,-0.20;cb_creative_mode;".. fgettext("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")) .. "]"..
|
||||
"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")) .. "]" ..
|
||||
"textlist[4,0.25;7.5,3.7;sp_worlds;" ..
|
||||
"textlist[3.9,0.4;7.9,3.45;sp_worlds;" ..
|
||||
menu_render_worldlist() ..
|
||||
";" .. index .. "]"
|
||||
|
||||
if core.settings:get_bool("enable_server") then
|
||||
retval = retval ..
|
||||
"button[8.5,4.8;3.2,1;play;".. fgettext("Host Game") .. "]" ..
|
||||
"checkbox[0.25,1.6;cb_server_announce;" .. fgettext("Announce Server") .. ";" ..
|
||||
"button[7.9,4.75;4.1,1;play;".. fgettext("Host Game") .. "]" ..
|
||||
"checkbox[0,1.15;cb_server_announce;" .. fgettext("Announce Server") .. ";" ..
|
||||
dump(core.settings:get_bool("server_announce")) .. "]" ..
|
||||
"label[0.25,2.2;" .. fgettext("Name/Password") .. "]" ..
|
||||
"field[0.55,3.2;3.5,0.5;te_playername;;" ..
|
||||
"field[0.3,2.85;3.8,0.5;te_playername;" .. fgettext("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")
|
||||
if bind_addr ~= nil and bind_addr ~= "" then
|
||||
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")) .. "]" ..
|
||||
"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")) .. "]"
|
||||
else
|
||||
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")) .. "]"
|
||||
end
|
||||
else
|
||||
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
|
||||
|
||||
return retval
|
||||
|
@ -122,56 +122,6 @@ local function antialiasing_fname_to_name(fname)
|
||||
return 0
|
||||
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 tab_string =
|
||||
"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]"
|
||||
|
||||
local video_driver = core.settings:get("video_driver")
|
||||
local shaders_supported = video_driver == "opengl"
|
||||
local shaders_enabled = false
|
||||
if shaders_supported then
|
||||
shaders_enabled = core.settings:get_bool("enable_shaders")
|
||||
local shaders_enabled = core.settings:get_bool("enable_shaders")
|
||||
if video_driver == "opengl" then
|
||||
tab_string = tab_string ..
|
||||
"checkbox[8.25,0;cb_shaders;" .. fgettext("Shaders") .. ";"
|
||||
.. 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
|
||||
core.settings:set_bool("enable_shaders", false)
|
||||
shaders_enabled = false
|
||||
tab_string = tab_string ..
|
||||
"label[8.38,0.2;" .. core.colorize("#888888",
|
||||
fgettext("Shaders (unavailable)")) .. "]"
|
||||
end
|
||||
|
||||
if core.settings:get("main_menu_style") == "simple" then
|
||||
-- 'Reset singleplayer world' only functions with simple menu
|
||||
tab_string = tab_string ..
|
||||
"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 ..
|
||||
"button[8,4.75;3.95,1;btn_change_keys;"
|
||||
.. fgettext("Change Keys") .. "]"
|
||||
|
||||
tab_string = tab_string ..
|
||||
"button[0,4.75;3.95,1;btn_advanced_settings;"
|
||||
@ -244,35 +190,23 @@ local function formspec(tabview, name, tabdata)
|
||||
|
||||
if shaders_enabled then
|
||||
tab_string = tab_string ..
|
||||
"checkbox[8.25,0.5;cb_bumpmapping;" .. fgettext("Bump Mapping") .. ";"
|
||||
.. dump(core.settings:get_bool("enable_bumpmapping")) .. "]" ..
|
||||
"checkbox[8.25,1;cb_tonemapping;" .. fgettext("Tone Mapping") .. ";"
|
||||
"checkbox[8.25,0.5;cb_tonemapping;" .. fgettext("Tone Mapping") .. ";"
|
||||
.. dump(core.settings:get_bool("tone_mapping")) .. "]" ..
|
||||
"checkbox[8.25,1.5;cb_generate_normalmaps;" .. fgettext("Generate Normal Maps") .. ";"
|
||||
.. dump(core.settings:get_bool("generate_normalmaps")) .. "]" ..
|
||||
"checkbox[8.25,2;cb_parallax;" .. fgettext("Parallax Occlusion") .. ";"
|
||||
.. dump(core.settings:get_bool("enable_parallax_occlusion")) .. "]" ..
|
||||
"checkbox[8.25,2.5;cb_waving_water;" .. fgettext("Waving Liquids") .. ";"
|
||||
"checkbox[8.25,1;cb_waving_water;" .. fgettext("Waving Liquids") .. ";"
|
||||
.. 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")) .. "]" ..
|
||||
"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")) .. "]"
|
||||
else
|
||||
tab_string = tab_string ..
|
||||
"label[8.38,0.7;" .. core.colorize("#888888",
|
||||
fgettext("Bump Mapping")) .. "]" ..
|
||||
"label[8.38,1.2;" .. core.colorize("#888888",
|
||||
fgettext("Tone Mapping")) .. "]" ..
|
||||
"label[8.38,1.7;" .. 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",
|
||||
"label[8.38,1.2;" .. core.colorize("#888888",
|
||||
fgettext("Waving Liquids")) .. "]" ..
|
||||
"label[8.38,3.2;" .. core.colorize("#888888",
|
||||
"label[8.38,1.7;" .. core.colorize("#888888",
|
||||
fgettext("Waving Leaves")) .. "]" ..
|
||||
"label[8.38,3.7;" .. core.colorize("#888888",
|
||||
"label[8.38,2.2;" .. core.colorize("#888888",
|
||||
fgettext("Waving Plants")) .. "]"
|
||||
end
|
||||
|
||||
@ -324,22 +258,10 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
|
||||
end
|
||||
return true
|
||||
end
|
||||
if fields["cb_bumpmapping"] then
|
||||
core.settings:set("enable_bumpmapping", fields["cb_bumpmapping"])
|
||||
return true
|
||||
end
|
||||
if fields["cb_tonemapping"] then
|
||||
core.settings:set("tone_mapping", fields["cb_tonemapping"])
|
||||
return true
|
||||
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
|
||||
core.settings:set("enable_waving_water", fields["cb_waving_water"])
|
||||
return true
|
||||
@ -359,10 +281,6 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
|
||||
core.settings:set("touchtarget", fields["cb_touchscreen_target"])
|
||||
return true
|
||||
end
|
||||
if fields["btn_reset_singleplayer"] then
|
||||
showconfirm_reset(this)
|
||||
return true
|
||||
end
|
||||
|
||||
--Note dropdowns have to be handled LAST!
|
||||
local ddhandled = false
|
||||
|
@ -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
|
||||
}
|
@ -110,9 +110,9 @@ doubletap_jump (Double tap jump for fly) bool false
|
||||
# enabled.
|
||||
always_fly_fast (Always fly and fast) bool true
|
||||
|
||||
# The time in seconds it takes between repeated right clicks when holding the right
|
||||
# mouse button.
|
||||
repeat_rightclick_time (Rightclick repetition interval) float 0.25 0.001
|
||||
# The time in seconds it takes between repeated node placements when holding
|
||||
# the place button.
|
||||
repeat_place_time (Place repetition interval) float 0.25 0.001
|
||||
|
||||
# Automatically jump up single-node obstacles.
|
||||
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
|
||||
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.
|
||||
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
|
||||
keymap_inventory (Inventory key) key KEY_KEY_I
|
||||
@ -517,8 +525,13 @@ texture_clean_transparent (Clean transparent textures) bool false
|
||||
# texture autoscaling.
|
||||
texture_min_size (Minimum texture size) int 64
|
||||
|
||||
# Experimental option, might cause visible spaces between blocks
|
||||
# when set to higher number than 0.
|
||||
# Use multi-sample antialiasing (MSAA) to smooth out block edges.
|
||||
# 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
|
||||
|
||||
# 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.
|
||||
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]
|
||||
|
||||
# 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.
|
||||
fps_max (Maximum FPS) int 60 1
|
||||
|
||||
# Maximum FPS when game is paused.
|
||||
pause_fps_max (FPS in pause menu) int 20 1
|
||||
# Maximum FPS when the window is not focused, or when the game is paused.
|
||||
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.
|
||||
pause_on_lost_focus (Pause on lost window focus) bool false
|
||||
|
||||
# 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
|
||||
# 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.
|
||||
# A restart is required after changing this.
|
||||
# Note: On Android, stick with OGLES1 if unsure! App may fail to start otherwise.
|
||||
# On other platforms, OpenGL is recommended, and it’s the only driver with
|
||||
# shader support currently.
|
||||
# On other platforms, OpenGL is recommended.
|
||||
# Shaders are supported by OpenGL (desktop only) and OGLES2 (experimental)
|
||||
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.
|
||||
@ -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
|
||||
# increase the cache hit %, reducing the data being copied from the main
|
||||
# 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.
|
||||
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.
|
||||
# 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).
|
||||
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.
|
||||
# The maximum total count is calculated dynamically:
|
||||
# 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.
|
||||
# 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
|
||||
# to maintain active objects up to this distance in the direction the
|
||||
# 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
|
||||
# active block stuff, stated in mapblocks (16 nodes).
|
||||
# In active blocks objects are loaded and ABMs run.
|
||||
# This is also the minimum range in which active objects (mobs) are maintained.
|
||||
# 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).
|
||||
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.
|
||||
max_forceloaded_blocks (Maximum forceloaded blocks) int 16
|
||||
@ -1259,10 +1235,10 @@ movement_gravity (Gravity) float 9.81
|
||||
[**Advanced]
|
||||
|
||||
# Handling for deprecated Lua API calls:
|
||||
# - legacy: (try to) mimic old behaviour (default for release).
|
||||
# - log: mimic and log backtrace of deprecated call (default for debug).
|
||||
# - none: Do not log deprecated calls
|
||||
# - log: mimic and log backtrace of deprecated call (default).
|
||||
# - 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.
|
||||
# This is a trade-off between sqlite transaction overhead and
|
||||
@ -1289,6 +1265,10 @@ active_block_mgmt_interval (Active block management interval) float 2.0
|
||||
# Length of time between Active Block Modifier (ABM) execution cycles
|
||||
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
|
||||
nodetimer_interval (NodeTimer interval) float 0.2
|
||||
|
||||
@ -1449,12 +1429,6 @@ curl_file_download_timeout (cURL file download timeout) int 300000
|
||||
# Makes DirectX work with LuaJIT. Disable if it causes troubles.
|
||||
high_precision_fpu (High-precision FPU) bool true
|
||||
|
||||
# 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.
|
||||
main_menu_script (Main menu script) string
|
||||
|
||||
@ -1474,7 +1448,7 @@ mg_name (Mapgen name) enum v7 v7,valleys,carpathian,v5,flat,fractal,singlenode,v
|
||||
water_level (Water level) int 1
|
||||
|
||||
# From how far blocks are generated for clients, stated in mapblocks (16 nodes).
|
||||
max_block_generate_distance (Max block generate distance) int 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).
|
||||
# Only mapchunks completely within the mapgen limit are generated.
|
||||
@ -1484,7 +1458,7 @@ mapgen_limit (Map generation limit) int 31000 0 31000
|
||||
# Global map generation attributes.
|
||||
# In Mapgen v6 the 'decorations' flag controls all decorations except trees
|
||||
# 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]
|
||||
|
||||
@ -1875,7 +1849,7 @@ mgcarpathian_np_dungeons (Dungeon noise) noise_params_3d 0.9, 0.5, (500, 500, 50
|
||||
|
||||
# Map generation attributes specific to Mapgen Flat.
|
||||
# Occasional lakes and hills can be added to the flat world.
|
||||
mgflat_spflags (Mapgen Flat specific flags) flags nolakes,nohills lakes,hills,nolakes,nohills
|
||||
mgflat_spflags (Mapgen Flat specific flags) flags nolakes,nohills,nocaverns lakes,hills,caverns,nolakes,nohills,nocaverns
|
||||
|
||||
# Y of flat ground.
|
||||
mgflat_ground_level (Ground level) int 8
|
||||
@ -1919,6 +1893,15 @@ mgflat_hill_threshold (Hill threshold) float 0.45
|
||||
# Controls steepness/height of hills.
|
||||
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.
|
||||
mgflat_dungeon_ymin (Dungeon minimum Y) int -31000
|
||||
|
||||
@ -1939,6 +1922,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.
|
||||
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.
|
||||
mgflat_np_dungeons (Dungeon noise) noise_params_3d 0.9, 0.5, (500, 500, 500), 0, 2, 0.8, 2.0
|
||||
|
||||
@ -2181,15 +2167,15 @@ chunksize (Chunk size) int 5
|
||||
enable_mapgen_debug_info (Mapgen debug) bool false
|
||||
|
||||
# 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.
|
||||
# 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.
|
||||
# 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.
|
||||
# Value 0:
|
||||
@ -2216,17 +2202,42 @@ contentdb_url (ContentDB URL) string https://content.minetest.net
|
||||
# so see a full list at https://content.minetest.net/help/content_flags/
|
||||
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]
|
||||
|
||||
# Font to use for cheat menu
|
||||
cheat_menu_font (MenuFont) enum FM_Mono FM_Standard,FM_Mono,FM_Fallback,FM_Simple,FM_SimpleMono,FM_MaxMode,FM_Unspecified
|
||||
|
||||
# (RGB value)
|
||||
cheat_menu_bg_color (Cell background color) v3f 255, 145, 88
|
||||
|
||||
cheat_menu_bg_color_alpha (Cell background color alpha) int 192
|
||||
|
||||
# (RGB value)
|
||||
cheat_menu_active_bg_color (Active cell background color) v3f 255, 87, 53
|
||||
|
||||
cheat_menu_active_bg_color_alpha (Active cell background color alpha) int 192
|
||||
|
||||
# (RGB value)
|
||||
cheat_menu_font_color (Font color) v3f 0, 0, 0
|
||||
|
||||
cheat_menu_font_color_alpha (Font color alpha) int 255
|
||||
|
||||
# (RGB value)
|
||||
cheat_menu_selected_font_color (Selected font color) v3f 255, 252, 88
|
||||
|
||||
cheat_menu_selected_font_color_alpha (Selected font color alpha) int 255
|
||||
|
||||
[Cheats]
|
||||
|
||||
fullbright (Fullbright) bool false
|
||||
|
||||
# Enable xray, requires fullbright
|
||||
xray (X-Ray) bool false
|
||||
xray (XRay) bool false
|
||||
|
||||
# Node to apply xray
|
||||
xray_node (X-RayTexture) string default:stone
|
||||
xray_nodes (XRay Nodes) string default:stone,mcl_core:stone
|
||||
|
||||
# Make the Client think it has all privs
|
||||
priv_bypass (PrivBypass) bool true
|
||||
|
||||
fastdig (FastDig) bool false
|
||||
@ -2249,7 +2260,6 @@ increase_tool_range (IncreasedRange) bool true
|
||||
|
||||
increase_tool_range_plus (IncreasedRangePlus) bool true
|
||||
|
||||
# HUD Flags Bypass
|
||||
hud_flags_bypass (HUDBypass) bool true
|
||||
|
||||
antiknockback (AntiKnockback) bool false
|
||||
@ -2272,10 +2282,92 @@ spamclick (FastHit) bool false
|
||||
|
||||
no_force_rotate (NoForceRotate) bool false
|
||||
|
||||
enable_tracers (Tracers) bool false
|
||||
|
||||
enable_esp (ESP) bool false
|
||||
|
||||
no_slow (NoSlow) bool false
|
||||
|
||||
trace_players_only (Only trace to players) bool true
|
||||
ignore_status_messages (IgnoreStatus) bool true
|
||||
|
||||
mark_deathmessages (Deathmessages) bool true
|
||||
|
||||
autosneak (AutoSneak) bool false
|
||||
|
||||
autoeject (AutoEject) bool false
|
||||
|
||||
eject_items (AutoEject Items) string
|
||||
|
||||
autotool (AutoTool) bool false
|
||||
|
||||
autorespawn (AutoRespawn) bool false
|
||||
|
||||
scaffold (Scaffold) bool false
|
||||
|
||||
scaffold_plus (ScaffoldPlus) bool false
|
||||
|
||||
block_water (BlockWater) bool false
|
||||
|
||||
autotnt (PlaceOnTop) bool false
|
||||
|
||||
replace (Replace) bool false
|
||||
|
||||
crystal_pvp (CrystalPvP) bool false
|
||||
|
||||
autototem (AutoTotem) bool false
|
||||
|
||||
dont_point_nodes (ThroughWalls) bool false
|
||||
|
||||
strip (Strip) bool false
|
||||
|
||||
autorefill (AutoRefill) bool false
|
||||
|
||||
nuke (Nuke) bool false
|
||||
|
||||
chat_color (Chat Color) string rainbow
|
||||
|
||||
use_chat_color (ColoredChat) bool false
|
||||
|
||||
chat_reverse (ReversedChat) bool false
|
||||
|
||||
forcefield (Forcefield) bool false
|
||||
|
||||
friendlist (Killaura / Forcefield Friendlist) string
|
||||
|
||||
cheat_hud (CheatHUD) bool true
|
||||
|
||||
node_esp_nodes (NodeESP Nodes) string
|
||||
|
||||
autosprint (AutoSprint) bool false
|
||||
|
||||
override_speed (SpeedOverride) bool false
|
||||
|
||||
override_jump (JumpOverride) bool false
|
||||
|
||||
override_gravity (GravityOverride) bool false
|
||||
|
||||
override_speed_factor (SpeedOverride Factor) float 1.2
|
||||
|
||||
override_jump_factor (JumpOverride Factor) float 2.0
|
||||
|
||||
override_gravity_factor (GravityOverride) float 0.8
|
||||
|
||||
jetpack (JetPack) bool false
|
||||
|
||||
autohit (AutoHit) bool false
|
||||
|
||||
antislip (AntiSlip) bool false
|
||||
|
||||
enable_entity_tracers (EntityTracers) bool false
|
||||
|
||||
enable_entity_esp (EntityESP) bool false
|
||||
|
||||
enable_player_tracers (PlayerTracers) bool false
|
||||
|
||||
enable_player_esp (PlayerESP) bool false
|
||||
|
||||
enable_node_esp (NodeESP) bool false
|
||||
|
||||
enable_node_tracers (NodeTracers) bool false
|
||||
|
||||
entity_esp_color (EntityESP Color) v3f 255, 255, 255
|
||||
|
||||
player_esp_color (PlayerESP Color) v3f 0, 255, 0
|
||||
|
||||
noweather (NoWeather) bool false
|
||||
|
@ -6,9 +6,11 @@ uniform sampler2D textureFlags;
|
||||
#define rightImage normalTexture
|
||||
#define maskImage textureFlags
|
||||
|
||||
varying mediump vec2 varTexCoord;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec2 uv = gl_TexCoord[0].st;
|
||||
vec2 uv = varTexCoord.st;
|
||||
vec4 left = texture2D(leftImage, uv).rgba;
|
||||
vec4 right = texture2D(rightImage, uv).rgba;
|
||||
vec4 mask = texture2D(maskImage, uv).rgba;
|
||||
|
@ -1,6 +1,7 @@
|
||||
varying mediump vec2 varTexCoord;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
gl_Position = gl_Vertex;
|
||||
gl_FrontColor = gl_BackColor = gl_Color;
|
||||
varTexCoord = inTexCoord0;
|
||||
gl_Position = inVertexPosition;
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
varying lowp vec4 varColor;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
gl_FragColor = gl_Color;
|
||||
gl_FragColor = varColor;
|
||||
}
|
||||
|
@ -1,9 +1,7 @@
|
||||
uniform mat4 mWorldViewProj;
|
||||
varying lowp vec4 varColor;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
gl_Position = mWorldViewProj * gl_Vertex;
|
||||
|
||||
gl_FrontColor = gl_BackColor = gl_Color;
|
||||
gl_Position = mWorldViewProj * inVertexPosition;
|
||||
varColor = inVertexColor;
|
||||
}
|
||||
|
@ -2,9 +2,12 @@ uniform sampler2D baseTexture;
|
||||
uniform sampler2D normalTexture;
|
||||
uniform vec3 yawVec;
|
||||
|
||||
varying lowp vec4 varColor;
|
||||
varying mediump vec2 varTexCoord;
|
||||
|
||||
void main (void)
|
||||
{
|
||||
vec2 uv = gl_TexCoord[0].st;
|
||||
vec2 uv = varTexCoord.st;
|
||||
|
||||
//texture sampling rate
|
||||
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;
|
||||
vec4 col = vec4(color.rgb, base.a);
|
||||
col *= gl_Color;
|
||||
col *= varColor;
|
||||
gl_FragColor = vec4(col.rgb, base.a);
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
uniform mat4 mWorldViewProj;
|
||||
uniform mat4 mWorld;
|
||||
|
||||
varying lowp vec4 varColor;
|
||||
varying mediump vec2 varTexCoord;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
gl_Position = mWorldViewProj * gl_Vertex;
|
||||
gl_FrontColor = gl_BackColor = gl_Color;
|
||||
varTexCoord = inTexCoord0.st;
|
||||
gl_Position = mWorldViewProj * inVertexPosition;
|
||||
varColor = inVertexColor;
|
||||
}
|
||||
|
@ -1,6 +1,4 @@
|
||||
uniform sampler2D baseTexture;
|
||||
uniform sampler2D normalTexture;
|
||||
uniform sampler2D textureFlags;
|
||||
|
||||
uniform vec4 skyBgColor;
|
||||
uniform float fogDistance;
|
||||
@ -17,19 +15,12 @@ varying vec3 vPosition;
|
||||
// cameraOffset + worldPosition (for large coordinates the limits of float
|
||||
// precision must be considered).
|
||||
varying vec3 worldPosition;
|
||||
varying float area_enable_parallax;
|
||||
|
||||
varying lowp vec4 varColor;
|
||||
varying mediump vec2 varTexCoord;
|
||||
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 fogShadingParameter = 1 / ( 1 - fogStart);
|
||||
const float fogShadingParameter = 1.0 / ( 1.0 - fogStart);
|
||||
|
||||
#ifdef ENABLE_TONE_MAPPING
|
||||
|
||||
@ -63,148 +54,24 @@ vec4 applyToneMapping(vec4 color)
|
||||
}
|
||||
#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)
|
||||
{
|
||||
vec3 color;
|
||||
vec4 bump;
|
||||
vec2 uv = gl_TexCoord[0].st;
|
||||
bool use_normalmap = false;
|
||||
get_texture_flags();
|
||||
vec2 uv = varTexCoord.st;
|
||||
|
||||
#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;
|
||||
|
||||
#ifdef ENABLE_BUMPMAPPING
|
||||
if (use_normalmap) {
|
||||
vec3 L = normalize(lightVec);
|
||||
vec3 E = normalize(eyeVec);
|
||||
float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0), 1.0);
|
||||
float diffuse = dot(-E,bump.xyz);
|
||||
color = (diffuse + 0.1 * specular) * base.rgb;
|
||||
} else {
|
||||
color = base.rgb;
|
||||
#ifdef USE_DISCARD
|
||||
// If alpha is zero, we can just discard the pixel. This fixes transparency
|
||||
// on GPUs like GC7000L, where GL_ALPHA_TEST is not implemented in mesa,
|
||||
// and also on GLES 2, where GL_ALPHA_TEST is missing entirely.
|
||||
if (base.a == 0.0) {
|
||||
discard;
|
||||
}
|
||||
#else
|
||||
color = base.rgb;
|
||||
#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
|
||||
col = applyToneMapping(col);
|
||||
|
@ -1,4 +1,3 @@
|
||||
uniform mat4 mWorldViewProj;
|
||||
uniform mat4 mWorld;
|
||||
|
||||
// Color of the light emitted by the sun.
|
||||
@ -16,12 +15,9 @@ varying vec3 vPosition;
|
||||
// cameraOffset + worldPosition (for large coordinates the limits of float
|
||||
// precision must be considered).
|
||||
varying vec3 worldPosition;
|
||||
|
||||
varying lowp vec4 varColor;
|
||||
varying mediump vec2 varTexCoord;
|
||||
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.
|
||||
const vec3 artificialLight = vec3(1.04, 1.04, 1.04);
|
||||
@ -85,25 +81,13 @@ float snoise(vec3 p)
|
||||
|
||||
void main(void)
|
||||
{
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
//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;
|
||||
varTexCoord = inTexCoord0.st;
|
||||
|
||||
//Allow parallax/relief mapping only for certain kind of nodes
|
||||
//Variable is also used to control area of the effect
|
||||
#if (DRAW_TYPE == NDT_NORMAL || DRAW_TYPE == NDT_LIQUID || DRAW_TYPE == NDT_FLOWINGLIQUID)
|
||||
area_enable_parallax = 1.0;
|
||||
#else
|
||||
area_enable_parallax = 0.0;
|
||||
#endif
|
||||
|
||||
|
||||
float disp_x;
|
||||
float disp_z;
|
||||
float disp_x;
|
||||
float disp_z;
|
||||
// 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)
|
||||
vec4 pos2 = mWorld * gl_Vertex;
|
||||
vec4 pos2 = mWorld * inVertexPosition;
|
||||
float tOffset = (pos2.x + pos2.y) * 0.001 + pos2.z * 0.002;
|
||||
disp_x = (smoothTriangleWave(animationTimer * 23.0 + tOffset) +
|
||||
smoothTriangleWave(animationTimer * 11.0 + tOffset)) * 0.4;
|
||||
@ -112,68 +96,43 @@ float disp_z;
|
||||
smoothTriangleWave(animationTimer * 13.0 + tOffset)) * 0.5;
|
||||
#endif
|
||||
|
||||
worldPosition = (mWorld * gl_Vertex).xyz;
|
||||
worldPosition = (mWorld * inVertexPosition).xyz;
|
||||
|
||||
// OpenGL < 4.3 does not support continued preprocessor lines
|
||||
#if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_OPAQUE || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_BASIC) && ENABLE_WAVING_WATER
|
||||
// Generate waves with Perlin-type noise.
|
||||
// The constants are calibrated such that they roughly
|
||||
// correspond to the old sine waves.
|
||||
vec4 pos = gl_Vertex;
|
||||
vec4 pos = inVertexPosition;
|
||||
vec3 wavePos = worldPosition + cameraOffset;
|
||||
// The waves are slightly compressed along the z-axis to get
|
||||
// wave-fronts along the x-axis.
|
||||
wavePos.x /= WATER_WAVE_LENGTH * 3;
|
||||
wavePos.z /= WATER_WAVE_LENGTH * 2;
|
||||
wavePos.z += animationTimer * WATER_WAVE_SPEED * 10;
|
||||
pos.y += (snoise(wavePos) - 1) * WATER_WAVE_HEIGHT * 5;
|
||||
wavePos.x /= WATER_WAVE_LENGTH * 3.0;
|
||||
wavePos.z /= WATER_WAVE_LENGTH * 2.0;
|
||||
wavePos.z += animationTimer * WATER_WAVE_SPEED * 10.0;
|
||||
pos.y += (snoise(wavePos) - 1.0) * WATER_WAVE_HEIGHT * 5.0;
|
||||
gl_Position = mWorldViewProj * pos;
|
||||
#elif MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES && ENABLE_WAVING_LEAVES
|
||||
vec4 pos = gl_Vertex;
|
||||
vec4 pos = inVertexPosition;
|
||||
pos.x += disp_x;
|
||||
pos.y += disp_z * 0.1;
|
||||
pos.z += disp_z;
|
||||
gl_Position = mWorldViewProj * pos;
|
||||
#elif MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS && ENABLE_WAVING_PLANTS
|
||||
vec4 pos = gl_Vertex;
|
||||
if (gl_TexCoord[0].y < 0.05) {
|
||||
vec4 pos = inVertexPosition;
|
||||
if (varTexCoord.y < 0.05) {
|
||||
pos.x += disp_x;
|
||||
pos.z += disp_z;
|
||||
}
|
||||
gl_Position = mWorldViewProj * pos;
|
||||
#else
|
||||
gl_Position = mWorldViewProj * gl_Vertex;
|
||||
gl_Position = mWorldViewProj * inVertexPosition;
|
||||
#endif
|
||||
|
||||
|
||||
vPosition = gl_Position.xyz;
|
||||
|
||||
// Don't generate heightmaps when too far from the eye
|
||||
float dist = distance (vec3(0.0, 0.0, 0.0), vPosition);
|
||||
if (dist > 150.0) {
|
||||
area_enable_parallax = 0.0;
|
||||
}
|
||||
|
||||
vec3 sunPosition = vec3 (0.0, eyePosition.y * BS + 900.0, 0.0);
|
||||
|
||||
vec3 normal, tangent, binormal;
|
||||
normal = normalize(gl_NormalMatrix * gl_Normal);
|
||||
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);
|
||||
eyeVec = -(mWorldView * inVertexPosition).xyz;
|
||||
|
||||
// Calculate color.
|
||||
// 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.
|
||||
vec4 color;
|
||||
// The alpha gives the ratio of sunlight in the incoming light.
|
||||
float nightRatio = 1 - gl_Color.a;
|
||||
color.rgb = gl_Color.rgb * (gl_Color.a * dayLight.rgb +
|
||||
nightRatio * artificialLight.rgb) * 2;
|
||||
color.a = 1;
|
||||
float nightRatio = 1.0 - inVertexColor.a;
|
||||
color.rgb = inVertexColor.rgb * (inVertexColor.a * dayLight.rgb +
|
||||
nightRatio * artificialLight.rgb) * 2.0;
|
||||
color.a = 1.0;
|
||||
|
||||
// Emphase blue a bit in darker places
|
||||
// See C++ implementation in mapblock_mesh.cpp final_color_blend()
|
||||
float brightness = (color.r + color.g + color.b) / 3;
|
||||
float brightness = (color.r + color.g + color.b) / 3.0;
|
||||
color.b += max(0.0, 0.021 - abs(0.2 * brightness - 0.021) +
|
||||
0.07 * brightness);
|
||||
|
||||
gl_FrontColor = gl_BackColor = clamp(color, 0.0, 1.0);
|
||||
varColor = clamp(color, 0.0, 1.0);
|
||||
}
|
||||
|
@ -1,6 +1,4 @@
|
||||
uniform sampler2D baseTexture;
|
||||
uniform sampler2D normalTexture;
|
||||
uniform sampler2D textureFlags;
|
||||
|
||||
uniform vec4 emissiveColor;
|
||||
uniform vec4 skyBgColor;
|
||||
@ -10,20 +8,16 @@ uniform vec3 eyePosition;
|
||||
varying vec3 vNormal;
|
||||
varying vec3 vPosition;
|
||||
varying vec3 worldPosition;
|
||||
varying lowp vec4 varColor;
|
||||
varying mediump vec2 varTexCoord;
|
||||
|
||||
varying vec3 eyeVec;
|
||||
varying vec3 lightVec;
|
||||
varying float vIDiff;
|
||||
|
||||
bool normalTexturePresent = false;
|
||||
bool texTileableHorizontal = false;
|
||||
bool texTileableVertical = false;
|
||||
bool texSeamless = false;
|
||||
|
||||
const float e = 2.718281828459;
|
||||
const float BS = 10.0;
|
||||
const float fogStart = FOG_START;
|
||||
const float fogShadingParameter = 1 / ( 1 - fogStart);
|
||||
const float fogShadingParameter = 1.0 / (1.0 - fogStart);
|
||||
|
||||
#ifdef ENABLE_TONE_MAPPING
|
||||
|
||||
@ -57,95 +51,27 @@ vec4 applyToneMapping(vec4 color)
|
||||
}
|
||||
#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)
|
||||
{
|
||||
vec3 color;
|
||||
vec4 bump;
|
||||
vec2 uv = gl_TexCoord[0].st;
|
||||
bool use_normalmap = false;
|
||||
get_texture_flags();
|
||||
|
||||
#if USE_NORMALMAPS == 1
|
||||
if (normalTexturePresent) {
|
||||
bump = get_normal_map(uv);
|
||||
use_normalmap = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if GENERATE_NORMALMAPS == 1
|
||||
if (normalTexturePresent == false) {
|
||||
float tl = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y + SAMPLE_STEP));
|
||||
float t = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y - SAMPLE_STEP));
|
||||
float tr = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y + SAMPLE_STEP));
|
||||
float r = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y));
|
||||
float br = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y - SAMPLE_STEP));
|
||||
float b = get_rgb_height(vec2(uv.x, uv.y - SAMPLE_STEP));
|
||||
float bl = get_rgb_height(vec2(uv.x -SAMPLE_STEP, uv.y - SAMPLE_STEP));
|
||||
float l = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y));
|
||||
float dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl);
|
||||
float dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr);
|
||||
bump = vec4(normalize(vec3 (dX, dY, NORMALMAPS_STRENGTH)), 1.0);
|
||||
use_normalmap = true;
|
||||
}
|
||||
#endif
|
||||
vec2 uv = varTexCoord.st;
|
||||
|
||||
vec4 base = texture2D(baseTexture, uv).rgba;
|
||||
|
||||
#ifdef ENABLE_BUMPMAPPING
|
||||
if (use_normalmap) {
|
||||
vec3 L = normalize(lightVec);
|
||||
vec3 E = normalize(eyeVec);
|
||||
float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0), 1.0);
|
||||
float diffuse = dot(-E,bump.xyz);
|
||||
color = (diffuse + 0.1 * specular) * base.rgb;
|
||||
} else {
|
||||
color = base.rgb;
|
||||
#ifdef USE_DISCARD
|
||||
// If alpha is zero, we can just discard the pixel. This fixes transparency
|
||||
// on GPUs like GC7000L, where GL_ALPHA_TEST is not implemented in mesa,
|
||||
// and also on GLES 2, where GL_ALPHA_TEST is missing entirely.
|
||||
if (base.a == 0.0) {
|
||||
discard;
|
||||
}
|
||||
#else
|
||||
color = base.rgb;
|
||||
#endif
|
||||
|
||||
color = base.rgb;
|
||||
|
||||
vec4 col = vec4(color.rgb, base.a);
|
||||
|
||||
col.rgb *= gl_Color.rgb;
|
||||
col.rgb *= varColor.rgb;
|
||||
|
||||
col.rgb *= emissiveColor.rgb * vIDiff;
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
uniform mat4 mWorldViewProj;
|
||||
uniform mat4 mWorld;
|
||||
|
||||
uniform vec3 eyePosition;
|
||||
@ -7,9 +6,10 @@ uniform float animationTimer;
|
||||
varying vec3 vNormal;
|
||||
varying vec3 vPosition;
|
||||
varying vec3 worldPosition;
|
||||
varying lowp vec4 varColor;
|
||||
varying mediump vec2 varTexCoord;
|
||||
|
||||
varying vec3 eyeVec;
|
||||
varying vec3 lightVec;
|
||||
varying float vIDiff;
|
||||
|
||||
const float e = 2.718281828459;
|
||||
@ -19,35 +19,31 @@ float directional_ambient(vec3 normal)
|
||||
{
|
||||
vec3 v = normal * normal;
|
||||
|
||||
if (normal.y < 0)
|
||||
return dot(v, vec3(0.670820f, 0.447213f, 0.836660f));
|
||||
if (normal.y < 0.0)
|
||||
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)
|
||||
{
|
||||
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
|
||||
gl_Position = mWorldViewProj * gl_Vertex;
|
||||
varTexCoord = (mTexture * inTexCoord0).st;
|
||||
gl_Position = mWorldViewProj * inVertexPosition;
|
||||
|
||||
vPosition = gl_Position.xyz;
|
||||
vNormal = gl_Normal;
|
||||
worldPosition = (mWorld * gl_Vertex).xyz;
|
||||
|
||||
vec3 sunPosition = vec3 (0.0, eyePosition.y * BS + 900.0, 0.0);
|
||||
|
||||
lightVec = sunPosition - worldPosition;
|
||||
eyeVec = -(gl_ModelViewMatrix * gl_Vertex).xyz;
|
||||
vNormal = inVertexNormal;
|
||||
worldPosition = (mWorld * inVertexPosition).xyz;
|
||||
eyeVec = -(mWorldView * inVertexPosition).xyz;
|
||||
|
||||
#if (MATERIAL_TYPE == TILE_MATERIAL_PLAIN) || (MATERIAL_TYPE == TILE_MATERIAL_PLAIN_ALPHA)
|
||||
vIDiff = 1.0;
|
||||
#else
|
||||
// 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
|
||||
vIDiff = length(gl_Normal) == 0.0
|
||||
vIDiff = length(inVertexNormal) == 0.0
|
||||
? 1.0
|
||||
: directional_ambient(normalize(gl_Normal));
|
||||
: directional_ambient(normalize(inVertexNormal));
|
||||
#endif
|
||||
|
||||
gl_FrontColor = gl_BackColor = gl_Color;
|
||||
varColor = inVertexColor;
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
uniform sampler2D baseTexture;
|
||||
|
||||
varying lowp vec4 varColor;
|
||||
varying mediump vec2 varTexCoord;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec2 uv = gl_TexCoord[0].st;
|
||||
vec2 uv = varTexCoord.st;
|
||||
vec4 color = texture2D(baseTexture, uv);
|
||||
color.rgb *= gl_Color.rgb;
|
||||
color.rgb *= varColor.rgb;
|
||||
gl_FragColor = color;
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
uniform mat4 mWorldViewProj;
|
||||
varying lowp vec4 varColor;
|
||||
varying mediump vec2 varTexCoord;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
gl_Position = mWorldViewProj * gl_Vertex;
|
||||
varTexCoord = inTexCoord0.st;
|
||||
gl_Position = mWorldViewProj * inVertexPosition;
|
||||
|
||||
gl_FrontColor = gl_BackColor = gl_Color;
|
||||
varColor = inVertexColor;
|
||||
}
|
||||
|
6
client/shaders/stars_shader/opengl_fragment.glsl
Normal file
6
client/shaders/stars_shader/opengl_fragment.glsl
Normal file
@ -0,0 +1,6 @@
|
||||
uniform vec4 starColor;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
gl_FragColor = starColor;
|
||||
}
|
4
client/shaders/stars_shader/opengl_vertex.glsl
Normal file
4
client/shaders/stars_shader/opengl_vertex.glsl
Normal file
@ -0,0 +1,4 @@
|
||||
void main(void)
|
||||
{
|
||||
gl_Position = mWorldViewProj * inVertexPosition;
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
local was_enabled = false
|
||||
local pwas_enabled = false
|
||||
|
||||
minetest.register_globalstep(function()
|
||||
if minetest.settings:get_bool("autosneak") then
|
||||
minetest.set_keypress("sneak", true)
|
||||
was_enabled = true
|
||||
elseif was_enabled then
|
||||
was_enabled = false
|
||||
minetest.set_keypress("sneak", false)
|
||||
end
|
||||
if minetest.settings:get_bool("autosneak_conditional") then
|
||||
local blck=minetest.get_node_or_nil(vector.add(minetest.localplayer:get_pos(),{x=0,y=-1,z=0}))
|
||||
if blck ~= nil and blck.name~="air" then
|
||||
minetest.set_keypress("sneak", true)
|
||||
pwas_enabled = true
|
||||
end
|
||||
elseif pwas_enabled then
|
||||
pwas_enabled = false
|
||||
minetest.set_keypress("sneak", false)
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_cheat("AutoSneak", "Movement", "autosneak")
|
||||
minetest.register_cheat("GroundASneak", "Movement", "autosneak_conditional")
|
@ -1,33 +0,0 @@
|
||||
function chat.send(message)
|
||||
local starts_with = message:sub(1, 1)
|
||||
|
||||
if starts_with == "/" or starts_with == "." then return end
|
||||
|
||||
local reverse = minetest.settings:get_bool("chat_reverse")
|
||||
|
||||
if reverse then
|
||||
local msg = ""
|
||||
for i = 1, #message do
|
||||
msg = message:sub(i, i) .. msg
|
||||
end
|
||||
message = msg
|
||||
end
|
||||
|
||||
local color = minetest.settings:get("chat_color")
|
||||
|
||||
if color then
|
||||
local msg
|
||||
if color == "rainbow" then
|
||||
msg = chat.rainbow(message)
|
||||
else
|
||||
msg = minetest.colorize(color, message)
|
||||
end
|
||||
message = msg
|
||||
end
|
||||
|
||||
minetest.send_chat_message(message)
|
||||
return true
|
||||
end
|
||||
|
||||
minetest.register_on_sending_chat_message(chat.send)
|
||||
|
@ -1,13 +1,48 @@
|
||||
chat = {}
|
||||
minetest.register_on_receiving_chat_message(function(message)
|
||||
if message:sub(1, 1) == "#" and minetest.settings:get_bool("ignore_status_messages") ~= false then
|
||||
return true
|
||||
elseif message:find('\1b@mcl_death_messages\1b') and minetest.settings:get_bool("mark_deathmessages") ~= false then
|
||||
minetest.display_chat_message(minetest.colorize("#F25819", "[Deathmessage] ") .. message)
|
||||
return true
|
||||
end
|
||||
end)
|
||||
|
||||
local modname = minetest.get_current_modname()
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
function minetest.send_colorized(message)
|
||||
local starts_with = message:sub(1, 1)
|
||||
|
||||
if starts_with == "/" or starts_with == "." then return end
|
||||
|
||||
chat.rainbow = dofile(modpath .. "/rainbow.lua")
|
||||
local reverse = minetest.settings:get_bool("chat_reverse")
|
||||
|
||||
if reverse then
|
||||
local msg = ""
|
||||
for i = 1, #message do
|
||||
msg = message:sub(i, i) .. msg
|
||||
end
|
||||
message = msg
|
||||
end
|
||||
|
||||
local use_chat_color = minetest.settings:get_bool("use_chat_color")
|
||||
local color = minetest.settings:get("chat_color")
|
||||
|
||||
dofile(modpath .. "/colors.lua")
|
||||
dofile(modpath .. "/spam.lua")
|
||||
dofile(modpath .. "/status.lua")
|
||||
dofile(modpath .. "/leak.lua")
|
||||
if use_chat_color and color then
|
||||
local msg
|
||||
if color == "rainbow" then
|
||||
msg = minetest.rainbow(message)
|
||||
else
|
||||
msg = minetest.colorize(color, message)
|
||||
end
|
||||
message = msg
|
||||
end
|
||||
|
||||
minetest.send_chat_message(message)
|
||||
return true
|
||||
end
|
||||
|
||||
minetest.register_on_sending_chat_message(minetest.send_colorized)
|
||||
|
||||
|
||||
minetest.register_cheat("IgnoreStatus", "Chat", "ignore_status_messages")
|
||||
minetest.register_cheat("DeathMessages", "Chat", "mark_deathmessages")
|
||||
minetest.register_cheat("ColoredChat", "Chat", "use_chat_color")
|
||||
minetest.register_cheat("ReversedChat", "Chat", "chat_reverse")
|
||||
|
@ -1,20 +0,0 @@
|
||||
|
||||
--[[minetest.register_globalstep(function(dtime)
|
||||
if not minetest.settings:get_bool("leak") then return end
|
||||
etime = etime + dtime
|
||||
if etime < 5 then return end
|
||||
etime = 0
|
||||
local player = minetest.localplayer
|
||||
minetest.send_chat_message(minetest.pos_to_string(vector.floor(player:get_pos())))
|
||||
end)--]]
|
||||
function cleak()
|
||||
minetest.send_chat_message(minetest.pos_to_string(vector.floor(minetest.localplayer:get_pos())))
|
||||
end
|
||||
minetest.register_chatcommand("cleak", {
|
||||
params = "<pos>",
|
||||
description = "Open node inventory metadata at position.",
|
||||
func = cleak
|
||||
})
|
||||
|
||||
|
||||
--minetest.register_cheat("Leak", "Player", "leak")
|
@ -1,61 +0,0 @@
|
||||
local function rgb_to_hex(rgb)
|
||||
local hexadecimal = '#'
|
||||
|
||||
for key, value in pairs(rgb) do
|
||||
local hex = ''
|
||||
|
||||
while(value > 0)do
|
||||
local index = math.fmod(value, 16) + 1
|
||||
value = math.floor(value / 16)
|
||||
hex = string.sub('0123456789ABCDEF', index, index) .. hex
|
||||
end
|
||||
|
||||
if(string.len(hex) == 0)then
|
||||
hex = '00'
|
||||
|
||||
elseif(string.len(hex) == 1)then
|
||||
hex = '0' .. hex
|
||||
end
|
||||
|
||||
hexadecimal = hexadecimal .. hex
|
||||
end
|
||||
|
||||
return hexadecimal
|
||||
end
|
||||
|
||||
local function color_from_hue(hue)
|
||||
local h = hue / 60
|
||||
local c = 255
|
||||
local x = (1 - math.abs(h%2 - 1)) * 255
|
||||
|
||||
local i = math.floor(h);
|
||||
if (i == 0) then
|
||||
return rgb_to_hex({c, x, 0})
|
||||
elseif (i == 1) then
|
||||
return rgb_to_hex({x, c, 0})
|
||||
elseif (i == 2) then
|
||||
return rgb_to_hex({0, c, x})
|
||||
elseif (i == 3) then
|
||||
return rgb_to_hex({0, x, c});
|
||||
elseif (i == 4) then
|
||||
return rgb_to_hex({x, 0, c});
|
||||
else
|
||||
return rgb_to_hex({c, 0, x});
|
||||
end
|
||||
end
|
||||
|
||||
return function(input)
|
||||
local step = 360 / input:len()
|
||||
local hue = 0
|
||||
local output = ""
|
||||
for i = 1, input:len() do
|
||||
local char = input:sub(i,i)
|
||||
if char:match("%s") then
|
||||
output = output .. char
|
||||
else
|
||||
output = output .. minetest.get_color_escape_sequence(color_from_hue(hue)) .. char
|
||||
end
|
||||
hue = hue + step
|
||||
end
|
||||
return output
|
||||
end
|
@ -1,6 +1,3 @@
|
||||
chat_color (Chat Color) string white
|
||||
chat_reverse (Reverse Chat messages) bool false
|
||||
chat_enable_spam (Spam Chat) bool false
|
||||
chat_spam (Message to spam into Chat) string
|
||||
ignore_status_messages (Ignore status messages from server) bool true
|
||||
leak (Frequently leak your coordinates to chat) bool false
|
||||
ignore_status_messages (Ignore status messages from server) bool false
|
||||
|
@ -1,12 +0,0 @@
|
||||
local etime = 0
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
etime = etime + dtime
|
||||
if etime < 10/8 then return end
|
||||
etime = 0
|
||||
local spam = minetest.settings:get("chat_spam")
|
||||
local enable_spam = minetest.settings:get("chat_enable_spam")
|
||||
if enable_spam and spam then
|
||||
local _ = chat.send(spam) or minetest.send_chat_message(spam)
|
||||
end
|
||||
end)
|
@ -1,7 +0,0 @@
|
||||
minetest.register_on_receiving_chat_message(function(message)
|
||||
if message:sub(1, 1) == "#" and minetest.settings:get_bool("ignore_status_messages") ~= false then
|
||||
return true
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_cheat("IgnoreStatus", "Player", "ignore_status_messages")
|
83
clientmods/dragonfire/combat/init.lua
Normal file
83
clientmods/dragonfire/combat/init.lua
Normal file
@ -0,0 +1,83 @@
|
||||
local placed_crystal
|
||||
local switched_to_totem = 0
|
||||
local used_sneak = true
|
||||
local totem_move_action = InventoryAction("move")
|
||||
totem_move_action:to("current_player", "main", 9)
|
||||
|
||||
minetest.register_list_command("friend", "Configure Friend List (friends dont get attacked by Killaura or Forcefield)", "friendlist")
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
local player = minetest.localplayer
|
||||
if not player then return end
|
||||
local control = player:get_control()
|
||||
local pointed = minetest.get_pointed_thing()
|
||||
local item = player:get_wielded_item():get_name()
|
||||
if minetest.settings:get_bool("killaura") or minetest.settings:get_bool("forcefield") and control.dig then
|
||||
local friendlist = minetest.settings:get("friendlist"):split(",")
|
||||
for _, obj in ipairs(minetest.get_objects_inside_radius(player:get_pos(), 5)) do
|
||||
local do_attack = true
|
||||
if obj:is_local_player() then
|
||||
do_attack = false
|
||||
else
|
||||
for _, friend in ipairs(friendlist) do
|
||||
if obj:get_name() == friend or obj:get_nametag() == friend then
|
||||
do_attack = false
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if do_attack then
|
||||
obj:punch()
|
||||
end
|
||||
end
|
||||
elseif minetest.settings:get_bool("crystal_pvp") then
|
||||
if placed_crystal then
|
||||
if minetest.switch_to_item("mobs_mc:totem") then
|
||||
switched_to_totem = 5
|
||||
end
|
||||
placed_crystal = false
|
||||
elseif switched_to_totem > 0 then
|
||||
if item ~= "mobs_mc:totem" then
|
||||
switched_to_totem = 0
|
||||
elseif pointed and pointed.type == "object" then
|
||||
pointed.ref:punch()
|
||||
switched_to_totem = 0
|
||||
else
|
||||
switched_to_totem = switched_to_totem
|
||||
end
|
||||
elseif control.place and item == "mcl_end:crystal" then
|
||||
placed_crystal = true
|
||||
elseif control.sneak then
|
||||
if pointed and pointed.type == "node" and not used_sneak then
|
||||
local pos = minetest.get_pointed_thing_position(pointed)
|
||||
local node = minetest.get_node_or_nil(pos)
|
||||
if node and (node.name == "mcl_core:obsidian" or node.name == "mcl_core:bedrock") then
|
||||
minetest.switch_to_item("mcl_end:crystal")
|
||||
minetest.place_node(pos)
|
||||
placed_crystal = true
|
||||
end
|
||||
end
|
||||
used_sneak = true
|
||||
else
|
||||
used_sneak = false
|
||||
end
|
||||
end
|
||||
|
||||
if minetest.settings:get_bool("autototem") then
|
||||
local totem_stack = minetest.get_inventory("current_player").main[9]
|
||||
if totem_stack and totem_stack:get_name() ~= "mobs_mc:totem" then
|
||||
local totem_index = minetest.find_item("mobs_mc:totem")
|
||||
if totem_index then
|
||||
totem_move_action:from("current_player", "main", totem_index)
|
||||
totem_move_action:apply()
|
||||
player:set_wield_index(9)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
minetest.register_cheat("Killaura", "Combat", "killaura")
|
||||
minetest.register_cheat("Forcefield", "Combat", "forcefield")
|
||||
minetest.register_cheat("CrystalPvP", "Combat", "crystal_pvp")
|
||||
minetest.register_cheat("AutoTotem", "Combat", "autototem")
|
@ -1,19 +0,0 @@
|
||||
minetest.register_globalstep(function()
|
||||
if minetest.settings:get_bool("autoeject") then
|
||||
local player = minetest.localplayer
|
||||
local list = (minetest.settings:get("eject_items") or ""):split(",")
|
||||
local inventory = minetest.get_inventory("current_player")
|
||||
for index, stack in pairs(inventory.main) do
|
||||
if table.indexof(list, stack:get_name()) ~= -1 then
|
||||
local old_index = player:get_wield_index()
|
||||
player:set_wield_index(index - 1)
|
||||
minetest.drop_selected_item()
|
||||
player:set_wield_index(old_index)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_chatcommand("eject", list.new("Configure AutoEject", "eject_items"))
|
||||
minetest.register_cheat("AutoEject", "Player", "autoeject")
|
@ -1,49 +0,0 @@
|
||||
autotool = {}
|
||||
local odx = nil
|
||||
|
||||
function autotool.check_tool(stack, node_groups, old_best_time)
|
||||
local toolcaps = stack:get_tool_capabilities()
|
||||
if not toolcaps then return end
|
||||
local best_time = old_best_time
|
||||
for group, groupdef in pairs(toolcaps.groupcaps) do
|
||||
local level = node_groups[group]
|
||||
if level then
|
||||
local this_time = groupdef.times[level]
|
||||
if this_time < best_time then
|
||||
best_time = this_time
|
||||
end
|
||||
end
|
||||
end
|
||||
return best_time < old_best_time, best_time
|
||||
end
|
||||
|
||||
function autotool.autotool(pos)
|
||||
if not minetest.settings:get_bool("autotool") then return end
|
||||
local node = minetest.get_node_or_nil(pos)
|
||||
if not node then return end
|
||||
local player = minetest.localplayer
|
||||
local inventory = minetest.get_inventory("current_player")
|
||||
local node_groups = minetest.get_node_def(node.name).groups
|
||||
local new_index = player:get_wield_index()
|
||||
local is_better, best_time = false, math.huge
|
||||
is_better, best_time = autotool.check_tool(player:get_wielded_item(), node_groups, best_time)
|
||||
if inventory.hand then
|
||||
is_better, best_time = autotool.check_tool(inventory.hand[1], node_groups, best_time)
|
||||
end
|
||||
|
||||
for index, stack in pairs(inventory.main) do
|
||||
is_better, best_time = autotool.check_tool(stack, node_groups, best_time)
|
||||
if is_better then
|
||||
new_index = index - 1
|
||||
end
|
||||
end
|
||||
local odx = player:get_wield_index()
|
||||
player:set_wield_index(new_index)
|
||||
minetest.after(best_time + 0.05,function() player:set_wield_index(odx) end)
|
||||
end
|
||||
|
||||
minetest.register_on_punchnode(function(pos,node)
|
||||
autotool.autotool(pos)
|
||||
end)
|
||||
|
||||
minetest.register_cheat("AutoTool", "Inventory", "autotool")
|
@ -1,27 +0,0 @@
|
||||
function get_itemslot_bg(x, y, w, h)
|
||||
local out = ""
|
||||
for i = 0, w - 1, 1 do
|
||||
for j = 0, h - 1, 1 do
|
||||
out = out .."image["..x+i..","..y+j..";1,1;mcl_formspec_itemslot.png]"
|
||||
end
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
local formspec = "size[9,8.75]"..
|
||||
"label[0,0;"..minetest.formspec_escape(minetest.colorize("#313131", "Ender Chest")).."]"..
|
||||
"list[current_player;enderchest;0,0.5;9,3;]"..
|
||||
get_itemslot_bg(0,0.5,9,3)..
|
||||
"label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", "Inventory")).."]"..
|
||||
"list[current_player;main;0,4.5;9,3;9]"..
|
||||
get_itemslot_bg(0,4.5,9,3)..
|
||||
"list[current_player;main;0,7.74;9,1;]"..
|
||||
get_itemslot_bg(0,7.74,9,1)..
|
||||
"listring[current_player;enderchest]"..
|
||||
"listring[current_player;main]"
|
||||
|
||||
function minetest.open_special_inventory()
|
||||
minetest.show_formspec("enderchest:enderchest", formspec)
|
||||
end
|
||||
|
||||
minetest.register_cheat("Enderchest", "Inventory", minetest.open_special_inventory)
|
@ -1,27 +0,0 @@
|
||||
function get_itemslot_bg(x, y, w, h)
|
||||
local out = ""
|
||||
for i = 0, w - 1, 1 do
|
||||
for j = 0, h - 1, 1 do
|
||||
out = out .."image["..x+i..","..y+j..";1,1;mcl_formspec_itemslot.png]"
|
||||
end
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
local formspec = "size[9,8.75]"..
|
||||
"label[0,0;"..minetest.formspec_escape(minetest.colorize("#313131", "Hand")).."]"..
|
||||
"list[current_player;hand;0,0.5;1,1;]"..
|
||||
get_itemslot_bg(0,0.5,1,1)..
|
||||
"label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", "Inventory")).."]"..
|
||||
"list[current_player;main;0,4.5;9,3;9]"..
|
||||
get_itemslot_bg(0,4.5,9,3)..
|
||||
"list[current_player;main;0,7.74;9,1;]"..
|
||||
get_itemslot_bg(0,7.74,9,1)..
|
||||
"listring[current_player;hand]"..
|
||||
"listring[current_player;main]"
|
||||
|
||||
local function hand()
|
||||
minetest.show_formspec("inventory:hand", formspec)
|
||||
end
|
||||
|
||||
minetest.register_cheat("Hand", "Player", hand)
|
@ -1,11 +1,179 @@
|
||||
inventory_mod = {}
|
||||
local drop_action = InventoryAction("drop")
|
||||
|
||||
local strip_move_act = InventoryAction("move")
|
||||
strip_move_act:to("current_player", "craft", 1)
|
||||
local strip_craft_act = InventoryAction("craft")
|
||||
strip_craft_act:craft("current_player")
|
||||
local strip_move_back_act = InventoryAction("move")
|
||||
strip_move_back_act:from("current_player", "craftresult", 1)
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
local player = minetest.localplayer
|
||||
if not player then return end
|
||||
local item = player:get_wielded_item()
|
||||
local itemdef = minetest.get_item_def(item:get_name())
|
||||
local wieldindex = player:get_wield_index()
|
||||
-- AutoRefill
|
||||
if minetest.settings:get_bool("autorefill") and itemdef then
|
||||
local space = item:get_free_space()
|
||||
local i = minetest.find_item(item:get_name(), wieldindex + 1)
|
||||
if i and space > 0 then
|
||||
local move_act = InventoryAction("move")
|
||||
move_act:to("current_player", "main", wieldindex)
|
||||
move_act:from("current_player", "main", i)
|
||||
move_act:set_count(space)
|
||||
move_act:apply()
|
||||
end
|
||||
end
|
||||
-- AutoPlanks (Strip in DF)
|
||||
if minetest.settings:get_bool("autoplanks") then
|
||||
if itemdef and itemdef.groups.tree and player:get_control().place then
|
||||
strip_move_act:from("current_player", "main", wieldindex)
|
||||
strip_move_back_act:to("current_player", "main", wieldindex)
|
||||
strip_move_act:apply()
|
||||
strip_craft_act:apply()
|
||||
strip_move_back_act:apply()
|
||||
end
|
||||
end
|
||||
-- AutoEject
|
||||
if minetest.settings:get_bool("autoeject") then
|
||||
local list = (minetest.settings:get("eject_items") or ""):split(",")
|
||||
local inventory = minetest.get_inventory("current_player")
|
||||
for index, stack in pairs(inventory.main) do
|
||||
if table.indexof(list, stack:get_name()) ~= -1 then
|
||||
drop_action:from("current_player", "main", index)
|
||||
drop_action:apply()
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_list_command("eject", "Configure AutoEject", "eject_items")
|
||||
|
||||
-- AutoTool
|
||||
|
||||
local function check_tool(stack, node_groups, old_best_time)
|
||||
local toolcaps = stack:get_tool_capabilities()
|
||||
if not toolcaps then return end
|
||||
local best_time = old_best_time
|
||||
for group, groupdef in pairs(toolcaps.groupcaps) do
|
||||
local level = node_groups[group]
|
||||
if level then
|
||||
local this_time = groupdef.times[level]
|
||||
if this_time < best_time then
|
||||
best_time = this_time
|
||||
end
|
||||
end
|
||||
end
|
||||
return best_time < old_best_time, best_time
|
||||
end
|
||||
|
||||
local function find_best_tool(nodename, switch)
|
||||
local player = minetest.localplayer
|
||||
local inventory = minetest.get_inventory("current_player")
|
||||
local node_groups = minetest.get_node_def(nodename).groups
|
||||
local new_index = player:get_wield_index()
|
||||
local is_better, best_time = false, math.huge
|
||||
|
||||
is_better, best_time = check_tool(player:get_wielded_item(), node_groups, best_time)
|
||||
if inventory.hand then
|
||||
is_better, best_time = check_tool(inventory.hand[1], node_groups, best_time)
|
||||
end
|
||||
|
||||
for index, stack in ipairs(inventory.main) do
|
||||
is_better, best_time = check_tool(stack, node_groups, best_time)
|
||||
if is_better then
|
||||
new_index = index
|
||||
end
|
||||
end
|
||||
|
||||
return new_index
|
||||
end
|
||||
|
||||
function minetest.select_best_tool(nodename)
|
||||
minetest.localplayer:set_wield_index(find_best_tool(nodename))
|
||||
end
|
||||
|
||||
local new_index, old_index, pointed_pos
|
||||
|
||||
minetest.register_on_punchnode(function(pos, node)
|
||||
if minetest.settings:get_bool("autotool") then
|
||||
pointed_pos = pos
|
||||
old_index = old_index or minetest.localplayer:get_wield_index()
|
||||
new_index = find_best_tool(node.name)
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_globalstep(function()
|
||||
local player = minetest.localplayer
|
||||
if not new_index then return end
|
||||
if minetest.settings:get_bool("autotool") then
|
||||
local pt = minetest.get_pointed_thing()
|
||||
if pt and pt.type == "node" and vector.equals(minetest.get_pointed_thing_position(pt), pointed_pos) and player:get_control().dig then
|
||||
player:set_wield_index(new_index)
|
||||
return
|
||||
end
|
||||
end
|
||||
player:set_wield_index(old_index)
|
||||
new_index, old_index, pointed_pos = nil
|
||||
end)
|
||||
|
||||
-- Enderchest
|
||||
|
||||
function get_itemslot_bg(x, y, w, h)
|
||||
local out = ""
|
||||
for i = 0, w - 1, 1 do
|
||||
for j = 0, h - 1, 1 do
|
||||
out = out .."image["..x+i..","..y+j..";1,1;mcl_formspec_itemslot.png]"
|
||||
end
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
local enderchest_formspec = "size[9,8.75]"..
|
||||
"label[0,0;"..minetest.formspec_escape(minetest.colorize("#313131", "Ender Chest")).."]"..
|
||||
"list[current_player;enderchest;0,0.5;9,3;]"..
|
||||
get_itemslot_bg(0,0.5,9,3)..
|
||||
"label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", "Inventory")).."]"..
|
||||
"list[current_player;main;0,4.5;9,3;9]"..
|
||||
get_itemslot_bg(0,4.5,9,3)..
|
||||
"list[current_player;main;0,7.74;9,1;]"..
|
||||
get_itemslot_bg(0,7.74,9,1)..
|
||||
"listring[current_player;enderchest]"..
|
||||
"listring[current_player;main]"
|
||||
|
||||
function minetest.open_enderchest()
|
||||
minetest.show_formspec("inventory:enderchest", enderchest_formspec)
|
||||
end
|
||||
|
||||
-- HandSlot
|
||||
|
||||
local hand_formspec = "size[9,8.75]"..
|
||||
"label[0,0;"..minetest.formspec_escape(minetest.colorize("#313131", "Hand")).."]"..
|
||||
"list[current_player;hand;0,0.5;1,1;]"..
|
||||
get_itemslot_bg(0,0.5,1,1)..
|
||||
"label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", "Inventory")).."]"..
|
||||
"list[current_player;main;0,4.5;9,3;9]"..
|
||||
get_itemslot_bg(0,4.5,9,3)..
|
||||
"list[current_player;main;0,7.74;9,1;]"..
|
||||
get_itemslot_bg(0,7.74,9,1)..
|
||||
"listring[current_player;hand]"..
|
||||
"listring[current_player;main]"
|
||||
|
||||
function minetest.open_handslot()
|
||||
minetest.show_formspec("inventory:hand", hand_formspec)
|
||||
end
|
||||
|
||||
minetest.register_cheat("AutoEject", "Inventory", "autoeject")
|
||||
minetest.register_cheat("AutoTool", "Inventory", "autotool")
|
||||
minetest.register_cheat("Hand", "Inventory", minetest.open_handslot)
|
||||
minetest.register_cheat("Enderchest", "Inventory", minetest.open_enderchest)
|
||||
minetest.register_cheat("AutoPlanks", "Inventory", "autoplanks")
|
||||
minetest.register_cheat("AutoRefill", "Inventory", "autorefill")
|
||||
|
||||
local modname = minetest.get_current_modname()
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
|
||||
dofile(modpath .. "/invhack.lua")
|
||||
dofile(modpath .. "/enderchest.lua")
|
||||
dofile(modpath .. "/hand.lua")
|
||||
dofile(modpath .. "/next_item.lua")
|
||||
dofile(modpath .. "/autotool.lua")
|
||||
dofile(modpath .. "/autoeject.lua")
|
||||
dofile(modpath .. "/invhack.lua")
|
||||
|
||||
|
44
clientmods/dragonfire/movement/init.lua
Normal file
44
clientmods/dragonfire/movement/init.lua
Normal file
@ -0,0 +1,44 @@
|
||||
local function register_keypress_cheat(cheat, keyname, condition)
|
||||
local was_active = false
|
||||
minetest.register_globalstep(function()
|
||||
local is_active = minetest.settings:get_bool(cheat) and (not condition or condition())
|
||||
if is_active then
|
||||
minetest.set_keypress(keyname, true)
|
||||
elseif was_active then
|
||||
minetest.set_keypress(keyname, false)
|
||||
end
|
||||
was_active = is_active
|
||||
end)
|
||||
end
|
||||
|
||||
register_keypress_cheat("autosneak", "sneak", function()
|
||||
return minetest.localplayer:is_touching_ground()
|
||||
end)
|
||||
register_keypress_cheat("autosprint", "special1")
|
||||
|
||||
local legit_override
|
||||
|
||||
local function get_override_factor(name)
|
||||
if minetest.settings:get_bool("override_" .. name) then
|
||||
return tonumber(minetest.settings:get("override_" .. name .. "_factor")) or 1
|
||||
else
|
||||
return 1.0
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_globalstep(function()
|
||||
if not legit_override then return end
|
||||
local override = table.copy(legit_override)
|
||||
override.speed = override.speed * get_override_factor("speed")
|
||||
override.jump = override.jump * get_override_factor("jump")
|
||||
override.gravity = override.gravity * get_override_factor("gravity")
|
||||
minetest.localplayer:set_physics_override(override)
|
||||
end)
|
||||
|
||||
minetest.register_on_recieve_physics_override(function(override)
|
||||
legit_override = override
|
||||
return true
|
||||
end)
|
||||
|
||||
minetest.register_cheat("AutoSneak", "Movement", "autosneak")
|
||||
minetest.register_cheat("AutoSprint", "Movement", "autosprint")
|
16
clientmods/dragonfire/render/init.lua
Normal file
16
clientmods/dragonfire/render/init.lua
Normal file
@ -0,0 +1,16 @@
|
||||
core.register_list_command("xray", "Configure X-Ray", "xray_nodes")
|
||||
core.register_list_command("search", "Configure NodeESP", "node_esp_nodes")
|
||||
|
||||
core.register_on_spawn_particle(function(particle)
|
||||
if core.settings:get_bool("noweather") and particle.texture:sub(1, 12) == "weather_pack" then
|
||||
return true
|
||||
end
|
||||
end)
|
||||
|
||||
core.register_on_play_sound(function(sound)
|
||||
if core.settings:get_bool("noweather") and sound.name == "weather_rain" then
|
||||
return true
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_cheat("NoWeather", "Render", "noweather")
|
@ -71,7 +71,11 @@ minetest.register_globalstep(function(dtime)
|
||||
local nodes_per_tick = tonumber(minetest.settings:get("nodes_per_tick")) or 8
|
||||
if item:get_count() > 0 and def.node_placement_prediction ~= "" then
|
||||
if minetest.settings:get_bool("scaffold") then
|
||||
minetest.place_node(vector.add(pos, {x = 0, y = -0.6, z = 0}))
|
||||
local p = vector.round(vector.add(pos, {x = 0, y = -0.6, z = 0}))
|
||||
local node = minetest.get_node_or_nil(p)
|
||||
if not node or minetest.get_node_def(node.name).buildable_to then
|
||||
minetest.place_node(p)
|
||||
end
|
||||
elseif minetest.settings:get_bool("mscaffold") then
|
||||
--local z = pos.z
|
||||
local positions = {
|
||||
@ -109,7 +113,7 @@ minetest.register_globalstep(function(dtime)
|
||||
minetest.place_node(p)
|
||||
end
|
||||
elseif minetest.settings:get_bool("block_water") then
|
||||
local positions = minetest.find_nodes_near(pos, 5, {"mcl_core:water_source", "mcl_core:water_floating"}, true)
|
||||
local positions = minetest.find_nodes_near(pos, 5, {"mcl_core:water_source", "mcl_core:water_flowing"}, true)
|
||||
for i, p in pairs(positions) do
|
||||
if i > nodes_per_tick then break end
|
||||
minetest.place_node(p)
|
||||
@ -122,6 +126,23 @@ minetest.register_globalstep(function(dtime)
|
||||
end
|
||||
end
|
||||
end
|
||||
if minetest.settings:get_bool("nuke") then
|
||||
local i = 0
|
||||
for x = pos.x - 4, pos.x + 4 do
|
||||
for y = pos.y - 4, pos.y + 4 do
|
||||
for z = pos.z - 4, pos.z + 4 do
|
||||
local p = vector.new(x, y, z)
|
||||
local node = minetest.get_node_or_nil(p)
|
||||
local def = node and minetest.get_node_def(node.name)
|
||||
if def and def.diggable then
|
||||
if i > nodes_per_tick then return end
|
||||
minetest.dig_node(p)
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_cheat("mScaffold", "World", "mscaffold")
|
||||
@ -130,3 +151,4 @@ minetest.register_cheat("HighwayZ", "World", "highway_z")
|
||||
minetest.register_cheat("BlockWater", "World", "block_water")
|
||||
minetest.register_cheat("AutoTNT", "World", "autotnt")
|
||||
minetest.register_cheat("Replace", "World", "replace")
|
||||
minetest.register_cheat("Nuke", "World", "nuke")
|
||||
|
@ -31,7 +31,6 @@ load_mod_autodupe = true
|
||||
load_mod_randomscreenshot = true
|
||||
load_mod_util = true
|
||||
load_mod_scaffold = true
|
||||
load_mod_adupe = false
|
||||
load_mod_speedlimit = true
|
||||
load_mod_frenemies = true
|
||||
load_mod_autocraft = true
|
||||
@ -41,3 +40,5 @@ load_mod_nlist = true
|
||||
load_mod_kamikaze = true
|
||||
load_mod_muse = true
|
||||
load_mod_optimize = true
|
||||
load_mod_render = true
|
||||
load_mod_combat = true
|
||||
|
4
clientmods/mods_here.txt
Normal file
4
clientmods/mods_here.txt
Normal file
@ -0,0 +1,4 @@
|
||||
You can install Minetest or Dragonfire clientmods by copying (and extracting) them into this folder.
|
||||
To enable them write
|
||||
load_mod_<modname> = true
|
||||
in mods.conf in this directory.
|
101
doc/builtin_entities.txt
Normal file
101
doc/builtin_entities.txt
Normal 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.
|
@ -219,7 +219,7 @@ For helper functions see "Vector helpers".
|
||||
### pointed_thing
|
||||
* `{type="nothing"}`
|
||||
* `{type="node", under=pos, above=pos}`
|
||||
* `{type="object", id=ObjectID}`
|
||||
* `{type="object", ref=ClientObjectRef}`
|
||||
|
||||
Flag Specifier Format
|
||||
---------------------
|
||||
@ -674,9 +674,8 @@ Minetest namespace reference
|
||||
### Global callback registration functions
|
||||
Call these functions only at load time!
|
||||
|
||||
* `minetest.open_special_inventory()`
|
||||
* `minetest.open_enderchest()`
|
||||
* This function is called if the client uses the Keybind for it (by default "O")
|
||||
* It is used for a client provided inventory
|
||||
* You can override it
|
||||
* `minetest.register_globalstep(function(dtime))`
|
||||
* Called every client environment step, usually interval of 0.1s
|
||||
@ -697,6 +696,18 @@ Call these functions only at load time!
|
||||
* Adds definition to minetest.registered_chatcommands
|
||||
* `minetest.unregister_chatcommand(name)`
|
||||
* Unregisters a chatcommands registered with register_chatcommand.
|
||||
* `minetest.register_list_command(command, desc, setting)`
|
||||
* Registers a chatcommand `command` to manage a list that takes the args `del | add | list <param>`
|
||||
* The list is stored comma-seperated in `setting`
|
||||
* `desc` is the description
|
||||
* `add` adds something to the list
|
||||
* `del` del removes something from 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())`
|
||||
* Called when the local player dies
|
||||
* `minetest.register_on_hp_modification(function(hp))`
|
||||
@ -740,6 +751,18 @@ Call these functions only at load time!
|
||||
* Called when the local player open inventory
|
||||
* Newest functions are called first
|
||||
* If any function returns true, inventory doesn't open
|
||||
* `minetest.register_on_recieve_physics_override(function(override))`
|
||||
* Called when recieving physics_override from server
|
||||
* Newest functions are called first
|
||||
* If any function returns true, the physics override does not change
|
||||
* `minetest.register_on_play_sound(function(SimpleSoundSpec))`
|
||||
* Called when recieving a play sound command from server
|
||||
* Newest functions are called first
|
||||
* If any function returns true, the sound does not play
|
||||
* `minetest.register_on_spawn_partice(function(particle definition))`
|
||||
* Called when recieving a spawn particle command from server
|
||||
* Newest functions are called first
|
||||
* If any function returns true, the particel does not spawn
|
||||
|
||||
### Setting-related
|
||||
* `minetest.settings`: Settings object containing all of the settings from the
|
||||
@ -837,6 +860,13 @@ Call these functions only at load time!
|
||||
* `pos2`: end of the ray
|
||||
* `objects`: if false, only nodes will be returned. Default is `true`.
|
||||
* `liquids`: if false, liquid nodes won't be returned. Default is `false`.
|
||||
* `minetest.get_pointed_thing()` returns `PointedThing`
|
||||
* Returns the thing currently pointed by player
|
||||
* `minetest.get_pointed_thing_position(pointed_thing, above)`
|
||||
* Returns the position of a `pointed_thing` or `nil` if the `pointed_thing`
|
||||
does not refer to a node or entity.
|
||||
* If the optional `above` parameter is true and the `pointed_thing` refers
|
||||
to a node, then it will return the `above` position of the `pointed_thing`.
|
||||
* `minetest.find_path(pos1,pos2,searchdistance,max_jump,max_drop,algorithm)`
|
||||
* returns table containing path that can be walked on
|
||||
* returns a table of 3D points representing a path from `pos1` to `pos2` or
|
||||
@ -891,6 +921,9 @@ Call these functions only at load time!
|
||||
### Client Environment
|
||||
* `minetest.get_player_names()`
|
||||
* Returns list of player names on server (nil if CSM_RF_READ_PLAYERINFO is enabled by server)
|
||||
* `minetest.get_objects_inside_radius(pos, radius)`: returns a list of
|
||||
ClientObjectRefs.
|
||||
* `radius`: using an euclidean metric
|
||||
* `minetest.disconnect()`
|
||||
* Disconnect from the server and exit to main menu.
|
||||
* Returns `false` if the client is already disconnecting otherwise returns `true`.
|
||||
@ -996,6 +1029,13 @@ Passed to `HTTPApiTable.fetch` callback. Returned by
|
||||
* e.g. minetest.set_keypress("jump", true) will cause te player to jump until minetest.set_keypress("jump", false) is called or the player presses & releases the space bar himself
|
||||
* `minetest.get_inventory(location)`
|
||||
* Returns the inventory at location
|
||||
* `minetest.find_item(item)`
|
||||
* finds and an item in the inventory
|
||||
* returns index on success or nil if item is not found
|
||||
* `minetest.switch_to_item(item)`
|
||||
* `item` is an Itemstring
|
||||
* searches to item in inventory, sets the wield index to it if found
|
||||
* returns true on success, false if item was not found
|
||||
* `minetest.register_cheat(name, category, setting | function)`
|
||||
* Register an entry for the cheat menu
|
||||
* If the Category is nonexistant, it will be created
|
||||
@ -1060,6 +1100,8 @@ Passed to `HTTPApiTable.fetch` callback. Returned by
|
||||
* returns the exact position on the surface of a pointed node
|
||||
* `minetest.global_exists(name)`
|
||||
* Checks if a global variable has been set, without triggering a warning.
|
||||
* `minetest.make_screenshot()`
|
||||
* Triggers the MT makeScreenshot functionality
|
||||
|
||||
### UI
|
||||
* `minetest.ui.minimap`
|
||||
@ -1069,6 +1111,14 @@ Passed to `HTTPApiTable.fetch` callback. Returned by
|
||||
* Reference to the camera object. See [`Camera`](#camera) class reference for methods.
|
||||
* `minetest.show_formspec(formname, formspec)` : returns true on success
|
||||
* Shows a formspec to the player
|
||||
* `minetest.close_formspec(formname)`
|
||||
* `formname`: has to exactly match the one given in `show_formspec`, or the
|
||||
formspec will not close.
|
||||
* calling `show_formspec(formname, "")` is equal to this
|
||||
expression.
|
||||
* to close a formspec regardless of the formname, call
|
||||
`minetest.close_formspec("")`.
|
||||
**USE THIS ONLY WHEN ABSOLUTELY NECESSARY!**
|
||||
* `minetest.display_chat_message(message)` returns true on success
|
||||
* Shows a chat message to the current player.
|
||||
|
||||
@ -1152,6 +1202,10 @@ Methods:
|
||||
* returns the yaw (degrees)
|
||||
* `set_yaw(yaw)`
|
||||
* sets the yaw (degrees)
|
||||
* `get_pitch()`
|
||||
* returns the pitch (degrees)
|
||||
* `set_pitch(pitch)`
|
||||
* sets the pitch (degrees)
|
||||
* `get_velocity()`
|
||||
* returns player speed vector
|
||||
* `set_velocity(vel)`
|
||||
@ -1161,9 +1215,9 @@ Methods:
|
||||
* `get_name()`
|
||||
* returns player name
|
||||
* `get_wield_index()`
|
||||
* returns the index of the wielded item
|
||||
* returns the index of the wielded item (starts at 1)
|
||||
* `set_wield_index()`
|
||||
* sets the index
|
||||
* sets the index (starts at 1)
|
||||
* `get_wielded_item()`
|
||||
* returns the itemstack the player is holding
|
||||
* `is_attached()`
|
||||
@ -1194,6 +1248,17 @@ Methods:
|
||||
}
|
||||
```
|
||||
|
||||
* `set_physics_override(override_table)`
|
||||
* `override_table` is a table with the following fields:
|
||||
* `speed`: multiplier to default walking speed value (default: `1`)
|
||||
* `jump`: multiplier to default jump value (default: `1`)
|
||||
* `gravity`: multiplier to default gravity value (default: `1`)
|
||||
* `sneak`: whether player can sneak (default: `true`)
|
||||
* `sneak_glitch`: whether player can use the new move code replications
|
||||
of the old sneak side-effects: sneak ladders and 2 node sneak jump
|
||||
(default: `false`)
|
||||
* `new_move`: use new move/sneak code. When `false` the exact old code
|
||||
is used for the specific old sneak behaviour (default: `true`)
|
||||
* `get_override_pos()`
|
||||
* returns override position
|
||||
* `get_last_pos()`
|
||||
@ -1255,8 +1320,8 @@ Methods:
|
||||
aux1 = boolean,
|
||||
sneak = boolean,
|
||||
zoom = boolean,
|
||||
LMB = boolean,
|
||||
RMB = boolean,
|
||||
dig = boolean,
|
||||
place = boolean,
|
||||
}
|
||||
```
|
||||
|
||||
@ -1273,6 +1338,8 @@ Methods:
|
||||
* change a value of a previously added HUD element
|
||||
* element `stat` values: `position`, `name`, `scale`, `text`, `number`, `item`, `dir`
|
||||
* Returns `true` on success, otherwise returns `nil`
|
||||
* `get_object()`
|
||||
* Returns the ClientObjectRef for the player
|
||||
|
||||
### Settings
|
||||
An interface to read config files in the format of `minetest.conf`.
|
||||
@ -1301,6 +1368,26 @@ Can be obtained via `minetest.get_meta(pos)`.
|
||||
* `fields`: key-value storage
|
||||
* `inventory`: `{list1 = {}, ...}}`
|
||||
|
||||
### ClientObjectRef
|
||||
|
||||
Moving things in the game are generally these.
|
||||
This is basically a reference to a C++ `GenericCAO`.
|
||||
|
||||
#### Methods
|
||||
|
||||
* `get_pos()`: returns `{x=num, y=num, z=num}`
|
||||
* `get_velocity()`: returns the velocity, a vector
|
||||
* `get_acceleration()`: returns the acceleration, a vector
|
||||
* `get_rotation()`: returns the rotation, a vector (radians)
|
||||
* `is_player()`: returns true if the object is a player
|
||||
* `is_local_player()`: returns true if the object is the local player
|
||||
* `get_attach()`: returns parent or nil if it isn't attached.
|
||||
* `get_nametag()`: returns the nametag (string)
|
||||
* `get_item_textures()`: returns the textures
|
||||
* `get_max_hp()`: returns the maximum heath
|
||||
* `punch()`: punches the object
|
||||
* `rightclick()`: rightclicks the object
|
||||
|
||||
### `Raycast`
|
||||
|
||||
A raycast on the map. It works with selection boxes.
|
||||
@ -1480,6 +1567,8 @@ The following functions provide escape sequences:
|
||||
`minetest.get_color_escape_sequence(color) ..
|
||||
message ..
|
||||
minetest.get_color_escape_sequence("#ffffff")`
|
||||
* `minetest.rainbow(message)`:
|
||||
* Rainbow colorizes the message.
|
||||
* `minetest.get_background_escape_sequence(color)`
|
||||
* `color` is a [ColorString](#colorstring)
|
||||
* The escape sequence sets the background of the whole text element to
|
||||
@ -1665,3 +1754,47 @@ Same as `image`, but does not accept a `position`; the position is instead deter
|
||||
-- ^ Uses texture (string)
|
||||
}
|
||||
|
||||
### InventoryAction
|
||||
A reference to a C++ InventoryAction. You can move, drop and craft items in all accessible inventories using InventoryActions.
|
||||
|
||||
#### methods
|
||||
|
||||
* `InventoryAction(type)`:
|
||||
* creates a new InventoryAction
|
||||
* type is on of "move", "drop", or "craft", else returns nil
|
||||
* indexing starts at 1
|
||||
* `apply()`:
|
||||
* applies the InventoryAction (InventoryActions can be applied multible times)
|
||||
* `from(inventorylocation, listname, stack)`
|
||||
* this is valid for move or drop actions
|
||||
* when `apply()` is called items are moved / dropped from `listname` `inventorylocation` in` at `stack`
|
||||
* `to(inventorylocation, listname, stack)`
|
||||
* this is valid for move actions
|
||||
* when `apply()` is called items are moved to `listname` in`inventorylocation` at `stack`
|
||||
* `craft(inventoryaction)`
|
||||
* this is valid for craft actions
|
||||
* when `apply()` is called a craft event for this inventory will be triggered
|
||||
* `set_count(count)`
|
||||
* this is valid for all actions
|
||||
* it specifies how many items to drop / craft / move
|
||||
* `0` means move all items
|
||||
* default count: `0`
|
||||
|
||||
#### example
|
||||
`local move_act = InventoryAction("move")
|
||||
move_act:from("current_player", "main", 1)
|
||||
move_act:to("current_player", "craft", 1)
|
||||
move_act:set_count(1)
|
||||
local craft_act = InventoryAction("craft")
|
||||
craft_act:craft("current_player")
|
||||
local drop_act = InventoryAction("drop")
|
||||
drop_act:from("current_player", "craft_result",10)
|
||||
move_act:apply()
|
||||
craft_act:apply()
|
||||
drop_act:apply()
|
||||
`
|
||||
* e.g. In first hotbar slot there are tree logs: Move one to craft field, then craft wood out of it and immediately drop it
|
||||
|
||||
|
||||
|
||||
|
||||
|
511
doc/lua_api.txt
511
doc/lua_api.txt
@ -62,12 +62,12 @@ Where `<gameid>` is unique to each game.
|
||||
The game directory can contain the following files:
|
||||
|
||||
* `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
|
||||
* `allowed_mapgens = <comma-separated mapgens>`
|
||||
e.g. `allowed_mapgens = v5,v6,flat`
|
||||
Mapgens not in this list are removed from the list of mapgens for
|
||||
the game.
|
||||
Mapgens not in this list are removed from the list of mapgens for the
|
||||
game.
|
||||
If not specified, all mapgens are allowed.
|
||||
* `disallowed_mapgens = <comma-separated mapgens>`
|
||||
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`
|
||||
These settings are hidden for this game in the world creation
|
||||
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`:
|
||||
Used to set default settings when running this game.
|
||||
* `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`.
|
||||
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
|
||||
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.
|
||||
|
||||
@ -152,7 +162,12 @@ Mod directory structure
|
||||
│ ├── models
|
||||
│ ├── textures
|
||||
│ │ ├── 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
|
||||
│ ├── media
|
||||
│ ├── locale
|
||||
@ -176,6 +191,11 @@ A `Settings` file that provides meta information about the mod.
|
||||
loaded before this mod.
|
||||
* `optional_depends`: A comma separated list of optional dependencies.
|
||||
Like a dependency, but no error if the mod doesn't exist.
|
||||
* `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.
|
||||
|
||||
@ -221,18 +241,20 @@ registered callbacks.
|
||||
`minetest.settings` can be used to read custom or existing settings at load
|
||||
time, if necessary. (See [`Settings`])
|
||||
|
||||
### `models`
|
||||
|
||||
Models for entities or meshnodes.
|
||||
|
||||
### `textures`, `sounds`, `media`
|
||||
### `textures`, `sounds`, `media`, `models`, `locale`
|
||||
|
||||
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
|
||||
------------------
|
||||
@ -378,11 +400,14 @@ stripping out the file extension:
|
||||
* e.g. `foomod_foothing.png`
|
||||
* e.g. `foomod_foothing`
|
||||
|
||||
|
||||
Texture modifiers
|
||||
-----------------
|
||||
|
||||
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
|
||||
|
||||
@ -780,7 +805,7 @@ Example (colored grass block):
|
||||
-- Overlay tiles: define them in the same style
|
||||
-- The top and bottom tile does not have overlay
|
||||
overlay_tiles = {"", "",
|
||||
{name = "default_grass_side.png", tileable_vertical = false}},
|
||||
{name = "default_grass_side.png"}},
|
||||
-- Global color, used in inventory
|
||||
color = "green",
|
||||
-- Palette in the world
|
||||
@ -1150,7 +1175,7 @@ Look for examples in `games/devtest` or `games/minetest_game`.
|
||||
base cube without affecting them.
|
||||
* The base cube texture tiles are defined as normal, the `plantlike`
|
||||
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
|
||||
(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.
|
||||
* `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
|
||||
================================
|
||||
@ -1973,8 +2023,10 @@ Item metadata only contains a key-value store.
|
||||
|
||||
Some of the values in the key-value store are handled specially:
|
||||
|
||||
* `description`: Set the item stack's description. Defaults to
|
||||
`idef.description`.
|
||||
* `description`: Set the item stack's 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.
|
||||
* `palette_index`: If the item has a palette, this is used to get the
|
||||
current color from the palette.
|
||||
@ -2220,6 +2272,18 @@ Elements
|
||||
* `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`.
|
||||
|
||||
### `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>]`
|
||||
|
||||
* Show an inventory image of registered item/node
|
||||
@ -2442,6 +2506,8 @@ Elements
|
||||
* Simple colored box
|
||||
* `color` is color specified as a `ColorString`.
|
||||
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>]`
|
||||
|
||||
@ -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.
|
||||
|
||||
* animated_image, inherits from image
|
||||
* box
|
||||
* button
|
||||
* button_exit, inherits from button
|
||||
* checkbox
|
||||
* scrollbar
|
||||
* table
|
||||
* textlist
|
||||
* dropdown
|
||||
* field
|
||||
* pwdfield, inherits from field
|
||||
* textarea
|
||||
* label
|
||||
* vertlabel, inherits from field
|
||||
* image
|
||||
* image_button
|
||||
* item_image_button
|
||||
* label
|
||||
* pwdfield, inherits from field
|
||||
* scrollbar
|
||||
* tabheader
|
||||
* table
|
||||
* textarea
|
||||
* textlist
|
||||
* vertlabel, inherits from label
|
||||
|
||||
|
||||
### 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.
|
||||
* box
|
||||
* 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
|
||||
* alpha - boolean, whether to draw alpha in bgimg. Default true.
|
||||
* 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.
|
||||
* padding - rect, adds space between the edges of the button and the content. This value is
|
||||
relative to bgimg_middle.
|
||||
* sound - a sound to be played when clicked.
|
||||
* textcolor - color, default white.
|
||||
* checkbox
|
||||
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
|
||||
* scrollbar
|
||||
* 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.
|
||||
* sound - a sound to be played when clicked.
|
||||
* dropdown
|
||||
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
|
||||
* sound - a sound to be played when clicked.
|
||||
* field, pwdfield, textarea
|
||||
* 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_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.
|
||||
* 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
|
||||
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
|
||||
* 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.
|
||||
* This is deprecated, use states instead.
|
||||
* 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
|
||||
* 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.
|
||||
* 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
|
||||
|
||||
@ -2988,6 +3076,8 @@ The following functions provide escape sequences:
|
||||
`minetest.get_color_escape_sequence(color) ..
|
||||
message ..
|
||||
minetest.get_color_escape_sequence("#ffffff")`
|
||||
* `minetest.rainbow(message)`:
|
||||
* Rainbow colorizes the message.
|
||||
* `minetest.get_background_escape_sequence(color)`
|
||||
* `color` is a ColorString
|
||||
* The escape sequence sets the background of the whole text element to
|
||||
@ -3012,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}`.
|
||||
|
||||
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])`:
|
||||
* Returns a vector.
|
||||
@ -3041,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`.
|
||||
* `vector.angle(v1, v2)`:
|
||||
* Returns the angle between `v1` and `v2` in radians.
|
||||
* `vector.dot(v1, v2)`
|
||||
* Returns the dot product of `v1` and `v2`
|
||||
* `vector.cross(v1, v2)`
|
||||
* Returns the cross product of `v1` and `v2`
|
||||
* `vector.dot(v1, v2)`:
|
||||
* Returns the dot product of `v1` and `v2`.
|
||||
* `vector.cross(v1, 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:
|
||||
|
||||
@ -3056,10 +3149,12 @@ For the following functions `x` can be either a vector or a number:
|
||||
* Returns a vector.
|
||||
* 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`.
|
||||
* `vector.multiply(v, x)`:
|
||||
* Returns a scaled vector or Schur product.
|
||||
* `vector.divide(v, x)`:
|
||||
* Returns a scaled vector or Schur quotient.
|
||||
* `vector.multiply(v, s)`:
|
||||
* Returns a scaled vector.
|
||||
* Deprecated: If `s` is a vector: Returns the Schur product.
|
||||
* `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
|
||||
vector ({x = <pitch>, y = <yaw>, z = <roll>}) where pitch, yaw and roll are
|
||||
@ -4252,6 +4347,8 @@ Utilities
|
||||
pathfinder_works = true,
|
||||
-- Whether Collision info is available to an objects' on_step (5.3.0)
|
||||
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`
|
||||
@ -4518,6 +4615,11 @@ Call these functions only at load time!
|
||||
* Called always when a player says something
|
||||
* Return `true` to mark the message as handled, which means that it will
|
||||
not be sent to other players.
|
||||
* `minetest.register_on_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))`
|
||||
* Called when the server received input from `player` in a formspec with
|
||||
the given `formname`. Specifically, this is called on any of the
|
||||
@ -4720,6 +4822,22 @@ Environment access
|
||||
* `pos`: The position where to measure the light.
|
||||
* `timeofday`: `nil` for current time, `0` for night, `0.5` for day
|
||||
* Returns a number between `0` and `15` or `nil`
|
||||
* `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)`
|
||||
* Place node with the same effects that a player would cause
|
||||
* `minetest.dig_node(pos)`
|
||||
@ -5238,17 +5356,23 @@ Sounds
|
||||
* `minetest.sound_fade(handle, step, gain)`
|
||||
* `handle` is a handle returned by `minetest.sound_play`
|
||||
* `step` determines how fast a sound will fade.
|
||||
Negative step will lower the sound volume, positive step will increase
|
||||
the sound volume.
|
||||
The gain will change by this much per second,
|
||||
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.
|
||||
Fading to zero will delete the sound.
|
||||
|
||||
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
|
||||
* Optional: Variable number of arguments that are passed to `func`
|
||||
|
||||
* `job:cancel()`
|
||||
* Cancels the job function from being called
|
||||
|
||||
Server
|
||||
------
|
||||
|
||||
@ -5712,6 +5836,9 @@ Global tables
|
||||
* Map of registered tool definitions, indexed by name
|
||||
* `minetest.registered_entities`
|
||||
* 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`
|
||||
* Map of object references, indexed by active object id
|
||||
* `minetest.luaentities`
|
||||
@ -5742,6 +5869,7 @@ Global tables
|
||||
* Map of registered chat command definitions, indexed by name
|
||||
* `minetest.registered_privileges`
|
||||
* Map of registered privilege definitions, indexed by name
|
||||
* Registered privileges can be modified directly in this table.
|
||||
|
||||
### Registered callback tables
|
||||
|
||||
@ -5856,6 +5984,31 @@ An `InvRef` is a reference to an inventory.
|
||||
`minetest.get_inventory(location)`.
|
||||
* 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`
|
||||
-----------
|
||||
|
||||
@ -5881,6 +6034,18 @@ an itemstring, a table or `nil`.
|
||||
stack).
|
||||
* `set_metadata(metadata)`: (DEPRECATED) Returns true.
|
||||
* `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.
|
||||
* `replace(item)`: replace the contents of this stack.
|
||||
* `item` can also be an itemstring or table.
|
||||
@ -6034,6 +6199,19 @@ object you are working with still exists.
|
||||
|
||||
* `get_pos()`: returns `{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)`
|
||||
* 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
|
||||
@ -6068,12 +6246,16 @@ object you are working with still exists.
|
||||
`frame_loop`.
|
||||
* `set_animation_frame_speed(frame_speed)`
|
||||
* `frame_speed`: number, default: `15.0`
|
||||
* `set_attach(parent, bone, position, rotation)`
|
||||
* `set_attach(parent, bone, position, rotation, forced_visible)`
|
||||
* `bone`: string
|
||||
* `position`: `{x=num, y=num, z=num}` (relative)
|
||||
* `rotation`: `{x=num, y=num, z=num}` = Rotation on each axis, in degrees
|
||||
* `get_attach()`: returns parent, bone, position, rotation or nil if it isn't
|
||||
attached.
|
||||
* `forced_visible`: Boolean to control whether the attached entity
|
||||
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_bone_position(bone, position, rotation)`
|
||||
* `bone`: string
|
||||
@ -6105,11 +6287,6 @@ object you are working with still exists.
|
||||
no effect and returning `nil`.
|
||||
* `set_velocity(vel)`
|
||||
* `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)`
|
||||
* `acc` is a vector
|
||||
* `get_acceleration()`: returns the acceleration, a vector
|
||||
@ -6117,35 +6294,37 @@ object you are working with still exists.
|
||||
* `rot` is a vector (radians). X is pitch (elevation), Y is yaw (heading)
|
||||
and Z is roll (bank).
|
||||
* `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
|
||||
* `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
|
||||
* `set_sprite(p, num_frames, framelength, select_horiz_by_yawpitch)`
|
||||
* Select sprite from spritesheet with optional animation and Dungeon Master
|
||||
style texture selection based on yaw relative to camera
|
||||
* `p`: {x=number, y=number}, the coordinate of the first frame
|
||||
(x: column, y: row), default: `{x=0, y=0}`
|
||||
* `num_frames`: number, default: `1`
|
||||
* `framelength`: number, default: `0.2`
|
||||
* `select_horiz_by_yawpitch`: boolean, this was once used for the Dungeon
|
||||
Master mob, default: `false`
|
||||
* `set_sprite(start_frame, num_frames, framelength, select_x_by_camera)`
|
||||
* Specifies and starts a sprite animation
|
||||
* Animations iterate along the frame `y` position.
|
||||
* `start_frame`: {x=column number, y=row number}, the coordinate of the
|
||||
first frame, default: `{x=0, y=0}`
|
||||
* `num_frames`: Total frames in the texture, default: `1`
|
||||
* `framelength`: Time per animated frame in seconds, default: `0.2`
|
||||
* `select_x_by_camera`: Only for visual = `sprite`. Changes the frame `x`
|
||||
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_luaentity()`
|
||||
|
||||
#### Player only (no-op for other objects)
|
||||
|
||||
* `get_player_name()`: returns `""` if is not a player
|
||||
* `get_player_velocity()`: returns `nil` if is not a player, otherwise a
|
||||
* `get_player_velocity()`: **DEPRECATED**, use get_velocity() instead.
|
||||
table {x, y, z} representing the player's instantaneous velocity in nodes/s
|
||||
* `add_player_velocity(vel)`
|
||||
* 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)
|
||||
* `add_player_velocity(vel)`: **DEPRECATED**, use add_velocity(vel) instead.
|
||||
* `get_look_dir()`: get camera direction as a unit vector
|
||||
* `get_look_vertical()`: pitch in radians
|
||||
* Angle ranges between -pi/2 and pi/2, which are straight up and down
|
||||
@ -6207,15 +6386,23 @@ object you are working with still exists.
|
||||
* Only affects formspecs shown after this is called.
|
||||
* `get_formspec_prepend(formspec)`: returns a formspec string.
|
||||
* `get_player_control()`: returns table with player pressed keys
|
||||
* The table consists of fields with boolean value representing the pressed
|
||||
keys, the fields are jump, right, left, LMB, RMB, sneak, aux1, down, up, zoom.
|
||||
* example: `{jump=false, right=true, left=false, LMB=false, RMB=false,
|
||||
sneak=true, aux1=false, down=false, up=false, zoom=false}`
|
||||
* The `zoom` field is available since 5.3
|
||||
* The table consists of fields with the following boolean values
|
||||
representing the pressed keys: `up`, `down`, `left`, `right`, `jump`,
|
||||
`aux1`, `sneak`, `dig`, `place`, `LMB`, `RMB`, and `zoom`.
|
||||
* The fields `LMB` and `RMB` are equal to `dig` and `place` respectively,
|
||||
and exist only to preserve backwards compatibility.
|
||||
* `get_player_control_bits()`: returns integer with bit packed player pressed
|
||||
keys.
|
||||
* bit nr/meaning: 0/up, 1/down, 2/left, 3/right, 4/jump, 5/aux1, 6/sneak,
|
||||
7/LMB, 8/RMB, 9/zoom (zoom available since 5.3)
|
||||
keys. Bits:
|
||||
* 0 - up
|
||||
* 1 - down
|
||||
* 2 - left
|
||||
* 3 - right
|
||||
* 4 - jump
|
||||
* 5 - aux1
|
||||
* 6 - sneak
|
||||
* 7 - dig
|
||||
* 8 - place
|
||||
* 9 - zoom
|
||||
* `set_physics_override(override_table)`
|
||||
* `override_table` is a table with the following fields:
|
||||
* `speed`: multiplier to default walking speed value (default: `1`)
|
||||
@ -6260,8 +6447,29 @@ object you are working with still exists.
|
||||
* `hud_set_hotbar_selected_image(texturename)`
|
||||
* sets image for selected item of hotbar
|
||||
* `hud_get_hotbar_selected_image`: returns texturename
|
||||
* `set_sky(parameters)`
|
||||
* `parameters` is a table with the following optional fields:
|
||||
* `set_minimap_modes({mode, mode, ...}, selected_mode)`
|
||||
* 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".
|
||||
* `type`: Available types:
|
||||
* `"regular"`: Uses 0 textures, `base_color` ignored
|
||||
@ -6305,8 +6513,8 @@ object you are working with still exists.
|
||||
* `get_sky()`: returns base_color, type, table of textures, clouds.
|
||||
* `get_sky_color()`: returns a table with the `sky_color` parameters as in
|
||||
`set_sky`.
|
||||
* `set_sun(parameters)`:
|
||||
* `parameters` is a table with the following optional fields:
|
||||
* `set_sun(sun_parameters)`:
|
||||
* `sun_parameters` is a table with the following optional fields:
|
||||
* `visible`: Boolean for whether the sun is visible.
|
||||
(default: `true`)
|
||||
* `texture`: A regular texture for the sun. Setting to `""`
|
||||
@ -6320,8 +6528,8 @@ object you are working with still exists.
|
||||
* `scale`: Float controlling the overall size of the sun. (default: `1`)
|
||||
* `get_sun()`: returns a table with the current sun parameters as in
|
||||
`set_sun`.
|
||||
* `set_moon(parameters)`:
|
||||
* `parameters` is a table with the following optional fields:
|
||||
* `set_moon(moon_parameters)`:
|
||||
* `moon_parameters` is a table with the following optional fields:
|
||||
* `visible`: Boolean for whether the moon is visible.
|
||||
(default: `true`)
|
||||
* `texture`: A regular texture for the moon. Setting to `""`
|
||||
@ -6331,8 +6539,8 @@ object you are working with still exists.
|
||||
* `scale`: Float controlling the overall size of the moon (default: `1`)
|
||||
* `get_moon()`: returns a table with the current moon parameters as in
|
||||
`set_moon`.
|
||||
* `set_stars(parameters)`:
|
||||
* `parameters` is a table with the following optional fields:
|
||||
* `set_stars(star_parameters)`:
|
||||
* `star_parameters` is a table with the following optional fields:
|
||||
* `visible`: Boolean for whether the stars are visible.
|
||||
(default: `true`)
|
||||
* `count`: Integer number to set the number of stars in
|
||||
@ -6344,8 +6552,8 @@ object you are working with still exists.
|
||||
* `scale`: Float controlling the overall size of the stars (default: `1`)
|
||||
* `get_stars()`: returns a table with the current stars parameters as in
|
||||
`set_stars`.
|
||||
* `set_clouds(parameters)`: set cloud parameters
|
||||
* `parameters` is a table with the following optional fields:
|
||||
* `set_clouds(cloud_parameters)`: set cloud parameters
|
||||
* `cloud_parameters` is a table with the following optional fields:
|
||||
* `density`: from `0` (no clouds) to `1` (full clouds) (default `0.4`)
|
||||
* `color`: basic cloud color with alpha channel, ColorSpec
|
||||
(default `#fff0f0e5`).
|
||||
@ -6363,21 +6571,17 @@ object you are working with still exists.
|
||||
amount.
|
||||
* `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
|
||||
* `set_local_animation(stand/idle, walk, dig, walk+dig, frame_speed=frame_speed)`:
|
||||
set animation for player model in third person view
|
||||
|
||||
set_local_animation({x=0, y=79}, -- stand/idle animation key frames
|
||||
{x=168, y=187}, -- walk animation key frames
|
||||
{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
|
||||
* `set_local_animation(idle, walk, dig, walk_while_dig, frame_speed)`:
|
||||
set animation for player model in third person view.
|
||||
* Every animation equals to a `{x=starting frame, y=ending frame}` table.
|
||||
* `frame_speed` sets the animations frame speed. Default is 30.
|
||||
* `get_local_animation()`: returns idle, walk, dig, walk_while_dig tables and
|
||||
`frame_speed`.
|
||||
* `set_eye_offset({x=0,y=0,z=0},{x=0,y=0,z=0})`: defines offset value for
|
||||
camera per player.
|
||||
* `set_eye_offset(firstperson, thirdperson)`: defines offset vectors for camera
|
||||
per player.
|
||||
* in first person view
|
||||
* 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)`:
|
||||
* Sends a server-side loaded mapblock to the player.
|
||||
* Returns `false` if failed.
|
||||
@ -6749,6 +6953,10 @@ Player properties need to be saved manually.
|
||||
|
||||
shaded = true,
|
||||
-- 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
|
||||
@ -6883,13 +7091,8 @@ Tile definition
|
||||
|
||||
* `"image.png"`
|
||||
* `{name="image.png", animation={Tile Animation definition}}`
|
||||
* `{name="image.png", backface_culling=bool, tileable_vertical=bool,
|
||||
tileable_horizontal=bool, align_style="node"/"world"/"user", scale=int}`
|
||||
* `{name="image.png", backface_culling=bool, align_style="node"/"world"/"user", scale=int}`
|
||||
* 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
|
||||
or kept aligned with its surroundings. "user" means that client
|
||||
setting will be used, similar to `glasslike_framed_optional`.
|
||||
@ -6942,6 +7145,13 @@ Used by `minetest.register_node`, `minetest.register_craftitem`, and
|
||||
|
||||
{
|
||||
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 = {},
|
||||
-- key = name, value = rating; rating = 1..3.
|
||||
@ -6980,6 +7190,13 @@ Used by `minetest.register_node`, `minetest.register_craftitem`, and
|
||||
|
||||
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
|
||||
tool_capabilities = {
|
||||
full_punch_interval = 1.0,
|
||||
@ -7109,6 +7326,8 @@ Used by `minetest.register_node`.
|
||||
|
||||
use_texture_alpha = false,
|
||||
-- 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",
|
||||
-- The node's `param2` is used to select a pixel from the image.
|
||||
@ -7177,12 +7396,6 @@ Used by `minetest.register_node`.
|
||||
drowning = 0,
|
||||
-- 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,
|
||||
-- If player is inside node, this damage is caused
|
||||
|
||||
@ -7261,10 +7474,13 @@ Used by `minetest.register_node`.
|
||||
-- Node was placed. Also played after falling
|
||||
|
||||
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>,
|
||||
-- When node starts to fall
|
||||
-- When node starts to fall or is detached
|
||||
},
|
||||
|
||||
drop = "",
|
||||
@ -7851,6 +8067,8 @@ Used by `minetest.register_chatcommand`.
|
||||
|
||||
func = function(name, param),
|
||||
-- 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:
|
||||
@ -7933,7 +8151,8 @@ Used by `Player:hud_add`. Returned by `Player:hud_get`.
|
||||
|
||||
{
|
||||
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},
|
||||
-- Left corner position of element
|
||||
@ -8101,6 +8320,66 @@ Used by `minetest.add_particlespawner`.
|
||||
-- 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
|
||||
---------------------------------
|
||||
|
||||
|
@ -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_overlay_round.png`: overlay texture for the round 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
|
||||
* `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 |
|
||||
| sides | x-, x+, z-, z+ faces |
|
||||
| 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 |
|
||||
| wield | The texture used when held by the player |
|
||||
|
||||
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
|
||||
----------------------------------------------------------
|
||||
|
Binary file not shown.
@ -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");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
Binary file not shown.
@ -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 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
|
||||
* 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
|
||||
|
||||
|
@ -124,8 +124,10 @@ minetest.register_node("basenodes:pine_needles", {
|
||||
})
|
||||
|
||||
minetest.register_node("basenodes:water_source", {
|
||||
description = "Water Source",
|
||||
description = "Water Source".."\n"..
|
||||
"Drowning damage: 1",
|
||||
drawtype = "liquid",
|
||||
waving = 3,
|
||||
tiles = {"default_water.png"},
|
||||
special_tiles = {
|
||||
{name = "default_water.png", backface_culling = false},
|
||||
@ -148,8 +150,10 @@ minetest.register_node("basenodes:water_source", {
|
||||
})
|
||||
|
||||
minetest.register_node("basenodes:water_flowing", {
|
||||
description = "Flowing Water",
|
||||
description = "Flowing Water".."\n"..
|
||||
"Drowning damage: 1",
|
||||
drawtype = "flowingliquid",
|
||||
waving = 3,
|
||||
tiles = {"default_water_flowing.png"},
|
||||
special_tiles = {
|
||||
{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", {
|
||||
description = "River Water Source",
|
||||
description = "River Water Source".."\n"..
|
||||
"Drowning damage: 1",
|
||||
drawtype = "liquid",
|
||||
waving = 3,
|
||||
tiles = { "default_river_water.png" },
|
||||
special_tiles = {
|
||||
{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", {
|
||||
description = "Flowing River Water",
|
||||
description = "Flowing River Water".."\n"..
|
||||
"Drowning damage: 1",
|
||||
drawtype = "flowingliquid",
|
||||
waving = 3,
|
||||
tiles = {"default_river_water_flowing.png"},
|
||||
special_tiles = {
|
||||
{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", {
|
||||
description = "Flowing Lava",
|
||||
description = "Flowing Lava".."\n"..
|
||||
"4 damage per second".."\n"..
|
||||
"Drowning damage: 1",
|
||||
drawtype = "flowingliquid",
|
||||
tiles = {"default_lava_flowing.png"},
|
||||
special_tiles = {
|
||||
@ -251,7 +261,9 @@ minetest.register_node("basenodes:lava_flowing", {
|
||||
})
|
||||
|
||||
minetest.register_node("basenodes:lava_source", {
|
||||
description = "Lava Source",
|
||||
description = "Lava Source".."\n"..
|
||||
"4 damage per second".."\n"..
|
||||
"Drowning damage: 1",
|
||||
drawtype = "liquid",
|
||||
tiles = { "default_lava.png" },
|
||||
special_tiles = {
|
||||
@ -290,7 +302,8 @@ minetest.register_node("basenodes:mossycobble", {
|
||||
})
|
||||
|
||||
minetest.register_node("basenodes:apple", {
|
||||
description = "Apple",
|
||||
description = "Apple".."\n"..
|
||||
"Food (+2)",
|
||||
drawtype = "plantlike",
|
||||
tiles ={"default_apple.png"},
|
||||
inventory_image = "default_apple.png",
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 796 B |
@ -6,7 +6,7 @@
|
||||
|
||||
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
|
||||
* Axe: dig choppy
|
||||
* Shovel: dig crumbly
|
||||
@ -24,25 +24,54 @@ Tool materials:
|
||||
]]
|
||||
|
||||
-- The hand
|
||||
minetest.register_item(":", {
|
||||
type = "none",
|
||||
wield_image = "wieldhand.png",
|
||||
wield_scale = {x=1,y=1,z=2.5},
|
||||
tool_capabilities = {
|
||||
full_punch_interval = 1.0,
|
||||
max_drop_level = 0,
|
||||
groupcaps = {
|
||||
crumbly = {times={[3]=1.50}, uses=0, maxlevel=0},
|
||||
snappy = {times={[3]=1.50}, uses=0, maxlevel=0},
|
||||
oddly_breakable_by_hand = {times={[1]=7.00,[2]=4.00,[3]=2.00}, uses=0, maxlevel=0},
|
||||
},
|
||||
damage_groups = {fleshy=1},
|
||||
}
|
||||
})
|
||||
if minetest.settings:get_bool("creative_mode") then
|
||||
local digtime = 42
|
||||
local caps = {times = {digtime, digtime, digtime}, uses = 0, maxlevel = 256}
|
||||
|
||||
minetest.register_item(":", {
|
||||
type = "none",
|
||||
wield_image = "wieldhand.png",
|
||||
wield_scale = {x = 1, y = 1, z = 2.5},
|
||||
range = 10,
|
||||
tool_capabilities = {
|
||||
full_punch_interval = 0.5,
|
||||
max_drop_level = 3,
|
||||
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
|
||||
minetest.register_tool("basetools:pick_mese", {
|
||||
description = "Mese Pickaxe",
|
||||
description = "Mese Pickaxe".."\n"..
|
||||
"Digs diggable nodes instantly",
|
||||
inventory_image = "basetools_mesepick.png",
|
||||
tool_capabilities = {
|
||||
full_punch_interval = 1.0,
|
||||
@ -65,7 +94,9 @@ minetest.register_tool("basetools:pick_mese", {
|
||||
|
||||
-- This should break after only 1 use
|
||||
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",
|
||||
tool_capabilities = {
|
||||
max_drop_level=0,
|
||||
@ -76,7 +107,8 @@ minetest.register_tool("basetools:pick_dirt", {
|
||||
})
|
||||
|
||||
minetest.register_tool("basetools:pick_wood", {
|
||||
description = "Wooden Pickaxe",
|
||||
description = "Wooden Pickaxe".."\n"..
|
||||
"Digs cracky=3",
|
||||
inventory_image = "basetools_woodpick.png",
|
||||
tool_capabilities = {
|
||||
max_drop_level=0,
|
||||
@ -86,7 +118,8 @@ minetest.register_tool("basetools:pick_wood", {
|
||||
},
|
||||
})
|
||||
minetest.register_tool("basetools:pick_stone", {
|
||||
description = "Stone Pickaxe",
|
||||
description = "Stone Pickaxe".."\n"..
|
||||
"Digs cracky=2..3",
|
||||
inventory_image = "basetools_stonepick.png",
|
||||
tool_capabilities = {
|
||||
max_drop_level=0,
|
||||
@ -96,7 +129,8 @@ minetest.register_tool("basetools:pick_stone", {
|
||||
},
|
||||
})
|
||||
minetest.register_tool("basetools:pick_steel", {
|
||||
description = "Steel Pickaxe",
|
||||
description = "Steel Pickaxe".."\n"..
|
||||
"Digs cracky=1..3",
|
||||
inventory_image = "basetools_steelpick.png",
|
||||
tool_capabilities = {
|
||||
max_drop_level=1,
|
||||
@ -106,7 +140,9 @@ minetest.register_tool("basetools:pick_steel", {
|
||||
},
|
||||
})
|
||||
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",
|
||||
tool_capabilities = {
|
||||
max_drop_level=1,
|
||||
@ -116,7 +152,9 @@ minetest.register_tool("basetools:pick_steel_l1", {
|
||||
},
|
||||
})
|
||||
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",
|
||||
tool_capabilities = {
|
||||
max_drop_level=1,
|
||||
@ -131,7 +169,8 @@ minetest.register_tool("basetools:pick_steel_l2", {
|
||||
--
|
||||
|
||||
minetest.register_tool("basetools:shovel_wood", {
|
||||
description = "Wooden Shovel",
|
||||
description = "Wooden Shovel".."\n"..
|
||||
"Digs crumbly=3",
|
||||
inventory_image = "basetools_woodshovel.png",
|
||||
tool_capabilities = {
|
||||
max_drop_level=0,
|
||||
@ -141,7 +180,8 @@ minetest.register_tool("basetools:shovel_wood", {
|
||||
},
|
||||
})
|
||||
minetest.register_tool("basetools:shovel_stone", {
|
||||
description = "Stone Shovel",
|
||||
description = "Stone Shovel".."\n"..
|
||||
"Digs crumbly=2..3",
|
||||
inventory_image = "basetools_stoneshovel.png",
|
||||
tool_capabilities = {
|
||||
max_drop_level=0,
|
||||
@ -151,7 +191,8 @@ minetest.register_tool("basetools:shovel_stone", {
|
||||
},
|
||||
})
|
||||
minetest.register_tool("basetools:shovel_steel", {
|
||||
description = "Steel Shovel",
|
||||
description = "Steel Shovel".."\n"..
|
||||
"Digs crumbly=1..3",
|
||||
inventory_image = "basetools_steelshovel.png",
|
||||
tool_capabilities = {
|
||||
max_drop_level=1,
|
||||
@ -166,7 +207,8 @@ minetest.register_tool("basetools:shovel_steel", {
|
||||
--
|
||||
|
||||
minetest.register_tool("basetools:axe_wood", {
|
||||
description = "Wooden Axe",
|
||||
description = "Wooden Axe".."\n"..
|
||||
"Digs choppy=3",
|
||||
inventory_image = "basetools_woodaxe.png",
|
||||
tool_capabilities = {
|
||||
max_drop_level=0,
|
||||
@ -176,7 +218,8 @@ minetest.register_tool("basetools:axe_wood", {
|
||||
},
|
||||
})
|
||||
minetest.register_tool("basetools:axe_stone", {
|
||||
description = "Stone Axe",
|
||||
description = "Stone Axe".."\n"..
|
||||
"Digs choppy=2..3",
|
||||
inventory_image = "basetools_stoneaxe.png",
|
||||
tool_capabilities = {
|
||||
max_drop_level=0,
|
||||
@ -186,7 +229,8 @@ minetest.register_tool("basetools:axe_stone", {
|
||||
},
|
||||
})
|
||||
minetest.register_tool("basetools:axe_steel", {
|
||||
description = "Steel Axe",
|
||||
description = "Steel Axe".."\n"..
|
||||
"Digs choppy=1..3",
|
||||
inventory_image = "basetools_steelaxe.png",
|
||||
tool_capabilities = {
|
||||
max_drop_level=1,
|
||||
@ -201,7 +245,8 @@ minetest.register_tool("basetools:axe_steel", {
|
||||
--
|
||||
|
||||
minetest.register_tool("basetools:shears_wood", {
|
||||
description = "Wooden Shears",
|
||||
description = "Wooden Shears".."\n"..
|
||||
"Digs snappy=3",
|
||||
inventory_image = "basetools_woodshears.png",
|
||||
tool_capabilities = {
|
||||
max_drop_level=0,
|
||||
@ -211,7 +256,8 @@ minetest.register_tool("basetools:shears_wood", {
|
||||
},
|
||||
})
|
||||
minetest.register_tool("basetools:shears_stone", {
|
||||
description = "Stone Shears",
|
||||
description = "Stone Shears".."\n"..
|
||||
"Digs snappy=2..3",
|
||||
inventory_image = "basetools_stoneshears.png",
|
||||
tool_capabilities = {
|
||||
max_drop_level=0,
|
||||
@ -221,7 +267,8 @@ minetest.register_tool("basetools:shears_stone", {
|
||||
},
|
||||
})
|
||||
minetest.register_tool("basetools:shears_steel", {
|
||||
description = "Steel Shears",
|
||||
description = "Steel Shears".."\n"..
|
||||
"Digs snappy=1..3",
|
||||
inventory_image = "basetools_steelshears.png",
|
||||
tool_capabilities = {
|
||||
max_drop_level=1,
|
||||
@ -236,7 +283,8 @@ minetest.register_tool("basetools:shears_steel", {
|
||||
--
|
||||
|
||||
minetest.register_tool("basetools:sword_wood", {
|
||||
description = "Wooden Sword",
|
||||
description = "Wooden Sword".."\n"..
|
||||
"Damage: fleshy=2",
|
||||
inventory_image = "basetools_woodsword.png",
|
||||
tool_capabilities = {
|
||||
full_punch_interval = 1.0,
|
||||
@ -244,7 +292,8 @@ minetest.register_tool("basetools:sword_wood", {
|
||||
}
|
||||
})
|
||||
minetest.register_tool("basetools:sword_stone", {
|
||||
description = "Stone Sword",
|
||||
description = "Stone Sword".."\n"..
|
||||
"Damage: fleshy=4",
|
||||
inventory_image = "basetools_stonesword.png",
|
||||
tool_capabilities = {
|
||||
full_punch_interval = 1.0,
|
||||
@ -253,7 +302,8 @@ minetest.register_tool("basetools:sword_stone", {
|
||||
}
|
||||
})
|
||||
minetest.register_tool("basetools:sword_steel", {
|
||||
description = "Steel Sword",
|
||||
description = "Steel Sword".."\n"..
|
||||
"Damage: fleshy=6",
|
||||
inventory_image = "basetools_steelsword.png",
|
||||
tool_capabilities = {
|
||||
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
|
||||
minetest.register_tool("basetools:sword_fire", {
|
||||
description = "Fire Sword",
|
||||
description = "Fire Sword".."\n"..
|
||||
"Damage: icy=6",
|
||||
inventory_image = "basetools_firesword.png",
|
||||
tool_capabilities = {
|
||||
full_punch_interval = 1.0,
|
||||
@ -273,12 +324,13 @@ minetest.register_tool("basetools:sword_fire", {
|
||||
}
|
||||
})
|
||||
minetest.register_tool("basetools:sword_ice", {
|
||||
description = "Ice Sword",
|
||||
description = "Ice Sword".."\n"..
|
||||
"Damage: fiery=6",
|
||||
inventory_image = "basetools_icesword.png",
|
||||
tool_capabilities = {
|
||||
full_punch_interval = 1.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
|
||||
--
|
||||
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",
|
||||
tool_capabilities = {
|
||||
full_punch_interval = 0.5,
|
||||
|
@ -1,7 +1,8 @@
|
||||
-- Bucket: Punch liquid source or flowing liquid to collect it
|
||||
|
||||
minetest.register_tool("bucket:bucket", {
|
||||
description = "Bucket",
|
||||
description = "Bucket".."\n"..
|
||||
"Picks up liquid nodes",
|
||||
inventory_image = "bucket.png",
|
||||
stack_max = 1,
|
||||
liquids_pointable = true,
|
||||
|
@ -1,5 +1,6 @@
|
||||
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",
|
||||
"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"},
|
||||
|
@ -43,7 +43,8 @@ local function get_chest_formspec(page)
|
||||
end
|
||||
|
||||
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",
|
||||
"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"},
|
||||
|
@ -214,3 +214,6 @@ minetest.register_chatcommand("test_place_nodes", {
|
||||
end,
|
||||
})
|
||||
|
||||
core.register_on_chatcommand(function(name, command, params)
|
||||
minetest.log("caught command '"..command.."', issued by '"..name.."'. Parameters: '"..params.."'")
|
||||
end)
|
||||
|
@ -44,7 +44,8 @@ minetest.register_node("experimental:callback_node", {
|
||||
})
|
||||
|
||||
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",
|
||||
groups = { testtool = 1, disable_repair = 1 },
|
||||
on_use = function(itemstack, user, pointed_thing)
|
||||
@ -67,7 +68,8 @@ minetest.register_tool("experimental:privatizer", {
|
||||
})
|
||||
|
||||
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",
|
||||
groups = { testtool = 1, disable_repair = 1 },
|
||||
on_use = function(itemstack, user, pointed_thing)
|
||||
|
@ -107,7 +107,8 @@ minetest.register_node("soundstuff:footstep_climbable", {
|
||||
|
||||
|
||||
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",
|
||||
on_use = minetest.item_eat(0),
|
||||
sound = {
|
||||
@ -116,7 +117,9 @@ minetest.register_craftitem("soundstuff:eat", {
|
||||
})
|
||||
|
||||
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",
|
||||
sound = {
|
||||
breaks = { name = "soundstuff_mono", gain = 1.0 },
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
local phasearmor = {
|
||||
[0]={icy=100},
|
||||
[1]={firy=100},
|
||||
[1]={fiery=100},
|
||||
[2]={fleshy=100},
|
||||
[3]={immortal=1},
|
||||
[4]={punch_operable=1},
|
||||
|
@ -68,7 +68,7 @@ minetest.register_entity("testentities:mesh_unshaded", {
|
||||
|
||||
-- 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", {
|
||||
initial_properties = {
|
||||
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},
|
||||
},
|
||||
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,
|
||||
})
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user