mirror of
https://github.com/luanti-org/luanti.git
synced 2025-07-02 16:38:41 +00:00
Merge branch 'master' into master
This commit is contained in:
commit
b5aab1bcc7
1196 changed files with 57421 additions and 35855 deletions
3
.gitattributes
vendored
3
.gitattributes
vendored
|
@ -3,3 +3,6 @@
|
||||||
|
|
||||||
*.cpp diff=cpp
|
*.cpp diff=cpp
|
||||||
*.h diff=cpp
|
*.h diff=cpp
|
||||||
|
|
||||||
|
*.gltf binary
|
||||||
|
*.x binary
|
||||||
|
|
12
.github/CONTRIBUTING.md
vendored
12
.github/CONTRIBUTING.md
vendored
|
@ -37,7 +37,7 @@ Contributions are welcome! Here's how you can help:
|
||||||
[Lua](http://dev.minetest.net/Lua_code_style_guidelines) code style guidelines.
|
[Lua](http://dev.minetest.net/Lua_code_style_guidelines) code style guidelines.
|
||||||
- Check your code works as expected and document any changes to the Lua API.
|
- Check your code works as expected and document any changes to the Lua API.
|
||||||
- To avoid conflicting changes between contributions, do not do the following manually. They will be done before each release.
|
- To avoid conflicting changes between contributions, do not do the following manually. They will be done before each release.
|
||||||
- Run `updatepo.sh` or update `minetest.po{,t}` even if your code adds new translatable strings.
|
- Run `updatepo.sh` or update `luanti.po{,t}` even if your code adds new translatable strings.
|
||||||
- Update `minetest.conf.example` and `settings_translation_file.cpp` even if your code adds new core settings.
|
- Update `minetest.conf.example` and `settings_translation_file.cpp` even if your code adds new core settings.
|
||||||
|
|
||||||
4. Commit & [push](https://help.github.com/articles/pushing-to-a-remote/) your changes to a new branch (not `master`, one change per branch)
|
4. Commit & [push](https://help.github.com/articles/pushing-to-a-remote/) your changes to a new branch (not `master`, one change per branch)
|
||||||
|
@ -83,7 +83,7 @@ a stable release is on the way.
|
||||||
- Error logs (check the bottom of the `debug.txt` file).
|
- Error logs (check the bottom of the `debug.txt` file).
|
||||||
- Screenshots.
|
- Screenshots.
|
||||||
- Ways you have tried to solve the issue, and whether they worked or not.
|
- Ways you have tried to solve the issue, and whether they worked or not.
|
||||||
- Your Minetest version and the content (games, mods or texture packs) you have installed.
|
- Your Luanti version and the content (games, mods or texture packs) you have installed.
|
||||||
- Your platform (e.g. Windows 10 or Ubuntu 15.04 x64).
|
- Your platform (e.g. Windows 10 or Ubuntu 15.04 x64).
|
||||||
|
|
||||||
After reporting you should aim to answer questions or clarifications as this
|
After reporting you should aim to answer questions or clarifications as this
|
||||||
|
@ -99,7 +99,7 @@ possible.
|
||||||
|
|
||||||
## Translations
|
## Translations
|
||||||
|
|
||||||
The core translations of Minetest are performed using Weblate. You can access
|
The core translations of Luanti are performed using Weblate. You can access
|
||||||
the project page with a list of current languages
|
the project page with a list of current languages
|
||||||
[here](https://hosted.weblate.org/projects/minetest/minetest/).
|
[here](https://hosted.weblate.org/projects/minetest/minetest/).
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ translated by editing a `.tr` text file. See
|
||||||
|
|
||||||
## Donations
|
## Donations
|
||||||
|
|
||||||
If you'd like to monetarily support Minetest development, you can find donation
|
If you'd like to monetarily support Luanti development, you can find donation
|
||||||
methods on [our website](http://www.minetest.net/development/#donate).
|
methods on [our website](http://www.minetest.net/development/#donate).
|
||||||
|
|
||||||
# Maintaining
|
# Maintaining
|
||||||
|
@ -118,7 +118,7 @@ methods on [our website](http://www.minetest.net/development/#donate).
|
||||||
* This is a concise version of the
|
* This is a concise version of the
|
||||||
[Rules & Guidelines](http://dev.minetest.net/Category:Rules_and_Guidelines) on the developer wiki.*
|
[Rules & Guidelines](http://dev.minetest.net/Category:Rules_and_Guidelines) on the developer wiki.*
|
||||||
|
|
||||||
These notes are for those who have push access Minetest (core developers / maintainers).
|
These notes are for those who have push access Luanti (core developers / maintainers).
|
||||||
|
|
||||||
- See the [project organisation](http://dev.minetest.net/Organisation) for the people involved.
|
- See the [project organisation](http://dev.minetest.net/Organisation) for the people involved.
|
||||||
|
|
||||||
|
@ -169,4 +169,4 @@ Submit a :+1: (+1) or "Looks good" comment to show you believe the pull-request
|
||||||
|
|
||||||
## Releasing a new version
|
## Releasing a new version
|
||||||
|
|
||||||
*Refer to [dev.minetest.net/Releasing_Minetest](http://dev.minetest.net/Releasing_Minetest)*
|
*Refer to [dev.minetest.net/Releasing_Luanti](https://dev.minetest.net/Releasing_Luanti)*
|
||||||
|
|
29
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
29
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
|
@ -6,22 +6,24 @@ body:
|
||||||
attributes:
|
attributes:
|
||||||
value: |
|
value: |
|
||||||
Please note the following:
|
Please note the following:
|
||||||
1. **Please update your Minetest Engine to the latest stable or dev version** before submitting bug reports. Make sure the bug is still reproducible on the latest version.
|
|
||||||
2. This page is for reporting the bugs of **the engine itself**. For bugs in a particular game, please [search for the game in the ContentDB](https://content.minetest.net/packages/?type=game) and submit a bug report in their issue trackers.
|
1. **Please update Luanti to the latest stable or dev version** before submitting bug reports. Make sure the bug is still reproducible on the latest version.
|
||||||
* For example, you can submit issues about the Minetest Game (the official game of Minetest) [in its own repository](https://github.com/minetest/minetest_game/issues).
|
2. This page is for reporting the bugs of **the engine itself**. For bugs in a particular game, please [search for the game in the ContentDB](https://content.luanti.org/packages/?type=game) and submit a bug report in their issue trackers.
|
||||||
|
* For example, you can submit issues about the Minetest Game [in its own repository](https://github.com/minetest/minetest_game/issues).
|
||||||
3. Please provide as many details as possible for us to spot the problem quicker.
|
3. Please provide as many details as possible for us to spot the problem quicker.
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: Minetest version
|
label: Luanti version
|
||||||
description: |
|
description: |
|
||||||
Paste the Minetest version below.
|
Paste the Luanti version below.
|
||||||
If you are on a dev version, please also indicate the git commit hash.
|
If you are on a dev version, please also indicate the git commit hash.
|
||||||
Refer to the "About" tab of the menu or run `minetest --version` on the command line.
|
Refer to the "About" tab of the menu or run `luanti --version` on the command line.
|
||||||
placeholder: |
|
placeholder: |
|
||||||
Example:
|
Example:
|
||||||
Minetest 5.7.0-dev-ca13c51 (Linux)
|
Luanti 5.10.0-3ad6aee9b (Linux)
|
||||||
Using Irrlicht 1.9.0mt9
|
Using LuaJIT 2.1.1727870382
|
||||||
Using LuaJIT 2.1.0-beta3
|
Built by GCC 14.2
|
||||||
|
Running on Linux/6.11.5 x86_64
|
||||||
BUILD_TYPE=Release
|
BUILD_TYPE=Release
|
||||||
RUN_IN_PLACE=1
|
RUN_IN_PLACE=1
|
||||||
USE_CURL=1
|
USE_CURL=1
|
||||||
|
@ -32,13 +34,6 @@ body:
|
||||||
render: "true"
|
render: "true"
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: input
|
|
||||||
attributes:
|
|
||||||
label: Irrlicht device
|
|
||||||
description:
|
|
||||||
placeholder: "Example: X11"
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: input
|
- type: input
|
||||||
attributes:
|
attributes:
|
||||||
label: Operating system and version
|
label: Operating system and version
|
||||||
|
@ -67,7 +62,7 @@ body:
|
||||||
attributes:
|
attributes:
|
||||||
label: Active renderer
|
label: Active renderer
|
||||||
description: You can find this in the "About" tab in the main menu.
|
description: You can find this in the "About" tab in the main menu.
|
||||||
placeholder: "Example: OpenGL 4.6.0"
|
placeholder: "Example: ES 3.2 / ogles2 / X11"
|
||||||
validations:
|
validations:
|
||||||
required: false
|
required: false
|
||||||
- type: textarea
|
- type: textarea
|
||||||
|
|
2
.github/ISSUE_TEMPLATE/config.yml
vendored
2
.github/ISSUE_TEMPLATE/config.yml
vendored
|
@ -4,5 +4,5 @@ contact_links:
|
||||||
url: https://github.com/minetest/minetest_game/issues/new/choose
|
url: https://github.com/minetest/minetest_game/issues/new/choose
|
||||||
about: Only submit issues of the engine in this repository's issue tracker. Submit those of Minetest Game in its own issue tracker.
|
about: Only submit issues of the engine in this repository's issue tracker. Submit those of Minetest Game in its own issue tracker.
|
||||||
- name: Search for issue trackers of third-party games
|
- name: Search for issue trackers of third-party games
|
||||||
url: https://content.minetest.net/packages/?type=game
|
url: https://content.luanti.org/packages/?type=game
|
||||||
about: For issues of third-party games, search for the game in the ContentDB and then submit an issue in their issue tracker.
|
about: For issues of third-party games, search for the game in the ContentDB and then submit an issue in their issue tracker.
|
||||||
|
|
2
.github/ISSUE_TEMPLATE/feature_request.yaml
vendored
2
.github/ISSUE_TEMPLATE/feature_request.yaml
vendored
|
@ -7,7 +7,7 @@ body:
|
||||||
value: |
|
value: |
|
||||||
Please note the following:
|
Please note the following:
|
||||||
1. Only submit a feature request if the feature does not exist on the latest dev version.
|
1. Only submit a feature request if the feature does not exist on the latest dev version.
|
||||||
2. This page is for suggesting changes to **the engine itself**. To suggest changes to games, please [search for the game in the ContentDB](https://content.minetest.net/packages/?type=game) and submit a feature request in their issue trackers.
|
2. This page is for suggesting changes to **the engine itself**. To suggest changes to games, please [search for the game in the ContentDB](https://content.luanti.org/packages/?type=game) and submit a feature request in their issue trackers.
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: Problem
|
label: Problem
|
||||||
|
|
2
.github/SECURITY.md
vendored
2
.github/SECURITY.md
vendored
|
@ -14,7 +14,7 @@ to give us time to fix them. You can do that by emailing one of the following ad
|
||||||
* rubenwardy@minetest.net
|
* rubenwardy@minetest.net
|
||||||
|
|
||||||
Depending on severity, we will either create a private issue for the vulnerability
|
Depending on severity, we will either create a private issue for the vulnerability
|
||||||
and release a patch version of Minetest, or give you permission to file the issue publicly.
|
and release a patch version of Luanti, or give you permission to file the issue publicly.
|
||||||
|
|
||||||
For more information on the justification of this policy, see
|
For more information on the justification of this policy, see
|
||||||
[Responsible Disclosure](https://en.wikipedia.org/wiki/Responsible_disclosure).
|
[Responsible Disclosure](https://en.wikipedia.org/wiki/Responsible_disclosure).
|
||||||
|
|
12
.github/workflows/android.yml
vendored
12
.github/workflows/android.yml
vendored
|
@ -12,6 +12,7 @@ on:
|
||||||
- 'irr/**.cpp'
|
- 'irr/**.cpp'
|
||||||
- '**/CMakeLists.txt'
|
- '**/CMakeLists.txt'
|
||||||
- 'cmake/Modules/**'
|
- 'cmake/Modules/**'
|
||||||
|
- 'po/**.po'
|
||||||
- 'android/**'
|
- 'android/**'
|
||||||
- '.github/workflows/android.yml'
|
- '.github/workflows/android.yml'
|
||||||
pull_request:
|
pull_request:
|
||||||
|
@ -24,6 +25,7 @@ on:
|
||||||
- 'irr/**.cpp'
|
- 'irr/**.cpp'
|
||||||
- '**/CMakeLists.txt'
|
- '**/CMakeLists.txt'
|
||||||
- 'cmake/Modules/**'
|
- 'cmake/Modules/**'
|
||||||
|
- 'po/**.po'
|
||||||
- 'android/**'
|
- 'android/**'
|
||||||
- '.github/workflows/android.yml'
|
- '.github/workflows/android.yml'
|
||||||
|
|
||||||
|
@ -50,25 +52,25 @@ jobs:
|
||||||
- name: Save AAB artifact
|
- name: Save AAB artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: Minetest-release.aab
|
name: Luanti-release.aab
|
||||||
path: android/app/build/outputs/bundle/release/app-release.aab
|
path: android/app/build/outputs/bundle/release/app-release.aab
|
||||||
- name: Save armeabi artifact
|
- name: Save armeabi artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: Minetest-armeabi-v7a.apk
|
name: Luanti-armeabi-v7a.apk
|
||||||
path: android/app/build/outputs/apk/release/app-armeabi-v7a-release-unsigned.apk
|
path: android/app/build/outputs/apk/release/app-armeabi-v7a-release-unsigned.apk
|
||||||
- name: Save arm64 artifact
|
- name: Save arm64 artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: Minetest-arm64-v8a.apk
|
name: Luanti-arm64-v8a.apk
|
||||||
path: android/app/build/outputs/apk/release/app-arm64-v8a-release-unsigned.apk
|
path: android/app/build/outputs/apk/release/app-arm64-v8a-release-unsigned.apk
|
||||||
- name: Save x86 artifact
|
- name: Save x86 artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: Minetest-x86.apk
|
name: Luanti-x86.apk
|
||||||
path: android/app/build/outputs/apk/release/app-x86-release-unsigned.apk
|
path: android/app/build/outputs/apk/release/app-x86-release-unsigned.apk
|
||||||
- name: Save x86_64 artifact
|
- name: Save x86_64 artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: Minetest-x86_64.apk
|
name: Luanti-x86_64.apk
|
||||||
path: android/app/build/outputs/apk/release/app-x86_64-release-unsigned.apk
|
path: android/app/build/outputs/apk/release/app-x86_64-release-unsigned.apk
|
||||||
|
|
6
.github/workflows/docker_image.yml
vendored
6
.github/workflows/docker_image.yml
vendored
|
@ -72,8 +72,8 @@ jobs:
|
||||||
with:
|
with:
|
||||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||||
labels: |
|
labels: |
|
||||||
org.opencontainers.image.title=Minetest
|
org.opencontainers.image.title=Luanti
|
||||||
org.opencontainers.image.vendor=Minetest
|
org.opencontainers.image.vendor=Luanti
|
||||||
org.opencontainers.image.licenses=LGPL-2.1-only
|
org.opencontainers.image.licenses=LGPL-2.1-only
|
||||||
|
|
||||||
# Build and push Docker image
|
# Build and push Docker image
|
||||||
|
@ -94,5 +94,5 @@ jobs:
|
||||||
|
|
||||||
- name: Test Docker Image
|
- name: Test Docker Image
|
||||||
run: |
|
run: |
|
||||||
docker run --rm $(cut -d, -f1 <<<"$DOCKER_METADATA_OUTPUT_TAGS") minetestserver --version
|
docker run --rm $(cut -d, -f1 <<<"$DOCKER_METADATA_OUTPUT_TAGS") luantiserver --version
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
25
.github/workflows/linux.yml
vendored
25
.github/workflows/linux.yml
vendored
|
@ -12,9 +12,8 @@ on:
|
||||||
- 'irr/**.cpp'
|
- 'irr/**.cpp'
|
||||||
- '**/CMakeLists.txt'
|
- '**/CMakeLists.txt'
|
||||||
- 'cmake/Modules/**'
|
- 'cmake/Modules/**'
|
||||||
|
- 'po/**.po'
|
||||||
- 'util/ci/**'
|
- 'util/ci/**'
|
||||||
- 'Dockerfile'
|
|
||||||
- '.dockerignore'
|
|
||||||
- '.github/workflows/linux.yml'
|
- '.github/workflows/linux.yml'
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
|
@ -26,9 +25,8 @@ on:
|
||||||
- 'irr/**.cpp'
|
- 'irr/**.cpp'
|
||||||
- '**/CMakeLists.txt'
|
- '**/CMakeLists.txt'
|
||||||
- 'cmake/Modules/**'
|
- 'cmake/Modules/**'
|
||||||
|
- 'po/**.po'
|
||||||
- 'util/ci/**'
|
- 'util/ci/**'
|
||||||
- 'Dockerfile'
|
|
||||||
- '.dockerignore'
|
|
||||||
- '.github/workflows/linux.yml'
|
- '.github/workflows/linux.yml'
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
@ -51,10 +49,12 @@ jobs:
|
||||||
env:
|
env:
|
||||||
CC: gcc-7
|
CC: gcc-7
|
||||||
CXX: g++-7
|
CXX: g++-7
|
||||||
|
# Test fallback SHA implementations
|
||||||
|
CMAKE_FLAGS: '-DENABLE_OPENSSL=0'
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: |
|
run: |
|
||||||
./bin/minetest --run-unittests
|
./bin/luanti --run-unittests
|
||||||
|
|
||||||
# Current gcc version
|
# Current gcc version
|
||||||
gcc_14:
|
gcc_14:
|
||||||
|
@ -78,7 +78,7 @@ jobs:
|
||||||
mkdir nowrite
|
mkdir nowrite
|
||||||
chmod a-w nowrite
|
chmod a-w nowrite
|
||||||
cd nowrite
|
cd nowrite
|
||||||
../bin/minetest --run-unittests
|
../bin/luanti --run-unittests
|
||||||
|
|
||||||
# Older clang version (should be close to our minimum supported version)
|
# Older clang version (should be close to our minimum supported version)
|
||||||
clang_7:
|
clang_7:
|
||||||
|
@ -88,7 +88,7 @@ jobs:
|
||||||
- name: Install deps
|
- name: Install deps
|
||||||
run: |
|
run: |
|
||||||
source ./util/ci/common.sh
|
source ./util/ci/common.sh
|
||||||
install_linux_deps clang-7 llvm
|
install_linux_deps clang-7 llvm-7
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
|
@ -100,7 +100,12 @@ jobs:
|
||||||
|
|
||||||
- name: Unittest
|
- name: Unittest
|
||||||
run: |
|
run: |
|
||||||
./bin/minetest --run-unittests
|
./bin/luanti --run-unittests
|
||||||
|
|
||||||
|
# Do this here because we have ASan and error paths are sensitive to dangling pointers
|
||||||
|
- name: Test error cases
|
||||||
|
run: |
|
||||||
|
./util/test_error_cases.sh
|
||||||
|
|
||||||
# Current clang version
|
# Current clang version
|
||||||
clang_18:
|
clang_18:
|
||||||
|
@ -121,7 +126,7 @@ jobs:
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: |
|
run: |
|
||||||
./bin/minetest --run-unittests
|
./bin/luanti --run-unittests
|
||||||
|
|
||||||
- name: Integration test + devtest
|
- name: Integration test + devtest
|
||||||
run: |
|
run: |
|
||||||
|
@ -151,4 +156,4 @@ jobs:
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: |
|
run: |
|
||||||
./bin/minetestserver --run-unittests
|
./bin/luantiserver --run-unittests
|
||||||
|
|
53
.github/workflows/macos.yml
vendored
53
.github/workflows/macos.yml
vendored
|
@ -13,6 +13,7 @@ on:
|
||||||
- 'irr/**.mm' # Objective-C(++)
|
- 'irr/**.mm' # Objective-C(++)
|
||||||
- '**/CMakeLists.txt'
|
- '**/CMakeLists.txt'
|
||||||
- 'cmake/Modules/**'
|
- 'cmake/Modules/**'
|
||||||
|
- 'po/**.po'
|
||||||
- '.github/workflows/macos.yml'
|
- '.github/workflows/macos.yml'
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
|
@ -25,12 +26,13 @@ on:
|
||||||
- 'irr/**.mm' # Objective-C(++)
|
- 'irr/**.mm' # Objective-C(++)
|
||||||
- '**/CMakeLists.txt'
|
- '**/CMakeLists.txt'
|
||||||
- 'cmake/Modules/**'
|
- 'cmake/Modules/**'
|
||||||
|
- 'po/**.po'
|
||||||
- '.github/workflows/macos.yml'
|
- '.github/workflows/macos.yml'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build-intel-macos:
|
||||||
# use lowest possible macOS running on x86_64 to support more users
|
# use lowest possible macOS running on x86_64 supported by brew to support more users
|
||||||
runs-on: macos-12
|
runs-on: macos-13
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Install deps
|
- name: Install deps
|
||||||
|
@ -53,7 +55,7 @@ jobs:
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: |
|
run: |
|
||||||
./build/macos/minetest.app/Contents/MacOS/minetest --run-unittests
|
./build/macos/luanti.app/Contents/MacOS/luanti --run-unittests
|
||||||
|
|
||||||
# Zipping the built .app preserves permissions on the contained files,
|
# Zipping the built .app preserves permissions on the contained files,
|
||||||
# which the GitHub artifact pipeline would otherwise strip away.
|
# which the GitHub artifact pipeline would otherwise strip away.
|
||||||
|
@ -66,5 +68,46 @@ jobs:
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: minetest-macos
|
name: luanti-macos
|
||||||
path: ./build/macos/*.zip
|
path: ./build/macos/*.zip
|
||||||
|
build-arm-macos-xcode:
|
||||||
|
runs-on: macos-14
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Install deps
|
||||||
|
run: |
|
||||||
|
source ./util/ci/common.sh
|
||||||
|
install_macos_deps
|
||||||
|
# brew jsoncpp do not include libjsoncpp.a, and if installed header conflict caused build failure
|
||||||
|
brew uninstall jsoncpp
|
||||||
|
|
||||||
|
- name: Build with Cmake
|
||||||
|
run: |
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake .. \
|
||||||
|
-DCMAKE_OSX_DEPLOYMENT_TARGET=14 \
|
||||||
|
-DCMAKE_FIND_FRAMEWORK=LAST \
|
||||||
|
-DCMAKE_INSTALL_PREFIX=../build/macos/ \
|
||||||
|
-DRUN_IN_PLACE=FALSE -DENABLE_GETTEXT=TRUE \
|
||||||
|
-DENABLE_SYSTEM_JSONCPP=OFF
|
||||||
|
cmake --build . -j$(sysctl -n hw.logicalcpu)
|
||||||
|
make install
|
||||||
|
|
||||||
|
- name: Build and Archive with Xcode
|
||||||
|
run: |
|
||||||
|
mkdir build_xcode
|
||||||
|
cd build_xcode
|
||||||
|
../util/ci/build_xcode.sh
|
||||||
|
|
||||||
|
- name: Tests
|
||||||
|
run: |
|
||||||
|
mkdir -p "${HOME}/Library/Application Support/minetest/games/"
|
||||||
|
ln -s "${PWD}/games/devtest" "${HOME}/Library/Application Support/minetest/games/"
|
||||||
|
./build/macos/luanti.app/Contents/MacOS/luanti --run-unittests
|
||||||
|
./build_xcode/luanti.xcarchive/Products/Applications/luanti.app/Contents/MacOS/luanti --run-unittests
|
||||||
|
|
||||||
|
- name: Diff Resources
|
||||||
|
run: |
|
||||||
|
diff -rd ./build/macos/luanti.app/Contents/Resources ./build_xcode/build/Release/luanti.app/Contents/Resources || exit 1
|
||||||
|
diff -rd ./build/macos/luanti.app/Contents/Resources ./build_xcode/luanti.xcarchive/Products/Applications/luanti.app/Contents/Resources || exit 1
|
||||||
|
|
12
.github/workflows/windows.yml
vendored
12
.github/workflows/windows.yml
vendored
|
@ -12,6 +12,7 @@ on:
|
||||||
- 'irr/**.cpp'
|
- 'irr/**.cpp'
|
||||||
- '**/CMakeLists.txt'
|
- '**/CMakeLists.txt'
|
||||||
- 'cmake/Modules/**'
|
- 'cmake/Modules/**'
|
||||||
|
- 'po/**.po'
|
||||||
- 'util/buildbot/**'
|
- 'util/buildbot/**'
|
||||||
- 'misc/*.manifest'
|
- 'misc/*.manifest'
|
||||||
- '.github/workflows/windows.yml'
|
- '.github/workflows/windows.yml'
|
||||||
|
@ -25,6 +26,7 @@ on:
|
||||||
- 'irr/**.cpp'
|
- 'irr/**.cpp'
|
||||||
- '**/CMakeLists.txt'
|
- '**/CMakeLists.txt'
|
||||||
- 'cmake/Modules/**'
|
- 'cmake/Modules/**'
|
||||||
|
- 'po/**.po'
|
||||||
- 'util/buildbot/**'
|
- 'util/buildbot/**'
|
||||||
- 'misc/*.manifest'
|
- 'misc/*.manifest'
|
||||||
- '.github/workflows/windows.yml'
|
- '.github/workflows/windows.yml'
|
||||||
|
@ -56,8 +58,8 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
dest=$(mktemp -d)
|
dest=$(mktemp -d)
|
||||||
unzip -q -d "$dest" B/build/*.zip
|
unzip -q -d "$dest" B/build/*.zip
|
||||||
cd "$dest"/minetest-*-win*
|
cd "$dest"/luanti-*-win*
|
||||||
wine bin/minetest.exe --version
|
wine bin/luanti.exe --version
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
|
@ -103,7 +105,7 @@ jobs:
|
||||||
vcpkgGitCommitId: ${{ env.VCPKG_VERSION }}
|
vcpkgGitCommitId: ${{ env.VCPKG_VERSION }}
|
||||||
vcpkgTriplet: ${{ matrix.config.vcpkg_triplet }}
|
vcpkgTriplet: ${{ matrix.config.vcpkg_triplet }}
|
||||||
|
|
||||||
- name: Minetest CMake
|
- name: CMake
|
||||||
run: |
|
run: |
|
||||||
cmake ${{matrix.config.generator}} `
|
cmake ${{matrix.config.generator}} `
|
||||||
-DCMAKE_TOOLCHAIN_FILE="${{ github.workspace }}\vcpkg\scripts\buildsystems\vcpkg.cmake" `
|
-DCMAKE_TOOLCHAIN_FILE="${{ github.workspace }}\vcpkg\scripts\buildsystems\vcpkg.cmake" `
|
||||||
|
@ -113,13 +115,13 @@ jobs:
|
||||||
-DREQUIRE_LUAJIT=TRUE `
|
-DREQUIRE_LUAJIT=TRUE `
|
||||||
-DRUN_IN_PLACE=${{ contains(matrix.type, 'portable') }} .
|
-DRUN_IN_PLACE=${{ contains(matrix.type, 'portable') }} .
|
||||||
|
|
||||||
- name: Build Minetest
|
- name: Build
|
||||||
run: cmake --build . --config Release
|
run: cmake --build . --config Release
|
||||||
|
|
||||||
- name: Unittests
|
- name: Unittests
|
||||||
# need this workaround for stdout to work
|
# need this workaround for stdout to work
|
||||||
run: |
|
run: |
|
||||||
$proc = start .\bin\Release\minetest.exe --run-unittests -NoNewWindow -Wait -PassThru
|
$proc = start .\bin\Release\luanti.exe --run-unittests -NoNewWindow -Wait -PassThru
|
||||||
exit $proc.ExitCode
|
exit $proc.ExitCode
|
||||||
continue-on-error: true # FIXME!!
|
continue-on-error: true # FIXME!!
|
||||||
|
|
||||||
|
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -26,6 +26,7 @@ tags
|
||||||
!tags/
|
!tags/
|
||||||
gtags.files
|
gtags.files
|
||||||
.idea
|
.idea
|
||||||
|
.qtcreator/
|
||||||
# Codelite
|
# Codelite
|
||||||
*.project
|
*.project
|
||||||
# Visual Studio Code & plugins
|
# Visual Studio Code & plugins
|
||||||
|
@ -109,6 +110,8 @@ src/cmake_config_githash.h
|
||||||
*.layout
|
*.layout
|
||||||
*.o
|
*.o
|
||||||
*.a
|
*.a
|
||||||
|
*.dump
|
||||||
|
*.dmp
|
||||||
*.ninja
|
*.ninja
|
||||||
.ninja*
|
.ninja*
|
||||||
*.gch
|
*.gch
|
||||||
|
|
|
@ -15,6 +15,7 @@ read_globals = {
|
||||||
"fgettext", "fgettext_ne",
|
"fgettext", "fgettext_ne",
|
||||||
"vector",
|
"vector",
|
||||||
"VoxelArea",
|
"VoxelArea",
|
||||||
|
"VoxelManip",
|
||||||
"profiler",
|
"profiler",
|
||||||
"Settings",
|
"Settings",
|
||||||
"PerlinNoise", "PerlinNoiseMap",
|
"PerlinNoise", "PerlinNoiseMap",
|
||||||
|
|
1
.mailmap
1
.mailmap
|
@ -72,3 +72,4 @@ Lars Müller <appgurulars@gmx.de>
|
||||||
Lars Müller <appgurulars@gmx.de> <34514239+appgurueu@users.noreply.github.com>
|
Lars Müller <appgurulars@gmx.de> <34514239+appgurueu@users.noreply.github.com>
|
||||||
ROllerozxa <rollerozxa@voxelmanip.se>
|
ROllerozxa <rollerozxa@voxelmanip.se>
|
||||||
ROllerozxa <rollerozxa@voxelmanip.se> <temporaryemail4meh+github@gmail.com>
|
ROllerozxa <rollerozxa@voxelmanip.se> <temporaryemail4meh+github@gmail.com>
|
||||||
|
Ælla Chiana Moskopp <erle@dieweltistgarnichtso.net> <nils@dieweltistgarnichtso.net>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
cmake_minimum_required(VERSION 3.12)
|
cmake_minimum_required(VERSION 3.12)
|
||||||
|
|
||||||
# This can be read from ${PROJECT_NAME} after project() is called
|
# This can be read from ${PROJECT_NAME} after project() is called
|
||||||
project(minetest)
|
project(luanti)
|
||||||
set(PROJECT_NAME_CAPITALIZED "Minetest")
|
set(PROJECT_NAME_CAPITALIZED "Luanti")
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
|
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
|
||||||
|
@ -11,7 +11,7 @@ set(CLANG_MINIMUM_VERSION "7.0.1")
|
||||||
|
|
||||||
# You should not need to edit these manually, use util/bump_version.sh
|
# You should not need to edit these manually, use util/bump_version.sh
|
||||||
set(VERSION_MAJOR 5)
|
set(VERSION_MAJOR 5)
|
||||||
set(VERSION_MINOR 10)
|
set(VERSION_MINOR 11)
|
||||||
set(VERSION_PATCH 0)
|
set(VERSION_PATCH 0)
|
||||||
set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string")
|
set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string")
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
|
||||||
# Load default options for Android
|
# Load default options for Android
|
||||||
if(ANDROID)
|
if(ANDROID)
|
||||||
cmake_minimum_required(VERSION 3.20)
|
cmake_minimum_required(VERSION 3.20)
|
||||||
include(MinetestAndroidLibs)
|
include(AndroidLibs)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
@ -261,23 +261,27 @@ install(FILES "doc/world_format.md" DESTINATION "${DOCDIR}" COMPONENT "Docs")
|
||||||
install(FILES "minetest.conf.example" DESTINATION "${EXAMPLE_CONF_DIR}")
|
install(FILES "minetest.conf.example" DESTINATION "${EXAMPLE_CONF_DIR}")
|
||||||
|
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
install(FILES "doc/minetest.6" "doc/minetestserver.6" DESTINATION "${MANDIR}/man6")
|
install(FILES "doc/luanti.6" "doc/luantiserver.6" DESTINATION "${MANDIR}/man6")
|
||||||
install(FILES "misc/net.minetest.minetest.desktop" DESTINATION "${XDG_APPS_DIR}")
|
install(FILES "misc/net.minetest.minetest.desktop" DESTINATION "${XDG_APPS_DIR}")
|
||||||
install(FILES "misc/net.minetest.minetest.metainfo.xml" DESTINATION "${METAINFODIR}")
|
install(FILES "misc/net.minetest.minetest.metainfo.xml" DESTINATION "${METAINFODIR}")
|
||||||
install(FILES "misc/minetest.svg" DESTINATION "${ICONDIR}/hicolor/scalable/apps")
|
install(FILES "misc/luanti.svg" DESTINATION "${ICONDIR}/hicolor/scalable/apps")
|
||||||
install(FILES "misc/minetest-xorg-icon-128.png"
|
install(FILES "misc/luanti-xorg-icon-128.png"
|
||||||
DESTINATION "${ICONDIR}/hicolor/128x128/apps"
|
DESTINATION "${ICONDIR}/hicolor/128x128/apps"
|
||||||
RENAME "minetest.png")
|
RENAME "luanti.png")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
install(FILES "misc/minetest-icon.icns" DESTINATION "${SHAREDIR}")
|
install(FILES "misc/luanti-icon.icns" DESTINATION "${SHAREDIR}")
|
||||||
install(FILES "misc/Info.plist" DESTINATION "${BUNDLE_PATH}/Contents")
|
install(FILES "${CMAKE_BINARY_DIR}/Info.plist" DESTINATION "${BUNDLE_PATH}/Contents")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_GENERATOR STREQUAL "Xcode")
|
||||||
|
set(client_RESOURCES "${CMAKE_SOURCE_DIR}/misc/luanti-icon.icns")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Library pack
|
# Library pack
|
||||||
find_package(GMP REQUIRED)
|
find_package(GMP REQUIRED)
|
||||||
find_package(Json REQUIRED)
|
find_package(Json 1.0.0 REQUIRED)
|
||||||
find_package(Lua REQUIRED)
|
find_package(Lua REQUIRED)
|
||||||
if(NOT USE_LUAJIT)
|
if(NOT USE_LUAJIT)
|
||||||
add_subdirectory(lib/bitop)
|
add_subdirectory(lib/bitop)
|
||||||
|
@ -307,7 +311,7 @@ include(CPackComponent)
|
||||||
|
|
||||||
cpack_add_component(Docs
|
cpack_add_component(Docs
|
||||||
DISPLAY_NAME "Documentation"
|
DISPLAY_NAME "Documentation"
|
||||||
DESCRIPTION "Documentation about Minetest and Minetest modding"
|
DESCRIPTION "Documentation about ${PROJECT_NAME_CAPITALIZED} and ${PROJECT_NAME_CAPITALIZED} modding"
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
|
@ -331,7 +335,7 @@ if(WIN32)
|
||||||
set(CPACK_CREATE_DESKTOP_LINKS ${PROJECT_NAME})
|
set(CPACK_CREATE_DESKTOP_LINKS ${PROJECT_NAME})
|
||||||
set(CPACK_PACKAGING_INSTALL_PREFIX "/${PROJECT_NAME_CAPITALIZED}")
|
set(CPACK_PACKAGING_INSTALL_PREFIX "/${PROJECT_NAME_CAPITALIZED}")
|
||||||
|
|
||||||
set(CPACK_WIX_PRODUCT_ICON "${CMAKE_CURRENT_SOURCE_DIR}/misc/minetest-icon.ico")
|
set(CPACK_WIX_PRODUCT_ICON "${CMAKE_CURRENT_SOURCE_DIR}/misc/luanti-icon.ico")
|
||||||
# Supported languages can be found at
|
# Supported languages can be found at
|
||||||
# http://wixtoolset.org/documentation/manual/v3/wixui/wixui_localization.html
|
# http://wixtoolset.org/documentation/manual/v3/wixui/wixui_localization.html
|
||||||
#set(CPACK_WIX_CULTURES "ar-SA,bg-BG,ca-ES,hr-HR,cs-CZ,da-DK,nl-NL,en-US,et-EE,fi-FI,fr-FR,de-DE")
|
#set(CPACK_WIX_CULTURES "ar-SA,bg-BG,ca-ES,hr-HR,cs-CZ,da-DK,nl-NL,en-US,et-EE,fi-FI,fr-FR,de-DE")
|
||||||
|
|
2
CNAME
2
CNAME
|
@ -1 +1 @@
|
||||||
api.minetest.net
|
api.luanti.org
|
||||||
|
|
38
Dockerfile
38
Dockerfile
|
@ -32,22 +32,22 @@ RUN git clone --recursive https://github.com/jupp0r/prometheus-cpp && \
|
||||||
|
|
||||||
FROM dev as builder
|
FROM dev as builder
|
||||||
|
|
||||||
COPY .git /usr/src/minetest/.git
|
COPY .git /usr/src/luanti/.git
|
||||||
COPY CMakeLists.txt /usr/src/minetest/CMakeLists.txt
|
COPY CMakeLists.txt /usr/src/luanti/CMakeLists.txt
|
||||||
COPY README.md /usr/src/minetest/README.md
|
COPY README.md /usr/src/luanti/README.md
|
||||||
COPY minetest.conf.example /usr/src/minetest/minetest.conf.example
|
COPY minetest.conf.example /usr/src/luanti/minetest.conf.example
|
||||||
COPY builtin /usr/src/minetest/builtin
|
COPY builtin /usr/src/luanti/builtin
|
||||||
COPY cmake /usr/src/minetest/cmake
|
COPY cmake /usr/src/luanti/cmake
|
||||||
COPY doc /usr/src/minetest/doc
|
COPY doc /usr/src/luanti/doc
|
||||||
COPY fonts /usr/src/minetest/fonts
|
COPY fonts /usr/src/luanti/fonts
|
||||||
COPY lib /usr/src/minetest/lib
|
COPY lib /usr/src/luanti/lib
|
||||||
COPY misc /usr/src/minetest/misc
|
COPY misc /usr/src/luanti/misc
|
||||||
COPY po /usr/src/minetest/po
|
COPY po /usr/src/luanti/po
|
||||||
COPY src /usr/src/minetest/src
|
COPY src /usr/src/luanti/src
|
||||||
COPY irr /usr/src/minetest/irr
|
COPY irr /usr/src/luanti/irr
|
||||||
COPY textures /usr/src/minetest/textures
|
COPY textures /usr/src/luanti/textures
|
||||||
|
|
||||||
WORKDIR /usr/src/minetest
|
WORKDIR /usr/src/luanti
|
||||||
RUN cmake -B build \
|
RUN cmake -B build \
|
||||||
-DCMAKE_INSTALL_PREFIX=/usr/local \
|
-DCMAKE_INSTALL_PREFIX=/usr/local \
|
||||||
-DCMAKE_BUILD_TYPE=Release \
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
@ -68,9 +68,9 @@ RUN apk add --no-cache curl gmp libstdc++ libgcc libpq jsoncpp zstd-libs \
|
||||||
|
|
||||||
WORKDIR /var/lib/minetest
|
WORKDIR /var/lib/minetest
|
||||||
|
|
||||||
COPY --from=builder /usr/local/share/minetest /usr/local/share/minetest
|
COPY --from=builder /usr/local/share/luanti /usr/local/share/luanti
|
||||||
COPY --from=builder /usr/local/bin/minetestserver /usr/local/bin/minetestserver
|
COPY --from=builder /usr/local/bin/luantiserver /usr/local/bin/luantiserver
|
||||||
COPY --from=builder /usr/local/share/doc/minetest/minetest.conf.example /etc/minetest/minetest.conf
|
COPY --from=builder /usr/local/share/doc/luanti/minetest.conf.example /etc/minetest/minetest.conf
|
||||||
COPY --from=builder /usr/local/lib/libspatialindex* /usr/local/lib/
|
COPY --from=builder /usr/local/lib/libspatialindex* /usr/local/lib/
|
||||||
COPY --from=builder /usr/local/lib/libluajit* /usr/local/lib/
|
COPY --from=builder /usr/local/lib/libluajit* /usr/local/lib/
|
||||||
USER minetest:minetest
|
USER minetest:minetest
|
||||||
|
@ -78,5 +78,5 @@ USER minetest:minetest
|
||||||
EXPOSE 30000/udp 30000/tcp
|
EXPOSE 30000/udp 30000/tcp
|
||||||
VOLUME /var/lib/minetest/ /etc/minetest/
|
VOLUME /var/lib/minetest/ /etc/minetest/
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/local/bin/minetestserver"]
|
ENTRYPOINT ["/usr/local/bin/luantiserver"]
|
||||||
CMD ["--config", "/etc/minetest/minetest.conf"]
|
CMD ["--config", "/etc/minetest/minetest.conf"]
|
||||||
|
|
33
LICENSE.txt
33
LICENSE.txt
|
@ -1,8 +1,8 @@
|
||||||
|
|
||||||
License of Minetest textures and sounds
|
License of Luanti textures and sounds
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
This applies to textures and sounds contained in the main Minetest
|
This applies to textures and sounds contained in the main Luanti
|
||||||
distribution.
|
distribution.
|
||||||
|
|
||||||
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
|
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
|
||||||
|
@ -29,7 +29,6 @@ ShadowNinja:
|
||||||
textures/base/pack/smoke_puff.png
|
textures/base/pack/smoke_puff.png
|
||||||
|
|
||||||
paramat:
|
paramat:
|
||||||
textures/base/pack/menu_header.png
|
|
||||||
textures/base/pack/next_icon.png
|
textures/base/pack/next_icon.png
|
||||||
textures/base/pack/prev_icon.png
|
textures/base/pack/prev_icon.png
|
||||||
textures/base/pack/clear.png
|
textures/base/pack/clear.png
|
||||||
|
@ -39,10 +38,10 @@ rubenwardy, paramat:
|
||||||
textures/base/pack/start_icon.png
|
textures/base/pack/start_icon.png
|
||||||
textures/base/pack/end_icon.png
|
textures/base/pack/end_icon.png
|
||||||
|
|
||||||
erlehmann:
|
erle:
|
||||||
misc/minetest-icon-24x24.png
|
misc/luanti-icon-24x24.png
|
||||||
misc/minetest-icon.ico
|
misc/luanti-icon.ico
|
||||||
misc/minetest.svg
|
misc/luanti.svg
|
||||||
textures/base/pack/logo.png
|
textures/base/pack/logo.png
|
||||||
|
|
||||||
JRottm:
|
JRottm:
|
||||||
|
@ -57,20 +56,20 @@ srifqi:
|
||||||
textures/base/pack/minimap_btn.png
|
textures/base/pack/minimap_btn.png
|
||||||
|
|
||||||
Zughy:
|
Zughy:
|
||||||
textures/base/pack/cdb_add.png
|
|
||||||
textures/base/pack/cdb_downloading.png
|
textures/base/pack/cdb_downloading.png
|
||||||
textures/base/pack/cdb_queued.png
|
textures/base/pack/cdb_queued.png
|
||||||
textures/base/pack/cdb_update.png
|
textures/base/pack/cdb_update.png
|
||||||
textures/base/pack/cdb_update_cropped.png
|
textures/base/pack/cdb_update_cropped.png
|
||||||
textures/base/pack/cdb_viewonline.png
|
|
||||||
textures/base/pack/settings_btn.png
|
textures/base/pack/settings_btn.png
|
||||||
textures/base/pack/settings_info.png
|
textures/base/pack/settings_info.png
|
||||||
textures/base/pack/settings_reset.png
|
textures/base/pack/settings_reset.png
|
||||||
|
textures/base/pack/server_url.png
|
||||||
|
textures/base/pack/server_view_clients.png
|
||||||
|
|
||||||
appgurueu:
|
appgurueu:
|
||||||
textures/base/pack/server_incompatible.png
|
textures/base/pack/server_incompatible.png
|
||||||
|
|
||||||
erlehmann, Warr1024, rollerozxa:
|
erle, Warr1024, rollerozxa:
|
||||||
textures/base/pack/no_screenshot.png
|
textures/base/pack/no_screenshot.png
|
||||||
|
|
||||||
kilbith:
|
kilbith:
|
||||||
|
@ -79,7 +78,6 @@ kilbith:
|
||||||
textures/base/pack/progress_bar_bg.png
|
textures/base/pack/progress_bar_bg.png
|
||||||
|
|
||||||
SmallJoker:
|
SmallJoker:
|
||||||
textures/base/pack/cdb_clear.png
|
|
||||||
textures/base/pack/server_favorite_delete.png (based on server_favorite.png)
|
textures/base/pack/server_favorite_delete.png (based on server_favorite.png)
|
||||||
|
|
||||||
DS:
|
DS:
|
||||||
|
@ -91,12 +89,17 @@ DS:
|
||||||
|
|
||||||
grorp:
|
grorp:
|
||||||
textures/base/pack/exit_btn.png
|
textures/base/pack/exit_btn.png
|
||||||
|
textures/base/pack/menu_header.png
|
||||||
|
using the font "undefined medium" (https://undefined-medium.com/),
|
||||||
|
which is licensed under the SIL Open Font License, Version 1.1
|
||||||
|
modified by DS
|
||||||
|
|
||||||
License of Minetest source code
|
License of Luanti source code
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
Minetest
|
Luanti
|
||||||
Copyright (C) 2010-2018 celeron55, Perttu Ahola <celeron55@gmail.com>
|
Copyright (C) 2010-2024 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
and contributors (see source file comments and the version control log)
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
@ -115,7 +118,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
Irrlicht
|
Irrlicht
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
This program uses IrrlichtMt, Minetest's fork of
|
This program uses IrrlichtMt, Luanti's fork of
|
||||||
the Irrlicht Engine. http://irrlicht.sourceforge.net/
|
the Irrlicht Engine. http://irrlicht.sourceforge.net/
|
||||||
|
|
||||||
The Irrlicht Engine License
|
The Irrlicht Engine License
|
||||||
|
|
16
README.md
16
README.md
|
@ -1,13 +1,13 @@
|
||||||
Minetest
|
Luanti (formerly Minetest)
|
||||||
========
|
==========================
|
||||||
|
|
||||||

|

|
||||||
[](https://hosted.weblate.org/engage/minetest/?utm_source=widget)
|
[](https://hosted.weblate.org/engage/minetest/?utm_source=widget)
|
||||||
[](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html)
|
[](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html)
|
||||||
|
|
||||||
Minetest is a free open-source voxel game engine with easy modding and game creation.
|
Luanti is a free open-source voxel game engine with easy modding and game creation.
|
||||||
|
|
||||||
Copyright (C) 2010-2022 Perttu Ahola <celeron55@gmail.com>
|
Copyright (C) 2010-2024 Perttu Ahola <celeron55@gmail.com>
|
||||||
and contributors (see source file comments and the version control log)
|
and contributors (see source file comments and the version control log)
|
||||||
|
|
||||||
Table of Contents
|
Table of Contents
|
||||||
|
@ -25,9 +25,9 @@ Table of Contents
|
||||||
|
|
||||||
Further documentation
|
Further documentation
|
||||||
----------------------
|
----------------------
|
||||||
- Website: https://www.minetest.net/
|
- Website: https://www.luanti.org/
|
||||||
- Wiki: https://wiki.minetest.net/
|
- Wiki: https://wiki.luanti.org/
|
||||||
- Forum: https://forum.minetest.net/
|
- Forum: https://forum.luanti.org/
|
||||||
- GitHub: https://github.com/minetest/minetest/
|
- GitHub: https://github.com/minetest/minetest/
|
||||||
- [Developer documentation](doc/developing/)
|
- [Developer documentation](doc/developing/)
|
||||||
- [doc/](doc/) directory of source distribution
|
- [doc/](doc/) directory of source distribution
|
||||||
|
@ -106,7 +106,7 @@ Configuration file
|
||||||
------------------
|
------------------
|
||||||
- Default location:
|
- Default location:
|
||||||
`user/minetest.conf`
|
`user/minetest.conf`
|
||||||
- This file is created by closing Minetest for the first time.
|
- This file is created by closing Luanti for the first time.
|
||||||
- A specific file can be specified on the command line:
|
- A specific file can be specified on the command line:
|
||||||
`--config <path-to-file>`
|
`--config <path-to-file>`
|
||||||
- A run-in-place build will look for the configuration file in
|
- A run-in-place build will look for the configuration file in
|
||||||
|
|
|
@ -95,7 +95,7 @@ task prepareAssets() {
|
||||||
def moPath = "${assetsFolder}/locale/${poFile.parentFile.name}/LC_MESSAGES/"
|
def moPath = "${assetsFolder}/locale/${poFile.parentFile.name}/LC_MESSAGES/"
|
||||||
file(moPath).mkdirs()
|
file(moPath).mkdirs()
|
||||||
exec {
|
exec {
|
||||||
commandLine 'msgfmt', '-o', "${moPath}/minetest.mo", poFile
|
commandLine 'msgfmt', '-o', "${moPath}/luanti.mo", poFile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ task prepareAssets() {
|
||||||
}
|
}
|
||||||
|
|
||||||
task zipAssets(dependsOn: prepareAssets, type: Zip) {
|
task zipAssets(dependsOn: prepareAssets, type: Zip) {
|
||||||
archiveFileName = "Minetest.zip"
|
archiveFileName = "assets.zip"
|
||||||
from assetsFolder
|
from assetsFolder
|
||||||
destinationDirectory = file("src/main/assets")
|
destinationDirectory = file("src/main/assets")
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,7 @@ preBuild.dependsOn zipAssets
|
||||||
prepareAssets.dependsOn ':native:getDeps'
|
prepareAssets.dependsOn ':native:getDeps'
|
||||||
|
|
||||||
clean {
|
clean {
|
||||||
delete new File("src/main/assets", "Minetest.zip")
|
delete new File("src/main/assets", "assets.zip")
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
|
@ -43,9 +43,6 @@
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<meta-data
|
|
||||||
android:name="android.app.lib_name"
|
|
||||||
android:value="minetest" />
|
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<service
|
<service
|
||||||
|
|
|
@ -52,7 +52,7 @@ import java.util.Objects;
|
||||||
public class GameActivity extends SDLActivity {
|
public class GameActivity extends SDLActivity {
|
||||||
@Override
|
@Override
|
||||||
protected String getMainSharedObject() {
|
protected String getMainSharedObject() {
|
||||||
return getContext().getApplicationInfo().nativeLibraryDir + "/libminetest.so";
|
return getContext().getApplicationInfo().nativeLibraryDir + "/libluanti.so";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -63,7 +63,7 @@ public class GameActivity extends SDLActivity {
|
||||||
@Override
|
@Override
|
||||||
protected String[] getLibraries() {
|
protected String[] getLibraries() {
|
||||||
return new String[] {
|
return new String[] {
|
||||||
"minetest"
|
"luanti"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ public class UnzipService extends IntentService {
|
||||||
@Override
|
@Override
|
||||||
protected void onHandleIntent(Intent intent) {
|
protected void onHandleIntent(Intent intent) {
|
||||||
Notification.Builder notificationBuilder = createNotification();
|
Notification.Builder notificationBuilder = createNotification();
|
||||||
final File zipFile = new File(getCacheDir(), "Minetest.zip");
|
final File zipFile = new File(getCacheDir(), "assets.zip");
|
||||||
try {
|
try {
|
||||||
setIsRunning(true);
|
setIsRunning(true);
|
||||||
File userDataDirectory = Utils.getUserDataDirectory(this);
|
File userDataDirectory = Utils.getUserDataDirectory(this);
|
||||||
|
|
|
@ -277,6 +277,7 @@ public class HIDDeviceManager {
|
||||||
0x044f, // Thrustmaster
|
0x044f, // Thrustmaster
|
||||||
0x045e, // Microsoft
|
0x045e, // Microsoft
|
||||||
0x0738, // Mad Catz
|
0x0738, // Mad Catz
|
||||||
|
0x0b05, // ASUS
|
||||||
0x0e6f, // PDP
|
0x0e6f, // PDP
|
||||||
0x0f0d, // Hori
|
0x0f0d, // Hori
|
||||||
0x10f5, // Turtle Beach
|
0x10f5, // Turtle Beach
|
||||||
|
@ -590,7 +591,13 @@ public class HIDDeviceManager {
|
||||||
} else {
|
} else {
|
||||||
flags = 0;
|
flags = 0;
|
||||||
}
|
}
|
||||||
mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, new Intent(HIDDeviceManager.ACTION_USB_PERMISSION), flags));
|
if (Build.VERSION.SDK_INT >= 33 /* Android 14.0 (U) */) {
|
||||||
|
Intent intent = new Intent(HIDDeviceManager.ACTION_USB_PERMISSION);
|
||||||
|
intent.setPackage(mContext.getPackageName());
|
||||||
|
mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, intent, flags));
|
||||||
|
} else {
|
||||||
|
mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, new Intent(HIDDeviceManager.ACTION_USB_PERMISSION), flags));
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.v(TAG, "Couldn't request permission for USB device " + usbDevice);
|
Log.v(TAG, "Couldn't request permission for USB device " + usbDevice);
|
||||||
HIDDeviceOpenResult(deviceID, false);
|
HIDDeviceOpenResult(deviceID, false);
|
||||||
|
|
|
@ -38,6 +38,10 @@ public class SDL {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void loadLibrary(String libraryName) throws UnsatisfiedLinkError, SecurityException, NullPointerException {
|
public static void loadLibrary(String libraryName) throws UnsatisfiedLinkError, SecurityException, NullPointerException {
|
||||||
|
loadLibrary(libraryName, mContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void loadLibrary(String libraryName, Context context) throws UnsatisfiedLinkError, SecurityException, NullPointerException {
|
||||||
|
|
||||||
if (libraryName == null) {
|
if (libraryName == null) {
|
||||||
throw new NullPointerException("No library name provided.");
|
throw new NullPointerException("No library name provided.");
|
||||||
|
@ -53,10 +57,10 @@ public class SDL {
|
||||||
// To use ReLinker, just add it as a dependency. For more information, see
|
// To use ReLinker, just add it as a dependency. For more information, see
|
||||||
// https://github.com/KeepSafe/ReLinker for ReLinker's repository.
|
// https://github.com/KeepSafe/ReLinker for ReLinker's repository.
|
||||||
//
|
//
|
||||||
Class<?> relinkClass = mContext.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker");
|
Class<?> relinkClass = context.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker");
|
||||||
Class<?> relinkListenerClass = mContext.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker$LoadListener");
|
Class<?> relinkListenerClass = context.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker$LoadListener");
|
||||||
Class<?> contextClass = mContext.getClassLoader().loadClass("android.content.Context");
|
Class<?> contextClass = context.getClassLoader().loadClass("android.content.Context");
|
||||||
Class<?> stringClass = mContext.getClassLoader().loadClass("java.lang.String");
|
Class<?> stringClass = context.getClassLoader().loadClass("java.lang.String");
|
||||||
|
|
||||||
// Get a 'force' instance of the ReLinker, so we can ensure libraries are reinstalled if
|
// Get a 'force' instance of the ReLinker, so we can ensure libraries are reinstalled if
|
||||||
// they've changed during updates.
|
// they've changed during updates.
|
||||||
|
@ -66,7 +70,7 @@ public class SDL {
|
||||||
|
|
||||||
// Actually load the library!
|
// Actually load the library!
|
||||||
Method loadMethod = relinkInstanceClass.getDeclaredMethod("loadLibrary", contextClass, stringClass, stringClass, relinkListenerClass);
|
Method loadMethod = relinkInstanceClass.getDeclaredMethod("loadLibrary", contextClass, stringClass, stringClass, relinkListenerClass);
|
||||||
loadMethod.invoke(relinkInstance, mContext, libraryName, null, null);
|
loadMethod.invoke(relinkInstance, context, libraryName, null, null);
|
||||||
}
|
}
|
||||||
catch (final Throwable e) {
|
catch (final Throwable e) {
|
||||||
// Fall back
|
// Fall back
|
||||||
|
|
|
@ -61,7 +61,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||||
private static final String TAG = "SDL";
|
private static final String TAG = "SDL";
|
||||||
private static final int SDL_MAJOR_VERSION = 2;
|
private static final int SDL_MAJOR_VERSION = 2;
|
||||||
private static final int SDL_MINOR_VERSION = 30;
|
private static final int SDL_MINOR_VERSION = 30;
|
||||||
private static final int SDL_MICRO_VERSION = 1;
|
private static final int SDL_MICRO_VERSION = 8;
|
||||||
/*
|
/*
|
||||||
// Display InputType.SOURCE/CLASS of events and devices
|
// Display InputType.SOURCE/CLASS of events and devices
|
||||||
//
|
//
|
||||||
|
@ -89,7 +89,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||||
| InputDevice.SOURCE_CLASS_POSITION
|
| InputDevice.SOURCE_CLASS_POSITION
|
||||||
| InputDevice.SOURCE_CLASS_TRACKBALL);
|
| InputDevice.SOURCE_CLASS_TRACKBALL);
|
||||||
|
|
||||||
if (s2 != 0) cls += "Some_Unkown";
|
if (s2 != 0) cls += "Some_Unknown";
|
||||||
|
|
||||||
s2 = s_copy & InputDevice.SOURCE_ANY; // keep source only, no class;
|
s2 = s_copy & InputDevice.SOURCE_ANY; // keep source only, no class;
|
||||||
|
|
||||||
|
@ -163,7 +163,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||||
if (s == FLAG_TAINTED) src += " FLAG_TAINTED";
|
if (s == FLAG_TAINTED) src += " FLAG_TAINTED";
|
||||||
s2 &= ~FLAG_TAINTED;
|
s2 &= ~FLAG_TAINTED;
|
||||||
|
|
||||||
if (s2 != 0) src += " Some_Unkown";
|
if (s2 != 0) src += " Some_Unknown";
|
||||||
|
|
||||||
Log.v(TAG, prefix + "int=" + s_copy + " CLASS={" + cls + " } source(s):" + src);
|
Log.v(TAG, prefix + "int=" + s_copy + " CLASS={" + cls + " } source(s):" + src);
|
||||||
}
|
}
|
||||||
|
@ -281,7 +281,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||||
// Load the .so
|
// Load the .so
|
||||||
public void loadLibraries() {
|
public void loadLibraries() {
|
||||||
for (String lib : getLibraries()) {
|
for (String lib : getLibraries()) {
|
||||||
SDL.loadLibrary(lib);
|
SDL.loadLibrary(lib, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -995,8 +995,8 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||||
/* No valid hint, nothing is explicitly allowed */
|
/* No valid hint, nothing is explicitly allowed */
|
||||||
if (!is_portrait_allowed && !is_landscape_allowed) {
|
if (!is_portrait_allowed && !is_landscape_allowed) {
|
||||||
if (resizable) {
|
if (resizable) {
|
||||||
/* All orientations are allowed */
|
/* All orientations are allowed, respecting user orientation lock setting */
|
||||||
req = ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR;
|
req = ActivityInfo.SCREEN_ORIENTATION_FULL_USER;
|
||||||
} else {
|
} else {
|
||||||
/* Fixed window and nothing specified. Get orientation from w/h of created window */
|
/* Fixed window and nothing specified. Get orientation from w/h of created window */
|
||||||
req = (w > h ? ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
|
req = (w > h ? ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
|
||||||
|
@ -1005,8 +1005,8 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||||
/* At least one orientation is allowed */
|
/* At least one orientation is allowed */
|
||||||
if (resizable) {
|
if (resizable) {
|
||||||
if (is_portrait_allowed && is_landscape_allowed) {
|
if (is_portrait_allowed && is_landscape_allowed) {
|
||||||
/* hint allows both landscape and portrait, promote to full sensor */
|
/* hint allows both landscape and portrait, promote to full user */
|
||||||
req = ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR;
|
req = ActivityInfo.SCREEN_ORIENTATION_FULL_USER;
|
||||||
} else {
|
} else {
|
||||||
/* Use the only one allowed "orientation" */
|
/* Use the only one allowed "orientation" */
|
||||||
req = (is_landscape_allowed ? orientation_landscape : orientation_portrait);
|
req = (is_landscape_allowed ? orientation_landscape : orientation_portrait);
|
||||||
|
|
|
@ -546,13 +546,15 @@ class SDLHapticHandler {
|
||||||
if (haptic == null) {
|
if (haptic == null) {
|
||||||
InputDevice device = InputDevice.getDevice(deviceIds[i]);
|
InputDevice device = InputDevice.getDevice(deviceIds[i]);
|
||||||
Vibrator vib = device.getVibrator();
|
Vibrator vib = device.getVibrator();
|
||||||
if (vib.hasVibrator()) {
|
if (vib != null) {
|
||||||
haptic = new SDLHaptic();
|
if (vib.hasVibrator()) {
|
||||||
haptic.device_id = deviceIds[i];
|
haptic = new SDLHaptic();
|
||||||
haptic.name = device.getName();
|
haptic.device_id = deviceIds[i];
|
||||||
haptic.vib = vib;
|
haptic.name = device.getName();
|
||||||
mHaptics.add(haptic);
|
haptic.vib = vib;
|
||||||
SDLControllerManager.nativeAddHaptic(haptic.device_id, haptic.name);
|
mHaptics.add(haptic);
|
||||||
|
SDLControllerManager.nativeAddHaptic(haptic.device_id, haptic.name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
11
android/app/src/main/res/values-de/strings.xml
Normal file
11
android/app/src/main/res/values-de/strings.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="label">Luanti</string>
|
||||||
|
<string name="loading">Lädt…</string>
|
||||||
|
<string name="unzip_notification_title">Luanti lädt</string>
|
||||||
|
<string name="unzip_notification_description">Weniger als 1 Minute…</string>
|
||||||
|
<string name="ime_dialog_done">Fertig</string>
|
||||||
|
<string name="no_web_browser">Kein Web-Browser gefunden</string>
|
||||||
|
<string name="notification_channel_name">Allgemeine Benachrichtigung</string>
|
||||||
|
<string name="notification_channel_description">Benachrichtigungen von Luanti</string>
|
||||||
|
</resources>
|
11
android/app/src/main/res/values-es-rUS/strings.xml
Normal file
11
android/app/src/main/res/values-es-rUS/strings.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="unzip_notification_description">Menos de 1 minuto…</string>
|
||||||
|
<string name="ime_dialog_done">Hecho</string>
|
||||||
|
<string name="no_web_browser">No se encontró ningún navegador web</string>
|
||||||
|
<string name="loading">Cargando…</string>
|
||||||
|
<string name="notification_channel_name">Notificación General</string>
|
||||||
|
<string name="label">Luanti</string>
|
||||||
|
<string name="notification_channel_description">Notificaciones de Luanti</string>
|
||||||
|
<string name="unzip_notification_title">Cargando Luanti</string>
|
||||||
|
</resources>
|
11
android/app/src/main/res/values-es/strings.xml
Normal file
11
android/app/src/main/res/values-es/strings.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="no_web_browser">No se encontró ningún navegador web</string>
|
||||||
|
<string name="loading">Cargando…</string>
|
||||||
|
<string name="notification_channel_description">Notificaciones de Luanti</string>
|
||||||
|
<string name="unzip_notification_description">Menos de 1 minuto…</string>
|
||||||
|
<string name="ime_dialog_done">Hecho</string>
|
||||||
|
<string name="label">Luanti</string>
|
||||||
|
<string name="unzip_notification_title">Cargando Luanti</string>
|
||||||
|
<string name="notification_channel_name">Notificación General</string>
|
||||||
|
</resources>
|
11
android/app/src/main/res/values-hu/strings.xml
Normal file
11
android/app/src/main/res/values-hu/strings.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="loading">Betöltés…</string>
|
||||||
|
<string name="notification_channel_name">Általános értesítés</string>
|
||||||
|
<string name="notification_channel_description">Értesítések a Luanti-től</string>
|
||||||
|
<string name="unzip_notification_title">Luanti betöltése…</string>
|
||||||
|
<string name="ime_dialog_done">Kész</string>
|
||||||
|
<string name="no_web_browser">Nem található webböngésző</string>
|
||||||
|
<string name="label">Luanti</string>
|
||||||
|
<string name="unzip_notification_description">Kevesebb, mint 1 perc…</string>
|
||||||
|
</resources>
|
11
android/app/src/main/res/values-in/strings.xml
Normal file
11
android/app/src/main/res/values-in/strings.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="no_web_browser">Tidak ditemukan peramban web</string>
|
||||||
|
<string name="ime_dialog_done">Selesai</string>
|
||||||
|
<string name="label">Luanti</string>
|
||||||
|
<string name="loading">Memuat…</string>
|
||||||
|
<string name="notification_channel_name">Pemberitahuan umum</string>
|
||||||
|
<string name="unzip_notification_description">Kurang dari 1 menit…</string>
|
||||||
|
<string name="notification_channel_description">Pemberitahuan dari Luanti</string>
|
||||||
|
<string name="unzip_notification_title">Memuat Luanti…</string>
|
||||||
|
</resources>
|
11
android/app/src/main/res/values-ms/strings.xml
Normal file
11
android/app/src/main/res/values-ms/strings.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="label">Luanti</string>
|
||||||
|
<string name="notification_channel_description">Pemberitahuan dari Luanti</string>
|
||||||
|
<string name="unzip_notification_title">Memuatkan Luanti…</string>
|
||||||
|
<string name="unzip_notification_description">Kurang dari 1 minit…</string>
|
||||||
|
<string name="no_web_browser">Tiada pelayar sesawang dijumpai</string>
|
||||||
|
<string name="loading">Memuatkan…</string>
|
||||||
|
<string name="notification_channel_name">Pemberitahuan umum</string>
|
||||||
|
<string name="ime_dialog_done">Selesai</string>
|
||||||
|
</resources>
|
11
android/app/src/main/res/values-nb-rNO/strings.xml
Normal file
11
android/app/src/main/res/values-nb-rNO/strings.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="label">Luanti</string>
|
||||||
|
<string name="loading">Laster inn …</string>
|
||||||
|
<string name="notification_channel_name">Generell merknad</string>
|
||||||
|
<string name="notification_channel_description">Merknader fra Luanti</string>
|
||||||
|
<string name="unzip_notification_description">Mindre enn ett minutt …</string>
|
||||||
|
<string name="ime_dialog_done">Ferdig</string>
|
||||||
|
<string name="no_web_browser">Fant ingen nettleser</string>
|
||||||
|
<string name="unzip_notification_title">Laster inn Luanti …</string>
|
||||||
|
</resources>
|
11
android/app/src/main/res/values-ru/strings.xml
Normal file
11
android/app/src/main/res/values-ru/strings.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="unzip_notification_title">Загрузка Luanti</string>
|
||||||
|
<string name="unzip_notification_description">Меньше чам за 1 минуту…</string>
|
||||||
|
<string name="ime_dialog_done">Готово</string>
|
||||||
|
<string name="label">Luаnti</string>
|
||||||
|
<string name="notification_channel_description">Уведомления от Luanti</string>
|
||||||
|
<string name="notification_channel_name">Основные уведомления</string>
|
||||||
|
<string name="loading">Загрузка…</string>
|
||||||
|
<string name="no_web_browser">Не найдено веб-браузера</string>
|
||||||
|
</resources>
|
|
@ -1,10 +1,10 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="label">Minetest</string>
|
<string name="label">Luanti</string>
|
||||||
<string name="loading">Loading…</string>
|
<string name="loading">Loading…</string>
|
||||||
<string name="notification_channel_name">General notification</string>
|
<string name="notification_channel_name">General notification</string>
|
||||||
<string name="notification_channel_description">Notifications from Minetest</string>
|
<string name="notification_channel_description">Notifications from Luanti</string>
|
||||||
<string name="unzip_notification_title">Loading Minetest</string>
|
<string name="unzip_notification_title">Loading Luanti</string>
|
||||||
<string name="unzip_notification_description">Less than 1 minute…</string>
|
<string name="unzip_notification_description">Less than 1 minute…</string>
|
||||||
<string name="ime_dialog_done">Done</string>
|
<string name="ime_dialog_done">Done</string>
|
||||||
<string name="no_web_browser">No web browser found</string>
|
<string name="no_web_browser">No web browser found</string>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
|
||||||
project.ext.set("versionMajor", 5) // Version Major
|
project.ext.set("versionMajor", 5) // Version Major
|
||||||
project.ext.set("versionMinor", 10) // Version Minor
|
project.ext.set("versionMinor", 11) // Version Minor
|
||||||
project.ext.set("versionPatch", 0) // Version Patch
|
project.ext.set("versionPatch", 0) // Version Patch
|
||||||
// ^ keep in sync with cmake
|
// ^ keep in sync with cmake
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ project.ext.set("versionBuild", 0) // Version Build
|
||||||
// ^ fourth version number to allow releasing Android-only fixes and beta versions
|
// ^ fourth version number to allow releasing Android-only fixes and beta versions
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.ndk_version = '26.2.11394342'
|
ext.ndk_version = '27.2.12479018'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
rootProject.name = "Minetest"
|
rootProject.name = "Luanti"
|
||||||
include ':app', ':native'
|
include ':app', ':native'
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
-- Minetest: builtin/client/chatcommands.lua
|
|
||||||
|
|
||||||
core.register_on_sending_chat_message(function(message)
|
core.register_on_sending_chat_message(function(message)
|
||||||
if message:sub(1,2) == ".." then
|
if message:sub(1,2) == ".." then
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
-- Minetest: builtin/client/init.lua
|
|
||||||
local scriptpath = core.get_builtin_path()
|
local scriptpath = core.get_builtin_path()
|
||||||
local clientpath = scriptpath.."client"..DIR_DELIM
|
local clientpath = scriptpath.."client"..DIR_DELIM
|
||||||
local commonpath = scriptpath.."common"..DIR_DELIM
|
local commonpath = scriptpath.."common"..DIR_DELIM
|
||||||
|
|
|
@ -155,7 +155,7 @@ end
|
||||||
|
|
||||||
function core.after(after, func, ...)
|
function core.after(after, func, ...)
|
||||||
assert(tonumber(after) and not core.is_nan(after) and type(func) == "function",
|
assert(tonumber(after) and not core.is_nan(after) and type(func) == "function",
|
||||||
"Invalid minetest.after invocation")
|
"Invalid core.after invocation")
|
||||||
|
|
||||||
local new_job = {
|
local new_job = {
|
||||||
mod_origin = core.get_last_run_mod(),
|
mod_origin = core.get_last_run_mod(),
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
-- Minetest: builtin/common/chatcommands.lua
|
|
||||||
|
|
||||||
-- For server-side translations (if INIT == "game")
|
-- For server-side translations (if INIT == "game")
|
||||||
-- Otherwise, use core.gettext
|
-- Otherwise, use core.gettext
|
||||||
local S = core.get_translator("__builtin")
|
local S = core.get_translator("__builtin")
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2013 sapier
|
--Copyright (C) 2013 sapier
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
-- Minetest: builtin/item_s.lua
|
|
||||||
-- The distinction of what goes here is a bit tricky, basically it's everything
|
-- The distinction of what goes here is a bit tricky, basically it's everything
|
||||||
-- that does not (directly or indirectly) need access to ServerEnvironment,
|
-- that does not (directly or indirectly) need access to ServerEnvironment,
|
||||||
-- Server or writable access to IGameDef on the engine side.
|
-- Server or writable access to IGameDef on the engine side.
|
||||||
|
@ -166,20 +165,19 @@ function core.is_colored_paramtype(ptype)
|
||||||
end
|
end
|
||||||
|
|
||||||
function core.strip_param2_color(param2, paramtype2)
|
function core.strip_param2_color(param2, paramtype2)
|
||||||
if not core.is_colored_paramtype(paramtype2) then
|
if paramtype2 == "color" then
|
||||||
|
return param2
|
||||||
|
elseif paramtype2 == "colorfacedir" then
|
||||||
|
return math.floor(param2 / 32) * 32
|
||||||
|
elseif paramtype2 == "color4dir" then
|
||||||
|
return math.floor(param2 / 4) * 4
|
||||||
|
elseif paramtype2 == "colorwallmounted" then
|
||||||
|
return math.floor(param2 / 8) * 8
|
||||||
|
elseif paramtype2 == "colordegrotate" then
|
||||||
|
return math.floor(param2 / 32) * 32
|
||||||
|
else
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
if paramtype2 == "colorfacedir" then
|
|
||||||
param2 = math.floor(param2 / 32) * 32
|
|
||||||
elseif paramtype2 == "color4dir" then
|
|
||||||
param2 = math.floor(param2 / 4) * 4
|
|
||||||
elseif paramtype2 == "colorwallmounted" then
|
|
||||||
param2 = math.floor(param2 / 8) * 8
|
|
||||||
elseif paramtype2 == "colordegrotate" then
|
|
||||||
param2 = math.floor(param2 / 32) * 32
|
|
||||||
end
|
|
||||||
-- paramtype2 == "color" requires no modification.
|
|
||||||
return param2
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Content ID caching
|
-- Content ID caching
|
||||||
|
|
|
@ -11,8 +11,8 @@ end
|
||||||
core.known_metatables = known_metatables
|
core.known_metatables = known_metatables
|
||||||
|
|
||||||
function core.register_async_metatable(...)
|
function core.register_async_metatable(...)
|
||||||
core.log("deprecated", "minetest.register_async_metatable is deprecated. " ..
|
core.log("deprecated", "core.register_async_metatable is deprecated. " ..
|
||||||
"Use minetest.register_portable_metatable instead.")
|
"Use core.register_portable_metatable instead.")
|
||||||
return core.register_portable_metatable(...)
|
return core.register_portable_metatable(...)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
-- Minetest: builtin/misc_helpers.lua
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- Localize functions to avoid table lookups (better performance).
|
-- Localize functions to avoid table lookups (better performance).
|
||||||
local string_sub, string_find = string.sub, string.find
|
local string_sub, string_find = string.sub, string.find
|
||||||
|
@ -235,6 +233,16 @@ function core.formspec_escape(text)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local hypertext_escapes = {
|
||||||
|
["\\"] = "\\\\",
|
||||||
|
["<"] = "\\<",
|
||||||
|
[">"] = "\\>",
|
||||||
|
}
|
||||||
|
function core.hypertext_escape(text)
|
||||||
|
return text and text:gsub("[\\<>]", hypertext_escapes)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
function core.wrap_text(text, max_length, as_table)
|
function core.wrap_text(text, max_length, as_table)
|
||||||
local result = {}
|
local result = {}
|
||||||
local line = {}
|
local line = {}
|
||||||
|
@ -564,12 +572,14 @@ function core.strip_colors(str)
|
||||||
return (str:gsub(ESCAPE_CHAR .. "%([bc]@[^)]+%)", ""))
|
return (str:gsub(ESCAPE_CHAR .. "%([bc]@[^)]+%)", ""))
|
||||||
end
|
end
|
||||||
|
|
||||||
function core.translate(textdomain, str, ...)
|
local function translate(textdomain, str, num, ...)
|
||||||
local start_seq
|
local start_seq
|
||||||
if textdomain == "" then
|
if textdomain == "" and num == "" then
|
||||||
start_seq = ESCAPE_CHAR .. "T"
|
start_seq = ESCAPE_CHAR .. "T"
|
||||||
else
|
elseif num == "" then
|
||||||
start_seq = ESCAPE_CHAR .. "(T@" .. textdomain .. ")"
|
start_seq = ESCAPE_CHAR .. "(T@" .. textdomain .. ")"
|
||||||
|
else
|
||||||
|
start_seq = ESCAPE_CHAR .. "(T@" .. textdomain .. "@" .. num .. ")"
|
||||||
end
|
end
|
||||||
local arg = {n=select('#', ...), ...}
|
local arg = {n=select('#', ...), ...}
|
||||||
local end_seq = ESCAPE_CHAR .. "E"
|
local end_seq = ESCAPE_CHAR .. "E"
|
||||||
|
@ -600,8 +610,31 @@ function core.translate(textdomain, str, ...)
|
||||||
return start_seq .. translated .. end_seq
|
return start_seq .. translated .. end_seq
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function core.translate(textdomain, str, ...)
|
||||||
|
return translate(textdomain, str, "", ...)
|
||||||
|
end
|
||||||
|
|
||||||
|
function core.translate_n(textdomain, str, str_plural, n, ...)
|
||||||
|
assert (type(n) == "number")
|
||||||
|
assert (n >= 0)
|
||||||
|
assert (math.floor(n) == n)
|
||||||
|
|
||||||
|
-- Truncate n if too large
|
||||||
|
local max = 1000000
|
||||||
|
if n >= 2 * max then
|
||||||
|
n = n % max + max
|
||||||
|
end
|
||||||
|
if n == 1 then
|
||||||
|
return translate(textdomain, str, "1", ...)
|
||||||
|
else
|
||||||
|
return translate(textdomain, str_plural, tostring(n), ...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function core.get_translator(textdomain)
|
function core.get_translator(textdomain)
|
||||||
return function(str, ...) return core.translate(textdomain or "", str, ...) end
|
return
|
||||||
|
(function(str, ...) return core.translate(textdomain or "", str, ...) end),
|
||||||
|
(function(str, str_plural, n, ...) return core.translate_n(textdomain or "", str, str_plural, n, ...) end)
|
||||||
end
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
|
@ -204,18 +204,18 @@ local function dummy_func() end
|
||||||
function core.deserialize(str, safe)
|
function core.deserialize(str, safe)
|
||||||
-- Backwards compatibility
|
-- Backwards compatibility
|
||||||
if str == nil then
|
if str == nil then
|
||||||
core.log("deprecated", "minetest.deserialize called with nil (expected string).")
|
core.log("deprecated", "core.deserialize called with nil (expected string).")
|
||||||
return nil, "Invalid type: Expected a string, got nil"
|
return nil, "Invalid type: Expected a string, got nil"
|
||||||
end
|
end
|
||||||
local t = type(str)
|
local t = type(str)
|
||||||
if t ~= "string" then
|
if t ~= "string" then
|
||||||
error(("minetest.deserialize called with %s (expected string)."):format(t))
|
error(("core.deserialize called with %s (expected string)."):format(t))
|
||||||
end
|
end
|
||||||
|
|
||||||
local func, err = loadstring(str)
|
local func, err = loadstring(str)
|
||||||
if not func then return nil, err end
|
if not func then return nil, err end
|
||||||
|
|
||||||
-- math.huge was serialized to inf and NaNs to nan by Lua in Minetest 5.6, so we have to support this here
|
-- math.huge was serialized to inf and NaNs to nan by Lua in engine version 5.6, so we have to support this here
|
||||||
local env = {inf = math_huge, nan = 0/0}
|
local env = {inf = math_huge, nan = 0/0}
|
||||||
if safe then
|
if safe then
|
||||||
env.loadstring = dummy_func
|
env.loadstring = dummy_func
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2014 sapier
|
--Copyright (C) 2014 sapier
|
||||||
--Copyright (C) 2023 Gregor Parzefall
|
--Copyright (C) 2023 Gregor Parzefall
|
||||||
--
|
--
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2014 sapier
|
--Copyright (C) 2014 sapier
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2014 sapier
|
--Copyright (C) 2014 sapier
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -66,13 +66,13 @@ local function get_formspec(self)
|
||||||
|
|
||||||
local content, prepend = tab.get_formspec(self, tab.name, tab.tabdata, tab.tabsize)
|
local content, prepend = tab.get_formspec(self, tab.name, tab.tabdata, tab.tabsize)
|
||||||
|
|
||||||
local ENABLE_TOUCH = core.settings:get_bool("enable_touch")
|
local TOUCH_GUI = core.settings:get_bool("touch_gui")
|
||||||
|
|
||||||
local orig_tsize = tab.tabsize or { width = self.width, height = self.height }
|
local orig_tsize = tab.tabsize or { width = self.width, height = self.height }
|
||||||
local tsize = { width = orig_tsize.width, height = orig_tsize.height }
|
local tsize = { width = orig_tsize.width, height = orig_tsize.height }
|
||||||
tsize.height = tsize.height
|
tsize.height = tsize.height
|
||||||
+ TABHEADER_H -- tabheader included in formspec size
|
+ TABHEADER_H -- tabheader included in formspec size
|
||||||
+ (ENABLE_TOUCH and GAMEBAR_OFFSET_TOUCH or GAMEBAR_OFFSET_DESKTOP)
|
+ (TOUCH_GUI and GAMEBAR_OFFSET_TOUCH or GAMEBAR_OFFSET_DESKTOP)
|
||||||
+ GAMEBAR_H -- gamebar included in formspec size
|
+ GAMEBAR_H -- gamebar included in formspec size
|
||||||
|
|
||||||
if self.parent == nil and not prepend then
|
if self.parent == nil and not prepend then
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2014 sapier
|
--Copyright (C) 2014 sapier
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
|
|
@ -10,7 +10,7 @@ end
|
||||||
|
|
||||||
function core.handle_async(func, callback, ...)
|
function core.handle_async(func, callback, ...)
|
||||||
assert(type(func) == "function" and type(callback) == "function",
|
assert(type(func) == "function" and type(callback) == "function",
|
||||||
"Invalid minetest.handle_async invocation")
|
"Invalid core.handle_async invocation")
|
||||||
local args = {n = select("#", ...), ...}
|
local args = {n = select("#", ...), ...}
|
||||||
local mod_origin = core.get_last_run_mod()
|
local mod_origin = core.get_last_run_mod()
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
-- Minetest: builtin/auth.lua
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Builtin authentication handler
|
-- Builtin authentication handler
|
||||||
--
|
--
|
||||||
|
@ -95,11 +93,11 @@ core.builtin_auth_handler = {
|
||||||
for priv, value in pairs(privileges) do
|
for priv, value in pairs(privileges) do
|
||||||
-- Warnings for improper API usage
|
-- Warnings for improper API usage
|
||||||
if value == false then
|
if value == false then
|
||||||
core.log('deprecated', "`false` value given to `minetest.set_player_privs`, "..
|
core.log('deprecated', "`false` value given to `core.set_player_privs`, "..
|
||||||
"this is almost certainly a bug, "..
|
"this is almost certainly a bug, "..
|
||||||
"granting a privilege rather than revoking it")
|
"granting a privilege rather than revoking it")
|
||||||
elseif value ~= true then
|
elseif value ~= true then
|
||||||
core.log('deprecated', "non-`true` value given to `minetest.set_player_privs`")
|
core.log('deprecated', "non-`true` value given to `core.set_player_privs`")
|
||||||
end
|
end
|
||||||
-- Run grant callbacks
|
-- Run grant callbacks
|
||||||
if prev_privs[priv] == nil then
|
if prev_privs[priv] == nil then
|
||||||
|
@ -196,7 +194,7 @@ function core.change_player_privs(name, changes)
|
||||||
elseif change == false then
|
elseif change == false then
|
||||||
privs[priv] = nil
|
privs[priv] = nil
|
||||||
else
|
else
|
||||||
error("non-bool value given to `minetest.change_player_privs`")
|
error("non-bool value given to `core.change_player_privs`")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
core.set_player_privs(name, privs)
|
core.set_player_privs(name, privs)
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
-- Minetest: builtin/game/chat.lua
|
|
||||||
|
|
||||||
local S = core.get_translator("__builtin")
|
local S = core.get_translator("__builtin")
|
||||||
|
|
||||||
-- Helper function that implements search and replace without pattern matching
|
-- Helper function that implements search and replace without pattern matching
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
-- Minetest: builtin/constants.lua
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Constants values for use with the Lua API
|
-- Constants values for use with the Lua API
|
||||||
--
|
--
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
-- Minetest: builtin/deprecated.lua
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- EnvRef
|
-- EnvRef
|
||||||
--
|
--
|
||||||
|
@ -35,9 +33,9 @@ local settings = core.settings
|
||||||
|
|
||||||
local function setting_proxy(name)
|
local function setting_proxy(name)
|
||||||
return function(...)
|
return function(...)
|
||||||
core.log("deprecated", "WARNING: minetest.setting_* "..
|
core.log("deprecated", "WARNING: core.setting_* "..
|
||||||
"functions are deprecated. "..
|
"functions are deprecated. "..
|
||||||
"Use methods on the minetest.settings object.")
|
"Use methods on the core.settings object.")
|
||||||
return settings[name](settings, ...)
|
return settings[name](settings, ...)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
-- Minetest: builtin/detached_inventory.lua
|
|
||||||
|
|
||||||
core.detached_inventories = {}
|
core.detached_inventories = {}
|
||||||
|
|
||||||
local create_detached_inventory_raw = core.create_detached_inventory_raw
|
local create_detached_inventory_raw = core.create_detached_inventory_raw
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
-- Minetest: builtin/item.lua
|
|
||||||
|
|
||||||
local builtin_shared = ...
|
local builtin_shared = ...
|
||||||
local SCALE = 0.667
|
local SCALE = 0.667
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
-- Minetest: builtin/features.lua
|
|
||||||
|
|
||||||
core.features = {
|
core.features = {
|
||||||
glasslike_framed = true,
|
glasslike_framed = true,
|
||||||
nodebox_as_selectionbox = true,
|
nodebox_as_selectionbox = true,
|
||||||
|
@ -45,6 +43,8 @@ core.features = {
|
||||||
hotbar_hud_element = true,
|
hotbar_hud_element = true,
|
||||||
bulk_lbms = true,
|
bulk_lbms = true,
|
||||||
abm_without_neighbors = true,
|
abm_without_neighbors = true,
|
||||||
|
biome_weights = true,
|
||||||
|
particle_blend_clip = true,
|
||||||
}
|
}
|
||||||
|
|
||||||
function core.has_feature(arg)
|
function core.has_feature(arg)
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
-- Minetest: builtin/item.lua
|
|
||||||
|
|
||||||
local builtin_shared = ...
|
local builtin_shared = ...
|
||||||
|
|
||||||
local function copy_pointed_thing(pointed_thing)
|
local function copy_pointed_thing(pointed_thing)
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
-- Minetest: builtin/item_entity.lua
|
|
||||||
|
|
||||||
function core.spawn_item(pos, item)
|
function core.spawn_item(pos, item)
|
||||||
-- Take item in any format
|
-- Take item in any format
|
||||||
local stack = ItemStack(item)
|
local stack = ItemStack(item)
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
-- Minetest: builtin/misc.lua
|
|
||||||
|
|
||||||
local S = core.get_translator("__builtin")
|
local S = core.get_translator("__builtin")
|
||||||
|
|
||||||
--
|
--
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
-- Minetest: builtin/misc_s.lua
|
|
||||||
-- The distinction of what goes here is a bit tricky, basically it's everything
|
-- The distinction of what goes here is a bit tricky, basically it's everything
|
||||||
-- that does not (directly or indirectly) need access to ServerEnvironment,
|
-- that does not (directly or indirectly) need access to ServerEnvironment,
|
||||||
-- Server or writable access to IGameDef on the engine side.
|
-- Server or writable access to IGameDef on the engine side.
|
||||||
|
@ -25,11 +24,8 @@ end
|
||||||
|
|
||||||
|
|
||||||
function core.get_item_group(name, group)
|
function core.get_item_group(name, group)
|
||||||
if not core.registered_items[name] or not
|
local def = core.registered_items[name]
|
||||||
core.registered_items[name].groups[group] then
|
return def and def.groups[group] or 0
|
||||||
return 0
|
|
||||||
end
|
|
||||||
return core.registered_items[name].groups[group]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,11 +36,7 @@ end
|
||||||
|
|
||||||
|
|
||||||
function core.setting_get_pos(name)
|
function core.setting_get_pos(name)
|
||||||
local value = core.settings:get(name)
|
return core.settings:get_pos(name)
|
||||||
if not value then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
return core.string_to_pos(value)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
-- Minetest: builtin/privileges.lua
|
|
||||||
|
|
||||||
local S = core.get_translator("__builtin")
|
local S = core.get_translator("__builtin")
|
||||||
|
|
||||||
--
|
--
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
-- Minetest: builtin/register.lua
|
|
||||||
|
|
||||||
local builtin_shared = ...
|
local builtin_shared = ...
|
||||||
local S = core.get_translator("__builtin")
|
local S = core.get_translator("__builtin")
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
-- Minetest: builtin/static_spawn.lua
|
|
||||||
|
|
||||||
local static_spawnpoint_string = core.settings:get("static_spawnpoint")
|
local static_spawnpoint_string = core.settings:get("static_spawnpoint")
|
||||||
if static_spawnpoint_string and
|
if static_spawnpoint_string and
|
||||||
static_spawnpoint_string ~= "" and
|
static_spawnpoint_string ~= "" and
|
||||||
not core.setting_get_pos("static_spawnpoint") then
|
not core.settings:get_pos("static_spawnpoint") then
|
||||||
error('The static_spawnpoint setting is invalid: "' ..
|
error('The static_spawnpoint setting is invalid: "' ..
|
||||||
static_spawnpoint_string .. '"')
|
static_spawnpoint_string .. '"')
|
||||||
end
|
end
|
||||||
|
|
|
@ -35,7 +35,7 @@ end
|
||||||
local log = function(...) end
|
local log = function(...) end
|
||||||
--local log = print
|
--local log = print
|
||||||
|
|
||||||
minetest.register_allow_player_inventory_action(function(_, action, inv, info)
|
core.register_allow_player_inventory_action(function(_, action, inv, info)
|
||||||
log("\tallow " .. action, info.count or info.stack:to_string())
|
log("\tallow " .. action, info.count or info.stack:to_string())
|
||||||
|
|
||||||
if action == "move" then
|
if action == "move" then
|
||||||
|
@ -69,7 +69,7 @@ minetest.register_allow_player_inventory_action(function(_, action, inv, info)
|
||||||
return -- Unlimited
|
return -- Unlimited
|
||||||
end)
|
end)
|
||||||
|
|
||||||
minetest.register_on_player_inventory_action(function(_, action, inv, info)
|
core.register_on_player_inventory_action(function(_, action, inv, info)
|
||||||
log("\ton " .. action, info.count or info.stack:to_string())
|
log("\ton " .. action, info.count or info.stack:to_string())
|
||||||
|
|
||||||
if action == "take" or action == "put" then
|
if action == "take" or action == "put" then
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
--
|
--
|
||||||
-- This file contains built-in stuff in Minetest implemented in Lua.
|
-- This file contains built-in stuff in Luanti implemented in Lua.
|
||||||
--
|
--
|
||||||
-- It is always loaded and executed after registration of the C API,
|
-- It is always loaded and executed after registration of the C API,
|
||||||
-- before loading and running any mods.
|
-- before loading and running any mods.
|
||||||
|
|
|
@ -11,11 +11,6 @@ end
|
||||||
core.async_event_handler = handle_job
|
core.async_event_handler = handle_job
|
||||||
|
|
||||||
function core.handle_async(func, parameter, callback)
|
function core.handle_async(func, parameter, callback)
|
||||||
-- Serialize function
|
|
||||||
local serialized_func = string.dump(func)
|
|
||||||
|
|
||||||
assert(serialized_func ~= nil)
|
|
||||||
|
|
||||||
-- Serialize parameters
|
-- Serialize parameters
|
||||||
local serialized_param = core.serialize(parameter)
|
local serialized_param = core.serialize(parameter)
|
||||||
|
|
||||||
|
@ -23,7 +18,7 @@ function core.handle_async(func, parameter, callback)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
local jobid = core.do_async_callback(serialized_func, serialized_param)
|
local jobid = core.do_async_callback(func, serialized_param)
|
||||||
|
|
||||||
core.async_jobs[jobid] = callback
|
core.async_jobs[jobid] = callback
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2014 sapier
|
--Copyright (C) 2014 sapier
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2018-24 rubenwardy
|
--Copyright (C) 2018-24 rubenwardy
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -182,6 +182,23 @@ function contentdb.get_package_by_id(id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function contentdb.calculate_package_id(type, author, name)
|
||||||
|
local id = author:lower() .. "/"
|
||||||
|
if (type == nil or type == "game") and #name > 5 and name:sub(#name - 4) == "_game" then
|
||||||
|
id = id .. name:sub(1, #name - 5)
|
||||||
|
else
|
||||||
|
id = id .. name
|
||||||
|
end
|
||||||
|
return id
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function contentdb.get_package_by_info(author, name)
|
||||||
|
local id = contentdb.calculate_package_id(nil, author, name)
|
||||||
|
return contentdb.package_by_id[id]
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Create a coroutine from `fn` and provide results to `callback` when complete (dead).
|
-- Create a coroutine from `fn` and provide results to `callback` when complete (dead).
|
||||||
-- Returns a resumer function.
|
-- Returns a resumer function.
|
||||||
local function make_callback_coroutine(fn, callback)
|
local function make_callback_coroutine(fn, callback)
|
||||||
|
@ -375,7 +392,7 @@ function contentdb.resolve_dependencies(package, game, callback)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function fetch_pkgs(params)
|
local function fetch_pkgs()
|
||||||
local version = core.get_version()
|
local version = core.get_version()
|
||||||
local base_url = core.settings:get("contentdb_url")
|
local base_url = core.settings:get("contentdb_url")
|
||||||
local url = base_url ..
|
local url = base_url ..
|
||||||
|
@ -412,49 +429,43 @@ local function fetch_pkgs(params)
|
||||||
if not packages or #packages == 0 then
|
if not packages or #packages == 0 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local aliases = {}
|
return packages
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function contentdb.set_packages_from_api(packages)
|
||||||
|
contentdb.package_by_id = {}
|
||||||
|
contentdb.aliases = {}
|
||||||
|
|
||||||
for _, package in pairs(packages) do
|
for _, package in pairs(packages) do
|
||||||
local name_len = #package.name
|
package.id = contentdb.calculate_package_id(package.type, package.author, package.name)
|
||||||
-- This must match what contentdb.update_paths() does!
|
|
||||||
package.id = package.author:lower() .. "/"
|
|
||||||
if package.type == "game" and name_len > 5 and package.name:sub(name_len - 4) == "_game" then
|
|
||||||
package.id = package.id .. package.name:sub(1, name_len - 5)
|
|
||||||
else
|
|
||||||
package.id = package.id .. package.name
|
|
||||||
end
|
|
||||||
|
|
||||||
package.url_part = core.urlencode(package.author) .. "/" .. core.urlencode(package.name)
|
package.url_part = core.urlencode(package.author) .. "/" .. core.urlencode(package.name)
|
||||||
|
|
||||||
|
contentdb.package_by_id[package.id] = package
|
||||||
|
|
||||||
if package.aliases then
|
if package.aliases then
|
||||||
for _, alias in ipairs(package.aliases) do
|
for _, alias in ipairs(package.aliases) do
|
||||||
-- We currently don't support name changing
|
-- We currently don't support name changing
|
||||||
local suffix = "/" .. package.name
|
local suffix = "/" .. package.name
|
||||||
if alias:sub(-#suffix) == suffix then
|
if alias:sub(-#suffix) == suffix then
|
||||||
aliases[alias:lower()] = package.id
|
contentdb.aliases[alias:lower()] = package.id
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return { packages = packages, aliases = aliases }
|
contentdb.load_ok = true
|
||||||
|
contentdb.load_error = false
|
||||||
|
contentdb.packages = packages
|
||||||
|
contentdb.packages_full = packages
|
||||||
|
contentdb.packages_full_unordered = packages
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function contentdb.fetch_pkgs(callback)
|
function contentdb.fetch_pkgs(callback)
|
||||||
contentdb.loading = true
|
contentdb.loading = true
|
||||||
core.handle_async(fetch_pkgs, nil, function(result)
|
core.handle_async(fetch_pkgs, nil, function(result)
|
||||||
if result then
|
if result then
|
||||||
contentdb.load_ok = true
|
contentdb.set_packages_from_api(result)
|
||||||
contentdb.load_error = false
|
|
||||||
contentdb.packages = result.packages
|
|
||||||
contentdb.packages_full = result.packages
|
|
||||||
contentdb.packages_full_unordered = result.packages
|
|
||||||
contentdb.aliases = result.aliases
|
|
||||||
|
|
||||||
for _, package in ipairs(result.packages) do
|
|
||||||
contentdb.package_by_id[package.id] = package
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
contentdb.load_error = true
|
contentdb.load_error = true
|
||||||
end
|
end
|
||||||
|
@ -554,30 +565,107 @@ function contentdb.filter_packages(query, by_type)
|
||||||
end
|
end
|
||||||
|
|
||||||
local keywords = {}
|
local keywords = {}
|
||||||
for word in query:lower():gmatch("%S+") do
|
for word in query:gmatch("%S+") do
|
||||||
table.insert(keywords, word)
|
table.insert(keywords, word:lower())
|
||||||
|
end
|
||||||
|
|
||||||
|
local function contains_all_keywords(str)
|
||||||
|
str = str:lower()
|
||||||
|
for _, keyword in ipairs(keywords) do
|
||||||
|
if not str:find(keyword, 1, true) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
local function matches_keywords(package)
|
local function matches_keywords(package)
|
||||||
for k = 1, #keywords do
|
return contains_all_keywords(package.name) or
|
||||||
local keyword = keywords[k]
|
contains_all_keywords(package.title) or
|
||||||
|
contains_all_keywords(package.author) or
|
||||||
if string.find(package.name:lower(), keyword, 1, true) or
|
contains_all_keywords(package.short_description)
|
||||||
string.find(package.title:lower(), keyword, 1, true) or
|
|
||||||
string.find(package.author:lower(), keyword, 1, true) or
|
|
||||||
string.find(package.short_description:lower(), keyword, 1, true) then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
contentdb.packages = {}
|
contentdb.packages = {}
|
||||||
for _, package in pairs(contentdb.packages_full) do
|
for _, package in pairs(contentdb.packages_full) do
|
||||||
if (query == "" or matches_keywords(package)) and
|
if (query == "" or matches_keywords(package)) and
|
||||||
(by_type == nil or package.type == by_type) then
|
(by_type == nil or package.type == by_type) then
|
||||||
contentdb.packages[#contentdb.packages + 1] = package
|
table.insert(contentdb.packages, package)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function contentdb.get_full_package_info(package, callback)
|
||||||
|
assert(package)
|
||||||
|
if package.full_info then
|
||||||
|
callback(package.full_info)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local function fetch(params)
|
||||||
|
local version = core.get_version()
|
||||||
|
local base_url = core.settings:get("contentdb_url")
|
||||||
|
|
||||||
|
local languages
|
||||||
|
local current_language = core.get_language()
|
||||||
|
if current_language ~= "" then
|
||||||
|
languages = { current_language, "en;q=0.8" }
|
||||||
|
else
|
||||||
|
languages = { "en" }
|
||||||
|
end
|
||||||
|
|
||||||
|
local url = base_url ..
|
||||||
|
"/api/packages/" .. params.package.url_part .. "/for-client/?" ..
|
||||||
|
"protocol_version=" .. core.urlencode(core.get_max_supp_proto()) ..
|
||||||
|
"&engine_version=" .. core.urlencode(version.string) ..
|
||||||
|
"&formspec_version=" .. core.urlencode(core.get_formspec_version()) ..
|
||||||
|
"&include_images=false"
|
||||||
|
local http = core.get_http_api()
|
||||||
|
local response = http.fetch_sync({
|
||||||
|
url = url,
|
||||||
|
extra_headers = {
|
||||||
|
"Accept-Language: " .. table.concat(languages, ", ")
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if not response.succeeded then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
return core.parse_json(response.data)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function my_callback(value)
|
||||||
|
package.full_info = value
|
||||||
|
callback(value)
|
||||||
|
end
|
||||||
|
|
||||||
|
if not core.handle_async(fetch, { package = package }, my_callback) then
|
||||||
|
core.log("error", "ERROR: async event failed")
|
||||||
|
callback(nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function contentdb.get_formspec_padding()
|
||||||
|
-- Padding is increased on Android to account for notches
|
||||||
|
-- TODO: use Android API to determine size of cut outs
|
||||||
|
return { x = PLATFORM == "Android" and 1 or 0.5, y = PLATFORM == "Android" and 0.25 or 0.5 }
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function contentdb.get_formspec_size()
|
||||||
|
local window = core.get_window_info()
|
||||||
|
local size = { x = window.max_formspec_size.x, y = window.max_formspec_size.y }
|
||||||
|
|
||||||
|
-- Minimum formspec size
|
||||||
|
local min_x = 15.5
|
||||||
|
local min_y = 10
|
||||||
|
if size.x < min_x or size.y < min_y then
|
||||||
|
local scale = math.max(min_x / size.x, min_y / size.y)
|
||||||
|
size.x = size.x * scale
|
||||||
|
size.y = size.y * scale
|
||||||
|
end
|
||||||
|
|
||||||
|
return size
|
||||||
|
end
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2018-20 rubenwardy
|
--Copyright (C) 2018-20 rubenwardy
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
if not core.get_http_api then
|
if not core.get_http_api then
|
||||||
function create_contentdb_dlg()
|
function create_contentdb_dlg()
|
||||||
return messagebox("contentdb",
|
return messagebox("contentdb",
|
||||||
fgettext("ContentDB is not available when Minetest was compiled without cURL"))
|
fgettext("ContentDB is not available when Luanti was compiled without cURL"))
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
@ -26,68 +26,20 @@ end
|
||||||
-- Filter
|
-- Filter
|
||||||
local search_string = ""
|
local search_string = ""
|
||||||
local cur_page = 1
|
local cur_page = 1
|
||||||
local num_per_page = 5
|
local filter_type
|
||||||
local filter_type = 1
|
|
||||||
local filter_types_titles = {
|
|
||||||
fgettext("All packages"),
|
|
||||||
fgettext("Games"),
|
|
||||||
fgettext("Mods"),
|
|
||||||
fgettext("Texture packs"),
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Automatic package installation
|
-- Automatic package installation
|
||||||
local auto_install_spec = nil
|
local auto_install_spec = nil
|
||||||
|
|
||||||
local filter_types_type = {
|
|
||||||
nil,
|
local filter_type_names = {
|
||||||
"game",
|
{ "type_all", nil },
|
||||||
"mod",
|
{ "type_game", "game" },
|
||||||
"txp",
|
{ "type_mod", "mod" },
|
||||||
|
{ "type_txp", "txp" },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
local function install_or_update_package(this, package)
|
|
||||||
local install_parent
|
|
||||||
if package.type == "mod" then
|
|
||||||
install_parent = core.get_modpath()
|
|
||||||
elseif package.type == "game" then
|
|
||||||
install_parent = core.get_gamepath()
|
|
||||||
elseif package.type == "txp" then
|
|
||||||
install_parent = core.get_texturepath()
|
|
||||||
else
|
|
||||||
error("Unknown package type: " .. package.type)
|
|
||||||
end
|
|
||||||
|
|
||||||
if package.queued or package.downloading then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local function on_confirm()
|
|
||||||
local dlg = create_install_dialog(package)
|
|
||||||
dlg:set_parent(this)
|
|
||||||
this:hide()
|
|
||||||
dlg:show()
|
|
||||||
|
|
||||||
dlg:load_deps()
|
|
||||||
end
|
|
||||||
|
|
||||||
if package.type == "mod" and #pkgmgr.games == 0 then
|
|
||||||
local dlg = messagebox("install_game",
|
|
||||||
fgettext("You need to install a game before you can install a mod"))
|
|
||||||
dlg:set_parent(this)
|
|
||||||
this:hide()
|
|
||||||
dlg:show()
|
|
||||||
elseif not package.path and core.is_dir(install_parent .. DIR_DELIM .. package.name) then
|
|
||||||
local dlg = create_confirm_overwrite(package, on_confirm)
|
|
||||||
dlg:set_parent(this)
|
|
||||||
this:hide()
|
|
||||||
dlg:show()
|
|
||||||
else
|
|
||||||
on_confirm()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-- Resolves the package specification stored in auto_install_spec into an actual package.
|
-- Resolves the package specification stored in auto_install_spec into an actual package.
|
||||||
-- May only be called after the package list has been loaded successfully.
|
-- May only be called after the package list has been loaded successfully.
|
||||||
local function resolve_auto_install_spec()
|
local function resolve_auto_install_spec()
|
||||||
|
@ -145,7 +97,7 @@ end
|
||||||
local function sort_and_filter_pkgs()
|
local function sort_and_filter_pkgs()
|
||||||
contentdb.update_paths()
|
contentdb.update_paths()
|
||||||
contentdb.sort_packages()
|
contentdb.sort_packages()
|
||||||
contentdb.filter_packages(search_string, filter_types_type[filter_type])
|
contentdb.filter_packages(search_string, filter_type)
|
||||||
|
|
||||||
local auto_install_pkg = resolve_auto_install_spec()
|
local auto_install_pkg = resolve_auto_install_spec()
|
||||||
if auto_install_pkg then
|
if auto_install_pkg then
|
||||||
|
@ -176,72 +128,151 @@ local function load()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function get_info_formspec(text)
|
local function get_info_formspec(size, padding, text)
|
||||||
local H = 9.5
|
|
||||||
return table.concat({
|
return table.concat({
|
||||||
"formspec_version[6]",
|
"formspec_version[6]",
|
||||||
"size[15.75,9.5]",
|
"size[", size.x, ",", size.y, "]",
|
||||||
core.settings:get_bool("touch_gui") and "padding[0.01,0.01]" or "position[0.5,0.55]",
|
"padding[0,0]",
|
||||||
|
"bgcolor[;true]",
|
||||||
|
|
||||||
"label[4,4.35;", text, "]",
|
"label[", padding.x + 3.625, ",4.35;", text, "]",
|
||||||
"container[0,", H - 0.8 - 0.375, "]",
|
"container[", padding.x, ",", size.y - 0.8 - padding.y, "]",
|
||||||
"button[0.375,0;5,0.8;back;", fgettext("Back to Main Menu"), "]",
|
"button[0,0;2,0.8;back;", fgettext("Back"), "]",
|
||||||
"container_end[]",
|
"container_end[]",
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Determines how to fit `num_per_page` into `size` space
|
||||||
|
local function fit_cells(num_per_page, size)
|
||||||
|
local cell_spacing = 0.5
|
||||||
|
local columns = 1
|
||||||
|
local cell_w, cell_h
|
||||||
|
-- Fit cells into the available height
|
||||||
|
while true do
|
||||||
|
cell_w = (size.x - (columns-1)*cell_spacing) / columns
|
||||||
|
cell_h = cell_w / 4
|
||||||
|
|
||||||
|
local required_height = math.ceil(num_per_page / columns) * (cell_h + cell_spacing) - cell_spacing
|
||||||
|
-- Add 0.1 to be more lenient
|
||||||
|
if required_height <= size.y + 0.1 then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
columns = columns + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
return cell_spacing, columns, cell_w, cell_h
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function calculate_num_per_page()
|
||||||
|
local size = contentdb.get_formspec_size()
|
||||||
|
local padding = contentdb.get_formspec_padding()
|
||||||
|
local window = core.get_window_info()
|
||||||
|
|
||||||
|
size.x = size.x - padding.x * 2
|
||||||
|
size.y = size.y - padding.y * 2 - 1.425 - 0.25 - 0.8
|
||||||
|
|
||||||
|
local coordToPx = window.size.x / window.max_formspec_size.x / window.real_gui_scaling
|
||||||
|
|
||||||
|
local num_per_page = 12
|
||||||
|
while num_per_page > 2 do
|
||||||
|
local _, _, cell_w, _ = fit_cells(num_per_page, size)
|
||||||
|
if cell_w * coordToPx > 350 then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
num_per_page = num_per_page - 1
|
||||||
|
end
|
||||||
|
return num_per_page
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
local function get_formspec(dlgdata)
|
local function get_formspec(dlgdata)
|
||||||
|
local window_padding = contentdb.get_formspec_padding()
|
||||||
|
local size = contentdb.get_formspec_size()
|
||||||
|
|
||||||
if contentdb.loading then
|
if contentdb.loading then
|
||||||
return get_info_formspec(fgettext("Loading..."))
|
return get_info_formspec(size, window_padding, fgettext("Loading..."))
|
||||||
end
|
end
|
||||||
if contentdb.load_error then
|
if contentdb.load_error then
|
||||||
return get_info_formspec(fgettext("No packages could be retrieved"))
|
return get_info_formspec(size, window_padding, fgettext("No packages could be retrieved"))
|
||||||
end
|
end
|
||||||
assert(contentdb.load_ok)
|
assert(contentdb.load_ok)
|
||||||
|
|
||||||
contentdb.update_paths()
|
contentdb.update_paths()
|
||||||
|
|
||||||
|
local num_per_page = dlgdata.num_per_page
|
||||||
dlgdata.pagemax = math.max(math.ceil(#contentdb.packages / num_per_page), 1)
|
dlgdata.pagemax = math.max(math.ceil(#contentdb.packages / num_per_page), 1)
|
||||||
if cur_page > dlgdata.pagemax then
|
if cur_page > dlgdata.pagemax then
|
||||||
cur_page = 1
|
cur_page = 1
|
||||||
end
|
end
|
||||||
|
|
||||||
local W = 15.75
|
local W = size.x - window_padding.x * 2
|
||||||
local H = 9.5
|
local H = size.y - window_padding.y * 2
|
||||||
|
|
||||||
|
local category_x = 0
|
||||||
|
local number_category_buttons = 4
|
||||||
|
local max_button_w = (W - 0.375 - 0.25 - 7) / number_category_buttons
|
||||||
|
local category_button_w = math.min(max_button_w, 3)
|
||||||
|
local function make_category_button(name, label, selected)
|
||||||
|
category_x = category_x + 1
|
||||||
|
local color = selected and mt_color_green or ""
|
||||||
|
return ("style[%s;bgcolor=%s]button[%f,0;%f,0.8;%s;%s]"):format(name, color,
|
||||||
|
(category_x - 1) * category_button_w, category_button_w, name, label)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local selected_type = filter_type
|
||||||
|
|
||||||
|
local search_box_width = W - 0.375 - 0.25 - 2*0.8
|
||||||
|
- number_category_buttons * category_button_w
|
||||||
local formspec = {
|
local formspec = {
|
||||||
"formspec_version[6]",
|
"formspec_version[7]",
|
||||||
"size[15.75,9.5]",
|
"size[", size.x, ",", size.y, "]",
|
||||||
core.settings:get_bool("touch_gui") and "padding[0.01,0.01]" or "position[0.5,0.55]",
|
"padding[0,0]",
|
||||||
|
"bgcolor[;true]",
|
||||||
|
|
||||||
"style[status,downloading,queued;border=false]",
|
"container[", window_padding.x, ",", window_padding.y, "]",
|
||||||
|
|
||||||
"container[0.375,0.375]",
|
-- Top-left: categories
|
||||||
"field[0,0;7.225,0.8;search_string;;", core.formspec_escape(search_string), "]",
|
make_category_button("type_all", fgettext("All"), selected_type == nil),
|
||||||
|
make_category_button("type_game", fgettext("Games"), selected_type == "game"),
|
||||||
|
make_category_button("type_mod", fgettext("Mods"), selected_type == "mod"),
|
||||||
|
make_category_button("type_txp", fgettext("Texture Packs"), selected_type == "txp"),
|
||||||
|
|
||||||
|
-- Top-right: Search
|
||||||
|
"container[", W - search_box_width - 0.8*2, ",0]",
|
||||||
|
"field[0,0;", search_box_width, ",0.8;search_string;;", core.formspec_escape(search_string), "]",
|
||||||
"field_enter_after_edit[search_string;true]",
|
"field_enter_after_edit[search_string;true]",
|
||||||
"image_button[7.3,0;0.8,0.8;", core.formspec_escape(defaulttexturedir .. "search.png"), ";search;]",
|
"image_button[", search_box_width, ",0;0.8,0.8;",
|
||||||
"image_button[8.125,0;0.8,0.8;", core.formspec_escape(defaulttexturedir .. "clear.png"), ";clear;]",
|
core.formspec_escape(defaulttexturedir .. "search.png"), ";search;]",
|
||||||
"dropdown[9.175,0;2.7875,0.8;type;", table.concat(filter_types_titles, ","), ";", filter_type, "]",
|
"image_button[", search_box_width + 0.8, ",0;0.8,0.8;",
|
||||||
|
core.formspec_escape(defaulttexturedir .. "clear.png"), ";clear;]",
|
||||||
"container_end[]",
|
"container_end[]",
|
||||||
|
|
||||||
-- Page nav buttons
|
-- Bottom strip start
|
||||||
"container[0,", H - 0.8 - 0.375, "]",
|
"container[0,", H - 0.8, "]",
|
||||||
"button[0.375,0;5,0.8;back;", fgettext("Back to Main Menu"), "]",
|
"button[0,0;2,0.8;back;", fgettext("Back"), "]",
|
||||||
|
|
||||||
"container[", W - 0.375 - 0.8*4 - 2, ",0]",
|
-- Bottom-center: Page nav buttons
|
||||||
"image_button[0,0;0.8,0.8;", core.formspec_escape(defaulttexturedir), "start_icon.png;pstart;]",
|
"container[", (W - 1*4 - 2) / 2, ",0]",
|
||||||
"image_button[0.8,0;0.8,0.8;", core.formspec_escape(defaulttexturedir), "prev_icon.png;pback;]",
|
"image_button[0,0;1,0.8;", core.formspec_escape(defaulttexturedir), "start_icon.png;pstart;]",
|
||||||
|
"image_button[1,0;1,0.8;", core.formspec_escape(defaulttexturedir), "prev_icon.png;pback;]",
|
||||||
"style[pagenum;border=false]",
|
"style[pagenum;border=false]",
|
||||||
"button[1.6,0;2,0.8;pagenum;", tonumber(cur_page), " / ", tonumber(dlgdata.pagemax), "]",
|
"button[2,0;2,0.8;pagenum;", tonumber(cur_page), " / ", tonumber(dlgdata.pagemax), "]",
|
||||||
"image_button[3.6,0;0.8,0.8;", core.formspec_escape(defaulttexturedir), "next_icon.png;pnext;]",
|
"image_button[4,0;1,0.8;", core.formspec_escape(defaulttexturedir), "next_icon.png;pnext;]",
|
||||||
"image_button[4.4,0;0.8,0.8;", core.formspec_escape(defaulttexturedir), "end_icon.png;pend;]",
|
"image_button[5,0;1,0.8;", core.formspec_escape(defaulttexturedir), "end_icon.png;pend;]",
|
||||||
"container_end[]",
|
"container_end[]", -- page nav end
|
||||||
|
|
||||||
"container_end[]",
|
-- Bottom-right: updating
|
||||||
|
"container[", W - 3, ",0]",
|
||||||
|
"style[status,downloading,queued;border=false]",
|
||||||
}
|
}
|
||||||
|
|
||||||
if contentdb.number_downloading > 0 then
|
if contentdb.number_downloading > 0 then
|
||||||
formspec[#formspec + 1] = "button[12.5875,0.375;2.7875,0.8;downloading;"
|
formspec[#formspec + 1] = "button[0,0;3,0.8;downloading;"
|
||||||
if #contentdb.download_queue > 0 then
|
if #contentdb.download_queue > 0 then
|
||||||
formspec[#formspec + 1] = fgettext("$1 downloading,\n$2 queued",
|
formspec[#formspec + 1] = fgettext("$1 downloading,\n$2 queued",
|
||||||
contentdb.number_downloading, #contentdb.download_queue)
|
contentdb.number_downloading, #contentdb.download_queue)
|
||||||
|
@ -260,16 +291,19 @@ local function get_formspec(dlgdata)
|
||||||
end
|
end
|
||||||
|
|
||||||
if num_avail_updates == 0 then
|
if num_avail_updates == 0 then
|
||||||
formspec[#formspec + 1] = "button[12.5875,0.375;2.7875,0.8;status;"
|
formspec[#formspec + 1] = "button[0,0;3,0.8;status;"
|
||||||
formspec[#formspec + 1] = fgettext("No updates")
|
formspec[#formspec + 1] = fgettext("No updates")
|
||||||
formspec[#formspec + 1] = "]"
|
formspec[#formspec + 1] = "]"
|
||||||
else
|
else
|
||||||
formspec[#formspec + 1] = "button[12.5875,0.375;2.7875,0.8;update_all;"
|
formspec[#formspec + 1] = "button[0,0;3,0.8;update_all;"
|
||||||
formspec[#formspec + 1] = fgettext("Update All [$1]", num_avail_updates)
|
formspec[#formspec + 1] = fgettext("Update All [$1]", num_avail_updates)
|
||||||
formspec[#formspec + 1] = "]"
|
formspec[#formspec + 1] = "]"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
formspec[#formspec + 1] = "container_end[]" -- updating end
|
||||||
|
formspec[#formspec + 1] = "container_end[]" -- bottom strip end
|
||||||
|
|
||||||
if #contentdb.packages == 0 then
|
if #contentdb.packages == 0 then
|
||||||
formspec[#formspec + 1] = "label[4,4.75;"
|
formspec[#formspec + 1] = "label[4,4.75;"
|
||||||
formspec[#formspec + 1] = fgettext("No results")
|
formspec[#formspec + 1] = fgettext("No results")
|
||||||
|
@ -281,81 +315,86 @@ local function get_formspec(dlgdata)
|
||||||
formspec[#formspec + 1] = "tooltip[downloading;" .. fgettext("Downloading...") .. tooltip_colors
|
formspec[#formspec + 1] = "tooltip[downloading;" .. fgettext("Downloading...") .. tooltip_colors
|
||||||
formspec[#formspec + 1] = "tooltip[queued;" .. fgettext("Queued") .. tooltip_colors
|
formspec[#formspec + 1] = "tooltip[queued;" .. fgettext("Queued") .. tooltip_colors
|
||||||
|
|
||||||
|
formspec[#formspec + 1] = "container[0,1.425]"
|
||||||
|
|
||||||
|
local cell_spacing, columns, cell_w, cell_h = fit_cells(num_per_page, {
|
||||||
|
x = W,
|
||||||
|
y = H - 1.425 - 0.25 - 0.8
|
||||||
|
})
|
||||||
|
local img_w = cell_h * 3 / 2
|
||||||
|
|
||||||
local start_idx = (cur_page - 1) * num_per_page + 1
|
local start_idx = (cur_page - 1) * num_per_page + 1
|
||||||
for i=start_idx, math.min(#contentdb.packages, start_idx+num_per_page-1) do
|
for i=start_idx, math.min(#contentdb.packages, start_idx+num_per_page-1) do
|
||||||
local package = contentdb.packages[i]
|
local package = contentdb.packages[i]
|
||||||
local container_y = (i - start_idx) * 1.375 + (2*0.375 + 0.8)
|
|
||||||
formspec[#formspec + 1] = "container[0.375,"
|
|
||||||
formspec[#formspec + 1] = container_y
|
|
||||||
formspec[#formspec + 1] = "]"
|
|
||||||
|
|
||||||
-- image
|
table.insert_all(formspec, {
|
||||||
formspec[#formspec + 1] = "image[0,0;1.5,1;"
|
"container[",
|
||||||
formspec[#formspec + 1] = core.formspec_escape(get_screenshot(package))
|
(cell_w + cell_spacing) * ((i - start_idx) % columns),
|
||||||
formspec[#formspec + 1] = "]"
|
",",
|
||||||
|
(cell_h + cell_spacing) * math.floor((i - start_idx) / columns),
|
||||||
|
"]",
|
||||||
|
|
||||||
-- title
|
"box[0,0;", cell_w, ",", cell_h, ";#ffffff11]",
|
||||||
formspec[#formspec + 1] = "label[1.875,0.1;"
|
|
||||||
formspec[#formspec + 1] = core.formspec_escape(
|
|
||||||
core.colorize(mt_color_green, package.title) ..
|
|
||||||
core.colorize("#BFBFBF", " by " .. package.author))
|
|
||||||
formspec[#formspec + 1] = "]"
|
|
||||||
|
|
||||||
-- buttons
|
-- image,
|
||||||
local description_width = W - 2.625 - 2 * 0.7 - 2 * 0.15
|
"image[0,0;", img_w, ",", cell_h, ";",
|
||||||
|
core.formspec_escape(get_screenshot(package, package.thumbnail, 2)), "]",
|
||||||
|
|
||||||
local second_base = "image_button[-1.55,0;0.7,0.7;" .. core.formspec_escape(defaulttexturedir)
|
"label[", img_w + 0.25 + 0.05, ",0.5;",
|
||||||
local third_base = "image_button[-2.4,0;0.7,0.7;" .. core.formspec_escape(defaulttexturedir)
|
core.formspec_escape(
|
||||||
formspec[#formspec + 1] = "container["
|
core.colorize(mt_color_green, package.title) ..
|
||||||
formspec[#formspec + 1] = W - 0.375*2
|
core.colorize("#BFBFBF", " by " .. package.author)), "]",
|
||||||
formspec[#formspec + 1] = ",0.1]"
|
|
||||||
|
|
||||||
if package.downloading then
|
"textarea[", img_w + 0.25, ",0.75;", cell_w - img_w - 0.25, ",", cell_h - 0.75, ";;;",
|
||||||
formspec[#formspec + 1] = "animated_image[-1.7,-0.15;1,1;downloading;"
|
core.formspec_escape(package.short_description), "]",
|
||||||
formspec[#formspec + 1] = core.formspec_escape(defaulttexturedir)
|
|
||||||
formspec[#formspec + 1] = "cdb_downloading.png;3;400;]"
|
|
||||||
elseif package.queued then
|
|
||||||
formspec[#formspec + 1] = second_base
|
|
||||||
formspec[#formspec + 1] = "cdb_queued.png;queued;]"
|
|
||||||
elseif not package.path then
|
|
||||||
local elem_name = "install_" .. i .. ";"
|
|
||||||
formspec[#formspec + 1] = "style[" .. elem_name .. "bgcolor=#71aa34]"
|
|
||||||
formspec[#formspec + 1] = second_base .. "cdb_add.png;" .. elem_name .. "]"
|
|
||||||
formspec[#formspec + 1] = "tooltip[" .. elem_name .. fgettext("Install") .. tooltip_colors
|
|
||||||
else
|
|
||||||
if package.installed_release < package.release then
|
|
||||||
-- The install_ action also handles updating
|
|
||||||
local elem_name = "install_" .. i .. ";"
|
|
||||||
formspec[#formspec + 1] = "style[" .. elem_name .. "bgcolor=#28ccdf]"
|
|
||||||
formspec[#formspec + 1] = third_base .. "cdb_update.png;" .. elem_name .. "]"
|
|
||||||
formspec[#formspec + 1] = "tooltip[" .. elem_name .. fgettext("Update") .. tooltip_colors
|
|
||||||
|
|
||||||
description_width = description_width - 0.7 - 0.15
|
"style[view_", i, ";border=false]",
|
||||||
end
|
"style[view_", i, ":hovered;bgimg=", core.formspec_escape(defaulttexturedir .. "button_hover_semitrans.png"), "]",
|
||||||
|
"style[view_", i, ":pressed;bgimg=", core.formspec_escape(defaulttexturedir .. "button_press_semitrans.png"), "]",
|
||||||
|
"button[0,0;", cell_w, ",", cell_h, ";view_", i, ";]",
|
||||||
|
})
|
||||||
|
|
||||||
local elem_name = "uninstall_" .. i .. ";"
|
if package.featured then
|
||||||
formspec[#formspec + 1] = "style[" .. elem_name .. "bgcolor=#a93b3b]"
|
table.insert_all(formspec, {
|
||||||
formspec[#formspec + 1] = second_base .. "cdb_clear.png;" .. elem_name .. "]"
|
"tooltip[0,0;0.8,0.8;", fgettext("Featured"), "]",
|
||||||
formspec[#formspec + 1] = "tooltip[" .. elem_name .. fgettext("Uninstall") .. tooltip_colors
|
"image[0.2,0.2;0.4,0.4;", core.formspec_escape(defaulttexturedir .. "server_favorite.png"), "]",
|
||||||
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
local web_elem_name = "view_" .. i .. ";"
|
table.insert_all(formspec, {
|
||||||
formspec[#formspec + 1] = "image_button[-0.7,0;0.7,0.7;" ..
|
"container[", cell_w - 0.625,",", 0.25, "]",
|
||||||
core.formspec_escape(defaulttexturedir) .. "cdb_viewonline.png;" .. web_elem_name .. "]"
|
})
|
||||||
formspec[#formspec + 1] = "tooltip[" .. web_elem_name ..
|
|
||||||
fgettext("View more information in a web browser") .. tooltip_colors
|
|
||||||
formspec[#formspec + 1] = "container_end[]"
|
|
||||||
|
|
||||||
-- description
|
if package.downloading then
|
||||||
formspec[#formspec + 1] = "textarea[1.855,0.3;"
|
table.insert_all(formspec, {
|
||||||
formspec[#formspec + 1] = tostring(description_width)
|
"animated_image[0,0;0.5,0.5;downloading;", core.formspec_escape(defaulttexturedir .. "cdb_downloading.png"),
|
||||||
formspec[#formspec + 1] = ",0.8;;;"
|
";3;400;;]",
|
||||||
formspec[#formspec + 1] = core.formspec_escape(package.short_description)
|
})
|
||||||
formspec[#formspec + 1] = "]"
|
elseif package.queued then
|
||||||
|
table.insert_all(formspec, {
|
||||||
|
"image[0,0;0.5,0.5;", core.formspec_escape(defaulttexturedir .. "cdb_queued.png"), "]",
|
||||||
|
})
|
||||||
|
elseif package.path then
|
||||||
|
if package.installed_release < package.release then
|
||||||
|
table.insert_all(formspec, {
|
||||||
|
"image[0,0;0.5,0.5;", core.formspec_escape(defaulttexturedir .. "cdb_update.png"), "]",
|
||||||
|
})
|
||||||
|
else
|
||||||
|
table.insert_all(formspec, {
|
||||||
|
"image[0.1,0.1;0.3,0.3;", core.formspec_escape(defaulttexturedir .. "checkbox_64.png"), "]",
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
formspec[#formspec + 1] = "container_end[]"
|
table.insert_all(formspec, {
|
||||||
|
"container_end[]",
|
||||||
|
"container_end[]",
|
||||||
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
formspec[#formspec + 1] = "container_end[]"
|
||||||
|
formspec[#formspec + 1] = "container_end[]"
|
||||||
|
|
||||||
return table.concat(formspec)
|
return table.concat(formspec)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -364,14 +403,14 @@ local function handle_submit(this, fields)
|
||||||
if fields.search or fields.key_enter_field == "search_string" then
|
if fields.search or fields.key_enter_field == "search_string" then
|
||||||
search_string = fields.search_string:trim()
|
search_string = fields.search_string:trim()
|
||||||
cur_page = 1
|
cur_page = 1
|
||||||
contentdb.filter_packages(search_string, filter_types_type[filter_type])
|
contentdb.filter_packages(search_string, filter_type)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
if fields.clear then
|
if fields.clear then
|
||||||
search_string = ""
|
search_string = ""
|
||||||
cur_page = 1
|
cur_page = 1
|
||||||
contentdb.filter_packages("", filter_types_type[filter_type])
|
contentdb.filter_packages("", filter_type)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -407,12 +446,11 @@ local function handle_submit(this, fields)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
if fields.type then
|
for _, pair in ipairs(filter_type_names) do
|
||||||
local new_type = table.indexof(filter_types_titles, fields.type)
|
if fields[pair[1]] then
|
||||||
if new_type ~= filter_type then
|
filter_type = pair[2]
|
||||||
filter_type = new_type
|
|
||||||
cur_page = 1
|
cur_page = 1
|
||||||
contentdb.filter_packages(search_string, filter_types_type[filter_type])
|
contentdb.filter_packages(search_string, filter_type)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -428,32 +466,20 @@ local function handle_submit(this, fields)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local num_per_page = this.data.num_per_page
|
||||||
local start_idx = (cur_page - 1) * num_per_page + 1
|
local start_idx = (cur_page - 1) * num_per_page + 1
|
||||||
assert(start_idx ~= nil)
|
assert(start_idx ~= nil)
|
||||||
for i=start_idx, math.min(#contentdb.packages, start_idx+num_per_page-1) do
|
for i=start_idx, math.min(#contentdb.packages, start_idx+num_per_page-1) do
|
||||||
local package = contentdb.packages[i]
|
local package = contentdb.packages[i]
|
||||||
assert(package)
|
assert(package)
|
||||||
|
|
||||||
if fields["install_" .. i] then
|
if fields["view_" .. i] or fields["title_" .. i] or fields["author_" .. i] then
|
||||||
install_or_update_package(this, package)
|
local dlg = create_package_dialog(package)
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
if fields["uninstall_" .. i] then
|
|
||||||
local dlg = create_delete_content_dlg(package)
|
|
||||||
dlg:set_parent(this)
|
dlg:set_parent(this)
|
||||||
this:hide()
|
this:hide()
|
||||||
dlg:show()
|
dlg:show()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
if fields["view_" .. i] then
|
|
||||||
local url = ("%s/packages/%s?protocol_version=%d"):format(
|
|
||||||
core.settings:get("contentdb_url"), package.url_part,
|
|
||||||
core.get_max_supp_proto())
|
|
||||||
core.open_url(url)
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
@ -462,8 +488,8 @@ end
|
||||||
|
|
||||||
local function handle_events(event)
|
local function handle_events(event)
|
||||||
if event == "DialogShow" then
|
if event == "DialogShow" then
|
||||||
-- On touchscreen, don't show the "MINETEST" header behind the dialog.
|
-- Don't show the header image behind the dialog.
|
||||||
mm_game_theme.set_engine(core.settings:get_bool("touch_gui"))
|
mm_game_theme.set_engine(true)
|
||||||
|
|
||||||
-- If ContentDB is already loaded, auto-install packages here.
|
-- If ContentDB is already loaded, auto-install packages here.
|
||||||
do_auto_install()
|
do_auto_install()
|
||||||
|
@ -471,6 +497,11 @@ local function handle_events(event)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if event == "WindowInfoChange" then
|
||||||
|
ui.update()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -485,17 +516,7 @@ end
|
||||||
function create_contentdb_dlg(type, install_spec)
|
function create_contentdb_dlg(type, install_spec)
|
||||||
search_string = ""
|
search_string = ""
|
||||||
cur_page = 1
|
cur_page = 1
|
||||||
if type then
|
filter_type = type
|
||||||
-- table.indexof does not work on tables that contain `nil`
|
|
||||||
for i, v in pairs(filter_types_type) do
|
|
||||||
if v == type then
|
|
||||||
filter_type = i
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
filter_type = 1
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Keep the old auto_install_spec if the caller doesn't specify one.
|
-- Keep the old auto_install_spec if the caller doesn't specify one.
|
||||||
if install_spec then
|
if install_spec then
|
||||||
|
@ -504,8 +525,10 @@ function create_contentdb_dlg(type, install_spec)
|
||||||
|
|
||||||
load()
|
load()
|
||||||
|
|
||||||
return dialog_create("contentdb",
|
local dlg = dialog_create("contentdb",
|
||||||
get_formspec,
|
get_formspec,
|
||||||
handle_submit,
|
handle_submit,
|
||||||
handle_events)
|
handle_events)
|
||||||
|
dlg.data.num_per_page = calculate_num_per_page()
|
||||||
|
return dlg
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2018-24 rubenwardy
|
--Copyright (C) 2018-24 rubenwardy
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -244,3 +244,45 @@ function create_install_dialog(package)
|
||||||
|
|
||||||
return dlg
|
return dlg
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function install_or_update_package(parent, package)
|
||||||
|
local install_parent
|
||||||
|
if package.type == "mod" then
|
||||||
|
install_parent = core.get_modpath()
|
||||||
|
elseif package.type == "game" then
|
||||||
|
install_parent = core.get_gamepath()
|
||||||
|
elseif package.type == "txp" then
|
||||||
|
install_parent = core.get_texturepath()
|
||||||
|
else
|
||||||
|
error("Unknown package type: " .. package.type)
|
||||||
|
end
|
||||||
|
|
||||||
|
if package.queued or package.downloading then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local function on_confirm()
|
||||||
|
local dlg = create_install_dialog(package)
|
||||||
|
dlg:set_parent(parent)
|
||||||
|
parent:hide()
|
||||||
|
dlg:show()
|
||||||
|
|
||||||
|
dlg:load_deps()
|
||||||
|
end
|
||||||
|
|
||||||
|
if package.type == "mod" and #pkgmgr.games == 0 then
|
||||||
|
local dlg = messagebox("install_game",
|
||||||
|
fgettext("You need to install a game before you can install a mod"))
|
||||||
|
dlg:set_parent(parent)
|
||||||
|
parent:hide()
|
||||||
|
dlg:show()
|
||||||
|
elseif not package.path and core.is_dir(install_parent .. DIR_DELIM .. package.name) then
|
||||||
|
local dlg = create_confirm_overwrite(package, on_confirm)
|
||||||
|
dlg:set_parent(parent)
|
||||||
|
parent:hide()
|
||||||
|
dlg:show()
|
||||||
|
else
|
||||||
|
on_confirm()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2018-24 rubenwardy
|
--Copyright (C) 2018-24 rubenwardy
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
|
329
builtin/mainmenu/content/dlg_package.lua
Normal file
329
builtin/mainmenu/content/dlg_package.lua
Normal file
|
@ -0,0 +1,329 @@
|
||||||
|
--Luanti
|
||||||
|
--Copyright (C) 2018-24 rubenwardy
|
||||||
|
--
|
||||||
|
--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_info_formspec(size, padding, text)
|
||||||
|
return table.concat({
|
||||||
|
"formspec_version[6]",
|
||||||
|
"size[", size.x, ",", size.y, "]",
|
||||||
|
"padding[0,0]",
|
||||||
|
"bgcolor[;true]",
|
||||||
|
|
||||||
|
"label[4,4.35;", text, "]",
|
||||||
|
"container[", padding.x, ",", size.y - 0.8 - padding.y, "]",
|
||||||
|
"button[0,0;2,0.8;back;", fgettext("Back"), "]",
|
||||||
|
"container_end[]",
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function get_formspec(data)
|
||||||
|
local window_padding = contentdb.get_formspec_padding()
|
||||||
|
local size = contentdb.get_formspec_size()
|
||||||
|
size.x = math.min(size.x, 20)
|
||||||
|
local W = size.x - window_padding.x * 2
|
||||||
|
local H = size.y - window_padding.y * 2
|
||||||
|
|
||||||
|
if not data.info then
|
||||||
|
if not data.loading and not data.loading_error then
|
||||||
|
data.loading = true
|
||||||
|
|
||||||
|
contentdb.get_full_package_info(data.package, function(info)
|
||||||
|
data.loading = false
|
||||||
|
|
||||||
|
if info == nil then
|
||||||
|
data.loading_error = true
|
||||||
|
ui.update()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
assert(data.package.name == info.name)
|
||||||
|
data.info = info
|
||||||
|
ui.update()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- get_full_package_info can return cached info immediately, so
|
||||||
|
-- check to see if that happened
|
||||||
|
if not data.info then
|
||||||
|
if data.loading_error then
|
||||||
|
return get_info_formspec(size, window_padding, fgettext("No packages could be retrieved"))
|
||||||
|
end
|
||||||
|
return get_info_formspec(size, window_padding, fgettext("Loading..."))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check installation status
|
||||||
|
contentdb.update_paths()
|
||||||
|
|
||||||
|
local info = data.info
|
||||||
|
|
||||||
|
local info_line =
|
||||||
|
fgettext("by $1 — $2 downloads — +$3 / $4 / -$5",
|
||||||
|
info.author, info.downloads,
|
||||||
|
info.reviews.positive, info.reviews.neutral, info.reviews.negative)
|
||||||
|
|
||||||
|
local bottom_buttons_y = H - 0.8
|
||||||
|
|
||||||
|
local formspec = {
|
||||||
|
"formspec_version[7]",
|
||||||
|
"size[", size.x, ",", size.y, "]",
|
||||||
|
"padding[0,0]",
|
||||||
|
"bgcolor[;true]",
|
||||||
|
|
||||||
|
"container[", window_padding.x, ",", window_padding.y, "]",
|
||||||
|
|
||||||
|
"button[0,", bottom_buttons_y, ";2,0.8;back;", fgettext("Back"), "]",
|
||||||
|
"button[", W - 3, ",", bottom_buttons_y, ";3,0.8;open_contentdb;", fgettext("ContentDB page"), "]",
|
||||||
|
|
||||||
|
"style_type[label;font_size=+24;font=bold]",
|
||||||
|
"label[0,0.4;", core.formspec_escape(info.title), "]",
|
||||||
|
"style_type[label;font_size=;font=]",
|
||||||
|
|
||||||
|
"label[0,1.2;", core.formspec_escape(info_line), "]",
|
||||||
|
}
|
||||||
|
|
||||||
|
table.insert_all(formspec, {
|
||||||
|
"container[", W - 6, ",0]"
|
||||||
|
})
|
||||||
|
|
||||||
|
local left_button_rect = "0,0;2.875,1"
|
||||||
|
local right_button_rect = "3.125,0;2.875,1"
|
||||||
|
if data.package.downloading then
|
||||||
|
formspec[#formspec + 1] = "animated_image[5,0;1,1;downloading;"
|
||||||
|
formspec[#formspec + 1] = core.formspec_escape(defaulttexturedir)
|
||||||
|
formspec[#formspec + 1] = "cdb_downloading.png;3;400;]"
|
||||||
|
elseif data.package.queued then
|
||||||
|
formspec[#formspec + 1] = "style[queued;border=false]"
|
||||||
|
formspec[#formspec + 1] = "image_button[5,0;1,1;" .. core.formspec_escape(defaulttexturedir)
|
||||||
|
formspec[#formspec + 1] = "cdb_queued.png;queued;]"
|
||||||
|
elseif not data.package.path then
|
||||||
|
formspec[#formspec + 1] = "style[install;bgcolor=green]"
|
||||||
|
formspec[#formspec + 1] = "button["
|
||||||
|
formspec[#formspec + 1] = right_button_rect
|
||||||
|
formspec[#formspec + 1] =";install;"
|
||||||
|
formspec[#formspec + 1] = fgettext("Install [$1]", info.download_size)
|
||||||
|
formspec[#formspec + 1] = "]"
|
||||||
|
else
|
||||||
|
if data.package.installed_release < data.package.release then
|
||||||
|
-- The install_ action also handles updating
|
||||||
|
formspec[#formspec + 1] = "style[install;bgcolor=#28ccdf]"
|
||||||
|
formspec[#formspec + 1] = "button["
|
||||||
|
formspec[#formspec + 1] = left_button_rect
|
||||||
|
formspec[#formspec + 1] = ";install;"
|
||||||
|
formspec[#formspec + 1] = fgettext("Update")
|
||||||
|
formspec[#formspec + 1] = "]"
|
||||||
|
end
|
||||||
|
|
||||||
|
formspec[#formspec + 1] = "style[uninstall;bgcolor=#a93b3b]"
|
||||||
|
formspec[#formspec + 1] = "button["
|
||||||
|
formspec[#formspec + 1] = right_button_rect
|
||||||
|
formspec[#formspec + 1] = ";uninstall;"
|
||||||
|
formspec[#formspec + 1] = fgettext("Uninstall")
|
||||||
|
formspec[#formspec + 1] = "]"
|
||||||
|
end
|
||||||
|
|
||||||
|
local current_tab = data.current_tab or 1
|
||||||
|
local tab_titles = {
|
||||||
|
fgettext("Description"),
|
||||||
|
fgettext("Information"),
|
||||||
|
}
|
||||||
|
|
||||||
|
local tab_body_height = bottom_buttons_y - 2.8
|
||||||
|
|
||||||
|
table.insert_all(formspec, {
|
||||||
|
"container_end[]",
|
||||||
|
|
||||||
|
"box[0,2.55;", W, ",", tab_body_height, ";#ffffff11]",
|
||||||
|
|
||||||
|
"tabheader[0,2.55;", W, ",0.8;tabs;",
|
||||||
|
table.concat(tab_titles, ","), ";", current_tab, ";true;true]",
|
||||||
|
|
||||||
|
"container[0,2.8]",
|
||||||
|
})
|
||||||
|
|
||||||
|
if current_tab == 1 then
|
||||||
|
-- Screenshots and description
|
||||||
|
local hypertext = "<big><b>" .. core.hypertext_escape(info.short_description) .. "</b></big>\n"
|
||||||
|
local winfo = core.get_window_info()
|
||||||
|
local fs_to_px = winfo.size.x / winfo.max_formspec_size.x
|
||||||
|
for i, ss in ipairs(info.screenshots) do
|
||||||
|
local path = get_screenshot(data.package, ss.url, 2)
|
||||||
|
hypertext = hypertext .. "<action name=\"ss_" .. i .. "\"><img name=\"" ..
|
||||||
|
core.hypertext_escape(path) .. "\" width=" .. (3 * fs_to_px) ..
|
||||||
|
" height=" .. (2 * fs_to_px) .. "></action>"
|
||||||
|
if i ~= #info.screenshots then
|
||||||
|
hypertext = hypertext .. "<img name=\"blank.png\" width=" .. (0.25 * fs_to_px) ..
|
||||||
|
" height=" .. (2.25 * fs_to_px).. ">"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
hypertext = hypertext .. "\n" .. info.long_description.head
|
||||||
|
|
||||||
|
local first = true
|
||||||
|
local function add_link_button(label, name)
|
||||||
|
if info[name] then
|
||||||
|
if not first then
|
||||||
|
hypertext = hypertext .. " | "
|
||||||
|
end
|
||||||
|
hypertext = hypertext .. "<action name=link_" .. name .. ">" .. core.hypertext_escape(label) .. "</action>"
|
||||||
|
info.long_description.links["link_" .. name] = info[name]
|
||||||
|
first = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
add_link_button(fgettext("Donate"), "donate_url")
|
||||||
|
add_link_button(fgettext("Website"), "website")
|
||||||
|
add_link_button(fgettext("Source"), "repo")
|
||||||
|
add_link_button(fgettext("Issue Tracker"), "issue_tracker")
|
||||||
|
add_link_button(fgettext("Translate"), "translation_url")
|
||||||
|
add_link_button(fgettext("Forum Topic"), "forum_url")
|
||||||
|
|
||||||
|
hypertext = hypertext .. "\n\n" .. info.long_description.body
|
||||||
|
|
||||||
|
hypertext = hypertext:gsub("<img name=\"?blank.png\"? ",
|
||||||
|
"<img name=\"" .. core.hypertext_escape(defaulttexturedir) .. "blank.png\" ")
|
||||||
|
|
||||||
|
table.insert_all(formspec, {
|
||||||
|
"hypertext[0,0;", W, ",", tab_body_height - 0.375,
|
||||||
|
";desc;", core.formspec_escape(hypertext), "]",
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
elseif current_tab == 2 then
|
||||||
|
local hypertext = info.info_hypertext.head .. info.info_hypertext.body
|
||||||
|
|
||||||
|
table.insert_all(formspec, {
|
||||||
|
"hypertext[0,0;", W, ",", tab_body_height - 0.375,
|
||||||
|
";info;", core.formspec_escape(hypertext), "]",
|
||||||
|
})
|
||||||
|
else
|
||||||
|
error("Unknown tab " .. current_tab)
|
||||||
|
end
|
||||||
|
|
||||||
|
formspec[#formspec + 1] = "container_end[]"
|
||||||
|
formspec[#formspec + 1] = "container_end[]"
|
||||||
|
|
||||||
|
return table.concat(formspec)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function handle_hypertext_event(this, event, hypertext_object)
|
||||||
|
if not (event and event:sub(1, 7) == "action:") then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
for i, ss in ipairs(this.data.info.screenshots) do
|
||||||
|
if event == "action:ss_" .. i then
|
||||||
|
core.open_url(ss.url)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local base_url = core.settings:get("contentdb_url"):gsub("(%W)", "%%%1")
|
||||||
|
for key, url in pairs(hypertext_object.links) do
|
||||||
|
if event == "action:" .. key then
|
||||||
|
local author, name = url:match("^" .. base_url .. "/?packages/([A-Za-z0-9 _-]+)/([a-z0-9_]+)/?$")
|
||||||
|
if author and name then
|
||||||
|
local package2 = contentdb.get_package_by_info(author, name)
|
||||||
|
if package2 then
|
||||||
|
local dlg = create_package_dialog(package2)
|
||||||
|
dlg:set_parent(this)
|
||||||
|
this:hide()
|
||||||
|
dlg:show()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
core.open_url_dialog(url)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function handle_submit(this, fields)
|
||||||
|
local info = this.data.info
|
||||||
|
local package = this.data.package
|
||||||
|
|
||||||
|
if fields.back then
|
||||||
|
this:delete()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
if not info then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if fields.open_contentdb then
|
||||||
|
local url = ("%s/packages/%s/?protocol_version=%d"):format(
|
||||||
|
core.settings:get("contentdb_url"), package.url_part,
|
||||||
|
core.get_max_supp_proto())
|
||||||
|
core.open_url(url)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
if fields.install then
|
||||||
|
install_or_update_package(this, package)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
if fields.uninstall then
|
||||||
|
local dlg = create_delete_content_dlg(package)
|
||||||
|
dlg:set_parent(this)
|
||||||
|
this:hide()
|
||||||
|
dlg:show()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
if fields.tabs then
|
||||||
|
this.data.current_tab = tonumber(fields.tabs)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
if handle_hypertext_event(this, fields.desc, info.long_description) or
|
||||||
|
handle_hypertext_event(this, fields.info, info.info_hypertext) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function handle_events(event)
|
||||||
|
if event == "WindowInfoChange" then
|
||||||
|
ui.update()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function create_package_dialog(package)
|
||||||
|
assert(package)
|
||||||
|
|
||||||
|
local dlg = dialog_create("package_dialog_" .. package.id,
|
||||||
|
get_formspec,
|
||||||
|
handle_submit,
|
||||||
|
handle_events)
|
||||||
|
local data = dlg.data
|
||||||
|
|
||||||
|
data.package = package
|
||||||
|
data.info = nil
|
||||||
|
data.loading = false
|
||||||
|
data.loading_error = nil
|
||||||
|
data.current_tab = 1
|
||||||
|
return dlg
|
||||||
|
end
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2023 rubenwardy
|
--Copyright (C) 2023 rubenwardy
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -23,4 +23,5 @@ dofile(path .. DIR_DELIM .. "update_detector.lua")
|
||||||
dofile(path .. DIR_DELIM .. "screenshots.lua")
|
dofile(path .. DIR_DELIM .. "screenshots.lua")
|
||||||
dofile(path .. DIR_DELIM .. "dlg_install.lua")
|
dofile(path .. DIR_DELIM .. "dlg_install.lua")
|
||||||
dofile(path .. DIR_DELIM .. "dlg_overwrite.lua")
|
dofile(path .. DIR_DELIM .. "dlg_overwrite.lua")
|
||||||
|
dofile(path .. DIR_DELIM .. "dlg_package.lua")
|
||||||
dofile(path .. DIR_DELIM .. "dlg_contentdb.lua")
|
dofile(path .. DIR_DELIM .. "dlg_contentdb.lua")
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2013 sapier
|
--Copyright (C) 2013 sapier
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -840,7 +840,7 @@ function pkgmgr.get_contentdb_id(content)
|
||||||
return content.author:lower() .. "/" .. content.name
|
return content.author:lower() .. "/" .. content.name
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Until Minetest 5.8.0, Minetest Game was bundled with Minetest.
|
-- Until version 5.8.0, Minetest Game was bundled with the engine.
|
||||||
-- Unfortunately, the bundled MTG was not versioned (missing "release"
|
-- Unfortunately, the bundled MTG was not versioned (missing "release"
|
||||||
-- field in game.conf).
|
-- field in game.conf).
|
||||||
-- Therefore, we consider any installation of MTG that is not versioned,
|
-- Therefore, we consider any installation of MTG that is not versioned,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2023-24 rubenwardy
|
--Copyright (C) 2023-24 rubenwardy
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -23,23 +23,40 @@ local screenshot_downloading = {}
|
||||||
local screenshot_downloaded = {}
|
local screenshot_downloaded = {}
|
||||||
|
|
||||||
|
|
||||||
|
local function get_filename(path)
|
||||||
|
local parts = path:split("/")
|
||||||
|
return parts[#parts]
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
local function get_file_extension(path)
|
local function get_file_extension(path)
|
||||||
local parts = path:split(".")
|
local parts = path:split(".")
|
||||||
return parts[#parts]
|
return parts[#parts]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function get_screenshot(package)
|
function get_screenshot(package, screenshot_url, level)
|
||||||
if not package.thumbnail then
|
if not screenshot_url then
|
||||||
return defaulttexturedir .. "no_screenshot.png"
|
return defaulttexturedir .. "no_screenshot.png"
|
||||||
elseif screenshot_downloading[package.thumbnail] then
|
end
|
||||||
|
|
||||||
|
-- Luanti only supports png and jpg
|
||||||
|
local ext = get_file_extension(screenshot_url)
|
||||||
|
if ext ~= "png" and ext ~= "jpg" then
|
||||||
|
screenshot_url = screenshot_url:sub(0, -#ext - 1) .. "png"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set thumbnail level
|
||||||
|
screenshot_url = screenshot_url:gsub("/thumbnails/[0-9]+/", "/thumbnails/" .. level .. "/")
|
||||||
|
screenshot_url = screenshot_url:gsub("/uploads/", "/thumbnails/" .. level .. "/")
|
||||||
|
|
||||||
|
if screenshot_downloading[screenshot_url] then
|
||||||
return defaulttexturedir .. "loading_screenshot.png"
|
return defaulttexturedir .. "loading_screenshot.png"
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get tmp screenshot path
|
|
||||||
local ext = get_file_extension(package.thumbnail)
|
|
||||||
local filepath = screenshot_dir .. DIR_DELIM ..
|
local filepath = screenshot_dir .. DIR_DELIM ..
|
||||||
("%s-%s-%s.%s"):format(package.type, package.author, package.name, ext)
|
("%s-%s-%s-l%d-%s"):format(package.type, package.author, package.name,
|
||||||
|
level, get_filename(screenshot_url))
|
||||||
|
|
||||||
-- Return if already downloaded
|
-- Return if already downloaded
|
||||||
local file = io.open(filepath, "r")
|
local file = io.open(filepath, "r")
|
||||||
|
@ -49,7 +66,7 @@ function get_screenshot(package)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Show error if we've failed to download before
|
-- Show error if we've failed to download before
|
||||||
if screenshot_downloaded[package.thumbnail] then
|
if screenshot_downloaded[screenshot_url] then
|
||||||
return defaulttexturedir .. "error_screenshot.png"
|
return defaulttexturedir .. "error_screenshot.png"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -59,16 +76,16 @@ function get_screenshot(package)
|
||||||
return core.download_file(params.url, params.dest)
|
return core.download_file(params.url, params.dest)
|
||||||
end
|
end
|
||||||
local function callback(success)
|
local function callback(success)
|
||||||
screenshot_downloading[package.thumbnail] = nil
|
screenshot_downloading[screenshot_url] = nil
|
||||||
screenshot_downloaded[package.thumbnail] = true
|
screenshot_downloaded[screenshot_url] = true
|
||||||
if not success then
|
if not success then
|
||||||
core.log("warning", "Screenshot download failed for some reason")
|
core.log("warning", "Screenshot download failed for some reason")
|
||||||
end
|
end
|
||||||
ui.update()
|
ui.update()
|
||||||
end
|
end
|
||||||
if core.handle_async(download_screenshot,
|
if core.handle_async(download_screenshot,
|
||||||
{ dest = filepath, url = package.thumbnail }, callback) then
|
{ dest = filepath, url = screenshot_url }, callback) then
|
||||||
screenshot_downloading[package.thumbnail] = true
|
screenshot_downloading[screenshot_url] = true
|
||||||
else
|
else
|
||||||
core.log("error", "ERROR: async event failed")
|
core.log("error", "ERROR: async event failed")
|
||||||
return defaulttexturedir .. "error_screenshot.png"
|
return defaulttexturedir .. "error_screenshot.png"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2022 rubenwardy
|
--Copyright (C) 2022 rubenwardy
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2023 rubenwardy
|
--Copyright (C) 2023 rubenwardy
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
|
|
@ -13,7 +13,9 @@
|
||||||
"Desour/DS",
|
"Desour/DS",
|
||||||
"srifqi",
|
"srifqi",
|
||||||
"Gregor Parzefall (grorp)",
|
"Gregor Parzefall (grorp)",
|
||||||
"Lars Müller (luatic)"
|
"Lars Müller (luatic)",
|
||||||
|
"cx384",
|
||||||
|
"sfence"
|
||||||
],
|
],
|
||||||
"previous_core_developers": [
|
"previous_core_developers": [
|
||||||
"BlockMen",
|
"BlockMen",
|
||||||
|
@ -44,30 +46,25 @@
|
||||||
],
|
],
|
||||||
"#": "For updating active/previous contributors, see the script in ./util/gather_git_credits.py",
|
"#": "For updating active/previous contributors, see the script in ./util/gather_git_credits.py",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
"cx384",
|
|
||||||
"numzero",
|
|
||||||
"AFCMS",
|
|
||||||
"sfence",
|
|
||||||
"Wuzzy",
|
|
||||||
"ROllerozxa",
|
|
||||||
"JosiahWI",
|
"JosiahWI",
|
||||||
"OgelGames",
|
|
||||||
"David Heidelberg",
|
|
||||||
"1F616EMO",
|
"1F616EMO",
|
||||||
"HybridDog",
|
|
||||||
"Bradley Pierce (Thresher)",
|
|
||||||
"savilli",
|
|
||||||
"Stvk imension",
|
|
||||||
"y5nw",
|
"y5nw",
|
||||||
|
"Erich Schubert",
|
||||||
|
"numzero",
|
||||||
|
"red-001 <red-001@outlook.ie>",
|
||||||
|
"David Heidelberg",
|
||||||
|
"Wuzzy",
|
||||||
|
"paradust7",
|
||||||
|
"HybridDog",
|
||||||
|
"Zemtzov7",
|
||||||
|
"kromka-chleba",
|
||||||
|
"AFCMS",
|
||||||
"chmodsayshello",
|
"chmodsayshello",
|
||||||
"jordan4ibanez",
|
"OgelGames"
|
||||||
"superfloh247"
|
|
||||||
],
|
],
|
||||||
"previous_contributors": [
|
"previous_contributors": [
|
||||||
"Nils Dagsson Moskopp (erlehmann) <nils@dieweltistgarnichtso.net> [Minetest logo]",
|
"Ælla Chiana Moskopp (erle) <erle@dieweltistgarnichtso.net> [Logo]",
|
||||||
"red-001 <red-001@outlook.ie>",
|
|
||||||
"Giuseppe Bilotta",
|
"Giuseppe Bilotta",
|
||||||
"HybridDog",
|
|
||||||
"ClobberXD",
|
"ClobberXD",
|
||||||
"Dániel Juhász (juhdanad) <juhdanad@gmail.com>",
|
"Dániel Juhász (juhdanad) <juhdanad@gmail.com>",
|
||||||
"MirceaKitsune <mirceakitsune@gmail.com>",
|
"MirceaKitsune <mirceakitsune@gmail.com>",
|
||||||
|
@ -75,6 +72,7 @@
|
||||||
"MoNTE48",
|
"MoNTE48",
|
||||||
"Constantin Wenger (SpeedProg)",
|
"Constantin Wenger (SpeedProg)",
|
||||||
"Ciaran Gultnieks (CiaranG)",
|
"Ciaran Gultnieks (CiaranG)",
|
||||||
|
"ROllerozxa",
|
||||||
"Paul Ouellette (pauloue)",
|
"Paul Ouellette (pauloue)",
|
||||||
"stujones11",
|
"stujones11",
|
||||||
"Rogier <rogier777@gmail.com>",
|
"Rogier <rogier777@gmail.com>",
|
||||||
|
|
49
builtin/mainmenu/dlg_clients_list.lua
Normal file
49
builtin/mainmenu/dlg_clients_list.lua
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
-- Luanti
|
||||||
|
-- Copyright (C) 2024 siliconsniffer
|
||||||
|
-- SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
|
||||||
|
|
||||||
|
local function clients_list_formspec(dialogdata)
|
||||||
|
local TOUCH_GUI = core.settings:get_bool("touch_gui")
|
||||||
|
local clients_list = dialogdata.server.clients_list
|
||||||
|
local servername = dialogdata.server.name
|
||||||
|
|
||||||
|
local function fmt_formspec_list(clients_list)
|
||||||
|
local escaped = {}
|
||||||
|
for i, str in ipairs(clients_list) do
|
||||||
|
escaped[i] = core.formspec_escape(str)
|
||||||
|
end
|
||||||
|
return table.concat(escaped, ",")
|
||||||
|
end
|
||||||
|
|
||||||
|
local formspec = {
|
||||||
|
"formspec_version[8]",
|
||||||
|
"size[6,9.5]",
|
||||||
|
TOUCH_GUI and "padding[0.01,0.01]" or "",
|
||||||
|
"hypertext[0,0;6,1.5;;<global margin=5 halign=center valign=middle>",
|
||||||
|
fgettext("This is the list of clients connected to\n$1",
|
||||||
|
"<b>" .. core.hypertext_escape(servername) .. "</b>") .. "]",
|
||||||
|
"textlist[0.5,1.5;5,6.8;;" .. fmt_formspec_list(clients_list) .. "]",
|
||||||
|
"button[1.5,8.5;3,0.8;quit;OK]"
|
||||||
|
}
|
||||||
|
return table.concat(formspec, "")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function clients_list_buttonhandler(this, fields)
|
||||||
|
if fields.quit then
|
||||||
|
this:delete()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function create_clientslist_dialog(server)
|
||||||
|
local retval = dialog_create("dlg_clients_list",
|
||||||
|
clients_list_formspec,
|
||||||
|
clients_list_buttonhandler,
|
||||||
|
nil)
|
||||||
|
retval.data.server = server
|
||||||
|
return retval
|
||||||
|
end
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2013 sapier
|
--Copyright (C) 2013 sapier
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2014 sapier
|
--Copyright (C) 2014 sapier
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2014 sapier
|
--Copyright (C) 2014 sapier
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2014 sapier
|
--Copyright (C) 2014 sapier
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2022 rubenwardy
|
--Copyright (C) 2022 rubenwardy
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2023 Gregor Parzefall
|
--Copyright (C) 2023 Gregor Parzefall
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -68,15 +68,15 @@ end
|
||||||
local function get_formspec(dialogdata)
|
local function get_formspec(dialogdata)
|
||||||
local markup = table.concat({
|
local markup = table.concat({
|
||||||
"<big>", fgettext("Minetest Game is no longer installed by default"), "</big>\n",
|
"<big>", fgettext("Minetest Game is no longer installed by default"), "</big>\n",
|
||||||
fgettext("For a long time, the Minetest engine shipped with a default game called \"Minetest Game\". " ..
|
fgettext("For a long time, Luanti shipped with a default game called \"Minetest Game\". " ..
|
||||||
"Since Minetest 5.8.0, Minetest ships without a default game."), "\n",
|
"Since version 5.8.0, Luanti ships without a default game."), "\n",
|
||||||
fgettext("If you want to continue playing in your Minetest Game worlds, you need to reinstall Minetest Game."),
|
fgettext("If you want to continue playing in your Minetest Game worlds, you need to reinstall Minetest Game."),
|
||||||
})
|
})
|
||||||
|
|
||||||
return table.concat({
|
return table.concat({
|
||||||
"formspec_version[6]",
|
"formspec_version[6]",
|
||||||
"size[12.8,7]",
|
"size[12.8,7]",
|
||||||
"hypertext[0.375,0.375;12.05,5.2;text;", minetest.formspec_escape(markup), "]",
|
"hypertext[0.375,0.375;12.05,5.2;text;", core.formspec_escape(markup), "]",
|
||||||
"container[0.375,5.825]",
|
"container[0.375,5.825]",
|
||||||
"style[dismiss;bgcolor=red]",
|
"style[dismiss;bgcolor=red]",
|
||||||
"button[0,0;4,0.8;dismiss;", fgettext("Dismiss"), "]",
|
"button[0,0;4,0.8;dismiss;", fgettext("Dismiss"), "]",
|
||||||
|
@ -114,7 +114,7 @@ local function eventhandler(event)
|
||||||
return true
|
return true
|
||||||
elseif event == "MenuQuit" then
|
elseif event == "MenuQuit" then
|
||||||
-- Don't allow closing the dialog with ESC, but still allow exiting
|
-- Don't allow closing the dialog with ESC, but still allow exiting
|
||||||
-- Minetest.
|
-- Luanti
|
||||||
core.close()
|
core.close()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2014 sapier
|
--Copyright (C) 2014 sapier
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
--[[
|
--[[
|
||||||
Minetest
|
Luanti
|
||||||
Copyright (C) 2018-2020 SmallJoker, 2022 rubenwardy
|
Copyright (C) 2018-2020 SmallJoker, 2022 rubenwardy
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2013 sapier
|
--Copyright (C) 2013 sapier
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2014 sapier
|
--Copyright (C) 2014 sapier
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -55,6 +55,7 @@ dofile(menupath .. DIR_DELIM .. "dlg_register.lua")
|
||||||
dofile(menupath .. DIR_DELIM .. "dlg_rename_modpack.lua")
|
dofile(menupath .. DIR_DELIM .. "dlg_rename_modpack.lua")
|
||||||
dofile(menupath .. DIR_DELIM .. "dlg_version_info.lua")
|
dofile(menupath .. DIR_DELIM .. "dlg_version_info.lua")
|
||||||
dofile(menupath .. DIR_DELIM .. "dlg_reinstall_mtg.lua")
|
dofile(menupath .. DIR_DELIM .. "dlg_reinstall_mtg.lua")
|
||||||
|
dofile(menupath .. DIR_DELIM .. "dlg_clients_list.lua")
|
||||||
|
|
||||||
local tabs = {
|
local tabs = {
|
||||||
content = dofile(menupath .. DIR_DELIM .. "tab_content.lua"),
|
content = dofile(menupath .. DIR_DELIM .. "tab_content.lua"),
|
||||||
|
@ -133,4 +134,5 @@ local function init_globals()
|
||||||
check_new_version()
|
check_new_version()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
assert(os.execute == nil)
|
||||||
init_globals()
|
init_globals()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2020 rubenwardy
|
--Copyright (C) 2020 rubenwardy
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2022 rubenwardy
|
--Copyright (C) 2022 rubenwardy
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -67,6 +67,19 @@ function make.heading(text)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function make.note(text)
|
||||||
|
return {
|
||||||
|
full_width = true,
|
||||||
|
get_formspec = function(self, avail_w)
|
||||||
|
-- Assuming label height 0.4:
|
||||||
|
-- Position at y=0 to eat 0.2 of the padding above, leave 0.05.
|
||||||
|
-- The returned used_height doesn't include padding.
|
||||||
|
return ("label[0,0;%s]"):format(core.colorize("#bbb", core.formspec_escape(text))), 0.2
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Used for string and numeric style fields
|
--- Used for string and numeric style fields
|
||||||
---
|
---
|
||||||
--- @param converter Function to coerce values from strings.
|
--- @param converter Function to coerce values from strings.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2015 PilzAdam
|
--Copyright (C) 2015 PilzAdam
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2022 rubenwardy
|
--Copyright (C) 2022 rubenwardy
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -123,6 +123,22 @@ local function load()
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local touchscreen_layout = {
|
||||||
|
query_text = "Touchscreen layout",
|
||||||
|
requires = {
|
||||||
|
touchscreen = true,
|
||||||
|
},
|
||||||
|
get_formspec = function(self, avail_w)
|
||||||
|
local btn_w = math.min(avail_w, 6)
|
||||||
|
return ("button[0,0;%f,0.8;btn_touch_layout;%s]"):format(btn_w, fgettext("Touchscreen layout")), 0.8
|
||||||
|
end,
|
||||||
|
on_submit = function(self, fields)
|
||||||
|
if fields.btn_touch_layout then
|
||||||
|
core.show_touchscreen_layout()
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
add_page({
|
add_page({
|
||||||
id = "accessibility",
|
id = "accessibility",
|
||||||
title = fgettext_ne("Accessibility"),
|
title = fgettext_ne("Accessibility"),
|
||||||
|
@ -151,10 +167,27 @@ local function load()
|
||||||
load_settingtypes()
|
load_settingtypes()
|
||||||
|
|
||||||
table.insert(page_by_id.controls_keyboard_and_mouse.content, 1, change_keys)
|
table.insert(page_by_id.controls_keyboard_and_mouse.content, 1, change_keys)
|
||||||
|
-- insert after "touch_controls"
|
||||||
|
table.insert(page_by_id.controls_touchscreen.content, 2, touchscreen_layout)
|
||||||
do
|
do
|
||||||
local content = page_by_id.graphics_and_audio_shaders.content
|
local content = page_by_id.graphics_and_audio_effects.content
|
||||||
local idx = table.indexof(content, "enable_dynamic_shadows")
|
local idx = table.indexof(content, "enable_dynamic_shadows")
|
||||||
table.insert(content, idx, shadows_component)
|
table.insert(content, idx, shadows_component)
|
||||||
|
|
||||||
|
idx = table.indexof(content, "enable_auto_exposure") + 1
|
||||||
|
local note = component_funcs.note(fgettext_ne("(The game will need to enable automatic exposure as well)"))
|
||||||
|
note.requires = get_setting_info("enable_auto_exposure").requires
|
||||||
|
table.insert(content, idx, note)
|
||||||
|
|
||||||
|
idx = table.indexof(content, "enable_bloom") + 1
|
||||||
|
note = component_funcs.note(fgettext_ne("(The game will need to enable bloom as well)"))
|
||||||
|
note.requires = get_setting_info("enable_bloom").requires
|
||||||
|
table.insert(content, idx, note)
|
||||||
|
|
||||||
|
idx = table.indexof(content, "enable_volumetric_lighting") + 1
|
||||||
|
note = component_funcs.note(fgettext_ne("(The game will need to enable volumetric lighting as well)"))
|
||||||
|
note.requires = get_setting_info("enable_volumetric_lighting").requires
|
||||||
|
table.insert(content, idx, note)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- These must not be translated, as they need to show in the local
|
-- These must not be translated, as they need to show in the local
|
||||||
|
@ -222,6 +255,12 @@ local function load()
|
||||||
zh_CN = "中文 (简体) [zh_CN]",
|
zh_CN = "中文 (简体) [zh_CN]",
|
||||||
zh_TW = "正體中文 (繁體) [zh_TW]",
|
zh_TW = "正體中文 (繁體) [zh_TW]",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get_setting_info("touch_controls").option_labels = {
|
||||||
|
["auto"] = fgettext_ne("Auto"),
|
||||||
|
["true"] = fgettext_ne("Enabled"),
|
||||||
|
["false"] = fgettext_ne("Disabled"),
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -320,13 +359,17 @@ local function check_requirements(name, requires)
|
||||||
end
|
end
|
||||||
|
|
||||||
local video_driver = core.get_active_driver()
|
local video_driver = core.get_active_driver()
|
||||||
local shaders_support = video_driver == "opengl" or video_driver == "opengl3" or video_driver == "ogles2"
|
local touch_support = core.irrlicht_device_supports_touch()
|
||||||
|
local touch_controls = core.settings:get("touch_controls")
|
||||||
local special = {
|
local special = {
|
||||||
android = PLATFORM == "Android",
|
android = PLATFORM == "Android",
|
||||||
desktop = PLATFORM ~= "Android",
|
desktop = PLATFORM ~= "Android",
|
||||||
shaders_support = shaders_support,
|
touch_support = touch_support,
|
||||||
shaders = core.settings:get_bool("enable_shaders") and shaders_support,
|
-- When touch_controls is "auto", we don't know which input method will
|
||||||
opengl = video_driver == "opengl",
|
-- be used, so we show settings for both.
|
||||||
|
touchscreen = touch_support and (touch_controls == "auto" or core.is_yes(touch_controls)),
|
||||||
|
keyboard_mouse = not touch_support or (touch_controls == "auto" or not core.is_yes(touch_controls)),
|
||||||
|
opengl = (video_driver == "opengl" or video_driver == "opengl3"),
|
||||||
gles = video_driver:sub(1, 5) == "ogles",
|
gles = video_driver:sub(1, 5) == "ogles",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,7 +377,7 @@ local function check_requirements(name, requires)
|
||||||
if special[req_key] == nil then
|
if special[req_key] == nil then
|
||||||
local required_setting = get_setting_info(req_key)
|
local required_setting = get_setting_info(req_key)
|
||||||
if required_setting == nil then
|
if required_setting == nil then
|
||||||
core.log("warning", "Unknown setting " .. req_key .. " required by " .. name)
|
core.log("warning", "Unknown setting " .. req_key .. " required by " .. (name or "???"))
|
||||||
end
|
end
|
||||||
local actual_value = core.settings:get_bool(req_key,
|
local actual_value = core.settings:get_bool(req_key,
|
||||||
required_setting and core.is_yes(required_setting.default))
|
required_setting and core.is_yes(required_setting.default))
|
||||||
|
@ -433,19 +476,6 @@ local function build_page_components(page)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Creates a scrollbaroptions for a scroll_container
|
|
||||||
--
|
|
||||||
-- @param visible_l the length of the scroll_container and scrollbar
|
|
||||||
-- @param total_l length of the scrollable area
|
|
||||||
-- @param scroll_factor as passed to scroll_container
|
|
||||||
local function make_scrollbaroptions_for_scroll_container(visible_l, total_l, scroll_factor)
|
|
||||||
assert(total_l >= visible_l)
|
|
||||||
local max = total_l - visible_l
|
|
||||||
local thumb_size = (visible_l / total_l) * max
|
|
||||||
return ("scrollbaroptions[min=0;max=%f;thumbsize=%f]"):format(max / scroll_factor, thumb_size / scroll_factor)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local formspec_show_hack = false
|
local formspec_show_hack = false
|
||||||
|
|
||||||
|
|
||||||
|
@ -507,8 +537,8 @@ local function get_formspec(dialogdata)
|
||||||
"tooltip[search;", fgettext("Search"), "]",
|
"tooltip[search;", fgettext("Search"), "]",
|
||||||
"tooltip[search_clear;", fgettext("Clear"), "]",
|
"tooltip[search_clear;", fgettext("Clear"), "]",
|
||||||
"container_end[]",
|
"container_end[]",
|
||||||
"scroll_container[0.25,1.25;", tostring(left_pane_width), ",",
|
("scroll_container[0.25,1.25;%f,%f;leftscroll;vertical;0.1;0]"):format(
|
||||||
tostring(tabsize.height - 1.5), ";leftscroll;vertical;0.1]",
|
left_pane_width, tabsize.height - 1.5),
|
||||||
"style_type[button;border=false;bgcolor=#3333]",
|
"style_type[button;border=false;bgcolor=#3333]",
|
||||||
"style_type[button:hover;border=false;bgcolor=#6663]",
|
"style_type[button:hover;border=false;bgcolor=#6663]",
|
||||||
}
|
}
|
||||||
|
@ -538,7 +568,6 @@ local function get_formspec(dialogdata)
|
||||||
fs[#fs + 1] = "scroll_container_end[]"
|
fs[#fs + 1] = "scroll_container_end[]"
|
||||||
|
|
||||||
if y >= tabsize.height - 1.25 then
|
if y >= tabsize.height - 1.25 then
|
||||||
fs[#fs + 1] = make_scrollbaroptions_for_scroll_container(tabsize.height - 1.5, y, 0.1)
|
|
||||||
fs[#fs + 1] = ("scrollbar[%f,1.25;%f,%f;vertical;leftscroll;%f]"):format(
|
fs[#fs + 1] = ("scrollbar[%f,1.25;%f,%f;vertical;leftscroll;%f]"):format(
|
||||||
left_pane_width + 0.25, scrollbar_w, tabsize.height - 1.5, dialogdata.leftscroll or 0)
|
left_pane_width + 0.25, scrollbar_w, tabsize.height - 1.5, dialogdata.leftscroll or 0)
|
||||||
end
|
end
|
||||||
|
@ -550,7 +579,7 @@ local function get_formspec(dialogdata)
|
||||||
end
|
end
|
||||||
|
|
||||||
local right_pane_width = tabsize.width - left_pane_width - 0.375 - 2*scrollbar_w - 0.25
|
local right_pane_width = tabsize.width - left_pane_width - 0.375 - 2*scrollbar_w - 0.25
|
||||||
fs[#fs + 1] = ("scroll_container[%f,0;%f,%f;rightscroll;vertical;0.1]"):format(
|
fs[#fs + 1] = ("scroll_container[%f,0;%f,%f;rightscroll;vertical;0.1;0.25]"):format(
|
||||||
tabsize.width - right_pane_width - scrollbar_w, right_pane_width, tabsize.height)
|
tabsize.width - right_pane_width - scrollbar_w, right_pane_width, tabsize.height)
|
||||||
|
|
||||||
y = 0.25
|
y = 0.25
|
||||||
|
@ -606,7 +635,6 @@ local function get_formspec(dialogdata)
|
||||||
fs[#fs + 1] = "scroll_container_end[]"
|
fs[#fs + 1] = "scroll_container_end[]"
|
||||||
|
|
||||||
if y >= tabsize.height then
|
if y >= tabsize.height then
|
||||||
fs[#fs + 1] = make_scrollbaroptions_for_scroll_container(tabsize.height, y + 0.375, 0.1)
|
|
||||||
fs[#fs + 1] = ("scrollbar[%f,0;%f,%f;vertical;rightscroll;%f]"):format(
|
fs[#fs + 1] = ("scrollbar[%f,0;%f,%f;vertical;rightscroll;%f]"):format(
|
||||||
tabsize.width - scrollbar_w, scrollbar_w, tabsize.height, dialogdata.rightscroll or 0)
|
tabsize.width - scrollbar_w, scrollbar_w, tabsize.height, dialogdata.rightscroll or 0)
|
||||||
end
|
end
|
||||||
|
@ -624,6 +652,18 @@ function write_settings_early()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function regenerate_page_list(dialogdata)
|
||||||
|
local suggested_page_id = update_filtered_pages(dialogdata.query)
|
||||||
|
|
||||||
|
dialogdata.components = nil
|
||||||
|
|
||||||
|
if not filtered_page_by_id[dialogdata.page_id] then
|
||||||
|
dialogdata.leftscroll = 0
|
||||||
|
dialogdata.rightscroll = 0
|
||||||
|
|
||||||
|
dialogdata.page_id = suggested_page_id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local function buttonhandler(this, fields)
|
local function buttonhandler(this, fields)
|
||||||
local dialogdata = this.data
|
local dialogdata = this.data
|
||||||
|
@ -648,27 +688,7 @@ local function buttonhandler(this, fields)
|
||||||
local value = core.is_yes(fields.show_advanced)
|
local value = core.is_yes(fields.show_advanced)
|
||||||
core.settings:set_bool("show_advanced", value)
|
core.settings:set_bool("show_advanced", value)
|
||||||
write_settings_early()
|
write_settings_early()
|
||||||
end
|
regenerate_page_list(dialogdata)
|
||||||
|
|
||||||
-- touch_controls is a checkbox in a setting component. We handle this
|
|
||||||
-- setting differently so we can hide/show pages using the next if-statement
|
|
||||||
if fields.touch_controls ~= nil then
|
|
||||||
local value = core.is_yes(fields.touch_controls)
|
|
||||||
core.settings:set_bool("touch_controls", value)
|
|
||||||
write_settings_early()
|
|
||||||
end
|
|
||||||
|
|
||||||
if fields.show_advanced ~= nil or fields.touch_controls ~= nil then
|
|
||||||
local suggested_page_id = update_filtered_pages(dialogdata.query)
|
|
||||||
|
|
||||||
dialogdata.components = nil
|
|
||||||
|
|
||||||
if not filtered_page_by_id[dialogdata.page_id] then
|
|
||||||
dialogdata.leftscroll = 0
|
|
||||||
dialogdata.rightscroll = 0
|
|
||||||
|
|
||||||
dialogdata.page_id = suggested_page_id
|
|
||||||
end
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
@ -701,20 +721,26 @@ local function buttonhandler(this, fields)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for i, comp in ipairs(dialogdata.components) do
|
local function after_setting_change(comp)
|
||||||
if comp.on_submit and comp:on_submit(fields, this) then
|
write_settings_early()
|
||||||
write_settings_early()
|
if comp.setting and comp.setting.name == "touch_controls" then
|
||||||
|
-- Changing the "touch_controls" setting may result in a different
|
||||||
|
-- page list.
|
||||||
|
regenerate_page_list(dialogdata)
|
||||||
|
else
|
||||||
-- Clear components so they regenerate
|
-- Clear components so they regenerate
|
||||||
dialogdata.components = nil
|
dialogdata.components = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for i, comp in ipairs(dialogdata.components) do
|
||||||
|
if comp.on_submit and comp:on_submit(fields, this) then
|
||||||
|
after_setting_change(comp)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
if comp.setting and fields["reset_" .. i] then
|
if comp.setting and fields["reset_" .. i] then
|
||||||
core.settings:remove(comp.setting.name)
|
core.settings:remove(comp.setting.name)
|
||||||
write_settings_early()
|
after_setting_change(comp)
|
||||||
|
|
||||||
-- Clear components so they regenerate
|
|
||||||
dialogdata.components = nil
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -725,7 +751,7 @@ end
|
||||||
|
|
||||||
local function eventhandler(event)
|
local function eventhandler(event)
|
||||||
if event == "DialogShow" then
|
if event == "DialogShow" then
|
||||||
-- Don't show the "MINETEST" header behind the dialog.
|
-- Don't show the header image behind the dialog.
|
||||||
mm_game_theme.set_engine(true)
|
mm_game_theme.set_engine(true)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,10 +13,10 @@ local minetest_example_header = [[
|
||||||
# ../minetest.conf
|
# ../minetest.conf
|
||||||
# ../../minetest.conf
|
# ../../minetest.conf
|
||||||
# Any other path can be chosen by passing the path as a parameter
|
# Any other path can be chosen by passing the path as a parameter
|
||||||
# to the program, eg. "minetest.exe --config ../minetest.conf.example".
|
# to the program, eg. "luanti.exe --config ../minetest.conf.example".
|
||||||
|
|
||||||
# Further documentation:
|
# Further documentation:
|
||||||
# https://wiki.minetest.net/
|
# https://wiki.luanti.org/
|
||||||
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2022 rubenwardy
|
--Copyright (C) 2022 rubenwardy
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2015 PilzAdam
|
--Copyright (C) 2015 PilzAdam
|
||||||
--
|
--
|
||||||
--This program is free software; you can redistribute it and/or modify
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
--Minetest
|
--Luanti
|
||||||
--Copyright (C) 2021-2 x2048
|
--Copyright (C) 2021-2 x2048
|
||||||
--Copyright (C) 2022-3 rubenwardy
|
--Copyright (C) 2022-3 rubenwardy
|
||||||
--
|
--
|
||||||
|
@ -82,7 +82,6 @@ end
|
||||||
return {
|
return {
|
||||||
query_text = "Shadows",
|
query_text = "Shadows",
|
||||||
requires = {
|
requires = {
|
||||||
shaders = true,
|
|
||||||
opengl = true,
|
opengl = true,
|
||||||
},
|
},
|
||||||
get_formspec = function(self, avail_w)
|
get_formspec = function(self, avail_w)
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue