1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00

Merge remote-tracking branch 'upstream/master' into Visuals-Vol-2

This commit is contained in:
Gefüllte Taubenbrust 2024-06-11 13:59:14 +02:00
commit cd6e304cfa
172 changed files with 27747 additions and 18949 deletions

View file

@ -20,6 +20,8 @@ on:
- 'lib/**.cpp'
- 'src/**.[ch]'
- 'src/**.cpp'
- 'irr/**.[ch]'
- 'irr/**.cpp'
- '**/CMakeLists.txt'
- 'cmake/Modules/**'
- 'android/**'
@ -27,15 +29,24 @@ on:
jobs:
build:
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Install deps
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends gettext openjdk-11-jdk-headless
- name: Build with Gradle
sudo apt-get install -y --no-install-recommends gettext openjdk-17-jdk-headless
- name: Build AAB with Gradle
# We build an AAB as well for uploading to the the Play Store.
run: cd android; ./gradlew bundlerelease
- name: Build APKs with Gradle
# "assemblerelease" is very fast after "bundlerelease".
run: cd android; ./gradlew assemblerelease
- name: Save AAB artifact
uses: actions/upload-artifact@v4
with:
name: Minetest-release.aab
path: android/app/build/outputs/bundle/release/app-release.aab
- name: Save armeabi artifact
uses: actions/upload-artifact@v4
with:

View file

@ -20,6 +20,8 @@ on:
- 'lib/**.cpp'
- 'src/**.[ch]'
- 'src/**.cpp'
- 'irr/**.[ch]'
- 'irr/**.cpp'
- '**/CMakeLists.txt'
- 'cmake/Modules/**'
- 'util/ci/**'

View file

@ -9,7 +9,7 @@ on:
push:
branches: [ "master" ]
# Publish semver tags as releases.
tags: [ "*.*.*" ]
tags: [ "*" ]
pull_request:
# Build docker image on pull requests. (but do not publish)
paths:
@ -17,6 +17,8 @@ on:
- 'lib/**.cpp'
- 'src/**.[ch]'
- 'src/**.cpp'
- 'irr/**.[ch]'
- 'irr/**.cpp'
- '**/CMakeLists.txt'
- 'cmake/Modules/**'
- 'util/ci/**'
@ -25,6 +27,12 @@ on:
- '.dockerignore'
- '.github/workflows/docker_image.yml'
workflow_dispatch:
inputs:
use_cache:
description: "Use build cache"
required: true
type: boolean
default: true
env:
REGISTRY: ghcr.io
@ -82,6 +90,7 @@ jobs:
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
no-cache: ${{ (github.event_name == 'workflow_dispatch' && !inputs.use_cache) || startsWith(github.ref, 'refs/tags/') }}
- name: Test Docker Image
run: |

View file

@ -22,6 +22,8 @@ on:
- 'lib/**.cpp'
- 'src/**.[ch]'
- 'src/**.cpp'
- 'irr/**.[ch]'
- 'irr/**.cpp'
- '**/CMakeLists.txt'
- 'cmake/Modules/**'
- 'util/ci/**'
@ -55,21 +57,21 @@ jobs:
./bin/minetest --run-unittests
# Current gcc version
gcc_12:
runs-on: ubuntu-22.04
gcc_14:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Install deps
run: |
source ./util/ci/common.sh
install_linux_deps g++-12 libluajit-5.1-dev
install_linux_deps g++-14 libluajit-5.1-dev
- name: Build
run: |
./util/ci/build.sh
env:
CC: gcc-12
CXX: g++-12
CC: gcc-14
CXX: g++-14
- name: Test
run: |
@ -101,21 +103,21 @@ jobs:
./bin/minetest --run-unittests
# Current clang version
clang_14:
runs-on: ubuntu-22.04
clang_18:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Install deps
run: |
source ./util/ci/common.sh
install_linux_deps clang-14 lldb
install_linux_deps clang-18 lldb
- name: Build
run: |
./util/ci/build.sh
env:
CC: clang-14
CXX: clang++-14
CC: clang-18
CXX: clang++-18
- name: Test
run: |
@ -126,27 +128,26 @@ jobs:
./util/test_multiplayer.sh
# Build with prometheus-cpp (server-only)
clang_9_prometheus:
name: "clang_9 (PROMETHEUS=1)"
runs-on: ubuntu-20.04
clang_11_prometheus:
name: "clang_11 (PROMETHEUS=1)"
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Install deps
run: |
source ./util/ci/common.sh
install_linux_deps clang-9
install_linux_deps clang-11
- name: Build prometheus-cpp
run: |
./util/ci/build_prometheus_cpp.sh
run: ./util/ci/build_prometheus_cpp.sh
- name: Build
run: |
./util/ci/build.sh
env:
CC: clang-9
CXX: clang++-9
CMAKE_FLAGS: "-DENABLE_PROMETHEUS=1 -DBUILD_CLIENT=0"
CC: clang-11
CXX: clang++-11
CMAKE_FLAGS: "-DENABLE_PROMETHEUS=1 -DBUILD_CLIENT=0 -DENABLE_CURSES=0"
- name: Test
run: |

View file

@ -17,7 +17,7 @@ jobs:
# Note that the integration tests are also run in build.yml, but only when C++ code is changed.
integration_tests:
name: "Compile and run multiplayer tests"
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Install deps
@ -39,7 +39,7 @@ jobs:
luacheck:
name: "Builtin Luacheck and Unit Tests"
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
@ -50,11 +50,7 @@ jobs:
- uses: leafo/gh-actions-luarocks@v4.3.0
- name: Install LuaJIT
run: |
cd $HOME
git clone https://github.com/LuaJIT/LuaJIT/
cd LuaJIT
make -j$(nproc)
run: ./util/ci/build_luajit.sh
- name: Install luarocks tools
run: |

View file

@ -19,6 +19,9 @@ on:
- 'lib/**.cpp'
- 'src/**.[ch]'
- 'src/**.cpp'
- 'irr/**.[ch]'
- 'irr/**.cpp'
- 'irr/**.mm' # Objective-C(++)
- '**/CMakeLists.txt'
- 'cmake/Modules/**'
- '.github/workflows/macos.yml'
@ -55,6 +58,7 @@ jobs:
- name: CPack
run: |
cd build
cmake .. -DINSTALL_DEVTEST=FALSE
cpack -G ZIP -B macos
- uses: actions/upload-artifact@v4

View file

@ -21,6 +21,8 @@ on:
- 'lib/**.cpp'
- 'src/**.[ch]'
- 'src/**.cpp'
- 'irr/**.[ch]'
- 'irr/**.cpp'
- '**/CMakeLists.txt'
- 'cmake/Modules/**'
- 'util/buildbot/**'
@ -67,8 +69,8 @@ jobs:
name: VS 2019 ${{ matrix.config.arch }}-${{ matrix.type }}
runs-on: windows-2019
env:
VCPKG_VERSION: 8eb57355a4ffb410a2e94c07b4dca2dffbee8e50
# 2023.10.19
VCPKG_VERSION: 01f602195983451bc83e72f4214af2cbc495aa94
# 2024.05.24
vcpkg_packages: zlib zstd curl[winssl] openal-soft libvorbis libogg libjpeg-turbo sqlite3 freetype luajit gmp jsoncpp sdl2
strategy:
fail-fast: false
@ -92,12 +94,6 @@ jobs:
steps:
- uses: actions/checkout@v4
# Workaround for regression, see https://github.com/minetest/minetest/pull/14536
- name: Pin CMake to 3.28
uses: lukka/get-cmake@latest
with:
cmakeVersion: "~3.28.0"
- name: Restore from cache and run vcpkg
uses: lukka/run-vcpkg@v7
with:

9
.gitignore vendored
View file

@ -1,5 +1,8 @@
## Editors and development environments
*~
.cmake
CMakeUserPresets.json
Testing/*
*.swp
*.bak*
*.orig
@ -26,7 +29,8 @@ gtags.files
# Codelite
*.project
# Visual Studio Code & plugins
.vscode/
.vscode/*
!.vscode/extensions.json
build/.cmake/
# Fleet
.fleet
@ -107,7 +111,10 @@ src/cmake_config_githash.h
*.iml
test_config.h
cmake-build-debug/
cmake-build-minsizerel/
cmake-build-release/
cmake-build-relwithdebinfo/
cmake-build-default/
cmake_config.h
cmake_config_githash.h
CMakeDoxy*

5
.vscode/extensions.json vendored Normal file
View file

@ -0,0 +1,5 @@
{
"recommendations": [
"ms-vscode.cpptools-extension-pack"
]
}

View file

@ -277,8 +277,9 @@ find_package(Lua REQUIRED)
if(NOT USE_LUAJIT)
add_subdirectory(lib/bitop)
endif()
add_subdirectory(lib/sha256)
if(BUILD_BENCHMARKS)
if(BUILD_UNITTESTS OR BUILD_BENCHMARKS)
add_subdirectory(lib/catch2)
endif()

41
CMakePresets.json Normal file
View file

@ -0,0 +1,41 @@
{
"version": 3,
"cmakeMinimumRequired": {
"major": 3,
"minor": 12
},
"configurePresets": [
{
"name": "Debug",
"displayName": "Debug",
"description": "Debug preset with debug symbols and no optimizations",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "Release",
"displayName": "Release",
"description": "Release preset with optimizations and no debug symbols",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
},
{
"name": "RelWithDebInfo",
"displayName": "RelWithDebInfo",
"description": "Release with debug symbols",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
}
},
{
"name": "MinSizeRel",
"displayName": "MinSizeRel",
"description": "Release with minimal code size",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "MinSizeRel"
}
}
]
}

View file

@ -1,7 +1,6 @@
ARG DOCKER_IMAGE=alpine:3.19
FROM $DOCKER_IMAGE AS dev
ENV SPATIALINDEX_VERSION master
ENV LUAJIT_VERSION v2.1
RUN apk add --no-cache git build-base cmake curl-dev zlib-dev zstd-dev \
@ -19,7 +18,7 @@ RUN git clone --recursive https://github.com/jupp0r/prometheus-cpp && \
cmake --build build && \
cmake --install build && \
cd /usr/src/ && \
git clone --recursive https://github.com/libspatialindex/libspatialindex -b ${SPATIALINDEX_VERSION} && \
git clone --recursive https://github.com/libspatialindex/libspatialindex && \
cd libspatialindex && \
cmake -B build \
-DCMAKE_INSTALL_PREFIX=/usr/local && \

View file

@ -23,6 +23,7 @@ package net.minetest.minetest;
import org.libsdl.app.SDLActivity;
import android.content.Intent;
import android.content.ActivityNotFoundException;
import android.net.Uri;
import android.os.Bundle;
import android.text.InputType;
@ -33,6 +34,7 @@ import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Toast;
import android.content.res.Configuration;
import androidx.annotation.Keep;
@ -201,7 +203,11 @@ public class GameActivity extends SDLActivity {
public void openURI(String uri) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
startActivity(browserIntent);
try {
startActivity(browserIntent);
} catch (ActivityNotFoundException e) {
runOnUiThread(() -> Toast.makeText(this, R.string.no_web_browser, Toast.LENGTH_SHORT).show());
}
}
public String getUserDataPath() {

View file

@ -7,4 +7,5 @@
<string name="unzip_notification_title">Loading Minetest</string>
<string name="unzip_notification_description">Less than 1 minute&#8230;</string>
<string name="ime_dialog_done">Done</string>
<string name="no_web_browser">No web browser found</string>
</resources>

View file

@ -36,7 +36,7 @@ android {
buildTypes {
release {
ndk {
debugSymbolLevel 'SYMBOL_TABLE'
debugSymbolLevel 'FULL'
}
}
}

View file

@ -78,15 +78,12 @@ function dialog_create(name,get_formspec,buttonhandler,eventhandler)
return self
end
-- "message" must already be formspec-escaped, e.g. via fgettext or
-- core.formspec_escape.
function messagebox(name, message)
return dialog_create(name,
function()
return ([[
formspec_version[3]
size[8,3]
textarea[0.375,0.375;7.25,1.2;;;%s]
button[3,1.825;2,0.8;ok;%s]
]]):format(message, fgettext("OK"))
return ui.get_message_formspec("", message, "ok")
end,
function(this, fields)
if fields.ok then

View file

@ -50,6 +50,20 @@ function ui.find_by_name(name)
return ui.childlist[name]
end
--------------------------------------------------------------------------------
-- "title" and "message" must already be formspec-escaped, e.g. via fgettext or
-- core.formspec_escape.
function ui.get_message_formspec(title, message, btn_id)
return table.concat({
"size[14,8]",
"real_coordinates[true]",
"set_focus[", btn_id, ";true]",
"box[0.5,1.2;13,5;#000]",
("textarea[0.5,1.2;13,5;;%s;%s]"):format(title, message),
"button[5,6.6;4,1;", btn_id, ";" .. fgettext("OK") .. "]",
})
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Internal functions not to be called from user
@ -76,6 +90,9 @@ function ui.update()
}
ui.overridden = true
elseif gamedata ~= nil and gamedata.errormessage ~= nil then
-- Note to API users:
-- "gamedata.errormessage" must not be formspec-escaped yet.
-- For translations, fgettext_ne should be used.
local error_message = core.formspec_escape(gamedata.errormessage)
local error_title
@ -84,15 +101,7 @@ function ui.update()
else
error_title = fgettext("An error occurred:")
end
formspec = {
"size[14,8]",
"real_coordinates[true]",
"set_focus[btn_error_confirm;true]",
"box[0.5,1.2;13,5;#000]",
("textarea[0.5,1.2;13,5;;%s;%s]"):format(
error_title, error_message),
"button[5,6.6;4,1;btn_error_confirm;" .. fgettext("OK") .. "]"
}
formspec = {ui.get_message_formspec(error_title, error_message, "btn_error_confirm")}
ui.overridden = true
else
local active_toplevel_ui_elements = 0

View file

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

View file

@ -110,7 +110,7 @@ if core.set_push_moveresult1 then
standing_on_object = b2,
collisions = {{
type = "node",
axis = AXES[axis],
axis = AXES[axis + 1],
node_pos = vector.new(npx, npy, npz),
new_pos = vector.new(v0x, v0y, v0z),
old_velocity = vector.new(v1x, v1y, v1z),

View file

@ -404,7 +404,7 @@ core.register_item(":", {
})
function core.override_item(name, redefinition)
function core.override_item(name, redefinition, del_fields)
if redefinition.name ~= nil then
error("Attempt to redefine name of "..name.." to "..dump(redefinition.name), 2)
end
@ -418,6 +418,9 @@ function core.override_item(name, redefinition)
for k, v in pairs(redefinition) do
rawset(item, k, v)
end
for _, field in ipairs(del_fields or {}) do
rawset(item, field, nil)
end
register_item_raw(item)
end

View file

@ -71,7 +71,9 @@ local function download_and_extract(param)
os.remove(filename)
if tempfolder == "" then
return {
msg = fgettext_ne("Failed to extract \"$1\" (unsupported file type or broken archive)", package.title),
msg = fgettext_ne("Failed to extract \"$1\" " ..
"(insufficient disk space, unsupported file type or broken archive)",
package.title),
}
end

View file

@ -117,7 +117,7 @@ local function resolve_auto_install_spec()
end
if not resolved then
gamedata.errormessage = fgettext("The package $1 was not found.", auto_install_spec)
gamedata.errormessage = fgettext_ne("The package $1 was not found.", auto_install_spec)
ui.update()
auto_install_spec = nil

View file

@ -66,35 +66,45 @@ local function get_formspec(data)
message_bg = mt_color_orange
end
local ENABLE_TOUCH = core.settings:get_bool("enable_touch")
local w = ENABLE_TOUCH and 14 or 7
local padded_w = w - 2*0.375
local dropdown_w = ENABLE_TOUCH and 10.2 or 4.25
local button_w = (padded_w - 0.25) / 3
local button_pad = button_w / 2
local formspec = {
"formspec_version[3]",
"size[7,7.85]",
"size[", w, ",9.05]",
ENABLE_TOUCH and "padding[0.01,0.01]" or "position[0.5,0.55]",
"style[title;border=false]",
"box[0,0;7,0.5;#3333]",
"button[0,0;7,0.5;title;", fgettext("Install $1", package.title) , "]",
"box[0,0;", w, ",0.8;#3333]",
"button[0,0;", w, ",0.8;title;", fgettext("Install $1", package.title) , "]",
"container[0.375,0.70]",
"container[0.375,1]",
"label[0,0.25;", fgettext("Base Game:"), "]",
"dropdown[2,0;4.25,0.5;selected_game;", table.concat(game_list, ","), ";", selected_game_idx, "]",
"label[0,0.4;", fgettext("Base Game:"), "]",
"dropdown[", padded_w - dropdown_w, ",0;", dropdown_w, ",0.8;selected_game;",
table.concat(game_list, ","), ";", selected_game_idx, "]",
"label[0,0.8;", fgettext("Dependencies:"), "]",
"label[0,1.1;", fgettext("Dependencies:"), "]",
"tablecolumns[color;text;color;text]",
"table[0,1.1;6.25,3;packages;", table.concat(formatted_deps, ","), "]",
"table[0,1.4;", padded_w, ",3;packages;", table.concat(formatted_deps, ","), "]",
"container_end[]",
"checkbox[0.375,5.1;will_install_deps;",
"checkbox[0.375,5.7;will_install_deps;",
fgettext("Install missing dependencies"), ";",
will_install_deps and "true" or "false", "]",
"box[0,5.4;7,1.2;", message_bg, "]",
"textarea[0.375,5.5;6.25,1;;;", message, "]",
"box[0,6;", w, ",1.8;", message_bg, "]",
"textarea[0.375,6.1;", padded_w, ",1.6;;;", message, "]",
"container[1.375,6.85]",
"button[0,0;2,0.8;install_all;", fgettext("Install"), "]",
"button[2.25,0;2,0.8;cancel;", fgettext("Cancel"), "]",
"container[", 0.375 + button_pad, ",8.05]",
"button[0,0;", button_w, ",0.8;install_all;", fgettext("Install"), "]",
"button[", 0.25 + button_w, ",0;", button_w, ",0.8;cancel;", fgettext("Cancel"), "]",
"container_end[]",
}

View file

@ -723,6 +723,11 @@ local function eventhandler(event)
mm_game_theme.set_engine(true)
return true
end
if event == "FullscreenChange" then
-- Refresh the formspec to keep the fullscreen checkbox up to date.
ui.update()
return true
end
return false
end

View file

@ -156,10 +156,18 @@ local function get_formspec(tabview, name, tabdata)
-- Point the player to ContentDB when no games are found
if #pkgmgr.games == 0 then
local W = tabview.width
local H = tabview.height
local hypertext = "<global valign=middle halign=center size=18>" ..
fgettext_ne("Minetest is a game-creation platform that allows you to play many different games.") .. "\n" ..
fgettext_ne("Minetest doesn't come with a game by default.") .. " " ..
fgettext_ne("You need to install a game before you can create a world.")
local button_y = H * 2/3 - 0.6
return table.concat({
"style[label_button;border=false]",
"button[2.75,1.5;10,1;label_button;", fgettext("You have no games installed."), "]",
"button[5.25,3.5;5,1.2;game_open_cdb;", fgettext("Install a game"), "]"})
"hypertext[0.375,0;", W - 2*0.375, ",", button_y, ";ht;", core.formspec_escape(hypertext), "]",
"button[5.25,", button_y, ";5,1.2;game_open_cdb;", fgettext("Install a game"), "]"})
end
local retval = ""

View file

@ -265,8 +265,8 @@ undersampling (Undersampling) int 1 1 8
[**Graphics Effects]
# Makes all liquids opaque
opaque_water (Opaque liquids) bool false
# Allows liquids to be translucent.
translucent_liquids (Translucent liquids) bool true
# Leaves style:
# - Fancy: all faces visible
@ -381,8 +381,7 @@ crosshair_alpha (Crosshair alpha) int 255 0 255
[**Fog]
# Whether to fog out the end of the visible area. This option only works
# with the 'debug' privilege.
# Whether to fog out the end of the visible area.
enable_fog (Fog) bool true
# Make fog and sky colors depend on daytime (dawn/sunset) and view direction.
@ -1785,6 +1784,9 @@ deprecated_lua_api_handling (Deprecated Lua API handling) enum log none,log,erro
# Enable random user input (only used for testing).
random_input (Random input) bool false
# Enable random mod loading (mainly used for testing).
random_mod_load_order (Random mod load order) bool false
# Enable mod channels support.
enable_mod_channels (Mod channels) bool false
@ -2421,6 +2423,9 @@ keymap_minimap (Minimap key) key KEY_KEY_V
# Key for taking screenshots.
keymap_screenshot (Screenshot) key KEY_F12
# Key for toggling fullscreen mode.
keymap_fullscreen (Fullscreen key) key KEY_F11
# Key for dropping the currently selected item.
keymap_drop (Drop item key) key KEY_KEY_Q
@ -2532,7 +2537,7 @@ keymap_toggle_chat (Chat toggle key) key KEY_F2
# Key for toggling the display of the large chat console.
keymap_console (Large chat console key) key KEY_F10
# Key for toggling the display of fog. Only usable with 'debug' privilege.
# Key for toggling the display of fog.
keymap_toggle_fog (Fog toggle key) key KEY_F3
# Key for toggling the camera update. Only usable with 'debug' privilege.
@ -2544,6 +2549,9 @@ keymap_toggle_debug (Debug info toggle key) key KEY_F5
# Key for toggling the display of the profiler. Used for development.
keymap_toggle_profiler (Profiler toggle key) key KEY_F6
# Key for toggling the display of mapblock boundaries.
keymap_toggle_block_bounds (Block bounds toggle key) key
# Key for switching between first- and third-person camera.
keymap_camera_mode (Toggle camera mode key) key KEY_KEY_C

View file

@ -62,7 +62,8 @@ vec4 applyBloom(vec4 color, vec2 uv)
equation used: ((x * (A * x + C * B) + D * E) / (x * (A * x + B) + D * F)) - E / F
*/
vec3 uncharted2Tonemap(vec3 x)
// see https://github.com/minetest/minetest/pull/14688
highp vec3 uncharted2Tonemap(highp vec3 x)
{
return ((x * (0.22 * x + 0.03) + 0.002) / (x * (0.22 * x + 0.3) + 0.06)) - 0.03333;
}

View file

@ -20,6 +20,8 @@ General options and their default values:
SemiDebug - Partially optimized debug build
RelWithDebInfo - Release build with debug information
MinSizeRel - Release build with -Os passed to compiler to make executable as small as possible
PRECOMPILE_HEADERS=FALSE - Precompile some headers (experimental; requires CMake 3.16 or later)
PRECOMPILED_HEADERS_PATH= - Path to a file listing all headers to precompile (default points to src/precompiled_headers.txt)
ENABLE_CURL=ON - Build with cURL; Enables use of online mod repo, public serverlist and remote media fetching via http
ENABLE_CURSES=ON - Build with (n)curses; Enables a server side terminal (command line option: --terminal)
ENABLE_GETTEXT=ON - Build with Gettext; Allows using translations

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

81
doc/ides/jetbrains.md Normal file
View file

@ -0,0 +1,81 @@
# [Jetbrains IntellIJ CLion](https://www.jetbrains.com/clion)
## Linux
When opening the folder for the first time, select `Open as CMake project` if the IDE ask you between Make and CMake.
The IDE will open the folder and display the open project wizard:
![Open Project Wizard](images/jetbrains_open_project_wizard_profiles.png)
CLion try to determine a base configuration, but Minetest define it's own presets for easier setup. So you need to
delete the `Debug` profile with the `-` sign and close the dialog.
You should notice a notification telling you 4 presets have been loaded in the bottom right corner.
![Notification Popup](images/jetbrains_notification_profiles.png)
Clicking on the `View` link or going to `Settings > Build, Execution, Deployment > CMake` you should get a window
similar to the Open Project Wizard, but with the readonly presets listed.
![CMake Profiles](images/jetbrains_cmake_profiles.png)
By default, none of the presets are enabled. You can select them and enable the ones you want. Keep in mind that
triggering the CMake project reload (VCS updates, config changes, etc) will reload all the enabled profiles, so unless
you need the other ones you can enable just `Debug` and `Release`.
If none of the availlable profiles fit your needs, you can create a `CMakeUserPresets.json` file, edit it by hand and
CLion will load the presets in this window. But the easiest solution is to create an editable copy of one of the availlable
presets with the `Copy` button icon.
After these steps you should get an IDE like this.
On the main toolbar at the top right, you have a dropdown for selecting the CMake profile to use for the build. You have another dropdown next to it to select the build target; by default the `minetest` executable will be selected, but you may also have to use `IrrlichtMt` for building just the library .
![Jetbrains IDE](images/jetbrains_ide.png)
You can rightclick the topbar to change the project icon and color, for fancier looking IDE.
## Windows
Under Windows, the recommended compiler is the [Visual Studio](https://visualstudio.microsoft.com) compiler.
From the Visual Studio installer, you need to install the `Desktop development with C++` Workload. CMake is already
bundled in CLion.
By default, CLion have a MinGW compiler bundled, so if you want to use Visual Studio, you need to configure it as the default compiler.
CLion may ask you in the open project wisard for your compilers, with MinGW and Visual Studio if you have installed it predefined. You can use the arrows to make `Visual Studio` the default.
If not you can go to `Settings > Build, Execution, Deployment > Toolchains` to change it.
![Jetbrains Open Project Wizard](images/jetbrains_open_project_wizard_windows_compiler.png)
Then, the process is roughly similar to Linux, you just need to pick `Visual Studio` as toolchain.
![Jetbrains Open Project Wizard](images/jetbrains_open_project_wizard_windows_cmake.png)
[Vcpkg](https://vcpkg.io) is the recommended way of installing Minetest dependencies.
You need to let CLion know about a `vcpkg` installation to let the bundled CMake use the dependencies seamlessly and get
IDE integration. (Require CLion 2023 or later)
Go to `View > Tool Windows > Vcpkg` and click the add button. I will open a popup allowing you to add a Vcpkg
installation. By default it will download a new one that you can use to install your dependencies, but if you already
have one installed or you do not plan on using CLion only then install Vcpkg by hand and select your installation
directory. Don't forget to check `Add vcpkg installation to existing CMake profiles`. If you haven't already installed
Minetest dependencies in your vcpkg installation, you can do it right from CLion's Vcpkg tool window.
![Jetbrains Vcpkg](images/jetbrains_vcpkg.png)
Reloading the CMake project (should happen automatically, or display a notification for outdated CMake project) will now
load the dependencies.
[More infos on Vcpkg integration in CLion](https://blog.jetbrains.com/clion/2023/01/support-for-vcpkg-in-clion)

View file

@ -0,0 +1,7 @@
# [Visual Studio](https://visualstudio.microsoft.com)
From the Visual Studio installer, you need to install the `Desktop development with C++` Workload. You need to make sure the `C++ CMake tools for Windows` component is included in the installation details panel.
You need to install [Vcpkg](https://vcpkg.io) and install Minetest dependencies as stated in the compilation documentation.
For the packages to be discoverable and used by Visual Studio, you need to run `vcpkg integrate install`.

51
doc/ides/vscode.md Normal file
View file

@ -0,0 +1,51 @@
# [Visual Studio Code](https://code.visualstudio.com)
VSCode suppport for C/C++ and CMake is provided by
the [Microsoft C/C++ extension pack](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools-extension-pack).
You can install it from the VSCode extensions tab.
If you use a unofficial VSCode distribution like [VSCodium](https://vscodium.com), you will need to install the
extension pack manually by downloading the VSIX files and going to `Extensions > ... > Install from VSIX`.
CMake support for VSCode uses CMake presets provided by the project by default.
When you open the Minetest folder with VSCode, you should get a quick pick asking you for the default preset.
![VSCode CMake Preset Selection](images/vscode_cmake_preset_selection.png)
You can use the bottom bar to change the CMake profile, change the build target, build, run and debug (running/debugging doesn't build first).
![VSCode Toolbar](images/vscode_toolbar.png)
Like most of the VSCode experience, it may be faster to use commands directly (most of the VSCode UI just trigger commands).
| Command Name | Usecase |
|----------------------------------|----------------------------------|
| `CMake: Select Configure Preset` | Change the current CMake profile |
| `CMake: Set Build Target` | Change the current build target |
| `CMake: Build` | Build current target |
| `CMake: Clean` | Clean build files |
| `CMake: Run Without Debugging` | Run selected run target |
| `CMake: Debug` | Debug selected run target |
## Windows
Under Windows, the recommended compiler is the [Visual Studio](https://visualstudio.microsoft.com) compiler.
From the Visual Studio installer, you need to install the `Desktop development with C++` Workload.
[Vcpkg](https://vcpkg.io) is the recommended way of installing Minetest dependencies.
Follow the official documentation to install it and install Minetest dependencies as explained in [Windows compilation process](../compiling/windows.md).
You need to let CMake know about the `vcpkg` installation in VSCode.
Modify your `.vscode/settings.json`:
```json
{
"cmake.configureSettings": {
"CMAKE_TOOLCHAIN_FILE": "C:/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake"
}
}
```

View file

@ -63,6 +63,8 @@ The game directory can contain the following files:
* `name`: (Deprecated) same as title.
* `description`: Short description to be shown in the content tab.
See [Translating content meta](#translating-content-meta).
* `first_mod`: Use this to specify the mod that must be loaded before any other mod.
* `last_mod`: Use this to specify the mod that must be loaded after all other mods
* `allowed_mapgens = <comma-separated mapgens>`
e.g. `allowed_mapgens = v5,v6,flat`
Mapgens not in this list are removed from the list of mapgens for the
@ -5444,6 +5446,8 @@ Utilities
node_interaction_actor = true,
-- "new_pos" field in entity moveresult (5.9.0)
moveresult_new_pos = true,
-- Allow removing definition fields in `minetest.override_item`
override_item_remove_fields = true,
}
```
@ -5613,11 +5617,17 @@ Call these functions only at load time!
* `minetest.register_node(name, node definition)`
* `minetest.register_craftitem(name, item definition)`
* `minetest.register_tool(name, item definition)`
* `minetest.override_item(name, redefinition)`
* `minetest.override_item(name, redefinition, del_fields)`
* `redefinition` is a table of fields `[name] = new_value`,
overwriting fields of or adding fields to the existing definition.
* `del_fields` is a list of field names to be set
to `nil` ("deleted from") the original definition.
* Overrides fields of an item registered with register_node/tool/craftitem.
* Note: Item must already be defined, (opt)depend on the mod defining it.
* Example: `minetest.override_item("default:mese",
{light_source=minetest.LIGHT_MAX})`
{light_source=minetest.LIGHT_MAX}, {"sounds"})`:
Overwrites the `light_source` field,
removes the sounds from the definition of the mese block.
* `minetest.unregister_item(name)`
* Unregisters the item from the engine, and deletes the entry with key
`name` from `minetest.registered_items` and from the associated item table
@ -5786,6 +5796,7 @@ Call these functions only at load time!
* `last_login`: The timestamp of the previous login, or nil if player is new
* `minetest.register_on_leaveplayer(function(ObjectRef, timed_out))`
* Called when a player leaves the game
* Does not get executed for connected players on shutdown.
* `timed_out`: True for timeout, false for other reasons.
* `minetest.register_on_authplayer(function(name, ip, is_success))`
* Called when a client attempts to log into an account.
@ -8222,7 +8233,11 @@ child will follow movement and rotation of that bone.
* `"plain"`: Uses 0 textures, `base_color` used as both fog and sky.
(default: `"regular"`)
* `textures`: A table containing up to six textures in the following
order: Y+ (top), Y- (bottom), X- (west), X+ (east), Z+ (north), Z- (south).
order: Y+ (top), Y- (bottom), X+ (east), X- (west), Z- (south), Z+ (north).
The top and bottom textures are oriented in-line with the east (X+) face (the top edge of the
bottom texture and the bottom edge of the top texture touch the east face).
Some top and bottom textures expect to be aligned with the north face and will need to be rotated
by -90 and 90 degrees, respectively, to fit the eastward orientation.
* `clouds`: Boolean for whether clouds appear. (default: `true`)
* `sky_color`: A table used in `"regular"` type only, containing the
following values (alpha is ignored):
@ -8257,14 +8272,13 @@ child will follow movement and rotation of that bone.
`"default"` uses the classic Minetest sun and moon tinting.
Will use tonemaps, if set to `"default"`. (default: `"default"`)
* `fog`: A table with following optional fields:
* `fog_distance`: integer, set an upper bound the client's viewing_range (inluding range_all).
By default, fog_distance is controlled by the client's viewing_range, and this field is not set.
Any value >= 0 sets the desired upper bound for the client's viewing_range and disables range_all.
Any value < 0, resets the behavior to being client-controlled.
* `fog_distance`: integer, set an upper bound for the client's viewing_range.
Any value >= 0 sets the desired upper bound for viewing_range,
disables range_all and prevents disabling fog (F3 key by default).
Any value < 0 resets the behavior to being client-controlled.
(default: -1)
* `fog_start`: float, override the client's fog_start.
Fraction of the visible distance at which fog starts to be rendered.
By default, fog_start is controlled by the client's `fog_start` setting, and this field is not set.
Any value between [0.0, 0.99] set the fog_start as a fraction of the viewing_range.
Any value < 0, resets the behavior to being client-controlled.
(default: -1)

View file

@ -14,7 +14,8 @@ Callbacks
* `core.button_handler(fields)`: called when a button is pressed.
* `fields` = `{name1 = value1, name2 = value2, ...}`
* `core.event_handler(event)`
* `event`: `"MenuQuit"`, `"KeyEnter"`, `"ExitButton"` or `"EditBoxEnter"`
* `event`: `"MenuQuit"`, `"KeyEnter"`, `"ExitButton"`, `"EditBoxEnter"` or
`"FullscreenChange"`
Gamedata

View file

@ -1,2 +1,4 @@
title = Development Test
description = Testing environment to help with testing the engine features of Minetest. It can also be helpful in mod development.
first_mod = first_mod
last_mod = last_mod

View file

@ -0,0 +1 @@
-- Nothing to do here, loading order is tested in C++ unittests.

View file

@ -0,0 +1,2 @@
name = first_mod
description = Mod which should be loaded before every other mod.

View file

@ -0,0 +1 @@
-- Nothing to do here, loading order is tested in C++ unittests.

View file

@ -0,0 +1,5 @@
name = last_mod
description = Mod which should be loaded as last mod.
# Test dependencies
optional_depends = unittests
depends = first_mod

View file

@ -181,14 +181,6 @@ fractal = nil
frac_emb = nil
checker = nil
do
-- we used to write the textures to our mod folder. in order to avoid
-- duplication errors delete them if they still exist.
local path = core.get_modpath(core.get_current_modname()) .. "/textures/"
os.remove(path .. "testnodes_generated_mb.png")
os.remove(path .. "testnodes_generated_ck.png")
end
local textures_path = core.get_worldpath() .. "/"
core.safe_file_write(
textures_path .. "testnodes1.png",

View file

@ -160,7 +160,7 @@ function unittests.run_all()
-- Print stats
assert(#unittests.list == counters.total)
print(string.rep("+", 80))
print(string.format("Unit Test Results: %s",
print(string.format("Devtest Unit Test Results: %s",
counters.total == counters.passed and "PASSED" or "FAILED"))
print(string.format(" %d / %d failed tests.",
counters.total - counters.passed, counters.total))
@ -185,22 +185,46 @@ dofile(modpath .. "/content_ids.lua")
dofile(modpath .. "/metadata.lua")
dofile(modpath .. "/raycast.lua")
dofile(modpath .. "/inventory.lua")
dofile(modpath .. "/load_time.lua")
--------------
local function send_results(name, ok)
core.chat_send_player(name,
minetest.colorize(ok and "green" or "red",
(ok and "All devtest unit tests passed." or
"There were devtest unit test failures.") ..
" Check the console for detailed output."))
end
if core.settings:get_bool("devtest_unittests_autostart", false) then
local test_results = nil
core.after(0, function()
-- CI adds a mod which sets `unittests.on_finished`
-- to write status information to the filesystem
local old_on_finished = unittests.on_finished
unittests.on_finished = function(ok)
for _, player in ipairs(minetest.get_connected_players()) do
send_results(player:get_player_name(), ok)
end
test_results = ok
old_on_finished(ok)
end
coroutine.wrap(unittests.run_all)()
end)
minetest.register_on_joinplayer(function(player)
if test_results == nil then
return -- tests haven't completed yet
end
send_results(player:get_player_name(), test_results)
end)
else
core.register_chatcommand("unittests", {
privs = {basic_privs=true},
description = "Runs devtest unittests (may modify player or map state)",
func = function(name, param)
unittests.on_finished = function(ok)
core.chat_send_player(name,
(ok and "All tests passed." or "There were test failures.") ..
" Check the console for detailed output.")
send_results(name, ok)
end
coroutine.wrap(unittests.run_all)()
return true, ""

View file

@ -0,0 +1,13 @@
-- Test item (un)registration and overriding
do
local itemname = "unittests:test_override_item"
minetest.register_craftitem(":" .. itemname, {description = "foo"})
assert(assert(minetest.registered_items[itemname]).description == "foo")
minetest.override_item(itemname, {description = "bar"})
assert(assert(minetest.registered_items[itemname]).description == "bar")
minetest.override_item(itemname, {}, {"description"})
-- description has the empty string as a default
assert(assert(minetest.registered_items[itemname]).description == "")
minetest.unregister_item("unittests:test_override_item")
assert(minetest.registered_items["unittests:test_override_item"] == nil)
end

View file

@ -1,3 +1,4 @@
name = unittests
description = Adds automated unit tests for the engine
depends = basenodes
# Also test that it is possible to depend on first_mod
depends = first_mod, basenodes

View file

@ -331,7 +331,6 @@ struct SEvent
//! A bitmap of button states. You can use isButtonPressed() to determine
//! if a button is pressed or not.
//! Currently only valid if the event was EMIE_MOUSE_MOVED
u32 ButtonStates;
//! Is the left button pressed down?

View file

@ -176,6 +176,32 @@ public:
}
return 0;
}
//! Calculate size of vertices and indices in memory
virtual size_t getSize() const
{
size_t ret = 0;
switch (getVertexType()) {
case video::EVT_STANDARD:
ret += sizeof(video::S3DVertex) * getVertexCount();
break;
case video::EVT_2TCOORDS:
ret += sizeof(video::S3DVertex2TCoords) * getVertexCount();
break;
case video::EVT_TANGENTS:
ret += sizeof(video::S3DVertexTangents) * getVertexCount();
break;
}
switch (getIndexType()) {
case video::EIT_16BIT:
ret += sizeof(u16) * getIndexCount();
break;
case video::EIT_32BIT:
ret += sizeof(u32) * getIndexCount();
break;
}
return ret;
}
};
} // end namespace scene

View file

@ -179,6 +179,11 @@ public:
/** \return True if window is fullscreen. */
virtual bool isFullscreen() const = 0;
//! Enables or disables fullscreen mode.
/** Only works on SDL.
\return True on success. */
virtual bool setFullscreen(bool fullscreen) { return false; }
//! Checks if the window could possibly be visible.
/** If this returns false, you should not do any rendering. */
virtual bool isWindowVisible() const { return true; };

View file

@ -852,6 +852,7 @@ bool CIrrDeviceMacOSX::run()
ievent.MouseInput.Wheel *= 10.0f;
else
ievent.MouseInput.Wheel *= 5.0f;
ievent.MouseInput.ButtonStates = MouseButtonStates;
postMouseEvent(event, ievent);
break;
@ -1048,6 +1049,7 @@ void CIrrDeviceMacOSX::storeMouseLocation()
ievent.MouseInput.Event = irr::EMIE_MOUSE_MOVED;
ievent.MouseInput.X = x;
ievent.MouseInput.Y = y;
ievent.MouseInput.ButtonStates = MouseButtonStates;
postEventFromUser(ievent);
}
}

View file

@ -272,6 +272,19 @@ CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters &param) :
SDL_SetHint(SDL_HINT_ENABLE_SCREEN_KEYBOARD, "0");
#endif
// Minetest has its own signal handler
SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS, "1");
// Disabling the compositor is not a good idea in windowed mode.
// See https://github.com/minetest/minetest/issues/14596
SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
#if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_)
// These are not interesting for our use
SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
SDL_SetHint(SDL_HINT_TV_REMOTE_AS_JOYSTICK, "0");
#endif
// Minetest has its own code to synthesize mouse events from touch events,
// so we prevent SDL from doing it.
SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
@ -463,13 +476,7 @@ bool CIrrDeviceSDL::createWindowWithContext()
{
u32 SDL_Flags = 0;
if (CreationParams.Fullscreen) {
#ifdef _IRR_EMSCRIPTEN_PLATFORM_
SDL_Flags |= SDL_WINDOW_FULLSCREEN;
#else
SDL_Flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
#endif
}
SDL_Flags |= getFullscreenFlag(CreationParams.Fullscreen);
if (Resizable)
SDL_Flags |= SDL_WINDOW_RESIZABLE;
if (CreationParams.WindowMaximized)
@ -673,6 +680,7 @@ bool CIrrDeviceSDL::run()
#else
irrevent.MouseInput.Wheel = SDL_event.wheel.y;
#endif
irrevent.MouseInput.ButtonStates = MouseButtonStates;
irrevent.MouseInput.Shift = (keymod & KMOD_SHIFT) != 0;
irrevent.MouseInput.Control = (keymod & KMOD_CTRL) != 0;
irrevent.MouseInput.X = MouseX;
@ -889,6 +897,14 @@ bool CIrrDeviceSDL::run()
IsInBackground = false;
break;
case SDL_RENDER_TARGETS_RESET:
os::Printer::log("Received SDL_RENDER_TARGETS_RESET. Rendering is probably broken.", ELL_ERROR);
break;
case SDL_RENDER_DEVICE_RESET:
os::Printer::log("Received SDL_RENDER_DEVICE_RESET. Rendering is probably broken.", ELL_ERROR);
break;
default:
break;
} // end switch
@ -1157,14 +1173,37 @@ bool CIrrDeviceSDL::isWindowMaximized() const
bool CIrrDeviceSDL::isFullscreen() const
{
#ifdef _IRR_EMSCRIPTEN_PLATFORM_
return SDL_GetWindowFlags(0) == SDL_WINDOW_FULLSCREEN;
#else
if (!Window)
return false;
u32 flags = SDL_GetWindowFlags(Window);
return (flags & SDL_WINDOW_FULLSCREEN) != 0 ||
(flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0;
}
return CIrrDeviceStub::isFullscreen();
u32 CIrrDeviceSDL::getFullscreenFlag(bool fullscreen)
{
if (!fullscreen)
return 0;
#ifdef _IRR_EMSCRIPTEN_PLATFORM_
return SDL_WINDOW_FULLSCREEN;
#else
return SDL_WINDOW_FULLSCREEN_DESKTOP;
#endif
}
bool CIrrDeviceSDL::setFullscreen(bool fullscreen)
{
if (!Window)
return false;
// The SDL wiki says that this may trigger SDL_RENDER_TARGETS_RESET, but
// looking at the SDL source, this only happens with D3D, so it's not
// relevant to us.
bool success = SDL_SetWindowFullscreen(Window, getFullscreenFlag(fullscreen)) == 0;
if (!success)
os::Printer::log("SDL_SetWindowFullscreen failed", SDL_GetError(), ELL_ERROR);
return success;
}
bool CIrrDeviceSDL::isWindowVisible() const
{
return !IsInBackground;

View file

@ -86,6 +86,10 @@ public:
/** \return True if window is fullscreen. */
bool isFullscreen() const override;
//! Enables or disables fullscreen mode.
/** \return True on success. */
bool setFullscreen(bool fullscreen) override;
//! Checks if the window could possibly be visible.
bool isWindowVisible() const override;
@ -299,6 +303,8 @@ private:
bool Resizable;
static u32 getFullscreenFlag(bool fullscreen);
core::rect<s32> lastElemPos;
struct SKeyMap

View file

@ -31,7 +31,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "^(GNU|Clang|AppleClang)$")
elseif(MSVC)
string(APPEND CMAKE_CXX_STANDARD_LIBRARIES " msvcrt.lib") # ???? fuck off
add_compile_options(/GR- /Zl)
add_compile_options(/Zl)
# Enable SSE for floating point math on 32-bit x86 by default
# reasoning see minetest issue #11810 and https://gcc.gnu.org/wiki/FloatingPointMath

View file

@ -29,18 +29,6 @@
#include "fast_atof.h"
#if defined(_IRR_COMPILE_WITH_SDL_DEVICE_)
static const bool sdl_supports_primary_selection = [] {
#if SDL_VERSION_ATLEAST(2, 25, 0)
SDL_version linked_version;
SDL_GetVersion(&linked_version);
return (linked_version.major == 2 && linked_version.minor >= 25) || linked_version.major > 2;
#else
return false;
#endif
}();
#endif
namespace irr
{
@ -131,8 +119,7 @@ void COSOperator::copyToPrimarySelection(const c8 *text) const
#if defined(_IRR_COMPILE_WITH_SDL_DEVICE_)
#if SDL_VERSION_ATLEAST(2, 25, 0)
if (sdl_supports_primary_selection)
SDL_SetPrimarySelectionText(text);
SDL_SetPrimarySelectionText(text);
#endif
#elif defined(_IRR_COMPILE_WITH_X11_DEVICE_)
@ -195,11 +182,9 @@ const c8 *COSOperator::getTextFromPrimarySelection() const
{
#if defined(_IRR_COMPILE_WITH_SDL_DEVICE_)
#if SDL_VERSION_ATLEAST(2, 25, 0)
if (sdl_supports_primary_selection) {
SDL_free(PrimarySelectionText);
PrimarySelectionText = SDL_GetPrimarySelectionText();
return PrimarySelectionText;
}
SDL_free(PrimarySelectionText);
PrimarySelectionText = SDL_GetPrimarySelectionText();
return PrimarySelectionText;
#endif
return 0;

View file

@ -704,12 +704,6 @@ IRenderTarget *COpenGL3DriverBase::addRenderTarget()
return renderTarget;
}
// small helper function to create vertex buffer object adress offsets
static inline u8 *buffer_offset(const long offset)
{
return ((u8 *)0 + offset);
}
//! draws a vertex primitive list
void COpenGL3DriverBase::drawVertexPrimitiveList(const void *vertices, u32 vertexCount,
const void *indexList, u32 primitiveCount,

View file

@ -102,6 +102,8 @@ public:
// internally used
virtual void draw2DImage(const video::ITexture *texture, u32 layer, bool flip);
using CNullDriver::draw2DImage;
void draw2DImageBatch(const video::ITexture *texture,
const core::array<core::position2d<s32>> &positions,
const core::array<core::rect<s32>> &sourceRects,

View file

@ -12,47 +12,14 @@
#include "os.h"
#include <mt_opengl.h>
// FIXME: this basically duplicates what mt_opengl.h already does
namespace irr
{
namespace video
{
void COpenGL3ExtensionHandler::initExtensionsOld()
{
auto extensions_string = reinterpret_cast<const char *>(GL.GetString(GL_EXTENSIONS));
const char *pos = extensions_string;
while (const char *next = strchr(pos, ' ')) {
addExtension(std::string{pos, next});
pos = next + 1;
}
addExtension(pos);
extensionsLoaded();
}
void COpenGL3ExtensionHandler::initExtensionsNew()
void COpenGL3ExtensionHandler::initExtensions()
{
int ext_count = GetInteger(GL_NUM_EXTENSIONS);
for (int k = 0; k < ext_count; k++)
addExtension(reinterpret_cast<const char *>(GL.GetStringi(GL_EXTENSIONS, k)));
extensionsLoaded();
}
void COpenGL3ExtensionHandler::addExtension(std::string &&name)
{
Extensions.emplace(std::move(name));
}
bool COpenGL3ExtensionHandler::queryExtension(const std::string &name) const noexcept
{
return Extensions.find(name) != Extensions.end();
}
void COpenGL3ExtensionHandler::extensionsLoaded()
{
os::Printer::log((std::string("Loaded ") + std::to_string(Extensions.size()) + " extensions:").c_str(), ELL_DEBUG);
for (const auto &it : Extensions)
os::Printer::log((std::string(" ") + it).c_str(), ELL_DEBUG);
// reading extensions happens in mt_opengl.cpp
for (size_t j = 0; j < IRR_OGLES_Feature_Count; ++j)
FeatureAvailable[j] = queryExtension(getFeatureString(j));
}

View file

@ -28,11 +28,13 @@ public:
COpenGL3ExtensionHandler() :
COGLESCoreExtensionHandler() {}
void initExtensionsOld();
void initExtensionsNew();
void initExtensions();
/// Checks whether a named extension is present
bool queryExtension(const std::string &name) const noexcept;
inline bool queryExtension(const std::string &name) const noexcept
{
return GL.IsExtensionPresent(name);
}
bool queryFeature(video::E_VIDEO_DRIVER_FEATURE feature) const
{
@ -138,7 +140,8 @@ public:
inline void irrGlDrawBuffer(GLenum mode)
{
GL.DrawBuffer(mode);
// GLES only has DrawBuffers, so use that
GL.DrawBuffers(1, &mode);
}
inline void irrGlDrawBuffers(GLsizei n, const GLenum *bufs)
@ -158,12 +161,6 @@ public:
bool AnisotropicFilterSupported = false;
bool BlendMinMaxSupported = false;
private:
void addExtension(std::string &&name);
void extensionsLoaded();
std::unordered_set<std::string> Extensions;
};
}

View file

@ -37,15 +37,15 @@ public:
GLuint getProgram() const;
virtual void OnSetMaterial(const SMaterial &material, const SMaterial &lastMaterial,
bool resetAllRenderstates, IMaterialRendererServices *services);
bool resetAllRenderstates, IMaterialRendererServices *services) override;
virtual bool OnRender(IMaterialRendererServices *service, E_VERTEX_TYPE vtxtype);
virtual bool OnRender(IMaterialRendererServices *service, E_VERTEX_TYPE vtxtype) override;
virtual void OnUnsetMaterial();
virtual void OnUnsetMaterial() override;
virtual bool isTransparent() const;
virtual bool isTransparent() const override;
virtual s32 getRenderCapability() const;
virtual s32 getRenderCapability() const override;
void setBasicRenderStates(const SMaterial &material, const SMaterial &lastMaterial, bool resetAllRenderstates) override;

View file

@ -36,7 +36,7 @@ void COpenGL3Driver::initFeatures()
{
assert(Version.Spec == OpenGLSpec::Compat);
assert(isVersionAtLeast(3, 2));
initExtensionsNew();
initExtensions();
TextureFormats[ECF_A1R5G5B5] = {GL_RGB5_A1, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV}; // WARNING: may not be renderable
TextureFormats[ECF_R5G6B5] = {GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5}; // GL_RGB565 is an extension until 4.1

View file

@ -31,10 +31,7 @@ void COpenGLES2Driver::initFeatures()
{
assert(Version.Spec == OpenGLSpec::ES);
assert(Version.Major >= 2);
if (Version.Major >= 3)
initExtensionsNew();
else
initExtensionsOld();
initExtensions();
static const GLenum BGRA8_EXT = 0x93A1;

View file

@ -1,8 +1,8 @@
# catch2 is distributed as a standalone header.
# catch2 is distributed as a standalone header / source amalgamation.
#
# Downloaded from:
#
# https://github.com/catchorg/Catch2/releases/download/v2.13.9/catch.hpp
# https://github.com/catchorg/Catch2/releases/tag/v3.6.0
#
# The following changes were made to always print in microseconds, fixed format:
#
@ -12,5 +12,7 @@
# - return os << duration.value() << ' ' << duration.unitsAsString();
# + return os << std::fixed << duration.value() << ' ' << duration.unitsAsString();
add_library(catch2 INTERFACE)
target_include_directories(catch2 INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
add_library(catch2 STATIC catch_amalgamated.cpp)
target_compile_definitions(catch2 PRIVATE CATCH_CONFIG_NOSTDOUT CATCH_AMALGAMATED_CUSTOM_MAIN)
add_library(Catch2::Catch2 ALIAS catch2)
target_include_directories(catch2 INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}")

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

14
lib/sha256/CMakeLists.txt Normal file
View file

@ -0,0 +1,14 @@
project(sha256 C)
add_library(sha256 STATIC sha256.c)
target_include_directories(sha256 INTERFACE .)
INCLUDE(CheckIncludeFiles)
check_include_files(endian.h HAVE_ENDIAN_H)
configure_file(
"${PROJECT_SOURCE_DIR}/cmake_config.h.in"
"${PROJECT_BINARY_DIR}/cmake_config.h"
)
target_include_directories(sha256 PRIVATE "${PROJECT_BINARY_DIR}")

View file

@ -0,0 +1,5 @@
// Filled in by the build system
#pragma once
#cmakedefine HAVE_ENDIAN_H

View file

@ -56,17 +56,13 @@
#include <stdlib.h>
#include <string.h>
#include "util/sha256.h"
#include "my_sha256.h"
#if defined(_MSC_VER) && !defined(__clang__) && !defined(__attribute__)
#define __attribute__(a)
#endif
/* pull HAVE_ENDIAN_H from Minetest */
#include "config.h"
#if !HAVE_ENDIAN_H
#undef HAVE_ENDIAN_H
#endif
#include "cmake_config.h" /* HAVE_ENDIAN_H */
/** endian.h **/
/*

View file

@ -48,6 +48,25 @@ if(NOT (BUILD_CLIENT OR BUILD_SERVER))
endif()
option(PRECOMPILE_HEADERS "Precompile some headers (experimental; requires CMake 3.16 or later)" FALSE)
set(PRECOMPILED_HEADERS_PATH "" CACHE FILEPATH "Path to a file listing all headers to precompile")
if(PRECOMPILE_HEADERS)
if(${CMAKE_VERSION} VERSION_LESS 3.16)
message(FATAL_ERROR "PRECOMPILE_HEADERS is on, but precompiled headers require at least CMake 3.16.")
endif()
if(PRECOMPILED_HEADERS_PATH)
set(PRECOMPILED_HEADERS ${PRECOMPILED_HEADERS_PATH})
else()
set(PRECOMPILED_HEADERS "${CMAKE_SOURCE_DIR}/src/precompiled_headers.txt")
endif()
message(STATUS "Reading headers to precompile from: ${PRECOMPILED_HEADERS}")
# ignore lines that begin with # and empty lines
file(STRINGS ${PRECOMPILED_HEADERS} PRECOMPILED_HEADERS_LIST REGEX "^[^#].*$")
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${PRECOMPILED_HEADERS})
endif()
option(ENABLE_CURL "Enable cURL support for fetching media" TRUE)
set(USE_CURL FALSE)
@ -332,6 +351,12 @@ endif()
include(CheckSymbolExists)
check_symbol_exists(strlcpy "string.h" HAVE_STRLCPY)
if(UNIX)
check_symbol_exists(malloc_trim "malloc.h" HAVE_MALLOC_TRIM)
else()
set(HAVE_MALLOC_TRIM FALSE)
endif()
check_include_files(endian.h HAVE_ENDIAN_H)
configure_file(
@ -449,6 +474,10 @@ if(BUILD_BENCHMARKS)
set(common_SRCS ${common_SRCS} ${BENCHMARK_SRCS})
endif()
if(BUILD_UNITTESTS OR BUILD_BENCHMARKS)
set(common_SRCS ${common_SRCS} catch.cpp)
endif()
# This gives us the icon and file version information
if(WIN32)
set(WINRESOURCE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/../misc/winresource.rc")
@ -565,6 +594,7 @@ if(BUILD_CLIENT)
${GMP_LIBRARY}
${JSON_LIBRARY}
${LUA_BIT_LIBRARY}
sha256
${FREETYPE_LIBRARY}
${PLATFORM_LIBS}
# on Android, Minetest depends on SDL2 directly
@ -615,8 +645,12 @@ if(BUILD_CLIENT)
if (USE_SPATIAL)
target_link_libraries(${PROJECT_NAME} ${SPATIAL_LIBRARY})
endif()
if(BUILD_BENCHMARKS)
target_link_libraries(${PROJECT_NAME} catch2)
if(BUILD_UNITTESTS OR BUILD_BENCHMARKS)
target_link_libraries(${PROJECT_NAME} Catch2::Catch2)
endif()
if(PRECOMPILE_HEADERS)
target_precompile_headers(${PROJECT_NAME} PRIVATE ${PRECOMPILED_HEADERS_LIST})
endif()
endif(BUILD_CLIENT)
@ -637,6 +671,7 @@ if(BUILD_SERVER)
${JSON_LIBRARY}
${LUA_LIBRARY}
${LUA_BIT_LIBRARY}
sha256
${GMP_LIBRARY}
${PLATFORM_LIBS}
)
@ -677,8 +712,12 @@ if(BUILD_SERVER)
${CURL_LIBRARY}
)
endif()
if(BUILD_BENCHMARKS)
target_link_libraries(${PROJECT_NAME}server catch2)
if(BUILD_UNITTESTS OR BUILD_BENCHMARKS)
target_link_libraries(${PROJECT_NAME}server Catch2::Catch2)
endif()
if(PRECOMPILE_HEADERS)
target_precompile_headers(${PROJECT_NAME}server PRIVATE ${PRECOMPILED_HEADERS_LIST})
endif()
endif(BUILD_SERVER)

View file

@ -31,7 +31,6 @@ class TestServerActiveObjectMgr;
template <typename T>
class ActiveObjectMgr
{
friend class ::TestClientActiveObjectMgr;
friend class ::TestServerActiveObjectMgr;
public:

View file

@ -19,9 +19,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "benchmark/benchmark.h"
// This must be set in just this file
#define CATCH_CONFIG_RUNNER
#include "benchmark_setup.h"
#define CATCH_CONFIG_ENABLE_BENCHMARKING
#include "catch.h"
bool run_benchmarks(const char *arg)
{

View file

@ -1,7 +1,7 @@
// Minetest
// SPDX-License-Identifier: LGPL-2.1-or-later
#include "benchmark_setup.h"
#include "catch.h"
#include "server/activeobjectmgr.h"
#include "util/numeric.h"

View file

@ -17,7 +17,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "benchmark_setup.h"
#include "catch.h"
#include "voxelalgorithms.h"
#include "dummygamedef.h"
#include "dummymap.h"

View file

@ -17,7 +17,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "benchmark_setup.h"
#include "catch.h"
#include "mapblock.h"
#include <vector>

View file

@ -17,7 +17,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "benchmark_setup.h"
#include "catch.h"
#include "util/container.h"
// Testing the standard library is not useful except to compare

View file

@ -17,7 +17,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "benchmark_setup.h"
#include "catch.h"
#include "util/serialize.h"
#include <sstream>
#include <ios>

View file

@ -1,22 +0,0 @@
/*
Minetest
Copyright (C) 2022 Minetest Authors
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.
*/
#define CATCH_CONFIG_ENABLE_BENCHMARKING
#define CATCH_CONFIG_CONSOLE_WIDTH 160
#include <catch.hpp>

18
src/catch.cpp Normal file
View file

@ -0,0 +1,18 @@
// Minetest
// SPDX-License-Identifier: LGPL-2.1-or-later
#include "catch.h"
#include "log.h"
namespace Catch {
std::ostream& cout() {
return rawstream;
}
std::ostream& clog() {
return rawstream;
}
std::ostream& cerr() {
return rawstream;
}
}

14
src/catch.h Normal file
View file

@ -0,0 +1,14 @@
// Minetest
// SPDX-License-Identifier: LGPL-2.1-or-later
// We want to have catch write to rawstream (stderr) instead of stdout.
// This should be included instead of <catch_amalgamated.hpp>
// to patch the output streams accordingly.
#define CATCH_CONFIG_NOSTDOUT
#include <catch_amalgamated.hpp>
namespace Catch {
std::ostream& cout();
std::ostream& clog();
std::ostream& cerr();
}

View file

@ -376,6 +376,13 @@ u32 ChatBuffer::formatChatLine(const ChatLine &line, u32 cols,
tempchar = linestring[in_pos+frag_length];
}
// Remove tailing punctuation characters
static const std::wstring tailing_chars = L",.";
tempchar = linestring[in_pos+frag_length - 1];
if (tailing_chars.find(tempchar) != std::wstring::npos) {
frag_length--;
}
space_pos = frag_length - 1;
// This frag may need to be force-split. That's ok, urls aren't "words"
if (frag_length >= remaining_in_output) {

View file

@ -278,9 +278,7 @@ void Client::scanModSubfolder(const std::string &mod_name, const std::string &mo
<< "\" as \"" << vfs_path << "\"." << std::endl;
std::string contents;
if (!fs::ReadFile(real_path, contents)) {
errorstream << "Client::scanModSubfolder(): Can't read file \""
<< real_path << "\"." << std::endl;
if (!fs::ReadFile(real_path, contents, true)) {
continue;
}
@ -1945,8 +1943,7 @@ void Client::makeScreenshot()
while (serial < SCREENSHOT_MAX_SERIAL_TRIES) {
filename = filename_base + (serial > 0 ? ("_" + itos(serial)) : "") + filename_ext;
std::ifstream tmp(filename.c_str());
if (!tmp.good())
if (!fs::PathExists(filename))
break; // File did not apparently exist, we'll go with it
serial++;
}

View file

@ -36,6 +36,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "network/networkexceptions.h"
#include <IGUISpriteBank.h>
#include <ICameraSceneNode.h>
#include <unordered_map>
#if USE_SOUND
#include "sound/sound_openal.h"
@ -68,6 +69,7 @@ static void dump_start_data(const GameStartData &data)
ClientLauncher::~ClientLauncher()
{
delete input;
g_settings->deregisterChangedCallback("gui_scaling", setting_changed_callback, this);
delete g_fontengine;
g_fontengine = nullptr;
@ -126,7 +128,8 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args)
setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true);
guienv = m_rendering_engine->get_gui_env();
init_guienv(guienv);
config_guienv();
g_settings->registerChangedCallback("gui_scaling", setting_changed_callback, this);
g_fontengine = new FontEngine(guienv);
@ -326,7 +329,12 @@ void ClientLauncher::init_input()
}
}
void ClientLauncher::init_guienv(gui::IGUIEnvironment *guienv)
void ClientLauncher::setting_changed_callback(const std::string &name, void *data)
{
static_cast<ClientLauncher*>(data)->config_guienv();
}
void ClientLauncher::config_guienv()
{
gui::IGUISkin *skin = guienv->getSkin();
@ -343,25 +351,37 @@ void ClientLauncher::init_guienv(gui::IGUIEnvironment *guienv)
float density = rangelim(g_settings->getFloat("gui_scaling"), 0.5f, 20) *
RenderingEngine::getDisplayDensity();
skin->setSize(gui::EGDS_CHECK_BOX_WIDTH, (s32)(17.0f * density));
skin->setSize(gui::EGDS_SCROLLBAR_SIZE, (s32)(14.0f * density));
skin->setSize(gui::EGDS_SCROLLBAR_SIZE, (s32)(21.0f * density));
skin->setSize(gui::EGDS_WINDOW_BUTTON_WIDTH, (s32)(15.0f * density));
static u32 orig_sprite_id = skin->getIcon(gui::EGDI_CHECK_BOX_CHECKED);
static std::unordered_map<std::string, u32> sprite_ids;
if (density > 1.5f) {
std::string sprite_path = porting::path_share + "/textures/base/pack/";
if (density > 3.5f)
sprite_path.append("checkbox_64.png");
else if (density > 2.0f)
sprite_path.append("checkbox_32.png");
else
sprite_path.append("checkbox_16.png");
// Texture dimensions should be a power of 2
gui::IGUISpriteBank *sprites = skin->getSpriteBank();
video::IVideoDriver *driver = m_rendering_engine->get_video_driver();
video::ITexture *sprite_texture = driver->getTexture(sprite_path.c_str());
if (sprite_texture) {
s32 sprite_id = sprites->addTextureAsSprite(sprite_texture);
if (sprite_id != -1)
skin->setIcon(gui::EGDI_CHECK_BOX_CHECKED, sprite_id);
std::string path = porting::path_share + "/textures/base/pack/";
if (density > 3.5f)
path.append("checkbox_64.png");
else if (density > 2.0f)
path.append("checkbox_32.png");
else
path.append("checkbox_16.png");
auto cached_id = sprite_ids.find(path);
if (cached_id != sprite_ids.end()) {
skin->setIcon(gui::EGDI_CHECK_BOX_CHECKED, cached_id->second);
} else {
gui::IGUISpriteBank *sprites = skin->getSpriteBank();
video::IVideoDriver *driver = m_rendering_engine->get_video_driver();
video::ITexture *texture = driver->getTexture(path.c_str());
s32 id = sprites->addTextureAsSprite(texture);
if (id != -1) {
skin->setIcon(gui::EGDI_CHECK_BOX_CHECKED, id);
sprite_ids.emplace(path, id);
}
}
} else {
skin->setIcon(gui::EGDI_CHECK_BOX_CHECKED, orig_sprite_id);
}
}

View file

@ -38,7 +38,9 @@ private:
void init_args(GameStartData &start_data, const Settings &cmd_args);
bool init_engine();
void init_input();
void init_guienv(gui::IGUIEnvironment *guienv);
static void setting_changed_callback(const std::string &name, void *data);
void config_guienv();
bool launch_game(std::string &error_message, bool reconnect_requested,
GameStartData &start_data, const Settings &cmd_args);

View file

@ -38,13 +38,9 @@ void FileCache::createDir()
bool FileCache::loadByPath(const std::string &path, std::ostream &os)
{
std::ifstream fis(path.c_str(), std::ios_base::binary);
if(!fis.good()){
verbosestream<<"FileCache: File not found in cache: "
<<path<<std::endl;
auto fis = open_ifstream(path.c_str(), false);
if (!fis.good())
return false;
}
bool bad = false;
for(;;){
@ -70,15 +66,10 @@ bool FileCache::loadByPath(const std::string &path, std::ostream &os)
bool FileCache::updateByPath(const std::string &path, std::string_view data)
{
createDir();
std::ofstream file(path.c_str(), std::ios_base::binary |
std::ios_base::trunc);
if(!file.good())
{
errorstream<<"FileCache: Can't write to file at "
<<path<<std::endl;
auto file = open_ofstream(path.c_str(), true);
if (!file.good())
return false;
}
file << data;
file.close();
@ -101,8 +92,7 @@ bool FileCache::load(const std::string &name, std::ostream &os)
bool FileCache::exists(const std::string &name)
{
std::string path = m_dir + DIR_DELIM + name;
std::ifstream fis(path.c_str(), std::ios_base::binary);
return fis.good();
return fs::PathExists(path);
}
bool FileCache::updateCopyFile(const std::string &name, const std::string &src_path)

View file

@ -801,7 +801,15 @@ protected:
// Misc
void showOverlayMessage(const char *msg, float dtime, int percent,
bool draw_clouds = true);
float *indef_pos = nullptr);
inline bool fogEnabled()
{
// Client setting only takes effect if fog distance unlimited or debug priv
if (sky->getFogDistance() < 0 || client->checkPrivilege("debug"))
return m_cache_enable_fog;
return true;
}
static void settingChangedCallback(const std::string &setting_name, void *data);
void readSettings();
@ -969,6 +977,8 @@ private:
#ifdef __ANDROID__
bool m_android_chat_open;
#endif
float m_shutdown_progress = 0.0f;
};
Game::Game() :
@ -1165,7 +1175,8 @@ void Game::run()
g_settings->getU16("screen_w"),
g_settings->getU16("screen_h")
);
const bool initial_window_maximized = g_settings->getBool("window_maximized");
const bool initial_window_maximized = !g_settings->getBool("fullscreen") &&
g_settings->getBool("window_maximized");
while (m_rendering_engine->run()
&& !(*kill || g_gamecallback->shutdown_requested
@ -1248,7 +1259,9 @@ void Game::shutdown()
if (g_touchscreengui)
g_touchscreengui->hide();
showOverlayMessage(N_("Shutting down..."), 0, 0, false);
// only if the shutdown progress bar isn't shown yet
if (m_shutdown_progress == 0.0f)
showOverlayMessage(N_("Shutting down..."), 0, 0);
if (clouds)
clouds->drop();
@ -1300,7 +1313,7 @@ void Game::shutdown()
m_rendering_engine->run();
f32 dtime;
fps_control.limit(device, &dtime);
showOverlayMessage(N_("Shutting down..."), dtime, 0, false);
showOverlayMessage(N_("Shutting down..."), dtime, 0, &m_shutdown_progress);
}
stop_thread->rethrow();
@ -1432,7 +1445,7 @@ bool Game::createSingleplayerServer(const std::string &map_dir,
if (success)
showOverlayMessage(N_("Creating server..."), dtime, 5);
else
showOverlayMessage(N_("Shutting down..."), dtime, 0, false);
showOverlayMessage(N_("Shutting down..."), dtime, 0, &m_shutdown_progress);
}
start_thread->rethrow();
@ -2426,9 +2439,6 @@ void Game::toggleBlockBounds()
case Hud::BLOCK_BOUNDS_NEAR:
m_game_ui->showTranslatedStatusText("Block bounds shown for nearby blocks");
break;
case Hud::BLOCK_BOUNDS_MAX:
m_game_ui->showTranslatedStatusText("Block bounds shown for all blocks");
break;
default:
break;
}
@ -2479,15 +2489,12 @@ void Game::toggleMinimap(bool shift_pressed)
void Game::toggleFog()
{
bool flag;
// do not modify setting if no privilege
if (!client->checkPrivilege("debug")) {
flag = true;
} else {
flag = !g_settings->getBool("enable_fog");
g_settings->setBool("enable_fog", flag);
}
if (flag)
bool flag = !g_settings->getBool("enable_fog");
g_settings->setBool("enable_fog", flag);
bool allowed = sky->getFogDistance() < 0 || client->checkPrivilege("debug");
if (!allowed)
m_game_ui->showTranslatedStatusText("Fog enabled by game or mod");
else if (flag)
m_game_ui->showTranslatedStatusText("Fog enabled");
else
m_game_ui->showTranslatedStatusText("Fog disabled");
@ -4242,8 +4249,7 @@ void Game::updateClouds(float dtime)
camera_node_position.Y = camera_node_position.Y + camera_offset.Y * BS;
camera_node_position.Z = camera_node_position.Z + camera_offset.Z * BS;
this->clouds->update(camera_node_position, this->sky->getCloudColor());
bool enable_fog = this->m_cache_enable_fog || !client->checkPrivilege("debug");
if (this->clouds->isCameraInsideCloud() && enable_fog) {
if (this->clouds->isCameraInsideCloud() && this->fogEnabled()) {
// If camera is inside cloud and fog is enabled, use cloud's colors as sky colors.
video::SColor clouds_dark = this->clouds->getColor().getInterpolated(
video::SColor(255, 0, 0, 0), 0.9);
@ -4303,7 +4309,7 @@ void Game::drawScene(ProfilerGraph *graph, RunStats *stats)
/*
Fog
*/
if (this->m_cache_enable_fog || !client->checkPrivilege("debug")) {
if (this->fogEnabled()) {
this->driver->setFog(
fog_color,
video::EFT_FOG_LINEAR,
@ -4374,10 +4380,10 @@ void Game::drawScene(ProfilerGraph *graph, RunStats *stats)
Misc
****************************************************************************/
void Game::showOverlayMessage(const char *msg, float dtime, int percent, bool draw_sky)
void Game::showOverlayMessage(const char *msg, float dtime, int percent, float *indef_pos)
{
m_rendering_engine->draw_load_screen(wstrgettext(msg), guienv, texture_src,
dtime, percent, draw_sky);
dtime, percent, indef_pos);
}
void Game::settingChangedCallback(const std::string &setting_name, void *data)

View file

@ -913,7 +913,7 @@ enum Hud::BlockBoundsMode Hud::toggleBlockBounds()
{
m_block_bounds_mode = static_cast<BlockBoundsMode>(m_block_bounds_mode + 1);
if (m_block_bounds_mode >= BLOCK_BOUNDS_MAX) {
if (m_block_bounds_mode > BLOCK_BOUNDS_NEAR) {
m_block_bounds_mode = BLOCK_BOUNDS_OFF;
}
return m_block_bounds_mode;

View file

@ -40,7 +40,6 @@ public:
BLOCK_BOUNDS_OFF,
BLOCK_BOUNDS_CURRENT,
BLOCK_BOUNDS_NEAR,
BLOCK_BOUNDS_MAX
} m_block_bounds_mode = BLOCK_BOUNDS_OFF;
video::SColor crosshair_argb;

View file

@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "settings.h"
#include "util/numeric.h"
#include "inputhandler.h"
#include "gui/mainmenumanager.h"
@ -113,6 +114,19 @@ bool MyEventReceiver::OnEvent(const SEvent &event)
return true;
}
// This is separate from other keyboard handling so that it also works in menus.
if (event.EventType == EET_KEY_INPUT_EVENT) {
const KeyPress keyCode(event.KeyInput);
if (keyCode == getKeySetting("keymap_fullscreen")) {
if (event.KeyInput.PressedDown && !fullscreen_is_down) {
bool fullscreen = RenderingEngine::get_raw_device()->isFullscreen();
g_settings->setBool("fullscreen", !fullscreen);
}
fullscreen_is_down = event.KeyInput.PressedDown;
return true;
}
}
// Let the menu handle events, if one is active.
if (isMenuActive()) {
if (g_touchscreengui)

View file

@ -220,6 +220,9 @@ private:
// often changing keys, and keysListenedFor is expected
// to change seldomly but contain lots of keys.
KeyList keysListenedFor;
// Intentionally not reset by clearInput/releaseAllKeys.
bool fullscreen_is_down = false;
};
class InputHandler

View file

@ -437,15 +437,18 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
m_speed.Z = 0.0f;
}
if (y_diff > 0 && m_speed.Y <= 0.0f &&
(physics_override.sneak_glitch || y_diff < BS * 0.6f)) {
if (y_diff > 0 && m_speed.Y <= 0.0f) {
// Move player to the maximal height when falling or when
// the ledge is climbed on the next step.
// Smoothen the movement (based on 'position.Y = bmax.Y')
position.Y += y_diff * dtime * 22.0f + BS * 0.01f;
position.Y = std::min(position.Y, bmax.Y);
m_speed.Y = 0.0f;
v3f check_pos = position;
check_pos.Y += y_diff * dtime * 22.0f + BS * 0.01f;
if (y_diff < BS * 0.6f || (physics_override.sneak_glitch
&& !collision_check_intersection(env, m_client, m_collisionbox, check_pos))) {
// Smoothen the movement (based on 'position.Y = bmax.Y')
position.Y = std::min(check_pos.Y, bmax.Y);
m_speed.Y = 0.0f;
}
}
// Allow jumping on node edges while sneaking

View file

@ -329,32 +329,6 @@ void final_color_blend(video::SColor *result,
Mesh generation helpers
*/
// This table is moved outside getNodeVertexDirs to avoid the compiler using
// a mutex to initialize this table at runtime right in the hot path.
// For details search the internet for "cxa_guard_acquire".
static const v3s16 vertex_dirs_table[] = {
// ( 1, 0, 0)
v3s16( 1,-1, 1), v3s16( 1,-1,-1),
v3s16( 1, 1,-1), v3s16( 1, 1, 1),
// ( 0, 1, 0)
v3s16( 1, 1,-1), v3s16(-1, 1,-1),
v3s16(-1, 1, 1), v3s16( 1, 1, 1),
// ( 0, 0, 1)
v3s16(-1,-1, 1), v3s16( 1,-1, 1),
v3s16( 1, 1, 1), v3s16(-1, 1, 1),
// invalid
v3s16(), v3s16(), v3s16(), v3s16(),
// ( 0, 0,-1)
v3s16( 1,-1,-1), v3s16(-1,-1,-1),
v3s16(-1, 1,-1), v3s16( 1, 1,-1),
// ( 0,-1, 0)
v3s16( 1,-1, 1), v3s16(-1,-1, 1),
v3s16(-1,-1,-1), v3s16( 1,-1,-1),
// (-1, 0, 0)
v3s16(-1,-1,-1), v3s16(-1,-1, 1),
v3s16(-1, 1, 1), v3s16(-1, 1,-1)
};
/*
Gets nth node tile (0 <= n <= 5).
*/
@ -826,11 +800,16 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs
MapBlockMesh::~MapBlockMesh()
{
size_t sz = 0;
for (scene::IMesh *m : m_mesh) {
for (u32 i = 0; i < m->getMeshBufferCount(); i++)
sz += m->getMeshBuffer(i)->getSize();
m->drop();
}
for (MinimapMapblock *block : m_minimap_mapblocks)
delete block;
porting::TrackFreedMemory(sz);
}
bool MapBlockMesh::animate(bool faraway, float time, int crack,
@ -1006,7 +985,6 @@ video::SColor encode_light(u16 light, u8 emissive_light)
u8 get_solid_sides(MeshMakeData *data)
{
std::unordered_map<v3s16, u8> results;
v3s16 ofs;
v3s16 blockpos_nodes = data->m_blockpos * MAP_BLOCKSIZE;
const NodeDefManager *ndef = data->nodedef;

View file

@ -1008,7 +1008,6 @@ video::SMaterial ParticleManager::getMaterialForParticle(const ClientParticleTex
video::EMFN_MODULATE_1X,
video::EAS_TEXTURE | video::EAS_VERTEX_COLOR);
material.BlendOperation = blendop;
assert(texture.ref);
material.setTexture(0, texture.ref);
return material;

View file

@ -207,7 +207,12 @@ RenderingEngine::RenderingEngine(IEventReceiver *receiver)
#else
u16 screen_w = std::max<u16>(g_settings->getU16("screen_w"), 1);
u16 screen_h = std::max<u16>(g_settings->getU16("screen_h"), 1);
bool window_maximized = g_settings->getBool("window_maximized");
// If I…
// 1. … set fullscreen = true and window_maximized = true on startup
// 2. … set fullscreen = false later
// on Linux with SDL, everything breaks.
// => Don't do it.
bool window_maximized = !fullscreen && g_settings->getBool("window_maximized");
#endif
// bpp, fsaa, vsync
@ -249,18 +254,40 @@ RenderingEngine::RenderingEngine(IEventReceiver *receiver)
gui::EGST_WINDOWS_METALLIC, driver);
m_device->getGUIEnvironment()->setSkin(skin);
skin->drop();
g_settings->registerChangedCallback("fullscreen", settingChangedCallback, this);
g_settings->registerChangedCallback("window_maximized", settingChangedCallback, this);
}
RenderingEngine::~RenderingEngine()
{
sanity_check(s_singleton == this);
g_settings->deregisterChangedCallback("fullscreen", settingChangedCallback, this);
g_settings->deregisterChangedCallback("window_maximized", settingChangedCallback, this);
core.reset();
m_device->closeDevice();
m_device->drop();
s_singleton = nullptr;
}
void RenderingEngine::settingChangedCallback(const std::string &name, void *data)
{
IrrlichtDevice *device = static_cast<RenderingEngine*>(data)->m_device;
if (name == "fullscreen") {
device->setFullscreen(g_settings->getBool("fullscreen"));
} else if (name == "window_maximized") {
if (!device->isFullscreen()) {
if (g_settings->getBool("window_maximized"))
device->maximizeWindow();
else
device->restoreWindow();
}
}
}
v2u32 RenderingEngine::_getWindowSize() const
{
if (core)
@ -308,7 +335,7 @@ bool RenderingEngine::setWindowIcon()
*/
void RenderingEngine::draw_load_screen(const std::wstring &text,
gui::IGUIEnvironment *guienv, ITextureSource *tsrc, float dtime,
int percent, bool sky)
int percent, float *indef_pos)
{
v2u32 screensize = getWindowSize();
@ -322,18 +349,22 @@ void RenderingEngine::draw_load_screen(const std::wstring &text,
auto *driver = get_video_driver();
if (sky) {
driver->beginScene(true, true, RenderingEngine::MENU_SKY_COLOR);
if (g_settings->getBool("menu_clouds")) {
g_menuclouds->step(dtime * 3);
g_menucloudsmgr->drawAll();
}
} else {
driver->beginScene(true, true, video::SColor(255, 0, 0, 0));
driver->setFog(RenderingEngine::MENU_SKY_COLOR);
driver->beginScene(true, true, RenderingEngine::MENU_SKY_COLOR);
if (g_settings->getBool("menu_clouds")) {
g_menuclouds->step(dtime * 3);
g_menucloudsmgr->drawAll();
}
int percent_min = 0;
int percent_max = percent;
if (indef_pos) {
*indef_pos = fmodf(*indef_pos + (dtime * 50.0f), 140.0f);
percent_max = std::min((int) *indef_pos, 100);
percent_min = std::max((int) *indef_pos - 40, 0);
}
// draw progress bar
if ((percent >= 0) && (percent <= 100)) {
if ((percent_min >= 0) && (percent_max <= 100)) {
video::ITexture *progress_img = tsrc->getTexture("progress_bar.png");
video::ITexture *progress_img_bg =
tsrc->getTexture("progress_bar_bg.png");
@ -364,11 +395,11 @@ void RenderingEngine::draw_load_screen(const std::wstring &text,
0, 0, true);
draw2DImageFilterScaled(get_video_driver(), progress_img,
core::rect<s32>(img_pos.X, img_pos.Y,
img_pos.X + (percent * imgW) / 100,
core::rect<s32>(img_pos.X + (percent_min * imgW) / 100, img_pos.Y,
img_pos.X + (percent_max * imgW) / 100,
img_pos.Y + imgH),
core::rect<s32>(0, 0,
(percent * img_size.Width) / 100,
core::rect<s32>(percent_min * img_size.Width / 100, 0,
percent_max * img_size.Width / 100,
img_size.Height),
0, 0, true);
}

View file

@ -137,9 +137,11 @@ public:
return m_device->getGUIEnvironment();
}
// If "indef_pos" is given, the value of "percent" is ignored and an indefinite
// progress bar is drawn.
void draw_load_screen(const std::wstring &text,
gui::IGUIEnvironment *guienv, ITextureSource *tsrc,
float dtime = 0, int percent = 0, bool sky = true);
float dtime = 0, int percent = 0, float *indef_pos = nullptr);
void draw_scene(video::SColor skycolor, bool show_hud,
bool draw_wield_tool, bool draw_crosshair);
@ -166,6 +168,7 @@ public:
const bool initial_window_maximized);
private:
static void settingChangedCallback(const std::string &name, void *data);
v2u32 _getWindowSize() const;
std::unique_ptr<RenderingCore> core;

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